informatica-python 1.9.3__py3-none-any.whl → 1.9.4__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.
- informatica_python/__init__.py +1 -1
- informatica_python/generators/mapping_gen.py +25 -6
- informatica_python/utils/expression_converter.py +18 -4
- {informatica_python-1.9.3.dist-info → informatica_python-1.9.4.dist-info}/METADATA +3 -3
- {informatica_python-1.9.3.dist-info → informatica_python-1.9.4.dist-info}/RECORD +9 -9
- {informatica_python-1.9.3.dist-info → informatica_python-1.9.4.dist-info}/WHEEL +0 -0
- {informatica_python-1.9.3.dist-info → informatica_python-1.9.4.dist-info}/entry_points.txt +0 -0
- {informatica_python-1.9.3.dist-info → informatica_python-1.9.4.dist-info}/licenses/LICENSE +0 -0
- {informatica_python-1.9.3.dist-info → informatica_python-1.9.4.dist-info}/top_level.txt +0 -0
informatica_python/__init__.py
CHANGED
|
@@ -757,7 +757,7 @@ def _generate_transformation(lines, tx, connector_graph, source_dfs, transform_m
|
|
|
757
757
|
elif tx_type in ("joiner",):
|
|
758
758
|
_gen_joiner_transform(lines, tx, tx_safe, input_df, input_sources, source_dfs, connector_graph, data_lib)
|
|
759
759
|
elif tx_type in ("lookup procedure", "lookup"):
|
|
760
|
-
_gen_lookup_transform(lines, tx, tx_safe, input_df, source_dfs, data_lib)
|
|
760
|
+
_gen_lookup_transform(lines, tx, tx_safe, input_df, source_dfs, connector_graph, data_lib)
|
|
761
761
|
elif tx_type == "router":
|
|
762
762
|
_gen_router_transform(lines, tx, tx_safe, input_df, source_dfs)
|
|
763
763
|
elif tx_type in ("union",):
|
|
@@ -982,7 +982,7 @@ def _gen_joiner_transform(lines, tx, tx_safe, input_df, input_sources, source_df
|
|
|
982
982
|
source_dfs[tx.name] = f"df_{tx_safe}"
|
|
983
983
|
|
|
984
984
|
|
|
985
|
-
def _gen_lookup_transform(lines, tx, tx_safe, input_df, source_dfs, data_lib="pandas"):
|
|
985
|
+
def _gen_lookup_transform(lines, tx, tx_safe, input_df, source_dfs, connector_graph=None, data_lib="pandas"):
|
|
986
986
|
lookup_table = ""
|
|
987
987
|
lookup_sql = ""
|
|
988
988
|
lookup_condition = ""
|
|
@@ -1012,6 +1012,11 @@ def _gen_lookup_transform(lines, tx, tx_safe, input_df, source_dfs, data_lib="pa
|
|
|
1012
1012
|
|
|
1013
1013
|
all_output_fields = return_fields + lookup_output_fields
|
|
1014
1014
|
|
|
1015
|
+
port_to_col = {}
|
|
1016
|
+
if connector_graph and tx.name in connector_graph.get("to", {}):
|
|
1017
|
+
for conn in connector_graph["to"][tx.name]:
|
|
1018
|
+
port_to_col[conn.to_field.lower()] = conn.from_field
|
|
1019
|
+
|
|
1015
1020
|
lines.append(f" # Lookup: {lookup_table or tx.name}")
|
|
1016
1021
|
if lookup_sql:
|
|
1017
1022
|
_emit_sql_with_params(lines, f"lkp_sql_{tx_safe}", lookup_sql)
|
|
@@ -1020,10 +1025,13 @@ def _gen_lookup_transform(lines, tx, tx_safe, input_df, source_dfs, data_lib="pa
|
|
|
1020
1025
|
lines.append(f" df_lkp_{tx_safe} = read_from_db(config, 'SELECT * FROM {lookup_table}', 'default')")
|
|
1021
1026
|
else:
|
|
1022
1027
|
empty_expr = lib_empty_df(data_lib)
|
|
1023
|
-
lines.append(f" df_lkp_{tx_safe} = {empty_expr}")
|
|
1028
|
+
lines.append(f" df_lkp_{tx_safe} = {empty_expr} # WARNING: no lookup table/SQL override found")
|
|
1024
1029
|
|
|
1025
1030
|
input_keys, lookup_keys = parse_lookup_condition(lookup_condition)
|
|
1026
1031
|
|
|
1032
|
+
if input_keys and port_to_col:
|
|
1033
|
+
input_keys = [port_to_col.get(k.lower(), k) for k in input_keys]
|
|
1034
|
+
|
|
1027
1035
|
if input_keys and lookup_keys:
|
|
1028
1036
|
lines.append(f" # Lookup condition: {lookup_condition}")
|
|
1029
1037
|
|
|
@@ -1078,12 +1086,23 @@ def _gen_router_transform(lines, tx, tx_safe, input_df, source_dfs):
|
|
|
1078
1086
|
if "Group Filter Condition" in attr.name:
|
|
1079
1087
|
group_conditions[attr.name] = attr.value
|
|
1080
1088
|
|
|
1089
|
+
remaining_mask_parts = []
|
|
1081
1090
|
if group_conditions:
|
|
1082
1091
|
for i, (gname, cond) in enumerate(group_conditions.items()):
|
|
1083
|
-
|
|
1084
|
-
|
|
1092
|
+
if cond and cond.strip():
|
|
1093
|
+
expr_py = convert_filter_vectorized(cond, input_df)
|
|
1094
|
+
else:
|
|
1095
|
+
expr_py = f"pd.Series(True, index={input_df}.index)"
|
|
1096
|
+
mask_var = f"_router_mask_{tx_safe}_{i}"
|
|
1097
|
+
lines.append(f" {mask_var} = {expr_py} # {gname}")
|
|
1098
|
+
lines.append(f" df_{tx_safe}_group{i} = {input_df}[{mask_var}].copy()")
|
|
1085
1099
|
source_dfs[f"{tx.name}_group{i}"] = f"df_{tx_safe}_group{i}"
|
|
1086
|
-
|
|
1100
|
+
remaining_mask_parts.append(f"~{mask_var}")
|
|
1101
|
+
if remaining_mask_parts:
|
|
1102
|
+
lines.append(f" _router_default_mask = {' & '.join(remaining_mask_parts)}")
|
|
1103
|
+
lines.append(f" df_{tx_safe} = {input_df}[_router_default_mask].copy() # Default group")
|
|
1104
|
+
else:
|
|
1105
|
+
lines.append(f" df_{tx_safe} = {input_df}.copy() # Default group")
|
|
1087
1106
|
source_dfs[tx.name] = f"df_{tx_safe}"
|
|
1088
1107
|
|
|
1089
1108
|
|
|
@@ -248,6 +248,7 @@ def _convert_infa_date_format(fmt_str):
|
|
|
248
248
|
fmt = fmt.replace("Mon", "%b").replace("MON", "%b")
|
|
249
249
|
fmt = fmt.replace("HH24", "%H").replace("HH12", "%I").replace("HH", "%H")
|
|
250
250
|
fmt = fmt.replace("MI", "%M").replace("SS", "%S")
|
|
251
|
+
fmt = fmt.replace("US", "%f").replace("NS", "%f").replace("MS", "%f")
|
|
251
252
|
return fmt
|
|
252
253
|
|
|
253
254
|
|
|
@@ -548,7 +549,7 @@ def _vec_recursive(expr, df_var):
|
|
|
548
549
|
'RTRIM': f'.str.rstrip("{char_arg}")',
|
|
549
550
|
'TRIM': f'.str.strip("{char_arg}")',
|
|
550
551
|
}
|
|
551
|
-
return f'{inner_val}{method_map[func_name.upper()]}'
|
|
552
|
+
return f'{inner_val}.astype(str){method_map[func_name.upper()]}'
|
|
552
553
|
|
|
553
554
|
upper_result = _find_func_call(cleaned, 'UPPER')
|
|
554
555
|
if upper_result and upper_result[0] == 0 and upper_result[1] == len(cleaned):
|
|
@@ -584,7 +585,7 @@ def _vec_recursive(expr, df_var):
|
|
|
584
585
|
if len(args) >= 2:
|
|
585
586
|
field_val = _vec_recursive(args[0], df_var)
|
|
586
587
|
try:
|
|
587
|
-
start = int(args[1].strip()) - 1
|
|
588
|
+
start = max(int(args[1].strip()) - 1, 0)
|
|
588
589
|
except ValueError:
|
|
589
590
|
start_val = _vec_recursive(args[1], df_var)
|
|
590
591
|
if len(args) >= 3:
|
|
@@ -722,7 +723,11 @@ def _vec_recursive(expr, df_var):
|
|
|
722
723
|
field_val = _vec_recursive(args[0], df_var)
|
|
723
724
|
pattern_val = args[1].strip().strip("'\"")
|
|
724
725
|
if func_name == 'REG_EXTRACT':
|
|
725
|
-
|
|
726
|
+
if re.search(r'(?<!\\)\((?!\?)', pattern_val):
|
|
727
|
+
extract_pat = pattern_val
|
|
728
|
+
else:
|
|
729
|
+
extract_pat = f'({pattern_val})'
|
|
730
|
+
return f'{field_val}.str.extract(r"{extract_pat}", expand=False)'
|
|
726
731
|
elif func_name == 'REG_REPLACE':
|
|
727
732
|
replace_val = args[2].strip().strip("'\"") if len(args) >= 3 else ''
|
|
728
733
|
return f'{field_val}.str.replace(r"{pattern_val}", "{replace_val}", regex=True)'
|
|
@@ -894,7 +899,8 @@ def _vec_recursive(expr, df_var):
|
|
|
894
899
|
'True', 'False', 'None', 'and', 'or', 'not', 'np', 'pd', 'get_variable',
|
|
895
900
|
'str', 'int', 'float', 'bool', 'len', 'abs', 'round',
|
|
896
901
|
'fillna', 'astype', 'isna', 'notna', 'where', 'errors', 'coerce',
|
|
897
|
-
'lookup_func',
|
|
902
|
+
'lookup_func', 'expand', 'extract', 'regex', 'contains', 'replace',
|
|
903
|
+
'upper', 'lower', 'strip', 'lstrip', 'rstrip', 'dt', 'copy',
|
|
898
904
|
}
|
|
899
905
|
converted = _substitute_fields(converted, df_var, skip_words)
|
|
900
906
|
|
|
@@ -904,6 +910,8 @@ def _vec_recursive(expr, df_var):
|
|
|
904
910
|
converted = re.sub(r'<>', '!=', converted)
|
|
905
911
|
converted = re.sub(r'(?<![<>!=])=(?!=)', '==', converted)
|
|
906
912
|
converted = re.sub(r'\berrors\s*==\s*(["\'])', r'errors=\1', converted)
|
|
913
|
+
converted = re.sub(r'\bexpand\s*==\s*', 'expand=', converted)
|
|
914
|
+
converted = re.sub(r'\bregex\s*==\s*', 'regex=', converted)
|
|
907
915
|
|
|
908
916
|
converted = re.sub(r'\s+', ' ', converted).strip()
|
|
909
917
|
|
|
@@ -1044,8 +1052,14 @@ def _vectorize_simple(part, df_var):
|
|
|
1044
1052
|
'True', 'False', 'None', 'and', 'or', 'not', 'np', 'pd',
|
|
1045
1053
|
'str', 'int', 'float', 'isna', 'notna', 'fillna',
|
|
1046
1054
|
'get_variable', 'lookup_func', 'isin', 'eq',
|
|
1055
|
+
'expand', 'extract', 'astype', 'errors', 'coerce', 'regex',
|
|
1056
|
+
'contains', 'replace', 'upper', 'lower', 'strip', 'lstrip', 'rstrip',
|
|
1057
|
+
'dt', 'len', 'copy', 'abs', 'round', 'where', 'bool',
|
|
1047
1058
|
}
|
|
1048
1059
|
c = _substitute_fields(c, df_var, skip_words)
|
|
1060
|
+
c = re.sub(r'\bexpand\s*==\s*', 'expand=', c)
|
|
1061
|
+
c = re.sub(r'\berrors\s*==\s*', 'errors=', c)
|
|
1062
|
+
c = re.sub(r'\bregex\s*==\s*', 'regex=', c)
|
|
1049
1063
|
|
|
1050
1064
|
return c
|
|
1051
1065
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: informatica-python
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.4
|
|
4
4
|
Summary: Convert Informatica PowerCenter workflow XML to Python/PySpark code
|
|
5
5
|
Author: Nick
|
|
6
6
|
License: MIT
|
|
@@ -430,7 +430,7 @@ The generated `helper_functions.py` provides a complete runtime library:
|
|
|
430
430
|
- **Generated code formatting**: Consistent `# ---` section headers for Source Qualifiers, Transforms, and Target Writes; metadata comments (database type, field lists); column mapping and write operation comments; clean blank line handling
|
|
431
431
|
- **Source/target detection**: Case-insensitive instance type matching
|
|
432
432
|
- **Session→mapping inference**: Longest-suffix-match strategy for ambiguous mapping names
|
|
433
|
-
- **
|
|
433
|
+
- **663 tests** across unit, integration, expression, and formatting test suites
|
|
434
434
|
|
|
435
435
|
### v1.9.2 (Phase 8)
|
|
436
436
|
- Mapping output files now use real mapping names (e.g., `mapping_m_customer_load.py`) instead of generic numeric indices (`mapping_1.py`)
|
|
@@ -495,7 +495,7 @@ The generated `helper_functions.py` provides a complete runtime library:
|
|
|
495
495
|
cd informatica_python
|
|
496
496
|
pip install -e ".[dev]"
|
|
497
497
|
|
|
498
|
-
# Run tests (
|
|
498
|
+
# Run tests (663 tests)
|
|
499
499
|
pytest tests/ -v
|
|
500
500
|
```
|
|
501
501
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
informatica_python/__init__.py,sha256=
|
|
1
|
+
informatica_python/__init__.py,sha256=UiVcrgRjgo439mxIWb1Oz1caKLcmgl0DTlz5-GrgKjs,337
|
|
2
2
|
informatica_python/cli.py,sha256=gFwg0O99vKM-OLO0HoHA4emd-6qrgjMNqa9T59e4e_s,2905
|
|
3
3
|
informatica_python/converter.py,sha256=xCuWrYzDji0yN72D3QqOgZCVVM2j3k2_CvlGplCWxLU,22779
|
|
4
4
|
informatica_python/models.py,sha256=G_C2WfQL-ykKjNj23m8vKFtLZYrQozp99HJzrLTKG1Y,17293
|
|
@@ -7,17 +7,17 @@ informatica_python/generators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
|
|
|
7
7
|
informatica_python/generators/config_gen.py,sha256=4tqcNKTB06kyGZIiM4yl0q97q_i3zeCHXTjuE1dNFKY,5726
|
|
8
8
|
informatica_python/generators/error_log_gen.py,sha256=2cc0rEcblydHkb9VAMXlrH7WdSQ-CNqAXcwVk3FYZeM,21319
|
|
9
9
|
informatica_python/generators/helper_gen.py,sha256=D6-UqNh09Qy2V7RimNgP-SzK_uB9YqAlsa0-cgLhf5o,72209
|
|
10
|
-
informatica_python/generators/mapping_gen.py,sha256=
|
|
10
|
+
informatica_python/generators/mapping_gen.py,sha256=TPcd9tIAhOAIZMbzPslUgPvF-FY_XkI7EfvCVf-yU50,71610
|
|
11
11
|
informatica_python/generators/sql_gen.py,sha256=O8Y-aJz9EyFJ0DXeuISRt5yKwC3wlp2K3B0BHrmxrXw,4872
|
|
12
12
|
informatica_python/generators/workflow_gen.py,sha256=_uSlBg31ZRMhMlCYk4hWDRBPaBROrepD8_v3QGEWJxE,18089
|
|
13
13
|
informatica_python/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
informatica_python/utils/datatype_map.py,sha256=iLOYg-iBKT4rMecGbrFkTpJj4yqs5S9HeBOTLUIWhX0,2809
|
|
15
|
-
informatica_python/utils/expression_converter.py,sha256=
|
|
15
|
+
informatica_python/utils/expression_converter.py,sha256=f8sNAhE0Yo8sdcVIPDjrw_uGfd5UTD8k1SN8NYApmhI,46846
|
|
16
16
|
informatica_python/utils/lib_adapters.py,sha256=1ZtuMbgDg9Ukf-OF_EG1L_BeeR-6JQk8Kx3WwMfvNRU,6516
|
|
17
17
|
informatica_python/utils/sql_dialect.py,sha256=_IHJbfu8a3mT_OvHpybgSfZKqz6mwVy5ItTKDRChqnU,5461
|
|
18
|
-
informatica_python-1.9.
|
|
19
|
-
informatica_python-1.9.
|
|
20
|
-
informatica_python-1.9.
|
|
21
|
-
informatica_python-1.9.
|
|
22
|
-
informatica_python-1.9.
|
|
23
|
-
informatica_python-1.9.
|
|
18
|
+
informatica_python-1.9.4.dist-info/licenses/LICENSE,sha256=77RaRDdXgey1D90YZAjXqEQdBxWfvUQqLQX3pC1qjUE,1061
|
|
19
|
+
informatica_python-1.9.4.dist-info/METADATA,sha256=0KXrQZPNvGQB-47LSGQDZv1hm_nN6YWBlhB8WtBCV4I,26097
|
|
20
|
+
informatica_python-1.9.4.dist-info/WHEEL,sha256=PovZm1ExVWmrRefZoXCfejlbKLnQI5SVIf1SWRV4QQI,97
|
|
21
|
+
informatica_python-1.9.4.dist-info/entry_points.txt,sha256=030jjTrx-1oRRQ16HZz52rdcKS8R8_llnymsTUtn_Xc,67
|
|
22
|
+
informatica_python-1.9.4.dist-info/top_level.txt,sha256=Dngg-WNteYi22XAJU2XKAQS8aZ52yM2LYC0tzxrlbVQ,19
|
|
23
|
+
informatica_python-1.9.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|