Coverage for src / bluetooth_sig / gatt / descriptors / registry.py: 87%

30 statements  

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

1"""Descriptor registry and resolution.""" 

2 

3from __future__ import annotations 

4 

5from ...types.uuid import BluetoothUUID 

6from .base import BaseDescriptor 

7 

8 

9class DescriptorRegistry: 

10 """Registry for descriptor classes.""" 

11 

12 _registry: dict[str, type[BaseDescriptor]] = {} 

13 

14 @classmethod 

15 def register(cls, descriptor_class: type[BaseDescriptor]) -> None: 

16 """Register a descriptor class.""" 

17 # Create an instance to resolve the UUID 

18 try: 

19 instance = descriptor_class() 

20 uuid_str = str(instance.uuid) 

21 cls._registry[uuid_str] = descriptor_class 

22 except (ValueError, TypeError, AttributeError): 

23 # If we can't create an instance or resolve UUID, skip registration 

24 pass 

25 

26 @classmethod 

27 def get_descriptor_class(cls, uuid: str | BluetoothUUID | int) -> type[BaseDescriptor] | None: 

28 """Get descriptor class for UUID. 

29 

30 Args: 

31 uuid: The descriptor UUID 

32 

33 Returns: 

34 Descriptor class if found, None otherwise 

35 

36 Raises: 

37 ValueError: If uuid format is invalid 

38 """ 

39 # Convert to BluetoothUUID and use full form for lookup (let ValueError propagate) 

40 uuid_obj = BluetoothUUID(uuid) 

41 full_uuid_str = uuid_obj.dashed_form 

42 return cls._registry.get(full_uuid_str) 

43 

44 @classmethod 

45 def create_descriptor(cls, uuid: str | BluetoothUUID | int) -> BaseDescriptor | None: 

46 """Create descriptor instance for UUID. 

47 

48 Args: 

49 uuid: The descriptor UUID 

50 

51 Returns: 

52 Descriptor instance if found, None otherwise 

53 

54 Raises: 

55 ValueError: If uuid format is invalid 

56 """ 

57 descriptor_class = cls.get_descriptor_class(uuid) 

58 if descriptor_class: 

59 try: 

60 return descriptor_class() 

61 except (ValueError, TypeError, AttributeError): 

62 return None 

63 return None 

64 

65 @classmethod 

66 def list_registered_descriptors(cls) -> list[str]: 

67 """List all registered descriptor UUIDs.""" 

68 return list(cls._registry.keys())