Skip to content

Add explicit WinRT Object boxing and type-preserving unboxing to Python - #194

Open
leileizhang (lei9444) wants to merge 2 commits into
mainfrom
lei9444-explicit-python-object-boxing
Open

leileizhang (lei9444) wants to merge 2 commits into
mainfrom
lei9444-explicit-python-object-boxing

Conversation

@lei9444

Copy link
Copy Markdown
Contributor

Problem

unbox_object() raised for DateTime, TimeSpan, Point/Size/Rect and InspectableArray boxes, returned UInt32/Int64/Single values as plain numbers that could not be written back with their original type, and Python had no way to box a value except the generated PropertyValue.create_* factories. Automatic conversion at every Object position (#192) was rejected: an Object is not always a box, and a Python value does not say which WinRT type it is.

Key changes

  • Core: PropertyValueData models all 37 PropertyTypes that have a payload and adds box_property_value. JavaScript keeps its exact behavior through a compile-only adapter.
  • unbox_object(value, *, preserve_type=False): adds DateTime, TimeSpan, Point/Size/Rect, their arrays, and InspectableArray, whose elements follow the same rules. With preserve_type=True, it returns tags and typed arrays that box again as the same PropertyType.
  • New to_winrt_object(value, property_type=None): boxes only values whose WinRT type is unambiguous. property_type= picks an exact type, with range checks.
  • New dynwinrt.values submodule: tags (UInt8 … Char16), typed arrays, immutable Point/Size/Rect, and a PropertyType IntEnum. They are kept out of dynwinrt.__all__, so they never shadow the generated Windows.Foundation names.
  • Tests:
    • a round-trip matrix over all 37 types, using the real PropertyValue factory;
    • every conversion rule and error case;
    • generated-binding E2E checks for the PropertyValue factories, StorageFile properties and DeviceInformation.properties.

Notes

  • Generated code does not change: Object positions are still raw DynWinRTValues.
  • unbox_object no longer raises for the newly supported types. Types it already supported return the same values and Python types. Empty, Inspectable, OtherType and OtherTypeArray boxes still raise OSError.
  • A plain int boxes as Int32 only. Enum members, empty or mixed lists, and InspectableArray values need property_type= or a typed array.
  • Boxing an unboxed value again keeps its PropertyType and value, but not the original box's COM identity.

Generated Object positions stay native (IInspectable); applications now
convert boxed values explicitly at the boundaries that want value semantics.

Core: PropertyValueData models every PropertyType that has a payload (37 of
41), unbox_property_value reports payload-less boxes as Unsupported, and
box_property_value creates system PropertyValue boxes. JavaScript keeps its
exact behavior and messages through a compile-only adapter.

Python:
- unbox_object additionally supports DateTime, TimeSpan, Point, Size, Rect,
  their arrays and InspectableArray (elements unboxed by the same rules);
  already-supported types return the same values, and payload-less boxes
  still raise OSError.
- unbox_object(raw, preserve_type=True) returns dynwinrt.values tags and typed
  arrays, so to_winrt_object restores the exact PropertyType and value.
- to_winrt_object(value, property_type=None) boxes only unambiguous values:
  a plain int is Int32 only, lists must be homogeneous, and enum members,
  empty or mixed lists and InspectableArray need an explicit type.
- The tags, typed arrays, Point/Size/Rect and PropertyType live in the new
  dynwinrt.values submodule, outside the top-level namespace.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Python-only checks on generated bindings:
- object_value_roundtrip: every PropertyValue.create_* factory (37
  PropertyTypes) round-trips through unbox_object(preserve_type=True) and
  to_winrt_object with its exact PropertyType, and dynwinrt.values.PropertyType
  matches the metadata enum.
- object_value_storage_properties: a temporary file's System.Size unboxes as
  UInt64 in preserve mode and System.DateModified as an aware datetime.
- object_value_device_properties: DeviceInformation.properties values unbox
  as str, bool and UUID, skipping gracefully without devices.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

Mixed-language test coverage

Workflow status: ✅ Passed

Layer Lines Functions Branches/regions
Rust, including native .pyd/.node 86.58% 81.8% 86.25% regions
Python aggregate 72.18% n/a 38.31% branches
Python runtime 98.74% n/a 97.92% branches
Generated Python WinRT projections 70.53% n/a 27.36% branches
Generated Python WinRT implementations 72.3% n/a 47.04% branches
JavaScript aggregate 21.91% 25.18% 57.61% branches
JavaScript runtime 44.27% 45.76% 78.99% branches
Generated WinRT projections 22.8% 18.7% 54.84% branches
Generated WinRT implementations 45.99% 59.19% 60.97% branches
Generated Classic COM projections 11.88% 23.97% 53.4% branches

View workflow run and download full HTML/LCOV/XML reports

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant