informatica-python 1.9.0__tar.gz → 1.9.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.
- {informatica_python-1.9.0 → informatica_python-1.9.2}/PKG-INFO +7 -1
- {informatica_python-1.9.0 → informatica_python-1.9.2}/README.md +6 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/__init__.py +1 -1
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/generators/helper_gen.py +11 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/generators/mapping_gen.py +36 -24
- informatica_python-1.9.2/informatica_python/utils/expression_converter.py +946 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python.egg-info/PKG-INFO +7 -1
- {informatica_python-1.9.0 → informatica_python-1.9.2}/pyproject.toml +1 -1
- {informatica_python-1.9.0 → informatica_python-1.9.2}/tests/test_integration.py +75 -0
- informatica_python-1.9.0/informatica_python/utils/expression_converter.py +0 -481
- {informatica_python-1.9.0 → informatica_python-1.9.2}/LICENSE +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/cli.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/converter.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/generators/__init__.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/generators/config_gen.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/generators/error_log_gen.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/generators/sql_gen.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/generators/workflow_gen.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/models.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/parser.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/utils/__init__.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/utils/datatype_map.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/utils/lib_adapters.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/utils/sql_dialect.py +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python.egg-info/SOURCES.txt +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python.egg-info/dependency_links.txt +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python.egg-info/entry_points.txt +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python.egg-info/requires.txt +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python.egg-info/top_level.txt +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/setup.cfg +0 -0
- {informatica_python-1.9.0 → informatica_python-1.9.2}/tests/test_converter.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: informatica-python
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.2
|
|
4
4
|
Summary: Convert Informatica PowerCenter workflow XML to Python/PySpark code
|
|
5
5
|
Author: Nick
|
|
6
6
|
License: MIT
|
|
@@ -307,6 +307,12 @@ Converts Informatica expressions to Python equivalents:
|
|
|
307
307
|
### v1.9.x (Phase 8)
|
|
308
308
|
- Mapping output files now use real mapping names (e.g., `mapping_m_customer_load.py`) instead of generic numeric indices (`mapping_1.py`)
|
|
309
309
|
- Workflow imports automatically match the named mapping files
|
|
310
|
+
- **Expression converter rewrite**: Recursive parenthesis-aware parser replacing simple regex; fixes nested IIF/INSTR/LTRIM/RTRIM/REPLACECHR/REPLACESTR/SUBSTR/TO_CHAR/CHR/MAKE_DATE_TIME
|
|
311
|
+
- **`:LKP.` references** now properly converted to `lookup_func()` calls in vectorized mode
|
|
312
|
+
- **String literal safety**: `||` concatenation no longer applies `.astype(str)` to string literals
|
|
313
|
+
- **NULL/TRUE/FALSE**: Correctly resolved as `None`/`True`/`False` before field-name substitution
|
|
314
|
+
- **`import pandas as pd`** and `from datetime import datetime` now included in generated mapping files
|
|
315
|
+
- **MSSQL connection fallbacks**: `pymssql` and `sqlalchemy` tried when `pyodbc` unavailable
|
|
310
316
|
|
|
311
317
|
### v1.8.x (Phase 7)
|
|
312
318
|
- Row-count logging at every pipeline step (source reads, transforms, target writes)
|
|
@@ -280,6 +280,12 @@ Converts Informatica expressions to Python equivalents:
|
|
|
280
280
|
### v1.9.x (Phase 8)
|
|
281
281
|
- Mapping output files now use real mapping names (e.g., `mapping_m_customer_load.py`) instead of generic numeric indices (`mapping_1.py`)
|
|
282
282
|
- Workflow imports automatically match the named mapping files
|
|
283
|
+
- **Expression converter rewrite**: Recursive parenthesis-aware parser replacing simple regex; fixes nested IIF/INSTR/LTRIM/RTRIM/REPLACECHR/REPLACESTR/SUBSTR/TO_CHAR/CHR/MAKE_DATE_TIME
|
|
284
|
+
- **`:LKP.` references** now properly converted to `lookup_func()` calls in vectorized mode
|
|
285
|
+
- **String literal safety**: `||` concatenation no longer applies `.astype(str)` to string literals
|
|
286
|
+
- **NULL/TRUE/FALSE**: Correctly resolved as `None`/`True`/`False` before field-name substitution
|
|
287
|
+
- **`import pandas as pd`** and `from datetime import datetime` now included in generated mapping files
|
|
288
|
+
- **MSSQL connection fallbacks**: `pymssql` and `sqlalchemy` tried when `pyodbc` unavailable
|
|
283
289
|
|
|
284
290
|
### v1.8.x (Phase 7)
|
|
285
291
|
- Row-count logging at every pipeline step (source reads, transforms, target writes)
|
{informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/generators/helper_gen.py
RENAMED
|
@@ -151,6 +151,17 @@ def _add_db_functions(lines, data_lib):
|
|
|
151
151
|
lines.append(" return pyodbc.connect(conn_str)")
|
|
152
152
|
lines.append(" except ImportError:")
|
|
153
153
|
lines.append(" pass")
|
|
154
|
+
lines.append(" try:")
|
|
155
|
+
lines.append(" import pymssql")
|
|
156
|
+
lines.append(" return pymssql.connect(server=host, port=int(port), database=database, user=username, password=password)")
|
|
157
|
+
lines.append(" except ImportError:")
|
|
158
|
+
lines.append(" pass")
|
|
159
|
+
lines.append(" try:")
|
|
160
|
+
lines.append(" from sqlalchemy import create_engine")
|
|
161
|
+
lines.append(" engine = create_engine(f'mssql+pymssql://{username}:{password}@{host}:{port}/{database}')")
|
|
162
|
+
lines.append(" return engine.connect()")
|
|
163
|
+
lines.append(" except ImportError:")
|
|
164
|
+
lines.append(" pass")
|
|
154
165
|
lines.append("")
|
|
155
166
|
lines.append(" if db_type == 'postgresql':")
|
|
156
167
|
lines.append(" try:")
|
{informatica_python-1.9.0 → informatica_python-1.9.2}/informatica_python/generators/mapping_gen.py
RENAMED
|
@@ -227,6 +227,8 @@ def generate_mapping_code(mapping: MappingDef, folder: FolderDef,
|
|
|
227
227
|
lines.append("")
|
|
228
228
|
lines.append("import logging")
|
|
229
229
|
lines.append("import numpy as np")
|
|
230
|
+
lines.append("import pandas as pd")
|
|
231
|
+
lines.append("from datetime import datetime")
|
|
230
232
|
lines.append("from helper_functions import *")
|
|
231
233
|
lines.append("")
|
|
232
234
|
lines.append("logger = logging.getLogger(__name__)")
|
|
@@ -601,8 +603,19 @@ def _generate_source_qualifier(lines, sq, source_map, source_dfs, connector_grap
|
|
|
601
603
|
lines.append(f" execute_sql(config, '''{pre_sql}''')")
|
|
602
604
|
lines.append("")
|
|
603
605
|
|
|
604
|
-
if
|
|
605
|
-
|
|
606
|
+
if not connected_sources:
|
|
607
|
+
sq_src_name = sq.name[3:] if sq.name.upper().startswith("SQ_") else sq.name
|
|
608
|
+
if sql_override:
|
|
609
|
+
lines.append(f" sql_{sq_safe} = '''")
|
|
610
|
+
for sql_line in sql_override.strip().split("\n"):
|
|
611
|
+
lines.append(f" {sql_line}")
|
|
612
|
+
lines.append(f" '''")
|
|
613
|
+
lines.append(f" df_{sq_safe} = read_from_db(config, sql_{sq_safe}, 'default')")
|
|
614
|
+
else:
|
|
615
|
+
lines.append(f" df_{sq_safe} = read_file(config.get('sources', {{}}).get('{sq_src_name}', {{}}).get('file_path', '{sq_src_name}'),")
|
|
616
|
+
lines.append(f" config.get('sources', {{}}).get('{sq_src_name}', {{}}))")
|
|
617
|
+
elif sql_override:
|
|
618
|
+
src_name = next(iter(connected_sources))
|
|
606
619
|
src_def = source_map.get(src_name, SourceDef(name=src_name))
|
|
607
620
|
sq_override = (session_overrides or {}).get(sq.name, {}) or (session_overrides or {}).get(src_name, {})
|
|
608
621
|
conn_name = sq_override.get("connection_name") or (_safe_name(src_def.db_name) if src_def.db_name else "default")
|
|
@@ -612,36 +625,35 @@ def _generate_source_qualifier(lines, sq, source_map, source_dfs, connector_grap
|
|
|
612
625
|
lines.append(f" {sql_line}")
|
|
613
626
|
lines.append(f" '''")
|
|
614
627
|
lines.append(f" df_{sq_safe} = read_from_db(config, sql_{sq_safe}, '{conn_name}')")
|
|
628
|
+
elif len(connected_sources) == 1:
|
|
629
|
+
src_name = next(iter(connected_sources))
|
|
630
|
+
src_def = source_map.get(src_name, SourceDef(name=src_name))
|
|
631
|
+
safe_src = _safe_name(src_name)
|
|
632
|
+
src_override = (session_overrides or {}).get(sq.name, {}) or (session_overrides or {}).get(src_name, {})
|
|
633
|
+
if src_def.database_type and src_def.database_type != "Flat File":
|
|
634
|
+
conn_name = src_override.get("connection_name") or (_safe_name(src_def.db_name) if src_def.db_name else "default")
|
|
635
|
+
schema = src_def.owner_name or "dbo"
|
|
636
|
+
cols = ", ".join(f.name for f in src_def.fields) if src_def.fields else "*"
|
|
637
|
+
lines.append(f" df_{sq_safe} = read_from_db(config, 'SELECT {cols} FROM {schema}.{src_def.name}', '{conn_name}')")
|
|
638
|
+
elif src_def.flatfile:
|
|
639
|
+
_emit_flatfile_read(lines, sq_safe, src_def)
|
|
640
|
+
else:
|
|
641
|
+
lines.append(f" df_{sq_safe} = read_file(config.get('sources', {{}}).get('{src_def.name}', {{}}).get('file_path', '{src_def.name}'),")
|
|
642
|
+
lines.append(f" config.get('sources', {{}}).get('{src_def.name}', {{}}))")
|
|
615
643
|
else:
|
|
616
|
-
|
|
617
|
-
src_name = next(iter(connected_sources))
|
|
644
|
+
for src_name in connected_sources:
|
|
618
645
|
src_def = source_map.get(src_name, SourceDef(name=src_name))
|
|
619
646
|
safe_src = _safe_name(src_name)
|
|
620
|
-
src_override = (session_overrides or {}).get(sq.name, {}) or (session_overrides or {}).get(src_name, {})
|
|
621
647
|
if src_def.database_type and src_def.database_type != "Flat File":
|
|
622
|
-
conn_name =
|
|
648
|
+
conn_name = _safe_name(src_def.db_name) if src_def.db_name else "default"
|
|
623
649
|
schema = src_def.owner_name or "dbo"
|
|
624
|
-
|
|
625
|
-
lines.append(f" df_{sq_safe} = read_from_db(config, 'SELECT {cols} FROM {schema}.{src_def.name}', '{conn_name}')")
|
|
650
|
+
lines.append(f" df_{safe_src} = read_from_db(config, 'SELECT * FROM {schema}.{src_def.name}', '{conn_name}')")
|
|
626
651
|
elif src_def.flatfile:
|
|
627
|
-
_emit_flatfile_read(lines,
|
|
652
|
+
_emit_flatfile_read(lines, safe_src, src_def)
|
|
628
653
|
else:
|
|
629
|
-
lines.append(f" df_{
|
|
654
|
+
lines.append(f" df_{safe_src} = read_file(config.get('sources', {{}}).get('{src_def.name}', {{}}).get('file_path', '{src_def.name}'),")
|
|
630
655
|
lines.append(f" config.get('sources', {{}}).get('{src_def.name}', {{}}))")
|
|
631
|
-
|
|
632
|
-
for src_name in connected_sources:
|
|
633
|
-
src_def = source_map.get(src_name, SourceDef(name=src_name))
|
|
634
|
-
safe_src = _safe_name(src_name)
|
|
635
|
-
if src_def.database_type and src_def.database_type != "Flat File":
|
|
636
|
-
conn_name = _safe_name(src_def.db_name) if src_def.db_name else "default"
|
|
637
|
-
schema = src_def.owner_name or "dbo"
|
|
638
|
-
lines.append(f" df_{safe_src} = read_from_db(config, 'SELECT * FROM {schema}.{src_def.name}', '{conn_name}')")
|
|
639
|
-
elif src_def.flatfile:
|
|
640
|
-
_emit_flatfile_read(lines, safe_src, src_def)
|
|
641
|
-
else:
|
|
642
|
-
lines.append(f" df_{safe_src} = read_file(config.get('sources', {{}}).get('{src_def.name}', {{}}).get('file_path', '{src_def.name}'),")
|
|
643
|
-
lines.append(f" config.get('sources', {{}}).get('{src_def.name}', {{}}))")
|
|
644
|
-
lines.append(f" df_{sq_safe} = df_{_safe_name(next(iter(connected_sources)))}")
|
|
656
|
+
lines.append(f" df_{sq_safe} = df_{_safe_name(next(iter(connected_sources)))}")
|
|
645
657
|
|
|
646
658
|
source_dfs[sq.name] = f"df_{sq_safe}"
|
|
647
659
|
lines.append(f" try:")
|