@@ -22,18 +22,18 @@ def __init__(self, *args, **kwargs):
2222--------------------------
2323# It usually makes sense to inherit directly from Command class.
2424# All common methods and attributes should be in the container.
25- # Specify any OptionParser options in options() method.
26- # OptionParser .parse_args() result is automatically passed to run(*args, **kwargs) method.
27- # A OptionParser instance os available in self.parser attribute.
25+ # Specify command arguments in the options() method using add_argument() .
26+ # ArgumentParser .parse_args() result is automatically passed to run(*args, **kwargs) method.
27+ # An ArgumentParser instance is available in self.parser attribute.
2828
2929class Make_Dirs(Command):
3030 '''create directories'''
3131 enabled = True
3232 admin = False
3333
3434 def options(self):
35- self.parser.usage = "%% prog %s [options] <user>" % self.normalized_name
36- self.parser.add_option ("-m", "--mode", help="set directory perms (0xxx)")
35+ self.parser.usage = "%( prog)s %s [options] <user>" % self.normalized_name
36+ self.parser.add_argument ("-m", "--mode", help="set directory perms (0xxx)")
3737
3838 def run(self, *args, **kwargs):
3939 if len(args) < 1:
@@ -68,9 +68,8 @@ def run(self, *args, **kwargs):
6868
6969from __future__ import print_function
7070import sys
71- import optparse
71+ import argparse
7272import datetime
73- from optparse import Option
7473from six .moves .xmlrpc_client import Fault
7574
7675from kobo .plugins import Plugin , PluginContainer
@@ -183,32 +182,41 @@ def normalize_name(cls, name):
183182 return name .lower ().replace ('_' , '-' ).replace (' ' , '-' )
184183
185184
186- class CommandOptionParser (optparse . OptionParser ):
185+ class CommandOptionParser (argparse . ArgumentParser ):
187186 """Enhanced OptionParser with plugin support."""
188187 def __init__ (self ,
189188 usage = None ,
190- option_list = None ,
191- option_class = Option ,
192189 version = None ,
193190 conflict_handler = "error" ,
194191 description = None ,
195- formatter = None ,
196- add_help_option = True ,
192+ formatter_class = None ,
193+ add_help = True ,
197194 prog = None ,
198195 command_container = None ,
199196 default_command = "help" ,
200197 add_username_password_options = False ,
201198 add_hub_option = False ,
202199 default_profile = "" ,
203200 configuration_directory = "/etc" ):
204-
205- usage = usage or "%prog <command> [args] [--help]"
201+ usage = usage or "%(prog)s <command> [args] [--help]"
206202 self .container = command_container
207203 self .default_command = default_command
208204 self .command = None
209- formatter = formatter or optparse .IndentedHelpFormatter (max_help_position = 33 )
210-
211- optparse .OptionParser .__init__ (self , usage , option_list , option_class , version , conflict_handler , description , formatter , add_help_option , prog )
205+ formatter_class = formatter_class or argparse .RawTextHelpFormatter
206+
207+ # Initialize the argument parser
208+ super (CommandOptionParser , self ).__init__ (
209+ prog = prog ,
210+ usage = usage ,
211+ description = description ,
212+ conflict_handler = conflict_handler ,
213+ add_help = add_help ,
214+ formatter_class = formatter_class ,
215+ )
216+
217+ # Add version argument if provided
218+ if version :
219+ self .add_argument ('--version' , action = 'version' , version = version )
212220
213221 if add_username_password_options :
214222 self ._add_opts (
@@ -263,7 +271,7 @@ def format_help_commands(self, admin=False):
263271
264272 def parse_args (self , args = None , values = None ):
265273 """return (command_instance, opts, args)"""
266- args = self . _get_args ( args )
274+ args = args if args is not None else sys . argv [ 1 :]
267275 command = None
268276
269277 if len (args ) > 0 and not args [0 ].startswith ("-" ):
@@ -281,25 +289,37 @@ def parse_args(self, args=None, values=None):
281289 if self .command != cmd .normalized_name :
282290 self .command = cmd .normalized_name
283291 cmd .options ()
284- cmd_opts , cmd_args = optparse .OptionParser .parse_args (self , args , values )
285- return (cmd , cmd_opts , cmd_args )
286292
287- def run (self , args = None , values = None ):
293+ # Parse arguments using argparse
294+ parsed_args = super (CommandOptionParser , self ).parse_args (args )
295+
296+ # Get remaining positional arguments (if any)
297+ remaining_args = getattr (parsed_args , 'args' , [])
298+
299+ return (cmd , parsed_args , remaining_args )
300+
301+ def run (self , args = None ):
288302 """parse arguments and run a command"""
289- cmd , cmd_opts , cmd_args = self .parse_args (args , values )
290- cmd_kwargs = cmd_opts .__dict__
303+ # Get command instance and parsed arguments
304+ cmd , parsed_args , remaining_args = self .parse_args (args )
305+
306+ # Convert Namespace to dictionary for kwargs
307+ cmd_kwargs = vars (parsed_args )
291308
292- # this block should only be evaluated if default_profile has been set at instantiation
309+ # Handle profile if specified
293310 if self .default_profile and 'profile' in cmd_kwargs :
294- self ._load_profile (cmd_kwargs ['profile' ])
311+ self ._load_profile (cmd_kwargs ['profile' ])
295312
296- cmd .run (* cmd_args , ** cmd_kwargs )
313+ # Run command with positional args and keyword args
314+ cmd .run (* remaining_args , ** cmd_kwargs )
297315
298316 def _add_opts (self , * args ):
299317 """populates one or more options with their respective help texts"""
300- option_list = [optparse .Option (option , help = help_text ) for option , help_text in args ]
301318
302- self ._populate_option_list (option_list = option_list , add_help = False )
319+ for option , help_text in args :
320+ # Strip leading dashes and use as destination
321+ dest = option .lstrip ('-' ).replace ('-' , '_' )
322+ self .add_argument (option , dest = dest , help = help_text )
303323
304324 def _load_profile (self , profile ):
305325 """load configuration file under location <CONFIGURATION_DIRECTORY>/<PROFILE>.conf"""
@@ -326,9 +346,12 @@ class Help_Admin(Command):
326346
327347 def options (self ):
328348 # override default --help option
329- opt = self .parser .get_option ("--help" )
330- opt .action = "store_true"
331- opt .dest = "help"
349+ self .parser .add_argument (
350+ "--help" ,
351+ action = "store_true" ,
352+ dest = "help" ,
353+ help = "show help message and exit"
354+ )
332355
333356 def run (self , * args , ** kwargs ):
334357 self .parser .print_help (admin = True )
@@ -366,12 +389,14 @@ def run(self, *args, **kwargs):
366389 print ("--------" )
367390
368391 for command_name , CommandClass in sorted (self .parser .container .plugins .items ()):
369- parser = optparse .OptionParser (usage = self .parser .usage )
392+ parser = argparse .ArgumentParser (
393+ usage = self .parser .usage ,
394+ formatter_class = argparse .RawTextHelpFormatter
395+ )
370396 cmd = CommandClass (parser )
371397 cmd .normalized_name = command_name
372398 cmd .options ()
373399 cmd .container = self .parser .container
374- cmd_opts , cmd_args = parser .parse_args ()
375400
376401 print (command_name )
377402 print ("-" * len (command_name ))
@@ -380,24 +405,39 @@ def run(self, *args, **kwargs):
380405 print ("[ADMIN ONLY]" , end = ' ' )
381406
382407 print (cmd .__doc__ .strip (), end = "\n \n " )
383- usage = parser .get_usage ().strip ().replace ("Usage: " , "**Usage:** " , 1 )
408+
409+ # Get formatted usage
410+ usage = parser .format_usage ()
384411 if usage :
385- print (usage , end = "\n \n " )
412+ print (usage . replace ( "usage: " , "**Usage:** " ) , end = "\n \n " )
386413
387- for opt in sorted (parser .option_list , key = str ):
388- if "-h/--help" in str (opt ):
414+ # Process and display arguments
415+ for action in parser ._actions :
416+ # Skip help action
417+ if action .dest == 'help' :
389418 continue
390- if opt .nargs :
391- metavar = opt .metavar or opt .dest .upper ()
392- opt_list = []
393- for opt_str in opt ._short_opts + opt ._long_opts :
394- if opt .nargs is not None :
395- opt_list .append ("%s=%s" % (opt_str , metavar ))
419+
420+ # Format option strings
421+ opts = []
422+ for opt_str in action .option_strings :
423+ if action .metavar :
424+ opts .append (f"{ opt_str } ={ action .metavar } " )
425+ elif action .nargs :
426+ opts .append (f"{ opt_str } ={ action .dest .upper ()} " )
396427 else :
397- opt_list .append (opt_str )
398- print ("/" .join (opt_list ))
399- print (" %s" % opt .help )
400- if opt .action == "append" :
428+ opts .append (opt_str )
429+
430+ if opts : # Optional arguments
431+ print ("/" .join (opts ))
432+ elif action .dest != 'help' : # Positional arguments
433+ print (action .dest )
434+
435+ # Print help text
436+ if action .help :
437+ print (f" { action .help } " )
438+
439+ # Show if argument can be specified multiple times
440+ if action .nargs in ('+' , '*' , argparse .REMAINDER ):
401441 print ("\n This option can be specified multiple times" )
402442 print ()
403443 print ()
0 commit comments