From 4f27849fd302d52d0bae10afcaf606c374317171 Mon Sep 17 00:00:00 2001 From: Carsten Kvist Date: Fri, 3 Apr 2026 01:04:29 +0200 Subject: [PATCH] Endelig 1 --- README.md | 50 +++++++++++++++++++------------------ udpak_semistruktur.py | 8 +++++- udpak_semistruktur/utils.py | 18 +++++++++++++ 3 files changed, 51 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 0d7b00b..9aff15e 100644 --- a/README.md +++ b/README.md @@ -15,24 +15,27 @@ ETL-værktøj til udtræk og transformation af semistrukturerede data (JSON og X ## 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 +uudpak_semistruktur/ +├── udpak_semistruktur/ # Python-pakken +│ ├── extract/ # Filindlæsning og JSON/XML-traversering +│ │ ├── reader.py # Filindlæsning, type- og encoding-detektion +│ │ ├── traversal.py # Rekursiv stibaseret navigation i JSON/XML +│ │ └── extractor.py # Udtræk af rækker baseret på YAML-konfiguration +│ ├── transform/ # Datatransformation +│ │ ├── convert.py # Typekonvertering (dato, tal, boolean m.m.) +│ │ ├── clean.py # Rensning, linjeskift, tag-stripping, case, filnavn +│ │ ├── reshape.py # Flatten, join, where-filter, id-felt, sammensat nøgle +│ │ └── hash.py # Hash-beregning af kolonneværdier +│ ├── load/ # Skrivning til fil og database +│ │ ├── file_writer.py # CSV/TSV-skrivning med retry ved låste filer +│ │ └── db_writer.py # Sybase ASE insert via ODBC +│ ├── config.py # YAML-indlæsning, validering og expansion +│ ├── db.py # Credentials fra pwd.json +│ ├── ddl.py # DDL-generering og flyt-scripts til Sybase ASE +│ ├── logger.py # Central logging med konfigurerbart logniveau +│ └── utils.py # Fælles hjælpefunktioner +├── tests/ # Unit tests +├── udpak_semistruktur.py # CLI entry point ├── requirements.txt └── README.md ``` @@ -53,10 +56,11 @@ 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 +python udpak_semistruktur.py --config min_config.yaml +python udpak_semistruktur.py --config min_config.yaml --DDL +python udpak_semistruktur.py --config min_config.yaml --DDL --tmp +python udpak_semistruktur.py --config min_config.yaml --DDL --flyt +python udpak_semistruktur.py --config min_config.yaml --DDL --flyt_kort ``` ### Vigtigste flag @@ -64,8 +68,6 @@ python udpak_semistruktur.py --config min_config.yaml --input data.json --DDL -- | 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) | diff --git a/udpak_semistruktur.py b/udpak_semistruktur.py index 5e0b79c..54654fe 100644 --- a/udpak_semistruktur.py +++ b/udpak_semistruktur.py @@ -1,3 +1,4 @@ +import sys import argparse from udpak_semistruktur.config import valider_yaml @@ -13,7 +14,7 @@ from udpak_semistruktur.transform.hash import beregn_hash from udpak_semistruktur.load.file_writer import generer_filer_med_overskrifter, skriv_fil_med_retry from udpak_semistruktur.load.db_writer import get_ase_connection_windows, insert_rows_ase from udpak_semistruktur.db import læs_json_fil -from udpak_semistruktur.utils import generer_filnavn +from udpak_semistruktur.utils import generer_filnavn, load_env_file logger = hent_logger(__name__) @@ -103,6 +104,11 @@ def _kør_udtræk(config: dict, global_config: dict) -> None: def main(): """Hovedfunktion der eksekveres ved kørsel af scriptet.""" + + # Indlæs lokal .env under udvikling – springes over i kompileret .exe + if not getattr(sys, "frozen", False): + load_env_file("testenv.env") + parser = _byg_argument_parser() args = parser.parse_args() diff --git a/udpak_semistruktur/utils.py b/udpak_semistruktur/utils.py index ac11c44..86ba80c 100644 --- a/udpak_semistruktur/utils.py +++ b/udpak_semistruktur/utils.py @@ -2,6 +2,9 @@ import os import re from typing import Any +from udpak_semistruktur.logger import hent_logger + +logger = hent_logger(__name__) EMPTY_SENTINELS = (None, "", [], {}) @@ -51,3 +54,18 @@ def parse_value_token(value: Any) -> tuple[str, Any]: return "prog", prog_match.group(1) return "const", value + +def load_env_file(filepath: str) -> None: + """Indlæser miljøvariabler fra en .env-fil. Bruges kun under udvikling.""" + if not os.path.exists(filepath): + logger.debug(f"{filepath} blev ikke fundet – springer over.") + return + + with open(filepath, "r", encoding="utf-8") as f: + for line in f: + line = line.strip() + if not line or line.startswith("#"): + continue + if "=" in line: + key, value = line.split("=", 1) + os.environ[key.strip()] = value.strip() \ No newline at end of file