11from typing import TYPE_CHECKING
22
3- __version__ = "0.0.4 "
3+ __version__ = "0.0.6 "
44if TYPE_CHECKING :
5- import argparse
6- from typing import Sequence , Generator , Any
5+ from argparse import ArgumentParser
6+ from typing import Sequence , Generator
77
88INVALID = object ()
99
@@ -15,7 +15,9 @@ def __init__(self, *args: str, **kwargs):
1515 self .args = args
1616 self .kwargs = kwargs
1717
18- def _add (self , name : str , type_ : type , argp : "argparse.ArgumentParser" , that : object ) -> None :
18+ def _add (
19+ self , name : str , type_ : type , argp : "ArgumentParser" , that : object
20+ ) -> None :
1921 """Add argument to parser."""
2022 args = []
2123 kwargs = {** self .kwargs }
@@ -27,10 +29,14 @@ def _add(self, name: str, type_: type, argp: "argparse.ArgumentParser", that: ob
2729 if action is None :
2830
2931 if const is not None :
30- kwargs ["action" ] = "append_const" if issubclass (type_ , list ) or isinstance (default , list ) else "store_const"
32+ kwargs ["action" ] = (
33+ "append_const"
34+ if issubclass (type_ , list ) or isinstance (default , list )
35+ else "store_const"
36+ )
3137 elif type_ is None :
3238 kwargs ["action" ] = "store"
33- elif issubclass (type_ , bool ):
39+ elif isinstance ( type_ , type ) and issubclass (type_ , bool ):
3440 if default is None :
3541 try :
3642 from argparse import BooleanOptionalAction
@@ -43,7 +49,9 @@ def _add(self, name: str, type_: type, argp: "argparse.ArgumentParser", that: ob
4349 else :
4450 assert default is INVALID or default is False
4551 kwargs ["action" ] = "store_true"
46- elif issubclass (type_ , list ) or isinstance (default , list ):
52+ elif (isinstance (type_ , type ) and issubclass (type_ , list )) or isinstance (
53+ default , list
54+ ):
4755 if "nargs" not in kwargs :
4856 kwargs ["action" ] = "append"
4957 if "default" not in kwargs :
@@ -56,7 +64,11 @@ def _add(self, name: str, type_: type, argp: "argparse.ArgumentParser", that: ob
5664 pass
5765 elif parser :
5866 kwargs ["type" ] = parser
59- elif type_ is not bool and type (type_ ) is type and issubclass (type_ , (int , float , str )):
67+ elif (
68+ type_ is not bool
69+ and type (type_ ) is type
70+ and issubclass (type_ , (int , float , str ))
71+ ):
6072 kwargs ["type" ] = type_
6173 # print(name, type_, that, "_add", action, flag_arg)
6274 if flag_arg is None :
@@ -71,7 +83,9 @@ def _add(self, name: str, type_: type, argp: "argparse.ArgumentParser", that: ob
7183 else :
7284
7385 def add_args (x : str ) -> None :
74- args .append (x if x .startswith ("-" ) else (f"--{ x } " if len (x ) > 1 else f"-{ x } " ))
86+ args .append (
87+ x if x .startswith ("-" ) else (f"--{ x } " if len (x ) > 1 else f"-{ x } " )
88+ )
7589
7690 for x in self .args :
7791 if " " in x or "\t " in x :
@@ -121,14 +135,16 @@ def __getattr__(self, name: str) -> object:
121135 try :
122136 m = super ().__getattr__
123137 except AttributeError :
124- raise AttributeError (f"{ self .__class__ .__name__ } has no attribute { name } " ) from None
138+ raise AttributeError (
139+ f"{ self .__class__ .__name__ } has no attribute { name } "
140+ ) from None
125141 else :
126142 return m (name )
127143
128144 def main (
129145 self ,
130146 args : "Sequence[str]|None" = None ,
131- argp : "argparse. ArgumentParser|None" = None ,
147+ argp : "ArgumentParser|None" = None ,
132148 ):
133149 """Entry point for CLI execution.
134150 Args:
@@ -142,17 +158,17 @@ def main(
142158 self .parse_arguments (argp , args )
143159 return self
144160
145- def new_argparse (self ) -> "argparse. ArgumentParser" :
161+ def new_argparse (self ) -> "ArgumentParser" :
146162 """Create a new argument parser."""
147163 from argparse import ArgumentParser
148164
149165 return ArgumentParser ()
150166
151- def init_argparse (self , argp : "argparse. ArgumentParser" ) -> None :
167+ def init_argparse (self , argp : "ArgumentParser" ) -> None :
152168 """Initialize the argument parser."""
153169 pass
154170
155- def add_arguments (self , argp : "argparse. ArgumentParser" ) -> None :
171+ def add_arguments (self , argp : "ArgumentParser" ) -> None :
156172 """Add arguments to the parser."""
157173 for k , v , t in _arg_fields (self ):
158174 v ._add (k , t , argp , self )
@@ -170,44 +186,32 @@ def start(self) -> None:
170186 pass
171187
172188 def sub_args (self ):
173- # type: () -> Generator[tuple[Main|None, dict[str,Any ]], None, None]
189+ # type: () -> Generator[tuple[Main|None, dict[str,object ]], None, None]
174190 """Yield subcommands."""
175191 yield None , {}
176192
177- def parse_arguments (self , argp : "argparse.ArgumentParser" , args : "Sequence[str]|None" ) -> None :
193+ def parse_arguments (
194+ self , argp : "ArgumentParser" , args : "Sequence[str]|None"
195+ ) -> None :
178196 """Parse command line arguments."""
179197 p = self ._walk_subparsers (argp )
180198
181199 if p :
182200 self ._arg_parent = None
183201 n = argp .parse_args (args )
184- try :
185- s = self ._arg_final = n ._arg_final
186- except AttributeError :
187- raise
188- else :
189- m , h , a = n .__dict__ , None , s
190- while a :
191- h = (a , h )
192- for k , v , t in _arg_fields (a ):
193- if k in m :
194- setattr (a , k , m [k ])
195- a = getattr (a , "_arg_parent" , None )
196- assert h and h [0 ] is self
197- s ._arg_parent_head = h
198- for m in s ._arg_parents_and_self ():
199- m .ready ()
200- for m in s ._arg_parents_and_self ():
201- m .start ()
202- for m in s ._arg_parents_and_self ():
203- m .done ()
202+ s = self ._arg_final = n ._arg_final
203+ for k , v in n .__dict__ .items ():
204+ setattr (s , k , v )
205+ s .ready ()
206+ s .start ()
207+ s .done ()
204208 else :
205209 argp .parse_args (args , self )
206210 self .ready ()
207211 self .start ()
208212 self .done ()
209213
210- def _walk_subparsers (self , argp : "argparse. ArgumentParser" , root = None ):
214+ def _walk_subparsers (self , argp : "ArgumentParser" , root = None ):
211215 s = None
212216 for c , d in self .sub_args ():
213217 if c :
@@ -222,19 +226,16 @@ def _walk_subparsers(self, argp: "argparse.ArgumentParser", root=None):
222226 return s
223227
224228 def _arg_parents_and_self (self ):
225- # type: () -> Generator[Main, Any, Any]
226- c = self ._arg_parent_head
229+ c : "Main | None" = self
227230 while c is not None :
228- d , n = c
229- yield d
230- c = n
231+ yield c
232+ c = c ._arg_parent
231233
232234 def _arg_parents (self ):
233- for d in self ._arg_parents_and_self ():
234- if d is self :
235- break
236- yield d
235+ c = self ._arg_parent
236+ while c is not None :
237+ yield c
238+ c = c . _arg_parent
237239
238240 _arg_final : "Main | None"
239241 _arg_parent : "Main | None"
240- _arg_parent_head : "tuple[Main, tuple] | None"
0 commit comments