Skip to main content

Friendly misc/utils/convenience library

Project description

Friendly misc/utils/convenience library

Version on pypi Tested with Github Actions Test code codecov Python versions tested (link to github project)

Overview

runez is a convenience "utils" library for common operations I found myself rewriting multiple times.

The name was initially meant as “run ez” (“run easy”), the fact that it sounds like “runes” gives it a bit of a mystery/magic side that’s also relatively appropriate (it does indeed concentrate a bit of invocation magic, as you can save quite a few lines of repetitive code by using it)

Features

  • Usable with any python version

  • Pure python standalone library, does not bring in any additional dependency

  • Takes care of most edge cases, with nice errors

    • Functions can be called without checking for return code etc (abort by default, with nice error)

    • They can also be called with fatal=False, in which case the return value will indicate whether call succeeded or not

  • Support for dryrun mode (show what would be done, but don’t do it)

  • Perform most typical logging setups in one call to runez.log.setup()

  • Log operations systematically (at debug level mostly), examples:

    Running: foo ...
    Copy foo -> bar
    Would move foo -> bar    (for dryrun)
  • CaptureOutput context manager -> grab output/logging from any code section

  • 100% test coverage

Example

Run a program:

import runez

# Aborts if "foo" doesn't exist
output = runez.run("ls", "foo")

# Output can also be ignored
runez.run("ls", "foo")

# Don't capture output, just run the command and let output "pass through"
runez.run("ls", "foo", stdout=None, stderr=None)

# Don't abort, return False on failure (or actual output when successful)
output = runez.run("ls", "foo", fatal=False)

File operations:

import runez

runez.touch("foo")
runez.copy("foo", "bar")
runez.move("foo", "baz")
runez.delete("foo")

runez.write("foo", "bar\nbaz\n")
content = "\n".join(runez.readlines("foo", first=10))

full_path = runez.resolved_path("foo/bar")
folder = runez.parent_folder(full_path)
runez.ensure_folder(folder)
with runez.Anchored(folder):
    assert runez.short(full_path) == "bar"

Installation

As usual, available on pypi: pip install runez

Philosophy

runez tries to provide a consistent interface across functions. Here are the main tenets for functions involving I/O (such as writing, reading, copy-ing files etc):

All IO-related functions NOT returning content (run(), delete(), …) have this common signature: fatal=True, logger=UNSET, dryrun=UNSET

  • fatal: decides whether operation should raise an exception on failure or not

    • fatal=True (default): raise an exception on failure, log a meaningful error

    • fatal=False: don’t raise on failure, log a meaningful error

    • fatal=None: don’t raise on failure, don’t log anything

    • In non-fatal mode, calls try to return a usable value appropriate for the call (see docstring of each function)

  • logger: decides how chatty the operation should be

    • LOG.error() is used for failures, except when fatal is not True AND provided logger is a callable

    • logger=UNSET (default):

      • LOG.debug("Running: ...") to trace activity

      • print("Would run: ...") in dryrun mode

    • logger=False: Log errors only (used internally, to avoid unnecessary log chatter when one operation calls another)

    • logger=mylogger: call provided mylogger() to trace activity (example: logger=MY_LOGGER.info)

      • mylogger("Running: ...") to trace activity

      • mylogger("Would run: ...") in dryrun mode

    • logger=None: Don’t log anything (even errors)

  • dryrun allows to override current runez.DRYRUN setting just for that call

All IO-related functions returning content (read_json(), readlines(), …) use a simpler convention based on: default=UNSET, which decides whether operation should raise an exception on failure or not:

  • When default is NOT provided, the function call will abort on failure with an exception, logging a meaningful error via LOG.error()

  • When default is provided (even if None), the function call will NOT abort, but return the specified default instead, it is up to the caller to log anything in that case (no log chatter comes from runez in that case, at all)

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

runez-5.6.1.tar.gz (158.3 kB view details)

Uploaded Source

Built Distribution

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

runez-5.6.1-py3-none-any.whl (118.9 kB view details)

Uploaded Python 3

File details

Details for the file runez-5.6.1.tar.gz.

File metadata

  • Download URL: runez-5.6.1.tar.gz
  • Upload date:
  • Size: 158.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for runez-5.6.1.tar.gz
Algorithm Hash digest
SHA256 dd48ec6a6464ddd449ca4d0845cf8c109c6bdeefca8d973e4346f0ff6d92e250
MD5 df5f4634ff8cd1c90ce7887fc79c1f3f
BLAKE2b-256 75e55a384bfc689c889f5011579b0d278ef5d8c07f1c0248f296d6e79cca547a

See more details on using hashes here.

Provenance

The following attestation bundles were made for runez-5.6.1.tar.gz:

Publisher: release.yml on codrsquad/runez

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file runez-5.6.1-py3-none-any.whl.

File metadata

  • Download URL: runez-5.6.1-py3-none-any.whl
  • Upload date:
  • Size: 118.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for runez-5.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 733dca446a931c5ebcd527b4cccb2914e027bb6a70c6b84413dc3e03e9dbe6d1
MD5 f113326567e053ee79938a42dda216f3
BLAKE2b-256 eab1e19ba4af203daedb1b1d91e17fca67f61d67e6ee1d6e83dc7c0fb857ff41

See more details on using hashes here.

Provenance

The following attestation bundles were made for runez-5.6.1-py3-none-any.whl:

Publisher: release.yml on codrsquad/runez

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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