-Fu is how a Python package is found, and nothing says so
- Type: docs / discoverability — Track D (usage line lives in
compiler/**, so the one-line code change is Track A; the prose is D). - Found: 2026-08-17, first attempt at a third-party Python corpus ([[feature-nilpy-thirdparty-libraries-as-targets]]).
The problem
To compile NilPy code that imports a third-party package:
./compiler/pascal26 -Fu/abs/path/to/library_candidates/webencodings drv.npy drv
That works — it resolves from webencodings import lookup, decode, encode and
begins compiling the package's __init__.py. But -Fu is not in the
compiler's usage line, which prints only:
usage: pascal26/PXX [--debug] [--dump-ir] [-dNAME] [-uNAME] [-Mobjfpc]
[--strict-overload] [--strict-operator] [--strict-case]
[--strict-python] [--no-unhandled-handler] <src> [out]
Why it matters more than a missing flag usually would
Without it the failure is:
error: import: no unit named webencodings and no shim mimic_webencodings
which reads as "this feature does not exist" for a feature that does. My
first diagnosis was "pxx cannot resolve third-party packages at all", and the
natural next move — the one CPython teaches — is sys.path.insert(0, ...),
which silently does nothing because sys.path is a RUNTIME mechanism and pxx
resolves imports at COMPILE time. Neither the message nor the usage line points
anywhere.
This is the same shape as a recent day lost on synapse: the mechanism existed and nothing pointed at it.
What to do
- Add
-Fu<dir>to the usage line (one line, Track A). - Improve the message.
no unit named Xshould mention the search path — e.g....and no directory on the unit search path contains it (-Fu<dir>). That single clause converts a dead end into a next step. - Document it in the NilPy docs where third-party imports are discussed:
-Futakes the directory containing the package directory (forlibrary_candidates/webencodings/webencodings/, passlibrary_candidates/webencodings), matching Python's own "parent of the package" path convention.
Note
sys.path manipulation is not a bug and should not be made to work — a compile
-time resolver cannot honour a runtime list. Worth saying explicitly in the docs
so the next person does not file it: the NilPy answer to sys.path is -Fu.
2026-08-17 — the wall table quoted above is SUPERSEDED. It came from a scan that passed only the scanned file's own
-Furoot, so cross-package imports (tinycss2->webencodings) recorded as compiler walls. Corrected table and the tool that now produces it (tools/nilpy_ladder.py): [[bug-t-the-ladder-scan-passes-only-one-root-so-cross-package-imports-read-as-walls]]. Thewebencodingsandconstantsrows were artefacts and are gone; the real top two areundefined variable (digits)(8 files) andundefined variable (CodecInfo)(7 files).
Resolved 2026-08-19 (Track D, pin v364) — with a correction to the ticket's own example
Documented in two places: a Finding a third-party Python package section in
docs/targets/nil-python.md, and an expanded -FuDIR row in
docs/reference/cli.md that links to it. The misleading failure
(no unit named X and no shim mimic_X) and the sys.path.insert dead end are
both named, since the whole point is that the error reads as "feature missing".
Measured, and it corrects the ticket: -Fu must point at the directory
that contains the package, not at the package directory. With
pkgdir/mypkg/__init__.py, from mypkg import greet resolves under
-Fu…/pkgdir and fails under -Fu…/pkgdir/mypkg — the same shape as
Python's own path. The ticket's example (-Fu…/library_candidates/webencodings)
points at the package itself. A plain single-file module in the search root is
found too.
The usage-line half stays open: the prose is Track D's, but adding -Fu to the
compiler's own usage: output is a one-line Track A change and is not done
here.
Log
- 2026-08-19 — resolved, commit d45d131ad.