Skip to content

Commit

Permalink
Deprecations
Browse files Browse the repository at this point in the history
  • Loading branch information
LeonarddeR committed Dec 27, 2024
1 parent 673d742 commit dcd8ffd
Show file tree
Hide file tree
Showing 18 changed files with 123 additions and 107 deletions.
141 changes: 78 additions & 63 deletions source/bdDetect.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import itertools
import threading
from concurrent.futures import ThreadPoolExecutor, Future
from enum import StrEnum
from enum import Enum
from typing import (
Any,
Callable,
Expand Down Expand Up @@ -53,15 +53,46 @@
USB_ID_REGEX = re.compile(r"^VID_[0-9A-F]{4}&PID_[0-9A-F]{4}$", re.U)


class DeviceType(StrEnum):
class ProtocolType(str, Enum):
HID = "hid"
"""HID devices"""
SERIAL = "serial"
"""Serial devices (COM ports)"""
CUSTOM = "custom"
"""Devices with a manufacturer specific driver"""
"""Devices with a manufacturer specific protocol"""


class CommunicationType(str, Enum):
BLUETOOTH = "bluetooth"
"""Bluetooth devices"""
USB = "usb"
"""USB devices"""


class _DeviceTypeMeta(type):
# Mapping old attributes to the new enums
_mapping = {
"HID": ProtocolType.HID,
"SERIAL": ProtocolType.SERIAL,
"CUSTOM": ProtocolType.CUSTOM,
"BLUETOOTH": CommunicationType.BLUETOOTH,
}

def __getattr__(cls, name: str) -> ProtocolType | CommunicationType:
repl = cls._mapping.get(name)
if repl is not None and NVDAState._allowDeprecatedAPI():
log.warning(
f"{cls.__name__}.{name} is deprecated. Use {repl} instead.",
)
return repl
raise AttributeError(f"'{cls.__name__}' object has no attribute '{name}'")


class DeviceType(metaclass=_DeviceTypeMeta):
"""This class is kept for backwards compatibility.
Former members were split into the L{ProtocolType} and L{CommunicationType} enums."""

...


def __getattr__(attrName: str) -> Any:
Expand All @@ -73,25 +104,25 @@ def __getattr__(attrName: str) -> Any:
log.warning(f"{attrName} is deprecated.")
return 2
_deprecatedConstantsMap = {
"KEY_HID": DeviceType.HID,
"KEY_SERIAL": DeviceType.SERIAL,
"KEY_BLUETOOTH": DeviceType.BLUETOOTH,
"KEY_CUSTOM": DeviceType.CUSTOM,
"KEY_HID": ProtocolType.HID,
"KEY_SERIAL": ProtocolType.SERIAL,
"KEY_BLUETOOTH": CommunicationType.BLUETOOTH,
"KEY_CUSTOM": ProtocolType.CUSTOM,
}
if attrName in _deprecatedConstantsMap and NVDAState._allowDeprecatedAPI():
replacementSymbol = _deprecatedConstantsMap[attrName]
log.warning(
f"{attrName} is deprecated. " f"Use bdDetect.DeviceType.{replacementSymbol.name} instead. ",
f"{attrName} is deprecated. " f"Use bdDetect.{replacementSymbol} instead. ",
)
return replacementSymbol
return replacementSymbol.value
raise AttributeError(f"module {repr(__name__)} has no attribute {repr(attrName)}")


class DeviceMatch(NamedTuple):
"""Represents a detected device."""

type: DeviceType
"""The type of the device."""
type: ProtocolType
"""The protocol type of the device."""
id: str
"""The identifier of the device."""
port: str
Expand All @@ -109,6 +140,8 @@ class _UsbDeviceRegistryEntry:

id: str
"""The identifier of the device."""
type: ProtocolType
"""The protocol type of the device."""
useAsFallback: bool = field(default=False, compare=False)
"""
determine how a device is associated with a driver.
Expand All @@ -123,9 +156,16 @@ class _UsbDeviceRegistryEntry:
It takes a L{DeviceMatch} as its only argument
and returns a C{bool} indicating whether it matched."""

def matches(self, deviceMatch: DeviceMatch) -> bool:
"""Returns whether this registry entry matches a specific device."""
if deviceMatch.type != self.type or deviceMatch.id != self.id:
return False
if self.matchFunc is None:
return True
return self.matchFunc(deviceMatch)

DriverDictT = defaultdict[DeviceType, set[_UsbDeviceRegistryEntry] | MatchFuncT]

DriverDictT = defaultdict[CommunicationType, set[_UsbDeviceRegistryEntry] | MatchFuncT]
_driverDevices = OrderedDict[str, DriverDictT]()

scanForDevices = extensionPoints.Chain[Tuple[str, DeviceMatch]]()
Expand Down Expand Up @@ -158,11 +198,11 @@ def getDriversForConnectedUsbDevices(
@return: Generator of pairs of drivers and device information.
"""
usbCustomDeviceMatches = (
DeviceMatch(DeviceType.CUSTOM, port["usbID"], port["devicePath"], port)
DeviceMatch(ProtocolType.CUSTOM, port["usbID"], port["devicePath"], port)
for port in deviceInfoFetcher.usbDevices
)
usbComDeviceMatches = (
DeviceMatch(DeviceType.SERIAL, port["usbID"], port["port"], port)
DeviceMatch(ProtocolType.SERIAL, port["usbID"], port["port"], port)
for port in deviceInfoFetcher.usbComPorts
)
# Tee is used to ensure that the DeviceMatches aren't created multiple times.
Expand All @@ -172,7 +212,7 @@ def getDriversForConnectedUsbDevices(
# device matches), if one is found early the iteration can stop.
usbHidDeviceMatches, usbHidDeviceMatchesForCustom = itertools.tee(
(
DeviceMatch(DeviceType.HID, port["usbID"], port["devicePath"], port)
DeviceMatch(ProtocolType.HID, port["usbID"], port["devicePath"], port)
for port in deviceInfoFetcher.hidDevices
if port["provider"] == "usb"
)
Expand All @@ -183,21 +223,9 @@ def getDriversForConnectedUsbDevices(
for driver, devs in _driverDevices.items():
if limitToDevices and driver not in limitToDevices:
continue
for type, typeDefs in devs.items():
if (
match.type == type
and (
typeDef := next(
(
t
for t in typeDefs
if isinstance(t, _UsbDeviceRegistryEntry) and t.id == match.id
),
None,
)
)
and (not callable(typeDef.matchFunc) or typeDef.matchFunc(match))
):
typeDefs = devs[CommunicationType.USB]
for typeDef in typeDefs:
if typeDef.matches(match):
if typeDef.useAsFallback:
fallbackDriversAndMatches.append({driver, match})
else:
Expand Down Expand Up @@ -225,7 +253,7 @@ def _getStandardHidDriverName() -> str:


def _isHIDUsagePageMatch(match: DeviceMatch, usagePage: int) -> bool:
return match.type == DeviceType.HID and match.deviceInfo.get("HIDUsagePage") == usagePage
return match.type == ProtocolType.HID and match.deviceInfo.get("HIDUsagePage") == usagePage


def _isHIDBrailleMatch(match: DeviceMatch) -> bool:
Expand All @@ -247,7 +275,7 @@ def getDriversForPossibleBluetoothDevices(
@return: Generator of pairs of drivers and port information.
"""
btSerialMatchesForCustom = (
DeviceMatch(DeviceType.SERIAL, port["bluetoothName"], port["port"], port)
DeviceMatch(ProtocolType.SERIAL, port["bluetoothName"], port["port"], port)
for port in deviceInfoFetcher.comPorts
if "bluetoothName" in port
)
Expand All @@ -258,7 +286,7 @@ def getDriversForPossibleBluetoothDevices(
# device matches), if one is found early the iteration can stop.
btHidDevMatchesForHid, btHidDevMatchesForCustom = itertools.tee(
(
DeviceMatch(DeviceType.HID, port["hardwareID"], port["devicePath"], port)
DeviceMatch(ProtocolType.HID, port["hardwareID"], port["devicePath"], port)
for port in deviceInfoFetcher.hidDevices
if port["provider"] == "bluetooth"
)
Expand All @@ -267,7 +295,7 @@ def getDriversForPossibleBluetoothDevices(
for driver, devs in _driverDevices.items():
if limitToDevices and driver not in limitToDevices:
continue
matchFunc = devs[DeviceType.BLUETOOTH]
matchFunc = devs[CommunicationType.BLUETOOTH]
if not callable(matchFunc):
continue
if matchFunc(match):
Expand Down Expand Up @@ -517,16 +545,16 @@ def getConnectedUsbDevicesForDriver(driver: str) -> Iterator[DeviceMatch]:
"""
usbDevs = itertools.chain(
(
DeviceMatch(DeviceType.CUSTOM, port["usbID"], port["devicePath"], port)
DeviceMatch(ProtocolType.CUSTOM, port["usbID"], port["devicePath"], port)
for port in deviceInfoFetcher.usbDevices
),
(
DeviceMatch(DeviceType.HID, port["usbID"], port["devicePath"], port)
DeviceMatch(ProtocolType.HID, port["usbID"], port["devicePath"], port)
for port in deviceInfoFetcher.hidDevices
if port["provider"] == "usb"
),
(
DeviceMatch(DeviceType.SERIAL, port["usbID"], port["port"], port)
DeviceMatch(ProtocolType.SERIAL, port["usbID"], port["port"], port)
for port in deviceInfoFetcher.usbComPorts
),
)
Expand All @@ -538,23 +566,10 @@ def getConnectedUsbDevicesForDriver(driver: str) -> Iterator[DeviceMatch]:
if _isHIDBrailleMatch(match):
yield match
else:
devs = _driverDevices[driver]
for type, typeDefs in devs.items():
if (
match.type == type
and (
typeDef := next(
(
t
for t in typeDefs
if isinstance(t, _UsbDeviceRegistryEntry) and t.id == match.id
),
None,
)
)
and (not callable(typeDef.matchFunc) or typeDef.matchFunc(match))
):
if typeDef.useAsFallback:
devs = _driverDevices[driver][CommunicationType.USB]
for dev in devs:
if dev.matches(match):
if dev.useAsFallback:
fallbackMatches.append(match)
else:
yield match
Expand All @@ -572,17 +587,17 @@ def getPossibleBluetoothDevicesForDriver(driver: str) -> Iterator[DeviceMatch]:
if driver == _getStandardHidDriverName():
matchFunc = _isHIDBrailleMatch
else:
matchFunc = _driverDevices[driver][DeviceType.BLUETOOTH]
matchFunc = _driverDevices[driver][CommunicationType.BLUETOOTH]
if not callable(matchFunc):
return
btDevs = itertools.chain(
(
DeviceMatch(DeviceType.SERIAL, port["bluetoothName"], port["port"], port)
DeviceMatch(ProtocolType.SERIAL, port["bluetoothName"], port["port"], port)
for port in deviceInfoFetcher.comPorts
if "bluetoothName" in port
),
(
DeviceMatch(DeviceType.HID, port["hardwareID"], port["devicePath"], port)
DeviceMatch(ProtocolType.HID, port["hardwareID"], port["devicePath"], port)
for port in deviceInfoFetcher.hidDevices
if port["provider"] == "bluetooth"
),
Expand Down Expand Up @@ -693,7 +708,7 @@ def _getDriverDict(self) -> DriverDictT:

def addUsbDevice(
self,
type: DeviceType,
type: ProtocolType,
id: str,
useAsFallback: bool = False,
matchFunc: MatchFuncT | None = None,
Expand All @@ -719,8 +734,8 @@ def addUsbDevice(
f"Invalid ID provided for driver {self._driver!r}, type {type!r}: " f"{id!r}",
)
devs = self._getDriverDict()
driverUsb = devs[type]
driverUsb.add(_UsbDeviceRegistryEntry(id, useAsFallback, matchFunc))
driverUsb = devs[CommunicationType.USB]
driverUsb.add(_UsbDeviceRegistryEntry(type, id, useAsFallback, matchFunc))

def addUsbDevices(
self,
Expand Down Expand Up @@ -752,8 +767,8 @@ def addUsbDevices(
f"{', '.join(malformedIds)}",
)
devs = self._getDriverDict()
driverUsb = devs[type]
driverUsb.update((_UsbDeviceRegistryEntry(id, useAsFallback, matchFunc) for id in ids))
driverUsb = devs[CommunicationType.USB]
driverUsb.update((_UsbDeviceRegistryEntry(id, type, useAsFallback, matchFunc) for id in ids))

def addBluetoothDevices(self, matchFunc: MatchFuncT):
"""Associate Bluetooth HID or COM ports with the driver on this instance.
Expand All @@ -762,7 +777,7 @@ def addBluetoothDevices(self, matchFunc: MatchFuncT):
and returns a C{bool} indicating whether it matched.
"""
devs = self._getDriverDict()
devs[DeviceType.BLUETOOTH] = matchFunc
devs[CommunicationType.BLUETOOTH] = matchFunc

def addDeviceScanner(
self,
Expand Down
2 changes: 1 addition & 1 deletion source/braille.py
Original file line number Diff line number Diff line change
Expand Up @@ -3517,7 +3517,7 @@ def _getTryPorts(
pass
else:
yield bdDetect.DeviceMatch(
bdDetect.DeviceType.SERIAL,
bdDetect.ProtocolType.SERIAL,
portInfo["bluetoothName" if "bluetoothName" in portInfo else "friendlyName"],
portInfo["port"],
portInfo,
Expand Down
4 changes: 2 additions & 2 deletions source/brailleDisplayDrivers/albatross/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import time

from collections import deque
from bdDetect import DeviceType, DriverRegistrar
from bdDetect import DriverRegistrar, ProtocolType
from logHandler import log
from serial.win32 import (
PURGE_RXABORT,
Expand Down Expand Up @@ -85,7 +85,7 @@ class BrailleDisplayDriver(braille.BrailleDisplayDriver):
@classmethod
def registerAutomaticDetection(cls, driverRegistrar: DriverRegistrar):
driverRegistrar.addUsbDevice(
DeviceType.SERIAL,
ProtocolType.SERIAL,
VID_AND_PID, # Caiku Albatross 46/80
# Filter for bus reported device description, which should be "Albatross Braille Display".
matchFunc=lambda match: match.deviceInfo.get("busReportedDeviceDescription") == BUS_DEVICE_DESC,
Expand Down
4 changes: 2 additions & 2 deletions source/brailleDisplayDrivers/alva.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ class BrailleDisplayDriver(braille.BrailleDisplayDriver, ScriptableObject):
@classmethod
def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar):
driverRegistrar.addUsbDevices(
bdDetect.DeviceType.HID,
bdDetect.ProtocolType.HID,
{
"VID_0798&PID_0640", # BC640
"VID_0798&PID_0680", # BC680
Expand Down Expand Up @@ -216,7 +216,7 @@ def __init__(self, port="auto"):
self._deviceId = None

for portType, portId, port, portInfo in self._getTryPorts(port):
self.isHid = portType == bdDetect.DeviceType.HID
self.isHid = portType == bdDetect.ProtocolType.HID
# Try talking to the display.
try:
if self.isHid:
Expand Down
6 changes: 3 additions & 3 deletions source/brailleDisplayDrivers/baum.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class BrailleDisplayDriver(braille.BrailleDisplayDriver):
@classmethod
def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar):
driverRegistrar.addUsbDevices(
bdDetect.DeviceType.HID,
bdDetect.ProtocolType.HID,
{
"VID_0904&PID_3001", # RefreshaBraille 18
"VID_0904&PID_6101", # VarioUltra 20
Expand All @@ -111,7 +111,7 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar):
)

driverRegistrar.addUsbDevices(
bdDetect.DeviceType.SERIAL,
bdDetect.ProtocolType.SERIAL,
{
"VID_0403&PID_FE70", # Vario 40
"VID_0403&PID_FE71", # PocketVario
Expand Down Expand Up @@ -164,7 +164,7 @@ def __init__(self, port="auto"):
for portType, portId, port, portInfo in self._getTryPorts(port):
# At this point, a port bound to this display has been found.
# Try talking to the display.
self.isHid = portType == bdDetect.DeviceType.HID
self.isHid = portType == bdDetect.ProtocolType.HID
try:
if self.isHid:
self._dev = hwIo.Hid(port, onReceive=self._onReceive)
Expand Down
2 changes: 1 addition & 1 deletion source/brailleDisplayDrivers/brailleNote.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class BrailleDisplayDriver(braille.BrailleDisplayDriver):
@classmethod
def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar):
driverRegistrar.addUsbDevices(
bdDetect.DeviceType.SERIAL,
bdDetect.ProtocolType.SERIAL,
{
"VID_1C71&PID_C004", # Apex
},
Expand Down
Loading

0 comments on commit dcd8ffd

Please sign in to comment.