Coverage for src/bluetooth_sig/types/gatt_services.py: 83%

24 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-30 00:10 +0000

1"""GATT service typing definitions. 

2 

3Strong typing for GATT services - no flexible dicts allowed! 

4NO LEGACY CODE SUPPORT - development phase only. 

5""" 

6 

7from __future__ import annotations 

8 

9from typing import Generic, TypeVar 

10 

11import msgspec 

12 

13from ..gatt.characteristics.base import BaseCharacteristic 

14from ..gatt.characteristics.registry import CharacteristicRegistry 

15from .data_types import CharacteristicInfo 

16from .gatt_enums import CharacteristicName 

17from .uuid import BluetoothUUID 

18 

19# Type variable for specific characteristic types 

20CharacteristicTypeVar = TypeVar("CharacteristicTypeVar", bound=BaseCharacteristic) 

21 

22 

23class CharacteristicSpec(msgspec.Struct, Generic[CharacteristicTypeVar], frozen=True, kw_only=True): 

24 """Specification for a single characteristic with strong typing. 

25 

26 This provides compile-time type safety and IDE autocompletion 

27 for service characteristic definitions. 

28 

29 Note: The characteristic name is derived from the dictionary key, 

30 eliminating redundancy and following DRY principles. 

31 """ 

32 

33 char_class: type[CharacteristicTypeVar] 

34 required: bool = False 

35 conditional: bool = False 

36 condition: str = "" 

37 

38 

39def characteristic(name: CharacteristicName, required: bool = False) -> CharacteristicSpec[BaseCharacteristic]: 

40 """Create a CharacteristicSpec using the central registry for class mapping. 

41 

42 This eliminates the need to manually specify the characteristic class 

43 by automatically resolving it from the CharacteristicName enum. 

44 

45 Args: 

46 name: The characteristic name enum 

47 required: Whether this characteristic is required 

48 

49 Returns: 

50 A CharacteristicSpec with the appropriate class from the registry 

51 

52 """ 

53 char_class = CharacteristicRegistry.get_characteristic_class(name) 

54 if char_class is None: 

55 raise ValueError(f"No characteristic class found for {name}") 

56 

57 return CharacteristicSpec(char_class=char_class, required=required) 

58 

59 

60# Strong type definitions - using enums instead of strings for type safety 

61CharacteristicCollection = dict[CharacteristicName, CharacteristicSpec[BaseCharacteristic]] 

62"""Maps characteristic names (enums) to their specifications - STRONG TYPING ONLY.""" 

63 

64# Network/protocol data structures - these are inherently dynamic from BLE 

65# Type aliases for service and characteristic discovery data 

66ServiceDiscoveryData = dict[BluetoothUUID, CharacteristicInfo] 

67"""Service discovery data: Service UUID -> characteristic discovery information.""" 

68 

69# Export helper function 

70__all__ = [ 

71 "CharacteristicSpec", 

72 "CharacteristicTypeVar", 

73 "CharacteristicCollection", 

74 "ServiceDiscoveryData", 

75 "characteristic", 

76]