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
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)