A project cli command and config library
Project description
Ackermann - Command/Config Library
This library simplifies the startup process of a more complicated python project with multiple subcommands, a complicated configuration, aswell as certain targets that need to be run or initialized before starting commands in a specific order.
The point of this library is to easily provide a way to setup a commandline interface using
logging
and argparse
and contextvars
that looks like this:
my-programm -vvv -c <config_file.py> my-custom-command --my-custom-options
While providing a default way of starting the programm you might implemented way. Just have a look
at ackermann.units
. The main purpose of this library is just to provide an extentable way to
implement commands and startup targets.
Usage
The most simple setup is just to call ackermann.run
in your __main__
file, like so:
from ackermann import run
from ackermann.units import run_command
run(targets=[run_command])
Now if you execute your module with python -m <module>
you can specify a config with -c
change the verbosity level with -v
and specify a subcommand.
Commands
If you want to write your own command you can do so:
from ackermann import Command, Config
from argparse import ArgumentParser
from time import sleep
class MyCommand(Command):
name = "my-command"
@classmethod
def get_arguments(cls, parser: ArgumentParser):
parser.add_argument("-s", "--skip", action="store_true")
def run(self, config: Config):
if config["ARGS"].skip:
print("You wanted to skip")
else:
print("We are doing it as you are not skipping")
sleep(1000)
If you run your program as suggested you are able to run this command with:
python -m <project> my-command -s
The same works for async
commands aswell:
from ackermann import Command, Config
from argparse import ArgumentParser
from asyncio import sleep
class MyAsyncCommand(Command):
name = "my-async-command"
is_async = True
@classmethod
def get_arguments(cls, parser: ArgumentParser):
parser.add_argument("-s", "--skip", action="store_true")
async def async_run(self, config: Config):
if config["ARGS"].skip:
print("You wanted to skip")
else:
print("We are doing it as you are not skipping")
await sleep(1000)
running this command would look like this:
python -m <project> my-async-command -s
Targets / Units
More complicated commands might want to reuse certain parts of code to initialize their project in
the correct way. For this ackermann
has ConfigUnit
s. These work pretty similiar to context
managers around your command.
A unit might be defined like this:
from ackermann import Config, config_unit
@config_unit
async def do_sth(config: Config):
print("I want to do sth before my command starts")
yield
print("Now I need to cleanup as the command finished")
This unit will not run by default, but it must be explicitly stated in the command. Using the
targets
variable. Config units might depend on each other, might conflict with one another or must
be run in a certain order.
They might also force the programm to be run in an async context or on multiple processors.
Signals
If your programm needs to signal certain parts of code about it's state you might also add signals.
To your config by default before executing a command ackermann will signal ready
and after
exiting a command it will signal stopping
. This might be used to signal systemd in case of using
a notify service.
Config Variables
All commands, units and signals are called with the current instance of Config
which itself
stores configuration variables that might be stored in a python module supplied with the -c
flag.
If you want to explicitly tell the programm about these variables you can use the small wrapper
ackermann.ConfigVar
around contextvars.ContextVar
which allows you to specify the format,
type, and default value for a config variable.
These variables might then be imported in your programm without worrying where the get the correct value like so:
from ackermann import ConfigVar
config_my_config_var = ConfigVar("MY_CONFIG_VAR", description="Does something", type=int, default=0)
# At some point in the code
def do_sth():
my_config_var_value = config_my_config_var.get()
One benefit of using this interface is that you can easily check the variables set when starting the
programm with the -V
flag.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file ackermann-1.0.0.tar.gz
.
File metadata
- Download URL: ackermann-1.0.0.tar.gz
- Upload date:
- Size: 20.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/4.0.1 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.0 CPython/3.9.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 16da50d8d73975a999fa1751d80e20a2c3571adafc7b039d74ff5ba7a5f3dc46 |
|
MD5 | 02482b33474ff17eb9092948cde7ac1f |
|
BLAKE2b-256 | 7786ebcc5c5eed1b42ed3e66d018c942026370e69c69b355b19f92ba4574d623 |
File details
Details for the file ackermann-1.0.0-py3-none-any.whl
.
File metadata
- Download URL: ackermann-1.0.0-py3-none-any.whl
- Upload date:
- Size: 52.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/4.0.1 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.0 CPython/3.9.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 82a48972dc828c204ce0aa8893c9a2fbc22e046e7b25069fbfa395bcbb0a1446 |
|
MD5 | e234441cefb711b877e69e46a0732c43 |
|
BLAKE2b-256 | 52eb0638304ebae459f14a7d27585f2ae842580ea4d7c62e942986e2afbd987d |