~brenns10/subc

eb843d36d089aa80bd436469a6fedc1bf33ab348 — Stephen Brennan 2 years ago v0.1.0
Initial commit
4 files changed, 143 insertions(+), 0 deletions(-)

A .gitignore
A README.rst
A setup.py
A subc.py
A  => .gitignore +3 -0
@@ 1,3 @@
*.pyc
__pycache__
venv

A  => README.rst +49 -0
@@ 1,49 @@
subc
====

This is a tiny library to help you write CLI applications with many
sub-commands.

Installation
------------

``pip install subc``

Use
---

Create your own command subclass for your application (optional, but
encouraged):


.. code:: python

    class MyCmd(subc.Command):
        pass

Then, write commands in your application which sub-class this:

.. code:: python

    class HelloWorld(MyCmd):
        name = 'hello-world'
        description = 'say hello'
        def run(self):
            print('hello world')

Finally, use your application-level subclass for creating the argument parser
and running your application:

.. code:: python

    def main():
        parser = argparse.ArgumentParser(description='a cool tool')
        MyCmd.add_commands(parser)
        args = parser.parse_args()
        args.func(args)

License
-------

This project is released under the Revised BSD license.  See ``LICENSE.txt`` for
details.

A  => setup.py +24 -0
@@ 1,24 @@
from setuptools import setup

long_description = open('README.rst').read()

setup(
    name='subc',
    version='0.1.0',
    description='CLI sub-command library',
    long_description=long_description,
    url='https://git.sr.ht/~brenns10/subc',
    author='Stephen Brennan',
    author_email='stephen@brennan.io',
    license='Revised BSD',
    py_modules=['subc'],
    classifiers=[
        'Development Status :: 3 - Alpha',
        'License :: OSI Approved :: BSD License',
        'Intended Audience :: Developers',
        'Environment :: Console',
        'Natural Language :: English',
        'Programming Language :: Python :: 3 :: Only',
    ],
    keywords='arguments sub-command command',
)

A  => subc.py +67 -0
@@ 1,67 @@
#!/usr/bin/env python3
"""
A simple sub-command library for writing rich CLIs
"""
import argparse
from abc import ABC
from abc import abstractproperty
from abc import abstractmethod


class Command(ABC):
    """
    A simple class for implementing sub-commands in your command line
    application. Create a subclass for your app as follows:

        class MyCmd(subc.Command):
            pass

    Then, each command in your app can subclass this, implementing the three
    required fields:

        class HelloWorld(MyCmd):
            name = 'hello-world'
            description = 'say hello'
            def run(self):
                print('hello world')

    Finally, use your app-level subclass for creating an argument parser:

        def main():
            parser = argparse.ArgumentParser(description='a cool tool')
            MyCmd.add_commands(parser)
            args = parser.parse_args()
            args.func(args)
    """

    @abstractproperty
    def name(self):
        pass

    @abstractproperty
    def description(self):
        pass

    def add_args(self, parser):
        pass  # default is no arguments

    @abstractmethod
    def run(self):
        pass

    def base_run(self, args):
        self.args = args
        return self.run()

    @classmethod
    def add_commands(cls, parser):
        subparsers = parser.add_subparsers(title='sub-command')
        for subcls in cls.__subclasses__():
            cmd = subcls()
            cmd_parser = subparsers.add_parser(cmd.name, description=cmd.description)
            cmd.add_args(cmd_parser)
            cmd_parser.set_defaults(func=cmd.base_run)
        def default(*args, **kwargs):
            raise Exception('you must select a sub-command')
        parser.set_defaults(func=default)
        return parser