#-----------------------------------------------------------------------------# Copyright (c) Anaconda, Inc., and Bokeh Contributors.# All rights reserved.## The full license is in the file LICENSE.txt, distributed with this software.#-----------------------------------------------------------------------------''' Provides a base class for defining subcommands of the Bokeh commandline application.'''#-----------------------------------------------------------------------------# Boilerplate#-----------------------------------------------------------------------------from__future__importannotationsimportlogging# isort:skiplog=logging.getLogger(__name__)#-----------------------------------------------------------------------------# Imports#-----------------------------------------------------------------------------# Standard library importsfromabcimportABCMeta,abstractmethodfromargparseimportArgumentParser,Namespacefromtypingimport(Any,ClassVar,Literal,Sequence,TypeAlias,)# Bokeh importsfrom..util.dataclassesimport(NotRequired,Unspecified,dataclass,entries,)#-----------------------------------------------------------------------------# Globals and constants#-----------------------------------------------------------------------------__all__=('Subcommand',)#-----------------------------------------------------------------------------# General API#-----------------------------------------------------------------------------#-----------------------------------------------------------------------------# Dev API#-----------------------------------------------------------------------------@dataclassclassArgument:action:NotRequired[Literal["store","store_const","store_true","append","append_const","count","help","version","extend"]]=Unspecifiednargs:NotRequired[int|Literal["?","*","+","..."]]=Unspecifiedconst:NotRequired[Any]=Unspecifieddefault:NotRequired[Any]=Unspecifiedtype:NotRequired[type[Any]]=Unspecifiedchoices:NotRequired[Sequence[Any]]=Unspecifiedrequired:NotRequired[bool]=Unspecifiedhelp:NotRequired[str]=Unspecifiedmetavar:NotRequired[str]=UnspecifiedArg:TypeAlias=tuple[str|tuple[str,...],Argument]Args:TypeAlias=tuple[Arg,...]
[docs]classSubcommand(metaclass=ABCMeta):''' Abstract base class for subcommands Subclasses should implement an ``invoke(self, args)`` method that accepts a set of argparse processed arguments as input. Subclasses should also define the following class attributes: * ``name`` a name for this subcommand * ``help`` a help string for argparse to use for this subcommand * ``args`` the parameters to pass to ``parser.add_argument`` The format of the ``args`` should be a sequence of tuples of the form: .. code-block:: python ('argname', Argument( metavar='ARGNAME', nargs='+', )) Example: A simple subcommand "foo" might look like this: .. code-block:: python class Foo(Subcommand): name = "foo" help = "performs the Foo action" args = ( ('--yell', Argument( action='store_true', help="Make it loud", )), ) def invoke(self, args): if args.yell: print("FOO!") else: print("foo") Then executing ``bokeh foo --yell`` would print ``FOO!`` at the console. '''name:ClassVar[str]help:ClassVar[str]args:ClassVar[Args]=()
[docs]def__init__(self,parser:ArgumentParser)->None:''' Initialize the subcommand with its parser Args: parser (Parser) : an Argparse ``Parser`` instance to configure with the args for this subcommand. This method will automatically add all the arguments described in ``self.args``. Subclasses can perform any additional customizations on ``self.parser``. '''self.parser=parserforarginself.args:flags,spec=argifnotisinstance(flags,tuple):flags=(flags,)ifnotisinstance(spec,dict):kwargs=dict(entries(spec))else:# NOTE: allow dict for run time backwards compatibility, but don't include in typeskwargs=specself.parser.add_argument(*flags,**kwargs)
[docs]@abstractmethoddefinvoke(self,args:Namespace)->bool|None:''' Takes over main program flow to perform the subcommand. *This method must be implemented by subclasses.* subclassed overwritten methods return different types: bool: Build None: FileOutput (subclassed by HTML, SVG and JSON. PNG overwrites FileOutput.invoke method), Info, Init, \ Sampledata, Secret, Serve, Static Args: args (argparse.Namespace) : command line arguments for the subcommand to parse Raises: NotImplementedError '''raiseNotImplementedError("implement invoke()")