pydpm_xl 0.2.5rc1__tar.gz → 0.2.5rc3__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 (99) hide show
  1. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/PKG-INFO +1 -1
  2. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/__init__.py +1 -1
  3. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/dpm_xl/ast_generator.py +122 -17
  4. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/pydpm_xl.egg-info/PKG-INFO +1 -1
  5. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/pyproject.toml +2 -2
  6. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/LICENSE +0 -0
  7. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/README.md +0 -0
  8. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/__init__.py +0 -0
  9. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/dpm/__init__.py +0 -0
  10. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/dpm/data_dictionary.py +0 -0
  11. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/dpm/explorer.py +0 -0
  12. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/dpm/hierarchical_queries.py +0 -0
  13. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/dpm/instance.py +0 -0
  14. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/dpm/migration.py +0 -0
  15. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/dpm_xl/__init__.py +0 -0
  16. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/dpm_xl/complete_ast.py +0 -0
  17. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/dpm_xl/operation_scopes.py +0 -0
  18. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/dpm_xl/semantic.py +0 -0
  19. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/api/dpm_xl/syntax.py +0 -0
  20. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/cli/__init__.py +0 -0
  21. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/cli/commands/__init__.py +0 -0
  22. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/cli/main.py +0 -0
  23. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm/__init__.py +0 -0
  24. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm/migration.py +0 -0
  25. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm/models.py +0 -0
  26. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm/queries/base.py +0 -0
  27. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm/queries/basic_objects.py +0 -0
  28. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm/queries/explorer_queries.py +0 -0
  29. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm/queries/filters.py +0 -0
  30. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm/queries/glossary.py +0 -0
  31. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm/queries/hierarchical_queries.py +0 -0
  32. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm/queries/tables.py +0 -0
  33. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm/utils.py +0 -0
  34. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/__init__.py +0 -0
  35. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/ast/__init__.py +0 -0
  36. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/ast/constructor.py +0 -0
  37. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/ast/ml_generation.py +0 -0
  38. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/ast/module_analyzer.py +0 -0
  39. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/ast/module_dependencies.py +0 -0
  40. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/ast/nodes.py +0 -0
  41. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/ast/operands.py +0 -0
  42. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/ast/template.py +0 -0
  43. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/ast/visitor.py +0 -0
  44. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/ast/where_clause.py +0 -0
  45. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/grammar/__init__.py +0 -0
  46. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/grammar/generated/__init__.py +0 -0
  47. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/grammar/generated/dpm_xlLexer.interp +0 -0
  48. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/grammar/generated/dpm_xlLexer.py +0 -0
  49. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/grammar/generated/dpm_xlLexer.tokens +0 -0
  50. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/grammar/generated/dpm_xlParser.interp +0 -0
  51. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/grammar/generated/dpm_xlParser.py +0 -0
  52. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/grammar/generated/dpm_xlParser.tokens +0 -0
  53. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/grammar/generated/dpm_xlParserListener.py +0 -0
  54. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/grammar/generated/dpm_xlParserVisitor.py +0 -0
  55. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/grammar/generated/listeners.py +0 -0
  56. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/operators/__init__.py +0 -0
  57. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/operators/aggregate.py +0 -0
  58. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/operators/arithmetic.py +0 -0
  59. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/operators/base.py +0 -0
  60. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/operators/boolean.py +0 -0
  61. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/operators/clause.py +0 -0
  62. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/operators/comparison.py +0 -0
  63. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/operators/conditional.py +0 -0
  64. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/operators/string.py +0 -0
  65. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/operators/time.py +0 -0
  66. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/semantic_analyzer.py +0 -0
  67. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/symbols.py +0 -0
  68. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/types/__init__.py +0 -0
  69. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/types/promotion.py +0 -0
  70. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/types/scalar.py +0 -0
  71. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/types/time.py +0 -0
  72. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/utils/__init__.py +0 -0
  73. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/utils/data_handlers.py +0 -0
  74. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/utils/operands_mapping.py +0 -0
  75. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/utils/operator_mapping.py +0 -0
  76. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/utils/scopes_calculator.py +0 -0
  77. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/utils/serialization.py +0 -0
  78. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/dpm_xl/utils/tokens.py +0 -0
  79. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/exceptions/__init__.py +0 -0
  80. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/exceptions/exceptions.py +0 -0
  81. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/exceptions/messages.py +0 -0
  82. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/instance/__init__.py +0 -0
  83. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/py_dpm/instance/instance.py +0 -0
  84. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/pydpm_xl.egg-info/SOURCES.txt +0 -0
  85. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/pydpm_xl.egg-info/dependency_links.txt +0 -0
  86. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/pydpm_xl.egg-info/entry_points.txt +0 -0
  87. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/pydpm_xl.egg-info/requires.txt +0 -0
  88. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/pydpm_xl.egg-info/top_level.txt +0 -0
  89. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/setup.cfg +0 -0
  90. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/tests/test_cli_semantic.py +0 -0
  91. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/tests/test_data_dictionary_releases.py +0 -0
  92. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/tests/test_db_connection_handling.py +0 -0
  93. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/tests/test_get_table_details.py +0 -0
  94. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/tests/test_get_tables_date_filter.py +0 -0
  95. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/tests/test_get_tables_release_code.py +0 -0
  96. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/tests/test_hierarchical_query.py +0 -0
  97. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/tests/test_query_refactor.py +0 -0
  98. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/tests/test_release_filters_semantic.py +0 -0
  99. {pydpm_xl-0.2.5rc1 → pydpm_xl-0.2.5rc3}/tests/test_semantic_release.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydpm_xl
3
- Version: 0.2.5rc1
3
+ Version: 0.2.5rc3
4
4
  Summary: Python library for DPM-XL data processing and analysis
5
5
  Author-email: "MeaningfulData S.L." <info@meaningfuldata.eu>
6
6
  License: GPL-3.0-or-later
@@ -41,7 +41,7 @@ Available packages:
41
41
  - pydpm.api: Main APIs for migration, syntax, and semantic analysis
42
42
  """
43
43
 
44
- __version__ = "0.2.5rc1"
44
+ __version__ = "0.2.5rc3"
45
45
  __author__ = "MeaningfulData S.L."
46
46
  __email__ = "info@meaningfuldata.eu"
47
47
  __license__ = "GPL-3.0-or-later"
@@ -811,7 +811,7 @@ class ASTGeneratorAPI:
811
811
  preconditions = {}
812
812
  precondition_variables = {}
813
813
 
814
- if precondition or (context and "table" in context):
814
+ if precondition:
815
815
  preconditions, precondition_variables = self._build_preconditions(
816
816
  precondition=precondition,
817
817
  context=context,
@@ -974,8 +974,6 @@ class ASTGeneratorAPI:
974
974
  match = re.match(r"\{v_([^}]+)\}", precondition)
975
975
  if match:
976
976
  table_code = match.group(1)
977
- elif context and "table" in context:
978
- table_code = context["table"]
979
977
 
980
978
  if table_code:
981
979
  # Query database for actual variable ID and version
@@ -1039,6 +1037,81 @@ class ASTGeneratorAPI:
1039
1037
  extract_from_node(ast_dict)
1040
1038
  return all_variables, variables_by_table
1041
1039
 
1040
+ def _extract_time_shifts_by_table(self, expression: str) -> Dict[str, str]:
1041
+ """
1042
+ Extract time shift information for each table in the expression.
1043
+
1044
+ Uses the AST to properly parse the expression and find TimeShiftOp nodes
1045
+ to determine the ref_period for each table reference.
1046
+
1047
+ Args:
1048
+ expression: DPM-XL expression
1049
+
1050
+ Returns:
1051
+ Dict mapping table codes to ref_period values (e.g., {"C_01.00": "T-1Q"})
1052
+ Tables without time shifts default to "T".
1053
+ """
1054
+ from py_dpm.dpm_xl.ast.template import ASTTemplate
1055
+
1056
+ time_shifts = {}
1057
+ current_period = ["t"] # Use list to allow mutation in nested function
1058
+
1059
+ class TimeShiftExtractor(ASTTemplate):
1060
+ """Lightweight AST visitor that extracts time shifts for each table."""
1061
+
1062
+ def visit_TimeShiftOp(self, node):
1063
+ # Save current time period and compute new one
1064
+ previous_period = current_period[0]
1065
+
1066
+ period_indicator = node.period_indicator
1067
+ shift_number = node.shift_number
1068
+
1069
+ # Compute time period (same logic as ModuleDependencies)
1070
+ if "-" in str(shift_number):
1071
+ current_period[0] = f"t+{period_indicator}{shift_number}"
1072
+ else:
1073
+ current_period[0] = f"t-{period_indicator}{shift_number}"
1074
+
1075
+ # Visit operand (which contains the VarID)
1076
+ self.visit(node.operand)
1077
+
1078
+ # Restore previous time period
1079
+ current_period[0] = previous_period
1080
+
1081
+ def visit_VarID(self, node):
1082
+ if node.table and current_period[0] != "t":
1083
+ time_shifts[node.table] = current_period[0]
1084
+
1085
+ def convert_to_ref_period(internal_period: str) -> str:
1086
+ """Convert internal time period format to ref_period format.
1087
+
1088
+ Internal format: "t+Q-1" or "t-Q1"
1089
+ Output format: "T-1Q" for one quarter back
1090
+ """
1091
+ if internal_period.startswith("t+"):
1092
+ # e.g., "t+Q-1" -> "T-1Q"
1093
+ indicator = internal_period[2]
1094
+ number = internal_period[3:]
1095
+ if number.startswith("-"):
1096
+ return f"T{number}{indicator}"
1097
+ return f"T+{number}{indicator}"
1098
+ elif internal_period.startswith("t-"):
1099
+ # e.g., "t-Q1" -> "T-1Q"
1100
+ indicator = internal_period[2]
1101
+ number = internal_period[3:]
1102
+ return f"T-{number}{indicator}"
1103
+ return "T"
1104
+
1105
+ try:
1106
+ ast = self.syntax_api.parse_expression(expression)
1107
+ extractor = TimeShiftExtractor()
1108
+ extractor.visit(ast)
1109
+
1110
+ return {table: convert_to_ref_period(period) for table, period in time_shifts.items()}
1111
+
1112
+ except Exception:
1113
+ return {}
1114
+
1042
1115
  def _detect_cross_module_dependencies(
1043
1116
  self,
1044
1117
  expression: str,
@@ -1075,7 +1148,7 @@ class ASTGeneratorAPI:
1075
1148
  )
1076
1149
 
1077
1150
  try:
1078
- # Get tables with module info
1151
+ # Get tables with module info (includes module_version)
1079
1152
  tables_with_modules = scopes_api.get_tables_with_metadata_from_expression(
1080
1153
  expression=expression,
1081
1154
  release_id=release_id
@@ -1091,10 +1164,35 @@ class ASTGeneratorAPI:
1091
1164
  if scope_result.has_error or not scope_result.is_cross_module:
1092
1165
  return {}, []
1093
1166
 
1167
+ # Extract time shifts for each table from expression
1168
+ time_shifts_by_table = self._extract_time_shifts_by_table(expression)
1169
+
1094
1170
  # Determine primary module from first table if not provided
1095
1171
  if primary_module_vid is None and tables_with_modules:
1096
1172
  primary_module_vid = tables_with_modules[0].get("module_vid")
1097
1173
 
1174
+ # Helper to normalize table code (remove 't' prefix if present)
1175
+ def normalize_table_code(code: str) -> str:
1176
+ return code[1:] if code and code.startswith('t') else code
1177
+
1178
+ # Helper to lookup ref_period for a table
1179
+ def get_ref_period(table_code: str) -> str:
1180
+ if not table_code:
1181
+ return "T"
1182
+ ref = time_shifts_by_table.get(table_code)
1183
+ if not ref:
1184
+ ref = time_shifts_by_table.get(normalize_table_code(table_code))
1185
+ return ref or "T"
1186
+
1187
+ # Helper to lookup variables for a table
1188
+ def get_table_variables(table_code: str) -> dict:
1189
+ if not table_code:
1190
+ return {}
1191
+ variables = variables_by_table.get(table_code)
1192
+ if not variables:
1193
+ variables = variables_by_table.get(f"t{table_code}", {})
1194
+ return variables or {}
1195
+
1098
1196
  # Group external tables by module
1099
1197
  external_modules = {}
1100
1198
  for table_info in tables_with_modules:
@@ -1106,36 +1204,38 @@ class ASTGeneratorAPI:
1106
1204
  if not module_code:
1107
1205
  continue
1108
1206
 
1109
- # Get module URI using existing ExplorerQuery
1207
+ # Get module URI
1110
1208
  try:
1111
1209
  module_uri = ExplorerQuery.get_module_url(
1112
1210
  scopes_api.session,
1113
1211
  module_code=module_code,
1114
1212
  release_id=release_id,
1115
1213
  )
1116
- # Remove .json suffix if present (for consistency with expected format)
1117
1214
  if module_uri.endswith(".json"):
1118
1215
  module_uri = module_uri[:-5]
1119
1216
  except Exception:
1120
1217
  continue
1121
1218
 
1219
+ table_code = table_info.get("code")
1220
+ ref_period = get_ref_period(table_code)
1221
+
1122
1222
  if module_uri not in external_modules:
1123
1223
  external_modules[module_uri] = {
1124
1224
  "module_vid": module_vid,
1225
+ "module_version": table_info.get("module_version"), # Already in table_info
1226
+ "ref_period": ref_period,
1125
1227
  "tables": {},
1126
1228
  "variables": {},
1127
1229
  "from_date": None,
1128
1230
  "to_date": None
1129
1231
  }
1232
+ elif ref_period != "T":
1233
+ # Keep most specific ref_period (non-T takes precedence)
1234
+ external_modules[module_uri]["ref_period"] = ref_period
1130
1235
 
1131
- # Add table - get variables from variables_by_table
1132
- table_code = table_info.get("code")
1236
+ # Add table and variables
1133
1237
  if table_code:
1134
- # Look up variables in variables_by_table (handles t prefix)
1135
- table_variables = variables_by_table.get(table_code, {})
1136
- if not table_variables:
1137
- # Try with t prefix
1138
- table_variables = variables_by_table.get(f"t{table_code}", {})
1238
+ table_variables = get_table_variables(table_code)
1139
1239
  external_modules[module_uri]["tables"][table_code] = {
1140
1240
  "variables": table_variables,
1141
1241
  "open_keys": {}
@@ -1169,11 +1269,16 @@ class ASTGeneratorAPI:
1169
1269
  # cross_instance_dependencies entry (one per external module)
1170
1270
  from_date = data["from_date"]
1171
1271
  to_date = data["to_date"]
1272
+ module_entry = {
1273
+ "URI": uri,
1274
+ "ref_period": data["ref_period"]
1275
+ }
1276
+ # Add module_version if available
1277
+ if data["module_version"]:
1278
+ module_entry["module_version"] = data["module_version"]
1279
+
1172
1280
  cross_instance_dependencies.append({
1173
- "modules": [{
1174
- "URI": uri,
1175
- "ref_period": "T"
1176
- }],
1281
+ "modules": [module_entry],
1177
1282
  "affected_operations": [operation_code],
1178
1283
  "from_reference_date": str(from_date) if from_date else "",
1179
1284
  "to_reference_date": str(to_date) if to_date else ""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydpm_xl
3
- Version: 0.2.5rc1
3
+ Version: 0.2.5rc3
4
4
  Summary: Python library for DPM-XL data processing and analysis
5
5
  Author-email: "MeaningfulData S.L." <info@meaningfuldata.eu>
6
6
  License: GPL-3.0-or-later
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pydpm_xl"
3
- version = "0.2.5rc1"
3
+ version = "0.2.5rc3"
4
4
  description = "Python library for DPM-XL data processing and analysis"
5
5
  authors = [
6
6
  {name = "MeaningfulData S.L.", email = "info@meaningfuldata.eu"}
@@ -52,7 +52,7 @@ exclude = []
52
52
 
53
53
  [tool.poetry]
54
54
  name = "pydpm_xl"
55
- version = "0.2.5rc1"
55
+ version = "0.2.5rc3"
56
56
  description = "Python library for DPM-XL data processing and analysis"
57
57
  authors = ["MeaningfulData S.L. <info@meaningfuldata.eu>"]
58
58
  readme = "README.md"
File without changes
File without changes
File without changes