@@ -98,7 +98,6 @@ def init(self):
9898 A transparent attribute will also not have its init function called automatically, so you will need to do that on your own, as seen in the Outer init.
9999 The function is upper case on purpose, as it is supposed to be used in a Type context
100100 """
101-
102101 class Cloned (subclass ):
103102 __secret__ = getattr (subclass , "__secret__" , False )
104103 __transparent__ = True
@@ -130,48 +129,46 @@ def indent(level: int) -> str:
130129
131130@overload
132131def parameter (
133- * ,
134- desc : str ,
135- default : T = ...,
136- init : bool = True ,
137- repr : bool = True ,
138- hash : Optional [bool ] = None ,
139- compare : bool = True ,
140- metadata : Optional [Dict [str , Any ]] = ...,
141- kw_only : Union [bool , _MISSING_TYPE ] = MISSING ,
132+ * ,
133+ desc : str ,
134+ default : T = ...,
135+ init : bool = True ,
136+ repr : bool = True ,
137+ hash : Optional [bool ] = None ,
138+ compare : bool = True ,
139+ metadata : Optional [Dict [str , Any ]] = ...,
140+ kw_only : Union [bool , _MISSING_TYPE ] = MISSING ,
142141) -> T :
143142 ...
144143
145-
146144@overload
147145def parameter (
148- * ,
149- desc : str ,
150- default : T = ...,
151- init : bool = True ,
152- repr : bool = True ,
153- hash : Optional [bool ] = None ,
154- compare : bool = True ,
155- metadata : Optional [Dict [str , Any ]] = ...,
156- kw_only : Union [bool , _MISSING_TYPE ] = MISSING ,
146+ * ,
147+ desc : str ,
148+ default : T = ...,
149+ init : bool = True ,
150+ repr : bool = True ,
151+ hash : Optional [bool ] = None ,
152+ compare : bool = True ,
153+ metadata : Optional [Dict [str , Any ]] = ...,
154+ kw_only : Union [bool , _MISSING_TYPE ] = MISSING ,
157155) -> Field [T ]:
158156 ...
159157
160-
161158def parameter (
162- * ,
163- desc : str ,
164- secret : bool = False ,
165- global_parameter : bool = False ,
166- global_name : Optional [str ] = None ,
167- choices : Optional [dict [str , type ]] = None ,
168- default : T = MISSING ,
169- init : bool = True ,
170- repr : bool = True ,
171- hash : Optional [bool ] = None ,
172- compare : bool = True ,
173- metadata : Optional [Dict [str , Any ]] = None ,
174- kw_only : Union [bool , _MISSING_TYPE ] = MISSING ,
159+ * ,
160+ desc : str ,
161+ secret : bool = False ,
162+ global_parameter : bool = False ,
163+ global_name : Optional [str ] = None ,
164+ choices : Optional [dict [str , type ]] = None ,
165+ default : T = MISSING ,
166+ init : bool = True ,
167+ repr : bool = True ,
168+ hash : Optional [bool ] = None ,
169+ compare : bool = True ,
170+ metadata : Optional [Dict [str , Any ]] = None ,
171+ kw_only : Union [bool , _MISSING_TYPE ] = MISSING ,
175172) -> Field [T ]:
176173 if metadata is None :
177174 metadata = dict ()
@@ -205,8 +202,7 @@ def get_default(key, default):
205202InstanceResults = NestedCollection [Any ]
206203
207204
208- def get_at (collection : NestedCollection [C ], name : list [str ], at : int = 0 , * , meta : bool = False ,
209- no_raise : bool = False ) -> Optional [C ]:
205+ def get_at (collection : NestedCollection [C ], name : list [str ], at : int = 0 , * , meta : bool = False , no_raise : bool = False ) -> Optional [C ]:
210206 if meta :
211207 name = name + ["$" ]
212208
@@ -248,8 +244,7 @@ def set_at(collection: NestedCollection[C], name: list[str], value: C, at: int =
248244 return set_at (collection [name [at ]], name , value , at + 1 , False )
249245
250246
251- def dfs_flatmap (collection : NestedCollection [C ], func : Callable [[list [str ], C ], Any ],
252- basename : Optional [list [str ]] = None ):
247+ def dfs_flatmap (collection : NestedCollection [C ], func : Callable [[list [str ], C ], Any ], basename : Optional [list [str ]] = None ):
253248 if basename is None :
254249 basename = []
255250 output = []
@@ -368,9 +363,7 @@ def __call__(self, collection: ParsingResults) -> C:
368363 if value is None :
369364 raise ParameterError (f"Missing required parameter '--{ '.' .join (self .name )} '" , self .name )
370365 if value not in self .choices :
371- raise ParameterError (
372- f"Invalid value for parameter '--{ '.' .join (self .name )} ': { value } (possible values are { ', ' .join (self .choices .keys ())} )" ,
373- self .name )
366+ raise ParameterError (f"Invalid value for parameter '--{ '.' .join (self .name )} ': { value } (possible values are { ', ' .join (self .choices .keys ())} )" , self .name )
374367 choice , parameters = self .choices [value ]
375368 self ._instance = choice (** {
376369 name : parameter (collection )
@@ -381,19 +374,15 @@ def __call__(self, collection: ParsingResults) -> C:
381374 return self ._instance
382375
383376
384- def get_inspect_parameters_for_class (cls : type , basename : list [str ]) -> dict [
385- str , tuple [inspect .Parameter , list [str ], Optional [dataclasses .Field ]]]:
377+ def get_inspect_parameters_for_class (cls : type , basename : list [str ]) -> dict [str , tuple [inspect .Parameter , list [str ], Optional [dataclasses .Field ]]]:
386378 fields = getattr (cls , "__dataclass_fields__" , {})
387379 return {
388380 name : (param , basename + [name ], fields .get (name ))
389381 for name , param in inspect .signature (cls .__init__ ).parameters .items ()
390382 if not (name == "self" or name .startswith ("_" ) or isinstance (name , NoneType ))
391383 }
392384
393-
394- def get_type_description_default_for_parameter (parameter : inspect .Parameter , name : list [str ],
395- field : Optional [dataclasses .Field ] = None ) -> tuple [
396- Type , Optional [str ], Any ]:
385+ def get_type_description_default_for_parameter (parameter : inspect .Parameter , name : list [str ], field : Optional [dataclasses .Field ] = None ) -> tuple [Type , Optional [str ], Any ]:
397386 parameter_type : Type = parameter .annotation
398387 description : Optional [str ] = None
399388
@@ -406,53 +395,42 @@ def get_type_description_default_for_parameter(parameter: inspect.Parameter, nam
406395 description = field .metadata .get ("desc" , None )
407396 if field .type is not None :
408397 if not (isinstance (field .type , type ) or get_origin (field .type ) is Union ):
409- raise ValueError (
410- f"Parameter { '.' .join (name )} has an invalid type annotation: { field .type } ({ type (field .type )} )" )
398+ raise ValueError (f"Parameter { '.' .join (name )} has an invalid type annotation: { field .type } ({ type (field .type )} )" )
411399 parameter_type = field .type
412400
413401 # check if type is an Optional, and then get the actual type
414- if get_origin (parameter_type ) is Union and len (parameter_type .__args__ ) == 2 and parameter_type .__args__ [
415- 1 ] is NoneType :
402+ if get_origin (parameter_type ) is Union and len (parameter_type .__args__ ) == 2 and parameter_type .__args__ [1 ] is NoneType :
416403 parameter_type = parameter_type .__args__ [0 ]
417404
418405 return parameter_type , description , default
419406
420407
421- def try_existing_parameter (parameter_collection : ParameterCollection , name : list [str ], typ : type , parameter_type : type ,
422- default : Any , description : str , secret_parameter : bool ) -> Optional [ParameterDefinition ]:
423- existing_parameter = get_at (parameter_collection , name ,
424- meta = (typ in (ComplexParameterDefinition , ChoiceParameterDefinition )))
408+ def try_existing_parameter (parameter_collection : ParameterCollection , name : list [str ], typ : type , parameter_type : type , default : Any , description : str , secret_parameter : bool ) -> Optional [ParameterDefinition ]:
409+ existing_parameter = get_at (parameter_collection , name , meta = (typ in (ComplexParameterDefinition , ChoiceParameterDefinition )))
425410 if not existing_parameter :
426411 return None
427412
428413 if existing_parameter .type != parameter_type :
429- raise ValueError (
430- f"Parameter { '.' .join (name )} already exists with a different type ({ existing_parameter .type } != { parameter_type } )" )
414+ raise ValueError (f"Parameter { '.' .join (name )} already exists with a different type ({ existing_parameter .type } != { parameter_type } )" )
431415 if existing_parameter .default != default :
432416 if existing_parameter .default is None and isinstance (secret_parameter , no_default ) \
433- or existing_parameter .default is not None and not isinstance (secret_parameter , no_default ):
434- pass # syncing up "no defaults"
417+ or existing_parameter .default is not None and not isinstance (secret_parameter , no_default ):
418+ pass # syncing up "no defaults"
435419 else :
436- raise ValueError (
437- f"Parameter { '.' .join (name )} already exists with a different default value ({ existing_parameter .default } != { default } )" )
420+ raise ValueError (f"Parameter { '.' .join (name )} already exists with a different default value ({ existing_parameter .default } != { default } )" )
438421 if existing_parameter .description != description :
439- raise ValueError (
440- f"Parameter { '.' .join (name )} already exists with a different description ({ existing_parameter .description } != { description } )" )
422+ raise ValueError (f"Parameter { '.' .join (name )} already exists with a different description ({ existing_parameter .description } != { description } )" )
441423 if existing_parameter .secret != secret_parameter :
442- raise ValueError (
443- f"Parameter { '.' .join (name )} already exists with a different secret status ({ existing_parameter .secret } != { secret_parameter } )" )
424+ raise ValueError (f"Parameter { '.' .join (name )} already exists with a different secret status ({ existing_parameter .secret } != { secret_parameter } )" )
444425
445426 return existing_parameter
446427
447428
448- def parameter_definitions_for_class (cls : type , name : list [str ], parameter_collection : ParameterCollection ) -> dict [
449- str , ParameterDefinition ]:
450- return {name : parameter_definition_for (* metadata , parameter_collection = parameter_collection ) for name , metadata in
451- get_inspect_parameters_for_class (cls , name ).items ()}
429+ def parameter_definitions_for_class (cls : type , name : list [str ], parameter_collection : ParameterCollection ) -> dict [str , ParameterDefinition ]:
430+ return {name : parameter_definition_for (* metadata , parameter_collection = parameter_collection ) for name , metadata in get_inspect_parameters_for_class (cls , name ).items ()}
452431
453432
454- def parameter_definition_for (param : inspect .Parameter , name : list [str ], field : Optional [dataclasses .Field ] = None , * ,
455- parameter_collection : ParameterCollection ) -> ParameterDefinition :
433+ def parameter_definition_for (param : inspect .Parameter , name : list [str ], field : Optional [dataclasses .Field ] = None , * , parameter_collection : ParameterCollection ) -> ParameterDefinition :
456434 parameter_type , description , default = get_type_description_default_for_parameter (param , name , field )
457435 secret_parameter = (field and field .metadata .get ("secret" , False )) or getattr (parameter_type , "__secret__" , False )
458436
@@ -468,18 +446,14 @@ def parameter_definition_for(param: inspect.Parameter, name: list[str], field: O
468446 name = name [:- 1 ]
469447
470448 if parameter_type in (str , int , float , bool ):
471- existing_parameter = try_existing_parameter (parameter_collection , name , typ = ParameterDefinition ,
472- parameter_type = parameter_type , default = default ,
473- description = description , secret_parameter = secret_parameter )
449+ existing_parameter = try_existing_parameter (parameter_collection , name , typ = ParameterDefinition , parameter_type = parameter_type , default = default , description = description , secret_parameter = secret_parameter )
474450 if existing_parameter :
475451 return existing_parameter
476452 parameter = ParameterDefinition (name , parameter_type , default , description , secret_parameter )
477453 set_at (parameter_collection , name , parameter )
478454
479455 elif get_origin (parameter_type ) is Union :
480- existing_parameter = try_existing_parameter (parameter_collection , name , typ = ChoiceParameterDefinition ,
481- parameter_type = parameter_type , default = default ,
482- description = description , secret_parameter = secret_parameter )
456+ existing_parameter = try_existing_parameter (parameter_collection , name , typ = ChoiceParameterDefinition , parameter_type = parameter_type , default = default , description = description , secret_parameter = secret_parameter )
483457 if existing_parameter :
484458 return existing_parameter
485459
@@ -508,9 +482,7 @@ def parameter_definition_for(param: inspect.Parameter, name: list[str], field: O
508482 set_at (parameter_collection , name , parameter , meta = True )
509483
510484 else :
511- existing_parameter = try_existing_parameter (parameter_collection , name , typ = ComplexParameterDefinition ,
512- parameter_type = parameter_type , default = default ,
513- description = description , secret_parameter = secret_parameter )
485+ existing_parameter = try_existing_parameter (parameter_collection , name , typ = ComplexParameterDefinition , parameter_type = parameter_type , default = default , description = description , secret_parameter = secret_parameter )
514486 if existing_parameter :
515487 return existing_parameter
516488
@@ -527,6 +499,8 @@ def parameter_definition_for(param: inspect.Parameter, name: list[str], field: O
527499 return parameter
528500
529501
502+
503+
530504@dataclass
531505class Parseable (Generic [C ]):
532506 cls : Type [C ]
@@ -549,9 +523,7 @@ def __post_init__(self):
549523 )
550524
551525 def to_help (self , defaults : list [tuple [str , ParsingResults ]], level : int = 0 ) -> str :
552- return "\n " .join (dfs_flatmap (self ._parameter_collection ,
553- lambda _ , parameter : parameter .to_help (defaults , level + 1 ) if not isinstance (
554- parameter , ComplexParameterDefinition ) else None ))
526+ return "\n " .join (dfs_flatmap (self ._parameter_collection , lambda _ , parameter : parameter .to_help (defaults , level + 1 ) if not isinstance (parameter , ComplexParameterDefinition ) else None ))
555527
556528
557529CommandMap = dict [str , Union ["CommandMap[C]" , Parseable [C ]]]
@@ -560,10 +532,10 @@ def to_help(self, defaults: list[tuple[str, ParsingResults]], level: int = 0) ->
560532def _to_help (name : str , commands : Union [CommandMap [C ], Parseable [C ]], level : int = 0 , max_length : int = 0 ) -> str :
561533 h = ""
562534 if isinstance (commands , Parseable ):
563- h += f"{ indent (level )} { COMMAND_COLOR } { name } { COLOR_RESET } { ' ' * (max_length - len (name ) + 4 )} { commands .description } \n "
535+ h += f"{ indent (level )} { COMMAND_COLOR } { name } { COLOR_RESET } { ' ' * (max_length - len (name )+ 4 )} { commands .description } \n "
564536 elif isinstance (commands , dict ):
565537 h += f"{ indent (level )} { COMMAND_COLOR } { name } { COLOR_RESET } :\n "
566- max_length = max (max_length , level * INDENT_WIDTH + max (len (k ) for k in commands .keys ()))
538+ max_length = max (max_length , level * INDENT_WIDTH + max (len (k ) for k in commands .keys ()))
567539 for name , parser in commands .items ():
568540 h += _to_help (name , parser , level + 1 , max_length )
569541 return h
@@ -577,8 +549,7 @@ def to_help_for_commands(program: str, commands: CommandMap[C], command_chain: O
577549 return h
578550
579551
580- def to_help_for_command (program : str , command : list [str ], parseable : Parseable [C ],
581- defaults : list [tuple [str , ParsingResults ]]) -> str :
552+ def to_help_for_command (program : str , command : list [str ], parseable : Parseable [C ], defaults : list [tuple [str , ParsingResults ]]) -> str :
582553 h = f"usage: { program } { COMMAND_COLOR } { ' ' .join (command )} { COLOR_RESET } { PARAMETER_COLOR } [--help] [--config config.json] [options...]{ COLOR_RESET } \n \n "
583554 h += parseable .to_help (defaults )
584555 h += "\n "
@@ -598,15 +569,7 @@ def instantiate(args: list[str], commands: CommandMap[C]) -> tuple[C, ParsingRes
598569 return _instantiate (args [0 ], args [1 :], commands , [])
599570
600571
601- def inner (cls ) -> Configurable :
602- cls .name = service_name
603- cls .host = service_desc
604- cls .__service__ = True
605- cls .__parameters__ = get_class_parameters (cls )
606-
607-
608- def _instantiate (program : str , args : list [str ], commands : CommandMap [C ], command_chain : list [str ]) -> tuple [
609- C , ParsingResults ]:
572+ def _instantiate (program : str , args : list [str ], commands : CommandMap [C ], command_chain : list [str ]) -> tuple [C , ParsingResults ]:
610573 if command_chain is None :
611574 command_chain = []
612575
@@ -629,8 +592,7 @@ def _instantiate(program: str, args: list[str], commands: CommandMap[C], command
629592 raise TypeError (f"Invalid command type { type (command )} " )
630593
631594
632- def get_environment_variables (parsing_results : ParsingResults , parameter_collection : ParameterCollection ) -> tuple [
633- str , ParsingResults ]:
595+ def get_environment_variables (parsing_results : ParsingResults , parameter_collection : ParameterCollection ) -> tuple [str , ParsingResults ]:
634596 env_parsing_results = dict ()
635597 for key , value in os .environ .items ():
636598 # legacy support
@@ -648,8 +610,7 @@ def get_environment_variables(parsing_results: ParsingResults, parameter_collect
648610 return ("environment variables" , env_parsing_results )
649611
650612
651- def get_env_file_variables (parsing_results : ParsingResults , parameter_collection : ParameterCollection ) -> tuple [
652- str , ParsingResults ]:
613+ def get_env_file_variables (parsing_results : ParsingResults , parameter_collection : ParameterCollection ) -> tuple [str , ParsingResults ]:
653614 env_file_parsing_results = dict ()
654615 for key , value in dotenv_values ().items ():
655616 key = key .split ("." )
@@ -660,15 +621,13 @@ def get_env_file_variables(parsing_results: ParsingResults, parameter_collection
660621 return (".env file" , env_file_parsing_results )
661622
662623
663- def get_config_file_variables (config_file_path : str , parsing_results : ParsingResults ,
664- parameter_collection : ParameterCollection ) -> tuple [str , ParsingResults ]:
624+ def get_config_file_variables (config_file_path : str , parsing_results : ParsingResults , parameter_collection : ParameterCollection ) -> tuple [str , ParsingResults ]:
665625 with open (config_file_path , "r" ) as config_file :
666626 config_file_parsing_results = json .load (config_file )
667627 return (f"config file at '{ config_file_path } '" , config_file_parsing_results )
668628
669629
670- def filter_secret_values (parsing_results : ParsingResults , parameter_collection : ParameterCollection ,
671- basename : Optional [list [str ]] = None ) -> ParsingResults :
630+ def filter_secret_values (parsing_results : ParsingResults , parameter_collection : ParameterCollection , basename : Optional [list [str ]] = None ) -> ParsingResults :
672631 if basename is None :
673632 basename = []
674633
@@ -681,8 +640,7 @@ def filter_secret_values(parsing_results: ParsingResults, parameter_collection:
681640 parsing_results [key ] = "<secret>"
682641
683642
684- def parse_args (program : str , command : list [str ], direct_args : list [str ], parseable : Parseable [C ],
685- parse_env_file : bool = True , parse_environment : bool = True ) -> tuple [C , ParsingResults ]:
643+ def parse_args (program : str , command : list [str ], direct_args : list [str ], parseable : Parseable [C ], parse_env_file : bool = True , parse_environment : bool = True ) -> tuple [C , ParsingResults ]:
686644 parameter_collection = parseable ._parameter_collection
687645
688646 parsing_results : ParsingResults = dict ()
0 commit comments