4.3.0:
-
The filehandle returned by
LockandRLockis now typed by the
open mode (#97): a literal text mode yieldsIO[str], a literal
binary modeIO[bytes], sofh.read()type-checks asstror
bytesinstead ofAny. Both classes are generic over the
filehandle (Lock[IO[bytes]]), with a PEP 696 default that keeps a
bareLockannotation valid and equal toLock[IO[str]],
matching the default mode of'a'. A mode that is not a literal at
the call site (aMode-typed variable, a conditional) falls back
to the honestIO[Any]of 4.2.0 through a catch-all overload.
TemporaryFileLockand itsPidFileLocksubclass are pinned to
IO[str]. No runtime dependency was added: the type variable
default comes from atyping_extensionsimport that only type
checkers see. -
New
portalocker.types.TextModeandportalocker.types.BinaryMode
aliases drive the overloads above.portalocker.types.Modestays a
single flatLiteral, sotyping.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:- A function annotated
-> Lockthat returns a binary-mode lock
now errors on every checker (Lockis invariant and bare
LockmeansLock[IO[str]]). Annotate it
-> Lock[typing.IO[bytes]]. - A bare subclass (
class MyLock(Lock)) is a text lock. Using it
with a binary mode silently yieldsIO[str]on both mypy and
pyright while the runtime hands out bytes, so pin it
(class MyLock(Lock[IO[bytes]])) or keep it generic
(class MyLock(Lock[IOT])). - Strict mypy older than 1.9 (March 2024) does not understand the
type variable default and reports "Missing type parameters" on
every bareLockannotation. Strict-mode checking of code using
bareLockneeds mypy 1.9 or newer; pyright has understood
defaults since early 2023, and non-strict mypy is unaffected. - Overrides of the
_get_fh,_get_lockand_prepare_fh
hooks that copied the 4.2.0 signatures (types.IO) now fail
override checks, because the hooks are typed by the class's type
variable. Re-type them with the subclass's filehandle type,
typing.IO[str]for a bare subclass. - A generic subclass cannot call
super().__init__(): no overload
binds an unsolved type variable. Run the parent initialization
throughLock._init, the plain methodRLockitself uses. - Two runtime-visible side effects, for code that introspects:
LockandRLockaccept subscription
(Lock[typing.IO[bytes]]raisedTypeErroron 4.2.0), and
RLock.__init__now initializes throughLock._initinstead
of callingLock.__init__, which monkeypatched constructors
notice. Everything else is unchanged at runtime.
- A function annotated