Codebase list python-keyring / 799ba8d
New upstream version 10.5.0 Dmitry Shachnev 6 years ago
40 changed file(s) with 307 addition(s) and 175 deletion(s). Raw diff Collapse all Expand all
22 brew install python3
33 rm /usr/local/bin/python
44 ln -s python3 /usr/local/bin/python
5 python -m pip install --upgrade tox
00 language: python
1 python:
2 - 2.7
3 - 3.3
4 - 3.4
5 - 3.5
6 - 3.6
7 matrix:
1
2 jobs:
3 fast_finish: true
84 include:
5 - python: 2.7
6 - python: 3.3
7 - python: &latest_py3 3.6
98 - os: osx
109 language: generic
10 - stage: deploy
11 if: tag IS present
12 python: *latest_py3
13 install: skip
14 script: skip
15 deploy:
16 provider: pypi
17 on:
18 tags: true
19 all_branches: true
20 user: jaraco
21 password:
22 secure: aDqlVdm6FZ8pqLkoDRR2LH3TEz7pBvKH2HhOlSy7OEmopN/36ncql/KvfE0ccpaOES9Xm31a51bUfNjcwb1HVKjfW544C+IoSHctkG1rI5bp3q4rW+4RbQcBZVHUUKR9yQf9ZyikEmoYXi3g+JKcOf9rj+v/32PAfUDzSpFbWik=
23 distributions: dists
24 skip_cleanup: true
25 skip_upload_docs: true
26
27 cache: pip
1128
1229 before_install:
1330 - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then source .travis-osx; fi
1431
1532 install:
16 - python -m pip install tox "setuptools>=28.2"
17 script:
18 - tox -- -rs -v
19 branches:
20 except:
21 - skeleton
22 deploy:
23 provider: pypi
24 server: https://upload.pypi.org/legacy/
25 on:
26 tags: true
27 all_branches: true
28 python: 3.6
29 user: jaraco
30 password:
31 secure: aDqlVdm6FZ8pqLkoDRR2LH3TEz7pBvKH2HhOlSy7OEmopN/36ncql/KvfE0ccpaOES9Xm31a51bUfNjcwb1HVKjfW544C+IoSHctkG1rI5bp3q4rW+4RbQcBZVHUUKR9yQf9ZyikEmoYXi3g+JKcOf9rj+v/32PAfUDzSpFbWik=
32 distributions: dists
33 skip_upload_docs: true
33 - pip install tox
34
35 script: tox
0 10.5.0
1 ------
2
3 * #287: Added ``--list-backends`` option to
4 command-line interface.
5
6 * Removed ``logger`` from ``keyring``. See #291 for related
7 request.
8
9 * #292: Set the appid for SecretService & KWallet to
10 something meaningful.
11
012 10.4.0
113 ------
214
486498
487499 * Removed support for Python 2.5.
488500 * Removed names in ``keyring.backend`` moved in 1.1 and previously retained
489 for compatibilty.
501 for compatibility.
490502
491503 2.1.1
492504 -----
788800 location or make assumptions about the storage location will need to take
789801 this change into consideration. Additionally, after upgrading to 0.8,
790802 it is not possible to downgrade to 0.7 without manually moving
791 configuration files. In 1.0, the backward compatibilty
803 configuration files. In 1.0, the backward compatibility
792804 will be removed.
793805
794806 0.7.1
0 Copyright Jason R. Coombs
1
2 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
3
4 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
5
6 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0 Metadata-Version: 1.1
0 Metadata-Version: 1.2
11 Name: keyring
2 Version: 10.4.0
2 Version: 10.5.0
33 Summary: Store and access your passwords safely.
44 Home-page: https://github.com/jaraco/keyring
55 Author: Jason R. Coombs
66 Author-email: jaraco@jaraco.com
77 License: UNKNOWN
8 Description-Content-Type: UNKNOWN
89 Description: .. image:: https://img.shields.io/pypi/v/keyring.svg
910 :target: https://pypi.org/project/keyring
1011
1112 .. image:: https://img.shields.io/pypi/pyversions/keyring.svg
1213
13 .. image:: https://img.shields.io/pypi/dm/keyring.svg
14
1514 .. image:: https://img.shields.io/travis/jaraco/keyring/master.svg
1615 :target: http://travis-ci.org/jaraco/keyring
1716
17 .. image:: https://readthedocs.org/projects/keyring/badge/?version=latest
18 :target: http://keyring.readthedocs.io/en/latest/?badge=latest
1819
1920 =======================================
2021 Installing and Using Python Keyring Lib
2627 What is Python keyring lib?
2728 ---------------------------
2829
29 The Python keyring lib provides a easy way to access the system keyring service
30 The Python keyring lib provides an easy way to access the system keyring service
3031 from python. It can be used in any application that needs safe password storage.
3132
3233 The keyring library is licensed under both the `MIT license
4142 `secretstorage <https://pypi.python.org/pypi/secretstorage>`_)
4243 * `KWallet <https://en.wikipedia.org/wiki/KWallet>`_
4344 (requires `dbus <https://pypi.python.org/pypi/dbus-python>`_)
44 * `Windows Credential Vault
45 <http://windows.microsoft.com/en-us/windows7/what-is-credential-manager>`_
45 * `Windows Credential Locker
46 <https://docs.microsoft.com/en-us/windows/uwp/security/credential-locker>`_
4647
4748 Other keyring implementations are provided in the `keyrings.alt package`_.
4849
219220 # invoke the keyring lib
220221 try:
221222 keyring.set_password("demo-service", "tarek", "passexample")
222 print("password stored sucessfully")
223 print("password stored successfully")
223224 except keyring.errors.PasswordSetError:
224225 print("failed to store password")
225226 print("password", keyring.get_password("demo-service", "tarek"))
361362 Classifier: Programming Language :: Python :: 3.4
362363 Classifier: Programming Language :: Python :: 3.5
363364 Classifier: Programming Language :: Python :: 3.6
365 Requires-Python: >=2.7
22
33 .. image:: https://img.shields.io/pypi/pyversions/keyring.svg
44
5 .. image:: https://img.shields.io/pypi/dm/keyring.svg
6
75 .. image:: https://img.shields.io/travis/jaraco/keyring/master.svg
86 :target: http://travis-ci.org/jaraco/keyring
97
8 .. image:: https://readthedocs.org/projects/keyring/badge/?version=latest
9 :target: http://keyring.readthedocs.io/en/latest/?badge=latest
1010
1111 =======================================
1212 Installing and Using Python Keyring Lib
1818 What is Python keyring lib?
1919 ---------------------------
2020
21 The Python keyring lib provides a easy way to access the system keyring service
21 The Python keyring lib provides an easy way to access the system keyring service
2222 from python. It can be used in any application that needs safe password storage.
2323
2424 The keyring library is licensed under both the `MIT license
3333 `secretstorage <https://pypi.python.org/pypi/secretstorage>`_)
3434 * `KWallet <https://en.wikipedia.org/wiki/KWallet>`_
3535 (requires `dbus <https://pypi.python.org/pypi/dbus-python>`_)
36 * `Windows Credential Vault
37 <http://windows.microsoft.com/en-us/windows7/what-is-credential-manager>`_
36 * `Windows Credential Locker
37 <https://docs.microsoft.com/en-us/windows/uwp/security/credential-locker>`_
3838
3939 Other keyring implementations are provided in the `keyrings.alt package`_.
4040
211211 # invoke the keyring lib
212212 try:
213213 keyring.set_password("demo-service", "tarek", "passexample")
214 print("password stored sucessfully")
214 print("password stored successfully")
215215 except keyring.errors.PasswordSetError:
216216 print("failed to store password")
217217 print("password", keyring.get_password("demo-service", "tarek"))
1515
1616 test_script:
1717 - "python -m pip install tox"
18 - "tox -- -rs -v"
18 - "tox"
1919
20 branches:
21 except:
22 - skeleton
20 version: '{build}'
44 ]
55
66 if platform.system() != 'Darwin':
7 collect_ignore.append('keyring/backends/_OS_X_API.py')
7 collect_ignore.append('keyring/backends/_OS_X_API.py')
88
99 collect_ignore.append('keyring/devpi_client.py')
1010 import pkg_resources
1111
1212 hiddenimports.extend(
13 ep.module_name
14 for ep in pkg_resources.iter_entry_points('keyring.backends')
13 ep.module_name
14 for ep in pkg_resources.iter_entry_points('keyring.backends')
1515 )
00 from __future__ import absolute_import
11
2 import logging
3 logger = logging.getLogger('keyring')
4
52 from .core import (set_keyring, get_keyring, set_password, get_password,
6 delete_password)
3 delete_password)
74 from .getpassbackend import get_password as get_pass_get_password
85
96 try:
10 import pkg_resources
11 __version__ = pkg_resources.require('keyring')[0].version
7 import pkg_resources
8 __version__ = pkg_resources.get_distribution('keyring').version
129 except Exception:
13 __version__ = 'unknown'
10 __version__ = 'unknown'
11
12 __all__ = (
13 'set_keyring', 'get_keyring', 'set_password', 'get_password',
14 'delete_password', 'get_pass_get_password',
15 )
9797 """
9898 raise errors.PasswordDeleteError("reason")
9999
100
100101 class Crypter(object):
101102 """Base class providing encryption and decryption
102103 """
113114 """
114115 pass
115116
117
116118 class NullCrypter(Crypter):
117119 """A crypter that does nothing
118120 """
127129 def _load_backend(name):
128130 "Load a backend by name"
129131 package = backends.__package__ or backends.__name__
130 mod = importlib.import_module('.'+name, package)
132 mod = importlib.import_module('.' + name, package)
131133 # invoke __name__ on each module to ensure it's loaded in demand-import
132134 # environments
133135 mod.__name__
136
134137
135138 def _load_backends():
136139 "ensure that native keyring backends are loaded"
137140 backends = 'kwallet', 'OS_X', 'SecretService', 'Windows'
138141 list(map(_load_backend, backends))
139142 _load_plugins()
143
140144
141145 def _load_plugins():
142146 """
169173 except Exception:
170174 log.exception("Error initializing plugin %s." % ep)
171175
176
172177 @util.once
173178 def get_all_keyring():
174179 """
187192 all_classes = KeyringBackend._classes
188193 viable_classes = filter(is_class_viable, all_classes)
189194 return list(util.suppress_exceptions(viable_classes,
190 exceptions=TypeError))
195 exceptions=TypeError))
3131 username = ''
3232
3333 try:
34 api.set_generic_password(self.keychain, service, username, password)
34 api.set_generic_password(
35 self.keychain, service, username, password)
3536 except api.Error:
3637 raise PasswordSetError("Can't store password on keychain")
3738
4950 username = ''
5051
5152 try:
52 return api.delete_generic_password(self.keychain, service, username)
53 return api.delete_generic_password(
54 self.keychain, service, username)
5355 except api.Error:
5456 raise PasswordDeleteError("Can't delete password in keychain")
00 import logging
1
2 import sys
3 import os
14
25 from ..util import properties
36 from ..backend import KeyringBackend
47 from ..errors import (InitError, PasswordDeleteError,
5 ExceptionRaisedContext)
8 ExceptionRaisedContext)
69
710 try:
811 import secretstorage
1215
1316 log = logging.getLogger(__name__)
1417
18
1519 class Keyring(KeyringBackend):
1620 """Secret Service Keyring"""
17 appid = "python-keyring"
21 appid = os.path.basename(sys.argv[0]) or 'Python keyring library'
1822
1923 @properties.ClassProperty
2024 @classmethod
4044 bus = secretstorage.dbus_init()
4145 try:
4246 if hasattr(self, 'preferred_collection'):
43 collection = secretstorage.Collection(bus, self.preferred_collection)
47 collection = secretstorage.Collection(
48 bus, self.preferred_collection)
4449 else:
4550 collection = secretstorage.get_default_collection(bus)
4651 except exceptions.SecretStorageException as e:
4752 raise InitError("Failed to create the collection: %s." % e)
4853 if collection.is_locked():
4954 collection.unlock()
50 if collection.is_locked(): # User dismissed the prompt
55 if collection.is_locked(): # User dismissed the prompt
5156 raise InitError("Failed to unlock the collection!")
5257 return collection
5358
7176 "application": self.appid,
7277 "service": service,
7378 "username": username
74 }
79 }
7580 label = "Password for '%s' on '%s'" % (username, service)
7681 collection.create_item(label, attributes, password, replace=True)
7782
1919 import win32cred
2020 except ImportError:
2121 pass
22
2223
2324 def has_pywin32():
2425 """
8283 )
8384 except pywintypes.error as e:
8485 e = OldPywinError.wrap(e)
85 if e.winerror == 1168 and e.funcname == 'CredRead': # not found
86 if e.winerror == 1168 and e.funcname == 'CredRead': # not found
8687 return None
8788 raise
8889 return res
9495 existing_username = existing_pw['UserName']
9596 target = self._compound_name(existing_username, service)
9697 self._set_password(target, existing_username,
97 existing_pw['CredentialBlob'].decode('utf-16'))
98 existing_pw['CredentialBlob'].decode('utf-16'))
9899 self._set_password(service, username, text_type(password))
99100
100101 def _set_password(self, target, username, password):
129130 A compatibility wrapper for old PyWin32 errors, such as reported in
130131 https://bitbucket.org/kang/python-keyring-lib/issue/140/
131132 """
133
132134 def __init__(self, orig):
133135 self.orig = orig
134136
88 sec_keychain_ref = sec_keychain_item_ref = c_void_p
99 OS_status = c_int32
1010
11
1112 class error:
1213 item_not_found = -25300
14
1315
1416 fw = '/System/Library/Frameworks/{name}.framework/Versions/A/{name}'.format
1517 _sec = ctypes.CDLL(fw(name='Security'))
2224 POINTER(sec_keychain_ref),
2325 )
2426 SecKeychainOpen.restype = OS_status
25
2627
2728
2829 SecKeychainCopyDefault = _sec.SecKeychainCopyDefault
6162 finally:
6263 _core.CFRelease(ref)
6364
65
6466 SecKeychainFindGenericPassword = _sec.SecKeychainFindGenericPassword
6567 SecKeychainFindGenericPassword.argtypes = (
6668 sec_keychain_ref,
7476 )
7577 SecKeychainFindGenericPassword.restype = OS_status
7678
79
7780 def find_generic_password(kc_name, service, username):
78 username = username.encode('utf-8')
79 service = service.encode('utf-8')
80 with open(kc_name) as keychain:
81 length = c_uint32()
82 data = c_void_p()
83 status = SecKeychainFindGenericPassword(
84 keychain,
85 len(service),
86 service,
87 len(username),
88 username,
89 length,
90 data,
91 None,
92 )
93
94 msg = "Can't fetch password from system"
95 NotFound.raise_for_status(status, msg)
96
97 password = ctypes.create_string_buffer(length.value)
98 ctypes.memmove(password, data.value, length.value)
99 SecKeychainItemFreeContent(None, data)
100 return password.raw.decode('utf-8')
81 username = username.encode('utf-8')
82 service = service.encode('utf-8')
83 with open(kc_name) as keychain:
84 length = c_uint32()
85 data = c_void_p()
86 status = SecKeychainFindGenericPassword(
87 keychain,
88 len(service),
89 service,
90 len(username),
91 username,
92 length,
93 data,
94 None,
95 )
96
97 msg = "Can't fetch password from system"
98 NotFound.raise_for_status(status, msg)
99
100 password = ctypes.create_string_buffer(length.value)
101 ctypes.memmove(password, data.value, length.value)
102 SecKeychainItemFreeContent(None, data)
103 return password.raw.decode('utf-8')
101104
102105
103106 SecKeychainFindInternetPassword = _sec.SecKeychainFindInternetPassword
104107 SecKeychainFindInternetPassword.argtypes = (
105 sec_keychain_ref, # keychainOrArray
108 sec_keychain_ref, # keychainOrArray
106109 c_uint32, # serverNameLength
107110 c_char_p, # serverName
108111 c_uint32, # securityDomainLength
169172
170173
171174 def find_internet_password(kc_name, service, username):
172 username = username.encode('utf-8')
173 domain = None
174 service = service.encode('utf-8')
175 path = None
176 port = 0
177
178 with open(kc_name) as keychain:
179 length = c_uint32()
180 data = c_void_p()
181 status = SecKeychainFindInternetPassword(
182 keychain,
183 len(service), service,
184 0, domain,
185 len(username), username,
186 0, path,
187 port,
188 SecProtocolType.kSecProtocolTypeHTTPS,
189 SecAuthenticationType.kSecAuthenticationTypeAny,
190 length,
191 data,
192 None,
193 )
194
195 msg = "Can't fetch password from system"
196 NotFound.raise_for_status(status, msg)
197
198 password = ctypes.create_string_buffer(length.value)
199 ctypes.memmove(password, data.value, length.value)
200 SecKeychainItemFreeContent(None, data)
201 return password.raw.decode('utf-8')
175 username = username.encode('utf-8')
176 domain = None
177 service = service.encode('utf-8')
178 path = None
179 port = 0
180
181 with open(kc_name) as keychain:
182 length = c_uint32()
183 data = c_void_p()
184 status = SecKeychainFindInternetPassword(
185 keychain,
186 len(service), service,
187 0, domain,
188 len(username), username,
189 0, path,
190 port,
191 SecProtocolType.kSecProtocolTypeHTTPS,
192 SecAuthenticationType.kSecAuthenticationTypeAny,
193 length,
194 data,
195 None,
196 )
197
198 msg = "Can't fetch password from system"
199 NotFound.raise_for_status(status, msg)
200
201 password = ctypes.create_string_buffer(length.value)
202 ctypes.memmove(password, data.value, length.value)
203 SecKeychainItemFreeContent(None, data)
204 return password.raw.decode('utf-8')
202205
203206
204207 SecKeychainAddGenericPassword = _sec.SecKeychainAddGenericPassword
243246
244247 SecKeychainAddInternetPassword = _sec.SecKeychainAddInternetPassword
245248 SecKeychainAddInternetPassword.argtypes = (
246 sec_keychain_ref, # keychainOrArray
249 sec_keychain_ref, # keychainOrArray
247250 c_uint32, # serverNameLength
248251 c_char_p, # serverName
249252 c_uint32, # securityDomainLength
00 from __future__ import absolute_import
1
2 import sys
3 import os
14
25 from ..backend import KeyringBackend
36 from ..errors import PasswordDeleteError
1619 KDE KWallet 5 via D-Bus
1720 """
1821
19 appid = 'Python program'
22 appid = os.path.basename(sys.argv[0]) or 'Python keyring library'
2023 wallet = None
2124 bus_name = 'org.kde.kwalletd5'
2225 object_path = '/modules/kwalletd5'
4750 entry_list = []
4851 if self.iface.hasFolder(self.handle, old_folder, self.appid):
4952 entry_list = self.iface.readPasswordList(
50 self.handle, old_folder, '*@*', self.appid)
53 self.handle, old_folder, '*@*', self.appid)
5154
5255 for entry in entry_list.items():
5356 key = entry[0]
5558
5659 username, service = key.rsplit('@', 1)
5760 ret = self.iface.writePassword(
58 self.handle, service, username, password, self.appid)
61 self.handle, service, username, password, self.appid)
5962 if ret == 0:
60 self.iface.removeEntry(self.handle, old_folder, key, self.appid)
63 self.iface.removeEntry(
64 self.handle, old_folder, key, self.appid)
6165
6266 entry_list = self.iface.readPasswordList(
63 self.handle, old_folder, '*', self.appid)
67 self.handle, old_folder, '*', self.appid)
6468 if not entry_list:
6569 self.iface.removeFolder(self.handle, old_folder, self.appid)
6670
7377 remote_obj = bus.get_object(self.bus_name, self.object_path)
7478 self.iface = dbus.Interface(remote_obj, 'org.kde.KWallet')
7579 self.handle = self.iface.open(
76 self.iface.networkWallet(), wId, self.appid)
80 self.iface.networkWallet(), wId, self.appid)
7781 except dbus.DBusException:
7882 self.handle = -1
7983 if self.handle < 0:
66 from optparse import OptionParser
77 import sys
88
9 from . import core
10 from . import backend
911 from . import get_keyring, set_keyring, get_password, set_password, delete_password
10 from . import core
1112
1213
1314 class CommandLineTool(object):
1415 def __init__(self):
1516 self.parser = OptionParser(
16 usage="%prog [get|set|del] SERVICE USERNAME")
17 usage="%prog [get|set|del] SERVICE USERNAME")
1718 self.parser.add_option("-p", "--keyring-path",
1819 dest="keyring_path", default=None,
1920 help="Path to the keyring backend")
2021 self.parser.add_option("-b", "--keyring-backend",
2122 dest="keyring_backend", default=None,
2223 help="Name of the keyring backend")
24 self.parser.add_option("--list-backends",
25 action="store_true",
26 help="List keyring backends and exit")
2327
2428 def run(self, argv):
2529 opts, args = self.parser.parse_args(argv)
30
31 if opts.list_backends:
32 for k in backend.get_all_keyring():
33 print(k)
34 return
2635
2736 try:
2837 kind, service, username = args
3847 try:
3948 if opts.keyring_path:
4049 sys.path.insert(0, opts.keyring_path)
41 backend = core.load_keyring(opts.keyring_backend)
42 set_keyring(backend)
50 set_keyring(core.load_keyring(opts.keyring_backend))
4351 except (Exception,):
4452 # Tons of things can go wrong here:
4553 # ImportError when using "fjkljfljkl"
6573
6674 elif kind == 'del':
6775 password = self.input_password("Deleting password for '%s' in '%s': " %
68 (username, service))
76 (username, service))
6977 delete_password(service, username)
7078 return 0
7179
99 from .py27compat import configparser, filter
1010 from .py33compat import max
1111
12 from . import logger
1312 from . import backend
1413 from .util import platform_ as platform
1514 from .backends import fail
1817 log = logging.getLogger(__name__)
1918
2019 _keyring_backend = None
20
2121
2222 def set_keyring(keyring):
2323 """Set current keyring backend.
5252 _keyring_backend.delete_password(service_name, username)
5353
5454
55 recommended = lambda backend: backend.priority >= 1
55 def recommended(backend): return backend.priority >= 1
56
57
5658 by_priority = operator.attrgetter('priority')
5759
5860
129131 raise configparser.NoOptionError('backend', 'default-keyring')
130132
131133 except (configparser.NoOptionError, ImportError):
134 logger = logging.getLogger('keyring')
132135 logger.warning("Keyring config file contains incorrect values.\n" +
133136 "Config file: %s" % keyring_cfg)
134137 return
135138
136139 return load_keyring(keyring_name)
140
137141
138142 def _load_keyring_path(config):
139143 "load the keyring-path option (if present)"
143147 except (configparser.NoOptionError, configparser.NoSectionError):
144148 pass
145149
150
146151 # init the _keyring_backend
147152 init_backend()
11 import abc
22
33 from .py27compat import add_metaclass
4
45
56 @add_metaclass(abc.ABCMeta)
67 class Credential(object):
1415 @abc.abstractproperty
1516 def password(self):
1617 return None
18
1719
1820 class SimpleCredential(Credential):
1921 """Simple credentials implementation
3133 def password(self):
3234 return self._password
3335
36
3437 class EnvironCredential(Credential):
3538 """Source credentials from environment variables.
3639 Actual sourcing is deferred until requested.
4548 """
4649 value = os.environ.get(env_var)
4750 if not value:
48 raise ValueError('Missing environment variable:%s' %env_var)
51 raise ValueError('Missing environment variable:%s' % env_var)
4952 return value
5053
5154 @property
44
55 hookimpl = HookimplMarker("devpiclient")
66
7
78 @hookimpl()
89 def devpiclient_get_password(url, username):
9 return keyring.get_password(url, username)
10 return keyring.get_password(url, username)
00 import sys
1
12
23 class PasswordSetError(Exception):
34 """Raised when the password can't be set.
45 """
56
7
68 class PasswordDeleteError(Exception):
79 """Raised when the password can't be deleted.
810 """
911
12
1013 class InitError(Exception):
1114 """Raised when the keyring could not be initialised
1215 """
16
1317
1418 class ExceptionRaisedContext(object):
1519 """
1620 An exception-trapping context that indicates whether an exception was
1721 raised.
1822 """
23
1924 def __init__(self, ExpectedException=Exception):
2025 self.ExpectedException = ExpectedException
2126 self.exc_info = None
2833 self.exc_info.__init__(*exc_info)
2934 return self.exc_info.type and issubclass(
3035 self.exc_info.type, self.ExpectedException)
36
3137
3238 class ExceptionInfo(object):
3339 def __init__(self, *info):
1414 import getpass
1515
1616 from . import get_password, delete_password, set_password
17
1718
1819 class PasswordMgr(object):
1920 def get_username(self, realm, authuri):
2929 filter = filter
3030
3131 # Taken from six.py
32
33
3234 def add_metaclass(metaclass):
3335 """Class decorator for creating a class with a metaclass."""
3436 def wrapper(cls):
4042 return metaclass(cls.__name__, cls.__bases__, orig_vars)
4143 return wrapper
4244
45
4346 try:
4447 import builtins
4548 except ImportError:
33 from ..test_backend import BackendBasicTests
44 from keyring.backends import OS_X
55
6
67 def is_osx_keychain_supported():
7 return sys.platform in ('mac','darwin')
8 return sys.platform in ('mac', 'darwin')
9
810
911 @unittest.skipUnless(is_osx_keychain_supported(),
1012 "Need OS X")
33 from keyring.backends import SecretService
44 from .. import util
55
6
67 @unittest.skipUnless(SecretService.Keyring.viable,
7 "SecretStorage package is needed for SecretServiceKeyring")
8 "SecretStorage package is needed for SecretServiceKeyring")
89 class SecretServiceKeyringTestCase(BackendBasicTests, unittest.TestCase):
910 __test__ = True
1011
1112 def init_keyring(self):
1213 print("Testing SecretServiceKeyring; the following "
13 "password prompts are for this keyring")
14 "password prompts are for this keyring")
1415 keyring = SecretService.Keyring()
1516 keyring.preferred_collection = '/org/freedesktop/secrets/collection/session'
1617 return keyring
18
1719
1820 class SecretServiceKeyringUnitTests(unittest.TestCase):
1921 def test_supported_no_secretstorage(self):
99
1010
1111 @unittest.skipUnless(keyring.backends.Windows.WinVaultKeyring.viable,
12 "Needs Windows")
12 "Needs Windows")
1313 class WinVaultKeyringTestCase(BackendBasicTests, unittest.TestCase):
1414 def tearDown(self):
1515 # clean up any credentials created
1515
1616 def tearDown(self):
1717 for item in self.credentials_created:
18 # Suppress errors, as only one pre/post migration item will be present
18 # Suppress errors, as only one pre/post migration item will be
19 # present
1920 try:
2021 self.keyring.delete_password(*item)
21 except:
22 except BaseException:
2223 pass
2324
2425 # TODO Remove empty folders created during tests
2930 self.credentials_created.add((service, username))
3031
3132 if old_format:
32 username = username+'@'+service
33 username = username + '@' + service
3334 service = 'Python'
3435
35 super(DBusKWalletTestCase, self).set_password(service, username, password)
36 super(
37 DBusKWalletTestCase,
38 self).set_password(
39 service,
40 username,
41 password)
3642
3743 def check_set_get(self, service, username, password):
3844 keyring = self.keyring
4652 self.keyring = keyring = self.init_keyring()
4753 ret_password = keyring.get_password(service, username)
4854 self.assertEqual(
49 ret_password, password,
50 "Incorrect password for username: '%s' on service: '%s'. '%s' != '%s'"
51 % (service, username, ret_password, password))
55 ret_password, password,
56 "Incorrect password for username: '%s' on service: '%s'. '%s' != '%s'"
57 % (service, username, ret_password, password))
5258
5359 # for the empty password
5460 self.set_password(service, username, "", True)
5662 self.keyring = keyring = self.init_keyring()
5763 ret_password = keyring.get_password(service, username)
5864 self.assertEqual(
59 ret_password, "",
60 "Incorrect password for username: '%s' on service: '%s'. '%s' != '%s'"
61 % (service, username, ret_password, ""))
62 ret_password = keyring.get_password('Python', username+'@'+service)
65 ret_password, "",
66 "Incorrect password for username: '%s' on service: '%s'. '%s' != '%s'"
67 % (service, username, ret_password, ""))
68 ret_password = keyring.get_password('Python', username + '@' + service)
6369 self.assertEqual(
64 ret_password, None,
65 "Not 'None' password returned for username: '%s' on service: '%s'. '%s' != '%s'. Passwords from old folder should be deleted during migration."
66 % (service, username, ret_password, None))
70 ret_password, None,
71 "Not 'None' password returned for username: '%s' on service: '%s'. '%s' != '%s'. Passwords from old folder should be deleted during migration."
72 % (service, username, ret_password, None))
6773
6874
6975 @unittest.skipUnless(kwallet.DBusKeyringKWallet4.viable,
70 "KWallet4 unavailable")
76 "KWallet4 unavailable")
7177 class DBusKWallet4TestCase(DBusKWalletTestCase):
7278 def init_keyring(self):
7379 return kwallet.DBusKeyringKWallet4()
2525 # ensure no-ascii chars slip by - watch your editor!
2626 assert min(ord(char) for char in UNICODE_CHARS) > 127
2727
28
2829 def is_ascii_printable(s):
2930 return all(32 <= ord(c) < 127 for c in s)
31
3032
3133 class BackendBasicTests(object):
3234 """Test for the keyring's basic functions. password_set and password_get
9193 def test_delete_one_in_group(self):
9294 username1 = random_string(20, self.DIFFICULT_CHARS)
9395 username2 = random_string(20, self.DIFFICULT_CHARS)
94 password = random_string(20, self.DIFFICULT_CHARS)
95 service = random_string(20, self.DIFFICULT_CHARS)
96 password = random_string(20, self.DIFFICULT_CHARS)
97 service = random_string(20, self.DIFFICULT_CHARS)
9698 self.keyring.set_password(service, username1, password)
9799 self.set_password(service, username2, password)
98100 self.keyring.delete_password(service, username1)
109111
110112 def test_unicode_and_ascii_chars(self):
111113 source = (random_string(10, UNICODE_CHARS) + random_string(10) +
112 random_string(10, self.DIFFICULT_CHARS))
114 random_string(10, self.DIFFICULT_CHARS))
113115 password = random_string(20, source)
114116 username = random_string(20, source)
115117 service = random_string(20, source)
33 import random
44 import string
55
6
67 class ImportKiller(object):
78 "Context manager to make an import of a given name or names fail."
9
810 def __init__(self, *names):
911 self.names = names
12
1013 def find_module(self, fullname, path=None):
1114 if fullname in self.names:
1215 return self
16
1317 def load_module(self, fullname):
1418 assert fullname in self.names
1519 raise ImportError(fullname)
20
1621 def __enter__(self):
1722 self.original = {}
1823 for name in self.names:
1924 self.original[name] = sys.modules.pop(name, None)
2025 sys.meta_path.insert(0, self)
26
2127 def __exit__(self, *args):
2228 sys.meta_path.remove(self)
2329 for key, value in self.original.items():
2430 if value is not None:
2531 sys.modules[key] = value
32
2633
2734 @contextlib.contextmanager
2835 def NoNoneDictMutator(destination, **changes):
5158 """A context manager to temporarily change the os.environ"""
5259 return NoNoneDictMutator(os.environ, **changes)
5360
61
5462 ALPHABET = string.ascii_letters + string.digits
5563
56 def random_string(k, source = ALPHABET):
64
65 def random_string(k, source=ALPHABET):
5766 """Generate a random string with length <i>k</i>
5867 """
5968 result = ''
00 import functools
1
12
23 def once(func):
34 """
2021 return func.always_returns
2122 return functools.wraps(func)(wrapper)
2223
24
2325 def suppress_exceptions(callables, exceptions=Exception):
2426 """
2527 yield the results of calling each element of callables, suppressing
1414 if PY3:
1515 def u(s):
1616 return s
17
1718 def _unichr(c):
1819 return chr(c)
1920 else:
2021 def u(s):
2122 return s.decode('utf-8')
23
2224 def _unichr(c):
2325 return unichr(c)
2426
2931
3032 ESCAPE_FMT = "_%02X"
3133
34
3235 def _escape_char(c):
3336 "Single char escape. Return the char, escaped if not already legal"
3437 if isinstance(c, int):
3538 c = _unichr(c)
3639 return c if c in LEGAL_CHARS else ESCAPE_FMT % ord(c)
40
3741
3842 def escape(value):
3943 """
4246 """
4347 return "".join(_escape_char(c) for c in value.encode('utf-8'))
4448
49
4550 def _unescape_code(regex_match):
4651 ordinal = int(regex_match.group('code'), 16)
4752 if sys.version_info >= (3,):
4853 return bytes([ordinal])
4954 return chr(ordinal)
55
5056
5157 def unescape(value):
5258 """
66 def _settings_root_XP():
77 return os.path.join(os.environ['USERPROFILE'], 'Local Settings')
88
9
910 def _settings_root_Vista():
1011 return os.environ.get('LOCALAPPDATA', os.environ.get('ProgramData', '.'))
12
1113
1214 def _data_root_Windows():
1315 release, version, csd, ptype = platform.win32_ver()
1416 root = _settings_root_XP() if release == 'XP' else _settings_root_Vista()
1517 return os.path.join(root, 'Python Keyring')
18
1619
1720 def _data_root_Linux():
1821 """
2326 root = os.environ.get('XDG_DATA_HOME', None) or fallback
2427 return os.path.join(root, 'python_keyring')
2528
29
2630 _config_root_Windows = _data_root_Windows
31
2732
2833 def _check_old_config_root():
2934 """
3944 config_file_old = os.path.join(_data_root_Linux(), 'keyringrc.cfg')
4045 if os.path.isfile(config_file_old) and not os.path.isfile(config_file_new):
4146 msg = ("Keyring config exists only in the old location "
42 "{config_file_old} and should be moved to {config_file_new} "
43 "to work with this version of keyring.")
47 "{config_file_old} and should be moved to {config_file_new} "
48 "to work with this version of keyring.")
4449 raise RuntimeError(msg.format(**locals()))
50
4551
4652 def _config_root_Linux():
4753 """
5460 root = os.environ.get(key, None) or fallback
5561 return os.path.join(root, 'python_keyring')
5662
63
5764 # by default, use Unix convention
5865 data_root = globals().get('_data_root_' + platform.system(), _data_root_Linux)
59 config_root = globals().get('_config_root' + platform.system(), _config_root_Linux)
66 config_root = globals().get(
67 '_config_root' +
68 platform.system(),
69 _config_root_Linux)
00 from collections import Callable
1
12
23 class ClassProperty(property):
34 """
1718 >>> YourClass.skillz
1819 False
1920 """
21
2022 def __get__(self, cls, owner):
2123 return self.fget.__get__(None, owner)()
2224
2325 # borrowed from jaraco.util.dictlib
26
27
2428 class NonDataProperty(object):
2529 """Much like the property builtin, but only implements __get__,
2630 making it a non-data property, and can be subsequently reset.
0 Metadata-Version: 1.1
0 Metadata-Version: 1.2
11 Name: keyring
2 Version: 10.4.0
2 Version: 10.5.0
33 Summary: Store and access your passwords safely.
44 Home-page: https://github.com/jaraco/keyring
55 Author: Jason R. Coombs
66 Author-email: jaraco@jaraco.com
77 License: UNKNOWN
8 Description-Content-Type: UNKNOWN
89 Description: .. image:: https://img.shields.io/pypi/v/keyring.svg
910 :target: https://pypi.org/project/keyring
1011
1112 .. image:: https://img.shields.io/pypi/pyversions/keyring.svg
1213
13 .. image:: https://img.shields.io/pypi/dm/keyring.svg
14
1514 .. image:: https://img.shields.io/travis/jaraco/keyring/master.svg
1615 :target: http://travis-ci.org/jaraco/keyring
1716
17 .. image:: https://readthedocs.org/projects/keyring/badge/?version=latest
18 :target: http://keyring.readthedocs.io/en/latest/?badge=latest
1819
1920 =======================================
2021 Installing and Using Python Keyring Lib
2627 What is Python keyring lib?
2728 ---------------------------
2829
29 The Python keyring lib provides a easy way to access the system keyring service
30 The Python keyring lib provides an easy way to access the system keyring service
3031 from python. It can be used in any application that needs safe password storage.
3132
3233 The keyring library is licensed under both the `MIT license
4142 `secretstorage <https://pypi.python.org/pypi/secretstorage>`_)
4243 * `KWallet <https://en.wikipedia.org/wiki/KWallet>`_
4344 (requires `dbus <https://pypi.python.org/pypi/dbus-python>`_)
44 * `Windows Credential Vault
45 <http://windows.microsoft.com/en-us/windows7/what-is-credential-manager>`_
45 * `Windows Credential Locker
46 <https://docs.microsoft.com/en-us/windows/uwp/security/credential-locker>`_
4647
4748 Other keyring implementations are provided in the `keyrings.alt package`_.
4849
219220 # invoke the keyring lib
220221 try:
221222 keyring.set_password("demo-service", "tarek", "passexample")
222 print("password stored sucessfully")
223 print("password stored successfully")
223224 except keyring.errors.PasswordSetError:
224225 print("failed to store password")
225226 print("password", keyring.get_password("demo-service", "tarek"))
361362 Classifier: Programming Language :: Python :: 3.4
362363 Classifier: Programming Language :: Python :: 3.5
363364 Classifier: Programming Language :: Python :: 3.6
365 Requires-Python: >=2.7
22 .travis-osx
33 .travis.yml
44 CHANGES.rst
5 LICENSE
56 README.rst
67 appveyor.yml
78 conftest.py
1212 [testing]
1313 pytest>=2.8
1414 pytest-sugar
15 collective.checkdocs
11 release = dists upload
22 dists = clean --all sdist bdist_wheel
33
4 [wheel]
4 [bdist_wheel]
55 universal = 1
66
77 [egg_info]
1010
1111 name = 'keyring'
1212 description = 'Store and access your passwords safely.'
13 nspkg_technique = 'native'
14 """
15 Does this package use "native" namespace packages or
16 pkg_resources "managed" namespace packages?
17 """
1318
1419 params = dict(
1520 name=name,
2328 url="https://github.com/jaraco/" + name,
2429 packages=setuptools.find_packages(),
2530 include_package_data=True,
26 namespace_packages=name.split('.')[:-1],
31 namespace_packages=(
32 name.split('.')[:-1] if nspkg_technique == 'managed'
33 else []
34 ),
35 python_requires='>=2.7',
2736 install_requires=[
2837 ],
2938 extras_require={
3645 'testing': [
3746 'pytest>=2.8',
3847 'pytest-sugar',
48 'collective.checkdocs',
3949 ],
4050 'docs': [
4151 'sphinx',
6777 },
6878 )
6979 if __name__ == '__main__':
70 setuptools.setup(**params)
80 setuptools.setup(**params)
00 import pkg_resources
1
12
23 def test_entry_point():
34 """
11 minversion = 2.4
22
33 [testenv]
4 commands = py.test {posargs}
4 commands =
5 py.test {posargs}
6 python setup.py checkdocs
57 usedevelop = True
68 extras = testing