eba-xbridge 1.5.0rc4__py3-none-any.whl → 1.5.0rc5__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eba-xbridge
3
- Version: 1.5.0rc4
3
+ Version: 1.5.0rc5
4
4
  Summary: XBRL-XML to XBRL-CSV converter for EBA Taxonomy (version 4.1)
5
5
  License: Apache 2.0
6
6
  License-File: LICENSE
@@ -1,8 +1,8 @@
1
- xbridge/__init__.py,sha256=joASbfhYee_2irYZhRCZ6J4oTn6u1fjt6ilQbXwL4M4,68
1
+ xbridge/__init__.py,sha256=S6yAyrnTJ19Trbh-OrGVDIwi5lh88C2pCxDncQyX1VY,68
2
2
  xbridge/__main__.py,sha256=trtFEv7TRJgrLL84leIapPvgC_iVTj05qLHRRS1Olts,2219
3
3
  xbridge/api.py,sha256=NCBz7VRJWE3gID6ndgL4Awoxw0w1yMIIf_OTLRuZyyQ,1559
4
- xbridge/converter.py,sha256=uu6djzgGZcmq0nibrkmg5lW-npcolB4XtQoNWu1p_3o,23498
5
- xbridge/instance.py,sha256=KQpXhsZIM9oTYJf2hyrzc9pqFY2-1JBF5y1xbnLbqk8,29991
4
+ xbridge/converter.py,sha256=vWlIaqQ2eA8Y5b1jqnqTIcOxeubJEu1itggMrFxYnS8,24077
5
+ xbridge/instance.py,sha256=GA5D2p3IobCp5W4-x1dibgOQFuy_W4R8LmZnQ4H900g,32292
6
6
  xbridge/modules/ae_ae_4.2.json,sha256=AdFvwZqX0KVP3jF1iHeQc5QSnSMvvT3GvoA2G1AgXis,460165
7
7
  xbridge/modules/ae_con_cir-680-2014_2017-04-04.json,sha256=4n0t9dKJNU8Nb5QHpssrDs8ZLwzI-Mw75ax-ar9pLu0,363273
8
8
  xbridge/modules/ae_con_cir-680-2014_2018-03-31.json,sha256=aVWeLLs20p39kQQUthUzqrxBGKTycqhgX9WLk1rVlNw,363538
@@ -383,8 +383,8 @@ xbridge/modules/sepa_ipr_pay_4.2.json,sha256=JLJvR02LOAJy6SWPRuhV1TT02oXQhsG83FB
383
383
  xbridge/modules.py,sha256=bTvBXtp3w4Gad2DpEQE7Hb-UfuUQLlRl8gywRstQtpU,22399
384
384
  xbridge/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
385
385
  xbridge/taxonomy_loader.py,sha256=K0lnJVryvkKsaoK3fMis-L2JpmwLO6z3Ruq3yj9FxDY,9317
386
- eba_xbridge-1.5.0rc4.dist-info/METADATA,sha256=5BAX_xFnRrIxcQiJbNi3y68A_42F8dR-qpL6Z-bBT0U,10430
387
- eba_xbridge-1.5.0rc4.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
388
- eba_xbridge-1.5.0rc4.dist-info/entry_points.txt,sha256=FATct4icSewM04cegjhybtm7xcQWhaSahL-DTtuFdZw,49
389
- eba_xbridge-1.5.0rc4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
390
- eba_xbridge-1.5.0rc4.dist-info/RECORD,,
386
+ eba_xbridge-1.5.0rc5.dist-info/METADATA,sha256=88P20ZbVDK8cMGG0-rs1W7OihOdBrmOxujMvoeB3RQM,10430
387
+ eba_xbridge-1.5.0rc5.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
388
+ eba_xbridge-1.5.0rc5.dist-info/entry_points.txt,sha256=FATct4icSewM04cegjhybtm7xcQWhaSahL-DTtuFdZw,49
389
+ eba_xbridge-1.5.0rc5.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
390
+ eba_xbridge-1.5.0rc5.dist-info/RECORD,,
xbridge/__init__.py CHANGED
@@ -2,4 +2,4 @@
2
2
  Init file for eba-xbridge library
3
3
  """
4
4
 
5
- __version__ = "1.5.0rc4"
5
+ __version__ = "1.5.0rc5"
xbridge/converter.py CHANGED
@@ -300,17 +300,27 @@ class Converter:
300
300
  if instance_df.empty or table.variable_df is None:
301
301
  return set()
302
302
 
303
+ variable_columns = set(table.variable_columns or [])
303
304
  open_keys = set(table.open_keys)
304
305
 
306
+ # self.instance.instance_df is guaranteed to not be None due to check at line 296
307
+ instance_columns = set(self.instance.instance_df.columns)
308
+
305
309
  datapoint_df = table.variable_df.copy()
306
310
 
307
- # For validation we match minimally on metric (concept) and any open keys present
308
- merge_cols: list[str] = []
309
- if "metric" in datapoint_df.columns and "metric" in instance_df.columns:
310
- merge_cols.append("metric")
311
- merge_cols.extend(
312
- [key for key in open_keys if key in datapoint_df.columns and key in instance_df.columns]
313
- )
311
+ # Handle missing columns by filtering datapoint_df (same as _variable_generator)
312
+ # This prevents requiring dimensions that don't exist in the instance
313
+ missing_cols = list(variable_columns - instance_columns)
314
+ if "data_type" in missing_cols:
315
+ missing_cols.remove("data_type")
316
+ if missing_cols:
317
+ mask = datapoint_df[missing_cols].isnull().all(axis=1)
318
+ datapoint_df = datapoint_df.loc[mask]
319
+ datapoint_df = datapoint_df.drop(columns=missing_cols)
320
+
321
+ # Match on all variable columns (dimensions) to avoid Cartesian product
322
+ # explosion. Consistent with _variable_generator() to prevent OOM.
323
+ merge_cols = list(variable_columns & instance_columns)
314
324
 
315
325
  instance_df = instance_df.copy()
316
326
  instance_df["_idx"] = instance_df.index
xbridge/instance.py CHANGED
@@ -40,6 +40,49 @@ def _derive_csv_prefix(namespace_uri: str) -> Optional[str]:
40
40
  return prefix
41
41
 
42
42
 
43
+ def _derive_metric_prefix(namespace_uri: str) -> Optional[str]:
44
+ """
45
+ Derive the CSV prefix for metrics from a namespace URI.
46
+
47
+ For metrics, we preserve version suffixes in the prefix:
48
+ - http://www.eba.europa.eu/xbrl/crr/dict/met -> eba_met
49
+ - http://www.eba.europa.eu/xbrl/crr/dict/met/3.5 -> eba_met_3.5
50
+ - http://www.eba.europa.eu/xbrl/crr/dict/met/4.0 -> eba_met_4.0
51
+ """
52
+ if not namespace_uri:
53
+ return None
54
+
55
+ cached = _namespace_prefix_cache.get(f"metric:{namespace_uri}")
56
+ if cached is not None:
57
+ return cached
58
+
59
+ cleaned = namespace_uri.rstrip("#/")
60
+
61
+ # Split the URI into path segments
62
+ segments = cleaned.split("/")
63
+
64
+ # Find the 'met' (metrics) segment and check if there's a version after it
65
+ prefix = None
66
+ for i, segment in enumerate(segments):
67
+ if segment == "met":
68
+ # Check if there's a version suffix (e.g., "3.5", "4.0")
69
+ if i + 1 < len(segments):
70
+ version = segments[i + 1]
71
+ prefix = f"eba_met_{version}"
72
+ else:
73
+ prefix = "eba_met"
74
+ break
75
+
76
+ # If we didn't find 'met', fall back to the standard logic
77
+ if prefix is None:
78
+ prefix = _derive_csv_prefix(namespace_uri)
79
+
80
+ if prefix:
81
+ _namespace_prefix_cache[f"metric:{namespace_uri}"] = prefix
82
+
83
+ return prefix
84
+
85
+
43
86
  def _normalize_namespaced_value(
44
87
  value: Optional[str], nsmap: Dict[Optional[str], str]
45
88
  ) -> Optional[str]:
@@ -67,6 +110,34 @@ def _normalize_namespaced_value(
67
110
  return value
68
111
 
69
112
 
113
+ def _normalize_metric_value(
114
+ value: Optional[str], nsmap: Dict[Optional[str], str]
115
+ ) -> Optional[str]:
116
+ """
117
+ Normalize a metric namespaced value to the CSV prefix convention.
118
+ For metrics, we preserve version suffixes (e.g., eba_met_3.5, eba_met_4.0).
119
+ Returns the original value if no namespace can be resolved.
120
+ """
121
+ if value is None:
122
+ return None
123
+
124
+ # Clark notation: {uri}local
125
+ if value.startswith("{") and "}" in value:
126
+ uri, local = value[1:].split("}", 1)
127
+ derived = _derive_metric_prefix(uri)
128
+ return f"{derived}:{local}" if derived else value
129
+
130
+ # Prefixed notation: prefix:local
131
+ if ":" in value:
132
+ potential_prefix, local = value.split(":", 1)
133
+ namespace_uri = nsmap.get(potential_prefix)
134
+ if namespace_uri:
135
+ derived = _derive_metric_prefix(namespace_uri)
136
+ return f"{derived}:{local}" if derived else value
137
+
138
+ return value
139
+
140
+
70
141
  class Instance:
71
142
  """
72
143
  Abstract class representing an XBRL instance file.
@@ -728,8 +799,8 @@ class Fact:
728
799
  def __dict__(self) -> Dict[str, Any]: # type: ignore[override]
729
800
  metric_clean = ""
730
801
  if self.metric:
731
- # Normalize metric to use consistent eba_* prefix like other dimensions
732
- metric_clean = _normalize_namespaced_value(self.metric, self.fact_xml.nsmap) or ""
802
+ # Normalize metric using metric-specific logic that preserves version suffixes
803
+ metric_clean = _normalize_metric_value(self.metric, self.fact_xml.nsmap) or ""
733
804
  # If still in Clark notation, extract the local name
734
805
  if metric_clean.startswith("{") and "}" in metric_clean:
735
806
  metric_clean = metric_clean.split("}", 1)[1]