runs

🏃 Run a block of text as a subprocess 🏃

https://github.com/rec/runs

Science Score: 13.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
  • DOI references
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (9.2%) to scientific vocabulary
Last synced: 11 months ago · JSON representation

Repository

🏃 Run a block of text as a subprocess 🏃

Basic Info
  • Host: GitHub
  • Owner: rec
  • License: mit
  • Language: Python
  • Default Branch: main
  • Homepage:
  • Size: 61.5 KB
Statistics
  • Stars: 3
  • Watchers: 3
  • Forks: 2
  • Open Issues: 0
  • Releases: 7
Created over 5 years ago · Last pushed over 2 years ago
Metadata Files
Readme Changelog Funding License

README.rst

🏃 runs: a better subprocess 🏃
---------------------------------------------------------------------

``runs`` has improved versions of ``call()``, ``check_call()``, ``check_output()``,
and ``run()`` from Python's ``subprocess`` module that handle multiple commands and
blocks of text, fix some defects, and add some features.

.. code-block:: python

    import runs

    runs('''
        ls
        df -k  # or perhaps -h?
        echo 'Done and done'
    ''')

---

``subprocess`` is essential but:

* You can only run one command at a time

* Commands to subprocess must be either a sequence of strings or a string,
  depending on whether ``shell=True`` or not

* Results are returned by default as bytes and not strings

---

The ``runs`` functions let you run a block of text as a sequence of subprocess
calls.

``runs`` provides call-compatible replacements for the functions
``subprocess.call()``, ``subprocess.check_call()``, ``subprocess.check_output()``,
and ``subprocess.run()``

Each replacement function takes a block of text, which is split into individual
command lines, or a list of commands, and returns a list of values, one for
each command.  A block of text can contain line continuations, and comments,
which are ignored.

The replacement functions also add optional logging, error handling,
and lazy evaluation, and use UTF-8 encoding by default.

The module ``runs`` is callable - ``runs()`` is a synonym for ``runs.run()``.

EXAMPLES:

.. code-block:: python

    # ``runs()`` or ``runs.run()`` writes to stdout and stderr just as if you'd run
    # the commands from the terminal

    import runs

    runs('echo "hello, world!"')  # prints hello, world!

    # runs.check_output() returns a list, one string result for each command

    results = check_output('''
        echo  line   one  # Here's line one.
        echo   'line "  two  "'  # and two!
    ''')
    assert results == ['line one', 'line "  two  "']

    # Line continuations work too, either single or double
    runs('''
        ls -cail

        # One command that takes many lines.
        g++ -DDEBUG  -O0 -g -std=c++17 -pthread -I ./include -lm -lstdc++ \
          -Wall -Wextra -Wno-strict-aliasing -Wpedantic \\
          -MMD -MP -MF -c src/tests.cpp -o build/./src/tests.cpp.o

        echo DONE
     ''')

NOTES:

Exactly like ``subprocess``, ``runs`` differs from the shell in a few ways, so
you can't just paste your shell scripts in:

* Redirection doesn't work.

.. code-block:: python

    result = runs.check_output('echo foo > bar.txt')
    assert result == ['foo > bar.txt\n']

* Pipes don't work.

.. code-block:: python

    result = runs.check_output('echo foo | wc')
    assert result == ['foo | wc \n']

*  Environment variables are not expanded in command lines

.. code-block:: python

    result = runs.check_output('echo $FOO', env={'FOO': 'bah!'})
    assert result == ['$FOO\n']

Environment variables are exported to the subprocess, absolutely,
but no environment variable expension happens on command lines.

API
===

``runs()``
~~~~~~~~~~

.. code-block:: python

  runs(
       commands,
       *args,
       iterate=False,
       encoding='utf8',
       on_exception=None,
       echo=False,
       **kwargs,
  )

(`runs.py, 186-200 `_)

Call ``subprocess.run()`` on each command.
Return a list of ``subprocess.CompletedProcess`` instances.
See the help for ``subprocess.run()`` for more information.

Arguments:
  commands:
    A string, which gets split into lines on line endings, or a list of
    strings.

  args:
    Positional arguments to ``subprocess.run()`` (but prefer keyword
    arguments!)

  on_exception:
    If ``on_exception`` is ``False``, the default, exceptions from
    ``subprocess.run()`` are raised as usual.

    If ``on_exception`` is True, they are ignored.

    If ``on_exception`` is a callable, the line that caused the exception is
    passed to it.

    If ``on_exception`` is a string, the line causing the exception
    is printed, prefixed with that string.

  echo:
    If ``echo`` is ``False``, the default, then commands are silently executed.
    If ``echo`` is ``True``, commands are printed prefixed with ``$``
    If ``echo`` is a string, commands are printed prefixed with that string
    If ``echo`` is callable, then each command is passed to it.

  iterate:
    If ``iterate`` is ``False``, the default, then a list of results is
    returned.

    Otherwise an iterator of results which is returned, allowing for lazy
    evaluation.

  encoding:
    Like the argument to ``subprocess.run()``, except the default  is
    ``'utf8'``

  kwargs:
    Named arguments passed on to ``subprocess.run()``

``runs.call()``
~~~~~~~~~~~~~~~

.. code-block:: python

  runs.call(
       commands,
       *args,
       iterate=False,
       encoding='utf8',
       on_exception=None,
       echo=False,
       **kwargs,
  )

(`runs.py, 186-200 `_)

Call ``subprocess.call()`` on each command.
Return a list of integer returncodes, one for each command executed.
See the help for ``subprocess.call()`` for more information.

Arguments:
  commands:
    A string, which gets split into lines on line endings, or a list of
    strings.

  args:
    Positional arguments to ``subprocess.call()`` (but prefer keyword
    arguments!)

  on_exception:
    If ``on_exception`` is ``False``, the default, exceptions from
    ``subprocess.call()`` are raised as usual.

    If ``on_exception`` is True, they are ignored.

    If ``on_exception`` is a callable, the line that caused the exception is
    passed to it.

    If ``on_exception`` is a string, the line causing the exception
    is printed, prefixed with that string.

  echo:
    If ``echo`` is ``False``, the default, then commands are silently executed.
    If ``echo`` is ``True``, commands are printed prefixed with ``$``
    If ``echo`` is a string, commands are printed prefixed with that string
    If ``echo`` is callable, then each command is passed to it.

  iterate:
    If ``iterate`` is ``False``, the default, then a list of results is
    returned.

    Otherwise an iterator of results which is returned, allowing for lazy
    evaluation.

  encoding:
    Like the argument to ``subprocess.call()``, except the default  is
    ``'utf8'``

  kwargs:
    Named arguments passed on to ``subprocess.call()``

``runs.check_call()``
~~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

  runs.check_call(
       commands,
       *args,
       iterate=False,
       encoding='utf8',
       on_exception=None,
       echo=False,
       **kwargs,
  )

(`runs.py, 186-200 `_)

Call ``subprocess.check_call()`` on each command.
If any command has a non-zero returncode, raise ``subprocess.CallProcessError``.

See the help for ``subprocess.check_call()`` for more information.

Arguments:
  commands:
    A string, which gets split into lines on line endings, or a list of
    strings.

  args:
    Positional arguments to ``subprocess.check_call()`` (but prefer keyword
    arguments!)

  on_exception:
    If ``on_exception`` is ``False``, the default, exceptions from
    ``subprocess.check_call()`` are raised as usual.

    If ``on_exception`` is True, they are ignored.

    If ``on_exception`` is a callable, the line that caused the exception is
    passed to it.

    If ``on_exception`` is a string, the line causing the exception
    is printed, prefixed with that string.

  echo:
    If ``echo`` is ``False``, the default, then commands are silently executed.
    If ``echo`` is ``True``, commands are printed prefixed with ``$``
    If ``echo`` is a string, commands are printed prefixed with that string
    If ``echo`` is callable, then each command is passed to it.

  iterate:
    If ``iterate`` is ``False``, the default, then a list of results is
    returned.

    Otherwise an iterator of results which is returned, allowing for lazy
    evaluation.

  encoding:
    Like the argument to ``subprocess.check_call()``, except the default  is
    ``'utf8'``

  kwargs:
    Named arguments passed on to ``subprocess.check_call()``

``runs.check_output()``
~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: python

  runs.check_output(
       commands,
       *args,
       iterate=False,
       encoding='utf8',
       on_exception=None,
       echo=False,
       **kwargs,
  )

(`runs.py, 186-200 `_)

Call ``subprocess.check_output()`` on each command.
If a command has a non-zero exit code, raise a ``subprocess.CallProcessError``.
Otherwise, return the results as a list of strings, one for each command.
See the help for ``subprocess.check_output()`` for more information.

Arguments:
  commands:
    A string, which gets split into lines on line endings, or a list of
    strings.

  args:
    Positional arguments to ``subprocess.check_output()`` (but prefer keyword
    arguments!)

  on_exception:
    If ``on_exception`` is ``False``, the default, exceptions from
    ``subprocess.check_output()`` are raised as usual.

    If ``on_exception`` is True, they are ignored.

    If ``on_exception`` is a callable, the line that caused the exception is
    passed to it.

    If ``on_exception`` is a string, the line causing the exception
    is printed, prefixed with that string.

  echo:
    If ``echo`` is ``False``, the default, then commands are silently executed.
    If ``echo`` is ``True``, commands are printed prefixed with ``$``
    If ``echo`` is a string, commands are printed prefixed with that string
    If ``echo`` is callable, then each command is passed to it.

  iterate:
    If ``iterate`` is ``False``, the default, then a list of results is
    returned.

    Otherwise an iterator of results which is returned, allowing for lazy
    evaluation.

  encoding:
    Like the argument to ``subprocess.check_output()``, except the default  is
    ``'utf8'``

  kwargs:
    Named arguments passed on to ``subprocess.check_output()``

(automatically generated by `doks `_ on 2020-12-16T13:48:26.579866)

Owner

  • Name: Tom Ritchford
  • Login: rec
  • Kind: user
  • Location: Rouen, France

Difficult problems made simpler

GitHub Events

Total
  • Watch event: 1
  • Fork event: 1
Last Year
  • Watch event: 1
  • Fork event: 1

Committers

Last synced: almost 3 years ago

All Time
  • Total Commits: 37
  • Total Committers: 1
  • Avg Commits per committer: 37.0
  • Development Distribution Score (DDS): 0.0
Past Year
  • Commits: 12
  • Committers: 1
  • Avg Commits per committer: 12.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
Tom Ritchford t****m@s****m 37
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 12 months ago

All Time
  • Total issues: 0
  • Total pull requests: 0
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Total issue authors: 0
  • Total pull request authors: 0
  • Average comments per issue: 0
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 0
  • Pull requests: 0
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Issue authors: 0
  • Pull request authors: 0
  • Average comments per issue: 0
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
Pull Request Authors
Top Labels
Issue Labels
Pull Request Labels

Packages

  • Total packages: 1
  • Total downloads:
    • pypi 2,926,553 last-month
  • Total dependent packages: 2
  • Total dependent repositories: 30
  • Total versions: 7
  • Total maintainers: 1
pypi.org: runs

🏃 Run a block of text as a subprocess 🏃

  • Versions: 7
  • Dependent Packages: 2
  • Dependent Repositories: 30
  • Downloads: 2,926,553 Last month
Rankings
Dependent repos count: 2.7%
Dependent packages count: 4.7%
Downloads: 12.4%
Average: 14.0%
Forks count: 22.6%
Stargazers count: 27.8%
Maintainers (1)
Last synced: 12 months ago

Dependencies

poetry.lock pypi
  • attrs 22.2.0 develop
  • colorama 0.4.6 develop
  • coverage 7.1.0 develop
  • exceptiongroup 1.1.0 develop
  • flake8 5.0.4 develop
  • importlib-metadata 4.2.0 develop
  • iniconfig 2.0.0 develop
  • mccabe 0.7.0 develop
  • packaging 23.0 develop
  • pluggy 1.0.0 develop
  • pycodestyle 2.9.1 develop
  • pyflakes 2.5.0 develop
  • pytest 7.2.1 develop
  • tdir 1.4.1 develop
  • tomli 2.0.1 develop
  • typing-extensions 4.4.0 develop
  • zipp 3.12.0 develop
  • dek 1.0.2
  • xmod 1.3.2
pyproject.toml pypi
  • python ^3.7
  • xmod ^1.3.2
.github/workflows/python-package.yml actions
  • actions/cache v2 composite
  • actions/checkout v3 composite
  • actions/setup-python v3 composite
  • snok/install-poetry v1 composite