ipxact-compiler 0.1.2__tar.gz → 0.2.0__tar.gz

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 (69) hide show
  1. ipxact_compiler-0.2.0/PKG-INFO +188 -0
  2. ipxact_compiler-0.2.0/README.md +161 -0
  3. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/pyproject.toml +1 -1
  4. ipxact_compiler-0.2.0/src/ipxact/__init__.py +17 -0
  5. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/abstractiondefinition_parser.py +49 -16
  6. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/busdefinition_parser.py +10 -8
  7. ipxact_compiler-0.2.0/src/ipxact/parser/common_parser.py +739 -0
  8. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/component_parser.py +490 -227
  9. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/design_parser.py +26 -21
  10. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/designconfig_parser.py +10 -6
  11. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/main_parser.py +14 -6
  12. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/__init__.py +77 -12
  13. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/abstractiondefinition.py +37 -4
  14. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/busdefinition.py +3 -2
  15. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/businterface.py +58 -39
  16. ipxact_compiler-0.2.0/src/ipxact/schema/common.py +416 -0
  17. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/component.py +4 -7
  18. ipxact_compiler-0.2.0/src/ipxact/schema/component_sections.py +262 -0
  19. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/design.py +14 -2
  20. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/designconfig.py +8 -2
  21. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/memorymap.py +101 -14
  22. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/model.py +30 -11
  23. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/ports.py +119 -19
  24. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/schema/vlnv.py +7 -3
  25. ipxact_compiler-0.2.0/src/ipxact/validation.py +57 -0
  26. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/LICENSE +202 -0
  27. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/README.md +12 -0
  28. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/abstractionDefinition.xsd +302 -0
  29. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/abstractor.xsd +165 -0
  30. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/autoConfigure.xsd +109 -0
  31. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/busDefinition.xsd +114 -0
  32. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/busInterface.xsd +591 -0
  33. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/catalog.xsd +79 -0
  34. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/commonStructures.xsd +1134 -0
  35. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/component.xsd +450 -0
  36. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/constraints.xsd +261 -0
  37. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/design.xsd +73 -0
  38. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/designConfig.xsd +187 -0
  39. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/file.xsd +467 -0
  40. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/fileType.xsd +88 -0
  41. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/generator.xsd +286 -0
  42. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/identifier.xsd +102 -0
  43. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/index.xsd +72 -0
  44. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/memoryMap.xsd +1862 -0
  45. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/model.xsd +372 -0
  46. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/port.xsd +1161 -0
  47. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/signalDrivers.xsd +221 -0
  48. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/simpleTypes.xsd +286 -0
  49. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/subInstances.xsd +376 -0
  50. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/typeDefinitions.xsd +198 -0
  51. ipxact_compiler-0.2.0/src/ipxact/xsd/1685-2022/xml.xsd +24 -0
  52. ipxact_compiler-0.2.0/src/ipxact_compiler.egg-info/PKG-INFO +188 -0
  53. ipxact_compiler-0.2.0/src/ipxact_compiler.egg-info/SOURCES.txt +59 -0
  54. ipxact_compiler-0.2.0/tests/test_validation.py +66 -0
  55. ipxact_compiler-0.1.2/PKG-INFO +0 -133
  56. ipxact_compiler-0.1.2/README.md +0 -106
  57. ipxact_compiler-0.1.2/src/ipxact/__init__.py +0 -7
  58. ipxact_compiler-0.1.2/src/ipxact/parser/common_parser.py +0 -443
  59. ipxact_compiler-0.1.2/src/ipxact/schema/common.py +0 -176
  60. ipxact_compiler-0.1.2/src/ipxact/schema/component_sections.py +0 -146
  61. ipxact_compiler-0.1.2/src/ipxact_compiler.egg-info/PKG-INFO +0 -133
  62. ipxact_compiler-0.1.2/src/ipxact_compiler.egg-info/SOURCES.txt +0 -31
  63. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/LICENSE +0 -0
  64. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/setup.cfg +0 -0
  65. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/parser/__init__.py +0 -0
  66. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact/py.typed +0 -0
  67. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact_compiler.egg-info/dependency_links.txt +0 -0
  68. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact_compiler.egg-info/requires.txt +0 -0
  69. {ipxact_compiler-0.1.2 → ipxact_compiler-0.2.0}/src/ipxact_compiler.egg-info/top_level.txt +0 -0
@@ -0,0 +1,188 @@
1
+ Metadata-Version: 2.4
2
+ Name: ipxact-compiler
3
+ Version: 0.2.0
4
+ Summary: Parses IEEE 1685-2022 IP-XACT XML into a Python object model.
5
+ Author: Maxime Travaillard
6
+ License-Expression: LGPL-3.0-only
7
+ Project-URL: Repository, https://github.com/IP-XACT/ipxact-compiler
8
+ Project-URL: Issues, https://github.com/IP-XACT/ipxact-compiler/issues
9
+ Keywords: IP-XACT,IEEE 1685,XML,Compiler
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: lxml
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest; extra == "dev"
26
+ Dynamic: license-file
27
+
28
+ # ipxact-compiler
29
+
30
+ A Python library that parses [IEEE 1685-2022](https://standards.ieee.org/ieee/1685/10307/) IP-XACT
31
+ XML documents into a Python object model.
32
+
33
+ It is a standalone, general-purpose parsing library, not tied to any specific downstream tool or
34
+ flow. `ipxact-compiler` reads IP-XACT and hands you back Python objects; it does not resolve
35
+ cross-file references, link a design, validate semantic consistency, or generate any output.
36
+ That is the job of tools built on top of it.
37
+
38
+ ## What it supports
39
+
40
+ Five IP-XACT top-level document types are supported for now:
41
+
42
+ - `component`
43
+ - `design`
44
+ - `designConfiguration`
45
+ - `busDefinition`
46
+ - `abstractionDefinition`
47
+
48
+ The object model covers the IEEE 1685-2022 XSD schema for these document types: every element and
49
+ attribute the schema allows in them has a place in the object model and is read by the parser. This
50
+ is checked against the official Accellera XSD files, with XML documents generated from the schema
51
+ itself.
52
+
53
+ ### How values are represented
54
+
55
+ - **Expressions are `Expression` objects.** Fields typed as an IP-XACT expression (parameter values,
56
+ addresses, sizes, vector and array bounds, and similar) hold an `Expression` with the raw `value`
57
+ text and its optional `minimum`/`maximum` bounds. Expressions are not evaluated: `"DATA_W-1"` stays
58
+ `"DATA_W-1"`. [XactFlow](https://github.com/IP-XACT/XactFlow) provides an evaluator
59
+ (`xactflow.evaluate`).
60
+ - **`xml:id` attributes** are kept as `xml_id` fields. Plain text elements that can carry an `xml:id`
61
+ (`viewRef`, `group`, `dependency`, ...) are `TextValue` objects (`value` and `xml_id`).
62
+ - **Attributes from other namespaces**, where the schema allows them, are kept in `other_attributes`
63
+ dictionaries, keyed by `{namespace}name`.
64
+ - **`vendorExtensions` is opaque.** Each extension is kept as a raw XML string, not modeled
65
+ per-vendor.
66
+ - **References are kept as references.** VLNV references (`busType`, `componentRef`, ...) and the
67
+ `*DefinitionRef` elements that point into a `typeDefinitions` document are stored as they are
68
+ written; resolving them is left to the caller.
69
+
70
+ ### What is not kept
71
+
72
+ - XML comments and processing instructions.
73
+ - `xsi:` attributes, such as `xsi:schemaLocation` on the root element. On elements that have
74
+ `other_attributes`, they are kept there like any other foreign attribute.
75
+ - The relative order of sibling elements that the schema lets you mix but that end up in separate
76
+ lists: `interconnection` and `monitorInterconnection`, and the different kinds of instantiations.
77
+ Order within each list is kept.
78
+ - Whether an optional element or attribute with a schema default was written out or omitted: both give
79
+ the default value.
80
+ - The `invert` attribute of a `portMap` is not typed in the XSD; it is read as a boolean.
81
+
82
+ Other IP-XACT document types (`typeDefinitions`, `catalog`, `abstractor`, `generatorChain`) are not
83
+ parsed.
84
+
85
+ ## Installation
86
+
87
+ ```bash
88
+ pip install ipxact-compiler
89
+ ```
90
+
91
+ Or, for local development:
92
+
93
+ ```bash
94
+ git clone https://github.com/IP-XACT/ipxact-compiler.git
95
+ cd ipxact-compiler
96
+ pip install -e ".[dev]"
97
+ ```
98
+
99
+ Requires Python >= 3.9. The only runtime dependency is [`lxml`](https://lxml.de/).
100
+
101
+ ## Usage
102
+
103
+ ```python
104
+ import ipxact
105
+
106
+ component = ipxact.parse_file("path/to/some_component.xml")
107
+
108
+ component.vlnv # VLNV
109
+ component.bus_interfaces # list[BusInterface]
110
+ component.memory_maps # list[MemoryMap]
111
+ component.model # Model | None
112
+
113
+ register = component.memory_maps[0].items[0].registers[0]
114
+ register.size # Expression(value="32", minimum=None, maximum=None, ...)
115
+ register.size.value # "32"
116
+ ```
117
+
118
+ `ipxact.parse_file(path)` reads a file, figures out its document type from the root element, and
119
+ returns the matching dataclass (`Component`, `Design`, `DesignConfiguration`, `BusDefinition`, or
120
+ `AbstractionDefinition`).
121
+
122
+ Every schema class (`Component`, `VLNV`, `BusInterface`, `Register`, `Field`, `Expression`, and so
123
+ on) is re-exported at the top level, so `ipxact.<ClassName>` works without reaching into submodules.
124
+
125
+ ### Validation
126
+
127
+ Parsing does not validate by default. The IEEE 1685-2022 XSD files are shipped with the package, so
128
+ validation works offline:
129
+
130
+ ```python
131
+ issues = ipxact.validate("path/to/some_component.xml") # [] when valid
132
+ for issue in issues:
133
+ print(issue.line, issue.message)
134
+
135
+ component = ipxact.parse_file("path/to/some_component.xml", validate=True)
136
+ # raises ipxact.ValidationError (with .issues) if the file is not valid
137
+ ```
138
+
139
+ `ipxact.validate()` also accepts an lxml tree or element, so tools that write IP-XACT can validate
140
+ their output before saving it. `ipxact.xsd_path()` gives the folder holding the XSD files
141
+ (`index.xsd` is the entry point) for tools that need the files themselves.
142
+
143
+ XSD validation checks the structure, types and values of a document, and the uniqueness and reference
144
+ rules the schema defines (for example, two parameters with the same `parameterId`). It does not check
145
+ the Semantic Consistency Rules of the standard.
146
+
147
+ ## Design principles
148
+
149
+ - **Single-file parsing only.** `ipxact-compiler` never opens a second file on its own. Resolving
150
+ VLNV references across a library of files (for example, finding the `Component` that a `Design`'s
151
+ instance refers to) is left to the caller.
152
+ - **Input files are assumed to be valid.** Unless you ask for validation, the parser assumes the
153
+ IP-XACT documents you give it are well-formed and conform to the standard. This is why it favors
154
+ defaulting over raising on missing or malformed data. Use `validate=True` or `ipxact.validate()`
155
+ when the input may not be valid.
156
+ - **The XSD files are shipped, not downloaded.** We decided to ship a copy of the official
157
+ Accellera files instead of downloading them when needed:
158
+ - Validation works offline, including in CI.
159
+ - Validation results only change when we decide to update. The published 1685-2022 files can be
160
+ updated at the same URL (two of the current files were last changed in September 2024, the others in July 2023); with a copy,
161
+ taking such an update is a deliberate change, tested like any other.
162
+ - The website only serves the files over plain HTTP.
163
+
164
+ The online URL (for example in `xsi:schemaLocation`) is only a hint of where to find the schema.
165
+ The schema itself is identified by its namespace, so a local copy is the same schema. To update the
166
+ copy, replace the files (see `src/ipxact/xsd/1685-2022/README.md`).
167
+
168
+ ## Known limitations / ideas for later
169
+
170
+ These are open items, not commitments.
171
+
172
+ - **No deliberate error-handling philosophy yet.** Right now, malformed input either silently
173
+ produces a default value or raises whatever low-level Python exception happens to occur (a
174
+ `ValueError`, an `AttributeError`, etc.) rather than a clear, intentional error type. Deciding on
175
+ and implementing a consistent policy (raise vs. warn vs. silently default, and what exception
176
+ types/messages to use) is still open.
177
+ - **No Semantic Consistency Rule (SCR) checking.** This rules are out of scope for this library.
178
+ They are handled by [XactFlow](https://github.com/IP-XACT/XactFlow), including the rules that
179
+ can be checked on a single document.
180
+ - **No dedicated documentation yet.** This README covers the basics, but a proper documentation site
181
+ (full API reference, more usage examples) is planned for the future.
182
+
183
+ ## License
184
+
185
+ LGPL-3.0. See [`LICENSE`](LICENSE).
186
+
187
+ The IEEE 1685-2022 XSD files in `src/ipxact/xsd/1685-2022/` are Accellera's, unmodified, under the
188
+ Apache License 2.0 (see the `LICENSE` file in that folder).
@@ -0,0 +1,161 @@
1
+ # ipxact-compiler
2
+
3
+ A Python library that parses [IEEE 1685-2022](https://standards.ieee.org/ieee/1685/10307/) IP-XACT
4
+ XML documents into a Python object model.
5
+
6
+ It is a standalone, general-purpose parsing library, not tied to any specific downstream tool or
7
+ flow. `ipxact-compiler` reads IP-XACT and hands you back Python objects; it does not resolve
8
+ cross-file references, link a design, validate semantic consistency, or generate any output.
9
+ That is the job of tools built on top of it.
10
+
11
+ ## What it supports
12
+
13
+ Five IP-XACT top-level document types are supported for now:
14
+
15
+ - `component`
16
+ - `design`
17
+ - `designConfiguration`
18
+ - `busDefinition`
19
+ - `abstractionDefinition`
20
+
21
+ The object model covers the IEEE 1685-2022 XSD schema for these document types: every element and
22
+ attribute the schema allows in them has a place in the object model and is read by the parser. This
23
+ is checked against the official Accellera XSD files, with XML documents generated from the schema
24
+ itself.
25
+
26
+ ### How values are represented
27
+
28
+ - **Expressions are `Expression` objects.** Fields typed as an IP-XACT expression (parameter values,
29
+ addresses, sizes, vector and array bounds, and similar) hold an `Expression` with the raw `value`
30
+ text and its optional `minimum`/`maximum` bounds. Expressions are not evaluated: `"DATA_W-1"` stays
31
+ `"DATA_W-1"`. [XactFlow](https://github.com/IP-XACT/XactFlow) provides an evaluator
32
+ (`xactflow.evaluate`).
33
+ - **`xml:id` attributes** are kept as `xml_id` fields. Plain text elements that can carry an `xml:id`
34
+ (`viewRef`, `group`, `dependency`, ...) are `TextValue` objects (`value` and `xml_id`).
35
+ - **Attributes from other namespaces**, where the schema allows them, are kept in `other_attributes`
36
+ dictionaries, keyed by `{namespace}name`.
37
+ - **`vendorExtensions` is opaque.** Each extension is kept as a raw XML string, not modeled
38
+ per-vendor.
39
+ - **References are kept as references.** VLNV references (`busType`, `componentRef`, ...) and the
40
+ `*DefinitionRef` elements that point into a `typeDefinitions` document are stored as they are
41
+ written; resolving them is left to the caller.
42
+
43
+ ### What is not kept
44
+
45
+ - XML comments and processing instructions.
46
+ - `xsi:` attributes, such as `xsi:schemaLocation` on the root element. On elements that have
47
+ `other_attributes`, they are kept there like any other foreign attribute.
48
+ - The relative order of sibling elements that the schema lets you mix but that end up in separate
49
+ lists: `interconnection` and `monitorInterconnection`, and the different kinds of instantiations.
50
+ Order within each list is kept.
51
+ - Whether an optional element or attribute with a schema default was written out or omitted: both give
52
+ the default value.
53
+ - The `invert` attribute of a `portMap` is not typed in the XSD; it is read as a boolean.
54
+
55
+ Other IP-XACT document types (`typeDefinitions`, `catalog`, `abstractor`, `generatorChain`) are not
56
+ parsed.
57
+
58
+ ## Installation
59
+
60
+ ```bash
61
+ pip install ipxact-compiler
62
+ ```
63
+
64
+ Or, for local development:
65
+
66
+ ```bash
67
+ git clone https://github.com/IP-XACT/ipxact-compiler.git
68
+ cd ipxact-compiler
69
+ pip install -e ".[dev]"
70
+ ```
71
+
72
+ Requires Python >= 3.9. The only runtime dependency is [`lxml`](https://lxml.de/).
73
+
74
+ ## Usage
75
+
76
+ ```python
77
+ import ipxact
78
+
79
+ component = ipxact.parse_file("path/to/some_component.xml")
80
+
81
+ component.vlnv # VLNV
82
+ component.bus_interfaces # list[BusInterface]
83
+ component.memory_maps # list[MemoryMap]
84
+ component.model # Model | None
85
+
86
+ register = component.memory_maps[0].items[0].registers[0]
87
+ register.size # Expression(value="32", minimum=None, maximum=None, ...)
88
+ register.size.value # "32"
89
+ ```
90
+
91
+ `ipxact.parse_file(path)` reads a file, figures out its document type from the root element, and
92
+ returns the matching dataclass (`Component`, `Design`, `DesignConfiguration`, `BusDefinition`, or
93
+ `AbstractionDefinition`).
94
+
95
+ Every schema class (`Component`, `VLNV`, `BusInterface`, `Register`, `Field`, `Expression`, and so
96
+ on) is re-exported at the top level, so `ipxact.<ClassName>` works without reaching into submodules.
97
+
98
+ ### Validation
99
+
100
+ Parsing does not validate by default. The IEEE 1685-2022 XSD files are shipped with the package, so
101
+ validation works offline:
102
+
103
+ ```python
104
+ issues = ipxact.validate("path/to/some_component.xml") # [] when valid
105
+ for issue in issues:
106
+ print(issue.line, issue.message)
107
+
108
+ component = ipxact.parse_file("path/to/some_component.xml", validate=True)
109
+ # raises ipxact.ValidationError (with .issues) if the file is not valid
110
+ ```
111
+
112
+ `ipxact.validate()` also accepts an lxml tree or element, so tools that write IP-XACT can validate
113
+ their output before saving it. `ipxact.xsd_path()` gives the folder holding the XSD files
114
+ (`index.xsd` is the entry point) for tools that need the files themselves.
115
+
116
+ XSD validation checks the structure, types and values of a document, and the uniqueness and reference
117
+ rules the schema defines (for example, two parameters with the same `parameterId`). It does not check
118
+ the Semantic Consistency Rules of the standard.
119
+
120
+ ## Design principles
121
+
122
+ - **Single-file parsing only.** `ipxact-compiler` never opens a second file on its own. Resolving
123
+ VLNV references across a library of files (for example, finding the `Component` that a `Design`'s
124
+ instance refers to) is left to the caller.
125
+ - **Input files are assumed to be valid.** Unless you ask for validation, the parser assumes the
126
+ IP-XACT documents you give it are well-formed and conform to the standard. This is why it favors
127
+ defaulting over raising on missing or malformed data. Use `validate=True` or `ipxact.validate()`
128
+ when the input may not be valid.
129
+ - **The XSD files are shipped, not downloaded.** We decided to ship a copy of the official
130
+ Accellera files instead of downloading them when needed:
131
+ - Validation works offline, including in CI.
132
+ - Validation results only change when we decide to update. The published 1685-2022 files can be
133
+ updated at the same URL (two of the current files were last changed in September 2024, the others in July 2023); with a copy,
134
+ taking such an update is a deliberate change, tested like any other.
135
+ - The website only serves the files over plain HTTP.
136
+
137
+ The online URL (for example in `xsi:schemaLocation`) is only a hint of where to find the schema.
138
+ The schema itself is identified by its namespace, so a local copy is the same schema. To update the
139
+ copy, replace the files (see `src/ipxact/xsd/1685-2022/README.md`).
140
+
141
+ ## Known limitations / ideas for later
142
+
143
+ These are open items, not commitments.
144
+
145
+ - **No deliberate error-handling philosophy yet.** Right now, malformed input either silently
146
+ produces a default value or raises whatever low-level Python exception happens to occur (a
147
+ `ValueError`, an `AttributeError`, etc.) rather than a clear, intentional error type. Deciding on
148
+ and implementing a consistent policy (raise vs. warn vs. silently default, and what exception
149
+ types/messages to use) is still open.
150
+ - **No Semantic Consistency Rule (SCR) checking.** This rules are out of scope for this library.
151
+ They are handled by [XactFlow](https://github.com/IP-XACT/XactFlow), including the rules that
152
+ can be checked on a single document.
153
+ - **No dedicated documentation yet.** This README covers the basics, but a proper documentation site
154
+ (full API reference, more usage examples) is planned for the future.
155
+
156
+ ## License
157
+
158
+ LGPL-3.0. See [`LICENSE`](LICENSE).
159
+
160
+ The IEEE 1685-2022 XSD files in `src/ipxact/xsd/1685-2022/` are Accellera's, unmodified, under the
161
+ Apache License 2.0 (see the `LICENSE` file in that folder).
@@ -48,4 +48,4 @@ version = {attr = "ipxact.__version__"}
48
48
  where = ["src"]
49
49
 
50
50
  [tool.setuptools.package-data]
51
- ipxact = ["py.typed"]
51
+ ipxact = ["py.typed", "xsd/*/*.xsd", "xsd/*/LICENSE", "xsd/*/README.md"]
@@ -0,0 +1,17 @@
1
+ __version__ = "0.2.0"
2
+
3
+ from .parser import parse_element, parse_file
4
+ from .schema import * # noqa: F401,F403
5
+ from .schema import __all__ as _schema_all
6
+ from .validation import ValidationError, ValidationIssue, validate, xsd_path
7
+
8
+ __all__ = [
9
+ *_schema_all,
10
+ "parse_element",
11
+ "parse_file",
12
+ "validate",
13
+ "xsd_path",
14
+ "ValidationError",
15
+ "ValidationIssue",
16
+ "__version__",
17
+ ]
@@ -5,6 +5,8 @@ from lxml import etree
5
5
  from ..schema.abstractiondefinition import (
6
6
  AbstractionDefinition,
7
7
  AbstractionPort,
8
+ Packet,
9
+ PacketField,
8
10
  PortConstraints,
9
11
  Presence,
10
12
  RequiresDriver,
@@ -22,11 +24,14 @@ from .common_parser import (
22
24
  child,
23
25
  children,
24
26
  elem_text,
27
+ expr,
25
28
  parse_assertions,
26
29
  parse_children,
27
30
  parse_choices,
28
31
  parse_drive_constraint,
32
+ parse_optional_expression,
29
33
  parse_load_constraint,
34
+ parse_name_group,
30
35
  parse_parameters,
31
36
  parse_protocol,
32
37
  parse_qualifier,
@@ -34,7 +39,9 @@ from .common_parser import (
34
39
  parse_vendor_extensions,
35
40
  parse_vlnv,
36
41
  parse_vlnv_ref,
42
+ required_expr,
37
43
  text,
44
+ xml_id,
38
45
  )
39
46
 
40
47
 
@@ -49,9 +56,8 @@ def parse_abstractiondefinition(root: etree._Element) -> AbstractionDefinition:
49
56
  choices=parse_choices(root),
50
57
  parameters=parse_parameters(root),
51
58
  assertions=parse_assertions(root),
52
- display_name=text(root, "displayName"),
53
- short_description=text(root, "shortDescription"),
54
- description=text(root, "description"),
59
+ **parse_name_group(root),
60
+ xml_id=xml_id(root),
55
61
  vendor_extensions=parse_vendor_extensions(root),
56
62
  )
57
63
 
@@ -65,7 +71,7 @@ def _parse_port_constraints(elem: etree._Element) -> PortConstraints:
65
71
 
66
72
 
67
73
  def _parse_requires_driver(elem: etree._Element) -> RequiresDriver:
68
- return RequiresDriver(value=as_bool(elem.text, False), driver_type=elem.get("driverType", "any"))
74
+ return RequiresDriver(value=as_bool(elem_text(elem), False), driver_type=elem.get("driverType", "any"))
69
75
 
70
76
 
71
77
  def _parse_wire_mode_constraints(elem: etree._Element) -> WireModeConstraints:
@@ -76,10 +82,10 @@ def _parse_wire_mode_constraints(elem: etree._Element) -> WireModeConstraints:
76
82
  mirrored_mode_constraints_elem = child(elem, "mirroredModeConstraints")
77
83
  return WireModeConstraints(
78
84
  presence=Presence(presence) if presence else Presence.OPTIONAL,
79
- width=elem_text(width_elem),
85
+ width=parse_optional_expression(width_elem),
80
86
  width_all_bits_required=attr_bool(width_elem, "allBits", False) if width_elem is not None else False,
81
- # direction defaults to "out" when absent
82
- direction=elem_text(direction_elem) or "out",
87
+ # default to out and missing means no restiction, so None.
88
+ direction=(elem_text(direction_elem) or "out") if direction_elem is not None else None,
83
89
  mode_constraints=(
84
90
  _parse_port_constraints(mode_constraints_elem) if mode_constraints_elem is not None else None
85
91
  ),
@@ -92,7 +98,9 @@ def _parse_wire_mode_constraints(elem: etree._Element) -> WireModeConstraints:
92
98
 
93
99
 
94
100
  def _parse_wire_system_constraints(elem: etree._Element) -> WireSystemConstraints:
95
- return WireSystemConstraints(group=text(elem, "group") or "", constraints=_parse_wire_mode_constraints(elem))
101
+ return WireSystemConstraints(
102
+ group=text(elem, "group") or "", constraints=_parse_wire_mode_constraints(elem), xml_id=xml_id(elem)
103
+ )
96
104
 
97
105
 
98
106
  def _parse_wire_abstraction_port(elem: etree._Element) -> WireAbstractionPort:
@@ -104,7 +112,7 @@ def _parse_wire_abstraction_port(elem: etree._Element) -> WireAbstractionPort:
104
112
  on_system=[_parse_wire_system_constraints(e) for e in children(elem, "onSystem")],
105
113
  on_initiator=_parse_wire_mode_constraints(on_initiator_elem) if on_initiator_elem is not None else None,
106
114
  on_target=_parse_wire_mode_constraints(on_target_elem) if on_target_elem is not None else None,
107
- default_value=text(elem, "defaultValue"),
115
+ default_value=expr(elem, "defaultValue"),
108
116
  requires_driver=_parse_requires_driver(requires_driver_elem) if requires_driver_elem is not None else None,
109
117
  )
110
118
 
@@ -115,17 +123,18 @@ def _parse_transactional_mode_constraints(elem: etree._Element) -> Transactional
115
123
  kind_elem = child(elem, "kind")
116
124
  return TransactionalModeConstraints(
117
125
  presence=Presence(presence) if presence else Presence.OPTIONAL,
118
- # initiative defaults to "requires" when absent
119
- initiative=elem_text(initiative_elem) or "requires",
126
+ # Same rule as <direction>: missing means "not restricted", default is "requires".
127
+ initiative=(elem_text(initiative_elem) or "requires") if initiative_elem is not None else None,
120
128
  kind=elem_text(kind_elem),
121
- bus_width=text(elem, "busWidth"),
129
+ kind_custom=kind_elem.get("custom") if kind_elem is not None else None,
130
+ bus_width=expr(elem, "busWidth"),
122
131
  protocol=parse_protocol(elem),
123
132
  )
124
133
 
125
134
 
126
135
  def _parse_transactional_system_constraints(elem: etree._Element) -> TransactionalSystemConstraints:
127
136
  return TransactionalSystemConstraints(
128
- group=text(elem, "group") or "", constraints=_parse_transactional_mode_constraints(elem)
137
+ group=text(elem, "group") or "", constraints=_parse_transactional_mode_constraints(elem), xml_id=xml_id(elem)
129
138
  )
130
139
 
131
140
 
@@ -142,6 +151,30 @@ def _parse_transactional_abstraction_port(elem: etree._Element) -> Transactional
142
151
  )
143
152
 
144
153
 
154
+ def _parse_packet_field(elem: etree._Element) -> PacketField:
155
+ return PacketField(
156
+ name=text(elem, "name") or "",
157
+ width=required_expr(elem, "width"),
158
+ value=expr(elem, "value"),
159
+ endianness=text(elem, "endianness"),
160
+ qualifier=parse_qualifier(elem),
161
+ **parse_name_group(elem),
162
+ xml_id=xml_id(elem),
163
+ vendor_extensions=parse_vendor_extensions(elem),
164
+ )
165
+
166
+
167
+ def _parse_packet(elem: etree._Element) -> Packet:
168
+ return Packet(
169
+ name=text(elem, "name") or "",
170
+ packet_fields=parse_children(elem, "packetFields", "packetField", _parse_packet_field),
171
+ endianness=text(elem, "endianness"),
172
+ **parse_name_group(elem),
173
+ xml_id=xml_id(elem),
174
+ vendor_extensions=parse_vendor_extensions(elem),
175
+ )
176
+
177
+
145
178
  def _parse_abstraction_port(elem: etree._Element) -> AbstractionPort:
146
179
  wire_elem = child(elem, "wire")
147
180
  transactional_elem = child(elem, "transactional")
@@ -151,9 +184,9 @@ def _parse_abstraction_port(elem: etree._Element) -> AbstractionPort:
151
184
  transactional=(
152
185
  _parse_transactional_abstraction_port(transactional_elem) if transactional_elem is not None else None
153
186
  ),
187
+ packets=parse_children(elem, "packets", "packet", _parse_packet),
154
188
  match=bool_text(elem, "match", False),
155
- display_name=text(elem, "displayName"),
156
- short_description=text(elem, "shortDescription"),
157
- description=text(elem, "description"),
189
+ **parse_name_group(elem),
190
+ xml_id=xml_id(elem),
158
191
  vendor_extensions=parse_vendor_extensions(elem),
159
192
  )
@@ -6,14 +6,17 @@ from ..schema.busdefinition import BusDefinition
6
6
  from .common_parser import (
7
7
  bool_text,
8
8
  child,
9
+ expr,
9
10
  parse_assertions,
11
+ parse_children,
10
12
  parse_choices,
13
+ parse_name_group,
11
14
  parse_parameters,
12
- parse_texts,
13
15
  parse_vendor_extensions,
14
16
  parse_vlnv,
15
17
  parse_vlnv_ref,
16
- text,
18
+ text_value,
19
+ xml_id,
17
20
  )
18
21
 
19
22
 
@@ -26,14 +29,13 @@ def parse_busdefinition(root: etree._Element) -> BusDefinition:
26
29
  is_addressable=bool_text(root, "isAddressable", False),
27
30
  broadcast=bool_text(root, "broadcast"),
28
31
  extends=parse_vlnv_ref(extends_elem) if extends_elem is not None else None,
29
- max_initiators=text(root, "maxInitiators"),
30
- max_targets=text(root, "maxTargets"),
31
- system_group_names=parse_texts(root, "systemGroupNames", "systemGroupName"),
32
+ max_initiators=expr(root, "maxInitiators"),
33
+ max_targets=expr(root, "maxTargets"),
34
+ system_group_names=parse_children(root, "systemGroupNames", "systemGroupName", text_value),
32
35
  choices=parse_choices(root),
33
36
  parameters=parse_parameters(root),
34
37
  assertions=parse_assertions(root),
35
- display_name=text(root, "displayName"),
36
- short_description=text(root, "shortDescription"),
37
- description=text(root, "description"),
38
+ **parse_name_group(root),
39
+ xml_id=xml_id(root),
38
40
  vendor_extensions=parse_vendor_extensions(root),
39
41
  )