Command-Line Interface¶
portalocker ships a small command-line interface, invoked as
python -m portalocker. Its only subcommand, combine, bundles the
package into a single vendorable portalocker.py file for projects
that cannot add portalocker as a dependency – a vendoring or
single-file-deployment constraint, for example – and instead copy one
generated file with the same public API into their own tree.
Running combine¶
$ python -m portalocker combine
This writes the combined file to dist/portalocker.py by default.
Pick a different destination with --output-file/-o:
$ python -m portalocker combine --output-file vendor/portalocker.py
$ python -m portalocker combine -o vendor/portalocker.py
If the ruff command is available, the output is formatted and
lint-fixed in place; if not, that step is skipped with a warning. Either
way, the generated file is then executed once as a smoke test, so a
broken combine surfaces immediately rather than only when a downstream
project imports the file.
What the transform does¶
Starting from portalocker/__init__.py, combine walks the
package’s modules and inlines every relative import it finds –
from .foo import bar and its parenthesised multi-line form – with
the source of the referenced module, recursively, so the result has no
relative imports left. A module referenced from more than one place is
only inlined once.
if TYPE_CHECKING: blocks are the one exception: they are copied
verbatim rather than inlined, preserving the runtime guard their
else-branch relies on. That includes the optional
try: from .redis import RedisLock guard in __init__.py:
redis.py is inlined like any other sibling module, re-indented to
stay inside the try, so the combined file binds RedisLock the
same way the package does – to None if importing redis fails.
Qualified references left behind by inlining (constants.LockFlags
becoming just LockFlags, for instance) are cleaned up, and useless
self-assignments the cleanup can produce (spam = spam) are stripped
entirely.
README.rst and LICENSE are also copied near the top of the
output, each wrapped in a triple-quoted string, for reference.
Limitations¶
The combined file still needs the redis package installed for
RedisLock to work: combining inlines the code that binds to
redis, not redis itself.
Every file combine reads – the package’s own modules, plus
README.rst and LICENSE – is opened with encoding='ascii'.
That means the entire portalocker source tree, along with
README.rst and LICENSE, must stay ASCII-only: an em dash, curly
quote, box-drawing character, or any other non-ASCII byte anywhere in
those files makes combine raise UnicodeDecodeError instead of
silently mis-encoding the result. portalocker_tests/test_combined.py
asserts the combined output can still be produced, which is how a stray
non-ASCII character elsewhere in the package gets caught by the test
suite. Keep contributions to those files ASCII-only for this reason.