Skip to content

Backport bug fixes from the ipfedor fork#25

Merged
gsokoll merged 2 commits into
mainfrom
backport/ws1-bugfixes
Jun 12, 2026
Merged

Backport bug fixes from the ipfedor fork#25
gsokoll merged 2 commits into
mainfrom
backport/ws1-bugfixes

Conversation

@gsokoll

@gsokoll gsokoll commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Part of #24. Reimplements six fixes from https://github.com/ipfedor/codescribe (commits 2e93ff4, 7eaec7d, 0dbb093) to our standards (ASCII source, English comments, no blanket exception swallowing).

Changes

  1. Visualisation/POU name collision (data loss). A visualisation named like a POU exported to the same Name.xml, one overwrote the other. Visualisations now export as Name.vis.xml; import handles the new suffix, and old plain .xml files still import through the existing bare-xml path. README migration note added.
  2. Mutation during iteration in remove_tracked_communication_devices: children are now snapshotted with list() before removal. Removing while iterating the live collection skips entries.
  3. Missing GUID mappings (data loss). Persistent GVLs (261bd6e6) and methods without a return type (f89f7675) were UNKNOWN and silently skipped on export. Both now export (as .gvl.xml/.gvl.st and .st respectively). import_gvl accepts either GVL type when resolving the imported object. INTERFACE, TASK, IMAGEPOOL, TEXTLIST, GLOBAL_TEXTLIST, PROPERTY_METHOD GUIDs are named in the map but deliberately not given export functions yet.
  4. Silent skip of unmapped GUIDs in export. The fork hit this with an LD nested inside a CFC: the child diagram had an unmapped GUID and vanished from the export without a trace. export_child now falls back to a native export and prints a warning naming the object and GUID on failure, then walks the children.
  5. project_template.py used scriptengine.projects.primary.path instead of its project parameter (latent, both callers pass primary today).
  6. DUT import normalization: strip() + "\n" like import_st, for byte-identical export/import/export round-trips.

Live validation required before merge (CODESYS SP11 + CoDeScribe-test-2.project)

  • Add a visualisation named identically to a POU; export; confirm both Main.st and Main.vis.xml exist; round-trip import; F11 with 0 errors.
  • Add a persistent GVL and a method without a return type; export; confirm the GUIDs CODESYS reports match 261bd6e6-249c-4232-bb6f-84c2fbeef430 and f89f7675-27f1-46b3-8abb-b7da8e774ffd (the fork is the claim, not the evidence) and the files appear.
  • Known caveat carried from the fork: objects exported via the UNKNOWN fallback are not in OBJECT_TYPE_TO_EXPORT_FUNCTION, so remove_tracked_objects does not remove them before import; importing such a file onto an existing object relies on import_native conflict handling. Worth observing during validation.

CI: ascii-check, IronPython compile, and import smoke all pass locally with IronPython 2.7.12.

- export visualisations as <name>.vis.xml to avoid overwriting a POU of
  the same name (Main program + Main visualisation collided on Main.xml)
- snapshot children before removing in remove_tracked_communication_devices
  (mutation during iteration skipped entries)
- map GUIDs for persistent GVLs and methods without a return type, which
  were silently skipped on export; name INTERFACE, TASK, IMAGEPOOL,
  TEXTLIST, GLOBAL_TEXTLIST, PROPERTY_METHOD GUIDs without export mapping
- fall back to native export with a warning for unmapped GUIDs instead of
  silently dropping the object (seen with an LD nested inside a CFC)
- use the project parameter instead of scriptengine.projects.primary in
  project_template.py
- normalize DUT declaration whitespace on import for idempotent round-trips

Credit: reimplemented from ipfedor/codescribe commits 2e93ff4, 2dbb0939,
7eaec7d, 0dbb093. Refs #24.
@gsokoll

gsokoll commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

Live validation on CODESYS V3.5 SP11 (CR711s compound test project), automated via --runscript.

Passed

  • Export of the full test project: tree complete, MyFB.NoRetTest.st, action/transition/method/property files all present. Round-trip (import, build, re-export) succeeds with only two known-benign diff classes: object GUID references in native xml change because import recreates POUs with fresh GUIDs (pre-existing, matches the commented-out regex list in write_native), and empty implementations gain one newline on first round-trip then converge (pre-existing import_st behaviour).
  • GUID verification: 98a2708a (Task) and 792f2eb6 (property accessor) confirmed live in the project dump; 225bfe47, 8753fe6f and the rest of the existing map also confirmed. The full fork GUID set is independently corroborated by the mapping list in 18thCentury/CodeSys export.py, which names f89f7675 "method no ret", 6654496c "interface", 261bd6e6 "gvl_Persistent", 2bef0454/63784cbb textlists, bb0b9044 ImagePool.
  • One nuance: create_method() without a return type produces the plain METHOD GUID f8a58466 on SP11, so the METHOD_NORET GUID could not be reproduced by script. It may be produced by GUI creation or newer CODESYS versions. The mapping is harmless either way since both route to export_method.

Outstanding (GUI-only objects, ScriptEngine cannot create them)

  • Visualisation named identically to a POU, confirm Main.st plus Main.vis.xml.
  • Persistent Variables object, confirm .gvl.xml/.gvl.st pair and the 261bd6e6 GUID.
  • GUI-created method with blank return type, to see whether SP11 ever emits f89f7675.

Live GUI testing showed that adding a visualisation brings a Visualization
Manager whose GUID was unmapped, so the UNKNOWN fallback exported it as
Visualization Manager.xml. Importing that file makes CODESYS raise an
interactive overwrite dialog on every Import From Files, which cannot be
answered from a script. The manager, target/web visualisation and
__VisualizationStyle objects are now named in the GUID map without an
export function, so they stay in the project template like the other
service objects. Visualisations themselves still export as .vis.xml.

GUIDs confirmed live on SP11 (4d3fdb8f, 8e687a04) and via the mapping
list in 18thCentury/CodeSys export.py (bc63f5fa, 0fdbf158).
@gsokoll

gsokoll commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

GUI and hardware validation complete. All outstanding items pass.

GUI objects (created in CODESYS SP11, exported, round-tripped)

  • Visualisation named PLC_PRG alongside the PLC_PRG program: PLC_PRG.st and PLC_PRG.vis.xml coexist in the export and the visualisation survives the import round-trip. Collision fix confirmed.
  • Persistent Variables object: exports as PersistentVars.gvl.xml/.gvl.st with TypeGuid 261bd6e6-249c-4232-bb6f-84c2fbeef430, confirming the fork GUID live. On main this object was silently dropped from the export.
  • GUI-created method with blank return type carries the plain METHOD GUID f8a58466, same as the script-created one, so SP11 never emits f89f7675. That GUID belongs to newer CODESYS versions; the mapping stays as forward compatibility and is untriggerable on SP11.

Hardware

  • StandardPLC.Application with all test content (incl. persistent vars, 46 bytes in the persistent data area) built with 0 errors, downloaded to a physical CR711s at 172.20.10.245, and runs.

Found and fixed during validation (f3cfdea)

  • Adding a visualisation brings a Visualization Manager whose GUID was unmapped, so the UNKNOWN fallback exported Visualization Manager.xml, and importing that file raised an interactive overwrite dialog on every Import From Files. The manager, target/web visualisation and __VisualizationStyle GUIDs are now named without an export function (template carries them, same as other service objects). Re-test: export contains no manager xml and the round-trip runs with no interactive dialog. Note for existing repos: a previously committed Visualization Manager.xml still triggers the dialog once on import until a fresh export removes it.

Round-trip diffs on the final run are limited to the two known benign classes (fresh object-GUID references in native xml after import recreates objects; one-time trailing-newline normalization on declarations).

@gsokoll gsokoll merged commit 06847da into main Jun 12, 2026
2 checks passed
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