Coverage for src / bluetooth_sig / registry / uuids / sdo_uuids.py: 90%

30 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-11 20:14 +0000

1"""SDO UUIDs registry for Bluetooth SIG Special Development Organization UUIDs.""" 

2 

3from __future__ import annotations 

4 

5import re 

6 

7from bluetooth_sig.registry.base import BaseUUIDRegistry 

8from bluetooth_sig.types.registry.sdo_uuids import SdoUuidInfo as SdoInfo 

9from bluetooth_sig.types.uuid import BluetoothUUID 

10 

11 

12class SdoUuidsRegistry(BaseUUIDRegistry[SdoInfo]): 

13 """Registry for Bluetooth SIG Special Development Organization UUIDs.""" 

14 

15 def _normalize_name_for_id(self, name: str) -> str: 

16 """Normalize a name to create a valid ID string. 

17 

18 Args: 

19 name: The name to normalize 

20 

21 Returns: 

22 Normalized ID string 

23 """ 

24 # Convert to lowercase, replace spaces and special chars with underscores 

25 normalized = re.sub(r"[^a-zA-Z0-9]", "_", name.lower()) 

26 # Remove multiple consecutive underscores 

27 normalized = re.sub(r"_+", "_", normalized) 

28 # Remove leading/trailing underscores 

29 normalized = normalized.strip("_") 

30 return normalized 

31 

32 def _load_yaml_path(self) -> str: 

33 """Return the YAML file path relative to bluetooth_sig/ root.""" 

34 return "assigned_numbers/uuids/sdo_uuids.yaml" 

35 

36 def _create_info_from_yaml(self, uuid_data: dict[str, str], uuid: BluetoothUUID) -> SdoInfo: 

37 """Create SdoInfo from YAML data.""" 

38 name = uuid_data["name"] 

39 return SdoInfo( 

40 uuid=uuid, 

41 name=name, 

42 ) 

43 

44 def _create_runtime_info(self, entry: object, uuid: BluetoothUUID) -> SdoInfo: 

45 """Create runtime SdoInfo from entry.""" 

46 return SdoInfo( 

47 uuid=uuid, 

48 name=getattr(entry, "name", ""), 

49 ) 

50 

51 def get_sdo_info(self, uuid: str | BluetoothUUID) -> SdoInfo | None: 

52 """Get SDO information by UUID. 

53 

54 Args: 

55 uuid: The UUID to look up (string, int, or BluetoothUUID) 

56 

57 Returns: 

58 SdoInfo if found, None otherwise 

59 """ 

60 return self.get_info(uuid) 

61 

62 def get_sdo_info_by_name(self, name: str) -> SdoInfo | None: 

63 """Get SDO information by name (case insensitive). 

64 

65 Args: 

66 name: The SDO name to look up 

67 

68 Returns: 

69 SdoInfo if found, None otherwise 

70 """ 

71 return self.get_info(name) 

72 

73 def get_sdo_info_by_id(self, sdo_id: str) -> SdoInfo | None: 

74 """Get SDO information by SDO ID. 

75 

76 Args: 

77 sdo_id: The SDO ID to look up 

78 

79 Returns: 

80 SdoInfo if found, None otherwise 

81 """ 

82 return self.get_info(sdo_id) 

83 

84 def is_sdo_uuid(self, uuid: str | BluetoothUUID) -> bool: 

85 """Check if a UUID corresponds to a known SDO. 

86 

87 Args: 

88 uuid: The UUID to check 

89 

90 Returns: 

91 True if the UUID is a known SDO, False otherwise 

92 """ 

93 return self.get_sdo_info(uuid) is not None 

94 

95 def get_all_sdo_uuids(self) -> list[SdoInfo]: 

96 """Get all SDO UUIDs in the registry. 

97 

98 Returns: 

99 List of all SdoInfo objects 

100 """ 

101 self._ensure_loaded() 

102 return list(self._canonical_store.values()) 

103 

104 

105# Global instance for convenience 

106sdo_uuids_registry = SdoUuidsRegistry.get_instance()