informatica-python 1.7.0__tar.gz → 1.7.1__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.
- {informatica_python-1.7.0 → informatica_python-1.7.1}/PKG-INFO +1 -1
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/__init__.py +1 -1
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/helper_gen.py +6 -3
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/mapping_gen.py +20 -2
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python.egg-info/PKG-INFO +1 -1
- {informatica_python-1.7.0 → informatica_python-1.7.1}/pyproject.toml +1 -1
- {informatica_python-1.7.0 → informatica_python-1.7.1}/tests/test_integration.py +30 -2
- {informatica_python-1.7.0 → informatica_python-1.7.1}/LICENSE +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/README.md +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/cli.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/converter.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/__init__.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/config_gen.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/error_log_gen.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/sql_gen.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/workflow_gen.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/models.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/parser.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/utils/__init__.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/utils/datatype_map.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/utils/expression_converter.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/utils/lib_adapters.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/utils/sql_dialect.py +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python.egg-info/SOURCES.txt +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python.egg-info/dependency_links.txt +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python.egg-info/entry_points.txt +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python.egg-info/requires.txt +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python.egg-info/top_level.txt +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/setup.cfg +0 -0
- {informatica_python-1.7.0 → informatica_python-1.7.1}/tests/test_converter.py +0 -0
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/helper_gen.py
RENAMED
|
@@ -1278,6 +1278,9 @@ def _add_update_strategy_functions(lines):
|
|
|
1278
1278
|
lines.append(" key_columns = data_cols[:1]")
|
|
1279
1279
|
lines.append(" logger.warning(f'No key columns specified for update strategy — using first column: {key_columns}')")
|
|
1280
1280
|
lines.append("")
|
|
1281
|
+
lines.append(" db_type = conn_config.get('type', 'mssql')")
|
|
1282
|
+
lines.append(" ph = '?' if db_type == 'mssql' else '%s'")
|
|
1283
|
+
lines.append("")
|
|
1281
1284
|
lines.append(" try:")
|
|
1282
1285
|
lines.append(" cursor = conn.cursor()")
|
|
1283
1286
|
lines.append("")
|
|
@@ -1295,8 +1298,8 @@ def _add_update_strategy_functions(lines):
|
|
|
1295
1298
|
lines.append("")
|
|
1296
1299
|
lines.append(" if len(df_update) > 0:")
|
|
1297
1300
|
lines.append(" non_key_cols = [c for c in data_cols if c not in key_columns]")
|
|
1298
|
-
lines.append(" set_clause = ', '.join(f'{c} =
|
|
1299
|
-
lines.append(" where_clause = ' AND '.join(f'{c} =
|
|
1301
|
+
lines.append(" set_clause = ', '.join(f'{c} = {ph}' for c in non_key_cols)")
|
|
1302
|
+
lines.append(" where_clause = ' AND '.join(f'{c} = {ph}' for c in key_columns)")
|
|
1300
1303
|
lines.append(" update_sql = f'UPDATE {qualified_table} SET {set_clause} WHERE {where_clause}'")
|
|
1301
1304
|
lines.append(" logger.info(f'Updating {len(df_update)} rows in {qualified_table}')")
|
|
1302
1305
|
lines.append(" for _, row in df_update.iterrows():")
|
|
@@ -1304,7 +1307,7 @@ def _add_update_strategy_functions(lines):
|
|
|
1304
1307
|
lines.append(" cursor.execute(update_sql, values)")
|
|
1305
1308
|
lines.append("")
|
|
1306
1309
|
lines.append(" if len(df_delete) > 0:")
|
|
1307
|
-
lines.append(" where_clause = ' AND '.join(f'{c} =
|
|
1310
|
+
lines.append(" where_clause = ' AND '.join(f'{c} = {ph}' for c in key_columns)")
|
|
1308
1311
|
lines.append(" delete_sql = f'DELETE FROM {qualified_table} WHERE {where_clause}'")
|
|
1309
1312
|
lines.append(" logger.info(f'Deleting {len(df_delete)} rows from {qualified_table}')")
|
|
1310
1313
|
lines.append(" for _, row in df_delete.iterrows():")
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/mapping_gen.py
RENAMED
|
@@ -253,7 +253,15 @@ def generate_mapping_code(mapping: MappingDef, folder: FolderDef,
|
|
|
253
253
|
lines.append(f" start_time = log_mapping_start('{mapping.name}')")
|
|
254
254
|
lines.append("")
|
|
255
255
|
|
|
256
|
-
has_persistent_vars =
|
|
256
|
+
has_persistent_vars = any(
|
|
257
|
+
getattr(v, 'is_persistent', 'NO').upper() == 'YES'
|
|
258
|
+
for v in (mapping.variables or [])
|
|
259
|
+
)
|
|
260
|
+
if has_persistent_vars:
|
|
261
|
+
lines.append(" # Load persistent state for mapping variables")
|
|
262
|
+
lines.append(" load_persistent_state()")
|
|
263
|
+
lines.append("")
|
|
264
|
+
|
|
257
265
|
if mapping.variables:
|
|
258
266
|
lines.append(" # Mapping Variables")
|
|
259
267
|
for var in mapping.variables:
|
|
@@ -318,6 +326,14 @@ def generate_mapping_code(mapping: MappingDef, folder: FolderDef,
|
|
|
318
326
|
for tgt_name, tgt_def in target_map.items():
|
|
319
327
|
_generate_target_write(lines, tgt_name, tgt_def, connector_graph, source_dfs, transform_map, instance_map, session_overrides, validate_casts=validate_casts)
|
|
320
328
|
|
|
329
|
+
if has_persistent_vars:
|
|
330
|
+
lines.append(" # Save persistent mapping variables")
|
|
331
|
+
for var in mapping.variables:
|
|
332
|
+
if getattr(var, 'is_persistent', 'NO').upper() == 'YES':
|
|
333
|
+
safe_var = _safe_name(var.name.replace("$$", ""))
|
|
334
|
+
lines.append(f" set_persistent_variable('{mapping.name}', '{safe_var}', {safe_var})")
|
|
335
|
+
lines.append(" save_persistent_state()")
|
|
336
|
+
|
|
321
337
|
lines.append("")
|
|
322
338
|
lines.append(f" log_mapping_end('{mapping.name}', start_time)")
|
|
323
339
|
lines.append(f" logger.info('Mapping {mapping.name} completed successfully')")
|
|
@@ -1230,7 +1246,7 @@ def _gen_stored_proc(lines, tx, tx_safe, input_df, source_dfs):
|
|
|
1230
1246
|
lines.append(f" # Stored Procedure: {proc_name or tx.name}")
|
|
1231
1247
|
|
|
1232
1248
|
if input_params:
|
|
1233
|
-
param_dict_items = ", ".join(f"'{p}': {input_df}['{p}'].iloc[0] if '{p}' in {input_df}.columns else None" for p in input_params)
|
|
1249
|
+
param_dict_items = ", ".join(f"'{p}': {input_df}['{p}'].iloc[0] if '{p}' in {input_df}.columns and len({input_df}) > 0 else None" for p in input_params)
|
|
1234
1250
|
lines.append(f" _sp_params_{tx_safe} = {{{param_dict_items}}}")
|
|
1235
1251
|
else:
|
|
1236
1252
|
lines.append(f" _sp_params_{tx_safe} = {{}}")
|
|
@@ -1304,6 +1320,8 @@ def _generate_target_write(lines, tgt_name, tgt_def, connector_graph, source_dfs
|
|
|
1304
1320
|
target_cols = [f.name for f in tgt_def.fields] if tgt_def.fields else None
|
|
1305
1321
|
if target_cols:
|
|
1306
1322
|
lines.append(f" available_cols = [c for c in {target_cols} if c in df_target_{tgt_safe}.columns]")
|
|
1323
|
+
lines.append(f" if '_update_strategy' in df_target_{tgt_safe}.columns and '_update_strategy' not in available_cols:")
|
|
1324
|
+
lines.append(f" available_cols.append('_update_strategy')")
|
|
1307
1325
|
lines.append(f" df_target_{tgt_safe} = df_target_{tgt_safe}[available_cols]")
|
|
1308
1326
|
else:
|
|
1309
1327
|
lines.append(f" df_target_{tgt_safe} = {input_df}")
|
|
@@ -946,6 +946,31 @@ class TestUpdateStrategy:
|
|
|
946
946
|
assert "write_to_db" in code
|
|
947
947
|
assert "_update_strategy" in code
|
|
948
948
|
|
|
949
|
+
def test_update_strategy_preserved_through_projection(self):
|
|
950
|
+
from informatica_python.models import TargetDef, FieldDef
|
|
951
|
+
from informatica_python.generators.mapping_gen import _generate_target_write
|
|
952
|
+
tgt = TargetDef(name="TGT_DB", database_type="Oracle",
|
|
953
|
+
fields=[FieldDef(name="ID", datatype="integer"),
|
|
954
|
+
FieldDef(name="VAL", datatype="string")])
|
|
955
|
+
lines = []
|
|
956
|
+
source_dfs = {"SRC": "df_src"}
|
|
957
|
+
from informatica_python.models import ConnectorDef
|
|
958
|
+
conns = [ConnectorDef(from_instance="SRC", to_instance="TGT_DB",
|
|
959
|
+
from_instance_type="", to_instance_type="",
|
|
960
|
+
from_field="ID", to_field="ID")]
|
|
961
|
+
connector_graph = {"to": {"TGT_DB": conns}, "from": {"SRC": conns}}
|
|
962
|
+
_generate_target_write(lines, "TGT_DB", tgt, connector_graph, source_dfs, {}, {})
|
|
963
|
+
code = "\n".join(lines)
|
|
964
|
+
assert "_update_strategy" in code
|
|
965
|
+
assert "available_cols.append('_update_strategy')" in code
|
|
966
|
+
|
|
967
|
+
def test_update_strategy_dialect_aware_placeholders(self):
|
|
968
|
+
from informatica_python.models import FolderDef
|
|
969
|
+
from informatica_python.generators.helper_gen import generate_helper_functions
|
|
970
|
+
folder = FolderDef(name="TestFolder")
|
|
971
|
+
code = generate_helper_functions(folder)
|
|
972
|
+
assert "ph = '?' if db_type == 'mssql' else '%s'" in code
|
|
973
|
+
|
|
949
974
|
def test_update_strategy_helper_generated(self):
|
|
950
975
|
from informatica_python.models import FolderDef
|
|
951
976
|
from informatica_python.generators.helper_gen import generate_helper_functions
|
|
@@ -1064,8 +1089,8 @@ class TestStatePersistence:
|
|
|
1064
1089
|
default_value="''", is_persistent="NO")])
|
|
1065
1090
|
folder = FolderDef(name="TestFolder", workflows=[wf])
|
|
1066
1091
|
code = generate_workflow_code(folder)
|
|
1067
|
-
assert "load_persistent_state" not in code
|
|
1068
|
-
assert "save_persistent_state" not in code
|
|
1092
|
+
assert "load_persistent_state()" not in code
|
|
1093
|
+
assert "save_persistent_state()" not in code
|
|
1069
1094
|
|
|
1070
1095
|
def test_mapping_persistent_variables(self):
|
|
1071
1096
|
from informatica_python.models import (
|
|
@@ -1091,6 +1116,9 @@ class TestStatePersistence:
|
|
|
1091
1116
|
code = generate_mapping_code(mapping, folder, "pandas", 1)
|
|
1092
1117
|
assert "get_persistent_variable('m_persist_test', 'last_id'" in code
|
|
1093
1118
|
assert "temp = ''" in code
|
|
1119
|
+
assert "load_persistent_state()" in code
|
|
1120
|
+
assert "set_persistent_variable('m_persist_test', 'last_id'" in code
|
|
1121
|
+
assert "save_persistent_state()" in code
|
|
1094
1122
|
|
|
1095
1123
|
def test_workflow_persistent_imports(self):
|
|
1096
1124
|
from informatica_python.models import FolderDef, WorkflowDef, WorkflowVariable
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/__init__.py
RENAMED
|
File without changes
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/config_gen.py
RENAMED
|
File without changes
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/error_log_gen.py
RENAMED
|
File without changes
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/sql_gen.py
RENAMED
|
File without changes
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/generators/workflow_gen.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/utils/datatype_map.py
RENAMED
|
File without changes
|
|
File without changes
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/utils/lib_adapters.py
RENAMED
|
File without changes
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python/utils/sql_dialect.py
RENAMED
|
File without changes
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python.egg-info/requires.txt
RENAMED
|
File without changes
|
{informatica_python-1.7.0 → informatica_python-1.7.1}/informatica_python.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|