Mercurial > p > roundup > code
changeset 4686:4e740f02e165
Remove pywin32 installation dependency by porting portalocker.py to ctypes.
portalocker.py lock/unlock functions now return result of operation, support
for Windows 95/98/ME is removed.
| author | anatoly techtonik <techtonik@gmail.com> |
|---|---|
| date | Wed, 28 Nov 2012 04:51:56 +0300 |
| parents | 61e922a93112 |
| children | 4960a2c21590 |
| files | CHANGES.txt doc/installation.txt roundup/backends/portalocker.py |
| diffstat | 3 files changed, 86 insertions(+), 73 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGES.txt Wed Nov 28 03:44:34 2012 +0300 +++ b/CHANGES.txt Wed Nov 28 04:51:56 2012 +0300 @@ -7,6 +7,8 @@ Features: +- pywin32 is not longer required to run on Windows (anatoly techtonik) +- Rewritten portalocker.py logic in ctypes for Windows (anatoly techtonik) - Add an interface to register clearCache callbacks in roundupdb. Sometimes complicated computations may require an application cache. This application can now register a callback to clear the application
--- a/doc/installation.txt Wed Nov 28 03:44:34 2012 +0300 +++ b/doc/installation.txt Wed Nov 28 04:51:56 2012 +0300 @@ -39,11 +39,6 @@ installed for Roundup installation to work. Debian and derivatives, are known to require this. -If you're on windows, you will either need to be using the ActiveState python -distribution (at http://www.activestate.com/Products/ActivePython/), or you'll -have to install the win32all package separately (get it from -http://starship.python.net/crew/mhammond/win32/). - Optional Components =================== @@ -83,11 +78,15 @@ configured, you can require email to be cryptographically signed before roundup will allow it to make modifications to issues. +Windows Service + You can run Roundup as a Windows service if pywin32_ is installed. + .. _Xapian: http://xapian.org/ .. _pytz: http://www.python.org/pypi/pytz .. _Olson tz database: http://www.twinsun.com/tz/tz-link.htm .. _pyopenssl: http://pyopenssl.sourceforge.net .. _pyme: http://pyme.sourceforge.net +.. _pywin32: http://pypi.python.org/pypi/pywin32 Getting Roundup
--- a/roundup/backends/portalocker.py Wed Nov 28 03:44:34 2012 +0300 +++ b/roundup/backends/portalocker.py Wed Nov 28 04:51:56 2012 +0300 @@ -1,7 +1,11 @@ +#!/usr/bin/env python +# # 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. +# +# http://code.activestate.com/recipes/65203-portalocker-cross-platform-posixnt-api-for-flock-s/ +# +""" +Cross-platform (posix/nt) API for flock-style file locking. Synopsis:: @@ -34,22 +38,69 @@ that accompanies the win32 modules. :Author: Jonathan Feinberg <jdf@pobox.com> -:Version: Id: portalocker.py,v 1.3 2001/05/29 18:47:55 Administrator Exp - **un-cvsified by richard so the version doesn't change** + +Roundup Changes +--------------- +2012-11-28 (anatoly techtonik) + - Ported to ctypes + - Dropped support for Win95, Win98 and WinME + - Added return result """ + __docformat__ = 'restructuredtext' import os if os.name == 'nt': - import win32file - import pywintypes import msvcrt + from ctypes import * + from ctypes.wintypes import BOOL, DWORD, HANDLE + LOCK_SH = 0 # the default LOCK_NB = 0x1 # LOCKFILE_FAIL_IMMEDIATELY LOCK_EX = 0x2 # LOCKFILE_EXCLUSIVE_LOCK - # is there any reason not to reuse the following structure? - __overlapped = pywintypes.OVERLAPPED() + + # --- the code is taken from pyserial project --- + # + # detect size of ULONG_PTR + def is_64bit(): + return sizeof(c_ulong) != sizeof(c_void_p) + if is_64bit(): + ULONG_PTR = c_int64 + else: + ULONG_PTR = c_ulong + PVOID = c_void_p + + # --- Union inside Structure by stackoverflow:3480240 --- + class _OFFSET(Structure): + _fields_ = [ + ('Offset', DWORD), + ('OffsetHigh', DWORD)] + + class _OFFSET_UNION(Union): + _anonymous_ = ['_offset'] + _fields_ = [ + ('_offset', _OFFSET), + ('Pointer', PVOID)] + + class OVERLAPPED(Structure): + _anonymous_ = ['_offset_union'] + _fields_ = [ + ('Internal', ULONG_PTR), + ('InternalHigh', ULONG_PTR), + ('_offset_union', _OFFSET_UNION), + ('hEvent', HANDLE)] + + LPOVERLAPPED = POINTER(OVERLAPPED) + + # --- Define function prototypes for extra safety --- + LockFileEx = windll.kernel32.LockFileEx + LockFileEx.restype = BOOL + LockFileEx.argtypes = [HANDLE, DWORD, DWORD, DWORD, DWORD, LPOVERLAPPED] + UnlockFileEx = windll.kernel32.UnlockFileEx + UnlockFileEx.restype = BOOL + UnlockFileEx.argtypes = [HANDLE, DWORD, DWORD, DWORD, LPOVERLAPPED] + elif os.name == 'posix': import fcntl LOCK_SH = fcntl.LOCK_SH # shared lock @@ -60,73 +111,34 @@ if os.name == 'nt': def lock(file, flags): + """ Return True on success, False otherwise """ hfile = msvcrt.get_osfhandle(file.fileno()) - # LockFileEx is not supported on all Win32 platforms (Win95, Win98, - # WinME). - # If it's not supported, win32file will raise an exception. - # Try LockFileEx first, as it has more functionality and handles - # blocking locks more efficiently. - try: - win32file.LockFileEx(hfile, flags, 0, 0xFFFF0000, __overlapped) - except win32file.error, e: - import winerror - # Propagate upwards all exceptions other than not-implemented. - if e[0] != winerror.ERROR_CALL_NOT_IMPLEMENTED: - raise e - - # LockFileEx is not supported. Use LockFile. - # LockFile does not support shared locking -- always exclusive. - # Care: the low/high length params are reversed compared to - # LockFileEx. - if not flags & LOCK_EX: - import warnings - warnings.warn("PortaLocker does not support shared " - "locking on Win9x", RuntimeWarning) - # LockFile only supports immediate-fail locking. - if flags & LOCK_NB: - win32file.LockFile(hfile, 0, 0, 0xFFFF0000, 0) - else: - # Emulate a blocking lock with a polling loop. - import time - while 1: - # Attempt a lock. - try: - win32file.LockFile(hfile, 0, 0, 0xFFFF0000, 0) - break - except win32file.error, e: - # Propagate upwards all exceptions other than lock - # violation. - if e[0] != winerror.ERROR_LOCK_VIOLATION: - raise e - # Sleep and poll again. - time.sleep(0.1) - # TODO: should this return the result of the lock? - + overlapped = OVERLAPPED() + if LockFileEx(hfile, flags, 0, 0, 0xFFFF0000, byref(overlapped)): + return True + else: + return False + def unlock(file): hfile = msvcrt.get_osfhandle(file.fileno()) - # UnlockFileEx is not supported on all Win32 platforms (Win95, Win98, - # WinME). - # If it's not supported, win32file will raise an api_error exception. - try: - win32file.UnlockFileEx(hfile, 0, 0xFFFF0000, __overlapped) - except win32file.error, e: - import winerror - # Propagate upwards all exceptions other than not-implemented. - if e[0] != winerror.ERROR_CALL_NOT_IMPLEMENTED: - raise e - - # UnlockFileEx is not supported. Use UnlockFile. - # Care: the low/high length params are reversed compared to - # UnLockFileEx. - win32file.UnlockFile(hfile, 0, 0, 0xFFFF0000, 0) + overlapped = OVERLAPPED() + if UnlockFileEx(hfile, 0, 0, 0xFFFF0000, byref(overlapped)): + return True + else: + return False elif os.name =='posix': def lock(file, flags): - fcntl.flock(file.fileno(), flags) - # TODO: should this return the result of the lock? + if fcntl.flock(file.fileno(), flags) == 0: + return True + else: + return False def unlock(file): - fcntl.flock(file.fileno(), fcntl.LOCK_UN) + if fcntl.flock(file.fileno(), fcntl.LOCK_UN) == 0: + return True + else: + return False if __name__ == '__main__': from time import time, strftime, localtime
