Skip to content

TypeError on import: "USBDevice" | None union syntax fails with forward reference strings #13

@rlinus

Description

@rlinus

usbipd fails to import on Python 3.11 with the following traceback:

Traceback (most recent call last):
File "/opt/homebrew/anaconda3/envs/usbipd/bin/usbipd", line 3, in
from usbipd import main
File ".../site-packages/usbipd.py", line 12, in
from usb_device import USBDevice, USBDeviceManager
File ".../site-packages/usb_device.py", line 344, in
class USBDeviceManager:
File ".../site-packages/usb_device.py", line 364, in USBDeviceManager
def find_by_bus_id(self, bus_id: str) -> "USBDevice" | None:
TypeError: unsupported operand type(s) for |: 'str' and 'NoneType'

Cause:

In usb_device.py, several methods use the X | None union syntax with a forward
reference string:

def find_by_bus_id(self, bus_id: str) -> "USBDevice" | None: # line 366
def find_by_vid_pid(...) -> "USBDevice" | None: # line 403
def find_by_binding(...) -> "USBDevice" | None: # line 433

The | union operator (PEP 604) works on actual type objects at runtime, but
"USBDevice" is a string (forward reference), and str.or is not defined.
This causes a TypeError at class body evaluation time.

Fix:

Add from future import annotations at the top of usb_device.py. This makes
all annotations lazily evaluated as strings, so the | operator is never
actually called at runtime.

Alternatively, replace "USBDevice" | None with Optional["USBDevice"] from
typing.

Environment:

  • usbipd 0.0.7
  • Python 3.11.15
  • macOS (Apple Silicon)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions