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.

🐌 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.7.0.tar.gz (40.9 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.7.0-py3-none-any.whl (63.4 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for nuclear-2.7.0.tar.gz
Algorithm Hash digest
SHA256 733020f28cbb3e354ff02cdadda1f3f030561e6230cf1d7f349290151faba868
MD5 fedc4c8fa2746eb1e41b4e2ce2aa2967
BLAKE2b-256 7a4135bb8978c9f0861763d138a73c1c8afc53d13279d48ab6b8050ce1422fbc

See more details on using hashes here.

File details

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

File metadata

  • Download URL: nuclear-2.7.0-py3-none-any.whl
  • Upload date:
  • Size: 63.4 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.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7982e8aa5f31922998723e1f9a409489391dbe426752c61c74af8582373ee44d
MD5 80b285b37b119a726ca0be1439aa18fe
BLAKE2b-256 f48e327986675a29405c4015910eed3200c860cafa404b485152331a57c726a5

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