argklass
|pypi| |py_versions| |codecov| |docs| |tests| |style|
.. |pypi| image:: https://img.shields.io/pypi/v/argklass.svg
:target: https://pypi.python.org/pypi/argklass
:alt: Current PyPi Version
.. |py_versions| image:: https://img.shields.io/pypi/pyversions/argklass.svg
:target: https://pypi.python.org/pypi/argklass
:alt: Supported Python Versions
.. |codecov| image:: https://codecov.io/gh/kiwi-lang/argklass/branch/master/graph/badge.svg?token=40Cr8V87HI
:target: https://codecov.io/gh/kiwi-lang/argklass
.. |docs| image:: https://readthedocs.org/projects/argklass/badge/?version=latest
:target: https://argklass.readthedocs.io/en/latest/?badge=latest
.. |tests| image:: https://github.com/kiwi-lang/argklass/actions/workflows/test.yml/badge.svg
:target: https://github.com/kiwi-lang/argklass/actions/workflows/test.yml
.. |style| image:: https://github.com/kiwi-lang/argklass/actions/workflows/style.yml/badge.svg?branch=master
:target: https://github.com/kiwi-lang/argklass/actions/workflows/style.yml
Inspired by Simple Parsing <https://github.com/lebrice/SimpleParsing>
_, simplified
and extended to build extensive, extendable command line interface without much code.
.. code-block:: bash
pip install argklass
Features
-
Automatic cli discovery and command plugin
.. code-block:: bash
# Folder structure
project/cli/
├── __init__.py <= empty
├── editor/
│ ├── __init__.py <= ParentCommand(editor)
│ ├── cook.py <= Command(cook)
│ ├── client.py <= Command(client)
│ ├── game.py <= Command(game)
│ └── open.py <= Command(open)
└── uat/
├── __init__.py <= ParentCommand(uat)
├── localize.py <= Command(localize)
└── test.py <= Command(test)
# editor/__init__.py
from argklass.command import ParentCommand
class Editor(ParentCommand):
name = "editor"
COMMANDS = Editor
# cook.py
from argklass.command import Command
class Cook(Command):
name = "cook"
@staticmethod
def execute(args) -> int:
print("cook")
COMMANDS = Cook
#
cli = CommandLineInterface(project.cli)
cli.run()
# or
cli.run(["editor", "cook", "--help"])
#
cli editor cook --help
cli uat localize --help
-
New Argument format
- able to show the entire command line interface with all its subparsers
- new format mirror dataclass syntax
.. code-block::
editor Set of commands to launch the editors in different modes
server Parameters added to the Map URL
game docstring ...
client docstring ...
resavepackages docstring ...
cook docstring ...
ml Launch unreal engine with mladapter setup
editor Other arguments
open docstring ...
localize docstring ...
worldpartition Convert a UE4 map using world partition
-h, --help Show help
engine Set of commands to manage engine installation/source
add docstring ...
update Update the engine source code
format docstring ...
--profile: str docstring ...
--file: str docstring ...
--fail_on_error: bool = False docstring ...
--col: int = 24 docstring ...
-
Compact argparse definition
.. code-block:: python
def workdir():
d = os.getcwd()
if os.access(d, os.W_OK):
return d
return None
@dataclass
class MyArguments:
a : str # Positional
b : int = 20 # My argument
c : bool = False # My argument
d : int = choice(0, 1, 2, 3, 4, default=1) # choices
e : List[int] = argument(default=[0]) # list
f : Optional[int] = None # Optional
p : Tuple[int, int] = (1, 1) # help p
g : Color = Color.RED # help g
s : SubArgs = SubArgs # helps group
cmd: Union[cmd1, cmd2] = subparsers(cmd1=cmd1, cmd2=cmd2) # Command subparser
de : str = deduceable(workdir)
parser = ArgumentParser()
parser.add_arguments(MyArguments)
args = parser.parse_args()
-
Save and load arguments from configuration files
.. code-block:: python
parser = build_parser(commands)
# load/save defaults before parsing
save_defaults(parser, "config.hjson")
apply_defaults(parser, "config.hjson")
args = parser.parse_args(["editor", "editor"])
# load save arguments after parsing
save_as_config(parser, args, "dump.hjson")
apply_config(parser, args, "dump.hjson")
-
Lower level interface, that gives you back all of argparse power
.. code-block:: python
@dataclass
class SubArgs:
aa: str = argument(default="123")
@dataclass
class cmd1:
args: str = "str1"
@dataclass
class cmd2:
args: str = "str2"
@dataclass
class MyArguments:
a: str = argument(help="Positional")
b: int = argument(default=20, help="My argument")
c: bool = argument(action="store_true", help="My argument")
d: int = argument(default=1, choices=[0, 1, 2, 3, 4], help="choices")
e: List[int] = argument(default=[0], help="list")
f: Optional[int] = argument(default=None, help="Optional")
p: Tuple[int, int] = argument(default=(1, 1), help="help p")
g: Color = argument(default=Color.RED, help="help g")
s: SubArgs = group(default=SubArgs, help="helps group")
cmd: Union[cmd1, cmd2] = subparsers(cmd1=cmd1, cmd2=cmd2)
parser = ArgumentParser()
parser.add_arguments(MyArguments)
args = parser.parse_args()
Architecture
argklass works by building the argument parser as a tree, adding
metadata to each nodes when necessary.
One of the core component is ArgumentParserIterator
which traverse the parsing tree.
Each features, such as argument grouping into dataclasses or saving/loading configuration,
are implemented as a simple traversal.
This enable us to implement each feature independently from each other and make them optional.