NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #444 most downloaded on PyPI
Cross-platform file locking, with Redis, PID-file and bounded-semaphore locks
Last release 15 days ago
19 Sep 2026
Release timing varies
gaps range from 3 weeks to 1.1 years
Most releases are documented
notes for 41 of 53 stable releases
1 version withdrawn
withdrawn after publishing
16 years old
54 releases · first in 2011
Deprecated passing a bool as timeout or check_interval . bool subclasses int , so Lock(timeout=True) has always meant one second and timeout=False zer…
4.4.0:
timeout or check_interval.bool subclasses int, so Lock(timeout=True) has alwaystimeout=False zero, rather than anything theTypeError in 5.0. Reported and originally patched by Jonpytest.raises pattern wasRestored the coverage badge. CI now merges the coverage data from every matrix cell, holds the merged result to the same 100% threshold each cell alre
4.3.2:
setup-uv acrossOne column per quarter.
Refreshed the README in Markdown and added a branded documentation landing page, light and dark logos, and links to the locking guides. README example
4.3.1:
check_interval no longer adds a full interval after the timeout.The filehandle returned by Lock and RLock is now typed by the open mode ( #97 ): a literal text mode yields IO[str] , a literal binary mode IO[bytes]
4.3.0:
The filehandle returned by Lock and RLock is now typed by the
open mode (#97): a literal text mode yields IO[str], a literal
binary mode IO[bytes], so fh.read() type-checks as str or
bytes instead of Any. Both classes are generic over the
filehandle (Lock[IO[bytes]]), with a PEP 696 default that keeps a
bare Lock annotation valid and equal to Lock[IO[str]],
matching the default mode of 'a'. A mode that is not a literal at
the call site (a Mode-typed variable, a conditional) falls back
to the honest IO[Any] of 4.2.0 through a catch-all overload.
TemporaryFileLock and its PidFileLock subclass are pinned to
IO[str]. No runtime dependency was added: the type variable
default comes from a typing_extensions import that only type
checkers see.
New portalocker.types.TextMode and portalocker.types.BinaryMode
aliases drive the overloads above. portalocker.types.Mode stays a
single flat Literal, so typing.get_args(Mode) still returns
the mode strings themselves and the
mode in typing.get_args(Mode) validation idiom keeps working.
Migration notes for the stricter typing, in decreasing order of
likelihood that they hit you:
-> Lock that returns a binary-mode lockLock is invariant and bareLock means Lock[IO[str]]). Annotate it-> Lock[typing.IO[bytes]].class MyLock(Lock)) is a text lock. Using itIO[str] on both mypy andclass MyLock(Lock[IO[bytes]])) or keep it genericclass MyLock(Lock[IOT])).Lock annotation. Strict-mode checking of code usingLock needs mypy 1.9 or newer; pyright has understood_get_fh, _get_lock and _prepare_fhtypes.IO) now failtyping.IO[str] for a bare subclass.super().__init__(): no overloadLock._init, the plain method RLock itself uses.Lock and RLock accept subscriptionLock[typing.IO[bytes]] raised TypeError on 4.2.0), andRLock.__init__ now initializes through Lock._init insteadLock.__init__, which monkeypatched constructorsThe main-thread interrupt is governed by the new interrupt_on_lost parameter, defaulting to True in 4.2 with a DeprecationWarning at loss time when le…
4.2.0:
RedisLock subscription nowretry=Retry(NoBackoff(), 0, supported_errors=()),health_check_interval (a supplied connection left at the redis-pysubscription_connection_factory parameter. Note that undersocket_timeout of five seconds a readRedisLock: a newportalocker.LockLostError (carrying channel, holder_id__cause__), a lost property, anensure_held() check for long critical sections, an on_lostwith block exit that raises LockLostError afterrelease() neveracquire() on a lost instance resets it (#137, #141)RedisLock worker failures to what actually failed: aBaseException (a SystemExit or KeyboardInterruptinterrupt_on_lostDeprecationWarningRedisLock teardown fork safe: a forked child inheriting arelease() orrelease() forever. A child that needs the lock must build itsRedisLock.check_or_kill_lock (removal in 5.0.0): itsacquire. The new read-only RedisLock.probe() answers "whoRedisLock non-blocking acquisition raising AlreadyLockedfail_when_locked writers on aRedisLock writer being usurped by a later writerelected fieldelected: false is visible, since thatRedisLock reply-staleness window that could yield twoAlreadyLocked after a full release under fail_when_locked. ARedisLock protocol to around a hundredtimeout=0, almost always missed a reply that wasRedisLock with fail_when_locked now raises only on atimeout, which also lets a non-blocking acquiretimeouttimeout=0 to keep the strictRedisLock.__exit__ on two edges: the lost flag isrelease, so a revocation landing in the instant the block exitswith body -__context__ withLock.__exit__ has carriedon_lost callback to call release() on the lock itRuntimeError: cannot join current thread after mostRedisLock.acquire stranding a live subscriptionPUBSUB NUMSUB timeout, for example): the erroracquire asrelease on it by hand. ARedisLock hanging forever in acquire or releasePubSubWorkerThread.run sets itsstop() clears that samestart() and thejoin(). The lock reachesfail_when_locked) and theRedisLockself_check_interval, default None meaning off): everymin(self_check_interval, unavailable_timeout)RedisLockSelfCheckError__cause__ of the LockLostError - and surfacesRedisLock (fencing=True):INCR on the never-expiring<channel>-fence key right after the confirm probe and exposesfence_token, so resources that can check fencesNonerelease foracquire, and is never drawn forINCR fails the acquire (transientLockBase base class (theRedisLock stub and the pubsub failure escalation were allpragma: no cover comments, so theraise AssertionError,raise NotImplementedError, except ImportError: and friends)import msvcrt guards inside theos.name == 'nt' branch were removed outright: msvcrt shipsrelease() calls on one Lock unlocking arelease() reentering from a signal handler (the standardTemporaryFileLock.release and PidFileLock.releaseKeyboardInterrupt escaping fh.close() during releaseBoundedSemaphore instance bothLockException instead ofos.fork in another thread cannotKeyboardInterrupt or SystemExit landing between aBoundedSemaphore slot lock succeeding and its publicationPidFileLock got for its sidecarrelease(), acquire() oros.register_at_fork, the way the standard library's loggingAttributeError when invoked directly on Windows: CPython only_at_fork_reinit into its lock types on builds withfork, so the hook now skips state locks without the method andnt, where nothing ever forksPidFileLock.read_pid raising UnicodeDecodeError for aNone like any other unreadable value, on every platformPidFileLock.read_pid raising ValueError for a PID fileNone like any other junk instead of leaking an exception theRLock.release zeroing the count and claiming the handle inPidFileLock.acquire contender's rollback wiping__exit__ then no-oped and garbage collection of itsPidFileLock.acquire crashing with AssertionError (orNone under python -O) when a signal handler'srelease() landed between publishing the lock and returning: theLock.acquire on one instancelockf) bothTemporaryFileLock and thePidFileLock sidecar against reentrant releases: a handle aLockExceptionValueError from fileno() or anEBADF OSError from fstatLock resolves its path with os.path.abspathfilename attribute now holds an absoluteos.chdir between acquire and release (the daemonize idiomchdir('/')) made release and the interpreter-exit cleanupKeyboardInterrupt during Lock.acquire leaking therelease a silent no-op) when it landed between theacquire, interrupts included, now unlocks and closes thePidFileLock.acquire rolls its sidecar back theTemporaryFileLockPidFileLock constructed before a fork and acquired inside thePidFileLock a stale PIDwith lock: block entered before a fork__exit__ in both processes, so the daemonize pattern mustos._exitRLock losing acquire counts when two threads nestedPidFileLock.__exit__ replacing the with body's ownraise_on_release_error in both directions: the POSIX releaseLock.__exit__ now (release failures are chained onto the body'sPidFileLock.release followsTemporaryFileLock and PidFileLock rejecting theraise_on_release_error keyword their documentation described:TemporaryFileLock.releasePermissionError failure escape regardless ofraise_on_release_error, unlike the POSIX path, and sleeping oncePidFileLock.acquire no longer normalizes plainLockException failures from the sidecar to AlreadyLocked.AlreadyLocked means contention and nothing else; a terminalENOLCK, an unsupported filesystem) propagatesfh, which made every contention raised inside amultiprocessing worker crash the result pipe withMaybeEncodingError: ... cannot pickle 'TextIOWrapper' instead ofAlreadyLocked to the parent. Pickling now drops thefh_namecopy.deepcopy drops the handle thecopy.copy keeps fh shared with the original__copy__, since a shallow copy never leaves thename lookupio.TextIOWrapper) no longer breaks exceptionAlreadyLocked raised by Lock.acquire withfail_when_locked=True having strerror=None with the OS message.strerror is populated at the Lockargs[0] is therefore nowOSError (POSIX) or error code (Windows) instead of__cause__.fh and holder_pid from the innerfh_name and the holder PID survive a pickle across__cause__ does notunlock now raisesportalocker.LockException instead of leaking the raw OSError,OSErrorerrno) stays reachable through args[0] and__cause__. The NFS-specific EOFError is wrapped as well,lock already didexceptions.FileToLarge: no version of this package hasDeprecationWarning onLOCK_FAILED code as args[0], but the POSIX lockersOSError there. Both real shapes are nowlock/unlock docstrings note that a raw(lock, unlock) callable tuple owns its own error translation, and'r+' example now creates its file firstRedisLock stale-holder cleanup killing healthy holders ofCLIENT LIST names, so aa matched the holders of a channel nameda-lock-b (whose connections are named a-lock-b-lock-<id>) anda-lock-. Client names are now matched exactly against<channel>-lock-<32 character hex holder id> shape, and the<channel>-lock name is still reaped as before (#142)RedisLock sleeping out a jittered check_interval before itsget_message(timeout=...) calls block on their own (#144)RedisLock instance that is alreadyportalocker.LockException instead ofAssertionError. The assert was the only re-acquire guard andpython -O strips asserts, which silently orphaned the worker threadRedisLock: holders onRedisLock teardown exception safe. release now runs everythread,pubsub and a self-created connection regardless, and re-raises onlyUNSUBSCRIBE (Redis unreachable whilepubsub behind that madeacquire on the instance fail its already-active guardRedisLock rollback for a worker thread that fails toacquire instead of RuntimeError: cannot join thread before it is started, and the subscribed pubsub no longerRedisLock.release no longer checks a fresh connection out of theUNSUBSCRIBE for a subscription the workerRedisLock.__del__ fail loudly at interpreter shutdown (#140)RedisLock.__del__ is now best effort and suppresses all errorsRedisLock with a self-created connection (noconnection= argument) killing its own worker thread and delivering aKeyboardInterrupt to the main thread. The release between retriesacquire kept resubscribing onchannel_handler failed its connection assertacquire gives up (#136)RedisLock probe reading at most one reply per pollingunavailable_timeout no matter how fast the holdersRedisLock.acquire races that could let two writers boththreading.Lock,pending from a writerPUBSUB NUMSUB reports counts rather than identities, and is tolerated becauseRedisLock requires aPUBSUB NUMSUB is node-localLockBase.__del__ released the OS lock, closed theTemporaryFileLock and PidFileLock, unlinkedfh = Lock(path).acquire() therefore lost mutual exclusion instantly,TemporaryFileLock still cleansatexit handler.release() now honours raise_on_release_error=False on theLock and TemporaryFileLock teardown paths:TemporaryFileLock.release() suppressed only FileNotFoundErrorPermissionError from a read-onlywith block. Suppressed release errors are nowLock.__exit__ guarantees theraise_on_release_error__context__, andPidFileLock overrides __exit__ but routes it throughLock.__exit__ and its release honours the flag as well, bothPidFileLock.__exit__ bullet aboveLockBase.__delete__ releasing the wrong object: deleting adel owner.attribute) calledrelease() on the owner instead of the lock, raisingAttributeError and leaving the lock held. The lock now releasesLock.release()lock() now validates its flagsLockFlags.UNBLOCK raise RuntimeError (on POSIX they used tofcntl). SHARED | EXCLUSIVE raises RuntimeError. A flagLockFlags(0) or NON_BLOCKINGRuntimeError on every platform instead of on POSIXMsvcrtLocker fallback table for LK_* constantsmsvcrt. The old values were shifted against the real<sys/locking.h> numbers, so a "blocking lock" through the fallbackLK_LOCK fell back to theLK_UNLCK value). The corrected values also now live on the lockersetattr'd onto the shared stdlibmsvcrt moduleWin32Locker.lock now wraps OSError (for example a stale filemsvcrt.get_osfhandle) in LockException,OSError escapedlock()Win32Locker now creates a fresh OVERLAPPED structure for everyLockFileEx/UnlockFileEx call instead of reusing one cachedpython -m portalocker combine now reads and assembles all of its--output-file. It used to truncate theREADME.rst and LICENSE now log the same snippet, naming theportalocker.RedisLock is now a stub class whose constructor raisesImportError naming the dependency and the install commandpip install "portalocker[redis]"). It used to be None, soTypeError: 'NoneType' object is not callable. Code that compared RedisLock is None to detect theImportError insteadU) mode strings from theportalocker.types.Mode literal. Python 3.11 removed them, and 3.10msvcrt lock retries ten times at oneLockfLocker: it silently used flock up to 3.2.0, and thelockf changes same-process contention, makesLock.acquire leaking an open, still locked filehandle whenw on a macOS append-only (chflags uappnd) file, where theEPERM. self.fh was never assigned, sorelease was a no-op while the escaping traceback pinned the handleLock.acquire now retries only contention, whichAlreadyLocked. A plainLockException, such as flock refusing a FIFO or an NFS/SMBENOLCK, or the EOFError somefcntl, is permanent: it is now raisedfail_when_locked=True it is no longer wrapped inAlreadyLocked, which claimed somebody held a lock on a filesystemBoundedSemaphore: a plain LockException while probing a slotAlreadyLockedLockBase._timeout_generator sleeping past its deadline by upcheck_interval: a contended Lock(timeout=0.5, check_interval=3) gave up after roughly 3 seconds instead of 0.5.RedisLock is unaffected, it overrides the generator with its ownLock built with an explicit timeout (at constructionacquire), pointing at portalocker's own sourceRLock,TemporaryFileLock and PidFileLock instances constructedfilterwarnings = error. The subclasses now forward None so theRLock.acquire on an instance whose acquire countportalocker.LockException instead of relying on a bare assert,python -O strips, silently handing the caller None asLock modes containing w on POSIX.a substitution left O_APPEND set, sofh.write('x'); fh.seek(0); fh.write('y') produced 'xy' where the builtin open(mode='w')'y'. The append flag is now cleared once the truncationTemporaryFileLock.acquire destroying a held/tmp is enough). The inode re-check introduced withtimeout=0AlreadyLocked after having dropped the lock it actuallyLockExceptionPidFileLock re-acquire runs the same verification on its sidecar.release now also skips the unlink, with a warningos.path.samestat, which checksTemporaryFileLock.acquire verification retry restartingtimeout**2 / check_interval. The retries nowPidFileLock.acquire on an instance that already holds theLock wasPidFileLock ignoring its instance-level timeout andcheck_interval when acquiring with fail_when_locked=False: theLock was built from the per-call arguments only, so aNone argument silently selected the five second module defaultPidFileLock(path, timeout=0.4).acquire() block for five secondsacquire(timeout=0.4) behaved. The call arguments are nowLockBase contractPidFileLockacquire storedLock before taking it and only except ExceptionKeyboardInterrupt or SystemExit (a SIGTERMsys.exit is the usual daemon idiom) left therelease additionally refuses to unlink anything whenLock no longer holds a filehandle. An interruptPidFileLock used as a context manager now raisesAlreadyLocked on entry when another process holds the lock but itsNone in that case, which the documented contract definesPidFileLock.read_pid now only accepts a plain positive ASCIINone). It used toint accepts, including -1, 0, +7,1_000 and non-ASCII digits, and the obvious consumer feeds theos.kill, where -1 signals every process the user ownsPidFileLock publishing the PID by truncating the PID file inos.replace, so readers see either the old complete PID or the newPidFileLock.release path unlinking the PID fileTemporaryFileLock and PidFileLock now annotate filename astypes.Filename like Lock does, so passing a pathlib.Path,BoundedSemaphorefail_when_locked contracts. The constructorAlreadyLockedacquire documented what the code hastimeout has expired. The runtime behaviour is unchanged and theAlreadyLocked, or returnsNone with fail_when_locked=False. Both the timing and thatNone return diverge from the other lock classes and are nowBoundedSemaphore orNamedBoundedSemaphore instance that already holds a slot nowportalocker.LockException instead of AssertionError.python -O stripsBoundedSemaphore default-name DeprecationWarningstacklevel=1). ItTemporaryFileLock and PidFileLock registering oneatexit callback per constructed instance and never unregisteringTemporaryFileLock andPidFileLock no longer releases locks a forked child inheritedportalocker.open_atomic now raisesFileExistsError when the destination already exists on entry,AssertionError beforeportalocker.open_atomic: publicationopen_atomic fails to publish, for anyopen_atomic publishing destinations with the private0o600 permissions of its temporary file. The temporary file is0o666 so the kernel applies the processopen would have produced, without portalocker ever touchingBoundedSemaphore operational hazards: a slot fileopen_atomic does not fsync theFixed the README demonstrating BoundedSemaphore without a name , which the library itself deprecates in favour of NamedBoundedSemaphore
4.1.0:
... bodies on the abstractLockBase.acquire/LockBase.release stubs with docstrings.ruff's pydocstyle rulesportalocker/ with no exemptionscombine CLI, troubleshooting, and a 3.x to 4.0.0docs/api/ and adocs/platforms.rst documents the advisory-versus-mandatoryflock versus lockf, msvcrt versus pywin32, and thedocs/cli.rst documents the combiner's ASCII-only requirement onportalocker/*.py, README.rst and LICENSE, which was previously__main__.pydocs/*.rst and README.rst as well as the# doctest: +SKIP remains anywhereValueError: I/O operation on closed fileBoundedSemaphore without a name,NamedBoundedSemaphoreFixed open_atomic() replacing a destination created while its context was open on POSIX; publication now raises FileExistsError and preserves the conc
4.0.0:
open_atomic() replacing a destination created while its contextFileExistsError and preservespywin32 is no longer installed by default on Windows; the msvcrt-basedportalocker[win32], and an informativeImportError is raised otherwise (#104).strerror and pass the message asstr() output of these exceptions on POSIX from theOSError text to a 2-tuple reprLockBase is now generic over the acquire return type (typing-onlyLock subclasses are unaffected)PidFileLock for pidfile-based locking (#106)PidFileLock.fail_closed() for ownership-only contexts; contentionAlreadyLocked before entering the body and exposes the competingAlreadyLocked.holder_pid when readable (#118)uv_build backend; releases are published topython -m portalocker combine: --output-file now opens lazily;RedisLock (it wasNone before); the smoke-run now uses sys.executablePidFileLock ignoring timeout when fail_when_locked=False;TemporaryFileLock/PidFileLock unlock-then-unlink race thatBoundedSemaphore staying permanently "Already locked" after aRedisLock crashed-holder detection: the liveness check wasfail_when_locked=True fails fast instead of polling the full timeout,acquire() rolls back cleanly so the lock can be retriedRedisLock readers through LockFlags.SHARED. WaitingFlockLocker/LockfLocker on POSIX to use their named syscallLOCKER); the module-levellock()/unlock() on POSIX now accept all documented LOCKERLockException per the documented contractRedisLock tests now run everywhere via fakeredis, with a liveLock.release() continues suppressing unlock and close errors by default;Lock(..., raise_on_release_error=True) (#117)TemporaryFileLock.release() and PidFileLock.release() are nowTemporaryFileLock no longer keeps a strong atexit reference toNamedBoundedSemaphore is now exported from the top-levelportalocker namespaceRewrote locking mechanism to allow for custom locking classes so both Windows and Posix (Linux/Mac/BSD) systems have configurable locking options for
Rewrote locking mechanism to allow for custom locking classes so both Windows and Posix (Linux/Mac/BSD) systems have configurable locking options for both exclusive and shared locking.
removed accidental toml requirements
removed accidental toml requirements
Improved type hints thanks to @jonde94 and modernised CI setup.
Improved type hints thanks to @jonde94 and modernised CI setup.
…formatting and checking. Dropped support for deprecated Python versions, only 3.9 and up are supported now.
Completely modernized portalocker build system and added fully strict pyright and mypy compliance with ruff formatting and checking. Dropped support for deprecated Python versions, only 3.9 and up are supported now.
fixed typo thanks to @harmstyler
fixed typo thanks to @harmstyler
Properly propagating exceptions for NFS read-only lock issues and added support for being able to choose between lockf and flock thanks to @oliver-s-l
Properly propagating exceptions for NFS read-only lock issues and added support for being able to choose between lockf and flock thanks to @oliver-s-lee
Removed docs from build to fix #88 again
Removed docs from build to fix #88 again
Removed docs from build to fix #88
Removed docs from build to fix #88
Added support for Python 3.11 and 3.12 thanks to @hugovk. Made the package fully ruff, pyright and mypy compliant with automated testsing using both t
Added support for Python 3.11 and 3.12 thanks to @hugovk. Made the package fully ruff, pyright and mypy compliant with automated testsing using both tox and Github actions
Added fail_when_locked=False support to BoundedSemaphore thanks to @flaviens
Added fail_when_locked=False support to BoundedSemaphore thanks to @flaviens
Added fileno() support. Fixes #80 on posix systems
Added fileno() support. Fixes #80 on posix systems
Added clear warning when locking in non-blocking mode without specifying either EXCLUSIVE or SHARED mode. Fixes #77
Added clear warning when locking in non-blocking mode without specifying either EXCLUSIVE or SHARED mode. Fixes #77
Fixed shared locks on Windows and simplified locking mechanism
Fixed shared locks on Windows and simplified locking mechanism
Added warning when trying to use a timeout in blocking mode. And removed deprecated testing code and checks
Added warning when trying to use a timeout in blocking mode. And removed deprecated testing code and checks
commit 5590a941f915904846593745ec632d2e42259534 Merge: 4257ced 0806422 Author: Rick van Hattem Date: Fri Aug 27 15:44:10 2021 +0200
commit 5590a941f915904846593745ec632d2e42259534 Merge: 4257ced 0806422 Author: Rick van Hattem Wolph@wol.ph Date: Fri Aug 27 15:44:10 2021 +0200
Merge tag 'v2.3.2' into develop
Added semver indicator and specified needed Python release thanks to @rayluo v2.3.2
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEEFJMl/RWQTpxOuJ6V6BRE6c4faV0FAmEo7CoACgkQ6BRE6c4f
# aV3OJA/+O4ck6qU/Tf7yudYCYK+xh+dpZ4A3kfxX/Ed5K0Q/1CQhQee1hqO7p4NE
# aTQbLpjsIBrpNNKjgHkz7qKXFDLhjygji0R6YRE4dxXbEbEdC98NY907FMOEO0kM
# cKZt/3FFBpW/LgTYnJ12cIw5Cwh+kHGnRIyisdUZuMcp3sTpANhMZ9eySyhrdh5k
# T3eROMZ+b0qItGnJcMPcyGz/UkkyKWdFH9cN63wMq1doh3nETdib761h47p/hmBz
# FYuYb5rmA9O2OORLJ1D06Q5d/KxIWG5u4XNYoNQ3BWBIPf53bcqkvcnztu5IyJmd
# ojEW8WAMRPp5m4tdS1Y/DrsplQxU5A83VW7Hu0DGB3xv4y0vsO9TIlEPgKCMu/jG
# Je2RQOMJarmLNin4MYs8DCn4p97mQBOyX+HKr4wa2IV+0lJd0+TaTqtKAx626HMQ
# Dq/d58g2n+F0vTjr0+2VeJAhsIXdbgDyAC2NN8rS6DEInmLZgDnHmu57VomEeR7Q
# NcClcO5O2dEtjBLt1SnKkXpjc8VqU1yHMwCnI8KUo40Iq7hLrSBqBGbHP7Jp7rRz
# cWuNdRtRmWTjHnA9JeH327ScC6Ikzuv7rbPRZttHliuGMxxHSLKc48S2xL1k7Cq4
# 5edh7gW5VDvA6e5cevt9PAHLeQRECecWEASkd1ca8AUNkZ+dheE=
# =FmXv
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri Aug 27 15:44:10 2021 CEST
# gpg: using RSA key 149325FD15904E9C4EB89E95E81444E9CE1F695D
# gpg: Good signature from "/Rick van Hattem <wolph@wol.ph>"/ [ultimate]
# gpg: aka "/[jpeg image of size 9662]"/ [ultimate]
commit d0eab0512b6640beca9f702f9ea6965ac9d686d5 Merge: 90d267a 248e450 Author: Rick van Hattem Date: Sat Aug 21 11:22:36 2021 +0200
commit d0eab0512b6640beca9f702f9ea6965ac9d686d5 Merge: 90d267a 248e450 Author: Rick van Hattem Wolph@wol.ph Date: Sat Aug 21 11:22:36 2021 +0200
Merge tag 'v2.3.1' into develop
Removed Python 2 classifier thanks to @rayluo v2.3.1
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEEFJMl/RWQTpxOuJ6V6BRE6c4faV0FAmEgxdwACgkQ6BRE6c4f
# aV28wA/+I2QuCx+G+Dqqo6ofvaSVe41f9nkgq+ce8v0guaLXptsZ478uuRMPG+1E
# 6TnuIb4bi0nUJp0C4Qj5ET5554OoD+wEE9t77H8Z18pYMT3Jdm6ZqSAAN+Hrl50/
# AtcP9B3l32Bj9wViaoo/9xt4vL0EDBPqpDo6q/xB/0OPUfMcWAvYky3yIGs61rLQ
# nQIlTqEFjz12dHCh+0uBTJ5AUbKRGYDj5VMufXS56U5jSMcAaIgTRAtPjbJJHTAL
# xoVcO7zgz/4uoAUtEuw+VEqVYMWE88hxnl9jS/KNyZv+QANA0vkRsiEssRw5QFh+
# ftzxZ4PzXDv7WzwF82XVU2c7JwPX9PxlZhtwSRZ00q3Uit2fhTVRXPwbPQ7rb3Is
# tUcT0wxYuIarA53iQEgbfeyWz3Hhi6ayBJeap/OC9KfyXBZiic2tOTTwhOXkBGw6
# w3uJdj8ZDhOLJbtnOaJi51xwlmA861YJODkr3vP2HjjgepgCcQMK0nLPnYHUXYe/
# qKFC9Z1CArgA+1lic4pKC402gpGoG7tJgyldoagKsbDgbz5nTKt/BQLhjT3vPavJ
# bYTphyQ4H3WUkK6ac5M6gN4exSBACYaKWyL7DltPoBrP8CyOzFexTCkoUw9WYCwv
# 8ut8Y7cqN9Da++Xgnfj6sdrY9IuCpPQJZCWJ1NOhMAORN1sMw+g=
# =YDYj
# -----END PGP SIGNATURE-----
# gpg: Signature made Sat Aug 21 11:22:36 2021 CEST
# gpg: using RSA key 149325FD15904E9C4EB89E95E81444E9CE1F695D
# gpg: Good signature from "/Rick van Hattem <wolph@wol.ph>"/ [ultimate]
# gpg: aka "/[jpeg image of size 9662]"/ [ultimate]
commit 631352fbfd9f2b780a6d5f9da39646f4088910aa Merge: e99c2d6 ec9f5da Author: Rick van Hattem Date: Sun Mar 28 04:18:59 2021 +0200
commit 631352fbfd9f2b780a6d5f9da39646f4088910aa Merge: e99c2d6 ec9f5da Author: Rick van Hattem Wolph@wol.ph Date: Sun Mar 28 04:18:59 2021 +0200
Merge tag 'v2.3.0' into develop
enabled PEP 561 compliance v2.3.0
# gpg: Signature made Sun 28 Mar 04:18:59 2021 CEST
# gpg: using RSA key 149325FD15904E9C4EB89E95E81444E9CE1F695D
# gpg: Good signature from "/Rick van Hattem <wolph@wol.ph>"/ [ultimate]
# gpg: aka "/[jpeg image of size 9662]"/ [ultimate]
commit 638f67af428413ef6b2a45633b6e4f034b11f272 Merge: ad33bc1 061837e Author: Rick van Hattem Date: Wed Feb 3 02:10:59 2021 +0100
commit 638f67af428413ef6b2a45633b6e4f034b11f272 Merge: ad33bc1 061837e Author: Rick van Hattem Wolph@wol.ph Date: Wed Feb 3 02:10:59 2021 +0100
Merge tag 'v2.2.1' into develop
removed debug statement v2.2.1
# gpg: Signature made Wed Feb 3 02:10:59 2021 CET
# gpg: using RSA key 149325FD15904E9C4EB89E95E81444E9CE1F695D
# gpg: Good signature from Rick van Hattem <wolph@wol.ph> [ultimate]
# gpg: aka [jpeg image of size 9662] [ultimate]
commit 3c5ea798a5bb8163a5deabc866934ff3d08b3191 Author: Rick van Hattem Date: Sat Jan 30 02:27:50 2021 +0100
commit 3c5ea798a5bb8163a5deabc866934ff3d08b3191 Author: Rick van Hattem Wolph@wol.ph Date: Sat Jan 30 02:27:50 2021 +0100
updated travis location
v2.1.0 Added Redis based distributed lock which gracefully handles connection loss and dying applications. Added full type hinting support. Fixed bug
v2.1.0 Added Redis based distributed lock which gracefully handles connection loss and dying applications. Added full type hinting support. Fixed bug where the file handle was not always explicitly closed with errors
v2.0.0 Removed support for old Python versions. Versions 3.5 and above are supported. Added BoundedSemaphore class
v2.0.0 Removed support for old Python versions. Versions 3.5 and above are supported. Added BoundedSemaphore class
v1.7.1 removed tests from wheel file
v1.7.1 removed tests from wheel file
v1.7.0 Fix ResourceWarning unclosed file if LockException is raised. Thanks to @ahauan4
v1.7.0 Fix ResourceWarning unclosed file if LockException is raised. Thanks to @ahauan4
v1.6.0 Fixed unlocking bug on Windows. Fixes #49
v1.6.0 Fixed unlocking bug on Windows. Fixes #49
v1.5.2 Aded workaround for broken pywin32 226 release. Fixes #48
v1.5.2 Aded workaround for broken pywin32 226 release. Fixes #48
v1.5.1 Exclude portalocker_tests from installed packages
v1.5.1 Exclude portalocker_tests from installed packages
v1.5.0 Renamed tests to prevent collisions with other packages
v1.5.0 Renamed tests to prevent collisions with other packages
v1.4.0 Fixed #42. Added support for file open kwargs
v1.4.0 Fixed #42. Added support for file open **kwargs
v1.3.0 Added fh attribute to LockExceptions which contain the file handle
v1.3.0 Added fh attribute to LockExceptions which contain the file handle
v1.2.1 Modernized requirements
v1.2.1 Modernized requirements
v1.2.0 Finally got windows working with both python 2 and python 3?
v1.2.0 Finally got windows working with both python 2 and python 3?
v1.1.0 Fixed crash with python 3.6 (#32) and using real time to calculate timeout (#33) thanks to @TWAC
v1.1.0 Fixed crash with python 3.6 (#32) and using real time to calculate timeout (#33) thanks to @TWAC
v1.0.1 Changed default for fail_when_locked to be more logical
v1.0.1 Changed default for fail_when_locked to be more logical
v1.0.0 1.0.0 changes the default behaviour of the Lock class from truncate to append which makes it safer for new users. Additionally it features much
v1.0.0 1.0.0 changes the default behaviour of the Lock class from truncate to append which makes it safer for new users. Additionally it features much improved documentation, restructured code, 100% test coverage and a single combined file for easy integration with other projects.
Nothing published for this version
Nothing published for this version
Nothing published for this version
v0.5.6 Added atomic_write utility function
v0.5.6 Added atomic_write utility function
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →