Compare commits

...

5 Commits

Author SHA1 Message Date
m.stangl 40eb51a6fd Erzeugt einen sortierten DataFrame. Bei leerer Liste (z.B. SPS ohne Ausgänge) wird ein leerer DataFrame mit den erwarteten Spalten erzeugt, damit Sortierung und spätere Spaltenzugriffe nicht mit KeyError abbrechen. 2026-10-21 10:31:02 +02:00
s.ayadi 22e9796593 Installtools und Liste der python packages an die neuere Arte der Python installation angepasst 2026-10-20 14:01:33 +02:00
m.schellhammer 79a7d2d750 merge durchgeführt 2026-10-15 10:40:29 +02:00
m.schellhammer 3142a58966 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/kabellaengen 2026-10-13 11:01:54 +02:00
m.schellhammer a4efd41cc2 ERWEITERT:
929055247 = GETR.MOT. SA57DRN80MK4, M5A, 0,55KW, 50HZ O.BR.
929055170 = GETR.MOT. SA57DRN80MK4, M6B, 0,55KW 50HZ O.BR.
400102555 = Camera DM280 mit Halter (CPC) - BG
929055161 = GETR.MOT. SA57DRN80MK4, M1A,0,55KW, 50HZ, O.BREMSE
610554012 = ENCODER KPL. FÜR CP2100 (WEGEVERFOLGUNG)
2026-10-13 10:52:48 +02:00
12 changed files with 57 additions and 36 deletions
+1
View File
@@ -15,6 +15,7 @@ dist/
downloads/ downloads/
eggs/ eggs/
.eggs/ .eggs/
.vscode/settings.json
lib64/ lib64/
parts/ parts/
sdist/ sdist/
+3 -2
View File
@@ -1,7 +1,8 @@
{ {
"python.languageServer": "None", "python.languageServer": "Default",
"cSpell.words": [ "cSpell.words": [
"DXFATTRIBS", "DXFATTRIBS",
"ezdxf" "ezdxf"
] ],
"iis.configDir": ""
} }
-1
View File
@@ -245,7 +245,6 @@ Key Python packages (see [lib/requirements.txt](lib/requirements.txt)):
- `pandas` - Data manipulation - `pandas` - Data manipulation
- `matplotlib` - Graph visualization - `matplotlib` - Graph visualization
- `dacite` - Dataclass conversion utilities - `dacite` - Dataclass conversion utilities
- `PyMuPDF` - PDF processing capabilities
- `pillow` - Image processing (flag/icon generation) - `pillow` - Image processing (flag/icon generation)
- `pytest` - Testing framework - `pytest` - Testing framework
+6 -1
View File
@@ -19,6 +19,7 @@ REM Namen der Ergebnisdateien
set ERROR_DOUBLE=%FILENAME%_errors.json set ERROR_DOUBLE=%FILENAME%_errors.json
set EXCEL_RES=%FILENAME%_cables.xlsx set EXCEL_RES=%FILENAME%_cables.xlsx
set DXF_RES=%FILENAME%_cables.dxf set DXF_RES=%FILENAME%_cables.dxf
set BOM_RES=%FILENAME%_BOM.xlsx
if exist "%~dp0_setenv.bat" ( if exist "%~dp0_setenv.bat" (
echo Lade lokale Umgebungseinstellungen aus _setenv.bat... echo Lade lokale Umgebungseinstellungen aus _setenv.bat...
@@ -63,8 +64,12 @@ if not exist "%PROJECT_WORK%\%EXCEL_RES%" (
) )
echo. echo.
move %PROJECT_WORK%\%FILENAME%_* %TARGET_DIR% REM nur die eigenen Ergebnisdateien verschieben (kein Wildcard, sonst werden z.B. bei "easy" auch "easy_sps_*" mitgenommen)
for %%f in (%JSON_POS% %JSON_TODRAW% %DXF_RES% %EXCEL_RES% %BOM_RES% %ERROR_DOUBLE%) do (
if exist "%PROJECT_WORK%\%%f" move "%PROJECT_WORK%\%%f" "%TARGET_DIR%"
)
pause pause
goto :eof
:usage :usage
+12 -5
View File
@@ -1,14 +1,21 @@
call setenv.bat call "%~dp0setenv.bat"
if "%PROJECT%"=="" (
ECHO FEHLER: PROJECT ist nicht gesetzt!
exit /b 1
)
REM Python 3.12: numpy 1.26 / pandas 2.1 aus requirements.txt gibt es nicht fuer neuere Versionen
if not exist %PROJECT%\.venv ( if not exist %PROJECT%\.venv (
ECHO Initialisiere Python virtual environment... ECHO Initialisiere Python virtual environment...
py -m venv %PROJECT%\.venv --upgrade-deps uv venv %PROJECT%\.venv --python 3.12 || exit /b 1
ECHO Erfolgreich. ECHO Erfolgreich.
call %PROJECT%\.venv\Scripts\activate.bat
ECHO Installiere erforderliche Python Packages... ECHO Installiere erforderliche Python Packages...
pip install -r %PROJECT_LIB%/requirements.txt -q uv pip install --python %PROJECT%\.venv -r %PROJECT_LIB%/requirements.txt -q || (
ECHO FEHLER: Installation fehlgeschlagen, entferne .venv
rmdir /s /q %PROJECT%\.venv
exit /b 1
)
ECHO Erfolgreich ECHO Erfolgreich
deactivate
) ELSE ( ) ELSE (
ECHO Erforderliche Python Packages bereits installiert! ECHO Erforderliche Python Packages bereits installiert!
+7 -4
View File
@@ -2,16 +2,19 @@
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/setenv.sh" source "$SCRIPT_DIR/setenv.sh"
# Python 3.12: numpy 1.26 / pandas 2.1 aus requirements.txt gibt es nicht fuer neuere Versionen
if [ ! -d "$PROJECT/.venv" ]; then if [ ! -d "$PROJECT/.venv" ]; then
echo "Initialisiere Python virtual environment..." echo "Initialisiere Python virtual environment..."
python3 -m venv "$PROJECT/.venv" --upgrade-deps uv venv "$PROJECT/.venv" --python 3.12 || exit 1
echo "Erfolgreich." echo "Erfolgreich."
source "$PROJECT/.venv/bin/activate"
echo "Installiere erforderliche Python Packages..." echo "Installiere erforderliche Python Packages..."
pip install -r "$PROJECT_LIB/requirements.txt" -q if ! uv pip install --python "$PROJECT/.venv" -r "$PROJECT_LIB/requirements.txt" -q; then
echo "FEHLER: Installation fehlgeschlagen, entferne .venv"
rm -rf "$PROJECT/.venv"
exit 1
fi
echo "Erfolgreich" echo "Erfolgreich"
deactivate
else else
echo "Erforderliche Python Packages bereits installiert!" echo "Erforderliche Python Packages bereits installiert!"
fi fi
+2 -1
View File
@@ -25,7 +25,8 @@ if not exist %PROJECT%\translation mkdir %PROJECT%\translation
if not exist %PROJECT%\logs mkdir %PROJECT%\logs if not exist %PROJECT%\logs mkdir %PROJECT%\logs
set PROJECT_IO_RESULTS=Z:\Automatisierung\Konvertierungstools\4_io-Konvertierer set PROJECT_IO_RESULTS=Z:\Automatisierung\Konvertierungstools\4_io-Konvertierer
set PROJECT_BOM_RESULTS=Z:\Automatisierung\Konvertierungstools\3_Kabellaengen-Konvertierer REM Kann vorab gesetzt werden (z.B. von run_tests.py), damit Testergebnisse in work bleiben
if not defined PROJECT_BOM_RESULTS set PROJECT_BOM_RESULTS=Z:\Automatisierung\Konvertierungstools\3_Kabellaengen-Konvertierer
set INSTALL_DIR="%ONEDRIVE%\Desktop\Kabeltool" set INSTALL_DIR="%ONEDRIVE%\Desktop\Kabeltool"
if exist "%~dp0_setenv.bat" ( if exist "%~dp0_setenv.bat" (
+1 -2
View File
@@ -205,7 +205,6 @@
827072015 = STATISCHE TROLLEYABFRAGE L=200 FÜR AP110 827072015 = STATISCHE TROLLEYABFRAGE L=200 FÜR AP110
929055247 = GETR.MOT. SA57DRN80MK4, M5A, 0,55KW, 50HZ O.BR. 929055247 = GETR.MOT. SA57DRN80MK4, M5A, 0,55KW, 50HZ O.BR.
929055170 = GETR.MOT. SA57DRN80MK4, M6B, 0,55KW 50HZ O.BR. 929055170 = GETR.MOT. SA57DRN80MK4, M6B, 0,55KW 50HZ O.BR.
400102555 = Camera DM280 mit Halter (CPC) - BG
929055161 = GETR.MOT. SA57DRN80MK4, M1A,0,55KW, 50HZ, O.BREMSE 929055161 = GETR.MOT. SA57DRN80MK4, M1A,0,55KW, 50HZ, O.BREMSE
610554012 = ENCODER KPL. FÜR CP2100 (WEGEVERFOLGUNG) 610554012 = ENCODER KPL. FÜR CP2100 (WEGEVERFOLGUNG)
400102555 = Camera DM280 mit Halter (CPC) - BG
+19 -6
View File
@@ -10,6 +10,16 @@ class ExcelConverter:
self.eingaenge_identifier = ["FDI", "B", "S", "E", "I", "DI", "BA", "BB", "BC", "BD", "BE", "BF", "BG", "BH", "BJ", "BK", "BL", "BM", "BN", "BP", "BQ", "BR", "BS", "BT", "BU", "BV", "BW", "BX", "BY", "BZ", "FA", "FB", "FC", "FD", "FE", "FF", "FG", "FH", "FJ", "FK", "FL", "FM", "FN", "FP", "FQ", "FR", "FS", "FT", "FU", "FV", "FW", "FX", "FY", "FZ", "SA", "SB", "SC", "SD", "SE", "SF", "SG", "SH", "SJ", "SK", "SL", "SM", "SN", "SP", "SQ", "SR", "SS", "ST", "SU", "SV", "SW", "SX", "SY", "SZ"] self.eingaenge_identifier = ["FDI", "B", "S", "E", "I", "DI", "BA", "BB", "BC", "BD", "BE", "BF", "BG", "BH", "BJ", "BK", "BL", "BM", "BN", "BP", "BQ", "BR", "BS", "BT", "BU", "BV", "BW", "BX", "BY", "BZ", "FA", "FB", "FC", "FD", "FE", "FF", "FG", "FH", "FJ", "FK", "FL", "FM", "FN", "FP", "FQ", "FR", "FS", "FT", "FU", "FV", "FW", "FX", "FY", "FZ", "SA", "SB", "SC", "SD", "SE", "SF", "SG", "SH", "SJ", "SK", "SL", "SM", "SN", "SP", "SQ", "SR", "SS", "ST", "SU", "SV", "SW", "SX", "SY", "SZ"]
self.ausgaenge_identifier = ["K", "O", "Q", "M", "A", "P", "DQ", "CA", "CB", "CC", "CD", "CE", "CF", "CG", "CH", "CJ", "CK", "CL", "CM", "CN", "CP", "CQ", "CR", "CS", "CT", "CU", "CV", "CW", "CX", "CY", "CZ", "EA", "EB", "EC", "ED", "EE", "EF", "EG", "EH", "EJ", "EK", "EL", "EM", "EN", "EP", "EQ", "ER", "ES", "ET", "EU", "EV", "EW", "EX", "EY", "EZ", "GA", "GB", "GC", "GD", "GE", "GF", "GG", "GH", "GJ", "GK", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GV", "GW", "GX", "GY", "GZ", "HA", "HB", "HC", "HD", "HE", "HF", "HG", "HH", "HJ", "HK", "HL", "HM", "HN", "HP", "HQ", "HR", "HS", "HT", "HU", "HV", "HW", "HX", "HY", "HZ", "KA", "KB", "KC", "KD", "KE", "KF", "KG", "KH", "KJ", "KK", "KL", "KM", "KN", "KP", "KQ", "KR", "KS", "KT", "KU", "KV", "KW", "KX", "KY", "KZ", "MA", "MB", "MC", "MD", "ME", "MF", "MG", "MH", "MJ", "MK", "ML", "MM", "MN", "MP", "MQ", "MR", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "PA", "PB", "PC", "PD", "PE", "PF", "PG", "PH", "PJ", "PK", "PL", "PM", "PN", "PP", "PQ", "PR", "PS", "PT", "PU", "PV", "PW", "PX", "PY", "PZ", "QA", "QB", "QC", "QD", "QE", "QF", "QG", "QH", "QJ", "QK", "QL", "QM", "QN", "QP", "QQ", "QR", "QS", "QT", "QU", "QV", "QW", "QX", "QY", "QZ", "RA", "RB", "RC", "RD", "RE", "RF", "RG", "RH", "RJ", "RK", "RL", "RM", "RN", "RP", "RQ", "RR", "RS", "RT", "RU", "RV", "RW", "RX", "RY", "RZ", "TA", "TB", "TC", "TD", "TE", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TP", "TQ", "TR", "TS", "TT", "TU", "TV", "TW", "TX", "TY", "TZ"] self.ausgaenge_identifier = ["K", "O", "Q", "M", "A", "P", "DQ", "CA", "CB", "CC", "CD", "CE", "CF", "CG", "CH", "CJ", "CK", "CL", "CM", "CN", "CP", "CQ", "CR", "CS", "CT", "CU", "CV", "CW", "CX", "CY", "CZ", "EA", "EB", "EC", "ED", "EE", "EF", "EG", "EH", "EJ", "EK", "EL", "EM", "EN", "EP", "EQ", "ER", "ES", "ET", "EU", "EV", "EW", "EX", "EY", "EZ", "GA", "GB", "GC", "GD", "GE", "GF", "GG", "GH", "GJ", "GK", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GV", "GW", "GX", "GY", "GZ", "HA", "HB", "HC", "HD", "HE", "HF", "HG", "HH", "HJ", "HK", "HL", "HM", "HN", "HP", "HQ", "HR", "HS", "HT", "HU", "HV", "HW", "HX", "HY", "HZ", "KA", "KB", "KC", "KD", "KE", "KF", "KG", "KH", "KJ", "KK", "KL", "KM", "KN", "KP", "KQ", "KR", "KS", "KT", "KU", "KV", "KW", "KX", "KY", "KZ", "MA", "MB", "MC", "MD", "ME", "MF", "MG", "MH", "MJ", "MK", "ML", "MM", "MN", "MP", "MQ", "MR", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "PA", "PB", "PC", "PD", "PE", "PF", "PG", "PH", "PJ", "PK", "PL", "PM", "PN", "PP", "PQ", "PR", "PS", "PT", "PU", "PV", "PW", "PX", "PY", "PZ", "QA", "QB", "QC", "QD", "QE", "QF", "QG", "QH", "QJ", "QK", "QL", "QM", "QN", "QP", "QQ", "QR", "QS", "QT", "QU", "QV", "QW", "QX", "QY", "QZ", "RA", "RB", "RC", "RD", "RE", "RF", "RG", "RH", "RJ", "RK", "RL", "RM", "RN", "RP", "RQ", "RR", "RS", "RT", "RU", "RV", "RW", "RX", "RY", "RZ", "TA", "TB", "TC", "TD", "TE", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TP", "TQ", "TR", "TS", "TT", "TU", "TV", "TW", "TX", "TY", "TZ"]
def _sortierter_df(self, eintraege, sortierung, spalten):
"""
Erzeugt einen sortierten DataFrame. Bei leerer Liste (z.B. SPS ohne Ausgänge)
wird ein leerer DataFrame mit den erwarteten Spalten erzeugt, damit Sortierung
und spätere Spaltenzugriffe nicht mit KeyError abbrechen.
"""
if not eintraege:
return pd.DataFrame(columns=spalten)
return pd.DataFrame(eintraege).sort_values(by=sortierung)
def _gleiche_finden(self, liste): def _gleiche_finden(self, liste):
counter = {} counter = {}
for eintrag in liste: for eintrag in liste:
@@ -147,8 +157,9 @@ class ExcelConverter:
gleiche_ausgaenge, ausgaenge = self._verarbeite_io_liste(ausgaenge) gleiche_ausgaenge, ausgaenge = self._verarbeite_io_liste(ausgaenge)
# DataFrames erzeugen u. sortieren # DataFrames erzeugen u. sortieren
df_eingaenge = pd.DataFrame(eingaenge).sort_values(by="Name") spalten = ['Name', 'Kommentar', 'Zeile']
df_ausgaenge = pd.DataFrame(ausgaenge).sort_values(by="Name") df_eingaenge = self._sortierter_df(eingaenge, "Name", spalten)
df_ausgaenge = self._sortierter_df(ausgaenge, "Name", spalten)
df_gleiche_eingaenge = pd.DataFrame(gleiche_eingaenge).sort_values(by="Name") if gleiche_eingaenge else pd.DataFrame() df_gleiche_eingaenge = pd.DataFrame(gleiche_eingaenge).sort_values(by="Name") if gleiche_eingaenge else pd.DataFrame()
df_gleiche_ausgaenge = pd.DataFrame(gleiche_ausgaenge).sort_values(by="Name") if gleiche_ausgaenge else pd.DataFrame() df_gleiche_ausgaenge = pd.DataFrame(gleiche_ausgaenge).sort_values(by="Name") if gleiche_ausgaenge else pd.DataFrame()
@@ -218,8 +229,9 @@ class ExcelConverter:
gleiche_ausgaenge, ausgaenge = self._verarbeite_io_liste(ausgaenge) gleiche_ausgaenge, ausgaenge = self._verarbeite_io_liste(ausgaenge)
# DataFrames erstellen u. sortieren # DataFrames erstellen u. sortieren
df_eingaenge = pd.DataFrame(eingaenge).sort_values(by="Zahl") spalten = ['Name', 'NameOriginal', 'NameConstant', 'Kommentar', 'Zahl', 'Zeile']
df_ausgaenge = pd.DataFrame(ausgaenge).sort_values(by="Zahl") df_eingaenge = self._sortierter_df(eingaenge, "Zahl", spalten)
df_ausgaenge = self._sortierter_df(ausgaenge, "Zahl", spalten)
df_gleiche_eingaenge = pd.DataFrame(gleiche_eingaenge).sort_values(by="Zahl") if gleiche_eingaenge else pd.DataFrame() df_gleiche_eingaenge = pd.DataFrame(gleiche_eingaenge).sort_values(by="Zahl") if gleiche_eingaenge else pd.DataFrame()
df_gleiche_ausgaenge = pd.DataFrame(gleiche_ausgaenge).sort_values(by="Zahl") if gleiche_ausgaenge else pd.DataFrame() df_gleiche_ausgaenge = pd.DataFrame(gleiche_ausgaenge).sort_values(by="Zahl") if gleiche_ausgaenge else pd.DataFrame()
@@ -362,8 +374,9 @@ class ExcelConverter:
gleiche_ausgaenge, ausgaenge = self._verarbeite_io_liste(ausgaenge) gleiche_ausgaenge, ausgaenge = self._verarbeite_io_liste(ausgaenge)
# DataFrames erzeugen u. sortieren # DataFrames erzeugen u. sortieren
df_eingaenge = pd.DataFrame(eingaenge).sort_values(by="Name") spalten = ['Name', 'Kommentar', 'Zeile', 'Bezug']
df_ausgaenge = pd.DataFrame(ausgaenge).sort_values(by="Name") df_eingaenge = self._sortierter_df(eingaenge, "Name", spalten)
df_ausgaenge = self._sortierter_df(ausgaenge, "Name", spalten)
df_gleiche_eingaenge = pd.DataFrame(gleiche_eingaenge).sort_values(by="Name") if gleiche_eingaenge else pd.DataFrame() df_gleiche_eingaenge = pd.DataFrame(gleiche_eingaenge).sort_values(by="Name") if gleiche_eingaenge else pd.DataFrame()
df_gleiche_ausgaenge = pd.DataFrame(gleiche_ausgaenge).sort_values(by="Name") if gleiche_ausgaenge else pd.DataFrame() df_gleiche_ausgaenge = pd.DataFrame(gleiche_ausgaenge).sort_values(by="Name") if gleiche_ausgaenge else pd.DataFrame()
+1 -1
View File
@@ -118,7 +118,7 @@ def do_export(conv_obj:ExcelConverter, mode_str, base_input, output_dir, lines,
conv_obj.export_excel(lines, export_type, export_path, getpos_errors, getpos_warnings) conv_obj.export_excel(lines, export_type, export_path, getpos_errors, getpos_warnings)
print(f"Export '{export_type}' erfolgreich: {export_path}") print(f"Export '{export_type}' erfolgreich: {export_path}")
except Exception as e: except Exception as e:
print(f"Fehler bei Export '{export_type}': {e}") print(f"Fehler bei Export '{export_type}' ({export_path}): {type(e).__name__}: {e}")
def do_exports(converter, export_mode, output_dir, base_input, lines, getpos_errors=None, getpos_warnings=None): def do_exports(converter, export_mode, output_dir, base_input, lines, getpos_errors=None, getpos_warnings=None):
if export_mode: if export_mode:
-11
View File
@@ -1,10 +1,7 @@
build==1.2.2.post1
click==8.1.8
colorama==0.4.6 colorama==0.4.6
contourpy==1.3.1 contourpy==1.3.1
cycler==0.12.1 cycler==0.12.1
dacite==1.9.2 dacite==1.9.2
dataclasses==0.6
et-xmlfile==1.1.0 et-xmlfile==1.1.0
ezdxf==1.4.1 ezdxf==1.4.1
fonttools==4.57.0 fonttools==4.57.0
@@ -17,21 +14,13 @@ openpyxl==3.1.2
packaging==24.2 packaging==24.2
pandas==2.1.1 pandas==2.1.1
pillow==11.1.0 pillow==11.1.0
pip-tools==7.4.1
pluggy==1.6.0 pluggy==1.6.0
Pygments==2.19.2 Pygments==2.19.2
PyMuPDF==1.25.5
pyparsing==3.2.3 pyparsing==3.2.3
pyproject_hooks==1.2.0
pytest==9.0.2 pytest==9.0.2
python-dateutil==2.8.2 python-dateutil==2.8.2
pytz==2023.3.post1 pytz==2023.3.post1
setuptools==80.0.0
shapely==2.1.0 shapely==2.1.0
shiboken6==6.9.0
six==1.16.0 six==1.16.0
snakeviz==2.2.2
tornado==6.5.1
typing_extensions==4.13.1 typing_extensions==4.13.1
tzdata==2023.3 tzdata==2023.3
wheel==0.45.1
+4 -1
View File
@@ -74,8 +74,11 @@ class TestRunner:
# Execute getexdraw.bat with automated input to handle pause # Execute getexdraw.bat with automated input to handle pause
cmd = [str(self.getexdraw_bat), str(dxf_file)] cmd = [str(self.getexdraw_bat), str(dxf_file)]
# Ergebnisse in work statt im produktiven Netzlaufwerk ablegen
env = os.environ.copy()
env['PROJECT_BOM_RESULTS'] = str(self.work_dir)
# Send newline to handle the pause command # Send newline to handle the pause command
result = subprocess.run(cmd, capture_output=True, text=True, shell=True, input="\n") result = subprocess.run(cmd, capture_output=True, text=True, shell=True, input="\n", env=env)
# Check if the expected output files were created instead of relying on return code # Check if the expected output files were created instead of relying on return code
# The batch script always exits with code 1 due to interactive design, but files are created # The batch script always exits with code 1 due to interactive design, but files are created