envdir
Advanced tools
+13
-1
| Changelog | ||
| --------- | ||
| 1.0.0 (26/03/2018) | ||
| ^^^^^^^^^^^^^^^^^^ | ||
| * Drop python 2.6, 3.2 and 3.3 | ||
| * Add explicit support for python 3.6 | ||
| * Add support for symlinks | ||
| * Improved support for windows | ||
| 0.7 (08/10/2014) | ||
@@ -26,3 +38,3 @@ ^^^^^^^^^^^^^^^^ | ||
| * Added Sphinx based docs: http://envdir.readthedocs.org/ | ||
| * Added Sphinx based docs: https://envdir.readthedocs.io/ | ||
@@ -29,0 +41,0 @@ * Fixed killing child process when capturing keyboard interrupt. |
+2
-2
@@ -55,5 +55,5 @@ # -*- coding: utf-8 -*- | ||
| # The short X.Y version. | ||
| version = '0.6' | ||
| version = '0.7' | ||
| # The full version, including alpha/beta/rc tags. | ||
| release = '0.6.1' | ||
| release = '0.7' | ||
@@ -60,0 +60,0 @@ # The language for content autogenerated by Sphinx. Refer to documentation |
+13
-0
@@ -57,1 +57,14 @@ Usage | ||
| .. _envdir: http://cr.yp.to/daemontools/envdir.html | ||
| Setup an empty environment variable | ||
| ----------------------------------- | ||
| Use an empty line to setup an empty environment variable (in contrast to an | ||
| empty file, which would unset the environment variable): | ||
| .. code-block:: console | ||
| $ echo > envdir/EMPTY_ENV | ||
| $ envdir envdir env | grep EMPTY_ENV | ||
| EMPTY_ENV= |
| [console_scripts] | ||
| envdir = envdir:run | ||
| envshell = envdir:shell | ||
| envdir = envdir:run | ||
+24
-10
| Metadata-Version: 1.1 | ||
| Name: envdir | ||
| Version: 0.7 | ||
| Version: 1.0.1 | ||
| Summary: A Python port of daemontools' envdir. | ||
| Home-page: http://envdir.readthedocs.org/ | ||
| Home-page: https://envdir.readthedocs.io/ | ||
| Author: Jannis Leidel | ||
@@ -12,6 +12,10 @@ Author-email: jannis@leidel.info | ||
| .. image:: https://api.travis-ci.org/jezdez/envdir.png | ||
| :alt: Build Status | ||
| .. image:: https://api.travis-ci.org/jezdez/envdir.svg | ||
| :alt: Linux Build Status | ||
| :target: https://travis-ci.org/jezdez/envdir | ||
| .. image:: https://ci.appveyor.com/api/projects/status/0fh77wei6cj5hei5?svg=true | ||
| :alt: Windows Build Status | ||
| :target: https://ci.appveyor.com/project/jezdez/envdir | ||
| This is a Python port of daemontools_' tool envdir_. It works on Windows and | ||
@@ -77,3 +81,2 @@ other systems which can run Python. It's well tested and doesn't need a | ||
| Feel free to open tickets at https://github.com/jezdez/envdir/issues. | ||
| Say thanks at https://www.gittip.com/jezdez/. | ||
@@ -88,2 +91,14 @@ .. _12factor: http://12factor.net/config | ||
| 1.0.0 (26/03/2018) | ||
| ^^^^^^^^^^^^^^^^^^ | ||
| * Drop python 2.6, 3.2 and 3.3 | ||
| * Add explicit support for python 3.6 | ||
| * Add support for symlinks | ||
| * Improved support for windows | ||
| 0.7 (08/10/2014) | ||
@@ -111,3 +126,3 @@ ^^^^^^^^^^^^^^^^ | ||
| * Added Sphinx based docs: http://envdir.readthedocs.org/ | ||
| * Added Sphinx based docs: https://envdir.readthedocs.io/ | ||
@@ -178,7 +193,6 @@ * Fixed killing child process when capturing keyboard interrupt. | ||
| Classifier: Programming Language :: Python :: 2 | ||
| Classifier: Programming Language :: Python :: 2.6 | ||
| Classifier: Programming Language :: Python :: 2.7 | ||
| Classifier: Programming Language :: Python :: 3 | ||
| Classifier: Programming Language :: Python :: 3.1 | ||
| Classifier: Programming Language :: Python :: 3.2 | ||
| Classifier: Programming Language :: Python :: 3.3 | ||
| Classifier: Programming Language :: Python :: 3.4 | ||
| Classifier: Programming Language :: Python :: 3.5 | ||
| Classifier: Programming Language :: Python :: 3.6 |
+33
-13
@@ -1,2 +0,1 @@ | ||
| import glob | ||
| import os | ||
@@ -15,2 +14,14 @@ | ||
| class _EmptyFile(Exception): | ||
| pass | ||
| try: | ||
| FileNotFoundError | ||
| except NameError: # <python3 | ||
| FileNotFoundError = OSError | ||
| _sentinel = object() | ||
| class Env(UserDict): | ||
@@ -37,4 +48,9 @@ """ | ||
| def __getitem__(self, name): | ||
| return self._get(name) | ||
| def __getitem__(self, name, default=_sentinel): | ||
| try: | ||
| return self._get(name, default=default) | ||
| except (_EmptyFile, FileNotFoundError): | ||
| if default is _sentinel: | ||
| raise KeyError(name) | ||
| return default | ||
@@ -55,6 +71,11 @@ def __setitem__(self, name, value): | ||
| def _load(self): | ||
| for path in filter(isenvvar, glob.glob(os.path.join(self.path, '*'))): | ||
| root, name = os.path.split(path) | ||
| value = self._get(name) | ||
| self._set(name, value) | ||
| for _, _, files in os.walk(self.path, followlinks=True): | ||
| for path in filter(isenvvar, files): | ||
| root, name = os.path.split(path) | ||
| try: | ||
| value = self._get(name) | ||
| except _EmptyFile: | ||
| self._delete(name) | ||
| else: | ||
| self._set(name, value) | ||
@@ -64,8 +85,10 @@ def _open(self, name, mode='r'): | ||
| def _get(self, name, default=None): | ||
| def _get(self, name, default=_sentinel): | ||
| path = os.path.join(self.path, name) | ||
| if os.stat(path).st_size == 0: | ||
| raise _EmptyFile | ||
| if not os.path.exists(path): | ||
| return default | ||
| with self._open(name) as var: | ||
| return var.read().strip().replace('\x00', '\n') | ||
| return var.read().strip('\n').replace('\x00', '\n') | ||
@@ -76,6 +99,3 @@ def _set(self, name, value): | ||
| self.data[name] = value | ||
| if value: | ||
| os.environ[name] = value | ||
| elif name in os.environ: | ||
| del os.environ[name] | ||
| os.environ[name] = value | ||
@@ -82,0 +102,0 @@ def _delete(self, name): |
+6
-1
@@ -67,3 +67,8 @@ import optparse | ||
| shell = os.environ['SHELL'] | ||
| if 'SHELL' in os.environ: | ||
| shell = os.environ['SHELL'] | ||
| elif 'COMSPEC' in os.environ: | ||
| shell = os.environ['COMSPEC'] | ||
| else: | ||
| raise Response('Unable to detect current environment shell') | ||
@@ -70,0 +75,0 @@ try: |
+76
-13
| import functools | ||
| import os | ||
| import platform | ||
| import signal | ||
| import subprocess | ||
| import sys | ||
| import threading | ||
@@ -13,3 +15,8 @@ | ||
| try: | ||
| FileNotFoundError | ||
| except NameError: # <python3 | ||
| FileNotFoundError = OSError | ||
| @pytest.fixture(scope="module") | ||
@@ -33,2 +40,3 @@ def run(): | ||
| original_execvpe = os.execvpe | ||
@@ -121,2 +129,22 @@ | ||
| def test_space_at_end(run, tmpenvdir, monkeypatch): | ||
| """Space at end of envdir file.""" | ||
| monkeypatch.setattr(os, 'execvpe', functools.partial(mocked_execvpe, | ||
| monkeypatch)) | ||
| tmpenvdir.join('WITH_SPACE').write("with space ") | ||
| with py.test.raises(Response): | ||
| run('envdir', str(tmpenvdir), 'ls') | ||
| assert os.environ['WITH_SPACE'] == 'with space ' | ||
| def test_empty_value(run, tmpenvdir, monkeypatch): | ||
| """File with empty string""" | ||
| monkeypatch.setattr(os, 'execvpe', functools.partial(mocked_execvpe, | ||
| monkeypatch)) | ||
| tmpenvdir.join('EMPTY_STRING').write('\n') | ||
| with py.test.raises(Response): | ||
| run('envdir', str(tmpenvdir), 'ls') | ||
| assert os.environ['EMPTY_STRING'] == '' | ||
| def test_lowercase_var_names(run, tmpenvdir, monkeypatch): | ||
@@ -217,2 +245,6 @@ "Lowercase env var name" | ||
| @pytest.mark.skipif(py.std.sys.version_info < (2, 7) and | ||
| platform.system() == 'Windows', | ||
| reason="os.kill doesn't work properly on " | ||
| "Python < 2.7 on Windows") | ||
| def test_keyboard_interrupt(run, tmpenvdir, monkeypatch): | ||
@@ -225,7 +257,10 @@ monkeypatch.setattr(os, 'execvpe', | ||
| run('envdir', str(tmpenvdir), 'sleep', '1') | ||
| # Minus sign is added by subprocess to distinguish signals from exit codes. | ||
| # Since we send a signal within the test to stop the process, it is the | ||
| # intended behaviour. | ||
| # signal.SIGINT is equivalent to KeyboardInterrupt on POSIX. | ||
| assert response.value.status == -signal.SIGINT | ||
| if platform.system() == 'Windows': | ||
| assert response.value.status == signal.SIGINT | ||
| else: | ||
| # Minus sign is added by subprocess to distinguish signals from exit | ||
| # codes. Since we send a signal within the test to stop the process, | ||
| # it is the intended behaviour. | ||
| # signal.SIGINT is equivalent to KeyboardInterrupt on POSIX. | ||
| assert response.value.status == -signal.SIGINT | ||
@@ -281,6 +316,3 @@ | ||
| if py.std.sys.version_info[:2] == (2, 6): | ||
| assert response.value == 2 | ||
| else: | ||
| assert response.value.code == 2 | ||
| assert response.value.code == 2 | ||
| assert "incorrect number of arguments" in err | ||
@@ -291,6 +323,3 @@ | ||
| out, err = capfd.readouterr() | ||
| if py.std.sys.version_info[:2] == (2, 6): | ||
| assert response.value == 2 | ||
| else: | ||
| assert response.value.code == 2 | ||
| assert response.value.code == 2 | ||
@@ -350,2 +379,6 @@ | ||
| assert 'ITER' not in os.environ | ||
| with pytest.raises(KeyError): | ||
| env['DOESNOTEXISTS'] | ||
| default = object() | ||
| assert env.get('DOESNOTEXISTS', default) is default | ||
@@ -395,1 +428,31 @@ with envdir.open(str(tmpenvdir)) as env: | ||
| assert 'CONTEXT_MANAGER_ITEM_SET' not in os.environ | ||
| @pytest.mark.skipif(sys.platform == 'win32', | ||
| reason="Symlinks are not supported on windows") | ||
| def test_envdir_follows_symlinks(run, tmpenvdir, monkeypatch): | ||
| """Check envdir follows symbolic links""" | ||
| monkeypatch.setattr(os, 'execvpe', functools.partial(mocked_execvpe, | ||
| monkeypatch)) | ||
| tmpenvdir.join('DEFAULT').mksymlinkto('SYMLINK_ENV') | ||
| tmpenvdir.join('DEFAULT').write('test') | ||
| with py.test.raises(Response) as response: | ||
| run('envdir', str(tmpenvdir), 'ls') | ||
| assert 'DEFAULT' in os.environ | ||
| assert 'SYMLINK_ENV' in os.environ | ||
| assert os.environ['SYMLINK_ENV'] == 'test' | ||
| assert response.value.status == 0 | ||
| assert response.value.message == '' | ||
| @pytest.mark.skipif(sys.platform == 'win32', | ||
| reason="Symlinks are not supported on windows") | ||
| def test_envdir_raise_broken_symlinks(run, tmpenvdir, monkeypatch): | ||
| """If broken symlink is encountered, raise loudly""" | ||
| monkeypatch.setattr(os, 'execvpe', functools.partial(mocked_execvpe, | ||
| monkeypatch)) | ||
| tmpenvdir.join('DEFAULT').mksymlinkto('SYMLINK_ENV') | ||
| tmpenvdir.join('DEFAULT').write('test') | ||
| tmpenvdir.join('SYMLINK_ENV').remove() | ||
| with pytest.raises(FileNotFoundError): | ||
| run('envdir', str(tmpenvdir), 'ls') |
@@ -1,1 +0,1 @@ | ||
| __version__ = '0.7' # noqa | ||
| __version__ = '1.0.1' # noqa |
+24
-10
| Metadata-Version: 1.1 | ||
| Name: envdir | ||
| Version: 0.7 | ||
| Version: 1.0.1 | ||
| Summary: A Python port of daemontools' envdir. | ||
| Home-page: http://envdir.readthedocs.org/ | ||
| Home-page: https://envdir.readthedocs.io/ | ||
| Author: Jannis Leidel | ||
@@ -12,6 +12,10 @@ Author-email: jannis@leidel.info | ||
| .. image:: https://api.travis-ci.org/jezdez/envdir.png | ||
| :alt: Build Status | ||
| .. image:: https://api.travis-ci.org/jezdez/envdir.svg | ||
| :alt: Linux Build Status | ||
| :target: https://travis-ci.org/jezdez/envdir | ||
| .. image:: https://ci.appveyor.com/api/projects/status/0fh77wei6cj5hei5?svg=true | ||
| :alt: Windows Build Status | ||
| :target: https://ci.appveyor.com/project/jezdez/envdir | ||
| This is a Python port of daemontools_' tool envdir_. It works on Windows and | ||
@@ -77,3 +81,2 @@ other systems which can run Python. It's well tested and doesn't need a | ||
| Feel free to open tickets at https://github.com/jezdez/envdir/issues. | ||
| Say thanks at https://www.gittip.com/jezdez/. | ||
@@ -88,2 +91,14 @@ .. _12factor: http://12factor.net/config | ||
| 1.0.0 (26/03/2018) | ||
| ^^^^^^^^^^^^^^^^^^ | ||
| * Drop python 2.6, 3.2 and 3.3 | ||
| * Add explicit support for python 3.6 | ||
| * Add support for symlinks | ||
| * Improved support for windows | ||
| 0.7 (08/10/2014) | ||
@@ -111,3 +126,3 @@ ^^^^^^^^^^^^^^^^ | ||
| * Added Sphinx based docs: http://envdir.readthedocs.org/ | ||
| * Added Sphinx based docs: https://envdir.readthedocs.io/ | ||
@@ -178,7 +193,6 @@ * Fixed killing child process when capturing keyboard interrupt. | ||
| Classifier: Programming Language :: Python :: 2 | ||
| Classifier: Programming Language :: Python :: 2.6 | ||
| Classifier: Programming Language :: Python :: 2.7 | ||
| Classifier: Programming Language :: Python :: 3 | ||
| Classifier: Programming Language :: Python :: 3.1 | ||
| Classifier: Programming Language :: Python :: 3.2 | ||
| Classifier: Programming Language :: Python :: 3.3 | ||
| Classifier: Programming Language :: Python :: 3.4 | ||
| Classifier: Programming Language :: Python :: 3.5 | ||
| Classifier: Programming Language :: Python :: 3.6 |
+6
-3
| envdir (Python port) | ||
| ==================== | ||
| .. image:: https://api.travis-ci.org/jezdez/envdir.png | ||
| :alt: Build Status | ||
| .. image:: https://api.travis-ci.org/jezdez/envdir.svg | ||
| :alt: Linux Build Status | ||
| :target: https://travis-ci.org/jezdez/envdir | ||
| .. image:: https://ci.appveyor.com/api/projects/status/0fh77wei6cj5hei5?svg=true | ||
| :alt: Windows Build Status | ||
| :target: https://ci.appveyor.com/project/jezdez/envdir | ||
| This is a Python port of daemontools_' tool envdir_. It works on Windows and | ||
@@ -68,3 +72,2 @@ other systems which can run Python. It's well tested and doesn't need a | ||
| Feel free to open tickets at https://github.com/jezdez/envdir/issues. | ||
| Say thanks at https://www.gittip.com/jezdez/. | ||
@@ -71,0 +74,0 @@ .. _12factor: http://12factor.net/config |
+1
-2
@@ -7,3 +7,3 @@ [wheel] | ||
| [pytest] | ||
| [tool:pytest] | ||
| flakes-ignore = UnusedImport | ||
@@ -15,3 +15,2 @@ addopts = --strict --quiet --tb=short | ||
| tag_date = 0 | ||
| tag_svn_revision = 0 | ||
+5
-6
@@ -21,3 +21,3 @@ import ast | ||
| def read(*parts): | ||
| return codecs.open(os.path.join(here, *parts), 'r').read() | ||
| return codecs.open(os.path.join(here, *parts), 'r', encoding='utf8').read() | ||
@@ -39,8 +39,7 @@ | ||
| 'Programming Language :: Python :: 2', | ||
| 'Programming Language :: Python :: 2.6', | ||
| 'Programming Language :: Python :: 2.7', | ||
| 'Programming Language :: Python :: 3', | ||
| 'Programming Language :: Python :: 3.1', | ||
| 'Programming Language :: Python :: 3.2', | ||
| 'Programming Language :: Python :: 3.3', | ||
| 'Programming Language :: Python :: 3.4', | ||
| 'Programming Language :: Python :: 3.5', | ||
| 'Programming Language :: Python :: 3.6', | ||
| ], | ||
@@ -53,3 +52,3 @@ description="A Python port of daemontools' envdir.", | ||
| author_email='jannis@leidel.info', | ||
| url='http://envdir.readthedocs.org/', | ||
| url='https://envdir.readthedocs.io/', | ||
| license='MIT', | ||
@@ -56,0 +55,0 @@ packages=['envdir'], |
+3
-4
| [tox] | ||
| envlist = py26,py27,pypy,py32,py33,flake827,flake833 | ||
| ;envlist = py27,flake827 | ||
| envlist = py{27,34,35,36,py},flake827,flake836 | ||
@@ -18,5 +17,5 @@ [testenv] | ||
| [testenv:flake833] | ||
| basepython = python3.3 | ||
| [testenv:flake836] | ||
| basepython = python3.6 | ||
| deps = flake8 | ||
| commands = flake8 envdir |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
76441
6.4%838
9.4%