odxtools 7.4.0__py3-none-any.whl → 8.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.
Files changed (50) hide show
  1. odxtools/cli/_print_utils.py +4 -3
  2. odxtools/cli/browse.py +13 -11
  3. odxtools/cli/compare.py +1 -1
  4. odxtools/cli/list.py +20 -10
  5. odxtools/cli/snoop.py +28 -5
  6. odxtools/database.py +46 -10
  7. odxtools/diagcomm.py +4 -4
  8. odxtools/diaglayercontainer.py +23 -11
  9. odxtools/diaglayers/basevariant.py +128 -0
  10. odxtools/diaglayers/basevariantraw.py +117 -0
  11. odxtools/diaglayers/diaglayer.py +422 -0
  12. odxtools/{diaglayerraw.py → diaglayers/diaglayerraw.py} +18 -156
  13. odxtools/diaglayers/ecushareddata.py +96 -0
  14. odxtools/diaglayers/ecushareddataraw.py +81 -0
  15. odxtools/diaglayers/ecuvariant.py +124 -0
  16. odxtools/diaglayers/ecuvariantraw.py +123 -0
  17. odxtools/diaglayers/functionalgroup.py +110 -0
  18. odxtools/diaglayers/functionalgroupraw.py +100 -0
  19. odxtools/{diaglayer.py → diaglayers/hierarchyelement.py} +183 -498
  20. odxtools/diaglayers/hierarchyelementraw.py +52 -0
  21. odxtools/diaglayers/protocol.py +64 -0
  22. odxtools/diaglayers/protocolraw.py +85 -0
  23. odxtools/diagvariable.py +10 -1
  24. odxtools/ecuvariantmatcher.py +6 -7
  25. odxtools/field.py +3 -4
  26. odxtools/matchingparameter.py +1 -1
  27. odxtools/nameditemlist.py +4 -3
  28. odxtools/parameterinfo.py +10 -1
  29. odxtools/parameters/parameterwithdop.py +2 -3
  30. odxtools/parentref.py +1 -1
  31. odxtools/snrefcontext.py +1 -1
  32. odxtools/templates/diag_layer_container.odx-d.xml.jinja2 +11 -6
  33. odxtools/templates/macros/printBaseVariant.xml.jinja2 +53 -0
  34. odxtools/templates/macros/printCompuMethod.xml.jinja2 +1 -1
  35. odxtools/templates/macros/printDiagLayer.xml.jinja2 +206 -0
  36. odxtools/templates/macros/printEcuSharedData.xml.jinja2 +30 -0
  37. odxtools/templates/macros/printEcuVariant.xml.jinja2 +53 -0
  38. odxtools/templates/macros/printFunctionalGroup.xml.jinja2 +40 -0
  39. odxtools/templates/macros/printHierarchyElement.xml.jinja2 +24 -0
  40. odxtools/templates/macros/printProtocol.xml.jinja2 +30 -0
  41. odxtools/variablegroup.py +11 -1
  42. odxtools/version.py +2 -2
  43. {odxtools-7.4.0.dist-info → odxtools-8.0.0.dist-info}/METADATA +1 -1
  44. {odxtools-7.4.0.dist-info → odxtools-8.0.0.dist-info}/RECORD +49 -31
  45. odxtools/templates/macros/printVariant.xml.jinja2 +0 -241
  46. /odxtools/{diaglayertype.py → diaglayers/diaglayertype.py} +0 -0
  47. {odxtools-7.4.0.dist-info → odxtools-8.0.0.dist-info}/LICENSE +0 -0
  48. {odxtools-7.4.0.dist-info → odxtools-8.0.0.dist-info}/WHEEL +0 -0
  49. {odxtools-7.4.0.dist-info → odxtools-8.0.0.dist-info}/entry_points.txt +0 -0
  50. {odxtools-7.4.0.dist-info → odxtools-8.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,52 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import Any, Dict, List
4
+ from xml.etree import ElementTree
5
+
6
+ from ..comparaminstance import ComparamInstance
7
+ from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId
8
+ from ..snrefcontext import SnRefContext
9
+ from ..utils import dataclass_fields_asdict
10
+ from .diaglayerraw import DiagLayerRaw
11
+
12
+
13
+ @dataclass
14
+ class HierarchyElementRaw(DiagLayerRaw):
15
+ """This is the base class for diagnostic layers that may be involved in value inheritance
16
+
17
+ This class represents the data present in the XML, not the "logical" view.
18
+ """
19
+
20
+ comparam_refs: List[ComparamInstance]
21
+
22
+ @staticmethod
23
+ def from_et(et_element: ElementTree.Element,
24
+ doc_frags: List[OdxDocFragment]) -> "HierarchyElementRaw":
25
+ kwargs = dataclass_fields_asdict(DiagLayerRaw.from_et(et_element, doc_frags))
26
+
27
+ comparam_refs = [
28
+ ComparamInstance.from_et(el, doc_frags)
29
+ for el in et_element.iterfind("COMPARAM-REFS/COMPARAM-REF")
30
+ ]
31
+
32
+ return HierarchyElementRaw(comparam_refs=comparam_refs, **kwargs)
33
+
34
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
35
+ result = super()._build_odxlinks()
36
+
37
+ for comparam_ref in self.comparam_refs:
38
+ result.update(comparam_ref._build_odxlinks())
39
+
40
+ return result
41
+
42
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
43
+ super()._resolve_odxlinks(odxlinks)
44
+
45
+ for comparam_ref in self.comparam_refs:
46
+ comparam_ref._resolve_odxlinks(odxlinks)
47
+
48
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
49
+ super()._resolve_snrefs(context)
50
+
51
+ for comparam_ref in self.comparam_refs:
52
+ comparam_ref._resolve_snrefs(context)
@@ -0,0 +1,64 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from copy import deepcopy
3
+ from dataclasses import dataclass
4
+ from typing import Any, Dict, List, Optional, cast
5
+ from xml.etree import ElementTree
6
+
7
+ from ..comparamspec import ComparamSpec
8
+ from ..exceptions import odxassert
9
+ from ..odxlink import OdxDocFragment
10
+ from ..protstack import ProtStack
11
+ from .hierarchyelement import HierarchyElement
12
+ from .protocolraw import ProtocolRaw
13
+
14
+
15
+ @dataclass
16
+ class Protocol(HierarchyElement):
17
+ """This is the class for primitives that are common for a given communication protocol
18
+
19
+ Most importantly this diagnostic layer is responsible for defining
20
+ the communication parameters that ought to be used.
21
+ """
22
+
23
+ @property
24
+ def protocol_raw(self) -> ProtocolRaw:
25
+ return cast(ProtocolRaw, self.diag_layer_raw)
26
+
27
+ @property
28
+ def comparam_spec(self) -> ComparamSpec:
29
+ return self.protocol_raw.comparam_spec
30
+
31
+ @property
32
+ def prot_stack(self) -> Optional[ProtStack]:
33
+ return self.protocol_raw.prot_stack
34
+
35
+ @staticmethod
36
+ def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "Protocol":
37
+ protocol_raw = ProtocolRaw.from_et(et_element, doc_frags)
38
+
39
+ return Protocol(diag_layer_raw=protocol_raw)
40
+
41
+ def __post_init__(self) -> None:
42
+ super().__post_init__()
43
+
44
+ odxassert(
45
+ isinstance(self.diag_layer_raw, ProtocolRaw),
46
+ "The raw diagnostic layer passed to Protocol "
47
+ "must be a ProtocolRaw")
48
+
49
+ def __deepcopy__(self, memo: Dict[int, Any]) -> Any:
50
+ """Create a deep copy of the protocol layer
51
+
52
+ Note that the copied diagnostic layer is not fully
53
+ initialized, so `_finalize_init()` should to be called on it
54
+ before it can be used normally.
55
+ """
56
+
57
+ result = super().__deepcopy__(memo)
58
+
59
+ # note that the self.protocol_raw object is *not* copied at
60
+ # this place because the attribute points to the same object
61
+ # as self.diag_layer_raw.
62
+ result.protocol_raw = deepcopy(self.protocol_raw, memo)
63
+
64
+ return result
@@ -0,0 +1,85 @@
1
+ # SPDX-License-Identifier: MIT
2
+ from dataclasses import dataclass
3
+ from typing import Any, Dict, List, Optional
4
+ from xml.etree import ElementTree
5
+
6
+ from ..comparamspec import ComparamSpec
7
+ from ..exceptions import odxrequire
8
+ from ..odxlink import OdxDocFragment, OdxLinkDatabase, OdxLinkId, OdxLinkRef, resolve_snref
9
+ from ..parentref import ParentRef
10
+ from ..protstack import ProtStack
11
+ from ..snrefcontext import SnRefContext
12
+ from ..utils import dataclass_fields_asdict
13
+ #from .comparaminstance import ComparamInstance
14
+ from .hierarchyelementraw import HierarchyElementRaw
15
+
16
+
17
+ @dataclass
18
+ class ProtocolRaw(HierarchyElementRaw):
19
+ """This is the base class for diagnostic layers that describe a
20
+ protocol which can be used to communicate with an ECU
21
+
22
+ This class represents the data present in the XML, not the "logical" view.
23
+
24
+ """
25
+
26
+ comparam_spec_ref: OdxLinkRef
27
+ prot_stack_snref: Optional[str]
28
+ parent_refs: List[ParentRef]
29
+
30
+ @property
31
+ def comparam_spec(self) -> ComparamSpec:
32
+ return self._comparam_spec
33
+
34
+ @property
35
+ def prot_stack(self) -> Optional[ProtStack]:
36
+ return self._prot_stack
37
+
38
+ @staticmethod
39
+ def from_et(et_element: ElementTree.Element, doc_frags: List[OdxDocFragment]) -> "ProtocolRaw":
40
+ kwargs = dataclass_fields_asdict(HierarchyElementRaw.from_et(et_element, doc_frags))
41
+
42
+ comparam_spec_ref = OdxLinkRef.from_et(
43
+ odxrequire(et_element.find("COMPARAM-SPEC-REF")), doc_frags)
44
+
45
+ prot_stack_snref = None
46
+ if (prot_stack_snref_elem := et_element.find("PROT-STACK-SNREF")) is not None:
47
+ prot_stack_snref = odxrequire(prot_stack_snref_elem.get("SHORT-NAME"))
48
+
49
+ parent_refs = [
50
+ ParentRef.from_et(pr_el, doc_frags)
51
+ for pr_el in et_element.iterfind("PARENT-REFS/PARENT-REF")
52
+ ]
53
+
54
+ return ProtocolRaw(
55
+ comparam_spec_ref=comparam_spec_ref,
56
+ prot_stack_snref=prot_stack_snref,
57
+ parent_refs=parent_refs,
58
+ **kwargs)
59
+
60
+ def _build_odxlinks(self) -> Dict[OdxLinkId, Any]:
61
+ result = super()._build_odxlinks()
62
+
63
+ for parent_ref in self.parent_refs:
64
+ result.update(parent_ref._build_odxlinks())
65
+
66
+ return result
67
+
68
+ def _resolve_odxlinks(self, odxlinks: OdxLinkDatabase) -> None:
69
+ super()._resolve_odxlinks(odxlinks)
70
+
71
+ for parent_ref in self.parent_refs:
72
+ parent_ref._resolve_odxlinks(odxlinks)
73
+
74
+ self._comparam_spec = odxlinks.resolve(self.comparam_spec_ref, ComparamSpec)
75
+
76
+ def _resolve_snrefs(self, context: SnRefContext) -> None:
77
+ super()._resolve_snrefs(context)
78
+
79
+ self._prot_stack = None
80
+ if self.prot_stack_snref is not None:
81
+ self._prot_stack = resolve_snref(self.prot_stack_snref, self._comparam_spec.prot_stacks,
82
+ ProtStack)
83
+
84
+ for parent_ref in self.parent_refs:
85
+ parent_ref._resolve_snrefs(context)
odxtools/diagvariable.py CHANGED
@@ -1,6 +1,7 @@
1
1
  # SPDX-License-Identifier: MIT
2
+ import typing
2
3
  from dataclasses import dataclass
3
- from typing import Any, Dict, List, Optional
4
+ from typing import Any, Dict, List, Optional, runtime_checkable
4
5
  from xml.etree import ElementTree
5
6
 
6
7
  from .admindata import AdminData
@@ -17,6 +18,14 @@ from .utils import dataclass_fields_asdict
17
18
  from .variablegroup import VariableGroup
18
19
 
19
20
 
21
+ @runtime_checkable
22
+ class HasDiagVariables(typing.Protocol):
23
+
24
+ @property
25
+ def diag_variables(self) -> "NamedItemList[DiagVariable]":
26
+ ...
27
+
28
+
20
29
  @dataclass
21
30
  class DiagVariable(IdentifiableElement):
22
31
  """Representation of a diagnostic variable
@@ -2,10 +2,11 @@
2
2
  from enum import Enum
3
3
  from typing import Dict, Generator, List, Optional
4
4
 
5
- from .diaglayer import DiagLayer
6
- from .diaglayertype import DiagLayerType
5
+ from .diaglayers.diaglayer import DiagLayer
6
+ from .diaglayers.diaglayertype import DiagLayerType
7
+ from .diaglayers.ecuvariant import EcuVariant
7
8
  from .diagservice import DiagService
8
- from .exceptions import OdxError, odxassert
9
+ from .exceptions import OdxError, odxassert, odxrequire
9
10
  from .matchingparameter import MatchingParameter
10
11
  from .odxtypes import ParameterValue
11
12
  from .response import Response
@@ -42,9 +43,7 @@ class EcuVariantMatcher:
42
43
  @staticmethod
43
44
  def get_ident_service(diag_layer: DiagLayer, matching_param: MatchingParameter) -> DiagService:
44
45
  service_name = matching_param.diag_comm_snref
45
- odxassert(service_name in [x.short_name for x in diag_layer.services])
46
- service = diag_layer.services[service_name]
47
- odxassert(isinstance(service, DiagService))
46
+ service = odxrequire(diag_layer.services.get(service_name))
48
47
  return service
49
48
 
50
49
  @staticmethod
@@ -89,7 +88,7 @@ class EcuVariantMatcher:
89
88
  raise OdxError(f"The snref or snpathref '{matching_param.out_param_if}' is cannot be \
90
89
  resolved for any positive or negative response.")
91
90
 
92
- def __init__(self, ecu_variant_candidates: List[DiagLayer], use_cache: bool = True):
91
+ def __init__(self, ecu_variant_candidates: List[EcuVariant], use_cache: bool = True):
93
92
 
94
93
  self.ecus = ecu_variant_candidates
95
94
  for ecu in self.ecus:
odxtools/field.py CHANGED
@@ -81,12 +81,11 @@ class Field(ComplexDop):
81
81
 
82
82
  def _resolve_snrefs(self, context: SnRefContext) -> None:
83
83
  """Recursively resolve any short-name references"""
84
- ddd_spec = odxrequire(context.diag_layer).diag_data_dictionary_spec
84
+ ddds = odxrequire(context.diag_layer).diag_data_dictionary_spec
85
85
 
86
86
  if self.structure_snref is not None:
87
- self._structure = resolve_snref(self.structure_snref, ddd_spec.structures,
88
- BasicStructure)
87
+ self._structure = resolve_snref(self.structure_snref, ddds.structures, BasicStructure)
89
88
 
90
89
  if self.env_data_desc_snref is not None:
91
- self._env_data_desc = resolve_snref(self.env_data_desc_snref, ddd_spec.env_data_descs,
90
+ self._env_data_desc = resolve_snref(self.env_data_desc_snref, ddds.env_data_descs,
92
91
  EnvironmentDataDescription)
@@ -12,7 +12,7 @@ from .utils import is_short_name, is_short_name_path
12
12
  class MatchingParameter:
13
13
  """According to ISO 22901, a MatchingParameter contains a string value identifying
14
14
  the active ECU variant. Moreover, it references a DIAG-COMM via snref and one of its
15
- positiv response's OUT-PARAM-IF via snref or snpathref.
15
+ positive response's OUT-PARAM-IF via snref or snpathref.
16
16
 
17
17
  Unlike other parameters defined in the `parameters` package, a MatchingParameter is
18
18
  not transferred over the network.
odxtools/nameditemlist.py CHANGED
@@ -1,15 +1,16 @@
1
1
  # SPDX-License-Identifier: MIT
2
2
  import abc
3
+ import typing
3
4
  from copy import deepcopy
4
5
  from keyword import iskeyword
5
- from typing import (Any, Collection, Dict, Iterable, List, Optional, Protocol, SupportsIndex, Tuple,
6
- TypeVar, Union, cast, overload, runtime_checkable)
6
+ from typing import (Any, Collection, Dict, Iterable, List, Optional, SupportsIndex, Tuple, TypeVar,
7
+ Union, cast, overload, runtime_checkable)
7
8
 
8
9
  from .exceptions import odxraise
9
10
 
10
11
 
11
12
  @runtime_checkable
12
- class OdxNamed(Protocol):
13
+ class OdxNamed(typing.Protocol):
13
14
 
14
15
  @property
15
16
  def short_name(self) -> str:
odxtools/parameterinfo.py CHANGED
@@ -132,7 +132,16 @@ def parameter_info(param_list: Iterable[Parameter], quoted_names: bool = False)
132
132
  val_str = ""
133
133
  if scale.lower_limit is not None:
134
134
  val_str = f"({repr(scale.lower_limit.value)})"
135
- of.write(f" {repr(scale.compu_const)}{val_str}\n")
135
+
136
+ if scale.compu_const is None:
137
+ of.write(f" <ERROR in ODX data: no value specified>\n")
138
+ else:
139
+ vt = scale.compu_const.vt
140
+ v = scale.compu_const.v
141
+ if vt is not None:
142
+ of.write(f" \"{vt}\" {val_str}\n")
143
+ else:
144
+ of.write(f" {v}\n")
136
145
 
137
146
  elif isinstance(cm, IdenticalCompuMethod):
138
147
  bdt = dop.physical_type.base_data_type
@@ -60,9 +60,8 @@ class ParameterWithDOP(Parameter):
60
60
  super()._resolve_snrefs(context)
61
61
 
62
62
  if self.dop_snref:
63
- all_dops = odxrequire(
64
- context.diag_layer).diag_data_dictionary_spec.all_data_object_properties
65
- self._dop = resolve_snref(self.dop_snref, all_dops, DopBase)
63
+ ddds = odxrequire(context.diag_layer).diag_data_dictionary_spec
64
+ self._dop = resolve_snref(self.dop_snref, ddds.all_data_object_properties, DopBase)
66
65
 
67
66
  @property
68
67
  def dop(self) -> DopBase:
odxtools/parentref.py CHANGED
@@ -10,7 +10,7 @@ from .snrefcontext import SnRefContext
10
10
  from .utils import dataclass_fields_asdict
11
11
 
12
12
  if TYPE_CHECKING:
13
- from .diaglayer import DiagLayer
13
+ from .diaglayers.diaglayer import DiagLayer
14
14
 
15
15
 
16
16
  @dataclass
odxtools/snrefcontext.py CHANGED
@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, List, Optional
4
4
 
5
5
  if TYPE_CHECKING:
6
6
  from .database import Database
7
- from .diaglayer import DiagLayer
7
+ from .diaglayers.diaglayer import DiagLayer
8
8
  from .diagservice import DiagService
9
9
  from .parameters.parameter import Parameter
10
10
  from .request import Request
@@ -2,10 +2,15 @@
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
4
  -#}
5
- {%- import('macros/printVariant.xml.jinja2') as pv -%}
6
5
  {%- import('macros/printAdminData.xml.jinja2') as pad -%}
7
6
  {%- import('macros/printCompanyData.xml.jinja2') as pcd -%}
8
7
  {%- import('macros/printSpecialData.xml.jinja2') as psd %}
8
+ {%- import('macros/printEcuSharedData.xml.jinja2') as pecusd -%}
9
+ {%- import('macros/printProtocol.xml.jinja2') as pprot %}
10
+ {%- import('macros/printFunctionalGroup.xml.jinja2') as pfuncgroup %}
11
+ {%- import('macros/printEcuSharedData.xml.jinja2') as pecusd %}
12
+ {%- import('macros/printBaseVariant.xml.jinja2') as pbv %}
13
+ {%- import('macros/printEcuVariant.xml.jinja2') as pecuv %}
9
14
  {#- -#}
10
15
 
11
16
  <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
@@ -35,35 +40,35 @@
35
40
  {%- if dlc.protocols %}
36
41
  <PROTOCOLS>
37
42
  {%- for dl in dlc.protocols %}
38
- {{pv.printVariant(dl)|indent(3)}}
43
+ {{pprot.printProtocol(dl)|indent(3)}}
39
44
  {%- endfor %}
40
45
  </PROTOCOLS>
41
46
  {%- endif %}
42
47
  {%- if dlc.functional_groups %}
43
48
  <FUNCTIONAL-GROUPS>
44
49
  {%- for dl in dlc.functional_groups %}
45
- {{pv.printVariant(dl)|indent(3)}}
50
+ {{pfuncgroup.printFunctionalGroup(dl)|indent(3)}}
46
51
  {%- endfor %}
47
52
  </FUNCTIONAL-GROUPS>
48
53
  {%- endif %}
49
54
  {%- if dlc.ecu_shared_datas %}
50
55
  <ECU-SHARED-DATAS>
51
56
  {%- for dl in dlc.ecu_shared_datas %}
52
- {{pv.printVariant(dl)|indent(3)}}
57
+ {{pecusd.printEcuSharedData(dl)|indent(3)}}
53
58
  {%- endfor %}
54
59
  </ECU-SHARED-DATAS>
55
60
  {%- endif %}
56
61
  {%- if dlc.base_variants %}
57
62
  <BASE-VARIANTS>
58
63
  {%- for dl in dlc.base_variants %}
59
- {{pv.printVariant(dl)|indent(3)}}
64
+ {{pbv.printBaseVariant(dl)|indent(3)}}
60
65
  {%- endfor %}
61
66
  </BASE-VARIANTS>
62
67
  {%- endif %}
63
68
  {%- if dlc.ecu_variants %}
64
69
  <ECU-VARIANTS>
65
70
  {%- for dl in dlc.ecu_variants %}
66
- {{pv.printVariant(dl)|indent(3)}}
71
+ {{pecuv.printEcuVariant(dl)|indent(3)}}
67
72
  {%- endfor %}
68
73
  </ECU-VARIANTS>
69
74
  {%- endif %}
@@ -0,0 +1,53 @@
1
+ {#- -*- mode: sgml; tab-width: 2; indent-tabs-mode: nil -*-
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+ -#}
5
+
6
+ {%- import('macros/printHierarchyElement.xml.jinja2') as phe %}
7
+ {%- import('macros/printComparamRef.xml.jinja2') as pcom %}
8
+ {%- import('macros/printParentRef.xml.jinja2') as pparref %}
9
+
10
+ {%- macro printBaseVariant(base_variant) -%}
11
+ <BASE-VARIANT {{- phe.printHierarchyElementAttribs(base_variant) -}}>
12
+ {{ phe.printHierarchyElementSubtags(base_variant) | indent(2) }}
13
+ {%- set dlr = base_variant.base_variant_raw %}
14
+
15
+ {%- if dlr.diag_variables %}
16
+ <DIAG-VARIABLES>
17
+ {%- for dv in dlr.diag_variables -%}
18
+ {{ pdv.printDiagVariable(dv)|indent(4) }}
19
+ {%- endfor -%}
20
+ </DIAG-VARIABLES>
21
+ {%- endif %}
22
+
23
+ {%- if dlr.variable_groups %}
24
+ <VARIABLE-GROUPS>
25
+ {%- for vg in dlr.variable_groups -%}
26
+ {{ pdv.printVariableGroup(vg)|indent(4) }}
27
+ {%- endfor -%}
28
+ </VARIABLE-GROUPS>
29
+ {%- endif %}
30
+
31
+ {%- if dlr.dyn_defined_spec %}
32
+ {{ pdynspec.printPrintDefinedSpec(dlr.dyn_defined_spec)|indent(4) }}
33
+ {%- endif %}
34
+
35
+ {#
36
+ {%- if dlr.base_variant_patterns %}
37
+ <BASE-VARIANT-PATTERNS>
38
+ {%- for vp in dlr.base_variant_patterns -%}
39
+ {{ pvpat.printBaseVariantPattern(vp)|indent(4) }}
40
+ {%- endfor -%}
41
+ </BASE-VARIANT-PATTERNS>
42
+ {%- endif %}
43
+ #}
44
+
45
+ {%- if dlr.parent_refs %}
46
+ <PARENT-REFS>
47
+ {%- for parent in dlr.parent_refs -%}
48
+ {{ pparref.printParentRef(parent)|indent(4) }}
49
+ {%- endfor %}
50
+ </PARENT-REFS>
51
+ {%- endif %}
52
+ </BASE-VARIANT>
53
+ {%- endmacro %}
@@ -18,7 +18,7 @@
18
18
  {%- if limit_obj.value_raw is none %}
19
19
  {#- #}/>
20
20
  {%- else %}
21
- {#- #}>{{- limit_obj.value_raw }}</{{tag_name}}>
21
+ {#- #}>{{- limit_obj.value_raw | e }}</{{tag_name}}>
22
22
  {%- endif -%}
23
23
  {%- endif -%}
24
24
  {%- endmacro -%}