summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Sateler <fsateler@debian.org>2018-10-20 12:35:03 -0300
committerFelipe Sateler <fsateler@debian.org>2018-10-20 12:35:03 -0300
commitbd02bb0b9837eeb8faa564552b4501ca2d81bfcf (patch)
treecf251abadd3d944de8d7cfcdf5feccc60667efc5
parent92dbe873a377d5bf1019baccecbd100ba74871b0 (diff)
parent76e9798cafc84afa601d4817bf6ffd343cb9d579 (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-INFO2
-rw-r--r--README.md2
-rw-r--r--docker_pycreds.egg-info/PKG-INFO2
-rw-r--r--docker_pycreds.egg-info/SOURCES.txt4
-rw-r--r--dockerpycreds/constants.py1
-rw-r--r--dockerpycreds/errors.py4
-rw-r--r--dockerpycreds/store.py19
-rw-r--r--dockerpycreds/utils.py38
-rw-r--r--dockerpycreds/version.py2
-rw-r--r--tests/store_test.py8
-rw-r--r--tests/utils_test.py22
11 files changed, 96 insertions, 8 deletions
diff --git a/PKG-INFO b/PKG-INFO
index f974a57..0cec3f7 100644
--- a/PKG-INFO
+++ b/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/README.md b/README.md
index 4e7ddd9..548c7fb 100644
--- a/README.md
+++ b/README.md
@@ -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