Skip to main content

Declarative parser for command line interfaces

Project description

☢️ Nuclear

GitHub version (latest SemVer) PyPI Github Pages Documentation Status codecov GitHub Workflow Status

Nuclear is a binding glue for CLI applications. It consists of tools for building CLI applications in Python, including:

CLI Demo

from nuclear import CliBuilder

cli = CliBuilder()

@cli.add_command('hello')
def say_hello(name: str, decode: bool = False, repeat: int = 1):
    """
    Say hello
    :param decode: Decode name as base64
    """
    message = f"I'm a {b64decode(name).decode() if decode else name}!"
    print(' '.join([message] * repeat))

@cli.add_command('calculate', 'factorial')
def calculate_factorial(n: int):
    """Calculate factorial"""
    print(reduce(lambda x, y: x * y, range(1, n + 1)))

@cli.add_command('calculate', 'primes')
def calculate_primes(n: int):
    """List prime numbers using Sieve of Eratosthenes"""
    print(sorted(reduce((lambda r, x: r - set(range(x**2, n, x)) if (x in r) else r), range(2, n), set(range(2, n)))))

cli.run()

See demo.py for a complete example.

Installation

python3 -m pip install --upgrade nuclear

You need Python 3.10 or newer.

📜 Sublog

Sublog is a nuclear's contextual logging system that allows you to:

  • display variables besides log messages: logger.debug('message', airspeed=20),
  • wrap errors with context: with add_context('ignition'),
  • catch errors and show traceback in a concise, pretty format: with error_handler().
from nuclear.sublog import logger, error_handler, add_context

with error_handler():
    logger.debug('checking engine', temperature=85.0, pressure='12kPa')
    with add_context('ignition', request=42):
        logger.info('ignition ready', speed='zero')
        with add_context('liftoff'):
            raise RuntimeError('explosion')

sublog demo

Context logger

Use nuclear.sublog.logger to log message with a pretty format out of the box.

Pass additional context variables as keyword arguments to display them in the log message.

from nuclear.sublog import logger

logger.info('info log')
logger.debug('debug log', var1=1, var2='two')
logger.info('not great not terrible', radioactivity=3.6)
logger.error('this is bad')
logger.exception(RuntimeError('this is worse'))

Error handler

Use nuclear.sublog.error_handler to catch errors and show traceback in a concise, pretty format.

from nuclear.sublog import error_handler

with error_handler():
    raise RuntimeError('explosion')

Wrapping context

Use nuclear.sublog.add_context to wrap code with additional context information. This will be included in in the log message, if an error occurs.

from nuclear.sublog import add_context

with add_context('reloading plugins'):
    with add_context('loading config'):
        raise RuntimeError('file is missing')

This will produce an error with the following message:

reloading plugins: loading config: file is missing

Note that while each individual part of the message may not provide a comprehensive explanation of the error, when combined, the whole message becomes highly informative. This is the core principle behind enriching errors with context.

🚀 Nuke - Task Runner

Nuke is a lightweight task runner built into Nuclear for automating project tasks. It serves as a replacement for Makefile.

Define tasks as simple Python functions in a nukefile.py:

from nuclear import nuke, logger

class Config:
    src_path: str = '/opt/dump'
    dst_path: str = '/media/user/DRIVE/'
    dry: bool = False

config, sh = nuke.init(Config)

def push():
    sh(f"rsync -avh --delete --size-only --info=progress2 '{src_path}/' '{dst_path}'")

def convert():
    sh(f'ffmpeg -i "{src_path}/input.mp4" "{dst_path}/audio.mp3"')

if __name__ == '__main__':
    nuke.run()

Run tasks from command line:

nuke push
# or
./nukefile.py push

# see available tasks
nuke
./nukefile.py

# dry run mode
nuke push --dry

# override config parameters
nuke convert --src_path=/src/dump

See Nuke documentation for detailed guide.

🐌 Shell utilities

Nuclear provides utilities for running system shell commands.

Basic usage:

from nuclear import shell

window_id: str = shell('xdotool getactivewindow')

shell function captures the stdout & stderr output of the shell command and returns it as a string. It may also print live stdout in real time (line by line) and capture output in case of errors.

It has a lot of possibilities thanks to its parameters:

  • cmd: str - shell command to run
  • workdir: Optional[Path] = None - working directory for the command
  • print_stdout: bool = False - whether to print live stdout in real time (line by line) from a subprocess
  • print_log: bool = False - whether to print a log message about running the command
  • raw_output: bool = False - whether to let subprocess manage stdout/stderr on its own instead of capturing it
  • independent: bool = False - whether to start an independent process that can outlive the caller process
  • output_file: Optional[Path] = None - optional file to write the output in real time

It returns the stdout of the command combined with stderr. In case of non-zero command exit code, shell raises CommandError exception.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nuclear-2.10.0.tar.gz (42.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nuclear-2.10.0-py3-none-any.whl (66.3 kB view details)

Uploaded Python 3

File details

Details for the file nuclear-2.10.0.tar.gz.

File metadata

  • Download URL: nuclear-2.10.0.tar.gz
  • Upload date:
  • Size: 42.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.12.10

File hashes

Hashes for nuclear-2.10.0.tar.gz
Algorithm Hash digest
SHA256 7fcc5f2f756f139f554e98fabab65001273f25a28d84752b2a8d20162f93ee2f
MD5 f4708a7dc866449ee9d29c4cfe3d5cd3
BLAKE2b-256 0865109073cd2dfb4865b19439afebb2e6e10ecd0cc6b8a593a130c3507e8487

See more details on using hashes here.

File details

Details for the file nuclear-2.10.0-py3-none-any.whl.

File metadata

  • Download URL: nuclear-2.10.0-py3-none-any.whl
  • Upload date:
  • Size: 66.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.12.10

File hashes

Hashes for nuclear-2.10.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4c1d0630bdcfc21ba0e51212f2fd57dbd41936665b491989fca4906c7320424e
MD5 860d98e5dfe2a5c1168995360898a98c
BLAKE2b-256 e58c197821668f75221a86ac688015569a06491ba0dc2eb62774328abca67639

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page