diff options
author | Felipe Sateler <fsateler@debian.org> | 2018-10-20 12:35:03 -0300 |
---|---|---|
committer | Felipe Sateler <fsateler@debian.org> | 2018-10-20 12:35:03 -0300 |
commit | bd02bb0b9837eeb8faa564552b4501ca2d81bfcf (patch) | |
tree | cf251abadd3d944de8d7cfcdf5feccc60667efc5 | |
parent | 92dbe873a377d5bf1019baccecbd100ba74871b0 (diff) | |
parent | 76e9798cafc84afa601d4817bf6ffd343cb9d579 (diff) |
Update upstream source from tag 'upstream/0.3.0'
Update to upstream version '0.3.0'
with Debian dir 591bb57a7569dab6db99e2cd51c67c90833cb378
-rw-r--r-- | PKG-INFO | 2 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | docker_pycreds.egg-info/PKG-INFO | 2 | ||||
-rw-r--r-- | docker_pycreds.egg-info/SOURCES.txt | 4 | ||||
-rw-r--r-- | dockerpycreds/constants.py | 1 | ||||
-rw-r--r-- | dockerpycreds/errors.py | 4 | ||||
-rw-r--r-- | dockerpycreds/store.py | 19 | ||||
-rw-r--r-- | dockerpycreds/utils.py | 38 | ||||
-rw-r--r-- | dockerpycreds/version.py | 2 | ||||
-rw-r--r-- | tests/store_test.py | 8 | ||||
-rw-r--r-- | tests/utils_test.py | 22 |
11 files changed, 96 insertions, 8 deletions
@@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: docker-pycreds -Version: 0.2.2 +Version: 0.3.0 Summary: Python bindings for the docker credentials store API Home-page: https://github.com/shin-/dockerpy-creds Author: UNKNOWN @@ -1,5 +1,7 @@ # docker-pycreds +[![CircleCI](https://circleci.com/gh/shin-/dockerpy-creds/tree/master.svg?style=svg)](https://circleci.com/gh/shin-/dockerpy-creds/tree/master) + Python bindings for the docker credentials store API ## Credentials store info diff --git a/docker_pycreds.egg-info/PKG-INFO b/docker_pycreds.egg-info/PKG-INFO index f974a57..0cec3f7 100644 --- a/docker_pycreds.egg-info/PKG-INFO +++ b/docker_pycreds.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: docker-pycreds -Version: 0.2.2 +Version: 0.3.0 Summary: Python bindings for the docker credentials store API Home-page: https://github.com/shin-/dockerpy-creds Author: UNKNOWN diff --git a/docker_pycreds.egg-info/SOURCES.txt b/docker_pycreds.egg-info/SOURCES.txt index 4651ea1..0cd3aa7 100644 --- a/docker_pycreds.egg-info/SOURCES.txt +++ b/docker_pycreds.egg-info/SOURCES.txt @@ -15,6 +15,8 @@ dockerpycreds/__init__.py dockerpycreds/constants.py dockerpycreds/errors.py dockerpycreds/store.py +dockerpycreds/utils.py dockerpycreds/version.py tests/__init__.py -tests/store_test.py
\ No newline at end of file +tests/store_test.py +tests/utils_test.py
\ No newline at end of file diff --git a/dockerpycreds/constants.py b/dockerpycreds/constants.py index c6492fe..6a82d8d 100644 --- a/dockerpycreds/constants.py +++ b/dockerpycreds/constants.py @@ -1,3 +1,4 @@ PROGRAM_PREFIX = 'docker-credential-' DEFAULT_LINUX_STORE = 'secretservice' DEFAULT_OSX_STORE = 'osxkeychain' +DEFAULT_WIN32_STORE = 'wincred' diff --git a/dockerpycreds/errors.py b/dockerpycreds/errors.py index 3bd53a2..9e4695c 100644 --- a/dockerpycreds/errors.py +++ b/dockerpycreds/errors.py @@ -6,6 +6,10 @@ class CredentialsNotFound(StoreError): pass +class InitializationError(StoreError): + pass + + def process_store_error(cpe, program): message = cpe.output.decode('utf-8') if 'credentials not found in native keychain' in message: diff --git a/dockerpycreds/store.py b/dockerpycreds/store.py index b83e71b..269b9e0 100644 --- a/dockerpycreds/store.py +++ b/dockerpycreds/store.py @@ -6,15 +6,25 @@ import six from . import constants from . import errors +from .utils import create_environment_dict +from .utils import find_executable class Store(object): - def __init__(self, program): + def __init__(self, program, environment=None): """ Create a store object that acts as an interface to perform the basic operations for storing, retrieving and erasing credentials using `program`. """ self.program = constants.PROGRAM_PREFIX + program + self.exe = find_executable(self.program) + self.environment = environment + if self.exe is None: + raise errors.InitializationError( + '{0} not installed or not available in PATH'.format( + self.program + ) + ) def get(self, server): """ Retrieve credentials for `server`. If no credentials are found, @@ -57,15 +67,16 @@ class Store(object): def _execute(self, subcmd, data_input): output = None + env = create_environment_dict(self.environment) try: if six.PY3: output = subprocess.check_output( - [self.program, subcmd], input=data_input + [self.exe, subcmd], input=data_input, env=env, ) else: process = subprocess.Popen( - [self.program, subcmd], stdin=subprocess.PIPE, - stdout=subprocess.PIPE + [self.exe, subcmd], stdin=subprocess.PIPE, + stdout=subprocess.PIPE, env=env, ) output, err = process.communicate(data_input) if process.returncode != 0: diff --git a/dockerpycreds/utils.py b/dockerpycreds/utils.py new file mode 100644 index 0000000..3f720ef --- /dev/null +++ b/dockerpycreds/utils.py @@ -0,0 +1,38 @@ +import distutils.spawn +import os +import sys + + +def find_executable(executable, path=None): + """ + As distutils.spawn.find_executable, but on Windows, look up + every extension declared in PATHEXT instead of just `.exe` + """ + if sys.platform != 'win32': + return distutils.spawn.find_executable(executable, path) + + if path is None: + path = os.environ['PATH'] + + paths = path.split(os.pathsep) + extensions = os.environ.get('PATHEXT', '.exe').split(os.pathsep) + base, ext = os.path.splitext(executable) + + if not os.path.isfile(executable): + for p in paths: + for ext in extensions: + f = os.path.join(p, base + ext) + if os.path.isfile(f): + return f + return None + else: + return executable + + +def create_environment_dict(overrides): + """ + Create and return a copy of os.environ with the specified overrides + """ + result = os.environ.copy() + result.update(overrides or {}) + return result diff --git a/dockerpycreds/version.py b/dockerpycreds/version.py index 9171e46..275c4ec 100644 --- a/dockerpycreds/version.py +++ b/dockerpycreds/version.py @@ -1,2 +1,2 @@ -version = "0.2.2" +version = "0.3.0" version_info = tuple([int(d) for d in version.split("-")[0].split(".")]) diff --git a/tests/store_test.py b/tests/store_test.py index 075186a..ba5fd7b 100644 --- a/tests/store_test.py +++ b/tests/store_test.py @@ -1,3 +1,4 @@ +import os import random import sys @@ -67,3 +68,10 @@ class TestStore(object): self.store.erase(key) with pytest.raises(CredentialsNotFound): self.store.get(key) + + def test_execute_with_env_override(self): + self.store.exe = 'env' + self.store.environment = {'FOO': 'bar'} + data = self.store._execute('--null', '') + assert b'\0FOO=bar\0' in data + assert 'FOO' not in os.environ diff --git a/tests/utils_test.py b/tests/utils_test.py new file mode 100644 index 0000000..ac06c9c --- /dev/null +++ b/tests/utils_test.py @@ -0,0 +1,22 @@ +import os + +from dockerpycreds.utils import create_environment_dict + +try: + from unittest import mock +except ImportError: + import mock + + +@mock.patch.dict(os.environ) +def test_create_environment_dict(): + base = {'FOO': 'bar', 'BAZ': 'foobar'} + os.environ = base + assert create_environment_dict({'FOO': 'baz'}) == { + 'FOO': 'baz', 'BAZ': 'foobar', + } + assert create_environment_dict({'HELLO': 'world'}) == { + 'FOO': 'bar', 'BAZ': 'foobar', 'HELLO': 'world', + } + + assert os.environ == base |