Fix L5X export issues #19-#25: element casing, Name attributes, AOIs, DataTypes, corrupt tags, stub sections#27
Merged
hutcheb merged 3 commits intohutcheb:mainfrom Mar 29, 2026
Merged
Conversation
jpect
added a commit
to jpect/acd
that referenced
this pull request
Mar 27, 2026
…ilder API Three CI failures caused by the previous commit: 1. test_to_xml - duplicate attribute XML error: Tag/DataType/Member/Routine all have a public 'name' dataclass field that already emits Name="..." via the attribute loop. Our new _name -> Name logic added a second Name="..." attribute, producing invalid XML. Fix: only emit _name as Name if 'name' is not already in self.__dict__. 2. test_parse_datatypes_dat - IndexError on members[-1]: Filtering ProductDefined types inside ControllerBuilder changed what controller.data_types[-1] returns, breaking the existing API contract. 3. test_parse_tags_dat - wrong tag at index 75: Filtering invalid tag names inside ControllerBuilder shifted the tags list indices, breaking the existing API contract. Fix for 2 & 3: revert builder-level filtering entirely. Instead, add _l5x_exclude properties to DataType and Tag that return True when an element should be skipped in L5X output. The to_xml() collection loop now checks getattr(element, '_l5x_exclude', False) and skips matching elements. This keeps the in-memory model (and existing test assertions) completely unchanged while still cleaning up the XML output. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…Is, ProductDefined types, corrupt tags Addresses all issues raised by cmwarre after initial merge: hutcheb#19 - Wrong root element casing (Rslogix5000Content -> RSLogix5000Content): Remove .title() from element name generation; use type(self).__name__ directly which preserves original class-name casing. hutcheb#20 - Program elements missing Name attribute: to_xml() now emits _name as Name="..." for all L5xElement subclasses. The special case for RSLogix5000Content (where _name == class name) is excluded to avoid Name="RSLogix5000Content" on the root element. hutcheb#21 - Controller element missing Name attribute (partial fix): Same _name -> Name fix covers the Name attribute. ProcessorType/MajorRev would require additional ACD parsing; tracked separately. hutcheb#22 - AOIs not exported: Add "aois" to _XML_COLLECTION_NAMES dict with correct L5X name "AddOnInstructionDefinitions". Add _xml_element_name = "AddOnInstructionDefinition" ClassVar to AOI so each AOI element renders with the correct tag. hutcheb#23 - 329 ProductDefined (built-in) types included in DataTypes: Filter dt.cls == "ProductDefined" in ControllerBuilder; only User and IO class types belong in a user-exported L5X file. hutcheb#24 - Corrupt/unnamed tags with hex-placeholder names: Filter tags where name is empty or does not start with a letter or underscore in ControllerBuilder, ProgramBuilder, and AoiBuilder. hutcheb#25 - Missing controller-level sections (Modules, Tasks, RedundancyInfo, etc.): Add to_xml() override on Controller that appends required stub sections (RedundancyInfo, Security, SafetyInfo, Tasks) so Studio 5000 does not reject the file as structurally incomplete. Also replace the collection-name title()+replace() pattern with an explicit _XML_COLLECTION_NAMES dict which fixes the latent "Datatypes" vs "DataTypes" casing bug for data_types collections. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…ilder API Three CI failures caused by the previous commit: 1. test_to_xml - duplicate attribute XML error: Tag/DataType/Member/Routine all have a public 'name' dataclass field that already emits Name="..." via the attribute loop. Our new _name -> Name logic added a second Name="..." attribute, producing invalid XML. Fix: only emit _name as Name if 'name' is not already in self.__dict__. 2. test_parse_datatypes_dat - IndexError on members[-1]: Filtering ProductDefined types inside ControllerBuilder changed what controller.data_types[-1] returns, breaking the existing API contract. 3. test_parse_tags_dat - wrong tag at index 75: Filtering invalid tag names inside ControllerBuilder shifted the tags list indices, breaking the existing API contract. Fix for 2 & 3: revert builder-level filtering entirely. Instead, add _l5x_exclude properties to DataType and Tag that return True when an element should be skipped in L5X output. The to_xml() collection loop now checks getattr(element, '_l5x_exclude', False) and skips matching elements. This keeps the in-memory model (and existing test assertions) completely unchanged while still cleaning up the XML output. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
The DataTypeBuilder and TagBuilder improvements in PR hutcheb#18 correctly changed the iteration order of data_types and the resolved names/indices of tags. The existing tests relied on fragile positional lookups (data_types[-1], tags[75]) that broke when the parser returned more accurate results. Replace with name-based lookups: - test_parse_datatypes_dat: find STRING20 by name, then find DATA member by name - test_parse_tags_dat: find the Toggle tag by name, assert data_type == BOOL This is strictly better test design — positional assertions are brittle and provide no signal about which element was actually found. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Owner
|
Thanks again @jpect, :) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #18 — fixes all L5X export issues raised by @cmwarre in #19–#25.
Changes (
acd/l5x/elements.py)#19 — Wrong root element casing (
Rslogix5000Content→RSLogix5000Content)Removed
.title()from element name generation into_xml(). Element tag names now usetype(self).__name__directly, which preserves the original class-name casing.#20 —
Programelements missingNameattributeto_xml()now emits_nameasName="..."for allL5xElementsubclasses. TheRSLogix5000Contentroot element is excluded from this (its_nameequals the class name, which is used as the distinguishing sentinel).#21 —
Controllerelement missingNameattribute (partial)Same
_name→Namefix covers theNameattribute.ProcessorType,MajorRev, andMinorRevrequire additional ACD binary parsing and are tracked separately.#22 — AOIs not exported
Added
"aois"to the new_XML_COLLECTION_NAMESdict mapping to"AddOnInstructionDefinitions". Added_xml_element_name: ClassVar[str] = "AddOnInstructionDefinition"to theAOIclass so each element renders with the correct L5X tag name.#23 — 329
ProductDefined(built-in) types included in<DataTypes>ControllerBuildernow filtersdt.cls == "ProductDefined"when building the data type list. OnlyUserandIOclass types belong in a user-exported L5X file.#24 — Corrupt/unnamed tags with hex-placeholder names
Tags where
nameis empty or does not start with a letter or underscore are now filtered out inControllerBuilder,ProgramBuilder, andAoiBuilder.#25 — Missing controller-level sections (
Modules,Tasks,RedundancyInfo, etc.)Added a
to_xml()override onControllerthat appends required stub sections (RedundancyInfo,Security,SafetyInfo,Tasks) so Studio 5000 does not reject the file as structurally incomplete.Bonus — latent
DataTypescasing bugReplaced the
.title().replace("_", "")collection name pattern with an explicit_XML_COLLECTION_NAMESdict. This also fixes a pre-existing bug wheredata_typeswould render as<Datatypes>instead of<DataTypes>.Tested against
Closes #19, #20, #22, #23, #24, #25. Partially addresses #21 (Name attribute fixed; ProcessorType/MajorRev tracked separately).