99__all__ = ["FromConfigMixin" ]
1010
1111T = TypeVar ("T" )
12+ OVERRIDE_KINDS = {inspect .Parameter .KEYWORD_ONLY , inspect .Parameter .POSITIONAL_OR_KEYWORD }
1213
1314
1415class FromConfigMixin :
@@ -55,6 +56,10 @@ def _parse_class_kwargs_from_config(cls: Type[T], config: Union[str, PathLike, d
5556 """Parse the init kwargs for ``cls`` from a config file or dict."""
5657 parser = ArgumentParser (exit_on_error = False , ** kwargs )
5758 parser .add_class_arguments (cls )
59+ for required in parser .required_args :
60+ action = next ((a for a in parser ._actions if a .dest == required ), None )
61+ action ._required = False # type: ignore[union-attr]
62+ parser .required_args .clear ()
5863 if isinstance (config , dict ):
5964 cfg = parser .parse_object (config , defaults = False )
6065 else :
@@ -79,12 +84,15 @@ def _override_init_defaults_this_class(cls: Type[T], defaults: dict) -> None:
7984 params = inspect .signature (cls .__init__ ).parameters
8085 for name , default in defaults .copy ().items ():
8186 param = params .get (name )
82- if param and param .kind in {inspect .Parameter .KEYWORD_ONLY , inspect .Parameter .POSITIONAL_OR_KEYWORD }:
87+ if param and param .kind in OVERRIDE_KINDS :
88+ if param .default == inspect ._empty :
89+ raise TypeError (f"Overriding of required parameters not allowed: '{ param .name } '" )
8390 defaults .pop (name )
8491 if param .kind == inspect .Parameter .KEYWORD_ONLY :
8592 cls .__init__ .__kwdefaults__ [name ] = default # type: ignore[index]
8693 else :
87- index = list (params ).index (name ) - 1
94+ required = [p for p in params .values () if p .kind in OVERRIDE_KINDS and p .default == inspect ._empty ]
95+ index = list (params ).index (name ) - len (required )
8896 aux = cls .__init__ .__defaults__ or ()
8997 cls .__init__ .__defaults__ = aux [:index ] + (default ,) + aux [index + 1 :]
9098
0 commit comments