docstr: Base function for registering a module in GraphGym.
  
  Args:
      module_group (str): The name of the module group
      key (string): The name of the module.
      module (any, optional): The module. If set to :obj:`None`, will
          return a decorator to register a module.
docstr_tok: ["Base","function","for","registering","a","module","in","GraphGym",".","Args",":","module_group","(","str",")",":","The","name","of","the","module","group","key","(","string",")",":","The","name","of","the","module",".","module","(","any",",","optional",")",":","The","module",".","If","set","to",":","obj",":","`","None","`",",","will","return","a","decorator","to","register","a","module","."]
code: def register(
      self, module_group: str, key: str, module: Any = None
  ) -> Union[None, Callable]:
      r"""Base function for registering a module in GraphGym.
  
      Args:
          module_group (str): The name of the module group
          key (string): The name of the module.
          module (any, optional): The module. If set to :obj:`None`, will
              return a decorator to register a module.
      """
  
      if module_group not in self.keys():
          self[module_group] = {}
  
      if module is not None:
          if key in self[module_group]:
              warnings.warn(
                  f"Module group {module_group} with '{key}' already "
                  f"defined, registeration failed"
              )
          self[module_group][key] = module
          return
  
      # Other-wise, use it as a decorator:
      def bounded_register(module):
          self.register(module_group, key, module)
          return module
  
      return bounded_register
  
imports: import warnings
  from typing import Any, Callable, Dict, Union
label_desc: Use image node_id 2 for calling the ModuleStore obj's underlying member method code with example usage: obj.register(module_group, key, module) and returns: bounded_register, module