Parity push #1 — six gap fixes on top of the 11-phase plan:
- Parent-module bindings: `import a.b.c` now binds `a`, `a.b`, `a.b.c`
via py_bind_dotted_prefixes. Walks the dotted prefix chain on every
import, regardless of import_is_from_style. Plus an attribute-access
path on a MODULE that detects submodules: when the registry has any
function whose qn starts with `<mod>.<attr>.`, evaluating `mod.attr`
yields MODULE("<mod>.<attr>"). This makes `os.path.join(...)` and
similar resolve correctly.
- typing.cast(T, x) returns NAMED(T) (re-evaluating T as an annotation,
so generic subscripts and forward references both resolve). Detects
bare `cast(...)` and qualified `typing.cast(...)` forms.
- typing.assert_type(x, T) is a no-op at runtime; we type the result
as type-of(x).
- Forward references as quoted strings: `def f(x: "Foo")` strips quotes
and re-resolves the inner annotation. Also handles double-quoted and
single-quoted forms.
- Self return type substitution: methods declared returning `Self` /
`typing.Self` / `typing_extensions.Self` substitute to NAMED(receiver)
at call resolution time. Enables fluent / builder pattern chaining
to keep resolving methods after each step.
- Generic subscript stripping: annotations like `list[Foo]` strip to
`list` for v1; `Optional[Foo]` likewise. Container element-type
substitution still deferred (Phase 8+).
Generator additions:
- Allowlist now includes urllib, http, concurrent (top stdlib usage).
- `from X import *` re-export following at generation time. Modules
like os.path (a star-import shim of posixpath / ntpath / genericpath)
now have all forwarded definitions registered under their own QN.
Iterates to a fixed point with an 8-step ceiling. typeshed tree
expansion is bounded — only modules transitively reachable from the
allowlist are pulled in.
Stats: 137 modules, 904 classes (2797 methods), 886 free functions
(was 114 / 753 / 794). Generated file grows from 20K to ~22K lines.
6 new test_py_lsp.c cases. All 2874 prior tests stay green.
Phase 10 of Python LSP integration. Adds:
- scripts/gen-py-stdlib.py: walks a typeshed/stdlib checkout, parses
each .pyi via Python's stdlib `ast` module, and emits one C source
file populating cbm_python_stdlib_register. v1 simplifications:
- overload stacks collapse to first signature
- ParamSpec / TypeVarTuple / Concatenate skipped
- version guards (if sys.version_info >= ...) flattened to union
of branches
- per-symbol min/max version guards not yet emitted (v1.1 follow-up)
Module allowlist matches PYTHON_LSP_PLAN.md Phase 10 list — top
stdlib modules by usage in indexed Python projects, skipping
tkinter / turtle / curses / xml / email for size.
- internal/cbm/lsp/generated/python_stdlib_data.c (auto-generated,
20,021 lines): 114 modules, 753 classes (2,385 methods), 794 free
functions registered. Source pinned to typeshed commit
a7912d521e16ff63caf7a8b64b9072542be36777 (recorded in header).
Compiles cleanly under ASan + UBSan.
- lsp_all.c includes the generated file. The CBM_PYTHON_STDLIB_GENERATED
macro disables py_lsp.c's no-op stub so the real registration runs.
4 new test_py_lsp.c cases verify resolution against the registry:
os.getcwd, collections.defaultdict constructor, pathlib.Path.exists
method via typed parameter, logging.getLogger.
Known v1 limitation captured in test comments: `import os.path` only
binds the leaf `path` in scope, so `os.path.join` style chained
attribute access on the parent module name doesn't yet resolve.
Phase 10.5 will stamp parent-module bindings.
All 2869 prior tests stay green; 4 new stdlib tests pass.