mirror of
ssh://git.janware.com/srv/git/janware/proj/jw-python
synced 2026-01-15 01:52:56 +01:00
jwutils.Cmd: Add method add_subcommands()
Add method jwutils.Cmd.add_subcommands(). cmd.add_subcommands(C) will parse and invoke C as a subcommand of cmd, if C is of type jwutils.cmd. Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
parent
ad67dd3832
commit
c5b964a5bb
2 changed files with 41 additions and 3 deletions
|
|
@ -1,9 +1,14 @@
|
||||||
import abc
|
import abc
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
from jwutils import log
|
||||||
|
|
||||||
# compatible with Python 2 *and* 3
|
# compatible with Python 2 *and* 3
|
||||||
ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()})
|
ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()})
|
||||||
|
|
||||||
|
# full blown example of one level of nested subcommands
|
||||||
|
# git -C project remote -v show -n myremote
|
||||||
|
|
||||||
class Cmd(ABC): # export
|
class Cmd(ABC): # export
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
|
|
@ -13,6 +18,9 @@ class Cmd(ABC): # export
|
||||||
def __init__(self, name, help):
|
def __init__(self, name, help):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.help = help
|
self.help = help
|
||||||
|
self.parent = None
|
||||||
|
self.children = []
|
||||||
|
self.child_classes = []
|
||||||
|
|
||||||
async def _run(self, args):
|
async def _run(self, args):
|
||||||
pass
|
pass
|
||||||
|
|
@ -23,3 +31,12 @@ class Cmd(ABC): # export
|
||||||
r.set_defaults(func=self.run)
|
r.set_defaults(func=self.run)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
def add_subcommands(self, cmd):
|
||||||
|
if isinstance(cmd, list):
|
||||||
|
for c in cmd:
|
||||||
|
self.add_subcommands(c)
|
||||||
|
return
|
||||||
|
self.child_classes.append(cmd)
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
pass
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,27 @@ import inspect
|
||||||
import re
|
import re
|
||||||
import pickle
|
import pickle
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
import jwutils
|
import jwutils
|
||||||
from jwutils import log
|
from jwutils import log
|
||||||
|
|
||||||
class Cmds: # export
|
class Cmds: # export
|
||||||
|
|
||||||
|
def __add_cmd_to_parser(self, cmd, parsers):
|
||||||
|
parser = cmd.add_parser(parsers)
|
||||||
|
cmd.add_arguments(parser)
|
||||||
|
if len(cmd.child_classes) > len(cmd.children):
|
||||||
|
for c in cmd.child_classes:
|
||||||
|
cmd.children.append(c())
|
||||||
|
for sub_cmd in cmd.children:
|
||||||
|
subparsers = parser.add_subparsers(title='Available commands of ' + cmd.name, metavar='')
|
||||||
|
self.__add_cmd_to_parser(sub_cmd, subparsers)
|
||||||
|
|
||||||
def __init__(self, description = '', filter = '^Cmd.*', modules=None, eloop=None):
|
def __init__(self, description = '', filter = '^Cmd.*', modules=None, eloop=None):
|
||||||
self.__description = description
|
self.__description = description
|
||||||
self.__filter = filter
|
self.__filter = filter
|
||||||
self.__modules = modules
|
self.__modules = modules
|
||||||
|
self.__cmds = []
|
||||||
default_log_level = log.NOTICE
|
default_log_level = log.NOTICE
|
||||||
default_log_flags = 'stderr,position,prio,color'
|
default_log_flags = 'stderr,position,prio,color'
|
||||||
# poor man's parsing in the absence of a complete command-line definition
|
# poor man's parsing in the absence of a complete command-line definition
|
||||||
|
|
@ -40,9 +52,9 @@ class Cmds: # export
|
||||||
if eloop is None:
|
if eloop is None:
|
||||||
self.eloop = asyncio.get_event_loop()
|
self.eloop = asyncio.get_event_loop()
|
||||||
self.__own_eloop = True
|
self.__own_eloop = True
|
||||||
subparsers = self.__parser.add_subparsers(title='Available commands', metavar='')
|
|
||||||
if self.__modules == None:
|
if self.__modules == None:
|
||||||
self.__modules = [ '__main__' ]
|
self.__modules = [ '__main__' ]
|
||||||
|
subcmds = set()
|
||||||
for m in self.__modules:
|
for m in self.__modules:
|
||||||
if m != '__main__':
|
if m != '__main__':
|
||||||
importlib.import_module(m)
|
importlib.import_module(m)
|
||||||
|
|
@ -54,7 +66,16 @@ class Cmds: # export
|
||||||
log.slog(log.DEBUG, 'instantiating command "{}"'.format(c))
|
log.slog(log.DEBUG, 'instantiating command "{}"'.format(c))
|
||||||
cmd = c()
|
cmd = c()
|
||||||
cmd.cmds = self
|
cmd.cmds = self
|
||||||
cmd.add_parser(subparsers)
|
#cmd.add_parser(subparsers)
|
||||||
|
self.__cmds.append(cmd)
|
||||||
|
for child in cmd.child_classes:
|
||||||
|
subcmds.add(child)
|
||||||
|
subcmds.update(cmd.child_classes)
|
||||||
|
|
||||||
|
cmds = [cmd for cmd in self.__cmds if type(cmd) not in subcmds]
|
||||||
|
subparsers = self.__parser.add_subparsers(title='Available commands', metavar='')
|
||||||
|
for cmd in cmds:
|
||||||
|
self.__add_cmd_to_parser(cmd, subparsers)
|
||||||
|
|
||||||
async def __run(self):
|
async def __run(self):
|
||||||
args = self.__parser.parse_args()
|
args = self.__parser.parse_args()
|
||||||
|
|
@ -69,7 +90,7 @@ class Cmds: # export
|
||||||
self.eloop = None
|
self.eloop = None
|
||||||
self.__own_eloop = False
|
self.__own_eloop = False
|
||||||
|
|
||||||
def parser():
|
def parser(self):
|
||||||
return self.__parser
|
return self.__parser
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue