Skip to content

feat(xml): modularize xmlutils into typed telemffb.xml package#67

Open
walmis wants to merge 5 commits into
refactorfrom
feature/xml-refactor
Open

feat(xml): modularize xmlutils into typed telemffb.xml package#67
walmis wants to merge 5 commits into
refactorfrom
feature/xml-refactor

Conversation

@walmis

@walmis walmis commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Summary

Refactors the monolithic xmlutils.py (2,383 lines) into a modular, typed telemffb/xml/ package with full backward compatibility.

Changes

New: telemffb/xml/ package

Module Lines Responsibility
store.py 132 XML I/O, retry parsing, consolidation/writing
read.py 535 Read-only queries & 6-layer config cascade resolution
write.py 336 Write/erase/profile mutation operations
merge.py 101 Pure functions for data merging/filtering
types.py 70 TypedDict definitions for all config row shapes
\_\_init\_\_.py 270 Backward-compatible facade + XmlConfigManager class

Concurrency improvements (namedmutex.py)

  • Added FileLock class: cross-platform file-level locking
    • POSIX: fcntl.flock() with shared (LOCK_SH) and exclusive (LOCK_EX) modes
    • Windows: named mutexes via Win32 ctypes
  • Reads use shared locks — multiple concurrent readers allowed
  • Writes use exclusive locks — writers block until all readers finish
  • Lock held only during raw byte read (~µs), then released before expensive DOM parse
  • Atomic writes via temp file + os.replace() for crash safety

Bug fixes

  • Fixed typos in defaults.xml: JetrAircraftJetAircraft, GilderAircraftGliderAircraft
  • Schema test now correctly allows classdefaults_any to reference classes from any sim

Tests

  • tests/test_xmlutils.py — 98 tests for legacy module parity
  • tests/test_defaults_xml_schema.py — 38 schema validation tests against shipped defaults.xml
  • 136 tests pass, 0 xfails

Migration path

Existing code using import telemffb.xmlutils as xu continues to work unchanged. The new package can be adopted incrementally via XmlConfigManager. Legacy xmlutils.py can be removed once all call sites are migrated.

walmis added 5 commits June 30, 2026 16:40
Split monolithic xmlutils.py (2383 lines) into a modular package:
- store.py: XML I/O, retry parsing, consolidation
- read.py: Read-only queries and 6-layer config cascade resolution
- write.py: Mutation operations (write, erase, clone, profile management)
- merge.py: Pure functions for merging/filtering data dicts
- types.py: TypedDict definitions for all config row shapes

xmlutils.py is now a thin backward-compat shim delegating to the new
package while preserving module-level globals (device, auto_user_root, etc.).

Added comprehensive type hints and docstrings across all modules.
All 229 tests pass (98 legacy + 94 new + 37 schema validation).
FileLock now accepts shared=True to acquire a shared lock on POSIX
(fcntl.LOCK_SH), allowing multiple processes to read concurrently while
writers block until all readers finish. Windows falls back to exclusive
locks since named mutexes lack reader-writer semantics.

- try_parse() acquires a shared lock per retry attempt
- update_roots() delegates locking to try_parse() (no outer wrapper)
- write_userconfig() / really_write_userconfig() remain exclusive
…-memory

try_parse() now reads raw bytes under the shared lock (fast I/O) then
releases it before calling ET.parse().  This lets writers proceed as soon
as the file read completes rather than waiting for full DOM construction.

A ParseError triggers a retry that re-acquires the lock and re-reads,
guarding against edge cases where another writer modifies the file between
our read and parse.
… typos in defaults.xml

- Update schema test to allow classdefaults_any to reference classes from any sim
- Fix 'JetrAircraft' -> 'JetAircraft' typo in classdefaults_BMS
- Fix 'GilderAircraft' -> 'GliderAircraft' typo in classdefaults_MSFS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant