Add dual-dialect Tag parsing (PLC4X + nodeS7)#701
Merged
Conversation
Introduces PLC4XTag and NodeS7Tag as subtypes of Tag, each with their
own .parse() classmethod and __str__ that round-trips to the source
dialect. Adds parse_tag(s, *, strict=True) as a dispatcher that
autodetects dialect from syntax markers (',' -> nodeS7, ':TYPE' -> PLC4X).
Why: lets users of pyS7 / Node-RED bring their existing addressing
conventions (DB1,X0.0, M7.1, IW22) into ha-s7 and other integrations
without learning PLC4X syntax, while keeping PLC4X as the default in
docs and examples. Subtypes make the source dialect visible in types
and debuggers; isinstance(tag, Tag) still works internally.
Tag.from_string stays as an alias for PLC4XTag.parse for backwards
compatibility. Canonical protocol-layer code continues to work with
the base Tag type.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
gijzelaerr
added a commit
that referenced
this pull request
Apr 21, 2026
) The post-merge CI for #701 hit Errno 98 ("Address already in use") on ubuntu-24.04 / py3.14 inside test_server_context_manager. Root cause: tests picked ports via random.randint over narrow ranges (5k-20k ports) with no collision check, so two concurrent server starts could grab the same port, and re-runs on the same runner hit TIME_WAIT lingers. Fix: bind a throwaway socket to port 0, read the OS-assigned ephemeral port, close, and pass it to the server. The ephemeral pool is tens of thousands wide and the OS guarantees the port is free at the moment of pick — much smaller collision window than a 1-in-5000 random draw. snap7.server already sets SO_REUSEADDR so TIME_WAIT lingers don't bite either. One helper (`get_free_tcp_port`) lives in tests/conftest.py and is reused by test_s7_unified, test_optimizer, and test_stress. Added tests/__init__.py so `from .conftest import ...` works. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
PLC4XTagandNodeS7Tagare new subtypes ofTag, each with their own.parse()classmethod and a__str__that round-trips to the source dialect.parse_tag(s, *, strict=True)is a dispatcher that autodetects dialect from syntax markers:,selects nodeS7,:TYPEselects PLC4X. In strict mode, bare short forms likeM7.1orIW22raise;strict=Falsedispatches them to the nodeS7 parser (which accepts bareness).Tag.from_stringstays as an alias forPLC4XTag.parsefor backwards compatibility. All existing callers and tests continue to work.Why nodeS7?
pyS7and the Node-RED ecosystem useDB1,X0.0/DB1,R4/M10.5/IW22. Accepting that syntax alongside PLC4X makes it painless for existing users of those tools (including the competingha-s7plcHA integration) to migrate to python-snap7 4.0. The canonical in-memory representation is unchanged; only the edges (parse +__str__) know about dialect.New API
Test plan
🤖 Generated with Claude Code