pysdmx 1.10.0__py3-none-any.whl → 1.10.0rc1__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 +2 -3
- pysdmx/io/json/sdmxjson2/messages/__init__.py +0 -4
- pysdmx/io/json/sdmxjson2/messages/code.py +6 -16
- pysdmx/io/json/sdmxjson2/messages/constraint.py +16 -235
- pysdmx/io/json/sdmxjson2/messages/dsd.py +7 -35
- pysdmx/io/json/sdmxjson2/messages/map.py +4 -5
- pysdmx/io/json/sdmxjson2/messages/metadataflow.py +0 -1
- pysdmx/io/json/sdmxjson2/messages/msd.py +10 -18
- pysdmx/io/json/sdmxjson2/messages/schema.py +2 -2
- pysdmx/io/json/sdmxjson2/messages/structure.py +44 -81
- pysdmx/io/json/sdmxjson2/messages/vtl.py +9 -13
- pysdmx/io/json/sdmxjson2/reader/doc_validation.py +0 -4
- pysdmx/model/__base.py +1 -46
- pysdmx/model/__init__.py +0 -18
- pysdmx/model/category.py +0 -17
- pysdmx/model/message.py +71 -80
- {pysdmx-1.10.0.dist-info → pysdmx-1.10.0rc1.dist-info}/METADATA +1 -1
- {pysdmx-1.10.0.dist-info → pysdmx-1.10.0rc1.dist-info}/RECORD +21 -22
- pysdmx/model/constraint.py +0 -69
- {pysdmx-1.10.0.dist-info → pysdmx-1.10.0rc1.dist-info}/WHEEL +0 -0
- {pysdmx-1.10.0.dist-info → pysdmx-1.10.0rc1.dist-info}/licenses/LICENSE +0 -0
pysdmx/__init__.py
CHANGED
pysdmx/api/fmr/__init__.py
CHANGED
|
@@ -44,7 +44,6 @@ from pysdmx.model import (
|
|
|
44
44
|
Metadataflow,
|
|
45
45
|
MetadataProvisionAgreement,
|
|
46
46
|
MetadataReport,
|
|
47
|
-
MetadataStructure,
|
|
48
47
|
MultiRepresentationMap,
|
|
49
48
|
ProvisionAgreement,
|
|
50
49
|
RepresentationMap,
|
|
@@ -768,7 +767,7 @@ class RegistryClient(__BaseRegistryClient):
|
|
|
768
767
|
agency: str = "*",
|
|
769
768
|
id: str = "*",
|
|
770
769
|
version: str = "+",
|
|
771
|
-
) -> Sequence[
|
|
770
|
+
) -> Sequence[Dataflow]:
|
|
772
771
|
"""Get the metadata structures (MSD) matching the supplied parameters.
|
|
773
772
|
|
|
774
773
|
Args:
|
|
@@ -1342,7 +1341,7 @@ class AsyncRegistryClient(__BaseRegistryClient):
|
|
|
1342
1341
|
agency: str = "*",
|
|
1343
1342
|
id: str = "*",
|
|
1344
1343
|
version: str = "+",
|
|
1345
|
-
) -> Sequence[
|
|
1344
|
+
) -> Sequence[Dataflow]:
|
|
1346
1345
|
"""Get the metadata structures (MSD) matching the supplied parameters.
|
|
1347
1346
|
|
|
1348
1347
|
Args:
|
|
@@ -12,9 +12,6 @@ from pysdmx.io.json.sdmxjson2.messages.code import (
|
|
|
12
12
|
JsonHierarchyMessage,
|
|
13
13
|
)
|
|
14
14
|
from pysdmx.io.json.sdmxjson2.messages.concept import JsonConceptSchemeMessage
|
|
15
|
-
from pysdmx.io.json.sdmxjson2.messages.constraint import (
|
|
16
|
-
JsonDataConstraintMessage,
|
|
17
|
-
)
|
|
18
15
|
from pysdmx.io.json.sdmxjson2.messages.dataflow import (
|
|
19
16
|
JsonDataflowMessage,
|
|
20
17
|
JsonDataflowsMessage,
|
|
@@ -53,7 +50,6 @@ __all__ = [
|
|
|
53
50
|
"JsonCategorySchemeMessage",
|
|
54
51
|
"JsonCodelistMessage",
|
|
55
52
|
"JsonConceptSchemeMessage",
|
|
56
|
-
"JsonDataConstraintMessage",
|
|
57
53
|
"JsonDataflowMessage",
|
|
58
54
|
"JsonDataflowsMessage",
|
|
59
55
|
"JsonDataStructuresMessage",
|
|
@@ -231,7 +231,7 @@ class JsonCodelists(Struct, frozen=True, omit_defaults=True):
|
|
|
231
231
|
"""SDMX-JSON payload for lists of codes."""
|
|
232
232
|
|
|
233
233
|
codelists: Sequence[JsonCodelist] = ()
|
|
234
|
-
|
|
234
|
+
valuelists: Sequence[JsonValuelist] = ()
|
|
235
235
|
|
|
236
236
|
|
|
237
237
|
class JsonCodelistMessage(Struct, frozen=True, omit_defaults=True):
|
|
@@ -244,7 +244,7 @@ class JsonCodelistMessage(Struct, frozen=True, omit_defaults=True):
|
|
|
244
244
|
if self.data.codelists:
|
|
245
245
|
return self.data.codelists[0].to_model()
|
|
246
246
|
else:
|
|
247
|
-
return self.data.
|
|
247
|
+
return self.data.valuelists[0].to_model()
|
|
248
248
|
|
|
249
249
|
|
|
250
250
|
class JsonHierarchicalCode(Struct, frozen=True, omit_defaults=True):
|
|
@@ -329,10 +329,10 @@ class JsonHierarchicalCode(Struct, frozen=True, omit_defaults=True):
|
|
|
329
329
|
code=code.urn,
|
|
330
330
|
validFrom=code.rel_valid_from,
|
|
331
331
|
validTo=code.rel_valid_to,
|
|
332
|
-
annotations=tuple(annotations)
|
|
333
|
-
hierarchicalCodes=
|
|
334
|
-
|
|
335
|
-
|
|
332
|
+
annotations=tuple(annotations),
|
|
333
|
+
hierarchicalCodes=[
|
|
334
|
+
JsonHierarchicalCode.from_model(c) for c in code.codes
|
|
335
|
+
],
|
|
336
336
|
)
|
|
337
337
|
|
|
338
338
|
|
|
@@ -475,15 +475,6 @@ class JsonHierarchyAssociation(
|
|
|
475
475
|
"SDMX-JSON hierarchy associations must reference a context",
|
|
476
476
|
{"hierarchy_association": ha.id},
|
|
477
477
|
)
|
|
478
|
-
lnk = (
|
|
479
|
-
JsonLink(
|
|
480
|
-
rel="UserDefinedOperator",
|
|
481
|
-
type="sdmx_artefact",
|
|
482
|
-
urn=ha.operator,
|
|
483
|
-
)
|
|
484
|
-
if ha.operator
|
|
485
|
-
else None
|
|
486
|
-
)
|
|
487
478
|
return JsonHierarchyAssociation(
|
|
488
479
|
agency=(
|
|
489
480
|
ha.agency.id if isinstance(ha.agency, Agency) else ha.agency
|
|
@@ -501,7 +492,6 @@ class JsonHierarchyAssociation(
|
|
|
501
492
|
linkedHierarchy=href,
|
|
502
493
|
linkedObject=ha.component_ref,
|
|
503
494
|
contextObject=ha.context_ref,
|
|
504
|
-
links=[lnk] if lnk else (),
|
|
505
495
|
)
|
|
506
496
|
|
|
507
497
|
|
|
@@ -1,43 +1,16 @@
|
|
|
1
1
|
"""Collection of SDMX-JSON schemas for content constraints."""
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from typing import Optional, Sequence
|
|
3
|
+
from typing import Dict, Literal, Optional, Sequence
|
|
5
4
|
|
|
6
5
|
from msgspec import Struct
|
|
7
6
|
|
|
8
|
-
from pysdmx import
|
|
9
|
-
from pysdmx.io.json.sdmxjson2.messages.core import (
|
|
10
|
-
JsonAnnotation,
|
|
11
|
-
MaintainableType,
|
|
12
|
-
)
|
|
13
|
-
from pysdmx.model import (
|
|
14
|
-
Agency,
|
|
15
|
-
ConstraintAttachment,
|
|
16
|
-
CubeKeyValue,
|
|
17
|
-
CubeRegion,
|
|
18
|
-
CubeValue,
|
|
19
|
-
DataConstraint,
|
|
20
|
-
DataKey,
|
|
21
|
-
DataKeyValue,
|
|
22
|
-
KeySet,
|
|
23
|
-
)
|
|
7
|
+
from pysdmx.io.json.sdmxjson2.messages.core import MaintainableType
|
|
24
8
|
|
|
25
9
|
|
|
26
10
|
class JsonValue(Struct, frozen=True, omit_defaults=True):
|
|
27
|
-
"""SDMX-JSON payload for
|
|
11
|
+
"""SDMX-JSON payload for an allowed value."""
|
|
28
12
|
|
|
29
13
|
value: str
|
|
30
|
-
validFrom: Optional[datetime] = None
|
|
31
|
-
validTo: Optional[datetime] = None
|
|
32
|
-
|
|
33
|
-
def to_model(self) -> CubeValue:
|
|
34
|
-
"""Converts a JsonValue to a CubeValue."""
|
|
35
|
-
return CubeValue(self.value, self.validFrom, self.validTo)
|
|
36
|
-
|
|
37
|
-
@classmethod
|
|
38
|
-
def from_model(self, cv: CubeValue) -> "JsonValue":
|
|
39
|
-
"""Converts a pysdmx cube value to an SDMX-JSON one."""
|
|
40
|
-
return JsonValue(cv.value, cv.valid_from, cv.valid_to)
|
|
41
14
|
|
|
42
15
|
|
|
43
16
|
class JsonKeyValue(Struct, frozen=True, omit_defaults=True):
|
|
@@ -45,228 +18,36 @@ class JsonKeyValue(Struct, frozen=True, omit_defaults=True):
|
|
|
45
18
|
|
|
46
19
|
id: str
|
|
47
20
|
values: Sequence[JsonValue]
|
|
48
|
-
# Additional properties are supported in the model (include,
|
|
49
|
-
# removePrefix, validFrom, validTo, timeRange) but not by the FMR.
|
|
50
|
-
# Therefore, they are ignored for now.
|
|
51
|
-
|
|
52
|
-
def to_model(self) -> CubeKeyValue:
|
|
53
|
-
"""Converts a JsonKeyValue to a CubeKeyValue."""
|
|
54
|
-
return CubeKeyValue(self.id, [v.to_model() for v in self.values])
|
|
55
21
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return JsonKeyValue(
|
|
60
|
-
key_value.id, [JsonValue.from_model(v) for v in key_value.values]
|
|
61
|
-
)
|
|
22
|
+
def to_model(self) -> Sequence[str]:
|
|
23
|
+
"""Returns the requested list of values."""
|
|
24
|
+
return [v.value for v in self.values]
|
|
62
25
|
|
|
63
26
|
|
|
64
27
|
class JsonCubeRegion(Struct, frozen=True, omit_defaults=True):
|
|
65
28
|
"""SDMX-JSON payload for a cube region."""
|
|
66
29
|
|
|
67
|
-
# The property `components` is ignored as it's not used in the FMR`
|
|
68
30
|
keyValues: Sequence[JsonKeyValue]
|
|
69
|
-
include: bool = True
|
|
70
31
|
|
|
71
|
-
def
|
|
72
|
-
"""
|
|
73
|
-
return
|
|
74
|
-
[kv.to_model() for kv in self.keyValues], self.include
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
@classmethod
|
|
78
|
-
def from_model(self, region: CubeRegion) -> "JsonCubeRegion":
|
|
79
|
-
"""Converts a pysdmx cube region to an SDMX-JSON one."""
|
|
80
|
-
return JsonCubeRegion(
|
|
81
|
-
[JsonKeyValue.from_model(kv) for kv in region.key_values],
|
|
82
|
-
region.is_included,
|
|
83
|
-
)
|
|
32
|
+
def to_map(self) -> Dict[str, Sequence[str]]:
|
|
33
|
+
"""Gets the list of allowed values for a component."""
|
|
34
|
+
return {kv.id: kv.to_model() for kv in self.keyValues}
|
|
84
35
|
|
|
85
36
|
|
|
86
37
|
class JsonConstraintAttachment(Struct, frozen=True, omit_defaults=True):
|
|
87
38
|
"""SDMX-JSON payload for a constraint attachment."""
|
|
88
39
|
|
|
89
|
-
dataProvider: Optional[str]
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
"""Converts a JsonConstraintAttachment to a ConstraintAttachment."""
|
|
96
|
-
return ConstraintAttachment(
|
|
97
|
-
self.dataProvider,
|
|
98
|
-
self.dataStructures,
|
|
99
|
-
self.dataflows,
|
|
100
|
-
self.provisionAgreements,
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
@classmethod
|
|
104
|
-
def from_model(
|
|
105
|
-
self, attachment: ConstraintAttachment
|
|
106
|
-
) -> "JsonConstraintAttachment":
|
|
107
|
-
"""Converts a pysdmx constraint attachment to an SDMX-JSON one."""
|
|
108
|
-
ds = attachment.data_structures if attachment.data_structures else ()
|
|
109
|
-
df = attachment.dataflows if attachment.dataflows else ()
|
|
110
|
-
pa = (
|
|
111
|
-
attachment.provision_agreements
|
|
112
|
-
if attachment.provision_agreements
|
|
113
|
-
else ()
|
|
114
|
-
)
|
|
115
|
-
return JsonConstraintAttachment(attachment.data_provider, ds, df, pa)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
class JsonDataKeyValue(Struct, frozen=True, omit_defaults=True):
|
|
119
|
-
"""SDMX-JSON payload for a data key value."""
|
|
120
|
-
|
|
121
|
-
id: str
|
|
122
|
-
value: str
|
|
123
|
-
|
|
124
|
-
def to_model(self) -> DataKeyValue:
|
|
125
|
-
"""Converts a JsonDataKeyValue to a DataKeyValue."""
|
|
126
|
-
return DataKeyValue(self.id, self.value)
|
|
127
|
-
|
|
128
|
-
@classmethod
|
|
129
|
-
def from_model(self, kv: DataKeyValue) -> "JsonDataKeyValue":
|
|
130
|
-
"""Converts a pysdmx key value to an SDMX-JSON one."""
|
|
131
|
-
return JsonDataKeyValue(kv.id, kv.value)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
class JsonDataKey(Struct, frozen=True, omit_defaults=True):
|
|
135
|
-
"""SDMX-JSON payload for a data key."""
|
|
136
|
-
|
|
137
|
-
keyValues: Sequence[JsonDataKeyValue]
|
|
138
|
-
validFrom: Optional[datetime] = None
|
|
139
|
-
validTo: Optional[datetime] = None
|
|
140
|
-
|
|
141
|
-
def to_model(self) -> DataKey:
|
|
142
|
-
"""Converts a JsonDataKey to a DataKey."""
|
|
143
|
-
return DataKey(
|
|
144
|
-
[kv.to_model() for kv in self.keyValues],
|
|
145
|
-
self.validFrom,
|
|
146
|
-
self.validTo,
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
@classmethod
|
|
150
|
-
def from_model(self, kv: DataKey) -> "JsonDataKey":
|
|
151
|
-
"""Converts a pysdmx key constraint to an SDMX-JSON one."""
|
|
152
|
-
return JsonDataKey(
|
|
153
|
-
[JsonDataKeyValue.from_model(val) for val in kv.keys_values],
|
|
154
|
-
kv.valid_from,
|
|
155
|
-
kv.valid_to,
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
class JsonKeySet(Struct, frozen=True, omit_defaults=True):
|
|
160
|
-
"""SDMX-JSON payload for a keyset."""
|
|
161
|
-
|
|
162
|
-
keys: Sequence[JsonDataKey]
|
|
163
|
-
isIncluded: bool
|
|
164
|
-
|
|
165
|
-
def to_model(self) -> KeySet:
|
|
166
|
-
"""Converts a JsonKeySet to a KeySet."""
|
|
167
|
-
return KeySet([k.to_model() for k in self.keys], self.isIncluded)
|
|
168
|
-
|
|
169
|
-
@classmethod
|
|
170
|
-
def from_model(self, ks: KeySet) -> "JsonKeySet":
|
|
171
|
-
"""Converts a pysdmx key set constraint to an SDMX-JSON one."""
|
|
172
|
-
return JsonKeySet(
|
|
173
|
-
[JsonDataKey.from_model(k) for k in ks.keys], ks.is_included
|
|
174
|
-
)
|
|
40
|
+
dataProvider: Optional[str]
|
|
41
|
+
simpleDataSources: Optional[Sequence[str]] = None
|
|
42
|
+
dataStructures: Optional[Sequence[str]] = None
|
|
43
|
+
dataflows: Optional[Sequence[str]] = None
|
|
44
|
+
provisionAgreements: Optional[Sequence[str]] = None
|
|
45
|
+
queryableDataSources: Optional[Sequence[str]] = None
|
|
175
46
|
|
|
176
47
|
|
|
177
48
|
class JsonDataConstraint(MaintainableType, frozen=True, omit_defaults=True):
|
|
178
49
|
"""SDMX-JSON payload for a content constraint."""
|
|
179
50
|
|
|
51
|
+
role: Optional[Literal["Allowed", "Actual"]] = None
|
|
180
52
|
constraintAttachment: Optional[JsonConstraintAttachment] = None
|
|
181
53
|
cubeRegions: Optional[Sequence[JsonCubeRegion]] = None
|
|
182
|
-
dataKeySets: Optional[Sequence[JsonKeySet]] = None
|
|
183
|
-
|
|
184
|
-
def to_model(self) -> DataConstraint:
|
|
185
|
-
"""Converts a JsonDataConstraint to a pysdmx Data Constraint."""
|
|
186
|
-
at = self.constraintAttachment.to_model() # type: ignore[union-attr]
|
|
187
|
-
return DataConstraint(
|
|
188
|
-
id=self.id,
|
|
189
|
-
name=self.name,
|
|
190
|
-
agency=self.agency,
|
|
191
|
-
description=self.description,
|
|
192
|
-
version=self.version,
|
|
193
|
-
annotations=tuple([a.to_model() for a in self.annotations]),
|
|
194
|
-
is_external_reference=self.isExternalReference,
|
|
195
|
-
valid_from=self.validFrom,
|
|
196
|
-
valid_to=self.validTo,
|
|
197
|
-
constraint_attachment=at,
|
|
198
|
-
cube_regions=[r.to_model() for r in self.cubeRegions]
|
|
199
|
-
if self.cubeRegions
|
|
200
|
-
else (),
|
|
201
|
-
key_sets=[s.to_model() for s in self.dataKeySets]
|
|
202
|
-
if self.dataKeySets
|
|
203
|
-
else (),
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
@classmethod
|
|
207
|
-
def from_model(self, cons: DataConstraint) -> "JsonDataConstraint":
|
|
208
|
-
"""Converts a pysdmx constraint to an SDMX-JSON one."""
|
|
209
|
-
crs = (
|
|
210
|
-
[JsonCubeRegion.from_model(r) for r in cons.cube_regions]
|
|
211
|
-
if cons.cube_regions
|
|
212
|
-
else None
|
|
213
|
-
)
|
|
214
|
-
dks = (
|
|
215
|
-
[JsonKeySet.from_model(s) for s in cons.key_sets]
|
|
216
|
-
if cons.key_sets
|
|
217
|
-
else None
|
|
218
|
-
)
|
|
219
|
-
if not cons.name:
|
|
220
|
-
raise errors.Invalid(
|
|
221
|
-
"Invalid input",
|
|
222
|
-
"SDMX-JSON data constraints must have a name",
|
|
223
|
-
{"data_constraint": cons.id},
|
|
224
|
-
)
|
|
225
|
-
if not cons.constraint_attachment:
|
|
226
|
-
raise errors.Invalid(
|
|
227
|
-
"Invalid input",
|
|
228
|
-
"SDMX-JSON data constraints must have a constraint attachment",
|
|
229
|
-
{"data_constraint": cons.id},
|
|
230
|
-
)
|
|
231
|
-
return JsonDataConstraint(
|
|
232
|
-
id=cons.id,
|
|
233
|
-
name=cons.name,
|
|
234
|
-
agency=(
|
|
235
|
-
cons.agency.id
|
|
236
|
-
if isinstance(cons.agency, Agency)
|
|
237
|
-
else cons.agency
|
|
238
|
-
),
|
|
239
|
-
description=cons.description,
|
|
240
|
-
version=cons.version,
|
|
241
|
-
annotations=tuple(
|
|
242
|
-
[JsonAnnotation.from_model(a) for a in cons.annotations]
|
|
243
|
-
),
|
|
244
|
-
isExternalReference=cons.is_external_reference,
|
|
245
|
-
validFrom=cons.valid_from,
|
|
246
|
-
validTo=cons.valid_to,
|
|
247
|
-
constraintAttachment=JsonConstraintAttachment.from_model(
|
|
248
|
-
cons.constraint_attachment
|
|
249
|
-
),
|
|
250
|
-
cubeRegions=crs,
|
|
251
|
-
dataKeySets=dks,
|
|
252
|
-
)
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
class JsonDataConstraints(Struct, frozen=True, omit_defaults=True):
|
|
256
|
-
"""SDMX-JSON payload for data constraints."""
|
|
257
|
-
|
|
258
|
-
dataConstraints: Sequence[JsonDataConstraint] = ()
|
|
259
|
-
|
|
260
|
-
def to_model(self) -> Sequence[DataConstraint]:
|
|
261
|
-
"""Returns the requested data constraints."""
|
|
262
|
-
return [cc.to_model() for cc in self.dataConstraints]
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
class JsonDataConstraintMessage(Struct, frozen=True, omit_defaults=True):
|
|
266
|
-
"""SDMX-JSON payload for /dataconstraint queries."""
|
|
267
|
-
|
|
268
|
-
data: JsonDataConstraints
|
|
269
|
-
|
|
270
|
-
def to_model(self) -> Sequence[DataConstraint]:
|
|
271
|
-
"""Returns the requested data constraints."""
|
|
272
|
-
return self.data.to_model()
|
|
@@ -265,17 +265,12 @@ class JsonAttribute(Struct, frozen=True, omit_defaults=True):
|
|
|
265
265
|
attribute.attachment_level # type: ignore[arg-type]
|
|
266
266
|
)
|
|
267
267
|
repr = _get_json_representation(attribute)
|
|
268
|
-
# The line below will need to be changed when we work on
|
|
269
|
-
# Measure Relationship (cf. issue #467)
|
|
270
|
-
mr = ["OBS_VALUE"] if attribute.attachment_level == "O" else None
|
|
271
|
-
|
|
272
268
|
return JsonAttribute(
|
|
273
269
|
id=attribute.id,
|
|
274
270
|
conceptIdentity=concept,
|
|
275
271
|
attributeRelationship=level,
|
|
276
272
|
usage=usage,
|
|
277
273
|
localRepresentation=repr,
|
|
278
|
-
measureRelationship=mr,
|
|
279
274
|
)
|
|
280
275
|
|
|
281
276
|
|
|
@@ -452,42 +447,19 @@ class JsonComponents(Struct, frozen=True, omit_defaults=True):
|
|
|
452
447
|
enums = [cl.to_model() for cl in cls]
|
|
453
448
|
enums.extend([vl.to_model() for vl in vls])
|
|
454
449
|
comps = []
|
|
455
|
-
if constraints:
|
|
456
|
-
|
|
457
|
-
for const in constraints:
|
|
458
|
-
incl_cubes.extend(
|
|
459
|
-
[cr for cr in (const.cubeRegions or []) if cr.include]
|
|
460
|
-
)
|
|
461
|
-
if len(incl_cubes) == 1:
|
|
462
|
-
cons = {
|
|
463
|
-
kv.id: [v.value for v in kv.values]
|
|
464
|
-
for kv in incl_cubes[0].keyValues
|
|
465
|
-
}
|
|
466
|
-
else:
|
|
467
|
-
cons = {}
|
|
450
|
+
if constraints and constraints[0].cubeRegions:
|
|
451
|
+
cons = constraints[0].cubeRegions[0].to_map()
|
|
468
452
|
else:
|
|
469
453
|
cons = {}
|
|
470
|
-
comps.extend(
|
|
471
|
-
self.dimensionList.to_model(
|
|
472
|
-
cs,
|
|
473
|
-
enums,
|
|
474
|
-
cons, # type: ignore[arg-type]
|
|
475
|
-
)
|
|
476
|
-
)
|
|
454
|
+
comps.extend(self.dimensionList.to_model(cs, enums, cons))
|
|
477
455
|
if self.measureList:
|
|
478
|
-
comps.extend(
|
|
479
|
-
self.measureList.to_model(
|
|
480
|
-
cs,
|
|
481
|
-
enums,
|
|
482
|
-
cons, # type: ignore[arg-type]
|
|
483
|
-
)
|
|
484
|
-
)
|
|
456
|
+
comps.extend(self.measureList.to_model(cs, enums, cons))
|
|
485
457
|
if self.attributeList:
|
|
486
458
|
comps.extend(
|
|
487
459
|
self.attributeList.to_model(
|
|
488
460
|
cs,
|
|
489
461
|
enums,
|
|
490
|
-
cons,
|
|
462
|
+
cons,
|
|
491
463
|
self.groups,
|
|
492
464
|
)
|
|
493
465
|
)
|
|
@@ -584,7 +556,7 @@ class JsonDataStructures(Struct, frozen=True, omit_defaults=True):
|
|
|
584
556
|
conceptSchemes: Sequence[JsonConceptScheme] = ()
|
|
585
557
|
valuelists: Sequence[JsonValuelist] = ()
|
|
586
558
|
codelists: Sequence[JsonCodelist] = ()
|
|
587
|
-
|
|
559
|
+
contentConstraints: Sequence[JsonDataConstraint] = ()
|
|
588
560
|
|
|
589
561
|
def to_model(self) -> Sequence[DataStructureDefinition]:
|
|
590
562
|
"""Returns the requested dsds."""
|
|
@@ -593,7 +565,7 @@ class JsonDataStructures(Struct, frozen=True, omit_defaults=True):
|
|
|
593
565
|
self.conceptSchemes,
|
|
594
566
|
self.codelists,
|
|
595
567
|
self.valuelists,
|
|
596
|
-
self.
|
|
568
|
+
self.contentConstraints,
|
|
597
569
|
)
|
|
598
570
|
for dsd in self.dataStructures
|
|
599
571
|
]
|
|
@@ -87,20 +87,19 @@ class JsonRepresentationMapping(Struct, frozen=True, omit_defaults=True):
|
|
|
87
87
|
self, vm: Union[MultiValueMap, ValueMap]
|
|
88
88
|
) -> "JsonRepresentationMapping":
|
|
89
89
|
"""Converts a value map to an SDMX-JSON JsonRepresentationMapping."""
|
|
90
|
-
fmt = r"%Y-%m-%dT%H:%M:%S"
|
|
91
90
|
if isinstance(vm, ValueMap):
|
|
92
91
|
return JsonRepresentationMapping(
|
|
93
92
|
[JsonSourceValue.from_model(vm.source)],
|
|
94
93
|
[vm.target],
|
|
95
|
-
vm.valid_from.strftime(
|
|
96
|
-
vm.valid_to.strftime(
|
|
94
|
+
vm.valid_from.strftime("%Y-%m-%d") if vm.valid_from else None,
|
|
95
|
+
vm.valid_to.strftime("%Y-%m-%d") if vm.valid_to else None,
|
|
97
96
|
)
|
|
98
97
|
else:
|
|
99
98
|
return JsonRepresentationMapping(
|
|
100
99
|
[JsonSourceValue.from_model(s) for s in vm.source],
|
|
101
100
|
vm.target,
|
|
102
|
-
vm.valid_from.strftime(
|
|
103
|
-
vm.valid_to.strftime(
|
|
101
|
+
vm.valid_from.strftime("%Y-%m-%d") if vm.valid_from else None,
|
|
102
|
+
vm.valid_to.strftime("%Y-%m-%d") if vm.valid_to else None,
|
|
104
103
|
)
|
|
105
104
|
|
|
106
105
|
|
|
@@ -15,6 +15,7 @@ from pysdmx.io.json.sdmxjson2.messages.core import (
|
|
|
15
15
|
from pysdmx.io.json.sdmxjson2.messages.dsd import (
|
|
16
16
|
_find_concept,
|
|
17
17
|
_get_concept_reference,
|
|
18
|
+
_get_json_representation,
|
|
18
19
|
_get_representation,
|
|
19
20
|
)
|
|
20
21
|
from pysdmx.model import (
|
|
@@ -27,13 +28,6 @@ from pysdmx.model import (
|
|
|
27
28
|
from pysdmx.util import parse_item_urn
|
|
28
29
|
|
|
29
30
|
|
|
30
|
-
def _get_attr_repr(comp: MetadataComponent) -> Optional[JsonRepresentation]:
|
|
31
|
-
enum = comp.local_enum_ref if comp.local_enum_ref else None
|
|
32
|
-
return JsonRepresentation.from_model(
|
|
33
|
-
comp.local_dtype, enum, comp.local_facets, None
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
|
|
37
31
|
class JsonMetadataAttribute(Struct, frozen=True, omit_defaults=True):
|
|
38
32
|
"""SDMX-JSON payload for an attribute."""
|
|
39
33
|
|
|
@@ -86,13 +80,11 @@ class JsonMetadataAttribute(Struct, frozen=True, omit_defaults=True):
|
|
|
86
80
|
def from_model(self, cmp: MetadataComponent) -> "JsonMetadataAttribute":
|
|
87
81
|
"""Converts a pysdmx metadata attribute to an SDMX-JSON one."""
|
|
88
82
|
concept = _get_concept_reference(cmp)
|
|
89
|
-
repr =
|
|
83
|
+
repr = _get_json_representation(cmp)
|
|
90
84
|
|
|
91
85
|
min_occurs = cmp.array_def.min_size if cmp.array_def else 0
|
|
92
|
-
if cmp.array_def is None:
|
|
93
|
-
max_occurs: Union[int, Literal["unbounded"]] =
|
|
94
|
-
elif cmp.array_def.max_size is None:
|
|
95
|
-
max_occurs = "unbounded"
|
|
86
|
+
if cmp.array_def is None or cmp.array_def.max_size is None:
|
|
87
|
+
max_occurs: Union[int, Literal["unbounded"]] = "unbounded"
|
|
96
88
|
else:
|
|
97
89
|
max_occurs = cmp.array_def.max_size
|
|
98
90
|
|
|
@@ -103,9 +95,9 @@ class JsonMetadataAttribute(Struct, frozen=True, omit_defaults=True):
|
|
|
103
95
|
minOccurs=min_occurs,
|
|
104
96
|
maxOccurs=max_occurs,
|
|
105
97
|
isPresentational=cmp.is_presentational,
|
|
106
|
-
metadataAttributes=
|
|
107
|
-
|
|
108
|
-
|
|
98
|
+
metadataAttributes=[
|
|
99
|
+
JsonMetadataAttribute.from_model(c) for c in cmp.components
|
|
100
|
+
],
|
|
109
101
|
)
|
|
110
102
|
|
|
111
103
|
|
|
@@ -127,9 +119,9 @@ class JsonMetadataAttributes(Struct, frozen=True, omit_defaults=True):
|
|
|
127
119
|
) -> "JsonMetadataAttributes":
|
|
128
120
|
"""Converts a pysdmx list of metadata attributes to SDMX-JSON."""
|
|
129
121
|
return JsonMetadataAttributes(
|
|
130
|
-
metadataAttributes=
|
|
131
|
-
|
|
132
|
-
|
|
122
|
+
metadataAttributes=[
|
|
123
|
+
JsonMetadataAttribute.from_model(a) for a in attributes
|
|
124
|
+
]
|
|
133
125
|
)
|
|
134
126
|
|
|
135
127
|
|
|
@@ -21,7 +21,7 @@ class JsonSchemas(msgspec.Struct, frozen=True, omit_defaults=True):
|
|
|
21
21
|
dataStructures: Sequence[JsonDataStructure]
|
|
22
22
|
valuelists: Sequence[JsonValuelist] = ()
|
|
23
23
|
codelists: Sequence[JsonCodelist] = ()
|
|
24
|
-
|
|
24
|
+
contentConstraints: Sequence[JsonDataConstraint] = ()
|
|
25
25
|
|
|
26
26
|
def to_model(
|
|
27
27
|
self,
|
|
@@ -32,7 +32,7 @@ class JsonSchemas(msgspec.Struct, frozen=True, omit_defaults=True):
|
|
|
32
32
|
self.conceptSchemes,
|
|
33
33
|
self.codelists,
|
|
34
34
|
self.valuelists,
|
|
35
|
-
self.
|
|
35
|
+
self.contentConstraints,
|
|
36
36
|
)
|
|
37
37
|
return comps, grps # type: ignore[return-value]
|
|
38
38
|
|