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

33 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-30 00:10 +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) -> type[BaseDescriptor] | None: 

28 """Get descriptor class for UUID.""" 

29 # Convert to BluetoothUUID and use full form for lookup 

30 try: 

31 uuid_obj = BluetoothUUID(uuid) 

32 full_uuid_str = uuid_obj.dashed_form 

33 return cls._registry.get(full_uuid_str) 

34 except ValueError: 

35 return None 

36 

37 @classmethod 

38 def create_descriptor(cls, uuid: str) -> BaseDescriptor | None: 

39 """Create descriptor instance for UUID.""" 

40 descriptor_class = cls.get_descriptor_class(uuid) 

41 if descriptor_class: 

42 try: 

43 return descriptor_class() 

44 except (ValueError, TypeError, AttributeError): 

45 return None 

46 return None 

47 

48 @classmethod 

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

50 """List all registered descriptor UUIDs.""" 

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