[Python-modules-commits] [portalocker] 01/03: Import portalocker_1.0.0.orig.tar.gz

Josué Ortega josue at moszumanska.debian.org
Sun Oct 2 22:49:38 UTC 2016


This is an automated email from the git hooks/post-receive script.

josue pushed a commit to branch master
in repository portalocker.

commit e4b25c8e4af0bd2b477834c685bd6db373fdae93
Author: Josue Ortega <josue at debian.org>
Date:   Sun Oct 2 16:41:07 2016 -0600

    Import portalocker_1.0.0.orig.tar.gz
---
 CHANGELOG                         |  29 ------
 PKG-INFO                          |  15 ++-
 README.rst                        |  13 ++-
 portalocker.egg-info/PKG-INFO     |  15 ++-
 portalocker.egg-info/SOURCES.txt  |   6 +-
 portalocker.egg-info/not-zip-safe |   1 -
 portalocker/__about__.py          |   7 ++
 portalocker/__init__.py           |  54 ++++++++++-
 portalocker/constants.py          |  23 +++++
 portalocker/exceptions.py         |  11 +++
 portalocker/portalocker.py        | 192 ++++++++++++--------------------------
 portalocker/utils.py              |  44 +++++----
 setup.cfg                         |   3 +
 setup.py                          | 111 ++++++++++++++++------
 tests/test_combined.py            |  15 +++
 tests/tests.py                    |  82 ++++++++++++----
 16 files changed, 363 insertions(+), 258 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
deleted file mode 100644
index 221562e..0000000
--- a/CHANGELOG
+++ /dev/null
@@ -1,29 +0,0 @@
-0.1:
-
- * Initial release
-
-0.2:
-
- * Added `Lock` class to help prevent cache race conditions
-
-0.3:
-
- * Now actually returning the file descriptor from the `Lock` class
-
-0.4:
-
- * Fixing a few bugs, added coveralls support, switched to py.test and added
-   100% test coverage.
-
-    - Fixing exception thrown when fail_when_locked is true
-    - Fixing exception "Lock object has no attribute '_release_lock'" when
-      fail_when_locked is true due to the call to Lock._release_lock() which
-      fails because _release_lock is not defined.
-
-0.5:
-
- * Python 3 support
-
-0.6:
-
- * Added msvcrt support for Windows
diff --git a/PKG-INFO b/PKG-INFO
index 6988304..d754298 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: portalocker
-Version: 0.6.1
+Version: 1.0.0
 Summary: Wraps the portalocker recipe for easy usage
 Home-page: https://github.com/WoLpH/portalocker
 Author: Rick van Hattem
@@ -14,7 +14,7 @@ Description: ############################################
             :alt: Linux Test Status
             :target: https://travis-ci.org/WoLpH/portalocker
             
-        .. image:: https://img.shields.io/appveyor/ci/WoLpH/portalocker.svg
+        .. image:: https://ci.appveyor.com/api/projects/status/mgqry98hgpy4prhh?svg=true
             :alt: Windows Tests Status
             :target: https://ci.appveyor.com/project/WoLpH/portalocker
         
@@ -22,10 +22,6 @@ Description: ############################################
             :alt: Coverage Status
             :target: https://coveralls.io/r/WoLpH/portalocker?branch=master
         
-        .. image:: https://landscape.io/github/WoLpH/portalocker/master/landscape.png
-           :target: https://landscape.io/github/WoLpH/portalocker/master
-           :alt: Code Health
-        
         Overview
         --------
         
@@ -79,15 +75,18 @@ Description: ############################################
         Do note that your data might still be in a buffer so it is possible that your
         data is not available until you `flush()` or `close()`.
         
+        More examples can be found in the
+        `tests <http://portalocker.readthedocs.io/en/latest/_modules/tests/tests.html>`_.
+        
         Changelog
         ---------
         
-        See CHANGELOG file
+        See the `changelog <http://portalocker.readthedocs.io/en/latest/changelog.html>`_ page.
         
         License
         -------
         
-        see the LICENSE file
+        See the `LICENSE <https://github.com/WoLpH/portalocker/blob/develop/LICENSE>`_ file.
         
         
 Keywords: locking,locks,with statement,windows,linux,unix
diff --git a/README.rst b/README.rst
index 844a5b5..93c3318 100644
--- a/README.rst
+++ b/README.rst
@@ -6,7 +6,7 @@ portalocker - Cross-platform locking library
     :alt: Linux Test Status
     :target: https://travis-ci.org/WoLpH/portalocker
     
-.. image:: https://img.shields.io/appveyor/ci/WoLpH/portalocker.svg
+.. image:: https://ci.appveyor.com/api/projects/status/mgqry98hgpy4prhh?svg=true
     :alt: Windows Tests Status
     :target: https://ci.appveyor.com/project/WoLpH/portalocker
 
@@ -14,10 +14,6 @@ portalocker - Cross-platform locking library
     :alt: Coverage Status
     :target: https://coveralls.io/r/WoLpH/portalocker?branch=master
 
-.. image:: https://landscape.io/github/WoLpH/portalocker/master/landscape.png
-   :target: https://landscape.io/github/WoLpH/portalocker/master
-   :alt: Code Health
-
 Overview
 --------
 
@@ -71,13 +67,16 @@ than you can do it like this:
 Do note that your data might still be in a buffer so it is possible that your
 data is not available until you `flush()` or `close()`.
 
+More examples can be found in the
+`tests <http://portalocker.readthedocs.io/en/latest/_modules/tests/tests.html>`_.
+
 Changelog
 ---------
 
-See CHANGELOG file
+See the `changelog <http://portalocker.readthedocs.io/en/latest/changelog.html>`_ page.
 
 License
 -------
 
-see the LICENSE file
+See the `LICENSE <https://github.com/WoLpH/portalocker/blob/develop/LICENSE>`_ file.
 
diff --git a/portalocker.egg-info/PKG-INFO b/portalocker.egg-info/PKG-INFO
index 6988304..d754298 100644
--- a/portalocker.egg-info/PKG-INFO
+++ b/portalocker.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: portalocker
-Version: 0.6.1
+Version: 1.0.0
 Summary: Wraps the portalocker recipe for easy usage
 Home-page: https://github.com/WoLpH/portalocker
 Author: Rick van Hattem
@@ -14,7 +14,7 @@ Description: ############################################
             :alt: Linux Test Status
             :target: https://travis-ci.org/WoLpH/portalocker
             
-        .. image:: https://img.shields.io/appveyor/ci/WoLpH/portalocker.svg
+        .. image:: https://ci.appveyor.com/api/projects/status/mgqry98hgpy4prhh?svg=true
             :alt: Windows Tests Status
             :target: https://ci.appveyor.com/project/WoLpH/portalocker
         
@@ -22,10 +22,6 @@ Description: ############################################
             :alt: Coverage Status
             :target: https://coveralls.io/r/WoLpH/portalocker?branch=master
         
-        .. image:: https://landscape.io/github/WoLpH/portalocker/master/landscape.png
-           :target: https://landscape.io/github/WoLpH/portalocker/master
-           :alt: Code Health
-        
         Overview
         --------
         
@@ -79,15 +75,18 @@ Description: ############################################
         Do note that your data might still be in a buffer so it is possible that your
         data is not available until you `flush()` or `close()`.
         
+        More examples can be found in the
+        `tests <http://portalocker.readthedocs.io/en/latest/_modules/tests/tests.html>`_.
+        
         Changelog
         ---------
         
-        See CHANGELOG file
+        See the `changelog <http://portalocker.readthedocs.io/en/latest/changelog.html>`_ page.
         
         License
         -------
         
-        see the LICENSE file
+        See the `LICENSE <https://github.com/WoLpH/portalocker/blob/develop/LICENSE>`_ file.
         
         
 Keywords: locking,locks,with statement,windows,linux,unix
diff --git a/portalocker.egg-info/SOURCES.txt b/portalocker.egg-info/SOURCES.txt
index 6526c00..5d756f3 100644
--- a/portalocker.egg-info/SOURCES.txt
+++ b/portalocker.egg-info/SOURCES.txt
@@ -1,15 +1,17 @@
-CHANGELOG
 LICENSE
 MANIFEST.in
 README.rst
 setup.cfg
 setup.py
+portalocker/__about__.py
 portalocker/__init__.py
+portalocker/constants.py
+portalocker/exceptions.py
 portalocker/portalocker.py
 portalocker/utils.py
 portalocker.egg-info/PKG-INFO
 portalocker.egg-info/SOURCES.txt
 portalocker.egg-info/dependency_links.txt
-portalocker.egg-info/not-zip-safe
 portalocker.egg-info/top_level.txt
+tests/test_combined.py
 tests/tests.py
\ No newline at end of file
diff --git a/portalocker.egg-info/not-zip-safe b/portalocker.egg-info/not-zip-safe
deleted file mode 100644
index 8b13789..0000000
--- a/portalocker.egg-info/not-zip-safe
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/portalocker/__about__.py b/portalocker/__about__.py
new file mode 100644
index 0000000..27bdd4c
--- /dev/null
+++ b/portalocker/__about__.py
@@ -0,0 +1,7 @@
+__package_name__ = 'portalocker'
+__author__ = 'Rick van Hattem'
+__email__ = 'wolph at wol.ph'
+__version__ = '1.0.0'
+__description__ = '''Wraps the portalocker recipe for easy usage'''
+__url__ = 'https://github.com/WoLpH/portalocker'
+
diff --git a/portalocker/__init__.py b/portalocker/__init__.py
index dae2991..91c7a8c 100644
--- a/portalocker/__init__.py
+++ b/portalocker/__init__.py
@@ -1,5 +1,54 @@
-from .portalocker import lock, unlock, LOCK_EX, LOCK_SH, LOCK_NB, LockException
-from .utils import Lock, AlreadyLocked, open_atomic
+from . import __about__
+from . import constants
+from . import exceptions
+from . import portalocker
+from . import utils
+
+#: The package name on Pypi
+__package_name__ = __about__.__package_name__
+#: Current author and maintainer, view the git history for the previous ones
+__author__ = __about__.__author__
+#: Current author's email address
+__email__ = __about__.__email__
+#: Version number
+__version__ = __about__.__version__
+#: Package description for Pypi
+__description__ = __about__.__description__
+#: Package homepage
+__url__ = __about__.__url__
+
+
+#: Exception thrown when the file is already locked by someone else
+AlreadyLocked = exceptions.AlreadyLocked
+#: Exception thrown if an error occurred during locking
+LockException = exceptions.LockException
+
+
+#: Lock a file. Note that this is an advisory lock on Linux/Unix systems
+lock = portalocker.lock
+#: Unlock a file
+unlock = portalocker.unlock
+
+#: Place an exclusive lock.
+#: Only one process may hold an exclusive lock for a given file at a given
+#: time.
+LOCK_EX = constants.LOCK_EX
+
+#: Place a shared lock.
+#: More than one process may hold a shared lock for a given file at a given
+#: time.
+LOCK_SH = constants.LOCK_SH
+
+#: Acquire the lock in a non-blocking fashion.
+LOCK_NB = constants.LOCK_NB
+
+#: Remove an existing lock held by this process.
+LOCK_UN = constants.LOCK_UN
+
+#: Locking utility class to automatically handle opening with timeouts and
+#: context wrappers
+Lock = utils.Lock
+open_atomic = utils.open_atomic
 
 __all__ = [
     'lock',
@@ -7,6 +56,7 @@ __all__ = [
     'LOCK_EX',
     'LOCK_SH',
     'LOCK_NB',
+    'LOCK_UN',
     'LockException',
     'Lock',
     'AlreadyLocked',
diff --git a/portalocker/constants.py b/portalocker/constants.py
new file mode 100644
index 0000000..976f578
--- /dev/null
+++ b/portalocker/constants.py
@@ -0,0 +1,23 @@
+import os
+
+# The actual tests will execute the code anyhow so the following code can
+# safely be ignored from the coverage tests
+if os.name == 'nt':  # pragma: no cover
+    import msvcrt
+
+    LOCK_EX = 0x1
+    LOCK_SH = 0x2
+    LOCK_NB = 0x4
+    LOCK_UN = msvcrt.LK_UNLCK
+
+elif os.name == 'posix':  # pragma: no cover
+    import fcntl
+
+    LOCK_EX = fcntl.LOCK_EX
+    LOCK_SH = fcntl.LOCK_SH
+    LOCK_NB = fcntl.LOCK_NB
+    LOCK_UN = fcntl.LOCK_UN
+
+else:  # pragma: no cover
+    raise RuntimeError('PortaLocker only defined for nt and posix platforms')
+
diff --git a/portalocker/exceptions.py b/portalocker/exceptions.py
new file mode 100644
index 0000000..4976b80
--- /dev/null
+++ b/portalocker/exceptions.py
@@ -0,0 +1,11 @@
+class BaseLockException(Exception):
+    # Error codes:
+    LOCK_FAILED = 1
+
+
+class LockException(BaseLockException):
+    pass
+
+
+class AlreadyLocked(BaseLockException):
+    pass
diff --git a/portalocker/portalocker.py b/portalocker/portalocker.py
index 3c68b96..d0df6f6 100644
--- a/portalocker/portalocker.py
+++ b/portalocker/portalocker.py
@@ -1,146 +1,78 @@
-# portalocker.py - Cross-platform (posix/nt) API for flock-style file locking.
-#                  Requires python 1.5.2 or better.
-'''Cross-platform (posix/nt) API for flock-style file locking.
-
-Synopsis:
-
-   import portalocker
-   file = open('somefile', 'r+')
-   portalocker.lock(file, portalocker.LOCK_EX)
-   file.seek(12)
-   file.write('foo')
-   file.close()
-
-If you know what you're doing, you may choose to
-
-   portalocker.unlock(file)
-
-before closing the file, but why?
-
-Methods:
-
-   lock( file, flags )
-   unlock( file )
-
-Constants:
-
-   LOCK_EX
-   LOCK_SH
-   LOCK_NB
-
-Exceptions:
-
-    LockException
-
-Notes:
-
-For the 'nt' platform, this module requires the Python Extensions for Windows.
-Be aware that this may not work as expected on Windows 95/98/ME.
-
-History:
-
-I learned the win32 technique for locking files from sample code
-provided by John Nielsen <nielsenjf at my-deja.com> in the documentation
-that accompanies the win32 modules.
-
-Author: Jonathan Feinberg <jdf at pobox.com>,
-        Lowell Alleman <lalleman at mfps.com>
-Version: $Id: portalocker.py 5474 2008-05-16 20:53:50Z lowell $
-
-'''
-
 import os
+from . import exceptions
+from . import constants
 
 
-__all__ = [
-    'lock',
-    'unlock',
-    'LOCK_EX',
-    'LOCK_SH',
-    'LOCK_NB',
-    'LockException',
-]
-
-
-class LockException(Exception):
-    # Error codes:
-    LOCK_FAILED = 1
-
 if os.name == 'nt':  # pragma: no cover
     import msvcrt
-    LOCK_EX = 0x1      # exclusive - msvcrt.LK_LOCK or msvcrt.LK_NBLCK
-    LOCK_SH = 0x2      # shared    - msvcrt.LK_RLOCK or msvcrt.LK_NBRLCK
-    LOCK_NB = 0x4      # 
-elif os.name == 'posix':
-    import fcntl
-    LOCK_EX = fcntl.LOCK_EX
-    LOCK_SH = fcntl.LOCK_SH
-    LOCK_NB = fcntl.LOCK_NB
-else:  # pragma: no cover
-    raise RuntimeError('PortaLocker only defined for nt and posix platforms')
 
-
-def nt_lock(file_, flags):  # pragma: no cover
-    if flags & LOCK_SH:
-        mode = msvcrt.LK_NBRLCK if (flags & LOCK_NB) else msvcrt.LK_RLOCK
-    else:
-        mode = msvcrt.LK_NBLCK if (flags & LOCK_NB) else msvcrt.LK_LOCK
-
-    # windows locks byte ranges, so make sure to lock from file start
-    try:
-        savepos = file_.tell()
-        if savepos:
-            # [ ] test exclusive lock fails on seek here
-            # [ ] test if shared lock passes this point
-            file_.seek(0)
-        # [x] check if 0 param locks entire file (not documented in Python)
-	#   [x] just fails with "IOError: [Errno 13] Permission denied",
-        #        but -1 seems to do the trick
+    def lock(file_, flags):
+        if flags & constants.LOCK_SH:
+            if flags & constants.LOCK_NB:
+                mode = msvcrt.LK_NBRLCK
+            else:
+                mode = msvcrt.LK_RLOCK
+        else:
+            if flags & constants.LOCK_NB:
+                mode = msvcrt.LK_NBLCK
+            else:
+                mode = msvcrt.LK_LOCK
+
+        # windows locks byte ranges, so make sure to lock from file start
         try:
-            msvcrt.locking(file_.fileno(), mode, -1)
-        except IOError as exc_value:
-            # [ ] be more specific here
-            raise LockException(LockException.LOCK_FAILED, exc_value.strerror)
-        finally:
+            savepos = file_.tell()
             if savepos:
-                file_.seek(savepos)
-    except IOError as exc_value:
-        raise LockException(LockException.LOCK_FAILED, exc_value.strerror)
-
+                # [ ] test exclusive lock fails on seek here
+                # [ ] test if shared lock passes this point
+                file_.seek(0)
+                # [x] check if 0 param locks entire file (not documented in
+                #     Python)
+                # [x] just fails with "IOError: [Errno 13] Permission denied",
+                #     but -1 seems to do the trick
+            try:
+                msvcrt.locking(file_.fileno(), mode, -1)
+            except IOError as exc_value:
+                # [ ] be more specific here
+                raise exceptions.LockException(
+                    exceptions.LockException.LOCK_FAILED, exc_value.strerror)
+            finally:
+                if savepos:
+                    file_.seek(savepos)
+        except IOError as exc_value:
+            raise exceptions.LockException(
+                exceptions.LockException.LOCK_FAILED, exc_value.strerror)
 
-def nt_unlock(file_):  # pragma: no cover
-    try:
-        savepos = file_.tell()
-        if savepos:
-            file_.seek(0)
+    def unlock(file_):
         try:
-            msvcrt.locking(file_.fileno(), msvcrt.LK_UNLCK, -1)
-        except IOError as exc_value:
-            raise LockException(LockException.LOCK_FAILED, exc_value.strerror)
-        finally:
+            savepos = file_.tell()
             if savepos:
-                file_.seek(savepos)
-    except IOError as exc_value:
-        raise LockException(LockException.LOCK_FAILED, exc_value.strerror)
-
+                file_.seek(0)
+            try:
+                msvcrt.locking(file_.fileno(), constants.LOCK_UN, -1)
+            except IOError as exc_value:
+                raise exceptions.LockException(
+                    exceptions.LockException.LOCK_FAILED, exc_value.strerror)
+            finally:
+                if savepos:
+                    file_.seek(savepos)
+        except IOError as exc_value:
+            raise exceptions.LockException(
+                exceptions.LockException.LOCK_FAILED, exc_value.strerror)
 
-def posix_lock(file_, flags):
-    try:
-        fcntl.flock(file_.fileno(), flags)
-    except IOError as exc_value:
-        # The exception code varies on different systems so we'll catch
-        # every IO error
-        raise LockException(exc_value)
+elif os.name == 'posix':  # pragma: no cover
+    import fcntl
 
+    def lock(file_, flags):
+        try:
+            fcntl.flock(file_.fileno(), flags)
+        except IOError as exc_value:
+            # The exception code varies on different systems so we'll catch
+            # every IO error
+            raise exceptions.LockException(exc_value)
 
-def posix_unlock(file_):
-    fcntl.flock(file_.fileno(), fcntl.LOCK_UN)
+    def unlock(file_):
+        fcntl.flock(file_.fileno(), constants.LOCK_UN)
 
-if os.name == 'nt':  # pragma: no cover
-    lock = nt_lock
-    unlock = nt_unlock
-elif os.name == 'posix':
-    lock = posix_lock
-    unlock = posix_unlock
 else:  # pragma: no cover
-    raise RuntimeError('Your os %r is unsupported.' % os.name)
+    raise RuntimeError('PortaLocker only defined for nt and posix platforms')
+
diff --git a/portalocker/utils.py b/portalocker/utils.py
index e55826f..cc1f1aa 100644
--- a/portalocker/utils.py
+++ b/portalocker/utils.py
@@ -2,29 +2,26 @@ import os
 import time
 import tempfile
 import contextlib
-
+from . import exceptions
+from . import constants
 from . import portalocker
 
 DEFAULT_TIMEOUT = 5
 DEFAULT_CHECK_INTERVAL = 0.25
-LOCK_METHOD = portalocker.LOCK_EX | portalocker.LOCK_NB
+LOCK_METHOD = constants.LOCK_EX | constants.LOCK_NB
 
 __all__ = [
     'Lock',
-    'AlreadyLocked',
     'open_atomic',
 ]
 
 
-class AlreadyLocked(Exception):
-    pass
-
-
 @contextlib.contextmanager
 def open_atomic(filename, binary=True):
     '''Open a file for atomic writing. Instead of locking this method allows
     you to write the entire file and move it to the actual location. Note that
-    is still not atomic in all cases and won't work on existing files.
+    this makes the assumption that a rename is atomic on your platform which
+    is generally the case but not a guarantee.
 
     http://docs.python.org/library/os.html#os.rename
 
@@ -33,7 +30,7 @@ def open_atomic(filename, binary=True):
     ...     os.remove(filename)
 
     >>> with open_atomic(filename) as fh:
-    ...     fh.write('test')
+    ...     written = fh.write(b'test')
     >>> assert os.path.exists(filename)
     >>> os.remove(filename)
 
@@ -66,7 +63,7 @@ def open_atomic(filename, binary=True):
 class Lock(object):
 
     def __init__(
-            self, filename, mode='a', truncate=0, timeout=DEFAULT_TIMEOUT,
+            self, filename, mode='a', timeout=DEFAULT_TIMEOUT,
             check_interval=DEFAULT_CHECK_INTERVAL, fail_when_locked=True,
             flags=LOCK_METHOD):
         '''Lock manager with build-in timeout
@@ -88,6 +85,12 @@ class Lock(object):
         mode will result in truncate _BEFORE_ the lock is checked.
         '''
 
+        if 'w' in mode:
+            truncate = True
+            mode = mode.replace('w', 'a')
+        else:
+            truncate = False
+
         self.fh = None
         self.filename = filename
         self.mode = mode
@@ -97,8 +100,6 @@ class Lock(object):
         self.fail_when_locked = fail_when_locked
         self.flags = flags
 
-        assert 'w' not in mode, 'Mode "w" clears the file before locking'
-
     def acquire(
             self, timeout=None, check_interval=None, fail_when_locked=None):
         '''Acquire the locked filehandle'''
@@ -123,7 +124,7 @@ class Lock(object):
         try:
             # Try to lock
             fh = self._get_lock(fh)
-        except portalocker.LockException as exception:
+        except exceptions.LockException as exception:
             # Try till the timeout is 0
             while timeout > 0:
                 # Wait a bit
@@ -136,19 +137,19 @@ class Lock(object):
                     # We already tried to the get the lock
                     # If fail_when_locked is true, then stop trying
                     if fail_when_locked:
-                        raise AlreadyLocked(exception)
+                        raise exceptions.AlreadyLocked(exception)
 
                     else:  # pragma: no cover
                         # We've got the lock
                         fh = self._get_lock(fh)
                         break
 
-                except portalocker.LockException:
+                except exceptions.LockException:
                     pass
 
             else:
                 # We got a timeout... reraising
-                raise portalocker.LockException(exception)
+                raise exceptions.LockException(exception)
 
         # Prepare the filehandle (truncate if needed)
         fh = self._prepare_fh(fh)
@@ -174,19 +175,16 @@ class Lock(object):
         portalocker.lock(fh, self.flags)
         return fh
 
-    def _prepare_fh(self, fh, truncate=None):
+    def _prepare_fh(self, fh):
         '''
         Prepare the filehandle for usage
 
         If truncate is a number, the file will be truncated to that amount of
         bytes
         '''
-        if truncate is None:
-            truncate = self.truncate
-
-        if truncate is not None:
-            fh.seek(truncate)
-            fh.truncate(truncate)
+        if self.truncate:
+            fh.seek(0)
+            fh.truncate(0)
 
         return fh
 
diff --git a/setup.cfg b/setup.cfg
index 01c7b78..a16a175 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -12,6 +12,9 @@ upload-dir = docs/_build/html
 [bdist_wheel]
 universal = 1
 
+[aliases]
+test = pytest
+
 [egg_info]
 tag_build = 
 tag_date = 0
diff --git a/setup.py b/setup.py
index bf899a5..5e86ce0 100644
--- a/setup.py
+++ b/setup.py
@@ -1,38 +1,86 @@
-import sys
+from __future__ import print_function
+
+import re
+import os
 import setuptools
-from setuptools.command.test import test as TestCommand
 
-__package_name__ = 'portalocker'
-__author__ = 'Rick van Hattem'
-__email__ = 'wolph at wol.ph'
-__version__ = '0.6.1'
-__description__ = '''Wraps the portalocker recipe for easy usage'''
-__url__ = 'https://github.com/WoLpH/portalocker'
 
-extra = {}
-if sys.version_info >= (3, 0):
-    extra.update(use_2to3=True)
+# To prevent importing about and thereby breaking the coverage info we use this
+# exec hack
+about = {}
+with open('portalocker/__about__.py') as fp:
+    exec(fp.read(), about)
+
+
+test_requirements_file = os.path.join('tests', 'requirements.txt')
+if os.path.isfile(test_requirements_file):
+    with open(test_requirements_file) as fh:
+        tests_require = fh.read().splitlines()
+else:
+    tests_require = ['pytest>=3.0']
 
 
-class PyTest(TestCommand):
+class Combine(setuptools.Command):
+    description = 'Build single combined portalocker file'
+    relative_import_re = re.compile(r'^from \. import (?P<name>.+)$',
+                                    re.MULTILINE)
+    user_options = [
+        ('output-file=', 'o', 'Path to the combined output file'),
+    ]
+
+    def initialize_options(self):
+        self.output_file = os.path.join(
+            'dist', '%(package_name)s_%(version)s.py' % dict(
+                package_name=about['__package_name__'],
+                version=about['__version__'].replace('.', '-'),
+            ))
 
     def finalize_options(self):
-        TestCommand.finalize_options(self)
-        self.test_args = ['tests']
-        self.test_suite = True
+        pass
+
+    def run(self):
+        dirname = os.path.dirname(self.output_file)
+        if dirname and not os.path.isdir(dirname):
+            os.makedirs(dirname)
+
+        output = open(self.output_file, 'w')
+        print("'''", file=output)
+        with open('README.rst') as fh:
+            output.write(fh.read().rstrip())
+            print('', file=output)
+            print('', file=output)
 
-    def run_tests(self):
-        # import here, cause outside the eggs aren't loaded
-        import pytest
-        errno = pytest.main(self.test_args)
-        sys.exit(errno)
+        with open('LICENSE') as fh:
+            output.write(fh.read().rstrip())
+
+        print('', file=output)
+        print("'''", file=output)
+
+        names = set()
+        lines = []
+        for line in open('portalocker/__init__.py'):
+            match = self.relative_import_re.match(line)
+            if match:
+                names.add(match.group('name'))
+                with open('portalocker/%(name)s.py' % match.groupdict()) as fh:
+                    line = fh.read()
+                    line = self.relative_import_re.sub('', line)
+
+            lines.append(line)
+
+        import_attributes = re.compile(r'\b(%s)\.' % '|'.join(names))
+        for line in lines[:]:
+            line = import_attributes.sub('', line)
+            output.write(line)
+
+        print('Wrote combined file to %r' % self.output_file)
 
 
 if __name__ == '__main__':
     setuptools.setup(
-        name=__package_name__,
-        version=__version__,
-        description=__description__,
+        name=about['__package_name__'],
+        version=about['__version__'],
+        description=about['__description__'],
         long_description=open('README.rst').read(),
         classifiers=[
             'Intended Audience :: Developers',
@@ -46,14 +94,19 @@ if __name__ == '__main__':
             'Programming Language :: Python :: Implementation :: PyPy',
         ],
         keywords='locking, locks, with statement, windows, linux, unix',
-        author=__author__,
-        author_email=__email__,
-        url=__url__,
+        author=about['__author__'],
+        author_email=about['__email__'],
+        url=about['__url__'],
         license='PSF',
         packages=setuptools.find_packages(exclude=['ez_setup', 'examples']),
-        zip_safe=False,
+        # zip_safe=False,
         platforms=['any'],
-        cmdclass={'test': PyTest},
-        **extra
+        cmdclass={
+            'combine': Combine,
+        },
+        setup_requires=[
+            'pytest-runner',
+        ],
+        tests_require=tests_require,
     )
 
diff --git a/tests/test_combined.py b/tests/test_combined.py
new file mode 100644
index 0000000..594de74
--- /dev/null
+++ b/tests/test_combined.py
@@ -0,0 +1,15 @@
+import sys
+
+
+def test_combined(tmpdir):
+    from distutils import dist
+    import setup
+
+    output_file = tmpdir.join('combined.py')
+    combine = setup.Combine(dist.Distribution())
+    combine.output_file = str(output_file)
+    combine.run()
+    sys.path.append(output_file.dirname)
+    import combined
+    assert combined
+
diff --git a/tests/tests.py b/tests/tests.py
index 540c515..f5da680 100644
--- a/tests/tests.py
+++ b/tests/tests.py
@@ -1,13 +1,26 @@
 from __future__ import print_function
 from __future__ import with_statement
+
+import py
 import pytest
 import portalocker
 
 
-def test_exceptions():
+ at pytest.fixture
+def tmpfile(tmpdir_factory):
+    tmpdir = tmpdir_factory.mktemp('temp')
+    filename = tmpdir.join('tmpfile')
+    yield str(filename)
+    try:
+        filename.remove(ignore_errors=True)
+    except py.error.EBUSY:
+        pass
+
+
+def test_exceptions(tmpfile):
     # Open the file 2 times
-    a = open('locked_file', 'a')
-    b = open('locked_file', 'a')
+    a = open(tmpfile, 'a')
+    b = open(tmpfile, 'a')
 
     # Lock exclusive non-blocking
     lock_flags = portalocker.LOCK_EX | portalocker.LOCK_NB
@@ -24,39 +37,70 @@ def test_exceptions():
     b.close()
 
 
-def test_with_timeout():
+def test_with_timeout(tmpfile):
     # Open the file 2 times
     with pytest.raises(portalocker.AlreadyLocked):
-        with portalocker.Lock('locked_file', timeout=0.1) as fh:
+        with portalocker.Lock(tmpfile, timeout=0.1) as fh:
             print('writing some stuff to my cache...', file=fh)
-            with portalocker.Lock('locked_file', timeout=0.1):
+            with portalocker.Lock(tmpfile, timeout=0.1, mode='wb'):
                 pass
             print('writing more stuff to my cache...', file=fh)
 
 
-def test_without_timeout():
+def test_without_timeout(tmpfile):
     # Open the file 2 times
     with pytest.raises(portalocker.LockException):
-        with portalocker.Lock('locked_file', timeout=None) as fh:
+        with portalocker.Lock(tmpfile, timeout=None) as fh:
             print('writing some stuff to my cache...', file=fh)
-            with portalocker.Lock('locked_file', timeout=None):
+            with portalocker.Lock(tmpfile, timeout=None, mode='w'):
                 pass
             print('writing more stuff to my cache...', file=fh)
 
 
-def test_simple():
-    fh = open('tests/test_file.txt', 'r+')
+def test_without_fail(tmpfile):
+    # Open the file 2 times
+    with pytest.raises(portalocker.LockException):
+        with portalocker.Lock(tmpfile, timeout=0.1) as fh:
+            print('writing some stuff to my cache...', file=fh)
+            lock = portalocker.Lock(tmpfile, timeout=0.1)
+            lock.acquire(check_interval=0.05, fail_when_locked=False)
+
+
+def test_simple(tmpfile):
+    with open(tmpfile, 'w') as fh:
+        fh.write('spam and eggs')
+
+    fh = open(tmpfile, 'r+')
     portalocker.lock(fh, portalocker.LOCK_EX)
-    fh.seek(12)
+
+    fh.seek(13)
     fh.write('foo')
+
+    # Make sure we didn't overwrite the original text
+    fh.seek(0)
+    assert fh.read(13) == 'spam and eggs'
+
     portalocker.unlock(fh)
     fh.close()
 
 
-def test_class():
-    lock = portalocker.Lock('tests/test_file.txt')
-    lock2 = portalocker.Lock('tests/test_file.txt', fail_when_locked=False,
-                             timeout=0.01)
+def test_truncate(tmpfile):
+    with open(tmpfile, 'w') as fh:
+        fh.write('spam and eggs')
+
+    with portalocker.Lock(tmpfile, mode='a+') as fh:
+        # Make sure we didn't overwrite the original text
+        fh.seek(0)
+        assert fh.read(13) == 'spam and eggs'
+
+    with portalocker.Lock(tmpfile, mode='w+') as fh:
+        # Make sure we truncated the file
... 22 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/portalocker.git



More information about the Python-modules-commits mailing list