77import os
88import re
99import sys
10- from inspect import currentframe , getmembers , isfunction , ismethod
10+ from inspect import getmembers , isfunction , ismethod
1111from os .path import basename , splitext
1212
1313from .features .handlers import _hooks
2626BANNER_FONT = None
2727BANNER_STYLE = {}
2828
29- parser_calls = [] # will be populated by calls to ProxyArgumentParser
30-
3129
3230def _save_config (glob ):
3331 cf = glob ['args' ].write_config
@@ -82,38 +80,23 @@ def initialize(add_banner=False,
8280 :param report_func: report generation function
8381 :param autocomplete: add autocompletion with argcomplete
8482 """
85- global parser , parser_calls
83+ global parser
84+ tokens = kwargs .get ('command' , sys .argv )
8685 # handle backward-compatibility arguments
8786 exit_at_interrupt = kwargs .pop ('exit_at_interrupt' , None )
8887 if len (kwargs ) > 0 :
8988 raise TypeError ("Unexpected keyword-arguments (%s)" % ", " .join (kwargs .keys ()))
90- # get caller's frame
91- frame = currentframe ().f_back
9289 # walk the stack until a frame containing a known object is found
93- glob = {}
94- while frame :
95- if isinstance (frame .f_globals .get ('parser' ), ProxyArgumentParser ):
96- glob = frame .f_globals
97- # search for dunders
98- for d in DUNDERS :
99- f = frame
100- while f and (d not in f .f_globals .keys () or f .f_globals [d ] is None ):
101- f = f .f_back
102- try :
103- glob [d ] = f .f_globals [d ]
104- except (AttributeError , KeyError ):
105- pass
106- break
107- frame = frame .f_back
90+ glob = get_tool_globals ()
10891 if any (glob .get (k ) is not None for k in ["NOTIFICATION_ICONS_PATH" , "NOTIFICATION_LEVEL" , "NOTIFICATION_TIMEOUT" ]):
10992 add_notify = True
11093 add = {'config' : add_config , 'demo' : add_demo , 'interact' : add_interact , 'notify' : add_notify ,
11194 'progress' : add_progress , 'step' : add_step , 'time' : add_time , 'version' : add_version , 'wizard' : add_wizard ,
11295 'help' : True , 'usage' : True }
113- p = ArgumentParser (glob )
96+ p = ArgumentParser (command = tokens )
11497 # 1) handle action when no input argument is given
11598 add ['demo' ] = add ['demo' ] and p .examples
116- noarg = len (sys . argv ) == 1
99+ noarg = len (tokens ) == 1
117100 if noarg and noargs_action :
118101 if noargs_action not in add .keys ():
119102 raise ValueError (gt ("Bad action when no args (should be one of: {})" ).format ('|' .join (add .keys ())))
@@ -141,6 +124,7 @@ def __proxy_to_real_parser(value):
141124 return [__proxy_to_real_parser (_ ) for _ in value ]
142125 return value
143126 # now iterate over the registered calls
127+ from .argreparse import parser_calls
144128 for proxy_parser , method , args , kwargs , proxy_subparser in parser_calls :
145129 real_parser = __parsers [proxy_parser ]
146130 args = (__proxy_to_real_parser (v ) for v in args )
@@ -150,7 +134,6 @@ def __proxy_to_real_parser(value):
150134 __parsers [proxy_subparser ] = real_subparser
151135 # this allows to ensure that another call to initialize(...) will have a clean list of calls and an empty _config
152136 # attribute
153- parser_calls = []
154137 ArgumentParser .reset ()
155138 i = p .add_argument_group ("extra arguments" )
156139 # configure documentation formatting
@@ -162,13 +145,13 @@ def __proxy_to_real_parser(value):
162145 note = gt ("this overrides other arguments" ))
163146 c .add_argument ("-w" , "--write-config" , metavar = "INI" , help = gt ("write args to a config file" ))
164147 if noarg and noargs_action == "config" :
165- sys . argv [1 :] = [opt , "config.ini" ]
148+ tokens [1 :] = [opt , "config.ini" ]
166149 # demonstration feature, for executing an example amongst these defined in __examples__, useful for observing what
167150 # the tool does
168151 if add ['demo' ]:
169152 opt = i .add_argument ("--demo" , action = "demo" , prefix = "play" , help = gt ("demonstrate a random example" ))
170153 if noarg and noargs_action == "demo" :
171- sys . argv [1 :] = [opt ]
154+ tokens [1 :] = [opt ]
172155 # help feature, for displaying classical or extended help about the tool
173156 if add ['help' ]:
174157 if glob .get ('__details__' ):
@@ -180,9 +163,9 @@ def __proxy_to_real_parser(value):
180163 else :
181164 opt = i .add_argument ("-h" , "--help" , action = "help" , help = gt ("show this help message and exit" ))
182165 if noarg and noargs_action == "help" :
183- sys . argv [1 :] = ["--help" ]
166+ tokens [1 :] = ["--help" ]
184167 elif noarg and noargs_action == "usage" :
185- sys . argv [1 :] = ["DISPLAY_USAGE" ]
168+ tokens [1 :] = ["DISPLAY_USAGE" ]
186169 # interaction mode feature, for interacting with the tool during its execution, useful for debugging
187170 if add ['interact' ]:
188171 j = p .add_argument_group ("interaction arguments" )
@@ -193,25 +176,25 @@ def __proxy_to_real_parser(value):
193176 j .add_argument ("--port" , default = 12345 , type = port_number , prefix = "remote" ,
194177 help = gt ("remote interacting port" ))
195178 if noarg and noargs_action == "interact" :
196- sys . argv [1 :] = [opt ]
179+ tokens [1 :] = [opt ]
197180 set_interact_items (glob )
198181 # notification feature, for displaying notifications during the execution
199182 if add ['notify' ]:
200183 opt = i .add_argument ("-n" , "--notify" , action = "store_true" , suffix = "mode" , help = gt ("notify mode" ))
201184 if noarg and noargs_action == "notify" :
202- sys . argv [1 :] = [opt ]
185+ tokens [1 :] = [opt ]
203186 set_notify_items (glob )
204187 # progress mode feature, for displaying a progress bar during the execution
205188 if add ['progress' ]:
206189 opt = i .add_argument ("-p" , "--progress" , action = "store_true" , suffix = "mode" , help = gt ("progress mode" ))
207190 if noarg and noargs_action == "progress" :
208- sys . argv [1 :] = [opt ]
191+ tokens [1 :] = [opt ]
209192 set_progress_items (glob )
210193 # stepping mode feature, for stepping within the tool during its execution, especially useful for debugging
211194 if add ['step' ]:
212195 opt = i .add_argument ("--step" , action = "store_true" , last = True , suffix = "mode" , help = gt ("stepping mode" ))
213196 if noarg and noargs_action == "step" :
214- sys . argv [1 :] = [opt ]
197+ tokens [1 :] = [opt ]
215198 set_step_items (glob )
216199 # timing mode feature, for measuring time along the execution of the tool
217200 if add ['time' ]:
@@ -221,15 +204,15 @@ def __proxy_to_real_parser(value):
221204 b .add_argument ("--timings" , action = 'store_true' , last = True , suffix = "mode" ,
222205 help = gt ("display time stats during execution" ))
223206 if noarg and noargs_action == "time" :
224- sys . argv [1 :] = [opt ]
207+ tokens [1 :] = [opt ]
225208 # version feature, for displaying the version from __version__
226209 if add ['version' ]:
227210 version = glob ['__version__' ] if '__version__' in glob else None
228211 if version is not None :
229212 opt = i .add_argument ("--version" , action = 'version' , prefix = "show" , version = version ,
230213 help = gt ("show program's version number and exit" ))
231214 if noarg and noargs_action == "version" :
232- sys . argv [1 :] = [opt ]
215+ tokens [1 :] = [opt ]
233216 # verbosity feature, for displaying debugging messages, with the possibility to handle multi-level verbosity
234217 if multi_level_debug :
235218 i .add_argument ("-v" , dest = "verbose" , default = 0 , action = "count" , suffix = "mode" , cancel = True , last = True ,
@@ -240,7 +223,7 @@ def __proxy_to_real_parser(value):
240223 if add ['wizard' ]:
241224 opt = i .add_argument ("-w" , "--wizard" , action = "wizard" , prefix = "start" , help = gt ("start a wizard" ))
242225 if noarg and noargs_action == "wizard" :
243- sys . argv [1 :] = [opt ]
226+ tokens [1 :] = [opt ]
244227 # reporting feature, for making a reporting with the results of the tool at the end of its execution
245228 if report_func is not None :
246229 if not isfunction (report_func ):
@@ -282,7 +265,7 @@ def __proxy_to_real_parser(value):
282265 # 3) if sudo required, restart the script
283266 if sudo and not is_admin ():
284267 exe = ["runas" , "/env" , "/user:Administrator" ] if WINDOWS else ["sudo" , "-E" ]
285- os .execvp (["sudo" , "runas" ][WINDOWS ], exe + [sys .executable ] + sys . argv )
268+ os .execvp (["sudo" , "runas" ][WINDOWS ], exe + [sys .executable ] + tokens )
286269 # 4) configure logging and get the main logger
287270 a = glob ['args' ]
288271 configure_logger (glob , multi_level_debug ,
@@ -340,36 +323,5 @@ def __at_exit():
340323 globals ()['AT_EXIT_SET' ] = False
341324
342325
343- class ProxyArgumentParser (object ):
344- """
345- Proxy class for collecting added arguments before initialization.
346- """
347- def __getattr__ (self , name ):
348- """ Each time a method is called, return __collect to make it capture the input arguments and keyword-arguments
349- if it exists in the original parser class. """
350- self .__call = name
351- return self .__collect
352-
353- def __collect (self , * args , ** kwargs ):
354- """ Capture the input arguments and keyword-arguments of the currently called method, appending a proxy
355- subparser in case it should be used for mutually exclusive groups or subparsers. """
356- subparser = ProxyArgumentParser ()
357- parser_calls .append ((self , self .__call , args , kwargs , subparser ))
358- del self .__call
359- return subparser
360-
361- def __enter__ (self ):
362- return self
363-
364- def __exit__ (self , exc_type , exc_value , exc_traceback ):
365- pass
366-
367- @staticmethod
368- def reset ():
369- global parser_calls
370- parser_calls = []
371- ArgumentParser .reset ()
372-
373-
374326parser = ProxyArgumentParser ()
375327
0 commit comments