Endelig 1

This commit is contained in:
2026-04-03 01:04:29 +02:00
parent 60fb674c8d
commit 4f27849fd3
3 changed files with 51 additions and 25 deletions

View File

@@ -15,21 +15,24 @@ ETL-værktøj til udtræk og transformation af semistrukturerede data (JSON og X
## Projektstruktur
```
udpak_semistruktur/
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 udtræk
│ │ ── 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
│ │ ── reshape.py # Flatten, join, where-filter, id-felt
│ │ ├── 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
│ │ ├── file_writer.py # CSV/TSV-skrivning med retry ved låste filer
│ │ └── db_writer.py # Sybase ASE insert via ODBC
│ ├── config.py # YAML-konfigurationshåndtering og -validering
│ ├── db.py # Databaseforbindelse og credentials
│ ├── 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
@@ -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) |

View File

@@ -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()

View File

@@ -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()