citizenshell


Namecitizenshell JSON
Version 2.1.1 PyPI version JSON
download
home_pagehttps://github.com/meuter/citizenshell
SummaryInteract with shell locally or over different connection types (telnet, ssh, serial, adb)
upload_time2018-04-08 08:18:33
maintainer
docs_urlNone
authorCedric Meuter
requires_python
licenseMIT
keywords shell telnet adb ssh serial
VCS
bugtrack_url
requirements paramiko termcolor pytest-catchlog pypandoc uritools pyserial backports.tempfile scp
Travis-CI
coveralls test coverage No coveralls.
            citizenshell |Build Status|
===========================

**citizenshell** is a python library allowing to execute shell commands
either locally or remotely over several protocols (telnet, ssh, serial
or adb) using a simple and consistent API. This library is compatible
with both python 2 (2.7) and 3 (>=3.4) as well as with
`PyPy <https://pypy.org/>`__. For now, it focuses on POSIX platforms
like Linux and MacOS, but may be extended to work to Windows based
platform in the future. It is distributed under
`MIT <https://opensource.org/licenses/MIT>`__ license.

Installation
------------

**citizenshell** can simply installed using ``pip install citizenshell``

Obtaining a shell
-----------------

First you need a shell. For that you have several options:

1. use the built-in ``LocalShell`` for quick access:

   .. code:: python

       from citizenshell import sh

2. you can instanciate your own ``LocalShell``:

   .. code:: python

       from citizenshell import LocalShell

       shell = LocalShell()

3. you can instanciate the ``TelnetShell`` for shell over telnet:

   .. code:: python

       from citizenshell import TelnetShell

       shell = TelnetShell(hostname="acme.org", username="john",
                           password="secretpassword")

4. you can instanciate the ``SecureShell`` for shell over SSH:

   .. code:: python

       from citizenshell import SecureShell

       shell = SecureShell(hostname="acme.org", username="john",
                           password="secretpassword")

5. you can instanciate the ``AdbShell`` for shell over ADB:

   .. code:: python

       from citizenshell import AdbShell

       shell = AdbShell(hostname="acme.org", username="john",
                        password="secretpassword")

6. you can instanciate the ``SerialShell`` for shell over serial line:

   .. code:: python

       from serial import EIGHTBITS, PARITY_NONE
       from citizenshell import SerialShell

       shell = SerialShell(port="/dev/ttyUSB3", username="john",
                           password="secretpassword",
                           baudrate=115200, parity=PARITY_NONE, bytesize=EIGHTBITS)

7. you can also obtain shell objects by URI using the ``Shell``
   function:

   .. code:: python

       from citizenshell import Shell

       localshell = Shell()
       telnetshell = Shell("telnet://john:secretpassword@acme.org:1234")
       secureshell = Shell("ssh://john:secretpassword@acme.org:1234")
       adbshell = Shell("adb://myandroiddevice:5555")
       serialshell = Shell("serial://jogn:secretpassword@/dev/ttyUSB3?baudrate=115200")

   you can also mix and match betweens providing arguments in the URI or
   via kwargs:

   .. code:: python

       telnetshell = Shell("telnet://john@acme.org", password="secretpassword", port=1234)
       serialshell = Shell("serial://john:secretpassword@/dev/ttyUSB3", baudrate=115200)

Using a shell
-------------

Once you have shell, any shell, you can call it directly and get the
standart output:

.. code:: python

    assert shell("echo Hello World") == "Hello World"

or you can also iterate over the standard output:

.. code:: python

    result = [int(x) for x in shell("""
        for i in 1 2 3 4; do
            echo $i;
        done
    """)]
    assert result == [1, 2, 3, 4]

you don't have to wait for the command to finish to recieve the lines:

.. code:: python

    for line in shell("for i in 1 2 3 4; do echo -n 'It is '; date +%H:%M:%S; sleep 1; done", wait=False)
        print ">>>", line + "!"

would produce something like:

.. code:: text

    >>> It is 14:24:52!
    >>> It is 14:24:53!
    >>> It is 14:24:54!
    >>> It is 14:24:55!

you can extract stdout, stderr and exit code seperately:

.. code:: python

    result = shell(">&2 echo error && echo output && exit 13")
    assert result.stdout() == ["output"]
    assert result.stderr() == ["error"]
    assert result.exit_code() == 13

you can inject environment variable to the shell

.. code:: python

    assert shell("echo $VAR", VAR="bar") == "bar"

or have the shell raise an exception if the exit code is non-zero:

.. code:: python

    assert shell("exit 13").exit_code() == 13 # will not raise any exception
    try:
        shell("exit 13", check_xc=True) # will raise an exception
        assert False, "will not be reached"
    except ShellError as e:
        assert True, "will be reached"

the shell can also raise an exception if something is printed on the
standard error:

.. code:: python

    shell("echo DANGER >&2").stderr() == ["DANGER"] # will not raise any exception
    try:
        shell("echo DANGER >&2", check_err=True) # will raise an exception
        assert False, "will not be reached"
    except ShellError as e:
        assert True, "will be reached"

you can pull file from the remote host (for ``LocalShell`` it's just
doing a copy):

.. code:: python

    shell("echo -n test > remote_file.txt")
    shell.pull("local_file.txt", "remote_file.txt")
    assert open("local_file.txt", "r").read() == "test"

or push file to the remote host (again, for ``LocalShell`` it's just
doing a copy):

.. code:: python

    open("local_file.txt", "w").write("test")
    shell.push("local_file.txt", "remote_file.txt")
    assert str(shell("cat remote_file.txt")) == "test"

.. |Build Status| image:: https://travis-ci.org/meuter/citizenshell.svg?branch=master
   :target: https://travis-ci.org/meuter/citizenshell



            

Raw data

            {
    "maintainer": "", 
    "docs_url": null, 
    "requires_python": "", 
    "maintainer_email": "", 
    "cheesecake_code_kwalitee_id": null, 
    "keywords": "shell,telnet,adb,ssh,serial", 
    "upload_time": "2018-04-08 08:18:33", 
    "requirements": [
        {
            "name": "paramiko", 
            "specs": []
        }, 
        {
            "name": "termcolor", 
            "specs": []
        }, 
        {
            "name": "pytest-catchlog", 
            "specs": []
        }, 
        {
            "name": "pypandoc", 
            "specs": []
        }, 
        {
            "name": "uritools", 
            "specs": []
        }, 
        {
            "name": "pyserial", 
            "specs": []
        }, 
        {
            "name": "backports.tempfile", 
            "specs": []
        }, 
        {
            "name": "scp", 
            "specs": []
        }
    ], 
    "author": "Cedric Meuter", 
    "home_page": "https://github.com/meuter/citizenshell", 
    "github_user": "meuter", 
    "download_url": "https://pypi.python.org/packages/e7/49/3636034ae4cb9d7a70065ff312caf010f50d6a27355ff3576ade5ec26fb0/citizenshell-2.1.1.tar.gz", 
    "platform": "", 
    "version": "2.1.1", 
    "cheesecake_documentation_id": null, 
    "description": "citizenshell |Build Status|\n===========================\n\n**citizenshell** is a python library allowing to execute shell commands\neither locally or remotely over several protocols (telnet, ssh, serial\nor adb) using a simple and consistent API. This library is compatible\nwith both python 2 (2.7) and 3 (>=3.4) as well as with\n`PyPy <https://pypy.org/>`__. For now, it focuses on POSIX platforms\nlike Linux and MacOS, but may be extended to work to Windows based\nplatform in the future. It is distributed under\n`MIT <https://opensource.org/licenses/MIT>`__ license.\n\nInstallation\n------------\n\n**citizenshell** can simply installed using ``pip install citizenshell``\n\nObtaining a shell\n-----------------\n\nFirst you need a shell. For that you have several options:\n\n1. use the built-in ``LocalShell`` for quick access:\n\n   .. code:: python\n\n       from citizenshell import sh\n\n2. you can instanciate your own ``LocalShell``:\n\n   .. code:: python\n\n       from citizenshell import LocalShell\n\n       shell = LocalShell()\n\n3. you can instanciate the ``TelnetShell`` for shell over telnet:\n\n   .. code:: python\n\n       from citizenshell import TelnetShell\n\n       shell = TelnetShell(hostname=\"acme.org\", username=\"john\",\n                           password=\"secretpassword\")\n\n4. you can instanciate the ``SecureShell`` for shell over SSH:\n\n   .. code:: python\n\n       from citizenshell import SecureShell\n\n       shell = SecureShell(hostname=\"acme.org\", username=\"john\",\n                           password=\"secretpassword\")\n\n5. you can instanciate the ``AdbShell`` for shell over ADB:\n\n   .. code:: python\n\n       from citizenshell import AdbShell\n\n       shell = AdbShell(hostname=\"acme.org\", username=\"john\",\n                        password=\"secretpassword\")\n\n6. you can instanciate the ``SerialShell`` for shell over serial line:\n\n   .. code:: python\n\n       from serial import EIGHTBITS, PARITY_NONE\n       from citizenshell import SerialShell\n\n       shell = SerialShell(port=\"/dev/ttyUSB3\", username=\"john\",\n                           password=\"secretpassword\",\n                           baudrate=115200, parity=PARITY_NONE, bytesize=EIGHTBITS)\n\n7. you can also obtain shell objects by URI using the ``Shell``\n   function:\n\n   .. code:: python\n\n       from citizenshell import Shell\n\n       localshell = Shell()\n       telnetshell = Shell(\"telnet://john:secretpassword@acme.org:1234\")\n       secureshell = Shell(\"ssh://john:secretpassword@acme.org:1234\")\n       adbshell = Shell(\"adb://myandroiddevice:5555\")\n       serialshell = Shell(\"serial://jogn:secretpassword@/dev/ttyUSB3?baudrate=115200\")\n\n   you can also mix and match betweens providing arguments in the URI or\n   via kwargs:\n\n   .. code:: python\n\n       telnetshell = Shell(\"telnet://john@acme.org\", password=\"secretpassword\", port=1234)\n       serialshell = Shell(\"serial://john:secretpassword@/dev/ttyUSB3\", baudrate=115200)\n\nUsing a shell\n-------------\n\nOnce you have shell, any shell, you can call it directly and get the\nstandart output:\n\n.. code:: python\n\n    assert shell(\"echo Hello World\") == \"Hello World\"\n\nor you can also iterate over the standard output:\n\n.. code:: python\n\n    result = [int(x) for x in shell(\"\"\"\n        for i in 1 2 3 4; do\n            echo $i;\n        done\n    \"\"\")]\n    assert result == [1, 2, 3, 4]\n\nyou don't have to wait for the command to finish to recieve the lines:\n\n.. code:: python\n\n    for line in shell(\"for i in 1 2 3 4; do echo -n 'It is '; date +%H:%M:%S; sleep 1; done\", wait=False)\n        print \">>>\", line + \"!\"\n\nwould produce something like:\n\n.. code:: text\n\n    >>> It is 14:24:52!\n    >>> It is 14:24:53!\n    >>> It is 14:24:54!\n    >>> It is 14:24:55!\n\nyou can extract stdout, stderr and exit code seperately:\n\n.. code:: python\n\n    result = shell(\">&2 echo error && echo output && exit 13\")\n    assert result.stdout() == [\"output\"]\n    assert result.stderr() == [\"error\"]\n    assert result.exit_code() == 13\n\nyou can inject environment variable to the shell\n\n.. code:: python\n\n    assert shell(\"echo $VAR\", VAR=\"bar\") == \"bar\"\n\nor have the shell raise an exception if the exit code is non-zero:\n\n.. code:: python\n\n    assert shell(\"exit 13\").exit_code() == 13 # will not raise any exception\n    try:\n        shell(\"exit 13\", check_xc=True) # will raise an exception\n        assert False, \"will not be reached\"\n    except ShellError as e:\n        assert True, \"will be reached\"\n\nthe shell can also raise an exception if something is printed on the\nstandard error:\n\n.. code:: python\n\n    shell(\"echo DANGER >&2\").stderr() == [\"DANGER\"] # will not raise any exception\n    try:\n        shell(\"echo DANGER >&2\", check_err=True) # will raise an exception\n        assert False, \"will not be reached\"\n    except ShellError as e:\n        assert True, \"will be reached\"\n\nyou can pull file from the remote host (for ``LocalShell`` it's just\ndoing a copy):\n\n.. code:: python\n\n    shell(\"echo -n test > remote_file.txt\")\n    shell.pull(\"local_file.txt\", \"remote_file.txt\")\n    assert open(\"local_file.txt\", \"r\").read() == \"test\"\n\nor push file to the remote host (again, for ``LocalShell`` it's just\ndoing a copy):\n\n.. code:: python\n\n    open(\"local_file.txt\", \"w\").write(\"test\")\n    shell.push(\"local_file.txt\", \"remote_file.txt\")\n    assert str(shell(\"cat remote_file.txt\")) == \"test\"\n\n.. |Build Status| image:: https://travis-ci.org/meuter/citizenshell.svg?branch=master\n   :target: https://travis-ci.org/meuter/citizenshell\n\n\n", 
    "lcname": "citizenshell", 
    "bugtrack_url": null, 
    "github": true, 
    "coveralls": false, 
    "name": "citizenshell", 
    "license": "MIT", 
    "travis_ci": true, 
    "github_project": "citizenshell", 
    "summary": "Interact with shell locally or over different connection types (telnet, ssh, serial, adb)", 
    "split_keywords": [
        "shell", 
        "telnet", 
        "adb", 
        "ssh", 
        "serial"
    ], 
    "author_email": "cedric.meuter@gmail.com", 
    "urls": [
        {
            "has_sig": false, 
            "upload_time": "2018-04-08T08:18:32", 
            "comment_text": "", 
            "python_version": "py2.py3", 
            "url": "https://pypi.python.org/packages/6d/b3/def0d1d95da074311b716fb47a77a44fd23e361dbe078e421a48180b88d7/citizenshell-2.1.1-py2.py3-none-any.whl", 
            "md5_digest": "56f457f93b9d7a1cde29606619fab73f", 
            "downloads": 0, 
            "filename": "citizenshell-2.1.1-py2.py3-none-any.whl", 
            "packagetype": "bdist_wheel", 
            "path": "6d/b3/def0d1d95da074311b716fb47a77a44fd23e361dbe078e421a48180b88d7/citizenshell-2.1.1-py2.py3-none-any.whl", 
            "digests": {
                "sha256": "bb29068e22cd20069cfdaf9890e4533967532e00733f8f21a9c16626600bd267", 
                "md5": "56f457f93b9d7a1cde29606619fab73f"
            }, 
            "sha256_digest": "bb29068e22cd20069cfdaf9890e4533967532e00733f8f21a9c16626600bd267", 
            "size": 20588
        }, 
        {
            "has_sig": false, 
            "upload_time": "2018-04-08T08:18:33", 
            "comment_text": "", 
            "python_version": "source", 
            "url": "https://pypi.python.org/packages/e7/49/3636034ae4cb9d7a70065ff312caf010f50d6a27355ff3576ade5ec26fb0/citizenshell-2.1.1.tar.gz", 
            "md5_digest": "3d7013ba686e9befb30aa720026e6d3b", 
            "downloads": 0, 
            "filename": "citizenshell-2.1.1.tar.gz", 
            "packagetype": "sdist", 
            "path": "e7/49/3636034ae4cb9d7a70065ff312caf010f50d6a27355ff3576ade5ec26fb0/citizenshell-2.1.1.tar.gz", 
            "digests": {
                "sha256": "19bc89226ee2840a1bf80dbc8d487991f9c679243a2029c53cb98ee2f483b5f6", 
                "md5": "3d7013ba686e9befb30aa720026e6d3b"
            }, 
            "sha256_digest": "19bc89226ee2840a1bf80dbc8d487991f9c679243a2029c53cb98ee2f483b5f6", 
            "size": 13573
        }
    ], 
    "_id": null, 
    "cheesecake_installability_id": null
}