192 lines
5.0 KiB
Python
192 lines
5.0 KiB
Python
"""
|
|
Common utility functions for the cable routing system.
|
|
|
|
This module contains frequently used helper functions for:
|
|
- File and path operations
|
|
- Environment variable handling
|
|
- JSON operations
|
|
- DXF file handling
|
|
- Dictionary operations
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Any, Tuple
|
|
|
|
import ezdxf
|
|
from ezdxf.lldxf.const import DXFStructureError
|
|
|
|
|
|
# ============================================================================
|
|
# File Operations
|
|
# ============================================================================
|
|
|
|
def check_file_in_work(work_dir, filename) -> Tuple[Path, bool]:
|
|
"""
|
|
Check if a file exists, either at the given path or in the work directory.
|
|
|
|
Args:
|
|
work_dir: Working directory to check if file not found at filename path (str or Path)
|
|
filename: Path to the file to check (str or Path)
|
|
|
|
Returns:
|
|
Tuple of (resolved_path, exists_flag)
|
|
- resolved_path: Path where file was found (or would be)
|
|
- exists_flag: True if file exists, False otherwise
|
|
"""
|
|
work_dir = Path(work_dir)
|
|
filename = Path(filename)
|
|
|
|
fexists = True
|
|
if not filename.exists():
|
|
mypath = work_dir.joinpath(filename)
|
|
if not mypath.exists():
|
|
fexists = False
|
|
else:
|
|
mypath = filename
|
|
return mypath, fexists
|
|
|
|
|
|
# ============================================================================
|
|
# Environment Variable Operations
|
|
# ============================================================================
|
|
|
|
def check_environment_var(env_str: str) -> Path:
|
|
"""
|
|
Get and validate an environment variable as a Path.
|
|
|
|
Args:
|
|
env_str: Name of the environment variable
|
|
|
|
Returns:
|
|
Path object from the environment variable
|
|
|
|
Exits:
|
|
Exits the program if the environment variable is not set or empty
|
|
"""
|
|
out_path = os.environ.get(env_str)
|
|
if out_path:
|
|
return Path(out_path)
|
|
else:
|
|
print(f"Umgebungsvariable {env_str} ist nicht gesetzt oder leer.")
|
|
exit()
|
|
|
|
|
|
# ============================================================================
|
|
# JSON Operations
|
|
# ============================================================================
|
|
|
|
def to_json(d: Any, pretty: bool = True) -> str:
|
|
"""
|
|
Convert a Python object to a JSON string.
|
|
|
|
Args:
|
|
d: Object to convert to JSON
|
|
pretty: If True, format with indentation for readability
|
|
|
|
Returns:
|
|
JSON string representation of the object
|
|
|
|
Note:
|
|
Uses ensure_ascii=False to properly display German umlauts (ä, ö, ü)
|
|
"""
|
|
return json.dumps(d, indent=2 if pretty else None, ensure_ascii=False, default=str)
|
|
|
|
|
|
def load_json(jsonfilename: str) -> dict:
|
|
"""
|
|
Load JSON data from a file.
|
|
|
|
Args:
|
|
jsonfilename: Path to the JSON file
|
|
|
|
Returns:
|
|
Parsed JSON data as a dictionary
|
|
"""
|
|
with open(jsonfilename, encoding='utf-8') as fh:
|
|
return json.load(fh)
|
|
|
|
|
|
def write_results(jsn_results: str, out_dir: Path, filename: str) -> None:
|
|
"""
|
|
Write JSON results to a file.
|
|
|
|
Args:
|
|
jsn_results: JSON string to write
|
|
out_dir: Output directory path
|
|
filename: Name of the output file
|
|
"""
|
|
print("writing results to a json file ...")
|
|
outfile = Path(out_dir) / filename
|
|
with open(outfile, 'w', encoding='utf-8') as fh:
|
|
fh.write(jsn_results)
|
|
print("done")
|
|
|
|
|
|
# ============================================================================
|
|
# DXF File Operations
|
|
# ============================================================================
|
|
|
|
def dxf_is_binary(dxf_path: Path) -> bool:
|
|
"""
|
|
Check if a DXF file is in binary format.
|
|
|
|
Args:
|
|
dxf_path: Path to the DXF file
|
|
|
|
Returns:
|
|
True if the file is a binary DXF, False otherwise
|
|
"""
|
|
with open(dxf_path, 'rb') as f:
|
|
header = f.read(22)
|
|
return b'AutoCAD Binary DXF' in header
|
|
|
|
|
|
def get_dxf_file(filepath: Path):
|
|
"""
|
|
Load a DXF file using ezdxf.
|
|
|
|
Args:
|
|
filepath: Path to the DXF file
|
|
|
|
Returns:
|
|
ezdxf Drawing object
|
|
|
|
Exits:
|
|
Exits with code 1 for I/O errors
|
|
Exits with code 2 for invalid/corrupted DXF files
|
|
"""
|
|
try:
|
|
print("reading file ..", end='')
|
|
doc = ezdxf.filemanagement.readfile(filepath)
|
|
print("done")
|
|
except IOError:
|
|
print("Not a DXF file or a generic I/O error.")
|
|
sys.exit(1)
|
|
except DXFStructureError:
|
|
print("Invalid or corrupted DXF file.")
|
|
sys.exit(2)
|
|
return doc
|
|
|
|
|
|
# ============================================================================
|
|
# Dictionary Operations
|
|
# ============================================================================
|
|
|
|
def merge_two_dicts(x: dict, y: dict) -> dict:
|
|
"""
|
|
Merge two dictionaries, with values from y overwriting those in x.
|
|
|
|
Args:
|
|
x: First dictionary (base)
|
|
y: Second dictionary (override values)
|
|
|
|
Returns:
|
|
New dictionary with merged values
|
|
"""
|
|
z = x.copy()
|
|
z.update(y)
|
|
return z
|