Python readiness checklist
September 3, 2026 ยท View on GitHub
This checklist records the shipped Python preview and tracks the remaining work
toward a stable, broadly supported WinRT projection. The dynwinrt runtime and
standalone dynwinrt-codegen command are published on PyPI.
See docs/guides/python/python-ui-ecosystem.md for research on
Python UI frameworks, static pywinrt adoption, real integrations, and the value
of a dynamic projection.
Target states
- Data API preview (shipped): a clean machine can install wheels and generated bindings, then call supported Windows SDK APIs without Rust, Node.js, or a source checkout.
- Data API release (in progress): generated APIs follow normal Python semantics for typing, async, events, collections, errors, and lifecycle.
- WinUI preview (x64 validated): Python can bootstrap the Windows App SDK, enter an STA, construct composable WinUI classes, and load Fluent resources. Native ARM64 immediate teardown remains tracked in issue #116.
Verified baseline
- The PyO3 runtime builds on Windows ARM64.
- Generated
Windows.Foundation.Uribindings import and call real WinRT APIs on ARM64. - Python generation emits
.pyimplementations. -
--lang pyemits.pyi,__init__.pyi, andpy.typedby default. - Generated Python E2E covers 42 API specs and 88 checks.
- Runtime primitives exist for arrays, structs, delegates, events, cancellation, progress callbacks, vectors, and maps.
- Python codegen snapshots cover the
Uriimplementation and stubs.
P0: generated package correctness
- Replace eager cross-module runtime imports with cycle-safe lazy resolution.
- Keep referenced types visible to static type checkers through
TYPE_CHECKINGimports. - Model WinRT runtime-class and interface compatibility structurally in input annotations without changing runtime inheritance.
- Add an import regression for a real cyclic graph such as
Windows.Data.Xml.Dom.XmlDocument. - Preserve
Uriimplementation and.pyisnapshots. - Organize output by WinRT namespace instead of one flat short-name namespace.
- Derive Python symbols, implementation modules, facade modules, and stable path hashes from a namespace- and kind-preserving semantic type identity, including recursively closed generic arguments.
- Keep same-short-name types available through their namespace facades, omit ambiguous root exports, and use deterministic qualified aliases in consumer modules instead of selecting a short-name ABI implicitly.
- Pass an immutable Python projection context through generation and rendering instead of installing thread-local module-layout state.
- Detect and reject namespace/type filename collisions.
- Add stage/swap generation and remove stale Python output.
- Emit a consumable Python package manifest with an exact runtime dependency.
- Emit one canonical module and Python class per WinRT struct instead of duplicating incompatible struct classes in every consumer module.
- Make root and namespace exports lazy, keep ABI helpers in type-specific facades, and expose only Python types from public package indexes.
P0: runtime and generated API agreement
- Ship a
.pyiandpy.typedmarker for thedynwinrtextension. - Return declared enum members as generated
IntEnuminstances while preserving unknown values as integers. - Use
invoke_all()for arbitrary multiple-out methods. - Add Python E2E for
IVector.IndexOfand other multiple-out methods. - Project
IReference<T>return positions asT | None. - Accept
T | NoneinIReference<T>input positions. - Project null reference returns and reference-array elements as
T | Noneconsistently in runtime code and stubs. - Project
IReference<T>struct fields as nativeT | Noneon reads while accepting native values,None, and legacy wrappers on writes. - Preserve the full
UInt32/UInt64range when converting to Python integers. - Make Python stubs part of E2E and run a static type checker.
- Make
.pyigeneration the default for--lang py. - Pass full-package
mypy --strict, including collection overrides and cross-module struct arguments.
P0: async semantics
- Return a Python awaitable instead of blocking inside generated async methods.
- Integrate WinRT completion with an
asyncioevent loop. - Propagate Python cancellation to
IAsyncInfo.Cancel. - Expose progress without forcing generated wrappers to call
.wait(). - Keep an explicit blocking API for scripts and non-async hosts.
- Reject blocking waits from an STA when they could deadlock.
P0: CI and distribution
- Execute all tests under
bindings/py/testsin CI. - Build and install wheels before running Python E2E.
- Complete the first live CPython 3.11โ3.14 x64/ARM64 release-matrix run. Native ARM64 builds and isolated consumers run on GitHub-hosted Windows ARM64 runners.
- Remove unverified PyPy metadata.
- Derive Python artifact versions from ordinary
v<version>release tags, inject them only into ephemeral CI workspaces, and attach the complete wheel set to the shared JavaScript GitHub release. - Publish signed/provenanced wheels to an approved internal Python feed.
- Route production PyPI publication through the official 1ES ADO release
pipeline and Microsoft ESRP identity.
PublishPyPIis enabled by default for tag releases and can be disabled for non-PyPI rehearsals. - Complete one-time ESRP/PyPI onboarding for
dynwinrtanddynwinrt-codegen, including release owners and approvers. - Add complete tested Python wheel assets and installation notes to GitHub releases.
- Provide a Python-native codegen CLI wheel using maturin binary bindings.
- Add clean, isolated wheel consumers that import/call stock WinRT and run codegen with Cargo/Rust unavailable.
P1: Python-native behavior
- Map HRESULT failures to
OSErrorwith a stable.winerror. - Include restricted WinRT error information when available.
- Surface Python callback failures instead of returning unconditional success to WinRT.
- Document callback threads and require explicit event unsubscription.
- Preserve token-based
on_*/off_*compatibility and provide idempotentsubscribe_*and reentrancy-safeonce_*helpers. - Convert
TypedEventHandler/EventHandlercallback arguments to typed projected Python values. - Implement Python collection protocols for iterable, vector, and map projections.
- Accept normal Python sequences, mappings, bytes, UUIDs, datetimes, and timedeltas where the WinRT signature permits them.
- Emit
IntFlagfor flags enums. - Add overload-aware runtime dispatch and
typing.overloadstubs. - Generate idiomatic constructors such as
Uri(...)while retaining an internal wrapper path for returned native objects. - Expose
project_as(value, Type)for typed, non-consuming projection of rawObject/IInspectablevalues to RuntimeClasses, matching JavaScriptprojectAs; useas_interface()/ interfacefrom_value()for QI views. - Declare non-suppressing runtime and generated context managers as
Literal[False]. - Replace deprecated PyO3 automatic
FromPyObjectbehavior explicitly. - Document COM apartment ownership and provide a balanced context manager.
P1: tooling and documentation
- Add a Python configuration surface to winapp CLI or a dedicated Python orchestration command.
- Generate package names and imports consistently across Windows SDK, Windows App SDK, and custom WinMD namespaces.
- Add runnable samples for files, notifications, imaging, async, events, collections, and custom WinMD consumption.
- Document generated-code version compatibility with
dynwinrt. - Add troubleshooting for metadata, apartment, bootstrap, architecture, and wheel compatibility failures.
- Add progress-callback tests for worker-thread delivery and operations that complete concurrently with callback registration.
WinUI milestone
- Project public composable
__init__overloads without requiring the ABI-onlyouterparameter. The low-level factory method remains available for parity and still exposes its raw ABI shape. - Keep protected composable constructors out of generated Python
__init__overloads. - Make WinMD activation/composition metadata the constructor boundary:
system-returned and protected-composition classes retain native wrapping
but reject public construction and expose no constructible
.pyioverload. - Add a reusable outer/inner aggregation host for public composable Python subclasses, preserving controlling COM identity and inner ownership.
- Add metadata-driven local overridable-interface vtables for public composable subclasses, including native-invoked FrameworkElement measure/arrange/template callbacks and fail-closed ABI validation.
- Register arbitrary Python runtime-class names and compose them into the XAML metadata-provider chain so custom types can be instantiated by name from XAML markup.
- Make Windows App SDK initialization idempotent and version-aware.
- Auto-discover or explicitly provision the bootstrap DLL.
- Expose the selected framework
resources.pripath. - Add Python-specific implicit XAML metadata provider generation.
- Generate the specialized
Application.create_with_metadata_provider()and Fluent-resource bootstrap helpers with matching.pyideclarations. - Run
Application.start,Application,Window,Grid,Button, andTextBlockon an STA in a live x64 WinUI E2E. - Validate worker-thread and
asyncioscheduling while the WinUI DispatcherQueue owns the UI thread, including a WinRT async completion andtry_enqueueback to the UI thread. - Add projected lifetime scopes that release UI/COM wrappers before apartment teardown.
- Add awaitable DispatcherQueue result/error/priority scheduling helpers.
- Project
IObservableVector<T>as a mutable Python sequence with typedVectorChangedevents. - Add a GIL-safe Python
IElementFactorybridge and live ItemsRepeater get/recycle identity coverage. - Load and validate Fluent Light, Dark, and High Contrast resources.
- Add a real Python WinUI application E2E on x64.
- Add Python WinUI application E2E coverage on ARM64.
Later
- Preserve projected object identity where it affects Python semantics.
- Support delegates with more than two ABI parameters.
- Add zero-copy Python buffer protocol integration.
- Add performance benchmarks against pywinrt for representative APIs.
- Add diagnostics for active COM wrappers, delegates, and async operations.
Current implementation slice
- Make generated runtime imports cycle-safe.
- Add a real cyclic-package import regression.
- Re-run Python snapshots, codegen tests, and generated Python E2E.
- Return known enum values as generated
IntEnuminstances. - Verify
Calendar.day_of_weekis aDayOfWeekat runtime. - Use
invoke_all()for arbitrary multiple-out methods. - Model FillArray as caller-owned
(capacity, buffer)ABI. - Verify Python and JavaScript
IndexOfandGetMany, including zero items. - Ship typed
dynwinrtwheels and validate the native extension stubs. - Generate Python stubs by default and type-check generated E2E APIs.
- Unbox
IReference<T>returns asT | None. - Box native Python values and
NoneforIReference<T>inputs. - Map synchronous and asynchronous HRESULT failures to
OSError. - Preserve signed HRESULTs in
.winerrorand captured WinRT error messages. - Project WinRT collections through Python sequence, mapping, and iterator protocols.
- Accept Python-native containers, bytes, UUID, datetime, and timedelta values.
- Route delegate exceptions through
sys.unraisablehookand fail WinRT invocation. - Emit
IntFlag, overload dispatch/stubs, and idiomatic runtime-class constructors. - Balance COM initialization with
RoApartmentand add deterministicIClosablecleanup. - Make reference returns null-safe without lying in generated annotations.
- Preserve
UInt32/UInt64values across the Python boundary. - Project and box
IReference<T>struct fields, including struct-valuedT. - Add typed event arguments while preserving token subscriptions and adding idempotent unsubscribe helpers.
- Project public composable constructors and reject protected composition.
- Add an experimental, typed WinUI
Applicationbootstrap path backed by a sharedcodegen/winrt/extensions/winuispec consumed by both JavaScript and Python projection. - Run a real unpackaged x64 Python WinUI app with Fluent resources, Window/Grid/Button/TextBlock, automation-driven Click, and clean apartment shutdown.
- Release the GIL around blocking WinUI host calls and verify asyncio worker progress, WinRT async completion, and DispatcherQueue UI dispatch.