Skip to content

Command line

The logic is a little bit complex and also is a big software architecture at command line option part.

Before how to extend the new command line and implement its feature, this section records the details of the command line part design and implementation.

Implementation details

About a whole command line structure, we can divide it as multiple parts to describe its details:

  • Pure value
    • Enum object about command line section SubCommandSection
    • Enum object about command line SubCommandLine
  • Object for truly function
    • Base data model about major command line BaseSubCommandXXX
    • Base data model about subcommand line SubCommandXXXOption for its options
    • Command line options of the subcommand line SubCommandXXXOption

What is different between Pure value and Object for truly function?

  • Pure value

    It just the value you can use for the command line feature to display, use look like. But it DOES NOT have truly function to work.

  • Object for truly function

    This sections are the implementations which could setup a truly features for working finely. In generally, these sections would use the value from previous one Pure value.

Pure value

Command line section value in SubCommandSection

source code

This is the section title of subcommand line usage. Each new subcommand line should define this value for brief of subcommand line operations.

fake_api_server.command.subcommand
1
2
3
4
5
6
# code usage of a command line option

class SubCommandSection(Enum):
    Base = "API servers"
    ApiServer = "API server subcommands"
    Foo = "Foo command line"

command line section

Command line value in SubCommandLine

source code

This is the command line self string value what it is.

fake_api_server.command.subcommand
1
2
3
4
5
6
7
8
9
# code usage of a command line option

class SubCommandLine(Enum):
    Base = "subcommand"

    # some code here ...

    Foo = "foo"
    Boo = "boo"

command line

Object for truly function

Major command line BaseSubCommandXXX

example source code

This is the top implementation layer of command line data models. PyFake-API-Server command line tool is a nested command line structure. And this layer is the top layer means the first layer command line.

fake_api_server.command.foo.option
# code usage of a command line option

class BaseMajorCommandFoo(CommandOption):
    sub_cmd: SubCommandAttr = SubCommandAttr(
        title=SubCommandSection.Foo,
        dest=SubCommandLine.Foo,
        description="Some operations for foo.",
        help="Demonstrate for foo.",
    )
    in_sub_cmd = SubCommandLine.Foo

major command line

Subcommand command line SubCommandXXXOption

example source code

Previous one is the top layer, this layer is the layers which are under second layer.

Subcommand line must identify one specific major command line

This layer command line data model would extend one specific major command line data model, which means it would only runs under one specific command line. So please take care what command line it should use to extend its features.

Below demonstration is extend feature under the parent command line foo.

fake_api_server.command.foo.boo.option
# code usage of a command line option

class SubCommandBooOption(BaseMajorCommandFoo):
    sub_parser: SubParserAttr = SubParserAttr(
        name=SubCommandLine.Boo,
        help="Set up a boo CLI for foo.",
    )
    option_value_type: type = str


BaseSubCmdBooOption: type = MetaCommandOption("BaseSubCmdBooOption", (SubCommandBooOption,), {})

subcommand lines

Options of subcommand command line SubCommandXXXOption

example source code

This is the truly command line options. Any command line option properties, i.e., option name, help description of option, etc., would be set here.

fake_api_server.command.foo.boo.option
1
2
3
4
5
6
7
# code usage of a command line option

class CmdOption(BaseSubCmdBooOption):
    cli_option: str = "-o, --option"
    name: str = "option"
    help_description: str = "The sample command line option setting."
    default_value: str = "test value"

subcommand line option

UML

  • It has 3 base classes:

    • MetaCommandOption source code

      It's a metaclass for instantiating base class. It would auto-register objects which extends the base class be instantiated from this metaclass to list type data COMMAND_OPTIONS. If it is sub-command, it also saves sub-command line string to list type data SUBCOMMAND.

    • CommandOption (includes all subclasses of BaseSubCommand) source code

      It defines all attributes and functions for subclass to reuse or override to implement customize logic.

    • BaseCmdOption, BaseSubCommandRestServer, etc.

      This is the base class which should be extended by all subclasses. This object be instantiated by metaclass MetaCommandOption and general object CommandOption.

  • Every sub-command has their own base class. For example, sub-command line run with BaseSubCmdRunOption, config with BaseSubCmdConfigOption and so on.

  • The list be used by function get_all_subcommands is variable SUBCOMMAND.
  • The list be used by function make_options is variable COMMAND_OPTIONS.
  • All subclasses, i.e., Version extends BaseCmdOption, WebAppType extends BaseSubCmdRunOption, ConfigPath extends BaseSubCmdConfigOption, etc., means the specific options under the sub-command line.
The great idea about auto-register refer to source code of project Gunicorn

About the powerful design auto-register which has beautiful extension, it refers to the module config implementation of open source project Gunicorn. Please refer to its source code if you have interesting in it.

Workflow

  • Sequence diagram

From above sequence diagram, it does auto-registration when initialize an object. It won't do something to iterate all objects and save them to list type object, it automates all things when you add one or more new subclasses which is responsible for new sub-command line.