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

29 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-18 11:17 +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 return normalized.strip("_") 

30 

31 def _load_yaml_path(self) -> str: 

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

33 return "assigned_numbers/uuids/sdo_uuids.yaml" 

34 

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

36 """Create SdoInfo from YAML data.""" 

37 name = uuid_data["name"] 

38 return SdoInfo( 

39 uuid=uuid, 

40 name=name, 

41 ) 

42 

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

44 """Create runtime SdoInfo from entry.""" 

45 return SdoInfo( 

46 uuid=uuid, 

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

48 ) 

49 

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

51 """Get SDO information by UUID. 

52 

53 Args: 

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

55 

56 Returns: 

57 SdoInfo if found, None otherwise 

58 """ 

59 return self.get_info(uuid) 

60 

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

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

63 

64 Args: 

65 name: The SDO name to look up 

66 

67 Returns: 

68 SdoInfo if found, None otherwise 

69 """ 

70 return self.get_info(name) 

71 

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

73 """Get SDO information by SDO ID. 

74 

75 Args: 

76 sdo_id: The SDO ID to look up 

77 

78 Returns: 

79 SdoInfo if found, None otherwise 

80 """ 

81 return self.get_info(sdo_id) 

82 

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

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

85 

86 Args: 

87 uuid: The UUID to check 

88 

89 Returns: 

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

91 """ 

92 return self.get_sdo_info(uuid) is not None 

93 

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

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

96 

97 Returns: 

98 List of all SdoInfo objects 

99 """ 

100 self._ensure_loaded() 

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

102 

103 

104# Global instance for convenience 

105sdo_uuids_registry = SdoUuidsRegistry.get_instance()