[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