Name | runez JSON |
Version |
5.3.0
JSON |
| download |
home_page | https://github.com/codrsquad/runez |
Summary | Friendly misc/utils/convenience library |
upload_time | 2025-01-17 18:40:50 |
maintainer | None |
docs_url | None |
author | Zoran Simic |
requires_python | >=3.6 |
license | MIT |
keywords |
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
Friendly misc/utils/convenience library
=======================================
.. image:: https://img.shields.io/pypi/v/runez.svg
:target: https://pypi.org/project/runez/
:alt: Version on pypi
.. image:: https://github.com/codrsquad/runez/workflows/Tests/badge.svg
:target: https://github.com/codrsquad/runez/actions
:alt: Tested with Github Actions
.. image:: https://codecov.io/gh/codrsquad/runez/branch/main/graph/badge.svg
:target: https://codecov.io/gh/codrsquad/runez
:alt: Test code codecov
.. image:: https://img.shields.io/pypi/pyversions/runez.svg
:target: https://github.com/codrsquad/runez
:alt: 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)
.. _pypi: https://pypi.org/
Raw data
{
"_id": null,
"home_page": "https://github.com/codrsquad/runez",
"name": "runez",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": null,
"keywords": null,
"author": "Zoran Simic",
"author_email": "zoran@simicweb.com",
"download_url": "https://files.pythonhosted.org/packages/18/61/22d3007e5215c6e0aec5be0cac55082354c8613714d68af5361ab72152e3/runez-5.3.0.tar.gz",
"platform": null,
"description": "Friendly misc/utils/convenience library\n=======================================\n\n.. image:: https://img.shields.io/pypi/v/runez.svg\n :target: https://pypi.org/project/runez/\n :alt: Version on pypi\n\n.. image:: https://github.com/codrsquad/runez/workflows/Tests/badge.svg\n :target: https://github.com/codrsquad/runez/actions\n :alt: Tested with Github Actions\n\n.. image:: https://codecov.io/gh/codrsquad/runez/branch/main/graph/badge.svg\n :target: https://codecov.io/gh/codrsquad/runez\n :alt: Test code codecov\n\n.. image:: https://img.shields.io/pypi/pyversions/runez.svg\n :target: https://github.com/codrsquad/runez\n :alt: Python versions tested (link to github project)\n\n\nOverview\n========\n\n**runez** is a convenience ``\"utils\"`` library for common operations I found myself rewriting multiple times.\n\nThe name was initially meant as \"run ez\" (\"run easy\"),\nthe fact that it sounds like \"runes\" gives it a bit of a mystery/magic side that's also relatively appropriate\n(it does indeed concentrate a bit of invocation magic, as you can save quite a few lines of repetitive code by using it)\n\n\nFeatures\n========\n\n- Usable with any python version\n\n- Pure python standalone library, does not bring in any additional dependency\n\n- Takes care of most edge cases, with nice errors\n\n - Functions can be called without checking for return code etc (abort by default, with nice error)\n\n - They can also be called with ``fatal=False``, in which case the return value will indicate whether call succeeded or not\n\n- Support for ``dryrun`` mode (show what would be done, but don't do it)\n\n- Perform most typical logging setups in one call to ``runez.log.setup()``\n\n- Log operations systematically (at debug level mostly), examples::\n\n Running: foo ...\n Copy foo -> bar\n Would move foo -> bar (for dryrun)\n\n- ``CaptureOutput`` context manager -> grab output/logging from any code section\n\n- 100% test coverage\n\n\nExample\n=======\n\nRun a program::\n\n import runez\n\n # Aborts if \"foo\" doesn't exist\n output = runez.run(\"ls\", \"foo\")\n\n # Output can also be ignored\n runez.run(\"ls\", \"foo\")\n\n # Don't capture output, just run the command and let output \"pass through\"\n runez.run(\"ls\", \"foo\", stdout=None, stderr=None)\n\n # Don't abort, return False on failure (or actual output when successful)\n output = runez.run(\"ls\", \"foo\", fatal=False)\n\n\nFile operations::\n\n import runez\n\n runez.touch(\"foo\")\n runez.copy(\"foo\", \"bar\")\n runez.move(\"foo\", \"baz\")\n runez.delete(\"foo\")\n\n runez.write(\"foo\", \"bar\\nbaz\\n\")\n content = \"\\n\".join(runez.readlines(\"foo\", first=10))\n\n full_path = runez.resolved_path(\"foo/bar\")\n folder = runez.parent_folder(full_path)\n runez.ensure_folder(folder)\n with runez.Anchored(folder):\n assert runez.short(full_path) == \"bar\"\n\n\nInstallation\n============\n\nAs usual, available on pypi_: ``pip install runez``\n\n\nPhilosophy\n==========\n\n``runez`` tries to provide a consistent interface across functions.\nHere are the main tenets for functions involving I/O (such as writing, reading, copy-ing files etc):\n\nAll IO-related functions **NOT returning content** (``run()``, ``delete()``, ...)\nhave this common signature: ``fatal=True, logger=UNSET, dryrun=UNSET``\n\n- ``fatal``: decides whether operation should raise an exception on failure or not\n\n - ``fatal=True`` (default): raise an exception on failure, log a meaningful error\n\n - ``fatal=False``: don't raise on failure, log a meaningful error\n\n - ``fatal=None``: don't raise on failure, don't log anything\n\n - In non-fatal mode, calls try to return a usable value appropriate for the call (see docstring of each function)\n\n- ``logger``: decides how chatty the operation should be\n\n - ``LOG.error()`` is used for failures, except when ``fatal`` is not True AND provided ``logger`` is a callable\n\n - ``logger=UNSET`` (default):\n\n - ``LOG.debug(\"Running: ...\")`` to trace activity\n\n - ``print(\"Would run: ...\")`` in dryrun mode\n\n - ``logger=False``: Log errors only (used internally, to avoid unnecessary log chatter when one operation calls another)\n\n - ``logger=mylogger``: call provided ``mylogger()`` to trace activity (example: ``logger=MY_LOGGER.info``)\n\n - ``mylogger(\"Running: ...\")`` to trace activity\n\n - ``mylogger(\"Would run: ...\")`` in dryrun mode\n\n - ``logger=None``: Don't log anything (even errors)\n\n- ``dryrun`` allows to override current ``runez.DRYRUN`` setting just for that call\n\n\n\nAll IO-related functions **returning content** (``read_json()``, ``readlines()``, ...)\nuse a simpler convention based on: ``default=UNSET``,\nwhich decides whether operation should raise an exception on failure or not:\n\n- When ``default`` is **NOT provided**, the function call will abort on failure with an exception,\n logging a meaningful error via ``LOG.error()``\n\n- When ``default`` **is provided** (even if ``None``), the function call will NOT abort,\n but return the specified ``default`` instead, it is up to the caller to log anything\n in that case (no log chatter comes from ``runez`` in that case, at all)\n\n\n.. _pypi: https://pypi.org/\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Friendly misc/utils/convenience library",
"version": "5.3.0",
"project_urls": {
"Documentation": "https://github.com/codrsquad/runez/wiki",
"Homepage": "https://github.com/codrsquad/runez",
"Release notes": "https://github.com/codrsquad/runez/wiki/Release-notes",
"Source": "https://github.com/codrsquad/runez"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "402efa9da4d52522be15341cfb8d051d28053c30950a9bb08fd7c61e2b97abce",
"md5": "4f8eb735890c3bc281e9898caaee6384",
"sha256": "c04b8389ec50aea4c40b47353df8b02d2fac0ad9747647ab55a1077b6998508a"
},
"downloads": -1,
"filename": "runez-5.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4f8eb735890c3bc281e9898caaee6384",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 120847,
"upload_time": "2025-01-17T18:40:45",
"upload_time_iso_8601": "2025-01-17T18:40:45.951428Z",
"url": "https://files.pythonhosted.org/packages/40/2e/fa9da4d52522be15341cfb8d051d28053c30950a9bb08fd7c61e2b97abce/runez-5.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "186122d3007e5215c6e0aec5be0cac55082354c8613714d68af5361ab72152e3",
"md5": "37b3c94da0bddb736a78f562c4322818",
"sha256": "ae53402a9fd6c5ce3b86882e208055c39fe20a924a9daa11402587525eeaf7cd"
},
"downloads": -1,
"filename": "runez-5.3.0.tar.gz",
"has_sig": false,
"md5_digest": "37b3c94da0bddb736a78f562c4322818",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 161433,
"upload_time": "2025-01-17T18:40:50",
"upload_time_iso_8601": "2025-01-17T18:40:50.554671Z",
"url": "https://files.pythonhosted.org/packages/18/61/22d3007e5215c6e0aec5be0cac55082354c8613714d68af5361ab72152e3/runez-5.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-17 18:40:50",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "codrsquad",
"github_project": "runez",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "runez"
}