Parse DIALux EVO project files (ISO 10303-21 / STEP) into type-safe Pydantic models.
.dat → .py → validated Python objects
EvoParse reads .evo / .dat project files exported by DIALux EVO (lighting design software) in the ISO 10303-21 (STEP) format and converts them into fully-typed Pydantic v2 models.
What you can do:
- 🔍 Inspect project structure programmatically (scenes, luminaires, spaces, materials)
- 🧪 Write automated tests that validate project data
- 🔄 Generate Python model code from the XML schema shipped with DIALux
- 🏗️ Build CI/CD pipelines that check project data integrity
# ── Install ──
pip install evoparse
# ── Parse a .dat file ──
python -m evoparse.parse_project MyProject.datOutput:
ObjectManager: next_id=55
30 collections, 18 total objects
InstanceObject (12): ControlGroup, FloorElement, LightScene, ...
RelAggregates (1): RelAggregates
RelContainedInSpatialStructure (1): RelContainedInSpatialStructure
...
| Module | Purpose |
|---|---|
evoparse.models |
50+ Pydantic models matching the DIALux EVO XML schema |
evoparse.generate_models |
Code generator: ProjectData.xml → models.py |
evoparse.parse_project |
STEP parser: ProjectData.dat → model instances |
from evoparse import parse_project as pp
# Load the full project graph
result = pp.load_project("ProjectData.dat")
# Find the Project object
for cls, items in result.object_collections:
for item in items:
if type(item).__name__ == "Project":
print(f"ID: {item.object_id}")
print(f"Property sets: {len(item.property_sets)}")
# Each property set is a typed Pydantic model
for ps in item.property_sets:
print(f" - {type(ps).__name__}")from evoparse import parse_project as pp
result = pp.load_project("ProjectData.dat")
for cls, items in result.object_collections:
for item in items:
if type(item).__name__ == "LightScene":
ls = item
print(f"Active: {ls.is_active}, Default: {ls.is_default}")
print(f"CoordSys: {ls.local_coord_sys.origin}")python -m evoparse.generate_models ProjectData.xml -o models.py# Install dev dependencies
pip install pytest pytest-cov ruff
# Run all tests
pytest
# With coverage
pytest --cov=evoparse --cov-report=term-missingTest structure:
| Test file | What it covers |
|---|---|
tests/test_models.py |
All 50+ models match the XML schema (175 tests) |
tests/test_generate_models.py |
Code generator functions (58 tests) |
tests/test_parse_project.py |
STEP tokenizer, parser, type coercion, full pipeline (75 tests) |
Current status: ✅ 308 tests passing
evoparse/
├── evoparse/
│ ├── __init__.py
│ ├── models.py # Pydantic models (50+ classes)
│ ├── generate_models.py # XML → Python code generator
│ └── parse_project.py # STEP file parser
├── tests/
│ ├── test_models.py
│ ├── test_generate_models.py
│ └── test_parse_project.py
├── ProjectData.xml # DIALux EVO schema definition
├── ProjectData.dat # Example project data
├── pyproject.toml
└── README.md
- Fork the repository
- Create a branch (
git checkout -b feature/my-idea) - Make your changes — keep the coding style consistent (no comments, concise)
- Run tests (
pytest) — all 308 must pass - Lint with ruff (
ruff check .) - Open a Pull Request
- ✏️ Follow existing patterns (naming, imports, type annotations)
- 🧪 Add tests for any new functionality
- 📝 Keep the README updated if you change the public API
- 🚫 Never commit secrets or
.datfiles with sensitive data
MIT © Luciodias