Coverage for sbe2/schema/type.py: 96%

45 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-21 19:48 +0200

1from .common import FixedLengthElement, Presence 

2from .primitive_type import PrimitiveType 

3from dataclasses import dataclass 

4from functools import cached_property 

5from typing import Any, override 

6 

7 

8 

9# TODO: move 

10 

11def value_ref_to_valid_value(value_ref:str, types): 

12 from .enum import Enum 

13 enum_name, valid_value = value_ref.split('.') 

14 enum = types[enum_name] 

15 if not isinstance(enum, Enum): 

16 raise ValueError(f"'{enum_name}' type is not enum") 

17 for vv in enum.valid_values: 

18 if vv.name == valid_value: 

19 return vv 

20 raise ValueError(f"Enum '{enum_name}' does not contain value '{valid_value}'") 

21 

22@dataclass 

23class Type(FixedLengthElement): 

24 """ 

25 Represents a type element in the schema. 

26 This is used to define a specific type of data. 

27 """ 

28 

29 presence: Presence 

30 primitive_type: PrimitiveType 

31 length: int = 1 # Length of an array, by default just one element 

32 offset: int | None = None # Offset in bytes, if applicable 

33 since_version: int = 0 # Version since this type is present 

34 deprecated: int | None = None # Version this type was deprecated, if applicable 

35 value_ref: str | None = None # constant value reference 

36 value: str | None = None # constant value of the given field 

37 const_val: Any = None # constant value translated into Python type 

38 

39 def lazy_bind(self, types): 

40 if self.presence is Presence.CONSTANT and self.const_val is None: 

41 if self.value_ref: 

42 vv = value_ref_to_valid_value(self.value_ref, types) 

43 self.const_val = vv.value 

44 elif self.value: 

45 self.const_val = self.parse(self.value) 

46 else: 

47 raise ValueError(f"Type '{self.name}' is constant but does not have any constant value assigned") 

48 

49 @cached_property 

50 @override 

51 def total_length(self): 

52 if self.presence is Presence.CONSTANT: 

53 return 0 

54 return self.primitive_type.length 

55 

56 

57 @override 

58 def parse(self, val: str): 

59 if self.length == 1: 

60 return self.primitive_type.base_type(val) 

61 raise NotImplementedError