Hello community,

here is the log from the commit of package python-fasteners for 
openSUSE:Factory checked in at 2019-06-13 22:31:51
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-fasteners (Old)
 and      /work/SRC/openSUSE:Factory/.python-fasteners.new.4811 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-fasteners"

Thu Jun 13 22:31:51 2019 rev:6 rq:708374 version:0.15

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-fasteners/python-fasteners.changes        
2018-12-13 19:44:19.581021845 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-fasteners.new.4811/python-fasteners.changes  
    2019-06-13 22:31:55.268409065 +0200
@@ -1,0 +2,9 @@
+Fri Jun  7 12:56:34 UTC 2019 - Marketa Calabkova <[email protected]>
+
+- update to version 0.15
+  * Welcome back alive!
+  * Drop Python 2.6
+  * TST: check exitcodes of child processes
+  * TST: fix multiplatform support for process lock tests
+
+-------------------------------------------------------------------

Old:
----
  fasteners-0.14.1.tar.gz

New:
----
  fasteners-0.15.tar.gz

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

Other differences:
------------------
++++++ python-fasteners.spec ++++++
--- /var/tmp/diff_new_pack.AQmLK0/_old  2019-06-13 22:31:55.796408893 +0200
+++ /var/tmp/diff_new_pack.AQmLK0/_new  2019-06-13 22:31:55.796408893 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-fasteners
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %bcond_without tests
 Name:           python-fasteners
-Version:        0.14.1
+Version:        0.15
 Release:        0
 Summary:        A python package that provides useful locks
 License:        Apache-2.0

++++++ fasteners-0.14.1.tar.gz -> fasteners-0.15.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fasteners-0.14.1/PKG-INFO new/fasteners-0.15/PKG-INFO
--- old/fasteners-0.14.1/PKG-INFO       2015-11-13 07:47:25.000000000 +0100
+++ new/fasteners-0.15/PKG-INFO 2019-05-20 19:36:52.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: fasteners
-Version: 0.14.1
+Version: 0.15
 Summary: A python package that provides useful locks.
 Home-page: https://github.com/harlowja/fasteners
 Author: Joshua Harlow
@@ -12,6 +12,9 @@
         .. image:: https://travis-ci.org/harlowja/fasteners.png?branch=master
            :target: https://travis-ci.org/harlowja/fasteners
         
+        .. image:: https://ci.appveyor.com/api/projects/status/7d7aku32pimpadiv
+           :target: https://ci.appveyor.com/project/JoshuaHarlow/fasteners
+        
         .. image:: 
https://readthedocs.org/projects/fasteners/badge/?version=latest
            :target: https://readthedocs.org/projects/fasteners/?badge=latest
            :alt: Documentation Status
@@ -71,7 +74,7 @@
 Classifier: Operating System :: POSIX :: Linux
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
 Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fasteners-0.14.1/README.rst 
new/fasteners-0.15/README.rst
--- old/fasteners-0.14.1/README.rst     2015-08-08 10:15:25.000000000 +0200
+++ new/fasteners-0.15/README.rst       2019-04-26 21:18:09.000000000 +0200
@@ -4,6 +4,9 @@
 .. image:: https://travis-ci.org/harlowja/fasteners.png?branch=master
    :target: https://travis-ci.org/harlowja/fasteners
 
+.. image:: https://ci.appveyor.com/api/projects/status/7d7aku32pimpadiv
+   :target: https://ci.appveyor.com/project/JoshuaHarlow/fasteners
+
 .. image:: https://readthedocs.org/projects/fasteners/badge/?version=latest
    :target: https://readthedocs.org/projects/fasteners/?badge=latest
    :alt: Documentation Status
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fasteners-0.14.1/fasteners/_utils.py 
new/fasteners-0.15/fasteners/_utils.py
--- old/fasteners-0.14.1/fasteners/_utils.py    2015-11-13 07:39:16.000000000 
+0100
+++ new/fasteners-0.15/fasteners/_utils.py      2019-04-26 21:18:09.000000000 
+0200
@@ -17,8 +17,25 @@
 #    under the License.
 
 import logging
+import sys
 import time
 
+try:
+    from os import fsencode as _fsencode
+except (ImportError, AttributeError):
+    def _fsencode(path):
+        # Replicate similar logic to what py3.2+ fsencode does.
+        # See: https://bugs.python.org/issue8514
+        encoding = sys.getfilesystemencoding()
+        if encoding == 'mbcs':
+            errors = 'strict'
+        else:
+            errors = 'surrogateescape'
+        return path.encode(encoding, errors)
+
+
+import six
+
 from monotonic import monotonic as now  # noqa
 
 # log level for low-level debugging
@@ -27,6 +44,19 @@
 LOG = logging.getLogger(__name__)
 
 
+def canonicalize_path(path):
+    """Canonicalizes a potential path.
+
+    Returns a binary string encoded into filesystem encoding.
+    """
+    if isinstance(path, six.binary_type):
+        return path
+    if isinstance(path, six.text_type):
+        return _fsencode(path)
+    else:
+        return canonicalize_path(str(path))
+
+
 def pick_first_not_none(*values):
     """Returns first of values that is *not* None (or None if all are/were)."""
     for val in values:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fasteners-0.14.1/fasteners/lock.py 
new/fasteners-0.15/fasteners/lock.py
--- old/fasteners-0.14.1/fasteners/lock.py      2015-11-13 07:39:16.000000000 
+0100
+++ new/fasteners-0.15/fasteners/lock.py        2019-04-26 21:18:09.000000000 
+0200
@@ -119,19 +119,6 @@
     #: Reader owner type/string constant.
     READER = 'r'
 
-    @staticmethod
-    def _fetch_current_thread_functor():
-        # Until https://github.com/eventlet/eventlet/issues/172 is resolved
-        # or addressed we have to use complicated workaround to get a object
-        # that will not be recycled; the usage of threading.current_thread()
-        # doesn't appear to currently be monkey patched and therefore isn't
-        # reliable to use (and breaks badly when used as all threads share
-        # the same current_thread() object)...
-        if eventlet is not None and eventlet_patcher is not None:
-            if eventlet_patcher.is_monkey_patched('thread'):
-                return eventlet.getcurrent
-        return threading.current_thread
-
     def __init__(self,
                  condition_cls=threading.Condition,
                  current_thread_functor=None):
@@ -139,9 +126,7 @@
         self._pending_writers = collections.deque()
         self._readers = {}
         self._cond = condition_cls()
-        if current_thread_functor is None:
-            current_thread_functor = self._fetch_current_thread_functor()
-        self._current_thread = current_thread_functor
+        self._current_thread = threading.current_thread
 
     @property
     def has_pending_writers(self):
@@ -222,6 +207,8 @@
 
         Will wait until no active readers. Blocks readers after acquiring.
 
+        Guaranteed for locks to be processed in fair order (FIFO).
+
         Raises a ``RuntimeError`` if an active reader attempts to acquire
         a lock.
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fasteners-0.14.1/fasteners/process_lock.py 
new/fasteners-0.15/fasteners/process_lock.py
--- old/fasteners-0.14.1/fasteners/process_lock.py      2015-11-13 
07:39:16.000000000 +0100
+++ new/fasteners-0.15/fasteners/process_lock.py        2019-04-26 
21:18:09.000000000 +0200
@@ -66,6 +66,11 @@
     safe to close the file descriptor while another thread holds the
     lock. Just opening and closing the lock file can break synchronization,
     so lock files must be accessed only using this abstraction.
+
+    .. warning::
+
+       It is quite useful to read before using (to understand
+       the risks involved): http://0pointer.de/blog/projects/locking.html
     """
 
     MAX_DELAY = 0.1
@@ -84,7 +89,7 @@
 
     def __init__(self, path, sleep_func=time.sleep, logger=None):
         self.lockfile = None
-        self.path = path
+        self.path = _utils.canonicalize_path(path)
         self.acquired = False
         self.sleep_func = sleep_func
         self.logger = _utils.pick_first_not_none(logger, LOG)
@@ -171,7 +176,12 @@
             self.lockfile = None
 
     def __enter__(self):
-        self.acquire()
+        gotten = self.acquire()
+        if not gotten:
+            # This shouldn't happen, but just incase...
+            raise threading.ThreadError("Unable to acquire a file lock"
+                                        " on `%s` (when used as a"
+                                        " context manager)" % self.path)
         return self
 
     def release(self):
@@ -204,30 +214,44 @@
         return os.path.exists(self.path)
 
     def trylock(self):
-        raise NotImplementedError()
+        self._trylock(self.lockfile)
 
     def unlock(self):
+        self._unlock(self.lockfile)
+
+    @staticmethod
+    def _trylock():
+        raise NotImplementedError()
+
+    @staticmethod
+    def _unlock():
         raise NotImplementedError()
 
 
 class _WindowsLock(_InterProcessLock):
     """Interprocess lock implementation that works on windows systems."""
 
-    def trylock(self):
-        msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_NBLCK, 1)
-
-    def unlock(self):
-        msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_UNLCK, 1)
+    @staticmethod
+    def _trylock(lockfile):
+        fileno = lockfile.fileno()
+        msvcrt.locking(fileno, msvcrt.LK_NBLCK, 1)
+
+    @staticmethod
+    def _unlock(lockfile):
+        fileno = lockfile.fileno()
+        msvcrt.locking(fileno, msvcrt.LK_UNLCK, 1)
 
 
 class _FcntlLock(_InterProcessLock):
     """Interprocess lock implementation that works on posix systems."""
 
-    def trylock(self):
-        fcntl.lockf(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
-
-    def unlock(self):
-        fcntl.lockf(self.lockfile, fcntl.LOCK_UN)
+    @staticmethod
+    def _trylock(lockfile):
+        fcntl.lockf(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
+
+    @staticmethod
+    def _unlock(lockfile):
+        fcntl.lockf(lockfile, fcntl.LOCK_UN)
 
 
 if os.name == 'nt':
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/fasteners-0.14.1/fasteners/tests/test_process_lock.py 
new/fasteners-0.15/fasteners/tests/test_process_lock.py
--- old/fasteners-0.14.1/fasteners/tests/test_process_lock.py   2015-08-08 
10:15:25.000000000 +0200
+++ new/fasteners-0.15/fasteners/tests/test_process_lock.py     2019-04-26 
21:18:09.000000000 +0200
@@ -15,12 +15,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import contextlib
 import errno
-import fcntl
 import multiprocessing
 import os
 import shutil
-import signal
+import sys
 import tempfile
 import threading
 import time
@@ -28,6 +28,8 @@
 from fasteners import process_lock as pl
 from fasteners import test
 
+WIN32 = os.name == 'nt'
+
 
 class BrokenLock(pl.InterProcessLock):
     def __init__(self, name, errno_code):
@@ -43,6 +45,87 @@
         raise err
 
 
[email protected]
+def scoped_child_processes(children, timeout=0.1, exitcode=0):
+    for child in children:
+        child.daemon = True
+        child.start()
+    yield
+    start = time.time()
+    timed_out = 0
+
+    for child in children:
+        child.join(max(timeout - (time.time() - start), 0))
+        if child.is_alive():
+            timed_out += 1
+        child.terminate()
+
+    if timed_out:
+        msg = "{} child processes killed due to timeout\n".format(timed_out)
+        sys.stderr.write(msg)
+
+    if exitcode is not None:
+        for child in children:
+            c_code = child.exitcode
+            msg = "Child exitcode {} != {}"
+            assert c_code == exitcode, msg.format(c_code, exitcode)
+
+
+def try_lock(lock_file):
+    try:
+        my_lock = pl.InterProcessLock(lock_file)
+        my_lock.lockfile = open(lock_file, 'w')
+        my_lock.trylock()
+        my_lock.unlock()
+        os._exit(1)
+    except IOError:
+        os._exit(0)
+
+
+def lock_files(lock_path, handles_dir, num_handles=50):
+    with pl.InterProcessLock(lock_path):
+
+        # Open some files we can use for locking
+        handles = []
+        for n in range(num_handles):
+            path = os.path.join(handles_dir, ('file-%s' % n))
+            handles.append(open(path, 'w'))
+
+        # Loop over all the handles and try locking the file
+        # without blocking, keep a count of how many files we
+        # were able to lock and then unlock. If the lock fails
+        # we get an IOError and bail out with bad exit code
+        count = 0
+        for handle in handles:
+            try:
+                pl.InterProcessLock._trylock(handle)
+                count += 1
+                pl.InterProcessLock._unlock(handle)
+            except IOError:
+                os._exit(2)
+            finally:
+                handle.close()
+
+        # Check if we were able to open all files
+        if count != num_handles:
+            raise AssertionError("Unable to open all handles")
+
+
+def inter_processlock_helper(lockname, lock_filename, pipe):
+    lock2 = pl.InterProcessLock(lockname)
+    lock2.lockfile = open(lock_filename, 'w')
+    have_lock = False
+    while not have_lock:
+        try:
+            lock2.trylock()
+            have_lock = True
+        except IOError:
+            pass
+    # Hold the lock and wait for the parent
+    pipe.send(None)
+    pipe.recv()
+
+
 class ProcessLockTest(test.TestCase):
     def setUp(self):
         super(ProcessLockTest, self).setUp()
@@ -59,27 +142,13 @@
         lock_file = os.path.join(self.lock_dir, 'lock')
         lock = pl.InterProcessLock(lock_file)
 
-        def try_lock():
-            try:
-                my_lock = pl.InterProcessLock(lock_file)
-                my_lock.lockfile = open(lock_file, 'w')
-                my_lock.trylock()
-                my_lock.unlock()
-                os._exit(1)
-            except IOError:
-                os._exit(0)
-
         def attempt_acquire(count):
-            children = []
-            for i in range(count):
-                child = multiprocessing.Process(target=try_lock)
-                child.start()
-                children.append(child)
-            exit_codes = []
-            for child in children:
-                child.join()
-                exit_codes.append(child.exitcode)
-            return sum(exit_codes)
+            children = [
+                multiprocessing.Process(target=try_lock, args=(lock_file,))
+                for i in range(count)]
+            with scoped_child_processes(children, timeout=10, exitcode=None):
+                pass
+            return sum(c.exitcode for c in children)
 
         self.assertTrue(lock.acquire())
         try:
@@ -108,49 +177,17 @@
     def _do_test_lock_externally(self, lock_dir):
         lock_path = os.path.join(lock_dir, "lock")
 
-        def lock_files(handles_dir):
-            with pl.InterProcessLock(lock_path):
-
-                # Open some files we can use for locking
-                handles = []
-                for n in range(50):
-                    path = os.path.join(handles_dir, ('file-%s' % n))
-                    handles.append(open(path, 'w'))
-
-                # Loop over all the handles and try locking the file
-                # without blocking, keep a count of how many files we
-                # were able to lock and then unlock. If the lock fails
-                # we get an IOError and bail out with bad exit code
-                count = 0
-                for handle in handles:
-                    try:
-                        fcntl.flock(handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
-                        count += 1
-                        fcntl.flock(handle, fcntl.LOCK_UN)
-                    except IOError:
-                        os._exit(2)
-                    finally:
-                        handle.close()
-
-                # Check if we were able to open all files
-                self.assertEqual(50, count)
-
         handles_dir = tempfile.mkdtemp()
         self.tmp_dirs.append(handles_dir)
-        children = []
-        for n in range(50):
-            pid = os.fork()
-            if pid:
-                children.append(pid)
-            else:
-                try:
-                    lock_files(handles_dir)
-                finally:
-                    os._exit(0)
-        for child in children:
-            (pid, status) = os.waitpid(child, 0)
-            if pid:
-                self.assertEqual(0, status)
+
+        num_handles = 50
+        num_processes = 50
+        args = [lock_path, handles_dir, num_handles]
+        children = [multiprocessing.Process(target=lock_files, args=args)
+                    for _ in range(num_processes)]
+
+        with scoped_child_processes(children, timeout=30, exitcode=0):
+            pass
 
     def test_lock_externally(self):
         self._do_test_lock_externally(self.lock_dir)
@@ -180,16 +217,20 @@
 
     def test_interprocess_lock(self):
         lock_file = os.path.join(self.lock_dir, 'lock')
+        lock_name = 'foo'
+
+        child_pipe, them = multiprocessing.Pipe()
+        child = multiprocessing.Process(
+            target=inter_processlock_helper, args=(lock_name, lock_file, them))
+
+        with scoped_child_processes((child,)):
 
-        pid = os.fork()
-        if pid:
             # Make sure the child grabs the lock first
+            if not child_pipe.poll(5):
+                self.fail('Timed out waiting for child to grab lock')
+
             start = time.time()
-            while not os.path.exists(lock_file):
-                if time.time() - start > 5:
-                    self.fail('Timed out waiting for child to grab lock')
-                time.sleep(0)
-            lock1 = pl.InterProcessLock('foo')
+            lock1 = pl.InterProcessLock(lock_name)
             lock1.lockfile = open(lock_file, 'w')
             # NOTE(bnemec): There is a brief window between when the lock file
             # is created and when it actually becomes locked.  If we happen to
@@ -206,26 +247,10 @@
                     break
             else:
                 self.fail('Never caught expected lock exception')
-            # We don't need to wait for the full sleep in the child here
-            os.kill(pid, signal.SIGKILL)
-        else:
-            try:
-                lock2 = pl.InterProcessLock('foo')
-                lock2.lockfile = open(lock_file, 'w')
-                have_lock = False
-                while not have_lock:
-                    try:
-                        lock2.trylock()
-                        have_lock = True
-                    except IOError:
-                        pass
-            finally:
-                # NOTE(bnemec): This is racy, but I don't want to add any
-                # synchronization primitives that might mask a problem
-                # with the one we're trying to test here.
-                time.sleep(.5)
-                os._exit(0)
 
+            child_pipe.send(None)
+
+    @test.testtools.skipIf(WIN32, "Windows cannot open file handles twice")
     def test_non_destructive(self):
         lock_file = os.path.join(self.lock_dir, 'not-destroyed')
         with open(lock_file, 'w') as f:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fasteners-0.14.1/fasteners.egg-info/PKG-INFO 
new/fasteners-0.15/fasteners.egg-info/PKG-INFO
--- old/fasteners-0.14.1/fasteners.egg-info/PKG-INFO    2015-11-13 
07:47:25.000000000 +0100
+++ new/fasteners-0.15/fasteners.egg-info/PKG-INFO      2019-05-20 
19:36:52.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: fasteners
-Version: 0.14.1
+Version: 0.15
 Summary: A python package that provides useful locks.
 Home-page: https://github.com/harlowja/fasteners
 Author: Joshua Harlow
@@ -12,6 +12,9 @@
         .. image:: https://travis-ci.org/harlowja/fasteners.png?branch=master
            :target: https://travis-ci.org/harlowja/fasteners
         
+        .. image:: https://ci.appveyor.com/api/projects/status/7d7aku32pimpadiv
+           :target: https://ci.appveyor.com/project/JoshuaHarlow/fasteners
+        
         .. image:: 
https://readthedocs.org/projects/fasteners/badge/?version=latest
            :target: https://readthedocs.org/projects/fasteners/?badge=latest
            :alt: Documentation Status
@@ -71,7 +74,7 @@
 Classifier: Operating System :: POSIX :: Linux
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
 Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fasteners-0.14.1/setup.cfg 
new/fasteners-0.15/setup.cfg
--- old/fasteners-0.14.1/setup.cfg      2015-11-13 07:47:25.000000000 +0100
+++ new/fasteners-0.15/setup.cfg        2019-05-20 19:36:52.000000000 +0200
@@ -4,5 +4,4 @@
 [egg_info]
 tag_build = 
 tag_date = 0
-tag_svn_revision = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fasteners-0.14.1/setup.py new/fasteners-0.15/setup.py
--- old/fasteners-0.14.1/setup.py       2015-11-13 07:46:46.000000000 +0100
+++ new/fasteners-0.15/setup.py 2019-05-20 19:35:56.000000000 +0200
@@ -31,7 +31,7 @@
 
 setup(
     name='fasteners',
-    version='0.14.1',
+    version='0.15',
     description='A python package that provides useful locks.',
     author="Joshua Harlow",
     author_email='[email protected]',
@@ -45,10 +45,10 @@
         "Operating System :: POSIX :: Linux",
         "Programming Language :: Python",
         "Programming Language :: Python :: 2",
-        "Programming Language :: Python :: 2.6",
         "Programming Language :: Python :: 2.7",
         "Programming Language :: Python :: 3",
         "Programming Language :: Python :: 3.4",
+        "Programming Language :: Python :: 3.5",
     ],
     keywords="locks thread threads interprocess"
              " processes process fasteners",


Reply via email to