From bbce45dbe5b8fe85d8ce7c397059a33c279e9218 Mon Sep 17 00:00:00 2001 From: Carsten Kvist Date: Thu, 2 Apr 2026 13:12:25 +0200 Subject: [PATCH] Init --- udpak_semistruktur/.env.example | 10 +++ udpak_semistruktur/.gitignore | 34 +++++++ udpak_semistruktur/README.md | 89 +++++++++++++++++++ udpak_semistruktur/requirements.txt | 16 ++++ udpak_semistruktur/tests/__init__.py | 0 udpak_semistruktur/udpak_semistruktur.py | 0 .../udpak_semistruktur/__init__.py | 0 .../udpak_semistruktur/config.py | 0 udpak_semistruktur/udpak_semistruktur/db.py | 0 udpak_semistruktur/udpak_semistruktur/ddl.py | 0 .../udpak_semistruktur/extract/__init__.py | 0 .../udpak_semistruktur/extract/reader.py | 0 .../udpak_semistruktur/extract/traversal.py | 0 .../udpak_semistruktur/load/__init__.py | 0 .../udpak_semistruktur/load/db_writer.py | 0 .../udpak_semistruktur/load/file_writer.py | 0 .../udpak_semistruktur/transform/__init__.py | 0 .../udpak_semistruktur/transform/clean.py | 0 .../udpak_semistruktur/transform/convert.py | 0 .../udpak_semistruktur/transform/reshape.py | 0 .../udpak_semistruktur/utils.py | 0 21 files changed, 149 insertions(+) create mode 100644 udpak_semistruktur/.env.example create mode 100644 udpak_semistruktur/.gitignore create mode 100644 udpak_semistruktur/README.md create mode 100644 udpak_semistruktur/requirements.txt create mode 100644 udpak_semistruktur/tests/__init__.py create mode 100644 udpak_semistruktur/udpak_semistruktur.py create mode 100644 udpak_semistruktur/udpak_semistruktur/__init__.py create mode 100644 udpak_semistruktur/udpak_semistruktur/config.py create mode 100644 udpak_semistruktur/udpak_semistruktur/db.py create mode 100644 udpak_semistruktur/udpak_semistruktur/ddl.py create mode 100644 udpak_semistruktur/udpak_semistruktur/extract/__init__.py create mode 100644 udpak_semistruktur/udpak_semistruktur/extract/reader.py create mode 100644 udpak_semistruktur/udpak_semistruktur/extract/traversal.py create mode 100644 udpak_semistruktur/udpak_semistruktur/load/__init__.py create mode 100644 udpak_semistruktur/udpak_semistruktur/load/db_writer.py create mode 100644 udpak_semistruktur/udpak_semistruktur/load/file_writer.py create mode 100644 udpak_semistruktur/udpak_semistruktur/transform/__init__.py create mode 100644 udpak_semistruktur/udpak_semistruktur/transform/clean.py create mode 100644 udpak_semistruktur/udpak_semistruktur/transform/convert.py create mode 100644 udpak_semistruktur/udpak_semistruktur/transform/reshape.py create mode 100644 udpak_semistruktur/udpak_semistruktur/utils.py diff --git a/udpak_semistruktur/.env.example b/udpak_semistruktur/.env.example new file mode 100644 index 0000000..09dbfa4 --- /dev/null +++ b/udpak_semistruktur/.env.example @@ -0,0 +1,10 @@ +# Eksempel på miljøvariabler brugt af udpak_semistruktur. +# Kopiér denne fil til .env og udfyld værdierne. +# .env må ALDRIG committes til git. + +# Rodmappe til PowerCenter/ETL-miljø (bruges til at finde credentials-fil) +PMROOTDIR=C:\path\to\pmroot + +# Kørselsmiljø: prd, pre eller udv +# Bruges til at vælge den rette databaseforbindelse +# ETLENV=udv diff --git a/udpak_semistruktur/.gitignore b/udpak_semistruktur/.gitignore new file mode 100644 index 0000000..a8351a6 --- /dev/null +++ b/udpak_semistruktur/.gitignore @@ -0,0 +1,34 @@ +# Python +__pycache__/ +*.py[cod] +*.pyo +*.pyd +.Python + +# Virtuelle miljøer +.venv/ +venv/ +env/ + +# PyInstaller output +build/ +dist/ +*.spec + +# Miljøvariabler (må aldrig committes) +.env + +# Logs og output +*.log +output/ +*.csv +*.tsv + +# IDE +.vscode/ +.idea/ +*.swp + +# Windows +Thumbs.db +desktop.ini diff --git a/udpak_semistruktur/README.md b/udpak_semistruktur/README.md new file mode 100644 index 0000000..0d7b00b --- /dev/null +++ b/udpak_semistruktur/README.md @@ -0,0 +1,89 @@ +# udpak_semistruktur + +ETL-værktøj til udtræk og transformation af semistrukturerede data (JSON og XML) til flade filer og Sybase ASE-tabeller. + +## Funktionalitet + +- Læser JSON- og XML-filer med automatisk encoding-detektion +- Konfigurationsstyret udtræk via YAML +- Datatransformation: typekonvertering, datohåndtering, rensning, tag-stripping m.m. +- Output til flad fil (CSV/TSV) og/eller Sybase ASE via ODBC +- DDL-generering (CREATE TABLE) til Sybase ASE +- Generering af flyt-scripts (DELETE + INSERT) til tmp → base tabelflytning +- Kompileres til Windows-eksekverbar via PyInstaller + +## Projektstruktur + +``` +udpak_semistruktur/ +├── udpak_semistruktur/ # Python-pakken +│ ├── extract/ # Filindlæsning og JSON/XML-traversering +│ │ ├── reader.py # Filindlæsning, type- og encoding-detektion +│ │ └── traversal.py # Rekursiv stibaseret udtræk +│ ├── transform/ # Datatransformation +│ │ ├── convert.py # Typekonvertering (dato, tal, boolean m.m.) +│ │ ├── clean.py # Rensning, linjeskift, tag-stripping, case +│ │ └── reshape.py # Flatten, join, where-filter, id-felt +│ ├── load/ # Skrivning til fil og database +│ │ ├── file_writer.py # CSV/TSV-skrivning med retry +│ │ └── db_writer.py # Sybase ASE insert via ODBC +│ ├── config.py # YAML-konfigurationshåndtering og -validering +│ ├── db.py # Databaseforbindelse og credentials +│ ├── ddl.py # DDL-generering og flyt-scripts til Sybase ASE +│ └── utils.py # Fælles hjælpefunktioner +├── tests/ # Unit tests +├── udpak_semistruktur.py # CLI entry point +├── requirements.txt +└── README.md +``` + +## Krav + +- Python (seneste stabile version anbefales) +- Sybase ASE ODBC-driver installeret på målmaskinen (kan ikke bundtes med PyInstaller) + +## Installation (udvikling) + +```bash +python -m venv .venv +.venv\Scripts\activate # Windows +pip install -r requirements.txt +``` + +## Brug + +```bash +python udpak_semistruktur.py --config min_config.yaml --input data.json +python udpak_semistruktur.py --config min_config.yaml --input-liste filer.txt +python udpak_semistruktur.py --config min_config.yaml --input data.xml --DDL +python udpak_semistruktur.py --config min_config.yaml --input data.json --DDL --flyt +``` + +### Vigtigste flag + +| Flag | Beskrivelse | +|---|---| +| `--config` | Sti til YAML-konfigurationsfil | +| `--input` | Sti til enkelt input-fil (JSON eller XML) | +| `--input-liste` | Sti til tekstfil med én input-fil per linje | +| `--DDL` | Generer CREATE TABLE DDL-filer | +| `--tmp` | Generer også `_tmp`-tabelvariant ved DDL | +| `--flyt` | Generer DELETE + INSERT flyt-scripts (fuld kolonteliste) | +| `--flyt_kort` | Generer DELETE + INSERT flyt-scripts (SELECT \*) | + +## Kompilering med PyInstaller + +```bash +pip install pyinstaller +pyinstaller --onefile udpak_semistruktur.py +``` + +Den kompilerede `.exe` lægges i `dist/`. Bemærk at Sybase ODBC-driveren skal være installeret separat på målmaskinen. + +## Miljøvariabler + +Se `.env.example` for en oversigt over anvendte miljøvariabler. + +## YAML-konfiguration + +Konfigurationen styrer hvilke felter der udtrækkes, hvordan de transformeres og hvor output skrives hen. Se eksempelkonfigurationer i `examples/` (oprettes løbende). diff --git a/udpak_semistruktur/requirements.txt b/udpak_semistruktur/requirements.txt new file mode 100644 index 0000000..bf94916 --- /dev/null +++ b/udpak_semistruktur/requirements.txt @@ -0,0 +1,16 @@ +# Filindlæsning og parsing +xmltodict +charset-normalizer + +# HTML/XML tag-stripping +beautifulsoup4 +lxml + +# Databaseadgang (Sybase ASE via ODBC) +pyodbc + +# YAML-konfiguration +pyyaml + +# Kompilering til eksekverbar +pyinstaller diff --git a/udpak_semistruktur/tests/__init__.py b/udpak_semistruktur/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur.py b/udpak_semistruktur/udpak_semistruktur.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/__init__.py b/udpak_semistruktur/udpak_semistruktur/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/config.py b/udpak_semistruktur/udpak_semistruktur/config.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/db.py b/udpak_semistruktur/udpak_semistruktur/db.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/ddl.py b/udpak_semistruktur/udpak_semistruktur/ddl.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/extract/__init__.py b/udpak_semistruktur/udpak_semistruktur/extract/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/extract/reader.py b/udpak_semistruktur/udpak_semistruktur/extract/reader.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/extract/traversal.py b/udpak_semistruktur/udpak_semistruktur/extract/traversal.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/load/__init__.py b/udpak_semistruktur/udpak_semistruktur/load/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/load/db_writer.py b/udpak_semistruktur/udpak_semistruktur/load/db_writer.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/load/file_writer.py b/udpak_semistruktur/udpak_semistruktur/load/file_writer.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/transform/__init__.py b/udpak_semistruktur/udpak_semistruktur/transform/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/transform/clean.py b/udpak_semistruktur/udpak_semistruktur/transform/clean.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/transform/convert.py b/udpak_semistruktur/udpak_semistruktur/transform/convert.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/transform/reshape.py b/udpak_semistruktur/udpak_semistruktur/transform/reshape.py new file mode 100644 index 0000000..e69de29 diff --git a/udpak_semistruktur/udpak_semistruktur/utils.py b/udpak_semistruktur/udpak_semistruktur/utils.py new file mode 100644 index 0000000..e69de29