Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-13 08:18:25

0001 import inspect
0002 import functools
0003 from typing import Optional, Callable, Dict, Any
0004 from pathlib import Path
0005 
0006 
0007 def _make_config_adapter(fn):
0008     @functools.wraps(fn)
0009     def wrapped(self, *args, **kwargs):
0010         if len(args) > 0:
0011             maybe_config = args[0]
0012             if isinstance(maybe_config, inspect.unwrap(type(self).Config)):
0013                 # is already config, nothing to do here
0014                 fn(self, maybe_config, *args[1:], **kwargs)
0015                 return
0016 
0017         if "config" in kwargs:
0018             config = kwargs.pop("config")
0019             fn(self, config, *args, **kwargs)
0020             return
0021 
0022         cfg = type(self).Config()
0023         _kwargs = {}
0024         for k, v in kwargs.items():
0025             if isinstance(v, Path):
0026                 v = str(v)
0027 
0028             if hasattr(cfg, k):
0029                 try:
0030                     setattr(cfg, k, v)
0031                 except TypeError as e:
0032                     raise RuntimeError(
0033                         "{}: Failed to set {}={}".format(type(cfg), k, v)
0034                     ) from e
0035             else:
0036                 _kwargs[k] = v
0037         try:
0038             fn(self, cfg, *args, **_kwargs)
0039         except TypeError as e:
0040             import textwrap
0041 
0042             print("-" * 80)
0043             print("Patched config constructor failed for", type(self))
0044             message = (
0045                 "This is most likely because one of the following kwargs "
0046                 "could not be assigned to the Config object, and the constructor "
0047                 "did not accept it as an additional argument:"
0048             )
0049             print("\n".join(textwrap.wrap(message, width=80)))
0050             print("->", ", ".join(_kwargs.keys()))
0051             members = inspect.getmembers(type(cfg), lambda a: not inspect.isroutine(a))
0052             members = [m for m, _ in members if not m.startswith("_")]
0053             print(type(cfg), "has the following properties:\n->", ", ".join(members))
0054             print("-" * 80)
0055             raise e
0056 
0057     return wrapped
0058 
0059 
0060 def _make_config_constructor(
0061     cls, proc: Optional[Callable[[Dict[str, Any]], Dict[str, Any]]] = None
0062 ):
0063     fn = cls.__init__
0064 
0065     @functools.wraps(fn)
0066     def wrapped(self, *args, **kwargs):
0067         _kwargs = {}
0068         for k in list(kwargs.keys()):
0069             if hasattr(cls, k):
0070                 _kwargs[k] = kwargs.pop(k)
0071 
0072         fn(self, *args, **kwargs)
0073 
0074         if proc is not None:
0075             _kwargs = proc(_kwargs)
0076         for k, v in _kwargs.items():
0077             setattr(self, k, v)
0078 
0079     return wrapped
0080 
0081 
0082 def _patchKwargsConstructor(
0083     cls, proc: Optional[Callable[[Dict[str, Any]], Dict[str, Any]]] = None
0084 ):
0085     cls.__init__ = _make_config_constructor(cls, proc)
0086 
0087 
0088 def _patch_config(m):
0089     for name, cls in inspect.getmembers(m, inspect.isclass):
0090         if name == "Config":
0091             _patchKwargsConstructor(cls)
0092 
0093         if hasattr(cls, "Config"):
0094             cls.__init__ = _make_config_adapter(cls.__init__)
0095             _patchKwargsConstructor(cls.Config)