Initial implementation of generic Excel-to-DB import tool
Supports .xls and .xlsx, Oracle and PostgreSQL via SQLAlchemy. Includes CLI (run/inspect/generate-config), YAML config, auto schema detection, and append/replace/upsert modes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import io
|
||||
from pathlib import Path
|
||||
import pandas as pd
|
||||
import pytest
|
||||
|
||||
from excel_import.reader import ExcelReader
|
||||
from excel_import.config import SheetConfig
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def xlsx_file(tmp_path: Path) -> Path:
|
||||
path = tmp_path / "test.xlsx"
|
||||
df = pd.DataFrame({
|
||||
"Artikelnummer": ["A001", "A002", "A003"],
|
||||
"Bezeichnung": ["Widget", "Gadget", None],
|
||||
"Preis": [9.99, 14.50, 0.99],
|
||||
})
|
||||
df.to_excel(path, index=False)
|
||||
return path
|
||||
|
||||
|
||||
def test_sheet_names(xlsx_file: Path):
|
||||
reader = ExcelReader(xlsx_file)
|
||||
assert reader.sheet_names() == ["Sheet1"]
|
||||
|
||||
|
||||
def test_read_basic(xlsx_file: Path):
|
||||
reader = ExcelReader(xlsx_file)
|
||||
df = reader.read(SheetConfig(sheet=0, target_table="t"))
|
||||
assert len(df) == 3
|
||||
assert list(df.columns) == ["Artikelnummer", "Bezeichnung", "Preis"]
|
||||
|
||||
|
||||
def test_read_drops_empty_rows(tmp_path: Path):
|
||||
path = tmp_path / "empty_rows.xlsx"
|
||||
df = pd.DataFrame({"A": ["x", None, "y"], "B": [1, None, 3]})
|
||||
df.to_excel(path, index=False)
|
||||
|
||||
reader = ExcelReader(path)
|
||||
result = reader.read(SheetConfig(sheet=0, target_table="t"))
|
||||
assert len(result) == 2
|
||||
|
||||
|
||||
def test_read_column_rename(xlsx_file: Path):
|
||||
from excel_import.config import ColumnMapping
|
||||
cfg = SheetConfig(
|
||||
sheet=0,
|
||||
target_table="t",
|
||||
columns=[
|
||||
ColumnMapping(source="Artikelnummer", target="art_nr"),
|
||||
ColumnMapping(source="Bezeichnung", target="bez"),
|
||||
ColumnMapping(source="Preis", target="preis"),
|
||||
],
|
||||
)
|
||||
reader = ExcelReader(xlsx_file)
|
||||
df = reader.read(cfg)
|
||||
assert "art_nr" in df.columns
|
||||
assert "Artikelnummer" not in df.columns
|
||||
|
||||
|
||||
def test_read_column_skip(xlsx_file: Path):
|
||||
from excel_import.config import ColumnMapping
|
||||
cfg = SheetConfig(
|
||||
sheet=0,
|
||||
target_table="t",
|
||||
columns=[
|
||||
ColumnMapping(source="Preis", target="Preis", skip=True),
|
||||
],
|
||||
)
|
||||
reader = ExcelReader(xlsx_file)
|
||||
df = reader.read(cfg)
|
||||
assert "Preis" not in df.columns
|
||||
|
||||
|
||||
def test_file_not_found():
|
||||
with pytest.raises(FileNotFoundError):
|
||||
ExcelReader("/nonexistent/path/file.xlsx")
|
||||
|
||||
|
||||
def test_unsupported_extension(tmp_path: Path):
|
||||
f = tmp_path / "data.csv"
|
||||
f.write_text("a,b\n1,2")
|
||||
with pytest.raises(ValueError, match="Unsupported"):
|
||||
ExcelReader(f)
|
||||
Reference in New Issue
Block a user