11from argparse import ArgumentParser
2- from typing import TYPE_CHECKING , Callable , Dict , List , Optional , Tuple , Type , get_args , get_origin
2+ from logging import getLogger
3+ from typing import TYPE_CHECKING , Callable , Dict , List , Literal , Optional , Tuple , Type , get_args , get_origin
34
45from hatchling .cli .build import build_command
56
1314)
1415_extras = None
1516
17+ _log = getLogger (__name__ )
18+
1619
1720def parse_extra_args (subparser : Optional [ArgumentParser ] = None ) -> List [str ]:
1821 if subparser is None :
@@ -29,28 +32,40 @@ def _recurse_add_fields(parser: ArgumentParser, model: "BaseModel", prefix: str
2932 arg_name = f"--{ prefix } { field_name .replace ('_' , '-' )} "
3033 if field_type is bool :
3134 parser .add_argument (arg_name , action = "store_true" , default = field .default )
35+ elif field_type in (str , int , float ):
36+ try :
37+ parser .add_argument (arg_name , type = field_type , default = field .default )
38+ except TypeError :
39+ # TODO: handle more complex types if needed
40+ parser .add_argument (arg_name , type = str , default = field .default )
3241 elif isinstance (field_type , Type ) and issubclass (field_type , BaseModel ):
3342 # Nested model, add its fields with a prefix
3443 _recurse_add_fields (parser , getattr (model , field_name ), prefix = f"{ field_name } ." )
44+ elif get_origin (field_type ) is Literal :
45+ literal_args = get_args (field_type )
46+ if not all (isinstance (arg , (str , int , float , bool )) for arg in literal_args ):
47+ _log .warning (f"Only Literal types of str, int, float, or bool are supported - got { literal_args } " )
48+ else :
49+ parser .add_argument (arg_name , type = type (literal_args [0 ]), choices = literal_args , default = field .default )
3550 elif get_origin (field_type ) in (list , List ):
36- # TODO: if list arg is complex type, raise as not implemented for now
51+ # TODO: if list arg is complex type, warn as not implemented for now
3752 if get_args (field_type ) and get_args (field_type )[0 ] not in (str , int , float , bool ):
38- raise NotImplementedError ("Only lists of str, int, float, or bool are supported" )
39- parser .add_argument (arg_name , type = str , default = "," .join (map (str , field .default )))
53+ _log .warning (f"Only lists of str, int, float, or bool are supported - got { get_args (field_type )[0 ]} " )
54+ else :
55+ parser .add_argument (arg_name , type = str , default = "," .join (map (str , field .default )) if isinstance (field , str ) else None )
4056 elif get_origin (field_type ) in (dict , Dict ):
41- # TODO: if key args are complex type, raise as not implemented for now
57+ # TODO: if key args are complex type, warn as not implemented for now
4258 key_type , value_type = get_args (field_type )
4359 if key_type not in (str , int , float , bool ):
44- raise NotImplementedError ( "Only dicts with str keys are supported" )
60+ _log . warning ( f "Only dicts with str keys are supported - got key type { key_type } " )
4561 if value_type not in (str , int , float , bool ):
46- raise NotImplementedError ("Only dicts with str values are supported" )
47- parser .add_argument (arg_name , type = str , default = "," .join (f"{ k } ={ v } " for k , v in field .default .items ()))
62+ _log .warning (f"Only dicts with str values are supported - got value type { value_type } " )
63+ else :
64+ parser .add_argument (
65+ arg_name , type = str , default = "," .join (f"{ k } ={ v } " for k , v in field .default .items ()) if isinstance (field .default , dict ) else None
66+ )
4867 else :
49- try :
50- parser .add_argument (arg_name , type = field_type , default = field .default )
51- except TypeError :
52- # TODO: handle more complex types if needed
53- parser .add_argument (arg_name , type = str , default = field .default )
68+ _log .warning (f"Unsupported field type for argument '{ arg_name } ': { field_type } " )
5469 return parser
5570
5671
0 commit comments