pydpm_xl 0.2.2__py3-none-any.whl → 0.2.3__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,98 +0,0 @@
1
- import numpy as np
2
- import pandas as pd
3
-
4
- from py_dpm.dpm_xl.validation.generation_utils import ValidationsGenerationUtils
5
- from py_dpm.dpm_xl.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]
@@ -1,359 +0,0 @@
1
- import copy
2
- import re
3
-
4
- import pandas as pd
5
-
6
- from py_dpm.dpm_xl.ast.nodes import VarID, WithExpression
7
- from py_dpm.dpm_xl.ast.template import ASTTemplate
8
- from py_dpm.exceptions import exceptions
9
- from py_dpm.dpm.models import (
10
- ModuleVersionComposition,
11
- TableGroup,
12
- TableGroupComposition,
13
- TableVersion,
14
- ViewDatapoints,
15
- )
16
- from py_dpm.dpm_xl.utils.tokens import (
17
- EXPRESSION,
18
- STATUS,
19
- STATUS_CORRECT,
20
- STATUS_INCOMPLETE,
21
- STATUS_INCORRECT,
22
- VALIDATION_CODE,
23
- )
24
- from py_dpm.dpm_xl.utils.data_handlers import filter_all_data
25
-
26
- cell_components = ["table", "rows", "cols", "sheets"]
27
- TABLE_ID = "TableID"
28
- MODULE_VID = "ModuleVID"
29
- TABLE_CODE = "Code"
30
- GROUP = "group"
31
- MODULE_VERSION_ID = "module_version_id"
32
- MODULE_CODE = "module_code"
33
-
34
-
35
- class VariantsProcessorChecker(ASTTemplate):
36
- def __init__(self, ast):
37
- super().__init__()
38
- self._is_variant = False
39
- self.visit(ast)
40
-
41
- @property
42
- def is_variant(self):
43
- return self._is_variant
44
-
45
- def visit_VarID(self, node: VarID):
46
- if node.is_table_group:
47
- self._is_variant = True
48
-
49
-
50
- class VariantsProcessor(ASTTemplate):
51
- """
52
- Class to generate individual validations from a validation defined on groups.
53
-
54
- :parameter expression: DPM-XL expression.
55
- :parameter ast: Abstract Syntax Tree of expression.
56
- :parameter session: SQLAlchemy Session to be used to connect to the DB.
57
- :parameter validation_code: Code of parent validation.
58
- """
59
-
60
- def __init__(self, expression, ast, session, validation_code, release_id):
61
- super().__init__()
62
- self.expression = expression
63
- self.AST = ast
64
- self.session = session
65
- self.validation_code = validation_code
66
- self.current_validation = 1
67
- self.partial_selection = None
68
- self.release_id = release_id
69
-
70
- self.table_data = {}
71
- self.group_tables = []
72
- self.table_groups_compositions = {}
73
- self.tables_without_cells = []
74
- self.children_suffix = None
75
- self.equal_children_suffix = True
76
-
77
- self.visit(self.AST)
78
-
79
- def check_if_table_has_cells(self, table_code, rows, cols, sheets):
80
- """
81
- Method to check if an individual table has cells for rows, columns and sheets of validation.
82
- :param table_code: code of table.
83
- :param rows: rows.
84
- :param cols: columns.
85
- :param sheets: sheets.
86
- :return: True if table has cells, False otherwise.
87
- """
88
- if table_code not in self.table_data:
89
- datapoints = ViewDatapoints.get_table_data(
90
- session=self.session, table=table_code, release_id=self.release_id
91
- )
92
- self.table_data[table_code] = datapoints
93
- else:
94
- datapoints = self.table_data[table_code]
95
- data = filter_all_data(
96
- data=datapoints, table_code=table_code, rows=rows, cols=cols, sheets=sheets
97
- )
98
- return not data.empty
99
-
100
- def check_table_from_module(self, node, table_module_id, is_abstract):
101
- """
102
- Method to get table_versions of a table group when there are cells for those tables.
103
- :param node: var_id node
104
- :param table_module_id: module id
105
- :param is_abstract: flag that represents if table is abstract
106
- :return: table version if table version has cells, None otherwise.
107
- """
108
-
109
- table_versions = TableVersion.get_tables_versions_of_table_group_compositions(
110
- session=self.session,
111
- table_id=table_module_id,
112
- is_abstract=is_abstract,
113
- release_id=self.release_id,
114
- )
115
-
116
- for table_version in table_versions:
117
- table_with_cells = self.check_if_table_has_cells(
118
- table_version.Code, node.rows, node.cols, node.sheets
119
- )
120
- if table_with_cells:
121
- return table_version
122
- else:
123
- if table_version.TableID not in self.tables_without_cells:
124
- self.tables_without_cells.append(table_version.TableID)
125
- return None
126
-
127
- def generate_child_expression(self, group_code, table_code):
128
- """
129
- Method to replace group_code by table_code in order to generate new validations.
130
- :param group_code: Group code.
131
- :param table_code: Table code.
132
- """
133
- groups = re.search("(" + re.escape(group_code) + "[^.$]" + ")", self.expression)
134
- if f"g{group_code}" in self.expression and groups:
135
- group = groups.group(0)
136
- suffix = table_code[-(len(table_code) - len(group_code)) :]
137
- if group:
138
- if not self.children_suffix:
139
- self.children_suffix = suffix
140
- else:
141
- if self.children_suffix != suffix:
142
- self.equal_children_suffix = False
143
- return
144
- self.expression = re.sub(
145
- re.escape(f"g{group_code}") + "[^.$]",
146
- f"t{table_code}" + group[-1],
147
- self.expression,
148
- )
149
-
150
- def generate_child_expressions(self):
151
- """
152
- Method to generate all the individual validations.
153
- :return: Expressions and expressions with errors.
154
- """
155
- if self.group_tables:
156
- final_expressions = []
157
- final_expressions_with_errors = []
158
- df_tables = pd.DataFrame.from_records(self.group_tables)
159
- df_tables = df_tables[~df_tables[TABLE_ID].isin(self.tables_without_cells)]
160
- df_tables.drop_duplicates(inplace=True)
161
-
162
- table_ids = df_tables[TABLE_ID].tolist()
163
- modules_df = ModuleVersionComposition.get_modules_from_table_ids(
164
- session=self.session, table_ids=table_ids, release_id=self.release_id
165
- )
166
-
167
- data = pd.merge(df_tables, modules_df, on=[TABLE_ID])
168
-
169
- expression = copy.deepcopy(self.expression)
170
- for module, modules_tables in data.groupby(MODULE_VID):
171
- modules_tables.apply(
172
- lambda x: self.generate_child_expression(x[GROUP], x[TABLE_CODE]),
173
- axis=1,
174
- )
175
- module_code = modules_tables[MODULE_CODE].unique().tolist()[0]
176
- if len(modules_tables) < len(self.table_groups_compositions):
177
- final_expressions_with_errors.append(
178
- {
179
- EXPRESSION: self.expression,
180
- MODULE_VERSION_ID: module,
181
- MODULE_CODE: module_code,
182
- }
183
- )
184
- else:
185
- if self.equal_children_suffix:
186
- final_expressions.append(
187
- {
188
- EXPRESSION: self.expression,
189
- MODULE_VERSION_ID: module,
190
- MODULE_CODE: module_code,
191
- }
192
- )
193
- else:
194
- final_expressions_with_errors.append(
195
- {
196
- EXPRESSION: self.expression,
197
- MODULE_VERSION_ID: module,
198
- MODULE_CODE: module_code,
199
- }
200
- )
201
- self.equal_children_suffix = True
202
- self.expression = copy.deepcopy(expression)
203
- self.children_suffix = None
204
-
205
- return final_expressions, final_expressions_with_errors
206
- else:
207
- raise exceptions.SemanticError("5-2-1")
208
-
209
- def create_validation(self, expression_info, status):
210
- """
211
- Method to centralize creation of validations given expression and status of new validation
212
- :param expression_info: Dictionary with information about expression, module_vid and module_code of validation
213
- :param status: Status of validation
214
- :return: Validation with code, expression and status
215
- """
216
-
217
- validation_code = (
218
- self.generate_child_validation_code() if status == STATUS_CORRECT else None
219
- )
220
-
221
- validation = {
222
- VALIDATION_CODE: validation_code,
223
- EXPRESSION: expression_info[EXPRESSION],
224
- STATUS: status,
225
- MODULE_VERSION_ID: expression_info[MODULE_VERSION_ID],
226
- MODULE_CODE: expression_info[MODULE_CODE],
227
- }
228
- return validation
229
-
230
- def create_validation_new_format(self, expressions_dict):
231
- """
232
- Method to centralize creation of validations given expression and status of new validation
233
- :param expression_info: Dictionary with information about expression, module_vid and module_code of validation
234
- :param status: Status of validation
235
- :return: Validation with code, expression and status
236
- """
237
-
238
- correct_expressions = expressions_dict[STATUS_CORRECT]
239
- incomplete_expressions = expressions_dict[STATUS_INCOMPLETE]
240
- incorrect_expressions = expressions_dict[STATUS_INCORRECT]
241
- unique_correct_expressions = (
242
- pd.DataFrame.from_records(correct_expressions)["expression"]
243
- .unique()
244
- .tolist()
245
- if correct_expressions
246
- else []
247
- )
248
- unique_incomplete_expressions = (
249
- pd.DataFrame.from_records(incomplete_expressions)["expression"]
250
- .unique()
251
- .tolist()
252
- if incomplete_expressions
253
- else []
254
- )
255
- unique_incorrect_expressions = (
256
- pd.DataFrame.from_records(incorrect_expressions)["expression"]
257
- .unique()
258
- .tolist()
259
- if incorrect_expressions
260
- else []
261
- )
262
- validations = []
263
- if correct_expressions:
264
- v = self._aux_create_validation_new_format(
265
- correct_expressions, unique_correct_expressions, STATUS_CORRECT
266
- )
267
- validations.extend(v)
268
- if incomplete_expressions:
269
- v = self._aux_create_validation_new_format(
270
- incomplete_expressions, unique_incomplete_expressions, STATUS_INCOMPLETE
271
- )
272
- validations.extend(v)
273
- if incorrect_expressions:
274
- v = self._aux_create_validation_new_format(
275
- incorrect_expressions, unique_incorrect_expressions, STATUS_INCORRECT
276
- )
277
- validations.extend(v)
278
-
279
- return validations
280
-
281
- def _aux_create_validation_new_format(
282
- self, expressions, unique_expressions, status
283
- ):
284
- validations = []
285
- for expr in unique_expressions:
286
- aux = {}
287
- aux[EXPRESSION] = expr
288
- aux[STATUS] = status
289
- if status == STATUS_CORRECT:
290
- aux[VALIDATION_CODE] = self.generate_child_validation_code()
291
- else:
292
- aux[VALIDATION_CODE] = None
293
- aux["scopes"] = []
294
- for elto in expressions:
295
- if elto[EXPRESSION] == aux[EXPRESSION]:
296
- aux["scopes"].append(
297
- {
298
- "module_versions_ids": [elto[MODULE_VERSION_ID]],
299
- "module_code": elto[MODULE_CODE],
300
- }
301
- )
302
- validations.append(aux)
303
- return validations
304
-
305
- def generate_child_validation_code(self):
306
- """
307
- Method to calculate validation codes for new validations.
308
- :return: New code for the individual validation.
309
- """
310
- child_code = f"{self.validation_code}-{self.current_validation}"
311
- self.current_validation += 1
312
- return child_code
313
-
314
- def visit_WithExpression(self, node: WithExpression):
315
- self.partial_selection = node.partial_selection
316
- self.visit(node.partial_selection)
317
- self.visit(node.expression)
318
-
319
- def visit_VarID(self, node: VarID):
320
- if self.partial_selection:
321
- for attribute in cell_components:
322
- if not getattr(node, attribute, False) and hasattr(
323
- self.partial_selection, attribute
324
- ):
325
- setattr(node, attribute, getattr(self.partial_selection, attribute))
326
-
327
- if node.is_table_group or self.partial_selection.is_table_group:
328
- if node.table:
329
- if node.table not in self.table_groups_compositions:
330
- group: TableGroup = TableGroup.get_group_from_code(
331
- session=self.session, group_code=node.table
332
- )
333
- if not group:
334
- raise exceptions.SemanticError("1-6", table_group=node.table)
335
- table_groups_compositions = (
336
- TableGroupComposition.get_from_parent_table_code(
337
- code=node.table, session=self.session
338
- )
339
- )
340
- self.table_groups_compositions[node.table] = (
341
- table_groups_compositions
342
- )
343
- else:
344
- table_groups_compositions = self.table_groups_compositions[
345
- node.table
346
- ]
347
-
348
- for table_id, is_abstract in table_groups_compositions:
349
- table_version = self.check_table_from_module(
350
- node, table_id, is_abstract
351
- )
352
- if table_version:
353
- self.group_tables.append(
354
- {
355
- GROUP: node.table,
356
- TABLE_CODE: table_version.Code,
357
- TABLE_ID: table_version.TableID,
358
- }
359
- )