pydpm_xl 0.2.1__tar.gz → 0.2.2__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 (103) hide show
  1. {pydpm_xl-0.2.1/pydpm_xl.egg-info → pydpm_xl-0.2.2}/PKG-INFO +1 -1
  2. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/__init__.py +1 -1
  3. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm/queries/tables.py +24 -4
  4. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/ast/operands.py +3 -3
  5. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2/pydpm_xl.egg-info}/PKG-INFO +1 -1
  6. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/pydpm_xl.egg-info/SOURCES.txt +1 -0
  7. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/pyproject.toml +2 -2
  8. pydpm_xl-0.2.2/tests/test_release_filters_semantic.py +108 -0
  9. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/LICENSE +0 -0
  10. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/README.md +0 -0
  11. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/__init__.py +0 -0
  12. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/dpm/__init__.py +0 -0
  13. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/dpm/data_dictionary.py +0 -0
  14. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/dpm/explorer.py +0 -0
  15. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/dpm/hierarchical_queries.py +0 -0
  16. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/dpm/migration.py +0 -0
  17. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/dpm/operation_scopes.py +0 -0
  18. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/dpm_xl/__init__.py +0 -0
  19. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/dpm_xl/ast_generator.py +0 -0
  20. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/dpm_xl/complete_ast.py +0 -0
  21. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/dpm_xl/semantic.py +0 -0
  22. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/dpm_xl/syntax.py +0 -0
  23. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/explorer.py +0 -0
  24. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/api/semantic.py +0 -0
  25. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/cli/__init__.py +0 -0
  26. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/cli/commands/__init__.py +0 -0
  27. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/cli/main.py +0 -0
  28. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm/__init__.py +0 -0
  29. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm/migration.py +0 -0
  30. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm/models.py +0 -0
  31. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm/queries/base.py +0 -0
  32. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm/queries/basic_objects.py +0 -0
  33. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm/queries/explorer_queries.py +0 -0
  34. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm/queries/filters.py +0 -0
  35. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm/queries/glossary.py +0 -0
  36. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm/queries/hierarchical_queries.py +0 -0
  37. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm/utils.py +0 -0
  38. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/__init__.py +0 -0
  39. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/ast/__init__.py +0 -0
  40. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/ast/constructor.py +0 -0
  41. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/ast/ml_generation.py +0 -0
  42. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/ast/module_analyzer.py +0 -0
  43. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/ast/module_dependencies.py +0 -0
  44. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/ast/nodes.py +0 -0
  45. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/ast/template.py +0 -0
  46. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/ast/visitor.py +0 -0
  47. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/ast/where_clause.py +0 -0
  48. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/grammar/__init__.py +0 -0
  49. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/grammar/generated/__init__.py +0 -0
  50. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/grammar/generated/dpm_xlLexer.interp +0 -0
  51. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/grammar/generated/dpm_xlLexer.py +0 -0
  52. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/grammar/generated/dpm_xlLexer.tokens +0 -0
  53. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/grammar/generated/dpm_xlParser.interp +0 -0
  54. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/grammar/generated/dpm_xlParser.py +0 -0
  55. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/grammar/generated/dpm_xlParser.tokens +0 -0
  56. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/grammar/generated/dpm_xlParserListener.py +0 -0
  57. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/grammar/generated/dpm_xlParserVisitor.py +0 -0
  58. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/grammar/generated/listeners.py +0 -0
  59. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/operators/__init__.py +0 -0
  60. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/operators/aggregate.py +0 -0
  61. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/operators/arithmetic.py +0 -0
  62. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/operators/base.py +0 -0
  63. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/operators/boolean.py +0 -0
  64. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/operators/clause.py +0 -0
  65. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/operators/comparison.py +0 -0
  66. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/operators/conditional.py +0 -0
  67. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/operators/string.py +0 -0
  68. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/operators/time.py +0 -0
  69. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/semantic_analyzer.py +0 -0
  70. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/symbols.py +0 -0
  71. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/types/__init__.py +0 -0
  72. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/types/promotion.py +0 -0
  73. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/types/scalar.py +0 -0
  74. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/types/time.py +0 -0
  75. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/utils/__init__.py +0 -0
  76. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/utils/data_handlers.py +0 -0
  77. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/utils/operands_mapping.py +0 -0
  78. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/utils/operator_mapping.py +0 -0
  79. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/utils/scopes_calculator.py +0 -0
  80. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/utils/serialization.py +0 -0
  81. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/utils/tokens.py +0 -0
  82. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/validation/__init__.py +0 -0
  83. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/validation/generation_utils.py +0 -0
  84. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/validation/property_constraints.py +0 -0
  85. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/validation/utils.py +0 -0
  86. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/dpm_xl/validation/variants.py +0 -0
  87. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/exceptions/__init__.py +0 -0
  88. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/exceptions/exceptions.py +0 -0
  89. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/py_dpm/exceptions/messages.py +0 -0
  90. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/pydpm_xl.egg-info/dependency_links.txt +0 -0
  91. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/pydpm_xl.egg-info/entry_points.txt +0 -0
  92. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/pydpm_xl.egg-info/requires.txt +0 -0
  93. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/pydpm_xl.egg-info/top_level.txt +0 -0
  94. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/setup.cfg +0 -0
  95. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/tests/test_cli_semantic.py +0 -0
  96. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/tests/test_data_dictionary_releases.py +0 -0
  97. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/tests/test_db_connection_handling.py +0 -0
  98. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/tests/test_get_table_details.py +0 -0
  99. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/tests/test_get_tables_date_filter.py +0 -0
  100. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/tests/test_get_tables_release_code.py +0 -0
  101. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/tests/test_hierarchical_query.py +0 -0
  102. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/tests/test_query_refactor.py +0 -0
  103. {pydpm_xl-0.2.1 → pydpm_xl-0.2.2}/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.1
3
+ Version: 0.2.2
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.1"
44
+ __version__ = "0.2.2"
45
45
  __author__ = "MeaningfulData S.L."
46
46
  __email__ = "info@meaningfuldata.eu"
47
47
  __license__ = "GPL-3.0-or-later"
@@ -74,7 +74,12 @@ class TableQuery:
74
74
  subq.c.table_code.isnot(None)
75
75
  )
76
76
 
77
- q = filter_by_release(q, release_id, subq.c.start_release, subq.c.end_release)
77
+ q = filter_by_release(
78
+ q,
79
+ start_col=subq.c.start_release,
80
+ end_col=subq.c.end_release,
81
+ release_id=release_id,
82
+ )
78
83
  q = q.order_by(subq.c.table_code)
79
84
 
80
85
  return BaseQuery(session, q)
@@ -91,7 +96,12 @@ class TableQuery:
91
96
  subq.c.table_code == table_code, subq.c.row_code.isnot(None)
92
97
  )
93
98
 
94
- q = filter_by_release(q, release_id, subq.c.start_release, subq.c.end_release)
99
+ q = filter_by_release(
100
+ q,
101
+ start_col=subq.c.start_release,
102
+ end_col=subq.c.end_release,
103
+ release_id=release_id,
104
+ )
95
105
  q = q.order_by(subq.c.row_code)
96
106
 
97
107
  return BaseQuery(session, q)
@@ -108,7 +118,12 @@ class TableQuery:
108
118
  subq.c.table_code == table_code, subq.c.column_code.isnot(None)
109
119
  )
110
120
 
111
- q = filter_by_release(q, release_id, subq.c.start_release, subq.c.end_release)
121
+ q = filter_by_release(
122
+ q,
123
+ start_col=subq.c.start_release,
124
+ end_col=subq.c.end_release,
125
+ release_id=release_id,
126
+ )
112
127
  q = q.order_by(subq.c.column_code)
113
128
 
114
129
  return BaseQuery(session, q)
@@ -127,7 +142,12 @@ class TableQuery:
127
142
  subq.c.sheet_code != "",
128
143
  )
129
144
 
130
- q = filter_by_release(q, release_id, subq.c.start_release, subq.c.end_release)
145
+ q = filter_by_release(
146
+ q,
147
+ start_col=subq.c.start_release,
148
+ end_col=subq.c.end_release,
149
+ release_id=release_id,
150
+ )
131
151
  q = q.order_by(subq.c.sheet_code)
132
152
 
133
153
  return BaseQuery(session, q)
@@ -208,9 +208,9 @@ class OperandsChecking(ASTTemplate, ABC):
208
208
  # Apply release filter
209
209
  query = filter_by_release(
210
210
  query,
211
- self.release_id,
212
- TableVersion.startreleaseid,
213
- TableVersion.endreleaseid,
211
+ start_col=TableVersion.startreleaseid,
212
+ end_col=TableVersion.endreleaseid,
213
+ release_id=self.release_id,
214
214
  )
215
215
 
216
216
  # Execute query and convert to DataFrame
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydpm_xl
3
- Version: 0.2.1
3
+ Version: 0.2.2
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
@@ -97,4 +97,5 @@ tests/test_get_tables_date_filter.py
97
97
  tests/test_get_tables_release_code.py
98
98
  tests/test_hierarchical_query.py
99
99
  tests/test_query_refactor.py
100
+ tests/test_release_filters_semantic.py
100
101
  tests/test_semantic_release.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pydpm_xl"
3
- version = "0.2.1"
3
+ version = "0.2.2"
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.1"
55
+ version = "0.2.2"
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"
@@ -0,0 +1,108 @@
1
+ import pandas as pd
2
+ from sqlalchemy import create_engine
3
+ from sqlalchemy.orm import sessionmaker
4
+
5
+ from py_dpm.dpm.models import Base, TableVersion
6
+ from py_dpm.dpm.queries.filters import filter_by_release
7
+ from py_dpm.dpm_xl.ast import operands as operands_module
8
+
9
+
10
+ def _make_session():
11
+ """Create a lightweight in-memory SQLAlchemy session for query compilation."""
12
+ engine = create_engine("sqlite:///:memory:")
13
+ Base.metadata.bind = engine
14
+ Session = sessionmaker(bind=engine)
15
+ return Session()
16
+
17
+
18
+ def test_filter_by_release_uses_is_null_for_end_release():
19
+ """
20
+ Ensure filter_by_release uses SQLAlchemy .is_(None) semantics for end_col,
21
+ resulting in an 'IS NULL' predicate rather than '= NULL' in the SQL.
22
+
23
+ This is important for PostgreSQL, which is strict about boolean expressions
24
+ and NULL comparison semantics.
25
+ """
26
+ session = _make_session()
27
+
28
+ query = session.query(TableVersion)
29
+ filtered = filter_by_release(
30
+ query,
31
+ start_col=TableVersion.startreleaseid,
32
+ end_col=TableVersion.endreleaseid,
33
+ release_id=5,
34
+ )
35
+
36
+ sql = str(
37
+ filtered.statement.compile(
38
+ dialect=session.get_bind().dialect, compile_kwargs={"literal_binds": True}
39
+ )
40
+ ).upper()
41
+
42
+ # Ensure NULL handling uses IS NULL rather than = NULL
43
+ assert "IS NULL" in sql
44
+ assert "= NULL" not in sql
45
+
46
+
47
+ def test_operands_check_headers_calls_filter_by_release_with_correct_args(monkeypatch):
48
+ """
49
+ Verify that OperandsChecking.check_headers wires filter_by_release correctly:
50
+ - start_col is TableVersion.startreleaseid
51
+ - end_col is TableVersion.endreleaseid
52
+ - release_id matches the instance's release_id
53
+ """
54
+ called = {}
55
+
56
+ def fake_filter_by_release(query, start_col, end_col, release_id=None, release_code=None):
57
+ called["query"] = query
58
+ called["start_col"] = start_col
59
+ called["end_col"] = end_col
60
+ called["release_id"] = release_id
61
+ called["release_code"] = release_code
62
+ return query
63
+
64
+ monkeypatch.setattr(operands_module, "filter_by_release", fake_filter_by_release)
65
+
66
+ # Stub out the pandas helpers used inside check_headers so that no real DB
67
+ # access is attempted.
68
+ import py_dpm.dpm.models as models
69
+
70
+ monkeypatch.setattr(
71
+ models,
72
+ "_compile_query_for_pandas",
73
+ lambda stmt, session: stmt,
74
+ )
75
+
76
+ def fake_read_sql(sql, session):
77
+ # Return an empty DataFrame with the expected columns so that
78
+ # check_headers completes without touching self.operands.
79
+ return pd.DataFrame(
80
+ columns=[
81
+ "Code",
82
+ "StartReleaseID",
83
+ "EndReleaseID",
84
+ "Direction",
85
+ "HasOpenRows",
86
+ "HasOpenColumns",
87
+ "HasOpenSheets",
88
+ ]
89
+ )
90
+
91
+ monkeypatch.setattr(models, "_read_sql_with_connection", fake_read_sql)
92
+
93
+ session = _make_session()
94
+
95
+ # Create a minimal OperandsChecking instance without running its __init__,
96
+ # since that would require a fully-populated AST and database.
97
+ oc = object.__new__(operands_module.OperandsChecking)
98
+ oc.session = session
99
+ oc.release_id = 7
100
+ oc.tables = {"DummyTable": {}} # Only keys are needed by check_headers
101
+
102
+ operands_module.OperandsChecking.check_headers(oc)
103
+
104
+ assert called["start_col"] is TableVersion.startreleaseid
105
+ assert called["end_col"] is TableVersion.endreleaseid
106
+ assert called["release_id"] == 7
107
+ assert called["release_code"] is None
108
+
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes