Hello community,

here is the log from the commit of package python-keyrings.alt for 
openSUSE:Factory checked in at 2017-01-25 23:32:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-keyrings.alt (Old)
 and      /work/SRC/openSUSE:Factory/.python-keyrings.alt.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-keyrings.alt"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-keyrings.alt/python-keyrings.alt.changes  
2016-07-21 07:55:19.000000000 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-keyrings.alt.new/python-keyrings.alt.changes 
    2017-01-25 23:32:31.327686517 +0100
@@ -1,0 +2,22 @@
+Mon Jan 23 21:09:11 UTC 2017 - dmuel...@suse.com
+
+- fix source url
+
+-------------------------------------------------------------------
+Sat Jan 14 18:57:11 UTC 2017 - h...@urpla.net
+
+- update to version 2.0
+  - #12: Drop kwallet support, now superseded by the dual kwallet support in
+    keyring. (from me ;)
+
+- update to version 1.3
+  - #9: Moved base file backend functionality from 'keyrings.alt.file' to
+    'keyrings.alt.base_file'. This allows the 'Windows' module to no longer
+    trigger a circular import with the 'file' module.
+
+- update to version 1.2
+  - Updated project skeleton. Tests now run under tox. Tagged commits are
+    automatically released to PyPI.
+  - #6: Added license file.
+
+-------------------------------------------------------------------

Old:
----
  keyrings.alt-1.1.1.tar.gz

New:
----
  keyrings.alt-2.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-keyrings.alt.spec ++++++
--- /var/tmp/diff_new_pack.WVUYQI/_old  2017-01-25 23:32:31.731625643 +0100
+++ /var/tmp/diff_new_pack.WVUYQI/_new  2017-01-25 23:32:31.731625643 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-keyrings.alt
 #
-# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
 # Copyright (c) 2016 LISA GmbH, Bingen, Germany.
 #
 # All modifications and additions to the file contributed by third parties
@@ -17,36 +17,37 @@
 #
 
 
-%if 0%{?suse_version} && 0%{?suse_version} <= 1110
-%{!?python_sitelib: %global python_sitelib %(python -c "from 
distutils.sysconfig import get_python_lib; print get_python_lib()")}
-%else
-BuildArch:      noarch
-%endif
 Name:           python-keyrings.alt
-Version:        1.1.1
+Version:        2.0
 Release:        0
 Summary:        Alternate keyring implementations
 License:        MIT
 Group:          Development/Languages/Python
 Url:            https://github.com/jaraco/keyrings.alt
-Source:         
https://pypi.python.org/packages/27/d0/9207bf58de11735fe2239deaecb9eae1084e2887077a700ac8aa27bd8159/keyrings.alt-%{version}.tar.gz
+Source:         
https://pypi.io/packages/source/k/keyrings.alt/keyrings.alt-%{version}.tar.gz
 BuildRequires:  python-devel
-BuildRequires:  python-fs
-BuildRequires:  python-gdata
-BuildRequires:  python-keyczar
 BuildRequires:  python-keyring
-# Testing requirements
-BuildRequires:  python-mock
 BuildRequires:  python-pycrypto
 BuildRequires:  python-pytest-runner
 BuildRequires:  python-setuptools
 BuildRequires:  python-setuptools_scm
-Requires:       python-fs
-Requires:       python-gdata
+Requires:       python-pycrypto
+BuildRequires:  python-keyczar
 Requires:       python-keyczar
+BuildRequires:  python-gdata
+Requires:       python-gdata
+BuildRequires:  python-fs
+Requires:       python-fs
+BuildRequires:  python-keyring
 Requires:       python-keyring
-Requires:       python-pycrypto
+# Testing requirements
+BuildRequires:  python-mock
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
+%if 0%{?suse_version} && 0%{?suse_version} <= 1110
+%{!?python_sitelib: %global python_sitelib %(python -c "from 
distutils.sysconfig import get_python_lib; print get_python_lib()")}
+%else
+BuildArch:      noarch
+%endif
 
 %description
 Alternate keyring backend implementations for use with the

++++++ keyrings.alt-1.1.1.tar.gz -> keyrings.alt-2.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/.gitignore 
new/keyrings.alt-2.0/.gitignore
--- old/keyrings.alt-1.1.1/.gitignore   2016-01-23 15:09:27.000000000 +0100
+++ new/keyrings.alt-2.0/.gitignore     1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +0,0 @@
-dist/
-build/
-.eggs/
-*.pyc
-*.egg-info/
-.cache/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/.hgtags 
new/keyrings.alt-2.0/.hgtags
--- old/keyrings.alt-1.1.1/.hgtags      2016-03-01 20:24:53.000000000 +0100
+++ new/keyrings.alt-2.0/.hgtags        1970-01-01 01:00:00.000000000 +0100
@@ -1,4 +0,0 @@
-b3173ad03e2b87d50ab31eecc5e6e57e9963785d 1.0
-f9defd8cbdfabaeb1739fd02929f272ba7e4be73 1.0.1
-acdefb2c6c473bf6460004dbbe1f62280fcdeac8 1.1
-43b2bf00ab0477d3734932feb05ce6d533df255a 1.1.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/.travis.yml 
new/keyrings.alt-2.0/.travis.yml
--- old/keyrings.alt-1.1.1/.travis.yml  2016-01-14 11:58:15.000000000 +0100
+++ new/keyrings.alt-2.0/.travis.yml    2016-12-22 18:51:45.000000000 +0100
@@ -1,8 +1,23 @@
 sudo: false
 language: python
 python:
- - 2.7
- - 3.5
+- 2.7
+- 3.5
+install:
+- pip install tox "setuptools>=28.2"
 script:
- - pip install -U pytest
- - python setup.py test
+- tox
+branches:
+  except:
+  - skeleton
+deploy:
+  provider: pypi
+  server: https://upload.pypi.org/legacy/
+  on:
+    tags: true
+    all_branches: true
+    python: 3.5
+  user: jaraco
+  distributions: dists
+  password:
+    secure: 
iRtbY9yEN8qwJ7wiycL8N5NdZhRDENT5M8Bkpm7YSN5OiM41LRwFYnHDoQhYpz9L/UdfbovgEvv1XsQX/o8XRTn5efmhXRgS/FY3cA7Ry0GG41hmk2fnAgYuivA8EGoPveS9CnbU71ikL0HjRHv93+7Pz1kyMEYXRUpbMZ16K74o1J1MLOoCdQXXlKWfYjqAV/BglWwjIkwXVmNM2JwGV7U2hJ8zjsX1Bn7XqsZdC2KB6jK1frVjEHDfbv3NLQYIzQYqGw8GMWa+9EGVfFzqPnQmUC3E5GA93rC1SceBUb2RDBfCUpyFkyin3lQ05EvyVJoIaZO56gJ9Py1XzzSinSTjylgTxvFWx4uweowv5oM9OWnV+3SsZDw5+55fW5CYiMjdqjLso83gTkc8jbDHeK73Yh0sju2+QnOejnMzKRaBtCBubUkL+TPjEzoeUYSKLgW+iVHIKNKEKNME/WLzNtEhQwEFbLD5u/0bmHMBFPt40cXv3kSz6tz7NSjCHyJbtsBnyadYWRQTTRoSPnNIt0P716feUY/R5/Am5TIo2ZHKkGbRkuqFcJoJYhKau2M24WkRA4og8uBSyliShovHkrbahe1MpbJ/ZtmIU583FQjxIlGQQtNPN4QTSnQ1fUpvyhQY89GupbSxuek7jlmxmIm9SgAy6w9PUDZ5FKuJzm4=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/CHANGES.rst 
new/keyrings.alt-2.0/CHANGES.rst
--- old/keyrings.alt-1.1.1/CHANGES.rst  2016-03-01 20:24:42.000000000 +0100
+++ new/keyrings.alt-2.0/CHANGES.rst    2016-12-22 18:51:45.000000000 +0100
@@ -1,3 +1,24 @@
+2.0
+===
+
+#12: Drop kwallet support, now superseded by the dual kwallet
+support in keyring.
+
+1.3
+===
+
+#9: Moved base file backend functionality from 'keyrings.alt.file'
+to 'keyrings.alt.base_file'. This allows the 'Windows' module to
+no longer trigger a circular import with the 'file' module.
+
+1.2
+===
+
+Updated project skeleton. Tests now run under tox. Tagged
+commits are automatically released to PyPI.
+
+#6: Added license file.
+
 1.1.1
 =====
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/LICENSE 
new/keyrings.alt-2.0/LICENSE
--- old/keyrings.alt-1.1.1/LICENSE      1970-01-01 01:00:00.000000000 +0100
+++ new/keyrings.alt-2.0/LICENSE        2016-12-22 18:51:45.000000000 +0100
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2016 Jason R. Coombs <jar...@jaraco.com>
+
+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:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+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.
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/PKG-INFO 
new/keyrings.alt-2.0/PKG-INFO
--- old/keyrings.alt-1.1.1/PKG-INFO     2016-03-01 20:25:02.000000000 +0100
+++ new/keyrings.alt-2.0/PKG-INFO       2016-12-22 18:53:14.000000000 +0100
@@ -1,17 +1,34 @@
 Metadata-Version: 1.1
 Name: keyrings.alt
-Version: 1.1.1
+Version: 2.0
 Summary: Alternate keyring implementations
 Home-page: https://github.com/jaraco/keyrings.alt
 Author: Jason R. Coombs
 Author-email: jar...@jaraco.com
 License: UNKNOWN
-Description: keyrings.alt
-        ============
+Description: .. image:: https://img.shields.io/pypi/v/keyrings.alt.svg
+           :target: https://pypi.org/project/keyrings.alt
+        
+        .. image:: https://img.shields.io/pypi/pyversions/keyrings.alt.svg
+        
+        .. image:: https://img.shields.io/pypi/dm/keyrings.alt.svg
+        
+        .. image:: https://img.shields.io/travis/jaraco/keyrings.alt/master.svg
+           :target: http://travis-ci.org/jaraco/keyrings.alt
         
         Alternate keyring backend implementations for use with the
         `keyring package <https://pypi.python.org/pypi/keyring>`_.
         
+        Docs
+        ====
+        
+        There's `no good mechanism for publishing documentation
+        <https://github.com/pypa/python-packaging-user-guide/pull/266>`_
+        easily. If there's a documentation link above, it's probably
+        stale because PyPI-based documentation is deprecated. This
+        project may have documentation published at ReadTheDocs, but
+        probably not. Good luck finding it.
+        
 Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Intended Audience :: Developers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/README.rst 
new/keyrings.alt-2.0/README.rst
--- old/keyrings.alt-1.1.1/README.rst   2016-01-14 16:58:19.000000000 +0100
+++ new/keyrings.alt-2.0/README.rst     2016-12-22 18:51:45.000000000 +0100
@@ -1,5 +1,22 @@
-keyrings.alt
-============
+.. image:: https://img.shields.io/pypi/v/keyrings.alt.svg
+   :target: https://pypi.org/project/keyrings.alt
+
+.. image:: https://img.shields.io/pypi/pyversions/keyrings.alt.svg
+
+.. image:: https://img.shields.io/pypi/dm/keyrings.alt.svg
+
+.. image:: https://img.shields.io/travis/jaraco/keyrings.alt/master.svg
+   :target: http://travis-ci.org/jaraco/keyrings.alt
 
 Alternate keyring backend implementations for use with the
 `keyring package <https://pypi.python.org/pypi/keyring>`_.
+
+Docs
+====
+
+There's `no good mechanism for publishing documentation
+<https://github.com/pypa/python-packaging-user-guide/pull/266>`_
+easily. If there's a documentation link above, it's probably
+stale because PyPI-based documentation is deprecated. This
+project may have documentation published at ReadTheDocs, but
+probably not. Good luck finding it.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/docs/conf.py 
new/keyrings.alt-2.0/docs/conf.py
--- old/keyrings.alt-1.1.1/docs/conf.py 2016-01-14 16:58:26.000000000 +0100
+++ new/keyrings.alt-2.0/docs/conf.py   2016-12-22 18:51:45.000000000 +0100
@@ -1,10 +1,11 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
-import setuptools_scm
+import pkg_resources
 
 extensions = [
     'sphinx.ext.autodoc',
+    'rst.linker',
 ]
 
 # General information about the project.
@@ -12,8 +13,27 @@
 copyright = '2016 Jason R. Coombs'
 
 # The short X.Y version.
-version = setuptools_scm.get_version(root='..', relative_to=__file__)
+version = pkg_resources.require(project)[0].version
 # The full version, including alpha/beta/rc tags.
 release = version
 
 master_doc = 'index'
+
+link_files = {
+       '../CHANGES.rst': dict(
+               using=dict(
+                       GH='https://github.com',
+                       project=project,
+               ),
+               replace=[
+                       dict(
+                               pattern=r"(Issue )?#(?P<issue>\d+)",
+                               url='{GH}/jaraco/{project}/issues/{issue}',
+                       ),
+                       dict(
+                               
pattern=r"^(?m)((?P<scm_version>v?\d+(\.\d+){1,2}))\n[-=]+\n",
+                               with_scm="{text}\n{rev[timestamp]:%d %b %Y}\n",
+                       ),
+               ],
+       ),
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/docs/history.rst 
new/keyrings.alt-2.0/docs/history.rst
--- old/keyrings.alt-1.1.1/docs/history.rst     2016-01-14 11:58:15.000000000 
+0100
+++ new/keyrings.alt-2.0/docs/history.rst       2016-12-22 18:51:45.000000000 
+0100
@@ -5,4 +5,4 @@
 History
 *******
 
-.. include:: ../CHANGES.rst
+.. include:: ../CHANGES (links).rst
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/docs/index.rst 
new/keyrings.alt-2.0/docs/index.rst
--- old/keyrings.alt-1.1.1/docs/index.rst       2016-01-14 16:59:51.000000000 
+0100
+++ new/keyrings.alt-2.0/docs/index.rst 2016-12-22 18:51:45.000000000 +0100
@@ -27,11 +27,6 @@
     :undoc-members:
     :show-inheritance:
 
-.. automodule:: keyrings.alt.kwallet
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
 .. automodule:: keyrings.alt.multi
     :members:
     :undoc-members:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/docs/requirements.txt 
new/keyrings.alt-2.0/docs/requirements.txt
--- old/keyrings.alt-1.1.1/docs/requirements.txt        1970-01-01 
01:00:00.000000000 +0100
+++ new/keyrings.alt-2.0/docs/requirements.txt  2016-12-22 18:51:45.000000000 
+0100
@@ -0,0 +1 @@
+rst.linker
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/keyrings/alt/Windows.py 
new/keyrings.alt-2.0/keyrings/alt/Windows.py
--- old/keyrings.alt-1.1.1/keyrings/alt/Windows.py      2016-01-14 
12:15:59.000000000 +0100
+++ new/keyrings.alt-2.0/keyrings/alt/Windows.py        2016-12-22 
18:51:45.000000000 +0100
@@ -6,7 +6,7 @@
 from keyring.util import properties
 from keyring.backend import KeyringBackend
 from keyring.errors import PasswordDeleteError, ExceptionRaisedContext
-from . import file
+from . import file_base
 
 try:
     # prefer pywin32-ctypes
@@ -56,7 +56,7 @@
         _win_crypto.__name__
     return not bool(exc)
 
-class EncryptedKeyring(file.BaseKeyring):
+class EncryptedKeyring(file_base.Keyring):
     """
     A File-based keyring secured by Windows Crypto API.
     """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/keyrings/alt/file.py 
new/keyrings.alt-2.0/keyrings/alt/file.py
--- old/keyrings.alt-1.1.1/keyrings/alt/file.py 2016-01-14 19:27:15.000000000 
+0100
+++ new/keyrings.alt-2.0/keyrings/alt/file.py   2016-12-22 18:51:45.000000000 
+0100
@@ -5,142 +5,16 @@
 import base64
 import sys
 import json
-import abc
 
 from keyring.py27compat import configparser
 
-from keyring.errors import PasswordDeleteError
-from keyring.backend import KeyringBackend
-from keyring.util import platform_, properties
+from keyring.util import properties
 from keyring.util.escape import escape as escape_for_ini
 
+from . import file_base
 
-class FileBacked(object):
-    @abc.abstractproperty
-    def filename(self):
-        """
-        The filename used to store the passwords.
-        """
-
-    @properties.NonDataProperty
-    def file_path(self):
-        """
-        The path to the file where passwords are stored. This property
-        may be overridden by the subclass or at the instance level.
-        """
-        return os.path.join(platform_.data_root(), self.filename)
-
-    def __repr__(self):
-        tmpl = "<{self.__class__.__name__} at {self.file_path}>"
-        return tmpl.format(**locals())
-
-
-class BaseKeyring(FileBacked, KeyringBackend):
-    """
-    BaseKeyring is a file-based implementation of keyring.
 
-    This keyring stores the password directly in the file and provides methods
-    which may be overridden by subclasses to support
-    encryption and decryption. The encrypted payload is stored in base64
-    format.
-    """
-
-    @abc.abstractmethod
-    def encrypt(self, password):
-        """
-        Given a password (byte string), return an encrypted byte string.
-        """
-
-    @abc.abstractmethod
-    def decrypt(self, password_encrypted):
-        """
-        Given a password encrypted by a previous call to `encrypt`, return
-        the original byte string.
-        """
-
-    def get_password(self, service, username):
-        """
-        Read the password from the file.
-        """
-        service = escape_for_ini(service)
-        username = escape_for_ini(username)
-
-        # load the passwords from the file
-        config = configparser.RawConfigParser()
-        if os.path.exists(self.file_path):
-            config.read(self.file_path)
-
-        # fetch the password
-        try:
-            password_base64 = config.get(service, username).encode()
-            # decode with base64
-            password_encrypted = base64.decodestring(password_base64)
-            # decrypted the password
-            password = self.decrypt(password_encrypted).decode('utf-8')
-        except (configparser.NoOptionError, configparser.NoSectionError):
-            password = None
-        return password
-
-    def set_password(self, service, username, password):
-        """Write the password in the file.
-        """
-        service = escape_for_ini(service)
-        username = escape_for_ini(username)
-
-        # encrypt the password
-        password_encrypted = self.encrypt(password.encode('utf-8'))
-        # encode with base64
-        password_base64 = base64.encodestring(password_encrypted).decode()
-
-        # ensure the file exists
-        self._ensure_file_path()
-
-        # load the keyring from the disk
-        config = configparser.RawConfigParser()
-        config.read(self.file_path)
-
-        # update the keyring with the password
-        if not config.has_section(service):
-            config.add_section(service)
-        config.set(service, username, password_base64)
-
-        # save the keyring back to the file
-        with open(self.file_path, 'w') as config_file:
-            config.write(config_file)
-
-    def _ensure_file_path(self):
-        """
-        Ensure the storage path exists.
-        If it doesn't, create it with "go-rwx" permissions.
-        """
-        storage_root = os.path.dirname(self.file_path)
-        if storage_root and not os.path.isdir(storage_root):
-            os.makedirs(storage_root)
-        if not os.path.isfile(self.file_path):
-            # create the file without group/world permissions
-            with open(self.file_path, 'w'):
-                pass
-            user_read_write = 0o600
-            os.chmod(self.file_path, user_read_write)
-
-    def delete_password(self, service, username):
-        """Delete the password for the username of the service.
-        """
-        service = escape_for_ini(service)
-        username = escape_for_ini(username)
-        config = configparser.RawConfigParser()
-        if os.path.exists(self.file_path):
-            config.read(self.file_path)
-        try:
-            if not config.remove_option(service, username):
-                raise PasswordDeleteError("Password not found")
-        except configparser.NoSectionError:
-            raise PasswordDeleteError("Password not found")
-        # update the file
-        with open(self.file_path, 'w') as config_file:
-            config.write(config_file)
-
-class PlaintextKeyring(BaseKeyring):
+class PlaintextKeyring(file_base.Keyring):
     """Simple File Keyring with no encryption"""
 
     priority = .5
@@ -158,6 +32,7 @@
         """
         return password_encrypted
 
+
 class Encrypted(object):
     """
     PyCrypto-backed Encryption support
@@ -189,7 +64,7 @@
             return password
 
 
-class EncryptedKeyring(Encrypted, BaseKeyring):
+class EncryptedKeyring(Encrypted, file_base.Keyring):
     """PyCrypto File Keyring"""
 
     filename = 'crypted_pass.cfg'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/keyrings/alt/file_base.py 
new/keyrings.alt-2.0/keyrings/alt/file_base.py
--- old/keyrings.alt-1.1.1/keyrings/alt/file_base.py    1970-01-01 
01:00:00.000000000 +0100
+++ new/keyrings.alt-2.0/keyrings/alt/file_base.py      2016-12-22 
18:51:45.000000000 +0100
@@ -0,0 +1,138 @@
+from __future__ import with_statement
+
+import os
+import base64
+import abc
+
+from keyring.py27compat import configparser
+
+from keyring.errors import PasswordDeleteError
+from keyring.backend import KeyringBackend
+from keyring.util import platform_, properties
+from keyring.util.escape import escape as escape_for_ini
+
+
+class FileBacked(object):
+    @abc.abstractproperty
+    def filename(self):
+        """
+        The filename used to store the passwords.
+        """
+
+    @properties.NonDataProperty
+    def file_path(self):
+        """
+        The path to the file where passwords are stored. This property
+        may be overridden by the subclass or at the instance level.
+        """
+        return os.path.join(platform_.data_root(), self.filename)
+
+    def __repr__(self):
+        tmpl = "<{self.__class__.__name__} at {self.file_path}>"
+        return tmpl.format(**locals())
+
+
+class Keyring(FileBacked, KeyringBackend):
+    """
+    BaseKeyring is a file-based implementation of keyring.
+
+    This keyring stores the password directly in the file and provides methods
+    which may be overridden by subclasses to support
+    encryption and decryption. The encrypted payload is stored in base64
+    format.
+    """
+
+    @abc.abstractmethod
+    def encrypt(self, password):
+        """
+        Given a password (byte string), return an encrypted byte string.
+        """
+
+    @abc.abstractmethod
+    def decrypt(self, password_encrypted):
+        """
+        Given a password encrypted by a previous call to `encrypt`, return
+        the original byte string.
+        """
+
+    def get_password(self, service, username):
+        """
+        Read the password from the file.
+        """
+        service = escape_for_ini(service)
+        username = escape_for_ini(username)
+
+        # load the passwords from the file
+        config = configparser.RawConfigParser()
+        if os.path.exists(self.file_path):
+            config.read(self.file_path)
+
+        # fetch the password
+        try:
+            password_base64 = config.get(service, username).encode()
+            # decode with base64
+            password_encrypted = base64.decodestring(password_base64)
+            # decrypted the password
+            password = self.decrypt(password_encrypted).decode('utf-8')
+        except (configparser.NoOptionError, configparser.NoSectionError):
+            password = None
+        return password
+
+    def set_password(self, service, username, password):
+        """Write the password in the file.
+        """
+        service = escape_for_ini(service)
+        username = escape_for_ini(username)
+
+        # encrypt the password
+        password_encrypted = self.encrypt(password.encode('utf-8'))
+        # encode with base64
+        password_base64 = base64.encodestring(password_encrypted).decode()
+
+        # ensure the file exists
+        self._ensure_file_path()
+
+        # load the keyring from the disk
+        config = configparser.RawConfigParser()
+        config.read(self.file_path)
+
+        # update the keyring with the password
+        if not config.has_section(service):
+            config.add_section(service)
+        config.set(service, username, password_base64)
+
+        # save the keyring back to the file
+        with open(self.file_path, 'w') as config_file:
+            config.write(config_file)
+
+    def _ensure_file_path(self):
+        """
+        Ensure the storage path exists.
+        If it doesn't, create it with "go-rwx" permissions.
+        """
+        storage_root = os.path.dirname(self.file_path)
+        if storage_root and not os.path.isdir(storage_root):
+            os.makedirs(storage_root)
+        if not os.path.isfile(self.file_path):
+            # create the file without group/world permissions
+            with open(self.file_path, 'w'):
+                pass
+            user_read_write = 0o600
+            os.chmod(self.file_path, user_read_write)
+
+    def delete_password(self, service, username):
+        """Delete the password for the username of the service.
+        """
+        service = escape_for_ini(service)
+        username = escape_for_ini(username)
+        config = configparser.RawConfigParser()
+        if os.path.exists(self.file_path):
+            config.read(self.file_path)
+        try:
+            if not config.remove_option(service, username):
+                raise PasswordDeleteError("Password not found")
+        except configparser.NoSectionError:
+            raise PasswordDeleteError("Password not found")
+        # update the file
+        with open(self.file_path, 'w') as config_file:
+            config.write(config_file)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/keyrings/alt/kwallet.py 
new/keyrings.alt-2.0/keyrings/alt/kwallet.py
--- old/keyrings.alt-1.1.1/keyrings/alt/kwallet.py      2016-01-14 
12:15:59.000000000 +0100
+++ new/keyrings.alt-2.0/keyrings/alt/kwallet.py        1970-01-01 
01:00:00.000000000 +0100
@@ -1,114 +0,0 @@
-from __future__ import absolute_import
-
-import os
-import sys
-
-from keyring.py27compat import unicode_str
-from keyring.backend import KeyringBackend
-from keyring.errors import PasswordDeleteError
-from keyring.errors import PasswordSetError, ExceptionRaisedContext
-from keyring.util import properties
-
-# mixing Qt4 & Qt5 causes errors and may segfault
-if 'PyQt5' not in sys.modules:
-    try:
-        from PyKDE4.kdeui import KWallet
-        from PyQt4 import QtGui
-    except ImportError:
-        pass
-
-kwallet = None
-
-def open_kwallet(kwallet_module=None, qt_module=None):
-
-    # If we specified the kwallet_module and/or qt_module, surely we won't need
-    # the cached kwallet object...
-    if kwallet_module is None and qt_module is None:
-        global kwallet
-        if not kwallet is None:
-            return kwallet
-
-    # Allow for the injection of module-like objects for testing purposes.
-    if kwallet_module is None:
-        kwallet_module = KWallet.Wallet
-    if qt_module is None:
-        qt_module = QtGui
-
-    # KDE wants us to instantiate an application object.
-    app = None
-    if qt_module.qApp.instance() == None:
-        app = qt_module.QApplication([])
-    try:
-        window = qt_module.QWidget()
-        kwallet = kwallet_module.openWallet(
-            kwallet_module.NetworkWallet(),
-            window.winId(),
-            kwallet_module.Synchronous)
-        if kwallet is not None:
-            if not kwallet.hasFolder('Python'):
-                kwallet.createFolder('Python')
-            kwallet.setFolder('Python')
-            return kwallet
-    finally:
-        if app:
-            app.exit()
-
-class QtKeyring(KeyringBackend):
-    """KDE KWallet"""
-
-    @properties.ClassProperty
-    @classmethod
-    def priority(cls):
-        with ExceptionRaisedContext() as exc:
-            KWallet.__name__
-        if exc:
-            raise RuntimeError("KDE libraries not available")
-        if "DISPLAY" not in os.environ:
-            raise RuntimeError("cannot connect to X server")
-        # Infer if KDE environment is active based on environment vars.
-        # TODO: Does PyKDE provide a better indicator?
-        kde_session_keys = (
-            'KDE_SESSION_ID', # most environments
-            'KDE_FULL_SESSION', # openSUSE
-        )
-        if not set(os.environ).intersection(kde_session_keys):
-            return 0
-        return 5
-
-    def get_password(self, service, username):
-        """Get password of the username for the service
-        """
-        key = username + '@' + service
-        network = KWallet.Wallet.NetworkWallet()
-        wallet = open_kwallet()
-        if wallet is None:
-            # the user pressed "cancel" when prompted to unlock their keyring.
-            return None
-        if wallet.keyDoesNotExist(network, 'Python', key):
-            return None
-
-        result = wallet.readPassword(key)[1]
-        # The string will be a PyQt4.QtCore.QString, so turn it into a unicode
-        # object.
-        return unicode_str(result)
-
-    def set_password(self, service, username, password):
-        """Set password for the username of the service
-        """
-        wallet = open_kwallet()
-        if wallet is None:
-            # the user pressed "cancel" when prompted to unlock their keyring.
-            raise PasswordSetError("Cancelled by user")
-        wallet.writePassword(username+'@'+service, password)
-
-    def delete_password(self, service, username):
-        """Delete the password for the username of the service.
-        """
-        key = username + '@' + service
-        wallet = open_kwallet()
-        if wallet is None:
-            # the user pressed "cancel" when prompted to unlock their keyring.
-            raise PasswordDeleteError("Cancelled by user")
-        if wallet.keyDoesNotExist(wallet.walletName(), 'Python', key):
-            raise PasswordDeleteError("Password not found")
-        wallet.removeEntry(key)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/keyrings.alt.egg-info/PKG-INFO 
new/keyrings.alt-2.0/keyrings.alt.egg-info/PKG-INFO
--- old/keyrings.alt-1.1.1/keyrings.alt.egg-info/PKG-INFO       2016-03-01 
20:25:02.000000000 +0100
+++ new/keyrings.alt-2.0/keyrings.alt.egg-info/PKG-INFO 2016-12-22 
18:53:14.000000000 +0100
@@ -1,17 +1,34 @@
 Metadata-Version: 1.1
 Name: keyrings.alt
-Version: 1.1.1
+Version: 2.0
 Summary: Alternate keyring implementations
 Home-page: https://github.com/jaraco/keyrings.alt
 Author: Jason R. Coombs
 Author-email: jar...@jaraco.com
 License: UNKNOWN
-Description: keyrings.alt
-        ============
+Description: .. image:: https://img.shields.io/pypi/v/keyrings.alt.svg
+           :target: https://pypi.org/project/keyrings.alt
+        
+        .. image:: https://img.shields.io/pypi/pyversions/keyrings.alt.svg
+        
+        .. image:: https://img.shields.io/pypi/dm/keyrings.alt.svg
+        
+        .. image:: https://img.shields.io/travis/jaraco/keyrings.alt/master.svg
+           :target: http://travis-ci.org/jaraco/keyrings.alt
         
         Alternate keyring backend implementations for use with the
         `keyring package <https://pypi.python.org/pypi/keyring>`_.
         
+        Docs
+        ====
+        
+        There's `no good mechanism for publishing documentation
+        <https://github.com/pypa/python-packaging-user-guide/pull/266>`_
+        easily. If there's a documentation link above, it's probably
+        stale because PyPI-based documentation is deprecated. This
+        project may have documentation published at ReadTheDocs, but
+        probably not. Good luck finding it.
+        
 Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Intended Audience :: Developers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/keyrings.alt.egg-info/SOURCES.txt 
new/keyrings.alt-2.0/keyrings.alt.egg-info/SOURCES.txt
--- old/keyrings.alt-1.1.1/keyrings.alt.egg-info/SOURCES.txt    2016-03-01 
20:25:02.000000000 +0100
+++ new/keyrings.alt-2.0/keyrings.alt.egg-info/SOURCES.txt      2016-12-22 
18:53:14.000000000 +0100
@@ -1,15 +1,16 @@
-.gitignore
-.hgtags
 .travis.yml
 CHANGES.rst
+LICENSE
 README.rst
 conftest.py
 pytest.ini
 setup.cfg
 setup.py
+tox.ini
 docs/conf.py
 docs/history.rst
 docs/index.rst
+docs/requirements.txt
 keyrings/__init__.py
 keyrings.alt.egg-info/PKG-INFO
 keyrings.alt.egg-info/SOURCES.txt
@@ -23,18 +24,18 @@
 keyrings/alt/__init__.py
 keyrings/alt/_win_crypto.py
 keyrings/alt/file.py
+keyrings/alt/file_base.py
 keyrings/alt/keyczar.py
-keyrings/alt/kwallet.py
 keyrings/alt/multi.py
 keyrings/alt/pyfs.py
 tests/__init__.py
 tests/mocks.py
+tests/requirements.txt
 tests/test_Gnome.py
 tests/test_Google.py
 tests/test_Windows.py
 tests/test_crypto.py
 tests/test_file.py
 tests/test_keyczar.py
-tests/test_kwallet.py
 tests/test_multi.py
 tests/test_pyfs.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/keyrings.alt-1.1.1/keyrings.alt.egg-info/entry_points.txt 
new/keyrings.alt-2.0/keyrings.alt.egg-info/entry_points.txt
--- old/keyrings.alt-1.1.1/keyrings.alt.egg-info/entry_points.txt       
2016-03-01 20:25:02.000000000 +0100
+++ new/keyrings.alt-2.0/keyrings.alt.egg-info/entry_points.txt 2016-12-22 
18:53:14.000000000 +0100
@@ -4,7 +4,6 @@
 Windows (alt) = keyrings.alt.Windows
 file = keyrings.alt.file
 keyczar = keyrings.alt.keyczar
-kwallet = keyrings.alt.kwallet
 multi = keyrings.alt.multi
 pyfs = keyrings.alt.pyfs
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/pytest.ini 
new/keyrings.alt-2.0/pytest.ini
--- old/keyrings.alt-1.1.1/pytest.ini   2016-01-14 11:58:15.000000000 +0100
+++ new/keyrings.alt-2.0/pytest.ini     2016-12-22 18:51:45.000000000 +0100
@@ -1,4 +1,4 @@
 [pytest]
-norecursedirs=*.egg .eggs dist build
+norecursedirs=dist build .tox
 addopts=--doctest-modules
 doctest_optionflags=ALLOW_UNICODE ELLIPSIS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/setup.cfg 
new/keyrings.alt-2.0/setup.cfg
--- old/keyrings.alt-1.1.1/setup.cfg    2016-03-01 20:25:02.000000000 +0100
+++ new/keyrings.alt-2.0/setup.cfg      2016-12-22 18:53:14.000000000 +0100
@@ -1,12 +1,15 @@
 [aliases]
-release = sdist bdist_wheel build_sphinx upload upload_docs
-test = pytest
+release = dists upload
+dists = clean --all sdist bdist_wheel
 
 [wheel]
 universal = 1
 
+[upload]
+repository = https://upload.pypi.org/legacy/
+
 [egg_info]
-tag_svn_revision = 0
 tag_build = 
 tag_date = 0
+tag_svn_revision = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/setup.py 
new/keyrings.alt-2.0/setup.py
--- old/keyrings.alt-1.1.1/setup.py     2016-01-23 15:09:27.000000000 +0100
+++ new/keyrings.alt-2.0/setup.py       2016-12-22 18:51:45.000000000 +0100
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
-# Generated by jaraco.develop 2.27.1
-# https://pypi.python.org/pypi/jaraco.develop
+
+# Project skeleton maintained at https://github.com/jaraco/skeleton
 
 import io
 import sys
@@ -10,51 +10,30 @@
 with io.open('README.rst', encoding='utf-8') as readme:
     long_description = readme.read()
 
-needs_pytest = {'pytest', 'test'}.intersection(sys.argv)
-pytest_runner = ['pytest_runner'] if needs_pytest else []
-needs_sphinx = {'release', 'build_sphinx', 
'upload_docs'}.intersection(sys.argv)
-sphinx = ['sphinx'] if needs_sphinx else []
-needs_wheel = {'release', 'bdist_wheel'}.intersection(sys.argv)
+needs_wheel = {'release', 'bdist_wheel', 'dists'}.intersection(sys.argv)
 wheel = ['wheel'] if needs_wheel else []
 
-test_requirements = [
-    'gdata',
-    'python-keyczar',
-    'fs>=0.5',
-    'pycrypto',
-]
-"dependencies for running tests"
-
-if sys.version_info >= (3, 0):
-    # gdata doesn't currently install on Python 3. Omit it also.
-    # http://code.google.com/p/gdata-python-client/issues/detail?id=229
-    test_requirements.remove('gdata')
-
-    # keyczar doesn't currently install on Python 3. Omit it also.
-    # http://code.google.com/p/keyczar/issues/detail?id=125
-    test_requirements.remove('python-keyczar')
+name = 'keyrings.alt'
+description = 'Alternate keyring implementations'
 
 setup_params = dict(
-    name='keyrings.alt',
+    name=name,
     use_scm_version=True,
     author="Jason R. Coombs",
     author_email="jar...@jaraco.com",
-    description="Alternate keyring implementations",
+    description=description or name,
     long_description=long_description,
-    url="https://github.com/jaraco/keyrings.alt";,
+    url="https://github.com/jaraco/"; + name,
     packages=setuptools.find_packages(exclude=['tests']),
     include_package_data=True,
-    namespace_packages=['keyrings'],
+    namespace_packages=name.split('.')[:-1],
     install_requires=[
     ],
     extras_require={
     },
     setup_requires=[
-        'setuptools_scm>=1.9',
-    ] + pytest_runner + sphinx + wheel,
-    tests_require=[
-        'keyring[test]',
-    ] + test_requirements,
+        'setuptools_scm>=1.15.0',
+    ] + wheel,
     classifiers=[
         "Development Status :: 5 - Production/Stable",
         "Intended Audience :: Developers",
@@ -68,7 +47,6 @@
             'Gnome = keyrings.alt.Gnome',
             'Google = keyrings.alt.Google',
             'keyczar = keyrings.alt.keyczar',
-            'kwallet = keyrings.alt.kwallet',
             'multi = keyrings.alt.multi',
             'pyfs = keyrings.alt.pyfs',
             'Windows (alt) = keyrings.alt.Windows',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/tests/requirements.txt 
new/keyrings.alt-2.0/tests/requirements.txt
--- old/keyrings.alt-1.1.1/tests/requirements.txt       1970-01-01 
01:00:00.000000000 +0100
+++ new/keyrings.alt-2.0/tests/requirements.txt 2016-12-22 18:51:45.000000000 
+0100
@@ -0,0 +1,15 @@
+pytest >= 2.8
+backports.unittest_mock
+keyring[test]
+
+fs>=0.5,<2
+pycrypto
+
+# gdata doesn't currently install on Python 3
+# http://code.google.com/p/gdata-python-client/issues/detail?id=229
+gdata; python_version=="2.7"
+
+
+# keyczar doesn't currently install on Python 3.
+# http://code.google.com/p/keyczar/issues/detail?id=125
+python-keyczar; python_version=="2.7"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/tests/test_crypto.py 
new/keyrings.alt-2.0/tests/test_crypto.py
--- old/keyrings.alt-1.1.1/tests/test_crypto.py 2016-01-14 12:35:21.000000000 
+0100
+++ new/keyrings.alt-2.0/tests/test_crypto.py   2016-12-22 18:51:45.000000000 
+0100
@@ -1,5 +1,5 @@
 import unittest
-import mock
+from unittest import mock
 
 from .test_file import FileKeyringTests
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/tests/test_kwallet.py 
new/keyrings.alt-2.0/tests/test_kwallet.py
--- old/keyrings.alt-1.1.1/tests/test_kwallet.py        2016-01-14 
12:27:14.000000000 +0100
+++ new/keyrings.alt-2.0/tests/test_kwallet.py  1970-01-01 01:00:00.000000000 
+0100
@@ -1,81 +0,0 @@
-import unittest
-
-from keyrings.alt import kwallet
-from keyring.tests.test_backend import BackendBasicTests
-
-def is_qt4_supported():
-    try:
-        __import__('PyQt4.QtGui')
-    except ImportError:
-        return False
-    return True
-
-@unittest.skipUnless(kwallet.QtKeyring.viable, "Need KWallet")
-class KDEKWalletTestCase(BackendBasicTests, unittest.TestCase):
-
-    def init_keyring(self):
-        return kwallet.QtKeyring()
-
-
-class UnOpenableKWallet(object):
-    """A module-like object used to test KDE wallet fall-back."""
-
-    Synchronous = None
-
-    def openWallet(self, *args):
-        return None
-
-    def NetworkWallet(self):
-        return None
-
-
-class FauxQtGui(object):
-    """A fake module-like object used in testing the open_kwallet function."""
-
-    class qApp:
-        @staticmethod
-        def instance():
-            pass
-
-    class QApplication(object):
-        def __init__(self, *args):
-            pass
-
-        def exit(self):
-            pass
-
-    class QWidget(object):
-        def __init__(self, *args):
-            pass
-
-        def winId(self):
-            pass
-
-class KDEWalletCanceledTestCase(unittest.TestCase):
-
-    def test_user_canceled(self):
-        # If the user cancels either the "enter your password to unlock the
-        # keyring" dialog or clicks "deny" on the "can this application access
-        # the wallet" dialog then openWallet() will return None.  The
-        # open_wallet() function should handle that eventuality by returning
-        # None to signify that the KWallet backend is not available.
-        self.assertEqual(
-            kwallet.open_kwallet(UnOpenableKWallet(), FauxQtGui()),
-            None)
-
-
-@unittest.skipUnless(kwallet.QtKeyring.viable and
-                     is_qt4_supported(),
-                     "Need KWallet and Qt4")
-class KDEKWalletInQApplication(unittest.TestCase):
-    def test_QApplication(self):
-        try:
-            from PyKDE4.kdeui import KWallet
-            from PyQt4.QtGui import QApplication
-        except:
-            return
-
-        app = QApplication([])
-        wallet = kwallet.open_kwallet()
-        self.assertIsInstance(wallet, KWallet.Wallet)
-        app.exit()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/keyrings.alt-1.1.1/tox.ini 
new/keyrings.alt-2.0/tox.ini
--- old/keyrings.alt-1.1.1/tox.ini      1970-01-01 01:00:00.000000000 +0100
+++ new/keyrings.alt-2.0/tox.ini        2016-12-22 18:51:45.000000000 +0100
@@ -0,0 +1,6 @@
+[testenv]
+deps =
+       -rtests/requirements.txt
+
+commands = py.test {posargs}
+usedevelop = True


Reply via email to