code: def from_config(func):
      if inspect.isclass(func):
          params = list(
              inspect.signature(func.__init__).parameters.values()
          )[1:]
      else:
          params = list(inspect.signature(func).parameters.values())
  
      arg_names = [p.name for p in params]
      has_defaults = [
          p.default != inspect.Parameter.empty for p in params
      ]
  
      @functools.wraps(func)
      def wrapper(*args, cfg: Any = None, **kwargs):
          if cfg is not None:
              cfg = (
                  dict(cfg)
                  if isinstance(cfg, Iterable)
                  else asdict(cfg)
              )
  
              iterator = zip(
                  arg_names[len(args) :], has_defaults[len(args) :]
              )
              for arg_name, has_default in iterator:
                  if arg_name in kwargs:
                      continue
                  elif arg_name in cfg:
                      kwargs[arg_name] = cfg[arg_name]
                  elif not has_default:
                      raise ValueError(f"'cfg.{arg_name}' undefined")
          return func(*args, **kwargs)
  
      return wrapper
  
file_path: GraphGym/graphgym/config.py
imports: import functools
  import inspect
  import logging
  import os
  import shutil
  from collections.abc import Iterable
  from dataclasses import asdict
  from typing import Any
  from yacs.config import CfgNode
  import graphgym.register
  import graphgym.contrib.config
label_desc: Use image node_id 9 for calling a global function with example usage: from_config(func) and returns: wrapper, func