pydpm_xl 0.1.10__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.
Files changed (94) hide show
  1. py_dpm/AST/ASTConstructor.py +503 -0
  2. py_dpm/AST/ASTObjects.py +827 -0
  3. py_dpm/AST/ASTTemplate.py +101 -0
  4. py_dpm/AST/ASTVisitor.py +13 -0
  5. py_dpm/AST/MLGeneration.py +588 -0
  6. py_dpm/AST/ModuleAnalyzer.py +79 -0
  7. py_dpm/AST/ModuleDependencies.py +203 -0
  8. py_dpm/AST/WhereClauseChecker.py +12 -0
  9. py_dpm/AST/__init__.py +0 -0
  10. py_dpm/AST/check_operands.py +302 -0
  11. py_dpm/DataTypes/ScalarTypes.py +324 -0
  12. py_dpm/DataTypes/TimeClasses.py +370 -0
  13. py_dpm/DataTypes/TypePromotion.py +195 -0
  14. py_dpm/DataTypes/__init__.py +0 -0
  15. py_dpm/Exceptions/__init__.py +0 -0
  16. py_dpm/Exceptions/exceptions.py +84 -0
  17. py_dpm/Exceptions/messages.py +114 -0
  18. py_dpm/OperationScopes/OperationScopeService.py +247 -0
  19. py_dpm/OperationScopes/__init__.py +0 -0
  20. py_dpm/Operators/AggregateOperators.py +138 -0
  21. py_dpm/Operators/BooleanOperators.py +30 -0
  22. py_dpm/Operators/ClauseOperators.py +159 -0
  23. py_dpm/Operators/ComparisonOperators.py +69 -0
  24. py_dpm/Operators/ConditionalOperators.py +362 -0
  25. py_dpm/Operators/NumericOperators.py +101 -0
  26. py_dpm/Operators/Operator.py +388 -0
  27. py_dpm/Operators/StringOperators.py +27 -0
  28. py_dpm/Operators/TimeOperators.py +53 -0
  29. py_dpm/Operators/__init__.py +0 -0
  30. py_dpm/Utils/ValidationsGenerationUtils.py +429 -0
  31. py_dpm/Utils/__init__.py +0 -0
  32. py_dpm/Utils/operands_mapping.py +73 -0
  33. py_dpm/Utils/operator_mapping.py +89 -0
  34. py_dpm/Utils/tokens.py +172 -0
  35. py_dpm/Utils/utils.py +2 -0
  36. py_dpm/ValidationsGeneration/PropertiesConstraintsProcessor.py +190 -0
  37. py_dpm/ValidationsGeneration/Utils.py +364 -0
  38. py_dpm/ValidationsGeneration/VariantsProcessor.py +265 -0
  39. py_dpm/ValidationsGeneration/__init__.py +0 -0
  40. py_dpm/ValidationsGeneration/auxiliary_functions.py +98 -0
  41. py_dpm/__init__.py +61 -0
  42. py_dpm/api/__init__.py +140 -0
  43. py_dpm/api/ast_generator.py +438 -0
  44. py_dpm/api/complete_ast.py +241 -0
  45. py_dpm/api/data_dictionary_validation.py +577 -0
  46. py_dpm/api/migration.py +77 -0
  47. py_dpm/api/semantic.py +224 -0
  48. py_dpm/api/syntax.py +182 -0
  49. py_dpm/client.py +106 -0
  50. py_dpm/data_handlers.py +99 -0
  51. py_dpm/db_utils.py +117 -0
  52. py_dpm/grammar/__init__.py +0 -0
  53. py_dpm/grammar/dist/__init__.py +0 -0
  54. py_dpm/grammar/dist/dpm_xlLexer.interp +428 -0
  55. py_dpm/grammar/dist/dpm_xlLexer.py +804 -0
  56. py_dpm/grammar/dist/dpm_xlLexer.tokens +106 -0
  57. py_dpm/grammar/dist/dpm_xlParser.interp +249 -0
  58. py_dpm/grammar/dist/dpm_xlParser.py +5224 -0
  59. py_dpm/grammar/dist/dpm_xlParser.tokens +106 -0
  60. py_dpm/grammar/dist/dpm_xlParserListener.py +742 -0
  61. py_dpm/grammar/dist/dpm_xlParserVisitor.py +419 -0
  62. py_dpm/grammar/dist/listeners.py +10 -0
  63. py_dpm/grammar/dpm_xlLexer.g4 +435 -0
  64. py_dpm/grammar/dpm_xlParser.g4 +260 -0
  65. py_dpm/migration.py +282 -0
  66. py_dpm/models.py +2139 -0
  67. py_dpm/semantics/DAG/DAGAnalyzer.py +158 -0
  68. py_dpm/semantics/DAG/__init__.py +0 -0
  69. py_dpm/semantics/SemanticAnalyzer.py +320 -0
  70. py_dpm/semantics/Symbols.py +223 -0
  71. py_dpm/semantics/__init__.py +0 -0
  72. py_dpm/utils/__init__.py +0 -0
  73. py_dpm/utils/ast_serialization.py +481 -0
  74. py_dpm/views/data_types.sql +12 -0
  75. py_dpm/views/datapoints.sql +65 -0
  76. py_dpm/views/hierarchy_operand_reference.sql +11 -0
  77. py_dpm/views/hierarchy_preconditions.sql +13 -0
  78. py_dpm/views/hierarchy_variables.sql +26 -0
  79. py_dpm/views/hierarchy_variables_context.sql +14 -0
  80. py_dpm/views/key_components.sql +18 -0
  81. py_dpm/views/module_from_table.sql +11 -0
  82. py_dpm/views/open_keys.sql +13 -0
  83. py_dpm/views/operation_info.sql +27 -0
  84. py_dpm/views/operation_list.sql +18 -0
  85. py_dpm/views/operations_versions_from_module_version.sql +30 -0
  86. py_dpm/views/precondition_info.sql +17 -0
  87. py_dpm/views/report_type_operand_reference_info.sql +18 -0
  88. py_dpm/views/subcategory_info.sql +17 -0
  89. py_dpm/views/table_info.sql +19 -0
  90. pydpm_xl-0.1.10.dist-info/LICENSE +674 -0
  91. pydpm_xl-0.1.10.dist-info/METADATA +50 -0
  92. pydpm_xl-0.1.10.dist-info/RECORD +94 -0
  93. pydpm_xl-0.1.10.dist-info/WHEEL +4 -0
  94. pydpm_xl-0.1.10.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,98 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+ from py_dpm.Utils.ValidationsGenerationUtils import ValidationsGenerationUtils
5
+ from py_dpm.Utils.tokens import *
6
+
7
+
8
+ def generate_context_structure(lst: list, group_df: pd.DataFrame):
9
+ """
10
+ Method to generate the structure of the contexts of variables in order to generate the hierarchy validations
11
+ :param lst: list to store the structure of contexts
12
+ :param group_df: Dataframe with information about properties and items of variables
13
+ """
14
+ group_df.set_index(CONTEXT_PROPERTY, inplace=True)
15
+ result = group_df.to_dict()[CONTEXT_ITEM]
16
+ result[VARIABLE_VID] = group_df[VARIABLE_VID].tolist()[0]
17
+ result[VARIABLE_PROPERTY_ID] = group_df[VARIABLE_PROPERTY_ID].tolist()[0]
18
+
19
+ lst.append(result)
20
+
21
+
22
+ def generate_subexpression(common_values, data, table, operator:str=None):
23
+ """
24
+ Method to generate the subexpression of a hierarchy expression
25
+ :param common_values: dictionary with information about the common components and their values
26
+ :param data: variable datapoints
27
+ :param table: table code
28
+ """
29
+ abs_value = True if operator and operator != '=' else False
30
+ if ROW_CODE in common_values:
31
+ rows = None
32
+ else:
33
+ rows = ROW + data[ROW_CODE].iloc[0] if data[ROW_CODE].iloc[0] else None
34
+
35
+ if COLUMN_CODE in common_values:
36
+ cols = None
37
+ else:
38
+ cols = COLUMN + data[COLUMN_CODE].iloc[0] if data[COLUMN_CODE].iloc[0] else None
39
+
40
+ if SHEET_CODE in common_values:
41
+ sheets = None
42
+ else:
43
+ sheets = SHEET + data[SHEET_CODE].iloc[0] if data[SHEET_CODE].iloc[0] else None
44
+
45
+ if abs_value:
46
+ expr = ValidationsGenerationUtils.write_cell(table, rows, cols, sheets)
47
+ return 'abs(' + expr + ')'
48
+
49
+ return ValidationsGenerationUtils.write_cell(table, rows, cols, sheets)
50
+
51
+
52
+ def get_common_components(left_data: pd.DataFrame, right_data: pd.DataFrame):
53
+ """
54
+ Method to get the common components of expression operands
55
+ :param left_data: Dataframe corresponding to the data of the left operand
56
+ :param right_data: Dataframe corresponding to the data of the right side operands
57
+ """
58
+ common_components = {}
59
+ for component in CELL_COMPONENTS:
60
+ left = left_data[component].dropna().tolist()
61
+ right = right_data[component].isnull().values.any()
62
+ if left and not right:
63
+ intersection_component = np.intersect1d(left_data[component], right_data[component])
64
+ if len(intersection_component):
65
+ if all(right_data[component].isin(intersection_component)):
66
+ common_components[component] = intersection_component
67
+ return common_components
68
+
69
+
70
+ def group_hierarchy_right_data(right_data: pd.DataFrame, left_table: str, common_components: list, comparisson_operator:str=None):
71
+ """
72
+ Method to group right side operands
73
+ :param right_data: Dataframe with the datapoints of the right side of expression
74
+ :param left_table: Table code of left operand
75
+ :param common_components: List with the common components of right and left operands
76
+ """
77
+ right_table = right_data[TABLE_CODE].tolist()[0]
78
+ is_table_unique = left_table == right_table
79
+ right_operands_lst = []
80
+ right_table_cell = right_table if not is_table_unique else None
81
+ # Here we have to add the order of the items in the expression
82
+ order_dict = {}
83
+ for keys, group in right_data.groupby([ARITHMETIC_OPERATOR_SYMBOL, ITEM_ID]):
84
+ operand = generate_subexpression(common_components, group, right_table_cell,comparisson_operator)
85
+ operand = keys[0] + operand
86
+ if ORDER in group:
87
+ order_dict[group[ORDER].tolist()[0]] = operand
88
+ else:
89
+ order_dict[group[ORDER + '_x'].tolist()[0]] = operand
90
+
91
+ right_operands_lst = [order_dict[order] for order in sorted(order_dict)]
92
+
93
+ right_expression = ' '.join(right_operands_lst)
94
+ if DUPLICATE_VARIABLES not in right_data:
95
+ right_data[DUPLICATE_VARIABLES] = False
96
+ duplicate_variables = right_data[DUPLICATE_VARIABLES].any()
97
+ right_items = right_data[ITEM_ID].unique().tolist()
98
+ return [right_expression, right_table, duplicate_variables,right_items]
py_dpm/__init__.py ADDED
@@ -0,0 +1,61 @@
1
+ """
2
+ PyDPM - Python Data Processing and Migration
3
+ ============================================
4
+
5
+ A Python library for DPM-XL data processing, migration, and analysis.
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
19
+
20
+ Main Features:
21
+ - Database migration from Access to SQLite
22
+ - DPM-XL syntax validation and parsing
23
+ - DPM-XL semantic analysis
24
+
25
+ Quick Start:
26
+ >>> import pydpm
27
+ >>>
28
+ >>> # Migration
29
+ >>> migration = pydpm.api.MigrationAPI()
30
+ >>> engine = migration.migrate_access_to_sqlite("data.mdb", "output.db")
31
+ >>>
32
+ >>> # Syntax validation
33
+ >>> syntax = pydpm.api.SyntaxAPI()
34
+ >>> result = syntax.validate_expression("{tC_01.00, r0100, c0010}")
35
+ >>>
36
+ >>> # Semantic analysis
37
+ >>> semantic = pydpm.api.SemanticAPI()
38
+ >>> result = semantic.validate_expression("{tC_01.00, r0100, c0010}")
39
+
40
+ Available packages:
41
+ - pydpm.api: Main APIs for migration, syntax, and semantic analysis
42
+ """
43
+
44
+ __version__ = "0.1.10"
45
+ __author__ = "MeaningfulData S.L."
46
+ __email__ = "info@meaningfuldata.eu"
47
+ __license__ = "GPL-3.0-or-later"
48
+
49
+ # Import main API modules for convenient access
50
+ from py_dpm import api
51
+
52
+ # Import main classes for direct usage
53
+ from py_dpm.api import MigrationAPI, SyntaxAPI, SemanticAPI
54
+
55
+ __all__ = [
56
+ 'api',
57
+ 'MigrationAPI',
58
+ 'SyntaxAPI',
59
+ 'SemanticAPI',
60
+ '__version__'
61
+ ]
py_dpm/api/__init__.py ADDED
@@ -0,0 +1,140 @@
1
+ from py_dpm.api.migration import MigrationAPI
2
+ from py_dpm.api.syntax import SyntaxAPI
3
+ from py_dpm.api.semantic import SemanticAPI
4
+ from py_dpm.api.ast_generator import ASTGenerator, parse_expression, validate_expression, parse_batch
5
+ from py_dpm.api.complete_ast import generate_complete_ast, generate_complete_batch
6
+
7
+ from antlr4 import CommonTokenStream, InputStream
8
+
9
+ from py_dpm.grammar.dist.dpm_xlLexer import dpm_xlLexer
10
+ from py_dpm.grammar.dist.dpm_xlParser import dpm_xlParser
11
+ from py_dpm.grammar.dist.listeners import DPMErrorListener
12
+ from py_dpm.AST.ASTConstructor import ASTVisitor
13
+ from py_dpm.AST.ASTObjects import TemporaryAssignment
14
+ from py_dpm.AST.MLGeneration import MLGeneration
15
+ from py_dpm.AST.ModuleAnalyzer import ModuleAnalyzer
16
+ from py_dpm.AST.ModuleDependencies import ModuleDependencies
17
+ from py_dpm.AST.check_operands import OperandsChecking
18
+ from py_dpm.semantics import SemanticAnalyzer
19
+
20
+ from py_dpm.ValidationsGeneration.VariantsProcessor import (
21
+ VariantsProcessor,
22
+ VariantsProcessorChecker,
23
+ )
24
+ from py_dpm.ValidationsGeneration.PropertiesConstraintsProcessor import (
25
+ PropertiesConstraintsChecker,
26
+ PropertiesConstraintsProcessor,
27
+ )
28
+
29
+ from py_dpm.db_utils import get_session, get_engine
30
+
31
+ # Export the main API classes
32
+ __all__ = [
33
+ # Complete AST API (recommended - includes data fields)
34
+ 'generate_complete_ast',
35
+ 'generate_complete_batch',
36
+
37
+ # Simple AST API
38
+ 'ASTGenerator',
39
+ 'parse_expression',
40
+ 'validate_expression',
41
+ 'parse_batch',
42
+
43
+ # Advanced APIs
44
+ 'MigrationAPI',
45
+ 'SyntaxAPI',
46
+ 'SemanticAPI',
47
+ 'API' # Keep for backward compatibility
48
+ ]
49
+
50
+
51
+ class API:
52
+ error_listener = DPMErrorListener()
53
+ visitor = ASTVisitor()
54
+
55
+ def __init__(self):
56
+ get_engine()
57
+ self.session = get_session()
58
+
59
+ @classmethod
60
+ def lexer(cls, text: str):
61
+ """
62
+ Extracts the tokens from the input expression
63
+ :param text: Expression to be analyzed
64
+ """
65
+ lexer = dpm_xlLexer(InputStream(text))
66
+ lexer._listeners = [cls.error_listener]
67
+ cls.stream = CommonTokenStream(lexer)
68
+
69
+ @classmethod
70
+ def parser(cls):
71
+ """
72
+ Parses the token from the lexer stream
73
+ """
74
+ parser = dpm_xlParser(cls.stream)
75
+ parser._listeners = [cls.error_listener]
76
+ cls.CST = parser.start()
77
+
78
+ if parser._syntaxErrors == 0:
79
+ return True
80
+
81
+ @classmethod
82
+ def syntax_validation(cls, expression):
83
+ """
84
+ Validates that the input expression is syntactically correct by applying the ANTLR lexer and parser
85
+ :param expression: Expression to be analyzed
86
+ """
87
+ cls.lexer(expression)
88
+ cls.parser()
89
+
90
+ @classmethod
91
+ def create_ast(cls, expression):
92
+ """
93
+ Generates the AST from the expression
94
+ :param expression: Expression to be analyzed
95
+ """
96
+ cls.lexer(expression)
97
+ if cls.parser():
98
+ cls.visitor = ASTVisitor()
99
+ cls.AST = cls.visitor.visit(cls.CST)
100
+
101
+ def semantic_validation(self, expression):
102
+ self.create_ast(expression=expression)
103
+
104
+ oc = OperandsChecking(session=self.session, expression=expression, ast=self.AST, release_id=None)
105
+ semanticAnalysis = SemanticAnalyzer.InputAnalyzer(expression)
106
+
107
+ semanticAnalysis.data = oc.data
108
+ semanticAnalysis.key_components = oc.key_components
109
+ semanticAnalysis.open_keys = oc.open_keys
110
+
111
+ semanticAnalysis.preconditions = oc.preconditions
112
+
113
+ results = semanticAnalysis.visit(self.AST)
114
+ return results
115
+
116
+ def _check_property_constraints(self, ast):
117
+ """
118
+ Method to check property constraints
119
+ :return: Boolean value indicating if the ast has property constraints
120
+ """
121
+ pcc = PropertiesConstraintsChecker(ast=ast, session=self.session)
122
+ return pcc.is_property_constraint
123
+
124
+ def _check_property_constraints_from_expression(self, expression):
125
+ """
126
+ Method to check property constraints
127
+ :return: Boolean value indicating if the ast has property constraints
128
+ """
129
+ self.create_ast(expression=expression)
130
+ pcc = PropertiesConstraintsChecker(ast=self.AST, session=self.session)
131
+ return pcc.is_property_constraint
132
+
133
+ def _check_variants(self, expression):
134
+ """
135
+ Method to check table groups
136
+ :return: Boolean value indicating if the ast has table groups
137
+ """
138
+ self.create_ast(expression=expression)
139
+ tgc = VariantsProcessorChecker(ast=self.AST)
140
+ return tgc.is_variant