Skip to content

Update for changes in annotations with Python 3.14#173

Draft
antoinevg wants to merge 2 commits intomainfrom
antoinevg/fix-172
Draft

Update for changes in annotations with Python 3.14#173
antoinevg wants to merge 2 commits intomainfrom
antoinevg/fix-172

Conversation

@antoinevg
Copy link
Copy Markdown
Member

@antoinevg antoinevg commented Feb 24, 2026

Python 3.14 introduces deferred evaluation of annotations (PEP 649 and PEP 749).

Code that relies on manipulating the __annotations__ attribute directly needs to, instead, make use of annotationlib and the get_annotations() function called with the format=Format.FORWARDREF argument.

In this PR we'll use the typeextensions library which provides a backward-compatible implementation for versions of Python <3.14.

More information: https://docs.python.org/3/whatsnew/3.14.html#whatsnew314-porting-annotations

--
Closes #172

@antoinevg antoinevg mentioned this pull request Feb 24, 2026
@mossmann mossmann requested a review from miek March 5, 2026 16:38
@antoinevg antoinevg marked this pull request as draft May 5, 2026 13:29
@miek
Copy link
Copy Markdown
Member

miek commented May 7, 2026

Sorry about the delay. We have chatted about some of this but just to get some notes written down:

I found that running the unit tests with python -m unittest fails after this change, with:

======================================================================
ERROR: test_code_generation (test.test_descriptors.TestDescriptors.test_code_generation)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/mike/repos/facedancer/test/test_descriptors.py", line 102, in test_code_generation
    new_device = Device()
                 ^^^^^^^^
  File "<string>", line 20, in __init__
  File "/home/mike/repos/facedancer/facedancer/device.py", line 164, in __post_init__
    for configuration in instantiate_subordinates(self, USBConfiguration):
  File "/home/mike/repos/facedancer/facedancer/magic.py", line 129, in instantiate_subordinates
    yield member(object)
          ^^^^^^^^^^^^^^
  File "/home/mike/repos/facedancer/facedancer/magic.py", line 64, in __call__
    return self._target_type(parent=parent)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<string>", line 10, in __init__
  File "/home/mike/repos/facedancer/facedancer/configuration.py", line 111, in __post_init__
    for interface in instantiate_subordinates(self, USBInterface):
  File "/home/mike/repos/facedancer/facedancer/magic.py", line 129, in instantiate_subordinates
    yield member(object)
          ^^^^^^^^^^^^^^
  File "/home/mike/repos/facedancer/facedancer/magic.py", line 64, in __call__
    return self._target_type(parent=parent)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<string>", line 14, in __init__
  File "/home/mike/repos/facedancer/facedancer/interface.py", line 88, in __post_init__
    for descriptor in instantiate_subordinates(self, USBDescriptor):
  File "/home/mike/repos/facedancer/facedancer/magic.py", line 129, in instantiate_subordinates
    yield member(object)
          ^^^^^^^^^^^^^^
  File "/home/mike/repos/facedancer/facedancer/magic.py", line 64, in __call__
    return self._target_type(parent=parent)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: Device.Configuration_1.Interface_0.Descriptor_0x24_A.__init__() missing 1 required keyword-only argument: 'raw'

I think that this change isn't actually keeping the same behaviour as before. Previously, it was adding to the __annotations__ element in classdict passed to the new class, but the new change is only accessing the base-class annotations and not updating anything in the child class.

Also, I think the warnings against manipulating __annotations__ directly apply to existing classes, not during class creation like this. I didn't get far enough into finding the right way to do it, but there's a relevant-looking example here: https://docs.python.org/3/library/annotationlib.html#using-annotations-in-a-metaclass

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.

Python 3.14 support

2 participants