odxtools 8.3.4__py3-none-any.whl → 9.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
odxtools/dtcdop.py CHANGED
@@ -15,13 +15,59 @@ from .dopbase import DopBase
15
15
  from .encodestate import EncodeState
16
16
  from .exceptions import DecodeError, EncodeError, odxassert, odxraise, odxrequire
17
17
  from .nameditemlist import NamedItemList
18
- from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef
18
+ from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
19
19
  from .odxtypes import ParameterValue, odxstr_to_bool
20
20
  from .physicaltype import PhysicalType
21
21
  from .snrefcontext import SnRefContext
22
22
  from .utils import dataclass_fields_asdict
23
23
 
24
24
 
25
+ @dataclass
26
+ class LinkedDtcDop:
27
+ not_inherited_dtc_snrefs: List[str]
28
+ dtc_dop_ref: OdxLinkRef
29
+
30
+ @property
31
+ def dtc_dop(self) -> "DtcDop":
32
+ return self._dtc_dop
33
+
34
+ @property
35
+ def short_name(self) -> str:
36
+ return self._dtc_dop.short_name
37
+
38
+ @property
39
+ def not_inherited_dtcs(self) -> NamedItemList[DiagnosticTroubleCode]:
40
+ return self._not_inherited_dtcs
41
+
42
+ @staticmethod
43
+ def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "LinkedDtcDop":
44
+ not_inherited_dtc_snrefs = [
45
+ odxrequire(el.get("SHORT-NAME"))
46
+ for el in et_element.iterfind("NOT-INHERITED-DTC-SNREFS/"
47
+ "NOT-INHERITED-DTC-SNREF")
48
+ ]
49
+
50
+ dtc_dop_ref = odxrequire(OdxLinkRef.from_et(et_element.find("DTC-DOP-REF"), doc_frags))
51
+
52
+ return LinkedDtcDop(
53
+ not_inherited_dtc_snrefs=not_inherited_dtc_snrefs, dtc_dop_ref=dtc_dop_ref)
54
+
55
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
56
+ return {}
57
+
58
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
59
+ self._dtc_dop = odxlinks.resolve(self.dtc_dop_ref, DtcDop)
60
+
61
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
62
+ dtc_dop = self._dtc_dop
63
+ not_inherited_dtcs = [
64
+ resolve_snref(ni_snref, dtc_dop.dtcs, DiagnosticTroubleCode)
65
+ for ni_snref in self.not_inherited_dtc_snrefs
66
+ ]
67
+
68
+ self._not_inherited_dtcs = NamedItemList(not_inherited_dtcs)
69
+
70
+
25
71
  @dataclass
26
72
  class DtcDop(DopBase):
27
73
  """A DOP describing a diagnostic trouble code"""
@@ -30,9 +76,12 @@ class DtcDop(DopBase):
30
76
  physical_type: PhysicalType
31
77
  compu_method: CompuMethod
32
78
  dtcs_raw: List[Union[DiagnosticTroubleCode, OdxLinkRef]]
33
- linked_dtc_dop_refs: List[OdxLinkRef]
79
+ linked_dtc_dops_raw: List[LinkedDtcDop]
34
80
  is_visible_raw: Optional[bool]
35
81
 
82
+ def __post_init__(self) -> None:
83
+ self._init_finished = False
84
+
36
85
  @staticmethod
37
86
  def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "DtcDop":
38
87
  """Reads a DTC-DOP."""
@@ -56,12 +105,10 @@ class DtcDop(DopBase):
56
105
  elif dtc_proxy_elem.tag == "DTC-REF":
57
106
  dtcs_raw.append(OdxLinkRef.from_et(dtc_proxy_elem, doc_frags))
58
107
 
59
- # TODO: NOT-INHERITED-DTC-SNREFS
60
- linked_dtc_dop_refs = [
61
- OdxLinkRef.from_et(dtc_ref_elem, doc_frags)
108
+ linked_dtc_dops_raw = [
109
+ LinkedDtcDop.from_et(dtc_ref_elem, doc_frags)
62
110
  for dtc_ref_elem in et_element.iterfind("LINKED-DTC-DOPS/"
63
- "LINKED-DTC-DOP/"
64
- "DTC-DOP-REF")
111
+ "LINKED-DTC-DOP")
65
112
  ]
66
113
  is_visible_raw = odxstr_to_bool(et_element.get("IS-VISIBLE"))
67
114
 
@@ -70,7 +117,7 @@ class DtcDop(DopBase):
70
117
  physical_type=physical_type,
71
118
  compu_method=compu_method,
72
119
  dtcs_raw=dtcs_raw,
73
- linked_dtc_dop_refs=linked_dtc_dop_refs,
120
+ linked_dtc_dops_raw=linked_dtc_dops_raw,
74
121
  is_visible_raw=is_visible_raw,
75
122
  **kwargs)
76
123
 
@@ -79,12 +126,12 @@ class DtcDop(DopBase):
79
126
  return self._dtcs
80
127
 
81
128
  @property
82
- def is_visible(self) -> bool:
83
- return self.is_visible_raw is True
129
+ def linked_dtc_dops(self) -> NamedItemList[LinkedDtcDop]:
130
+ return self._linked_dtc_dops
84
131
 
85
132
  @property
86
- def linked_dtc_dops(self) -> NamedItemList["DtcDop"]:
87
- return self._linked_dtc_dops
133
+ def is_visible(self) -> bool:
134
+ return self.is_visible_raw is True
88
135
 
89
136
  @override
90
137
  def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
@@ -185,6 +232,9 @@ class DtcDop(DopBase):
185
232
  if isinstance(dtc_proxy, DiagnosticTroubleCode):
186
233
  odxlinks.update(dtc_proxy._build_odxlinks())
187
234
 
235
+ for linked_dtc_dop in self.linked_dtc_dops_raw:
236
+ odxlinks.update(linked_dtc_dop._build_odxlinks())
237
+
188
238
  return odxlinks
189
239
 
190
240
  def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
@@ -201,10 +251,19 @@ class DtcDop(DopBase):
201
251
  dtc = odxlinks.resolve(dtc_proxy, DiagnosticTroubleCode)
202
252
  self._dtcs.append(dtc)
203
253
 
204
- linked_dtc_dops = [odxlinks.resolve(x, DtcDop) for x in self.linked_dtc_dop_refs]
205
- self._linked_dtc_dops = NamedItemList(linked_dtc_dops)
254
+ for linked_dtc_dop in self.linked_dtc_dops_raw:
255
+ linked_dtc_dop._resolve_odxlinks(odxlinks)
206
256
 
207
257
  def _resolve_snrefs(self, context: SnRefContext) -> None:
258
+ # hack to avoid initializing the DtcDop object multiple
259
+ # times. This is required, because the linked DTC DOP feature
260
+ # requires the "parent" DTC DOPs to be fully initialized but
261
+ # the standard does not define a formal ordering of DTC DOPs.
262
+ if self._init_finished:
263
+ return
264
+
265
+ self._init_finished = True
266
+
208
267
  super()._resolve_snrefs(context)
209
268
 
210
269
  self.compu_method._resolve_snrefs(context)
@@ -212,3 +271,31 @@ class DtcDop(DopBase):
212
271
  for dtc_proxy in self.dtcs_raw:
213
272
  if isinstance(dtc_proxy, DiagnosticTroubleCode):
214
273
  dtc_proxy._resolve_snrefs(context)
274
+
275
+ for linked_dtc_dop in self.linked_dtc_dops_raw:
276
+ linked_dtc_dop._resolve_snrefs(context)
277
+
278
+ # add the inherited DTCs from linked DTC DOPs. Note that this
279
+ # requires that there are no cycles in the "link-hierarchy"
280
+ dtc_short_names = {dtc.short_name for dtc in self._dtcs}
281
+ for linked_dtc_dop in self.linked_dtc_dops_raw:
282
+ linked_dtc_dop.dtc_dop._resolve_snrefs(context)
283
+
284
+ for dtc in linked_dtc_dop.dtc_dop.dtcs:
285
+ if dtc.short_name in dtc_short_names:
286
+ # we already have a DTC with that name. Since we
287
+ # are not supposed to overwrite the local DTCs, we
288
+ # skip processing this one. TODO: Are inheritance
289
+ # conflicts for DTCs allowed?
290
+ continue
291
+
292
+ if dtc.short_name in linked_dtc_dop.not_inherited_dtc_snrefs:
293
+ # DTC is explicitly not inherited
294
+ continue
295
+
296
+ self._dtcs.append(dtc)
297
+ dtc_short_names.add(dtc.short_name)
298
+
299
+ # at this place, the linked DTC DOPs exhibit .short_name, so
300
+ # we can create a NamedItemList...
301
+ self._linked_dtc_dops = NamedItemList(self.linked_dtc_dops_raw)
odxtools/inputparam.py CHANGED
@@ -3,8 +3,6 @@ from dataclasses import dataclass
3
3
  from typing import Any, Dict, List, Optional
4
4
  from xml.etree import ElementTree
5
5
 
6
- from deprecation import deprecated
7
-
8
6
  from .dopbase import DopBase
9
7
  from .element import NamedElement
10
8
  from .exceptions import odxrequire
@@ -49,8 +47,3 @@ class InputParam(NamedElement):
49
47
  def dop_base(self) -> DopBase:
50
48
  """The data object property describing this parameter."""
51
49
  return self._dop_base
52
-
53
- @property
54
- @deprecated(details="use .dop_base") # type: ignore[misc]
55
- def dop(self) -> DopBase:
56
- return self._dop_base
@@ -1,6 +1,6 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import List, Optional
3
+ from typing import List
4
4
  from xml.etree import ElementTree
5
5
 
6
6
  from typing_extensions import override
@@ -50,13 +50,6 @@ class LeadingLengthInfoType(DiagCodedType):
50
50
  def dct_type(self) -> DctType:
51
51
  return "LEADING-LENGTH-INFO-TYPE"
52
52
 
53
- def get_static_bit_length(self) -> Optional[int]:
54
- # note that self.bit_length is just the length of the length
55
- # specifier field. This is then followed by the same number of
56
- # bytes as the value of this field, i.e., the length of this
57
- # DCT is dynamic!
58
- return None
59
-
60
53
  @override
61
54
  def encode_into_pdu(self, internal_value: AtomicOdxType, encode_state: EncodeState) -> None:
62
55
 
odxtools/message.py CHANGED
@@ -2,8 +2,6 @@
2
2
  from dataclasses import dataclass
3
3
  from typing import TYPE_CHECKING, Union
4
4
 
5
- from deprecation import deprecated
6
-
7
5
  from .odxtypes import ParameterValue, ParameterValueDict
8
6
 
9
7
  if TYPE_CHECKING:
@@ -29,8 +27,3 @@ class Message:
29
27
 
30
28
  def __getitem__(self, key: str) -> ParameterValue:
31
29
  return self.param_dict[key]
32
-
33
- @property
34
- @deprecated("use .coding_object") # type: ignore[misc]
35
- def structure(self) -> Union["Request", "Response"]:
36
- return self.coding_object
@@ -20,6 +20,10 @@ class MinMaxLengthType(DiagCodedType):
20
20
  max_length: Optional[int]
21
21
  termination: str
22
22
 
23
+ @property
24
+ def dct_type(self) -> DctType:
25
+ return "MIN-MAX-LENGTH-TYPE"
26
+
23
27
  @staticmethod
24
28
  @override
25
29
  def from_et(et_element: ElementTree.Element,
@@ -50,10 +54,6 @@ class MinMaxLengthType(DiagCodedType):
50
54
  "END-OF-PDU",
51
55
  ], f"A min-max length type cannot have the termination {self.termination}")
52
56
 
53
- @property
54
- def dct_type(self) -> DctType:
55
- return "MIN-MAX-LENGTH-TYPE"
56
-
57
57
  def __termination_sequence(self) -> bytes:
58
58
  """Returns the termination byte sequence if it isn't defined."""
59
59
  # The termination sequence is actually not specified by ASAM
odxtools/outputparam.py CHANGED
@@ -3,8 +3,6 @@ from dataclasses import dataclass
3
3
  from typing import Any, Dict, List, Optional
4
4
  from xml.etree import ElementTree
5
5
 
6
- from deprecation import deprecated
7
-
8
6
  from .dopbase import DopBase
9
7
  from .element import IdentifiableElement
10
8
  from .exceptions import odxrequire
@@ -40,8 +38,3 @@ class OutputParam(IdentifiableElement):
40
38
  def dop_base(self) -> DopBase:
41
39
  """The data object property describing this parameter."""
42
40
  return self._dop_base
43
-
44
- @property
45
- @deprecated(details="use .dop_base") # type: ignore[misc]
46
- def dop(self) -> DopBase:
47
- return self._dop_base
odxtools/parameterinfo.py CHANGED
@@ -34,36 +34,36 @@ from .staticfield import StaticField
34
34
 
35
35
  def _get_linear_segment_info(segment: LinearSegment) -> str:
36
36
  ll = segment.physical_lower_limit
37
- ul = segment.physical_upper_limit
38
37
  if ll is None or ll.interval_type == IntervalType.INFINITE:
39
38
  ll_str = "(-inf"
40
39
  else:
41
40
  ll_delim = '(' if ll.interval_type == IntervalType.OPEN else '['
42
41
  ll_str = f"{ll_delim}{ll._value!r}"
43
42
 
44
- if ul is None or ul.interval_type == IntervalType.INFINITE:
45
- ul_str = "inf)"
46
- else:
47
- ul_delim = ')' if ul.interval_type == IntervalType.OPEN else ']'
48
- ul_str = f"{ul._value!r}{ul_delim}"
43
+ ul = segment.physical_upper_limit
44
+ if ul is None or ul.interval_type == IntervalType.INFINITE:
45
+ ul_str = "inf)"
46
+ else:
47
+ ul_delim = ')' if ul.interval_type == IntervalType.OPEN else ']'
48
+ ul_str = f"{ul._value!r}{ul_delim}"
49
49
 
50
50
  return f"{ll_str}, {ul_str}"
51
51
 
52
52
 
53
53
  def _get_rat_func_segment_info(segment: RatFuncSegment) -> str:
54
54
  ll = segment.lower_limit
55
- ul = segment.upper_limit
56
55
  if ll is None or ll.interval_type == IntervalType.INFINITE:
57
56
  ll_str = "(-inf"
58
57
  else:
59
58
  ll_delim = '(' if ll.interval_type == IntervalType.OPEN else '['
60
59
  ll_str = f"{ll_delim}{ll._value!r}"
61
60
 
62
- if ul is None or ul.interval_type == IntervalType.INFINITE:
63
- ul_str = "inf)"
64
- else:
65
- ul_delim = ')' if ul.interval_type == IntervalType.OPEN else ']'
66
- ul_str = f"{ul._value!r}{ul_delim}"
61
+ ul = segment.upper_limit
62
+ if ul is None or ul.interval_type == IntervalType.INFINITE:
63
+ ul_str = "inf)"
64
+ else:
65
+ ul_delim = ')' if ul.interval_type == IntervalType.OPEN else ']'
66
+ ul_str = f"{ul._value!r}{ul_delim}"
67
67
 
68
68
  return f"{ll_str}, {ul_str}"
69
69
 
@@ -33,11 +33,13 @@ ParameterType = Literal[
33
33
  @dataclass
34
34
  class Parameter(NamedElement):
35
35
  """This class corresponds to POSITIONABLE-PARAM in the ODX
36
- specification.
36
+ specification
37
37
 
38
- Be aware that, even though the ODX specification seems to make the
39
- distinction of "positionable" and "normal" parameters, it does not
40
- define any non-positionable parameter types.
38
+ All parameter classes must adhere to the `Codec` type protocol, so
39
+ `isinstance(param, Codec)` ought to be true. Be aware that, even
40
+ though the ODX specification seems to make the distinction of
41
+ "positionable" and "normal" parameters, it does not define any
42
+ non-positionable parameter types.
41
43
 
42
44
  """
43
45
  oid: Optional[str]
@@ -20,9 +20,16 @@ if TYPE_CHECKING:
20
20
 
21
21
  @dataclass
22
22
  class ParamLengthInfoType(DiagCodedType):
23
-
24
23
  length_key_ref: OdxLinkRef
25
24
 
25
+ @property
26
+ def dct_type(self) -> DctType:
27
+ return "PARAM-LENGTH-INFO-TYPE"
28
+
29
+ @property
30
+ def length_key(self) -> "LengthKeyParameter":
31
+ return self._length_key
32
+
26
33
  @staticmethod
27
34
  @override
28
35
  def from_et(et_element: ElementTree.Element,
@@ -34,10 +41,6 @@ class ParamLengthInfoType(DiagCodedType):
34
41
 
35
42
  return ParamLengthInfoType(length_key_ref=length_key_ref, **kwargs)
36
43
 
37
- @property
38
- def dct_type(self) -> DctType:
39
- return "PARAM-LENGTH-INFO-TYPE"
40
-
41
44
  def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
42
45
  return super()._build_odxlinks()
43
46
 
@@ -54,10 +57,6 @@ class ParamLengthInfoType(DiagCodedType):
54
57
  """Recursively resolve any short-name references"""
55
58
  super()._resolve_snrefs(context)
56
59
 
57
- @property
58
- def length_key(self) -> "LengthKeyParameter":
59
- return self._length_key
60
-
61
60
  @override
62
61
  def encode_into_pdu(self, internal_value: AtomicOdxType, encode_state: EncodeState) -> None:
63
62
  bit_length = encode_state.length_keys.get(self.length_key.short_name)
odxtools/request.py CHANGED
@@ -1,39 +1,132 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  from dataclasses import dataclass
3
- from typing import List
3
+ from typing import Any, Dict, List, Optional, cast
4
4
  from xml.etree import ElementTree
5
5
 
6
- from .basicstructure import BasicStructure
6
+ from .admindata import AdminData
7
+ from .codec import (composite_codec_decode_from_pdu, composite_codec_encode_into_pdu,
8
+ composite_codec_get_coded_const_prefix, composite_codec_get_free_parameters,
9
+ composite_codec_get_required_parameters, composite_codec_get_static_bit_length)
10
+ from .decodestate import DecodeState
11
+ from .element import IdentifiableElement
7
12
  from .encodestate import EncodeState
8
- from .odxlink import OdxDocFragment
9
- from .odxtypes import ParameterValue
13
+ from .exceptions import odxraise
14
+ from .nameditemlist import NamedItemList
15
+ from .odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
16
+ from .odxtypes import ParameterValue, ParameterValueDict
17
+ from .parameters.createanyparameter import create_any_parameter_from_et
18
+ from .parameters.parameter import Parameter
10
19
  from .snrefcontext import SnRefContext
20
+ from .specialdatagroup import SpecialDataGroup
11
21
  from .utils import dataclass_fields_asdict
12
22
 
13
23
 
14
- # TODO: The spec does not say that requests are basic structures. For
15
- # now, we derive from it anyway because it simplifies the en- and
16
- # decoding machinery...
17
24
  @dataclass
18
- class Request(BasicStructure):
25
+ class Request(IdentifiableElement):
26
+ """Represents all information related to an UDS request
27
+
28
+ This class implements the `CompositeCodec` interface.
29
+ """
30
+ admin_data: Optional[AdminData]
31
+ parameters: NamedItemList[Parameter]
32
+ sdgs: List[SpecialDataGroup]
33
+
34
+ @property
35
+ def required_parameters(self) -> List[Parameter]:
36
+ return composite_codec_get_required_parameters(self)
37
+
38
+ @property
39
+ def free_parameters(self) -> List[Parameter]:
40
+ return composite_codec_get_free_parameters(self)
19
41
 
20
42
  @staticmethod
21
43
  def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "Request":
22
- """Reads a response."""
23
- kwargs = dataclass_fields_asdict(BasicStructure.from_et(et_element, doc_frags))
44
+ kwargs = dataclass_fields_asdict(IdentifiableElement.from_et(et_element, doc_frags))
24
45
 
25
- return Request(**kwargs)
46
+ admin_data = AdminData.from_et(et_element.find("ADMIN-DATA"), doc_frags)
47
+ parameters = NamedItemList([
48
+ create_any_parameter_from_et(et_parameter, doc_frags)
49
+ for et_parameter in et_element.iterfind("PARAMS/PARAM")
50
+ ])
51
+ sdgs = [
52
+ SpecialDataGroup.from_et(sdge, doc_frags) for sdge in et_element.iterfind("SDGS/SDG")
53
+ ]
26
54
 
27
- def encode(self, **kwargs: ParameterValue) -> bytes:
28
- encode_state = EncodeState(is_end_of_pdu=True)
55
+ return Request(admin_data=admin_data, parameters=parameters, sdgs=sdgs, **kwargs)
29
56
 
30
- self.encode_into_pdu(physical_value=kwargs, encode_state=encode_state)
57
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
58
+ result = {self.odx_id: self}
31
59
 
32
- return encode_state.coded_message
60
+ if self.admin_data is not None:
61
+ result.update(self.admin_data._build_odxlinks())
62
+
63
+ for param in self.parameters:
64
+ result.update(param._build_odxlinks())
65
+
66
+ for sdg in self.sdgs:
67
+ result.update(sdg._build_odxlinks())
68
+
69
+ return result
70
+
71
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
72
+ if self.admin_data is not None:
73
+ self.admin_data._resolve_odxlinks(odxlinks)
74
+
75
+ for param in self.parameters:
76
+ param._resolve_odxlinks(odxlinks)
77
+
78
+ for sdg in self.sdgs:
79
+ sdg._resolve_odxlinks(odxlinks)
33
80
 
34
81
  def _resolve_snrefs(self, context: SnRefContext) -> None:
35
82
  context.request = self
83
+ context.parameters = self.parameters
36
84
 
37
- super()._resolve_snrefs(context)
85
+ if self.admin_data is not None:
86
+ self.admin_data._resolve_snrefs(context)
87
+
88
+ for param in self.parameters:
89
+ param._resolve_snrefs(context)
90
+
91
+ for sdg in self.sdgs:
92
+ sdg._resolve_snrefs(context)
38
93
 
39
94
  context.request = None
95
+ context.parameters = None
96
+
97
+ def get_static_bit_length(self) -> Optional[int]:
98
+ return composite_codec_get_static_bit_length(self)
99
+
100
+ def print_free_parameters_info(self) -> None:
101
+ """Print a human readable description of the composite codec's
102
+ free parameters to `stdout`
103
+ """
104
+ from .parameterinfo import parameter_info
105
+
106
+ print(parameter_info(self.free_parameters), end="")
107
+
108
+ def encode(self, **kwargs: ParameterValue) -> bytearray:
109
+ encode_state = EncodeState(is_end_of_pdu=True)
110
+
111
+ self.encode_into_pdu(physical_value=kwargs, encode_state=encode_state)
112
+
113
+ return encode_state.coded_message
114
+
115
+ def decode(self, message: bytes) -> ParameterValueDict:
116
+ decode_state = DecodeState(coded_message=message)
117
+ param_values = self.decode_from_pdu(decode_state)
118
+
119
+ if not isinstance(param_values, dict):
120
+ odxraise("Decoding a request must result in a dictionary")
121
+
122
+ return cast(ParameterValueDict, param_values)
123
+
124
+ def encode_into_pdu(self, physical_value: Optional[ParameterValue],
125
+ encode_state: EncodeState) -> None:
126
+ composite_codec_encode_into_pdu(self, physical_value, encode_state)
127
+
128
+ def decode_from_pdu(self, decode_state: DecodeState) -> ParameterValue:
129
+ return composite_codec_decode_from_pdu(self, decode_state)
130
+
131
+ def coded_const_prefix(self, request_prefix: bytes = b'') -> bytes:
132
+ return composite_codec_get_coded_const_prefix(self, request_prefix)