pysdmx 1.5.2__py3-none-any.whl → 1.6.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.
- pysdmx/__init__.py +1 -1
- pysdmx/api/fmr/__init__.py +8 -3
- pysdmx/api/fmr/maintenance.py +158 -0
- pysdmx/api/qb/structure.py +1 -0
- pysdmx/api/qb/util.py +1 -0
- pysdmx/io/csv/__csv_aux_reader.py +99 -0
- pysdmx/io/csv/__csv_aux_writer.py +118 -0
- pysdmx/io/csv/sdmx10/reader/__init__.py +9 -14
- pysdmx/io/csv/sdmx10/writer/__init__.py +28 -2
- pysdmx/io/csv/sdmx20/__init__.py +0 -9
- pysdmx/io/csv/sdmx20/reader/__init__.py +8 -61
- pysdmx/io/csv/sdmx20/writer/__init__.py +32 -25
- pysdmx/io/csv/sdmx21/__init__.py +1 -0
- pysdmx/io/csv/sdmx21/reader/__init__.py +86 -0
- pysdmx/io/csv/sdmx21/writer/__init__.py +70 -0
- pysdmx/io/format.py +8 -0
- pysdmx/io/input_processor.py +16 -2
- pysdmx/io/json/fusion/messages/code.py +21 -4
- pysdmx/io/json/fusion/messages/concept.py +16 -8
- pysdmx/io/json/fusion/messages/dataflow.py +8 -1
- pysdmx/io/json/fusion/messages/dsd.py +15 -0
- pysdmx/io/json/fusion/messages/schema.py +8 -1
- pysdmx/io/json/sdmxjson2/messages/agency.py +43 -7
- pysdmx/io/json/sdmxjson2/messages/category.py +92 -7
- pysdmx/io/json/sdmxjson2/messages/code.py +239 -18
- pysdmx/io/json/sdmxjson2/messages/concept.py +78 -13
- pysdmx/io/json/sdmxjson2/messages/constraint.py +5 -5
- pysdmx/io/json/sdmxjson2/messages/core.py +121 -14
- pysdmx/io/json/sdmxjson2/messages/dataflow.py +63 -8
- pysdmx/io/json/sdmxjson2/messages/dsd.py +215 -20
- pysdmx/io/json/sdmxjson2/messages/map.py +200 -24
- pysdmx/io/json/sdmxjson2/messages/pa.py +36 -5
- pysdmx/io/json/sdmxjson2/messages/provider.py +35 -7
- pysdmx/io/json/sdmxjson2/messages/report.py +85 -7
- pysdmx/io/json/sdmxjson2/messages/schema.py +11 -12
- pysdmx/io/json/sdmxjson2/messages/structure.py +150 -2
- pysdmx/io/json/sdmxjson2/messages/vtl.py +547 -17
- pysdmx/io/json/sdmxjson2/reader/metadata.py +32 -0
- pysdmx/io/json/sdmxjson2/reader/structure.py +32 -0
- pysdmx/io/json/sdmxjson2/writer/__init__.py +9 -0
- pysdmx/io/json/sdmxjson2/writer/metadata.py +60 -0
- pysdmx/io/json/sdmxjson2/writer/structure.py +61 -0
- pysdmx/io/reader.py +28 -9
- pysdmx/io/serde.py +17 -0
- pysdmx/io/writer.py +45 -9
- pysdmx/io/xml/__write_data_aux.py +1 -54
- pysdmx/io/xml/__write_structure_specific_aux.py +1 -1
- pysdmx/io/xml/sdmx21/writer/generic.py +1 -1
- pysdmx/model/code.py +11 -1
- pysdmx/model/dataflow.py +23 -0
- pysdmx/model/map.py +12 -4
- pysdmx/model/message.py +9 -1
- pysdmx/toolkit/pd/_data_utils.py +100 -0
- pysdmx/toolkit/vtl/_validations.py +2 -3
- {pysdmx-1.5.2.dist-info → pysdmx-1.6.0.dist-info}/METADATA +3 -2
- {pysdmx-1.5.2.dist-info → pysdmx-1.6.0.dist-info}/RECORD +58 -46
- {pysdmx-1.5.2.dist-info → pysdmx-1.6.0.dist-info}/WHEEL +1 -1
- {pysdmx-1.5.2.dist-info → pysdmx-1.6.0.dist-info/licenses}/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Collection of SDMX-JSON schemas for SDMX-REST schema queries."""
|
|
2
2
|
|
|
3
|
-
from typing import Literal, Sequence
|
|
3
|
+
from typing import Literal, Optional, Sequence, Tuple
|
|
4
4
|
|
|
5
5
|
import msgspec
|
|
6
6
|
|
|
@@ -10,13 +10,11 @@ from pysdmx.io.json.sdmxjson2.messages.constraint import JsonDataConstraint
|
|
|
10
10
|
from pysdmx.io.json.sdmxjson2.messages.core import JsonHeader
|
|
11
11
|
from pysdmx.io.json.sdmxjson2.messages.dsd import JsonDataStructure
|
|
12
12
|
from pysdmx.model import Components, HierarchyAssociation, Schema
|
|
13
|
+
from pysdmx.model.dataflow import Group
|
|
13
14
|
from pysdmx.util import parse_item_urn
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
class JsonSchemas(
|
|
17
|
-
msgspec.Struct,
|
|
18
|
-
frozen=True,
|
|
19
|
-
):
|
|
17
|
+
class JsonSchemas(msgspec.Struct, frozen=True, omit_defaults=True):
|
|
20
18
|
"""SDMX-JSON payload schema structures."""
|
|
21
19
|
|
|
22
20
|
conceptSchemes: Sequence[JsonConceptScheme]
|
|
@@ -25,21 +23,21 @@ class JsonSchemas(
|
|
|
25
23
|
codelists: Sequence[JsonCodelist] = ()
|
|
26
24
|
contentConstraints: Sequence[JsonDataConstraint] = ()
|
|
27
25
|
|
|
28
|
-
def to_model(
|
|
26
|
+
def to_model(
|
|
27
|
+
self,
|
|
28
|
+
) -> Tuple[Components, Optional[Sequence[Group]]]:
|
|
29
29
|
"""Returns the requested schema."""
|
|
30
30
|
comps = self.dataStructures[0].dataStructureComponents
|
|
31
|
-
|
|
31
|
+
comps, grps = comps.to_model( # type: ignore[union-attr,assignment]
|
|
32
32
|
self.conceptSchemes,
|
|
33
33
|
self.codelists,
|
|
34
34
|
self.valuelists,
|
|
35
35
|
self.contentConstraints,
|
|
36
36
|
)
|
|
37
|
+
return comps, grps # type: ignore[return-value]
|
|
37
38
|
|
|
38
39
|
|
|
39
|
-
class JsonSchemaMessage(
|
|
40
|
-
msgspec.Struct,
|
|
41
|
-
frozen=True,
|
|
42
|
-
):
|
|
40
|
+
class JsonSchemaMessage(msgspec.Struct, frozen=True, omit_defaults=True):
|
|
43
41
|
"""SDMX-JSON payload for /schema queries."""
|
|
44
42
|
|
|
45
43
|
meta: JsonHeader
|
|
@@ -54,7 +52,7 @@ class JsonSchemaMessage(
|
|
|
54
52
|
hierarchies: Sequence[HierarchyAssociation],
|
|
55
53
|
) -> Schema:
|
|
56
54
|
"""Returns the requested schema."""
|
|
57
|
-
components = self.data.to_model()
|
|
55
|
+
components, groups = self.data.to_model()
|
|
58
56
|
comp_dict = {c.id: c for c in components}
|
|
59
57
|
urns = [a.urn for a in self.meta.links]
|
|
60
58
|
for ha in hierarchies:
|
|
@@ -78,4 +76,5 @@ class JsonSchemaMessage(
|
|
|
78
76
|
comps,
|
|
79
77
|
version,
|
|
80
78
|
urns, # type: ignore[arg-type]
|
|
79
|
+
groups=groups,
|
|
81
80
|
)
|
|
@@ -4,6 +4,7 @@ from typing import Sequence
|
|
|
4
4
|
|
|
5
5
|
from msgspec import Struct
|
|
6
6
|
|
|
7
|
+
from pysdmx import errors
|
|
7
8
|
from pysdmx.io.json.sdmxjson2.messages.agency import JsonAgencyScheme
|
|
8
9
|
from pysdmx.io.json.sdmxjson2.messages.category import (
|
|
9
10
|
JsonCategorisation,
|
|
@@ -37,7 +38,7 @@ from pysdmx.model.__base import MaintainableArtefact
|
|
|
37
38
|
from pysdmx.model.message import StructureMessage
|
|
38
39
|
|
|
39
40
|
|
|
40
|
-
class JsonStructures(Struct, frozen=True):
|
|
41
|
+
class JsonStructures(Struct, frozen=True, omit_defaults=True):
|
|
41
42
|
"""The allowed strutures."""
|
|
42
43
|
|
|
43
44
|
dataStructures: Sequence[JsonDataStructure] = ()
|
|
@@ -126,8 +127,144 @@ class JsonStructures(Struct, frozen=True):
|
|
|
126
127
|
structures.append(rm.to_model(multi))
|
|
127
128
|
return structures
|
|
128
129
|
|
|
130
|
+
@classmethod
|
|
131
|
+
def from_model(cls, msg: StructureMessage) -> "JsonStructures":
|
|
132
|
+
"""Create an SDMX-JSON structures from a list of artefacts."""
|
|
133
|
+
if not msg.structures:
|
|
134
|
+
raise errors.Invalid(
|
|
135
|
+
"Invalid input",
|
|
136
|
+
"SDMX-JSON structure messages must have structures.",
|
|
137
|
+
)
|
|
138
|
+
codelists = tuple(
|
|
139
|
+
[JsonCodelist.from_model(c) for c in msg.get_codelists()]
|
|
140
|
+
)
|
|
141
|
+
valuelists = tuple(
|
|
142
|
+
[JsonValuelist.from_model(c) for c in msg.get_value_lists()]
|
|
143
|
+
)
|
|
144
|
+
agencies = tuple(
|
|
145
|
+
[JsonAgencyScheme.from_model(a) for a in msg.get_agency_schemes()]
|
|
146
|
+
)
|
|
147
|
+
dataflows = tuple(
|
|
148
|
+
[JsonDataflow.from_model(d) for d in msg.get_dataflows()]
|
|
149
|
+
)
|
|
150
|
+
agreements = tuple(
|
|
151
|
+
[
|
|
152
|
+
JsonProvisionAgreement.from_model(p)
|
|
153
|
+
for p in msg.get_provision_agreements()
|
|
154
|
+
]
|
|
155
|
+
)
|
|
156
|
+
categorisations = tuple(
|
|
157
|
+
[
|
|
158
|
+
JsonCategorisation.from_model(c)
|
|
159
|
+
for c in msg.get_categorisations()
|
|
160
|
+
]
|
|
161
|
+
)
|
|
162
|
+
hier_associations = tuple(
|
|
163
|
+
[
|
|
164
|
+
JsonHierarchyAssociation.from_model(ha)
|
|
165
|
+
for ha in msg.get_hierarchy_associations()
|
|
166
|
+
]
|
|
167
|
+
)
|
|
168
|
+
category_schemes = tuple(
|
|
169
|
+
[
|
|
170
|
+
JsonCategoryScheme.from_model(cs)
|
|
171
|
+
for cs in msg.get_category_schemes()
|
|
172
|
+
]
|
|
173
|
+
)
|
|
174
|
+
concept_schemes = tuple(
|
|
175
|
+
[
|
|
176
|
+
JsonConceptScheme.from_model(cs)
|
|
177
|
+
for cs in msg.get_concept_schemes()
|
|
178
|
+
]
|
|
179
|
+
)
|
|
180
|
+
data_structures = tuple(
|
|
181
|
+
[
|
|
182
|
+
JsonDataStructure.from_model(ds)
|
|
183
|
+
for ds in msg.get_data_structure_definitions()
|
|
184
|
+
]
|
|
185
|
+
)
|
|
186
|
+
data_providers = tuple(
|
|
187
|
+
[
|
|
188
|
+
JsonDataProviderScheme.from_model(dps)
|
|
189
|
+
for dps in msg.get_data_provider_schemes()
|
|
190
|
+
]
|
|
191
|
+
)
|
|
192
|
+
representations_maps = tuple(
|
|
193
|
+
[
|
|
194
|
+
JsonRepresentationMap.from_model(rm)
|
|
195
|
+
for rm in msg.get_representation_maps()
|
|
196
|
+
]
|
|
197
|
+
)
|
|
198
|
+
structure_maps = tuple(
|
|
199
|
+
[
|
|
200
|
+
JsonStructureMap.from_model(sm)
|
|
201
|
+
for sm in msg.get_structure_maps()
|
|
202
|
+
]
|
|
203
|
+
)
|
|
204
|
+
custom_types = tuple(
|
|
205
|
+
[
|
|
206
|
+
JsonCustomTypeScheme.from_model(ct)
|
|
207
|
+
for ct in msg.get_custom_type_schemes()
|
|
208
|
+
]
|
|
209
|
+
)
|
|
210
|
+
name_personalisations = tuple(
|
|
211
|
+
[
|
|
212
|
+
JsonNamePersonalisationScheme.from_model(np)
|
|
213
|
+
for np in msg.get_name_personalisation_schemes()
|
|
214
|
+
]
|
|
215
|
+
)
|
|
216
|
+
user_operators = tuple(
|
|
217
|
+
[
|
|
218
|
+
JsonUserDefinedOperatorScheme.from_model(uo)
|
|
219
|
+
for uo in msg.get_user_defined_operator_schemes()
|
|
220
|
+
]
|
|
221
|
+
)
|
|
222
|
+
rulesets = tuple(
|
|
223
|
+
[
|
|
224
|
+
JsonRulesetScheme.from_model(rs)
|
|
225
|
+
for rs in msg.get_ruleset_schemes()
|
|
226
|
+
]
|
|
227
|
+
)
|
|
228
|
+
vtl_mappings = tuple(
|
|
229
|
+
[
|
|
230
|
+
JsonVtlMappingScheme.from_model(vm)
|
|
231
|
+
for vm in msg.get_vtl_mapping_schemes()
|
|
232
|
+
]
|
|
233
|
+
)
|
|
234
|
+
transformations = tuple(
|
|
235
|
+
[
|
|
236
|
+
JsonTransformationScheme.from_model(ts)
|
|
237
|
+
for ts in msg.get_transformation_schemes()
|
|
238
|
+
]
|
|
239
|
+
)
|
|
240
|
+
hierarchies = tuple(
|
|
241
|
+
[JsonHierarchy.from_model(h) for h in msg.get_hierarchies()]
|
|
242
|
+
)
|
|
243
|
+
return JsonStructures(
|
|
244
|
+
agencySchemes=agencies,
|
|
245
|
+
categorisations=categorisations,
|
|
246
|
+
categorySchemes=category_schemes,
|
|
247
|
+
codelists=codelists,
|
|
248
|
+
conceptSchemes=concept_schemes,
|
|
249
|
+
customTypeSchemes=custom_types,
|
|
250
|
+
dataflows=dataflows,
|
|
251
|
+
dataProviderSchemes=data_providers,
|
|
252
|
+
dataStructures=data_structures,
|
|
253
|
+
hierarchies=hierarchies,
|
|
254
|
+
hierarchyAssociations=hier_associations,
|
|
255
|
+
namePersonalisationSchemes=name_personalisations,
|
|
256
|
+
provisionAgreements=agreements,
|
|
257
|
+
representationMaps=representations_maps,
|
|
258
|
+
rulesetSchemes=rulesets,
|
|
259
|
+
structureMaps=structure_maps,
|
|
260
|
+
transformationSchemes=transformations,
|
|
261
|
+
userDefinedOperatorSchemes=user_operators,
|
|
262
|
+
valueLists=valuelists,
|
|
263
|
+
vtlMappingSchemes=vtl_mappings,
|
|
264
|
+
)
|
|
129
265
|
|
|
130
|
-
|
|
266
|
+
|
|
267
|
+
class JsonStructureMessage(Struct, frozen=True, omit_defaults=True):
|
|
131
268
|
"""A generic SDMX-JSON 2.0 Structure message."""
|
|
132
269
|
|
|
133
270
|
meta: JsonHeader
|
|
@@ -138,3 +275,14 @@ class JsonStructureMessage(Struct, frozen=True):
|
|
|
138
275
|
header = self.meta.to_model()
|
|
139
276
|
structures = self.data.to_model()
|
|
140
277
|
return StructureMessage(header, structures)
|
|
278
|
+
|
|
279
|
+
@classmethod
|
|
280
|
+
def from_model(cls, message: StructureMessage) -> "JsonStructureMessage":
|
|
281
|
+
"""Creates an SDMX-JSON payload from a pysdmx StructureMessage."""
|
|
282
|
+
if not message.header:
|
|
283
|
+
raise errors.Invalid(
|
|
284
|
+
"Invalid input", "SDMX-JSON messages must have a header."
|
|
285
|
+
)
|
|
286
|
+
header = JsonHeader.from_model(message.header)
|
|
287
|
+
structs = JsonStructures.from_model(message)
|
|
288
|
+
return JsonStructureMessage(header, structs)
|