Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

dynwinrt

dynwinrt is the native CPython runtime for Python projections generated by dynwinrt-codegen. It supports CPython 3.11–3.14 on Windows x64 and ARM64.

Install

python -m pip install --pre dynwinrt dynwinrt-codegen
dynwinrt-codegen generate --namespace Windows.Foundation --class-name Uri `
  --lang py --output generated_uri

Generated package manifests pin dynwinrt to the exact version of dynwinrt-codegen that produced them. The runtime wheel includes __init__.pyi and py.typed for static type checking.

Generated IReference<T> values are projected as T | None; native values, None, and generated IReference_* wrappers are accepted as inputs.

Async WinRT operations

Generated async methods return typed, asyncio-compatible operation objects:

operation = writer.store_async()
stored_bytes = await operation

Their public types are WinRTAsync[T] and WinRTAsyncWithProgress[T, P]; the concrete runtime wrappers remain private.

Regenerated bindings no longer block inside async methods. Existing code that expects an immediate result must use await operation or operation.wait().

asyncio task cancellation calls IAsyncInfo.Cancel() on the underlying WinRT operation. Operations with supported progress values also expose operation.progress(callback). Fast operations can finish before registration; in that case no future progress exists and registration is a no-op.

For scripts without an event loop, operation.wait() remains available as an explicit blocking API. It rejects started operations when called from a running asyncio loop or an STA thread, where blocking could freeze or deadlock the caller.

WinRT HRESULT failures raise OSError (or a standard OSError subclass) with the signed HRESULT in error.winerror. The exception message preserves restricted WinRT error information when Windows provides it.

Python-native values

Generated collection projections implement the standard collections.abc protocols: vectors behave as sequences, maps as mappings, and WinRT iterables and iterators work with iter() and next(). Mutable vectors support indexing, slicing, assignment, insertion, and deletion; mutable maps support standard mapping assignment and deletion.

Method inputs accept normal Python sequences and mappings in place of compatible WinRT collection interfaces. Byte arrays accept bytes and bytearray; GUID, DateTime, and TimeSpan values use uuid.UUID, datetime.datetime, and datetime.timedelta.

Exceptions raised by Python event or delegate callbacks are reported through sys.unraisablehook. The originating WinRT invocation receives 0xA0EE4005 (PYWINRT_E_UNRAISABLE_PYTHON_EXCEPTION) instead of unconditional success. Generated delegate parameters accept normal Python callables. WinRT chooses the callback thread, so callbacks must not assume they run on the registration thread or an asyncio event-loop thread. Keep each token returned by on_* and pass it to the matching off_* when the subscription is no longer needed. For callback-style cleanup, subscribe_* returns an idempotent unsubscribe function. once_* subscribes for at most one callback invocation.

WinRT flags enums are projected as enum.IntFlag. Overloaded methods share one Python name with runtime type/arity dispatch and typing.overload declarations. Activatable runtime classes use normal constructors, for example Uri("https://example.com"). Constructor overloads come only from WinMD ActivatableAttribute and public ComposableAttribute declarations. Classes without that metadata, including system-returned classes and protected-only composition, raise a class-named TypeError on normal construction and their stubs expose no public constructor. Native return values still use the internal _from_native/DynWinRTValue wrapping path.

Raw object projection

Use project_as(value, Type) when metadata returns Object/IInspectable but the application knows the concrete generated type. This is common with XAML APIs such as XamlReader.load() and FrameworkElement.find_name():

from dynwinrt import project_as
from generated.microsoft.ui.xaml.controls import Button, StackPanel
from generated.microsoft.ui.xaml.markup import XamlReader

raw_panel = XamlReader.load(XAML)
if raw_panel is None:
    raise RuntimeError("XamlReader returned no value")
panel = project_as(raw_panel, StackPanel)

raw_button = panel.find_name("Submit")
if raw_button is None:
    raise RuntimeError("Submit was not found")
button = project_as(raw_button, Button)

project_as() accepts generated runtime classes only and borrows its input: the raw value or source wrapper remains valid. The returned wrapper owns the QueryInterface result, participates in the active projected_lifetime_scope(), and preserves the projection identity cache. Classes with a verifiable default-interface IID remain valid projection targets even when metadata exposes them only through Object/IInspectable. Projection always performs QueryInterface, so a static-only declaration cannot produce a wrapper unless the input actually implements that default interface. Incompatible types raise the ordinary WinRT OSError. Static-only metadata classes with no instance surface are not projection targets.

Use wrapper.as_interface(InterfaceClass) when converting an existing wrapper to an interface view. Use InterfaceClass.from_value(raw) for a raw DynWinRTValue. Do not call the internal _from_native() method from application code.

COM apartments and cleanup

Use RoApartment to initialize COM for a thread and balance every successful initialization:

with RoApartment(0):  # RO_INIT_SINGLETHREADED
    use_winrt()

Use RoApartment(1) for RO_INIT_MULTITHREADED. Nested contexts using the same model are supported. Requesting a conflicting model raises OSError with RPC_E_CHANGED_MODE. The low-level ro_initialize() API remains available, but each successful call, including S_FALSE, must be paired with one ro_uninitialize() call on the same thread.

Generated runtime classes that implement IClosable support with and an idempotent close() method. Prefer deterministic cleanup instead of relying on Python garbage collection.

Experimental WinUI support

When the required WinUI metadata is generated, Application.create() installs XamlControlsResources and configures unpackaged resource resolution. Application.create_with_metadata_provider(...) is available when the application supplies its own provider.

Python subclasses of public composable controls preserve one COM identity for inherited properties and methods. Metadata-supported measure_override, arrange_override, and on_apply_template callbacks run synchronously on the creating UI apartment with the contextvars context captured during construction. Unsupported native override shapes fail during construction instead of falling back to an unsafe ABI.

After creating the generated application, publicly composable controls can register a Python subclass for activation by XamlReader:

from generated.microsoft.ui.xaml.controls import StackPanel
from generated.microsoft.ui.xaml.markup import XamlReader

class PythonPanel(StackPanel):
    def measure_override(self, available_size):
        return available_size

registration = StackPanel.register_xaml_runtime_class(
    "MyApp.Controls.PythonPanel",
    PythonPanel,
)
raw_panel = XamlReader.load(
    '<local:PythonPanel '
    'xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" '
    'xmlns:local="using:MyApp.Controls" />'
)
if raw_panel is None:
    raise RuntimeError("XamlReader returned no value")
panel = StackPanel(raw_panel)

# First remove every instance from the XAML tree and release application owners.
panel = None
raw_panel = None
registration.unregister()
registration.release_instances()

Registrations are process-local, and duplicate names fail. Unregistering, closing, or dropping the registration prevents new XAML metadata lookups. XAML-created Python owners remain rooted until release_instances(); call it only after every corresponding native control has left the XAML tree. Registration does not make the class globally activatable through RoActivateInstance.

Generated Application.start() and DispatcherQueue.run_event_loop() calls stay on the caller's native thread but release the Python GIL while WinUI pumps messages. WinRT callbacks reacquire the GIL, and worker threads can use DispatcherQueue.try_enqueue() to return to the UI thread.

Use a projection lifetime scope inside the COM apartment so wrappers release their native values before RoUninitialize:

from dynwinrt import RoApartment, projected_lifetime_scope

with RoApartment(0), projected_lifetime_scope():
    app = Application.create()
    # Create and use WinUI objects here.

Scopes nest in LIFO order. Wrappers that survive a closed scope remain Python objects, but their native values are released and further WinRT calls fail.

Normal construction remains unavailable for protected-only composable classes and system-returned classes without public activation metadata. Named Python XAML registration does not support generic names, collection or dictionary bases, markup-extension bases, or Python-defined XAML members.

Develop

From bindings\py:

python -m pip install "maturin>=1.11,<2" "pytest>=8.3.5" "mypy>=1.13,<2"
python -m maturin develop
python -m pytest

Release process

The release tag supplies one unified npm/Cargo version. For example, v0.1.0-preview.21 produces npm version 0.1.0-preview.21 and Python version 0.1.0rc21 after PEP 440 normalization.

  1. GitHub Actions builds and consumes eight CPython 3.11–3.14 runtime wheels and two standalone codegen wheels on Windows x64 and native ARM64.
  2. The official 1ES ADO pipeline builds both npm packages and waits for the complete Python wheel matrix.
  3. ADO creates one shared GitHub Release with the npm tarballs. GitHub Actions attaches the ten tested Python wheels, and ADO downloads and revalidates the complete set.
  4. With DoEsrp enabled, ADO publishes both npm packages. PublishPyPI defaults to enabled and publishes the eight dynwinrt wheels before the two dynwinrt-codegen wheels. Disable it only for a non-PyPI rehearsal.

PyPI publication uses the Microsoft ESRP release identity and is not available from GitHub Actions.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

dynwinrt-0.1.0rc21-cp314-cp314-win_arm64.whl (664.2 kB view details)

Uploaded CPython 3.14Windows ARM64

dynwinrt-0.1.0rc21-cp314-cp314-win_amd64.whl (689.7 kB view details)

Uploaded CPython 3.14Windows x86-64

dynwinrt-0.1.0rc21-cp313-cp313-win_arm64.whl (663.8 kB view details)

Uploaded CPython 3.13Windows ARM64

dynwinrt-0.1.0rc21-cp313-cp313-win_amd64.whl (689.4 kB view details)

Uploaded CPython 3.13Windows x86-64

dynwinrt-0.1.0rc21-cp312-cp312-win_arm64.whl (662.9 kB view details)

Uploaded CPython 3.12Windows ARM64

dynwinrt-0.1.0rc21-cp312-cp312-win_amd64.whl (688.6 kB view details)

Uploaded CPython 3.12Windows x86-64

dynwinrt-0.1.0rc21-cp311-cp311-win_arm64.whl (669.1 kB view details)

Uploaded CPython 3.11Windows ARM64

dynwinrt-0.1.0rc21-cp311-cp311-win_amd64.whl (696.0 kB view details)

Uploaded CPython 3.11Windows x86-64

File details

Details for the file dynwinrt-0.1.0rc21-cp314-cp314-win_arm64.whl.

File metadata

File hashes

Hashes for dynwinrt-0.1.0rc21-cp314-cp314-win_arm64.whl
Algorithm Hash digest
SHA256 4d79a580d3f452dfbbcbcd32dfddf9a8c3f9037e6682efda0040cb70d4e26cd0
MD5 faeefb1dbf1cafbd2147dac709616309
BLAKE2b-256 b67c846e1ab3c69dafccbb935e5cc6317ae124b170d4045ce199d4ab7eef53b6

See more details on using hashes here.

File details

Details for the file dynwinrt-0.1.0rc21-cp314-cp314-win_amd64.whl.

File metadata

File hashes

Hashes for dynwinrt-0.1.0rc21-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 f267c85491e41a81e1e747d1a1f7d039de12c1ee5db298c69afc354e11dd79e7
MD5 0b52604e91b8bcd509980bb02efcb03f
BLAKE2b-256 5c9fc0f8f59044a09d5b4f10c41e5eaa977ea79883303141f445139ec61357d6

See more details on using hashes here.

File details

Details for the file dynwinrt-0.1.0rc21-cp313-cp313-win_arm64.whl.

File metadata

File hashes

Hashes for dynwinrt-0.1.0rc21-cp313-cp313-win_arm64.whl
Algorithm Hash digest
SHA256 37214e45cdd7a86fff5b5cc01120bf54c0a5ec078260be5ec23e2686bbac7dd6
MD5 f3a124c337ba6108be1041770c93d596
BLAKE2b-256 30c02fc27667d763f52fbbec47f0d8e546044f8566fe4fec28e3f1adf1a77791

See more details on using hashes here.

File details

Details for the file dynwinrt-0.1.0rc21-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for dynwinrt-0.1.0rc21-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 fb435e1590de0a1d9048a7dc0df4385b8a8ec4c42116f42ff560af8b74e119ce
MD5 efb2b98e5c669eba3ac0f2cc9334be76
BLAKE2b-256 d9d46dcd01f981b92cfbf6777c25dadc8014b219c0c5ca6e8de1b8e4120a6949

See more details on using hashes here.

File details

Details for the file dynwinrt-0.1.0rc21-cp312-cp312-win_arm64.whl.

File metadata

File hashes

Hashes for dynwinrt-0.1.0rc21-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 ea26c3748d8f050770dd2768d02a34a4b6b95295750cdeae29e474eda1cd458d
MD5 4b3970fb8243246c49b3b5d72ff79252
BLAKE2b-256 bd64c4327a354c5348dd32e2e9deb5f75d2b74e8534f3c3395524f0b29b13909

See more details on using hashes here.

File details

Details for the file dynwinrt-0.1.0rc21-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for dynwinrt-0.1.0rc21-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 2b705306a75ed74288ad4f74367ae6923e021c3851e7a359fc1635480741dd10
MD5 25200b40ba4043b63b53eb6b10047f6f
BLAKE2b-256 f7a1bef11deb0725225ffea0212f6e2af9480a61d9475cb0cdd40296f614c8de

See more details on using hashes here.

File details

Details for the file dynwinrt-0.1.0rc21-cp311-cp311-win_arm64.whl.

File metadata

File hashes

Hashes for dynwinrt-0.1.0rc21-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 ccd38e33ca85b2f7c67ecfd53dd1587d9bdad58d5728286a4cf3778252ae99f0
MD5 8e2ebd89288f1f06fcc8658bdbd8dc4c
BLAKE2b-256 22d5a6c50973156a299e15c5bbe3d32b1ab8ebaecf2f6452d0ed40ea0116a6f8

See more details on using hashes here.

File details

Details for the file dynwinrt-0.1.0rc21-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for dynwinrt-0.1.0rc21-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 e32718c20556e30e46ead07cf7f03cebf55493cc6d90a55dd0c04a345dcb120b
MD5 501fbf31c93bafa0a2e74269a23d6d19
BLAKE2b-256 745e6237d95565d04b44b744f82c1eba638f7bb785f3274f1581c108e7623dc3

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0rc21 This release

8 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page