diff --git a/.travis.yml b/.travis.yml index 359681d2412b49688e85065413b96b4fe6e9d6e0..78897da6f49a305fce11cbf4f9e56992fe369743 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ language: python python: - "2.7" - - "3.4" - "3.5" - "3.6" - "3.7" diff --git a/Pipfile.lock b/Pipfile.lock index 144a03dc509e7eb77e9cff676ae4bf4c169bf60c..be17798ccf2a9387ac264c560cb2ba095674ca5a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "62827577f8781dd89462ca09eb23122a71010f2f121432f74817d72b1fad6bac" + "sha256": "c5874f74427fb4c93b0b946d55db06144a048e54bf913867cd0a76d8167f8412" }, "pipfile-spec": 6, "requires": { @@ -88,10 +88,10 @@ }, "cfgv": { "hashes": [ - "sha256:32edbe09de6f4521224b87822103a8c16a614d31a894735f7a5b3bcf0eb3c37e", - "sha256:3bd31385cd2bebddbba8012200aaf15aa208539f1b33973759b4d02fc2148da5" + "sha256:edb387943b665bf9c434f717bf630fa78aecd53d5900d2e05da6ad6048553144", + "sha256:fbd93c9ab0a523bf7daec408f3be2ed99a980e20b2d19b50fc184ca6b820d289" ], - "version": "==2.0.0" + "version": "==2.0.1" }, "chardet": { "hashes": [ @@ -130,11 +130,10 @@ }, "docutils": { "hashes": [ - "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", - "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", - "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" + "sha256:54a349c622ff31c91cbec43b0b512f113b5b24daf00e2ea530bb1bd9aac14849", + "sha256:d2ddba74835cb090a1b627d3de4e7835c628d07ee461f7b4480f51af2fe4d448" ], - "version": "==0.14" + "version": "==0.15" }, "entrypoints": { "hashes": [ @@ -143,14 +142,6 @@ ], "version": "==0.3" }, - "hashin": { - "hashes": [ - "sha256:dbace6900d8de44f3106a64496803e45843cf4974755613db811a487fadbf4c6", - "sha256:fe764df71cabbbddfa72aa4d6685581c932bb5cf9100ddee6b2b04f3446ae2f7" - ], - "index": "pypi", - "version": "==0.14.5" - }, "identify": { "hashes": [ "sha256:0a11379b46d06529795442742a043dc2fa14cd8c995ae81d1febbc5f1c014c87", @@ -240,20 +231,6 @@ ], "version": "==1.3.3" }, - "packaging": { - "hashes": [ - "sha256:0c98a5d0be38ed775798ece1b9727178c4469d9c3b4ada66e8e6b7849f8732af", - "sha256:9e1cbf8c12b1f1ce0bb5344b8d7ecf66a6f8a6e91bcb0c84593ed6d3ab5c4ab3" - ], - "version": "==19.0" - }, - "pip-api": { - "hashes": [ - "sha256:742b3edb5b077853ffcfec8a849f6ff1a622c6ecf648adb5fa0e4594998fcd46", - "sha256:a685eb315b9f10f6df4ceb66f3710148c8ad7de2d4ff29ee98fed0e4d949ec81" - ], - "version": "==0.0.10" - }, "pkginfo": { "hashes": [ "sha256:7424f2c8511c186cd5424bbf31045b77435b37a8d604990b79d4e70d741148bb", @@ -282,13 +259,6 @@ ], "version": "==2.4.2" }, - "pyparsing": { - "hashes": [ - "sha256:1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a", - "sha256:9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03" - ], - "version": "==2.4.0" - }, "pyyaml": { "hashes": [ "sha256:57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3", @@ -341,6 +311,13 @@ ], "version": "==1.12.0" }, + "subprocess32": { + "hashes": [ + "sha256:88e37c1aac5388df41cc8a8456bb49ebffd321a3ad4d70358e3518176de3a56b", + "sha256:eb2937c80497978d181efa1b839ec2d9622cf9600a039a79d0e108d1f9aec79d" + ], + "version": "==3.5.4" + }, "template": { "editable": true, "path": "." @@ -376,10 +353,10 @@ }, "virtualenv": { "hashes": [ - "sha256:b7335cddd9260a3dd214b73a2521ffc09647bde3e9457fcca31dc3be3999d04a", - "sha256:d28ca64c0f3f125f59cabf13e0a150e1c68e5eea60983cc4395d88c584495783" + "sha256:861bbce3a418110346c70f5c7a696fdcf23a261424e1d28aa4f9362fc2ccbc19", + "sha256:ba8ce6a961d842320681fb90a3d564d0e5134f41dacd0e2bae7f02441dde2d52" ], - "version": "==16.6.1" + "version": "==16.6.2" }, "webencodings": { "hashes": [ @@ -390,10 +367,10 @@ }, "zipp": { "hashes": [ - "sha256:8c1019c6aad13642199fbe458275ad6a84907634cc9f0989877ccc4a2840139d", - "sha256:ca943a7e809cc12257001ccfb99e3563da9af99d52f261725e96dfe0f9275bc3" + "sha256:4970c3758f4e89a7857a973b1e2a5d75bcdc47794442f2e2dd4fe8e0466e809a", + "sha256:8a5712cfd3bb4248015eb3b0b3c54a5f6ee3f2425963ef2a0125b8bc40aafaec" ], - "version": "==0.5.1" + "version": "==0.5.2" } } } diff --git a/README.rst b/README.rst index da231554dec99171b116be780643de80b5df09c4..dfe8dd443de6be4c76f6e3a6f97ba38a79b441c5 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ Template :target: https://travis-ci.org/adarnimrod/template A CLI tool for generating files from `Jinja2 <http://jinja.pocoo.org/>`_ -templates and environment variables. Tested on Python versions 2.7, 3.4 and +templates and environment variables. Tested on Python versions 2.7, 3.5 and later. Examples @@ -48,6 +48,9 @@ The following Jinja filters were added: - :code:`from_toml`: Convert from toml. - :code:`jmespath`: Queries data using the `JMESPath <http://jmespath.org/>`_ query language. +- :code:`run`: Runs a command and returns the stdout, stderr and returncode + using `run + <https://docs.python.org/3.5/library/subprocess.html?highlight=popen#subprocess.run>`_. Example usage can be seen in :code:`tests` and for specific filters in the docstrings in :code:`template/filters.py`. diff --git a/setup.py b/setup.py index 5d3d4dcc56ffd7dbf05c122d9d6384d32e25a35b..903465d3da3a4af304586d03ed359bfad075b670 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,6 @@ setup( "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", @@ -29,7 +28,13 @@ setup( ], keywords="config configuration jinja template environment", packages=find_packages(), - install_requires=["Jinja2", "PyYAML", "jmespath", "toml"], + install_requires=[ + "Jinja2", + "PyYAML", + "jmespath", + "toml", + "subprocess32>=3.5.0", + ], extras_require={"dev": ["pipenv"]}, entry_points={"console_scripts": ["template=template:main"]}, ) diff --git a/template/__init__.py b/template/__init__.py old mode 100755 new mode 100644 diff --git a/template/filters.py b/template/filters.py index f17598f4ed12bf51b8a78db4f4f6f86372142564..6d1a9f5220e6995fefdc82b22101376586b3bbc0 100644 --- a/template/filters.py +++ b/template/filters.py @@ -143,3 +143,26 @@ def jmespath(value, query): import jmespath as jp return jp.search(query, value) + + +def run(*argv, **kwargs): + """ + Runs a command and returns the stdout, stderr and returncode + using `run + <https://docs.python.org/3.5/library/subprocess.html?highlight=popen#subprocess.run>`_. + >>> run('ls')["returncode"] == 0 + True + >>> 'SHELL' not in run('echo $SHELL', shell=True)['stdout'] + True + >>> run(['ls', 'foo'])['returncode'] > 0 + True + """ + import subprocess32 # nosec + + defaults = {"stdout": subprocess32.PIPE, "stderr": subprocess32.PIPE} + defaults.update(kwargs) + proc = subprocess32.run(*argv, **defaults).__dict__ + if "text" not in kwargs or kwargs["text"]: + proc["stdout"] = proc["stdout"].decode() + proc["stderr"] = proc["stderr"].decode() + return proc