pysdmx 1.6.0__py3-none-any.whl → 1.7.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 CHANGED
@@ -1,3 +1,3 @@
1
1
  """Your opinionated Python SDMX library."""
2
2
 
3
- __version__ = "1.6.0"
3
+ __version__ = "1.7.0"
@@ -3,11 +3,11 @@
3
3
  import csv
4
4
  import os.path
5
5
  from io import BytesIO, StringIO, TextIOWrapper
6
- from json import JSONDecodeError, loads
7
6
  from os import PathLike
8
7
  from pathlib import Path
9
8
  from typing import Optional, Tuple, Union
10
9
 
10
+ import msgspec
11
11
  from httpx import Client as httpx_Client
12
12
  from httpx import HTTPStatusError, create_ssl_context
13
13
 
@@ -29,7 +29,7 @@ def __check_xml(input_str: str) -> bool:
29
29
 
30
30
  def __check_csv(input_str: str) -> bool:
31
31
  try:
32
- max_length = len(input_str) if len(input_str) < 2048 else 2048
32
+ max_length = min(2048, len(input_str))
33
33
  dialect = csv.Sniffer().sniff(input_str[:max_length])
34
34
  control_csv_format = (
35
35
  dialect.delimiter == "," and dialect.quotechar == '"'
@@ -47,9 +47,9 @@ def __check_csv(input_str: str) -> bool:
47
47
 
48
48
  def __check_json(input_str: str) -> bool:
49
49
  try:
50
- loads(input_str)
50
+ msgspec.json.decode(input_str)
51
51
  return True
52
- except JSONDecodeError:
52
+ except msgspec.DecodeError:
53
53
  return False
54
54
 
55
55
 
@@ -17,6 +17,7 @@ class FusionConcept(msgspec.Struct, frozen=True):
17
17
  """Fusion-JSON payload for concepts."""
18
18
 
19
19
  id: str
20
+ urn: str
20
21
  names: Sequence[FusionString]
21
22
  representation: Optional[FusionRepresentation] = None
22
23
  descriptions: Optional[Sequence[FusionString]] = None
@@ -48,6 +49,7 @@ class FusionConcept(msgspec.Struct, frozen=True):
48
49
  description=d,
49
50
  codes=c,
50
51
  enum_ref=cl_ref,
52
+ urn=self.urn,
51
53
  )
52
54
 
53
55
 
@@ -63,18 +65,10 @@ class FusionConceptScheme(
63
65
  version: str = "1.0"
64
66
  items: Sequence[FusionConcept] = ()
65
67
 
66
- def __set_urn(self, concept: Concept) -> Concept:
67
- urn = (
68
- "urn:sdmx:org.sdmx.infomodel.conceptscheme.Concept="
69
- f"{self.agency}:{self.id}({self.version}).{concept.id}"
70
- )
71
- return msgspec.structs.replace(concept, urn=urn)
72
-
73
68
  def to_model(self, codelists: Sequence[FusionCodelist]) -> CS:
74
69
  """Converts a FusionConceptScheme to a standard concept scheme."""
75
70
  d = self.descriptions[0].value if self.descriptions else None
76
71
  concepts = [c.to_model(codelists) for c in self.items]
77
- concepts = [self.__set_urn(c) for c in concepts]
78
72
  return CS(
79
73
  id=self.id,
80
74
  name=self.names[0].value,
@@ -34,7 +34,7 @@ class JsonCode(NameableType, frozen=True, omit_defaults=True):
34
34
  parent: Optional[str] = None
35
35
 
36
36
  def __handle_date(self, datestr: str) -> datetime:
37
- return datetime.strptime(datestr, _VAL_FMT)
37
+ return datetime.strptime(datestr, _VAL_FMT) # noqa
38
38
 
39
39
  def __get_val(
40
40
  self, a: JsonAnnotation
@@ -49,26 +49,38 @@ class JsonCode(NameableType, frozen=True, omit_defaults=True):
49
49
 
50
50
  def to_model(self) -> Code:
51
51
  """Converts a JsonCode to a standard code."""
52
+ # Pre-filter annotations once outside the tuple creation
53
+ vf, vt = None, None
54
+
52
55
  if self.annotations:
53
- vp = [
54
- a for a in self.annotations if a.type == "FR_VALIDITY_PERIOD"
56
+ # Get validity period info
57
+ vp = next(
58
+ (
59
+ a
60
+ for a in self.annotations
61
+ if a.type == "FR_VALIDITY_PERIOD"
62
+ ),
63
+ None,
64
+ )
65
+ if vp:
66
+ vf, vt = self.__get_val(vp)
67
+
68
+ # Pre-filter non-validity period annotations
69
+ filtered_annotations = [
70
+ a.to_model()
71
+ for a in self.annotations
72
+ if a.type != "FR_VALIDITY_PERIOD"
55
73
  ]
56
74
  else:
57
- vp = None
58
- vf, vt = self.__get_val(vp[0]) if vp else (None, None)
75
+ filtered_annotations = []
76
+
59
77
  return Code(
60
78
  id=self.id,
61
79
  name=self.name,
62
80
  description=self.description,
63
81
  valid_from=vf,
64
82
  valid_to=vt,
65
- annotations=tuple(
66
- [
67
- a.to_model()
68
- for a in self.annotations
69
- if a.type != "FR_VALIDITY_PERIOD"
70
- ]
71
- ),
83
+ annotations=tuple(filtered_annotations),
72
84
  )
73
85
 
74
86
  @classmethod
@@ -113,13 +125,23 @@ class JsonCodelist(ItemSchemeType, frozen=True, omit_defaults=True):
113
125
 
114
126
  def to_model(self) -> Codelist:
115
127
  """Converts a JsonCodelist to a standard codelist."""
128
+ # Process codes in batches to reduce memory pressure
129
+ batch_size = 10000
130
+ all_codes = []
131
+
132
+ # Process in batches
133
+ for i in range(0, len(self.codes), batch_size):
134
+ batch = self.codes[i : i + batch_size]
135
+ batch_models = [code.to_model() for code in batch]
136
+ all_codes.extend(batch_models)
137
+
116
138
  return Codelist(
117
139
  id=self.id,
118
140
  name=self.name,
119
141
  agency=self.agency,
120
142
  description=self.description,
121
143
  version=self.version,
122
- items=tuple([i.to_model() for i in self.codes]),
144
+ items=tuple(all_codes),
123
145
  annotations=tuple([a.to_model() for a in self.annotations]),
124
146
  is_external_reference=self.isExternalReference,
125
147
  is_partial=self.isPartial,
@@ -9,6 +9,7 @@ from pysdmx.io.json.sdmxjson2.messages.code import JsonCodelist
9
9
  from pysdmx.io.json.sdmxjson2.messages.core import (
10
10
  ItemSchemeType,
11
11
  JsonAnnotation,
12
+ JsonLink,
12
13
  JsonRepresentation,
13
14
  NameableType,
14
15
  )
@@ -29,6 +30,7 @@ class JsonConcept(NameableType, frozen=True, omit_defaults=True):
29
30
  coreRepresentation: Optional[JsonRepresentation] = None
30
31
  parent: Optional[str] = None
31
32
  isoConceptReference: Optional[IsoConceptReference] = None
33
+ links: Sequence[JsonLink] = ()
32
34
 
33
35
  def to_model(self, codelists: Sequence[Codelist]) -> Concept:
34
36
  """Converts a JsonConcept to a standard concept."""
@@ -48,6 +50,8 @@ class JsonConcept(NameableType, frozen=True, omit_defaults=True):
48
50
  facets = None
49
51
  codes = None
50
52
  cl_ref = None
53
+ urn_lnk = [lnk for lnk in self.links if lnk.rel == "self"]
54
+ c_urn = urn_lnk[0].urn if len(urn_lnk) > 0 else None
51
55
  return Concept(
52
56
  id=self.id,
53
57
  dtype=dt,
@@ -56,6 +60,7 @@ class JsonConcept(NameableType, frozen=True, omit_defaults=True):
56
60
  description=self.description,
57
61
  codes=codes,
58
62
  enum_ref=cl_ref,
63
+ urn=c_urn,
59
64
  )
60
65
 
61
66
  @classmethod
@@ -95,18 +100,10 @@ class JsonConceptScheme(ItemSchemeType, frozen=True, omit_defaults=True):
95
100
 
96
101
  concepts: Sequence[JsonConcept] = ()
97
102
 
98
- def __set_urn(self, concept: Concept) -> Concept:
99
- urn = (
100
- "urn:sdmx:org.sdmx.infomodel.conceptscheme.Concept="
101
- f"{self.agency}:{self.id}({self.version}).{concept.id}"
102
- )
103
- return msgspec.structs.replace(concept, urn=urn)
104
-
105
103
  def to_model(self, codelists: Sequence[JsonCodelist]) -> ConceptScheme:
106
104
  """Converts a JsonConceptScheme to a standard concept scheme."""
107
105
  cls = [cl.to_model() for cl in codelists]
108
106
  concepts = [c.to_model(cls) for c in self.concepts]
109
- concepts = [self.__set_urn(c) for c in concepts]
110
107
  return ConceptScheme(
111
108
  id=self.id,
112
109
  name=self.name,
@@ -30,8 +30,7 @@ def _reading_str_series(dataset: Dict[str, Any]) -> pd.DataFrame:
30
30
  if OBS in data:
31
31
  del keys[OBS]
32
32
  data[OBS] = add_list(data[OBS])
33
- for j in data[OBS]:
34
- test_list.append({**keys, **j})
33
+ test_list.extend([{**keys, **j} for j in data[OBS]])
35
34
  else:
36
35
  test_list.append(keys)
37
36
  test_list, df = __process_df(test_list, df)
@@ -397,7 +397,7 @@ class StructureParser(Struct):
397
397
  """
398
398
  if json_fac is None:
399
399
  return
400
- for key, _value in json_fac.items():
400
+ for key in json_fac:
401
401
  if key == TEXT_TYPE and json_fac[TEXT_TYPE] in list(DataType):
402
402
  json_obj["dtype"] = DataType(json_fac[TEXT_TYPE])
403
403
 
@@ -907,9 +907,9 @@ class StructureParser(Struct):
907
907
  item_json_info = self.__format_name_description(item_json_info)
908
908
  if CONTACT in item_json_info and item_name_class == AGENCY:
909
909
  item_json_info[CONTACT] = add_list(item_json_info[CONTACT])
910
- contacts = []
911
- for e in item_json_info[CONTACT]:
912
- contacts.append(self.__format_contact(e))
910
+ contacts = [
911
+ self.__format_contact(e) for e in item_json_info[CONTACT]
912
+ ]
913
913
  item_json_info[CONTACT.lower() + "s"] = contacts
914
914
  del item_json_info[CONTACT]
915
915
 
@@ -949,9 +949,11 @@ class StructureParser(Struct):
949
949
  group_dimensions = [group_dimensions]
950
950
 
951
951
  group["dimensions"] = [
952
- d[DIM_REF]
953
- if isinstance(d[DIM_REF], str)
954
- else d[DIM_REF][REF][ID]
952
+ (
953
+ d[DIM_REF]
954
+ if isinstance(d[DIM_REF], str)
955
+ else d[DIM_REF][REF][ID]
956
+ )
955
957
  for d in group_dimensions
956
958
  ]
957
959
 
@@ -994,9 +996,12 @@ class StructureParser(Struct):
994
996
  items = []
995
997
  if item in element:
996
998
  element[item] = add_list(element[item])
997
- for item_elem in element[item]:
998
- # Dynamic
999
- items.append(self.__format_item(item_elem, item))
999
+ items.extend(
1000
+ [
1001
+ self.__format_item(item_elem, item)
1002
+ for item_elem in element[item]
1003
+ ]
1004
+ )
1000
1005
  del element[item]
1001
1006
  element["items"] = items
1002
1007
  element = self.__format_agency(element)
@@ -310,9 +310,9 @@ def __write_maintainable(
310
310
  f"{str(maintainable.is_external_reference).lower()!r}"
311
311
  )
312
312
  if not references_30 and not (isinstance(maintainable, AgencyScheme)):
313
- outfile["Attributes"] += (
314
- f" isFinal={str(maintainable.is_final).lower()!r}"
315
- )
313
+ outfile[
314
+ "Attributes"
315
+ ] += f" isFinal={str(maintainable.is_final).lower()!r}"
316
316
 
317
317
  if isinstance(maintainable.agency, str):
318
318
  outfile["Attributes"] += f" agencyID={maintainable.agency!r}"
@@ -462,7 +462,7 @@ def __write_components( # noqa: C901
462
462
  )
463
463
 
464
464
  position = 1
465
- for _, comps in components.items():
465
+ for comps in components.values():
466
466
  if comps:
467
467
  role_name = ROLE_MAPPING[comps[0].role]
468
468
  if role_name == MEASURE:
@@ -809,9 +809,9 @@ def __write_scheme( # noqa: C901
809
809
  DSD,
810
810
  DFW,
811
811
  ]:
812
- data["Attributes"] += (
813
- f" isPartial={str(item_scheme.is_partial).lower()!r}"
814
- )
812
+ data[
813
+ "Attributes"
814
+ ] += f" isPartial={str(item_scheme.is_partial).lower()!r}"
815
815
  if scheme in [
816
816
  RULE_SCHEME,
817
817
  UDO_SCHEME,
@@ -820,9 +820,9 @@ def __write_scheme( # noqa: C901
820
820
  CUSTOM_TYPE_SCHEME,
821
821
  NAME_PER_SCHEME,
822
822
  ]:
823
- data["Attributes"] += (
824
- f" {_write_vtl(item_scheme, indent, references_30)}"
825
- )
823
+ data[
824
+ "Attributes"
825
+ ] += f" {_write_vtl(item_scheme, indent, references_30)}"
826
826
 
827
827
  outfile = ""
828
828
 
@@ -1129,9 +1129,11 @@ def _write_vtl( # noqa: C901
1129
1129
  ref_codelist = (
1130
1130
  item_or_scheme.codelist
1131
1131
  if isinstance(item_or_scheme.codelist, Reference)
1132
- else parse_urn(item_or_scheme.codelist)
1133
- if isinstance(item_or_scheme.codelist, str)
1134
- else parse_short_urn(item_or_scheme.codelist.short_urn)
1132
+ else (
1133
+ parse_urn(item_or_scheme.codelist)
1134
+ if isinstance(item_or_scheme.codelist, str)
1135
+ else parse_short_urn(item_or_scheme.codelist.short_urn)
1136
+ )
1135
1137
  )
1136
1138
  if references_30:
1137
1139
  data += (
@@ -54,13 +54,15 @@ def writing_validation(dataset: PandasDataset) -> None:
54
54
  for comp in dataset.structure.components
55
55
  if comp.role in (Role.DIMENSION, Role.MEASURE)
56
56
  ]
57
- for att in dataset.structure.components.attributes:
57
+ required_components.extend(
58
+ att.id
59
+ for att in dataset.structure.components.attributes
58
60
  if (
59
61
  att.required
60
62
  and att.attachment_level is not None
61
63
  and att.attachment_level != "D"
62
- ):
63
- required_components.append(att.id)
64
+ )
65
+ )
64
66
  non_required = [
65
67
  comp.id
66
68
  for comp in dataset.structure.components
@@ -198,8 +198,12 @@ def __group_processing(
198
198
  .to_dict(orient="records")
199
199
  )
200
200
 
201
- for record in grouped_data:
202
- out_list.append(__format_group_str(record, group["group_id"]))
201
+ out_list.extend(
202
+ [
203
+ __format_group_str(record, group["group_id"])
204
+ for record in grouped_data
205
+ ]
206
+ )
203
207
 
204
208
  return "".join(out_list)
205
209
 
@@ -39,9 +39,7 @@ def validate_doc(input_str: str) -> None:
39
39
  doc = etree.parse(bytes_infile, parser=parser)
40
40
  if not xmlschema.validate(doc):
41
41
  log_errors = list(xmlschema.error_log) # type: ignore[call-overload]
42
- unhandled_errors = []
43
- for e in log_errors:
44
- unhandled_errors.append(e.message)
42
+ unhandled_errors = [e.message for e in log_errors]
45
43
  severe_errors = unhandled_errors.copy()
46
44
  for e in unhandled_errors:
47
45
  for allowed_error in ALLOWED_ERRORS_CONTENT:
@@ -327,10 +327,12 @@ def __group_processing(
327
327
  .to_dict(orient="records")
328
328
  )
329
329
 
330
- for record in grouped_data:
331
- out_list.append(
330
+ out_list.extend(
331
+ [
332
332
  __format_group_str(record, group_id, dimensions, attribute)
333
- )
333
+ for record in grouped_data
334
+ ]
335
+ )
334
336
 
335
337
  return "".join(out_list)
336
338
 
pysdmx/model/__init__.py CHANGED
@@ -131,9 +131,7 @@ def decoders(type: Type, obj: Any) -> Any: # type: ignore[type-arg]
131
131
  target types
132
132
  """
133
133
  if type is Components:
134
- comps = []
135
- for item in obj:
136
- comps.append(msgspec.convert(item, Component))
134
+ comps = [msgspec.convert(item, Component) for item in obj]
137
135
  return Components(comps)
138
136
  else:
139
137
  raise NotImplementedError(f"Objects of type {type} are not supported")
pysdmx/model/map.py CHANGED
@@ -486,9 +486,7 @@ class StructureMap(MaintainableArtefact, frozen=True, omit_defaults=True):
486
486
  """Return the number of mapping rules in the structure map."""
487
487
  return len(self.maps)
488
488
 
489
- def __getitem__(
490
- self, id_: str
491
- ) -> Optional[
489
+ def __getitem__(self, id_: str) -> Optional[
492
490
  Sequence[
493
491
  Union[
494
492
  ComponentMap,
@@ -500,12 +498,12 @@ class StructureMap(MaintainableArtefact, frozen=True, omit_defaults=True):
500
498
  ]
501
499
  ]:
502
500
  """Return the mapping rules for the supplied component."""
503
- out = []
504
- for m in self.maps:
505
- if (
506
- hasattr(m, "source") and (m.source == id_ or id_ in m.source)
507
- ) or (isinstance(m, FixedValueMap) and m.target == id_):
508
- out.append(m)
501
+ out = [
502
+ m
503
+ for m in self.maps
504
+ if (hasattr(m, "source") and (m.source == id_ or id_ in m.source))
505
+ or (isinstance(m, FixedValueMap) and m.target == id_)
506
+ ]
509
507
  if len(out) == 0:
510
508
  return None
511
509
  else:
pysdmx/model/message.py CHANGED
@@ -168,10 +168,7 @@ class StructureMessage(Struct, repr_omit_defaults=True, frozen=True):
168
168
  raise NotFound(
169
169
  f"No {type_.__name__} found in message.",
170
170
  )
171
- structures = []
172
- for element in self.structures:
173
- if isinstance(element, type_):
174
- structures.append(element)
171
+ structures = [e for e in self.structures if isinstance(e, type_)]
175
172
  return structures
176
173
 
177
174
  def __get_enumerations(
@@ -53,15 +53,14 @@ def get_codes(
53
53
  dimension_code: str, structure: Schema, data: pd.DataFrame
54
54
  ) -> Tuple[List[str], List[str], List[Dict[str, Any]]]:
55
55
  """This function divides the components in Series and Obs."""
56
- series_codes = []
57
56
  groups = structure.groups
58
57
  group_codes = []
59
58
  obs_codes = [dimension_code, structure.components.measures[0].id]
60
59
 
61
60
  # Getting the series and obs codes
62
- for dim in structure.components.dimensions:
63
- if dim.id != dimension_code:
64
- series_codes.append(dim.id)
61
+ series_codes = [
62
+ d.id for d in structure.components.dimensions if d.id != dimension_code
63
+ ]
65
64
 
66
65
  # Adding the attributes based on the attachment level
67
66
  for att in structure.components.attributes:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pysdmx
3
- Version: 1.6.0
3
+ Version: 1.7.0
4
4
  Summary: Your opinionated Python SDMX library
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -18,7 +18,7 @@ Provides-Extra: data
18
18
  Provides-Extra: dc
19
19
  Provides-Extra: vtl
20
20
  Provides-Extra: xml
21
- Requires-Dist: httpx (>=0)
21
+ Requires-Dist: httpx[http2] (>=0)
22
22
  Requires-Dist: lxml (>=5.2) ; extra == "all"
23
23
  Requires-Dist: lxml (>=5.2) ; extra == "xml"
24
24
  Requires-Dist: msgspec (>=0)
@@ -1,5 +1,5 @@
1
1
  pysdmx/__extras_check.py,sha256=I39OaM1lAPBnyzHVJ7kA_ZA_tMeDAQLr6ZKqEQ9MK1Q,1659
2
- pysdmx/__init__.py,sha256=cHUjmNrPbr3mfScL4Gxdsxgf2PUgEDnYf5v8XTQl04Q,67
2
+ pysdmx/__init__.py,sha256=wT-iFGPp5NSw97EUGKgaqjmRmRqdND7Pc58tuIjjcro,67
3
3
  pysdmx/api/__init__.py,sha256=8lRaF6kEO51ehl0fmW_pHLvkN_34TtEhqhr3oKo6E6g,26
4
4
  pysdmx/api/dc/__init__.py,sha256=oPU32X8CRZy4T1to9mO5KMqMwxQsVI424dPqai-I8zI,121
5
5
  pysdmx/api/dc/_api.py,sha256=poy1FYFXnF6maBGy5lpOodf32-7QQjH8PCBNDkuOXxQ,7747
@@ -38,11 +38,11 @@ pysdmx/io/csv/sdmx21/__init__.py,sha256=I3_dwi4A4if62_mwEjqbOa-F7mhoIMf0D6szpDf3
38
38
  pysdmx/io/csv/sdmx21/reader/__init__.py,sha256=J1cCkZh3klgZZWjdQ_U1zkfzT_DVzQmdreGZhN33SLs,2866
39
39
  pysdmx/io/csv/sdmx21/writer/__init__.py,sha256=CH8Nm7hqvXyN6XM_D2nJRmbKj6CJV-X1QzSF0WJrs0E,2484
40
40
  pysdmx/io/format.py,sha256=EO-PyYpiU0WswvEGA5UHokladxPezcwBUo1AJTqxp1Q,5250
41
- pysdmx/io/input_processor.py,sha256=kJuo3-zSuTD3eejGDCXS_5aBxnDwnAh8hO0Tl2dS_XY,6948
41
+ pysdmx/io/input_processor.py,sha256=rj2GzDs3xVQRzikzWonPWJGEa4_mxUPgCqHQ50JI5xY,6917
42
42
  pysdmx/io/json/fusion/messages/__init__.py,sha256=C0LAG6UfIZcQdlCv5d_D1ZNIcCq04RxZYLAp6tLDqwY,1573
43
43
  pysdmx/io/json/fusion/messages/category.py,sha256=E9jrzXenEpqDNUhT1JJLYxty37PSGegRtx45mB3-COg,4589
44
44
  pysdmx/io/json/fusion/messages/code.py,sha256=YayxSKiHa124WTr_lK8HTfXHomh_e0oDZvuydd29XKg,8300
45
- pysdmx/io/json/fusion/messages/concept.py,sha256=k_Ym4J9Nibv7QV_UmIKsO5QfOdJVgJRlbk9SxRHHblA,3113
45
+ pysdmx/io/json/fusion/messages/concept.py,sha256=m4lTyncSIriFXWWupE-zLxUVPx3Xrg56qahzKr4HEag,2824
46
46
  pysdmx/io/json/fusion/messages/constraint.py,sha256=dPkzhCWN49Y9ReSZPRFTdM6GWc0rU2BZTyFfWsqlX34,615
47
47
  pysdmx/io/json/fusion/messages/core.py,sha256=GdzF3TNUGrB0gxuaaSpk9LaYqcdy_M6L2azExZQfM0Q,4843
48
48
  pysdmx/io/json/fusion/messages/dataflow.py,sha256=lsaMPjmA-KiM51I78wrONfNHyvfBSeAll5Sp0jmTezc,2972
@@ -64,8 +64,8 @@ pysdmx/io/json/gds/reader/__init__.py,sha256=cXQvjSzRe4lTsGmru6qMYE_HU2DEccJSYKs
64
64
  pysdmx/io/json/sdmxjson2/messages/__init__.py,sha256=pqLbzZf-FkuSJWy8DLxtCXIu-Si2Mm-vDTzCqnJDNVA,1984
65
65
  pysdmx/io/json/sdmxjson2/messages/agency.py,sha256=d9t_2HrcZcqu_Y-EchShWDRF5yJQn86urfcFl5qvWAc,3720
66
66
  pysdmx/io/json/sdmxjson2/messages/category.py,sha256=k61oDSLNKl0G_Mov2AmC4ff1efCPsNfyNEbz0iajkpI,7656
67
- pysdmx/io/json/sdmxjson2/messages/code.py,sha256=XX9-OC_KH1ZF0Gef0ucGky5yVYCZwcWcVAnVCN63noo,17245
68
- pysdmx/io/json/sdmxjson2/messages/concept.py,sha256=IRr6xfmFKsTrugnxbcWWUiUgEM11s8Oa5IW6mZA5NQA,5624
67
+ pysdmx/io/json/sdmxjson2/messages/code.py,sha256=t2MMvx2nQzlu4l8MMAPDEq15w5UIjHGgaJI2HoFPdus,17908
68
+ pysdmx/io/json/sdmxjson2/messages/concept.py,sha256=x7BoG6AaziZGNjxeypwy_lsFTmdHs-0MPUpqPsTBQIA,5496
69
69
  pysdmx/io/json/sdmxjson2/messages/constraint.py,sha256=6pONMHr7IT8O026Xnv6AjIMVmoS29ivNiOMPr1OWQZQ,1736
70
70
  pysdmx/io/json/sdmxjson2/messages/core.py,sha256=Cb6U1J13KCXnGJ2P8xbThTg9GCdzhkIK-cA8EHbY6Js,10077
71
71
  pysdmx/io/json/sdmxjson2/messages/dataflow.py,sha256=wjeq9yexTa012AtGdZsZflp3WQ6fP-3kas-gxADTFeQ,6256
@@ -91,15 +91,15 @@ pysdmx/io/xml/__allowed_lxml_errors.py,sha256=PdIK2i6JwwGRh1Ogc5JA0hRySO7QXJKN-D
91
91
  pysdmx/io/xml/__data_aux.py,sha256=ztivjZANN1PJ63IvoMfx-5TA2AiPQTVPC_0YYHOT9Ns,4069
92
92
  pysdmx/io/xml/__init__.py,sha256=tcUsSEiM3nBA7lDbZPwGZ7Vu_K9gQd8oliASUMTGjFE,105
93
93
  pysdmx/io/xml/__parse_xml.py,sha256=SITC7Yptq_qY_exetRez90lJCukH1WsKDMqlk7Q1RaY,2899
94
- pysdmx/io/xml/__ss_aux_reader.py,sha256=Tfp7oSb_0-AVEVdu7YFtj-SlBuEKp7fpg3-SxCmOHW0,2868
95
- pysdmx/io/xml/__structure_aux_reader.py,sha256=dGPmAiW4j38fbsAJ8xCDwXgUcwpOCwgO5jQpvgoKD4Q,40258
96
- pysdmx/io/xml/__structure_aux_writer.py,sha256=9x2wGYRP9vPGLlHA-3P5Xr3gY5g3gW5fmz0tDQJyH4U,43543
94
+ pysdmx/io/xml/__ss_aux_reader.py,sha256=6mumQYcDdF_vrX65vSodE4I1b7upKbP6yNNSM2N6pUs,2853
95
+ pysdmx/io/xml/__structure_aux_reader.py,sha256=xqwZZ2qWi8IUW2KMVhuABp1TSx6dSRH4BmvKh5kXxyk,40348
96
+ pysdmx/io/xml/__structure_aux_writer.py,sha256=jOcp7Ywx7mEUrrhgKj6Kz5-6KctQoD7TbOSOoPxj_ZE,43583
97
97
  pysdmx/io/xml/__tokens.py,sha256=Y_SlFWYIXolsgjHoFq7pm3TYlEu07CR9TmJKk2jHfQ0,6823
98
98
  pysdmx/io/xml/__write_aux.py,sha256=KHZxEhGSjZPRW93OvniZ0kHmiAJtKJu-2aLtMhsKt90,15396
99
- pysdmx/io/xml/__write_data_aux.py,sha256=Ma0aGo97dzrkSQ-U0_ytVPec1zn2VB3rffTIoRNTNco,3365
100
- pysdmx/io/xml/__write_structure_specific_aux.py,sha256=3u7mAgFeP1bmhsYrIGlbOm31LDCN4y7AGA1H-IvW02g,8862
99
+ pysdmx/io/xml/__write_data_aux.py,sha256=x-RNwVfUgEkBoGG_Sen-rPg7MnqE5_0SV-6PmjDdAxY,3373
100
+ pysdmx/io/xml/__write_structure_specific_aux.py,sha256=reRDVw4Xwag0ODyMzm9uOk9WJ_e1ELxAPYHSMUUDJBQ,8919
101
101
  pysdmx/io/xml/config.py,sha256=R24cczVkzkhjVLXpv-qfEm88W3_QTqVt2Qofi8IvJ5Y,93
102
- pysdmx/io/xml/doc_validation.py,sha256=qS-riLo3fMNLBrsQWzizeVNePuYT9W8wp9q-xE3QXto,1842
102
+ pysdmx/io/xml/doc_validation.py,sha256=WXDhte96VEAeZMMHJ0Y68WW8HEoOhEiOYEnbGP5Zwjw,1795
103
103
  pysdmx/io/xml/header.py,sha256=_XiruPAfMtr4wudCpiuhFXDvRgWITGQ9GZVG3lMvWcc,5535
104
104
  pysdmx/io/xml/sdmx21/__init__.py,sha256=_rh_dz1d-LmUw4iVbsZQkTXANTJeR8ov8z_4jNRGhtg,38
105
105
  pysdmx/io/xml/sdmx21/reader/__init__.py,sha256=2jMsySFbbq-So3ymqzKVi5gOPRwO0qasBBwntD03rTw,34
@@ -110,7 +110,7 @@ pysdmx/io/xml/sdmx21/reader/structure_specific.py,sha256=S3-gLmaBFjBRIr25qQtlrao
110
110
  pysdmx/io/xml/sdmx21/reader/submission.py,sha256=8daiBW-sIVGaB6lYwHqJNkLI7IixMSydCK-0ZO8ri4I,1711
111
111
  pysdmx/io/xml/sdmx21/writer/__init__.py,sha256=QQGFAss26njCC4eKYxhBcI9LYm5NHuJaAJGKCrIrL80,31
112
112
  pysdmx/io/xml/sdmx21/writer/error.py,sha256=0wkX7K_n2oZNkOKg_zpl9Id82qP72Lqof-T-ZLGoZ1M,353
113
- pysdmx/io/xml/sdmx21/writer/generic.py,sha256=eir14yUVXIgCrh-ZM6zVOCcwQWsYLfUYh21UdzPtJp8,15759
113
+ pysdmx/io/xml/sdmx21/writer/generic.py,sha256=8_kUMMUiIFVdKMyhpR2LKDyfiinBohO_aL_6GZpOInY,15786
114
114
  pysdmx/io/xml/sdmx21/writer/structure.py,sha256=S3qoNgXxrakn2V4NLdL5U5mAA16XisI0PpJDuxqalFE,2084
115
115
  pysdmx/io/xml/sdmx21/writer/structure_specific.py,sha256=iXc1J-RzoKyRznvgGgdTSeUfyqZLouI8CtSq2YhGBWI,2877
116
116
  pysdmx/io/xml/sdmx30/__init__.py,sha256=8BScJFEgLy8DoUreu2RBUtxjGjKyClkKBI_Qtarbk-Y,38
@@ -129,15 +129,15 @@ pysdmx/io/xml/sdmx31/writer/structure.py,sha256=hK-BYOsyyuqLTqxe6qC3PxeDJDp3_qyB
129
129
  pysdmx/io/xml/sdmx31/writer/structure_specific.py,sha256=OtP_uxn-y9tVB9eNRP6ov3zBL1wtr4SRef9llB4A3yk,3236
130
130
  pysdmx/io/xml/utils.py,sha256=ljrocQwPTYycg3I68sqYI5pF8qukNccSCMM9Xf_Tag0,583
131
131
  pysdmx/model/__base.py,sha256=H5OpCpi6fGxB30vFn-lCstTczSdOB4YJiBynThovQs4,13810
132
- pysdmx/model/__init__.py,sha256=gmY8uGK0_SK9Ca5TqtYJqPSXvO9godlDKu2rhYouPSU,4984
132
+ pysdmx/model/__init__.py,sha256=PHfVmxbfBzRNoCJ2kqRl-aSvGN4fLz2E8DYAoDxBTRA,4948
133
133
  pysdmx/model/category.py,sha256=WWWysaTdlcU8KZpQyZgbZkrOelNVCGOfVUk_APJxm-w,6031
134
134
  pysdmx/model/code.py,sha256=Wu6rEXeZf_XA0aBrDXgN-3yvySAHH7SAjrWliFlmC24,12799
135
135
  pysdmx/model/concept.py,sha256=mQfqJdtWc10WdTKX_Mw7Znw65cN3QO-kCar9MWYeWO4,9645
136
136
  pysdmx/model/dataflow.py,sha256=RDuL3GMhfMR5Dn1bTb4saWhn5v6igcJSKZ4d7ip7WPw,23887
137
137
  pysdmx/model/dataset.py,sha256=Lbr7tYonGHD3NZUD-M9hK2puaEAluOVPG2DbkOohzMM,4861
138
138
  pysdmx/model/gds.py,sha256=QrnmI8Hn--C95gGXCeUeWwhn-Ur7DuT08Cg7oPJIEVI,4976
139
- pysdmx/model/map.py,sha256=vMRfhNUuKBAgJPYrqBCkGYfV6CIzbIr1gPPkYj1Z-aU,17529
140
- pysdmx/model/message.py,sha256=OWbsHC4w8Qt__cleuKCzd3Y4oKUDv2OJjw7kzwuAG5Q,14773
139
+ pysdmx/model/map.py,sha256=BR23koomqDGDYvHLTg2axVwlTkst7aJ0X65-0tw11j4,17492
140
+ pysdmx/model/message.py,sha256=tuUr0sQf6P3QflhNAbmYjQaz4_3ly06psk19c8zlJ2s,14697
141
141
  pysdmx/model/metadata.py,sha256=EwElZZ8oewpuaEDDWM9ZV95Xvklcq333qxqPwoUqmXU,7653
142
142
  pysdmx/model/organisation.py,sha256=k6ZQ_O4l7174Y8tr-nnMnsUL0q0O8Rw3q4mIWmJUh2A,4706
143
143
  pysdmx/model/submission.py,sha256=iMQSvt-BYuDrqPEBcjw_wWNp74Vsx2OnEj3tnkth0Z8,833
@@ -145,7 +145,7 @@ pysdmx/model/vtl.py,sha256=k7WIb89876xKlf7k0R9sgZ1VVlRrIkbV7FzvMFZn8e0,6985
145
145
  pysdmx/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
146
146
  pysdmx/toolkit/__init__.py,sha256=yBRw4FXQH_RUJgF6vwZscNwCVBt-FMwslJEfDKa7eXo,26
147
147
  pysdmx/toolkit/pd/__init__.py,sha256=3JoCZHamJR4mZfLt9GmaznLlG_YilmY0hAhuW5COQC8,3138
148
- pysdmx/toolkit/pd/_data_utils.py,sha256=_aF2AnN_TY1UuZenxQiFAlFAAnfh8bB5DBEt6uJkd1k,3305
148
+ pysdmx/toolkit/pd/_data_utils.py,sha256=fzXl_a1M8NI7HHI23tRmLlS4PBZ9N4Tgtqh-zxg19qk,3265
149
149
  pysdmx/toolkit/vtl/__init__.py,sha256=nVwtISeFiT4tr2gNjb2A-P_IRAdqv6Mn7EOgFkaRleg,216
150
150
  pysdmx/toolkit/vtl/_validations.py,sha256=Djc5hHpj79SksvnAA0vL5EnpsDCdQ_BmB6zsr7Ze9Eg,5639
151
151
  pysdmx/toolkit/vtl/script_generation.py,sha256=YOP_-MMcIdDIHYa8HIMuVCN9N-S9CQD8bH5xpF1kc2E,3235
@@ -154,7 +154,7 @@ pysdmx/util/__init__.py,sha256=m_XWRAmVJ7F6ai4Ckrj_YuPbhg3cJZAXeZrEThrL88k,3997
154
154
  pysdmx/util/_date_pattern_map.py,sha256=IS1qONwVHbTBNIFCT0Rqbijj2a9mYvs7onXSK6GeQAQ,1620
155
155
  pysdmx/util/_model_utils.py,sha256=d0XY8cnxvviQtkJJInVik7LWeuqX-eb4-zikFortL58,2335
156
156
  pysdmx/util/_net_utils.py,sha256=nOTz_x3FgFrwKh42_J70IqYXz9duQkMFJWtejZXcLHs,1326
157
- pysdmx-1.6.0.dist-info/METADATA,sha256=lMABrenHbBZfRuFItDBUNi99bSi1pRmIFm9NuQ78vZc,4712
158
- pysdmx-1.6.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
159
- pysdmx-1.6.0.dist-info/licenses/LICENSE,sha256=3XTNDPtv2RxDUNkQzn9MIWit2u7_Ob5daMLEq-4pBJs,649
160
- pysdmx-1.6.0.dist-info/RECORD,,
157
+ pysdmx-1.7.0.dist-info/METADATA,sha256=3zJX2O0JkzICIK-VuqsZ84oRhJCn5D_B70P2LTx3QxM,4719
158
+ pysdmx-1.7.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
159
+ pysdmx-1.7.0.dist-info/licenses/LICENSE,sha256=3XTNDPtv2RxDUNkQzn9MIWit2u7_Ob5daMLEq-4pBJs,649
160
+ pysdmx-1.7.0.dist-info/RECORD,,
File without changes