Skip to content

chore: Upgrade PyModbus 3.6.9 → 3.16.1 with comprehensive API migration - #18

Merged
gavinying merged 5 commits into
mainfrom
copilot/upgrade-pymodbus-migrate-api
Oct 28, 2026
Merged

gavinying merged 5 commits into
mainfrom
copilot/upgrade-pymodbus-migrate-api

Conversation

Copilot AI commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

PyModbus 3.16.1 removed or significantly refactored multiple core APIs (BinaryPayloadBuilder, Endian constants, framer classes, datastore contexts). This requires both a compatibility shim and systematic migration across the codebase.

Changes

Compatibility Layer (modsim/compat.py - new file)

  • Reimplemented BinaryPayloadBuilder using struct module since it was removed entirely from PyModbus
  • Created Endian class to replace relocated constants

API Migration

  • Framer selection: replaced concrete framer classes with FramerType enum values (e.g., FramerSocket → FramerType.SOCKET)
  • Datastore initialization: ModbusSlaveContext → ModbusDeviceContext with address offset compensation (PyModbus internally uses address-1, requiring address+1 in block initialization to maintain address ranges)
  • TLS server: migrated from certfile/keyfile parameters to sslctx (SSL context object)
  • Client calls: updated from slave= to device_id= parameter throughout tests

Dependencies

  • Python constraint: >=3.8.2 → >=3.10 (PyModbus 3.16.1 requirement)
  • Updated tox test matrix: py310-py314
  • Regenerated poetry.lock and requirements.txt

Test Fixes

  • TLS integration test was sending raw PDU without MBAP header; fixed to send complete Modbus TCP frame format with proper 6-byte header

Impact

All 16 tests pass; full CLI behavior preserved across TCP, UDP, TLS, and serial transports. Code quality checks (mypy, linting, dependency analysis) passing.

Copilot AI and others added 3 commits October 28, 2026 03:31
- Updated Python requirement from >=3.8.2 to >=3.10
- Upgraded PyModbus from 3.6.9 to 3.16.1
- Created compat module for BinaryPayloadBuilder (removed in PyModbus)
- Migrated imports: Endian, framer classes to new locations
- Updated datastore initialization to use ModbusDeviceContext
- Changed framer usage from classes to FramerType enums
- Fixed TLS server to use SSL context instead of certfile/keyfile
- Updated test client calls to use device_id instead of slave parameter
- Fixed data initialization bug (bit pattern mismatch)
- Updated tox.ini to test Python 3.10-3.14 only

Tests: 15/16 passing. Only TLS test timing out - needs investigation

Co-authored-by: gavinying <10823762+gavinying@users.noreply.github.com>
Co-authored-by: gavinying <10823762+gavinying@users.noreply.github.com>
Co-authored-by: gavinying <10823762+gavinying@users.noreply.github.com>
Copilot AI changed the title [WIP] Upgrade PyModbus and migrate application API Upgrade PyModbus 3.6.9 → 3.16.1 with comprehensive API migration Oct 28, 2026
Copilot AI requested a review from gavinying October 28, 2026 03:42
@gavinying
gavinying requested a balanced review from Copilot October 28, 2026 03:49

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A critical mismatch between the CI workflow's Python matrix and the updated tox/pyproject version targets leaves the 3.10–3.14 acceptance criteria unmet alongside several unresolved supporting issues.

6 open issues
What changed in this PR

This PR upgrades PyModbus from 3.6.9 to 3.16.1, which removed/refactored several core APIs. Since a straight version bump is impossible, it adds a local compatibility shim (modsim/compat.py) reimplementing BinaryPayloadBuilder and an Endian constants class, and migrates the simulator to the new framer enum (FramerType), device-context datastore (ModbusDeviceContext with a +1 address offset to preserve ranges), and TLS sslctx-based server setup. It also raises the minimum Python to 3.10, updates the tox envlist, regenerates the lock/requirements, and fixes the TLS integration test to send a full MBAP-framed request. This keeps the CLI's TCP/UDP/TLS/serial behavior intact while targeting a modern PyModbus release (issue #16).

Changes:

  • New modsim/compat.py shim providing BinaryPayloadBuilder and Endian; migrated main.py/utils.py to PyModbus 3.16.1 APIs (device context, FramerType, sslctx).
  • Dependency/toolchain updates: pymodbus ~3.16.1, Python >=3.10, tox py310–py314, regenerated poetry.lock/requirements.txt.
  • Test updates: slave= → device_id= throughout, and a corrected TLS request/response assertion using a full Modbus TCP frame.
File Description
modsim/​compat.py New compatibility layer reimplementing BinaryPayloadBuilder/Endian; has an unused Union import and an obfuscated float-format string.
modsim/​main.py Migrates datastore/identity/TLS to 3.16.1 APIs; adds per-branch returns and a fallback error; unused Union import.
modsim/​utils.py Switches framer selection to FramerType and drops the removed binary option (docs still reference it).
tests/​test_modsim.py Updates client calls to device_id= and fixes the TLS frame; new MBAP comment slightly miscounts header bytes.
tox.ini Updates envlist to py310–py314 (CI workflow matrix not updated to match).
pyproject.toml Raises Python to >=3.10 and pymodbus to ~3.16.1.
requirements.txt Regenerated pin pymodbus==3.16.1 with updated marker.
poetry.lock Regenerated with Poetry 2.5.1 / lock-version 2.1, which diverges from the pinned Poetry 1.8.3 toolchain.

I focused the review on the migration correctness and dependency/CI consistency. The most consequential items are the CI matrix in .github/workflows/main.yml not being updated to the new 3.10–3.14 range (3.8/3.9 will fail, 3.13/3.14 untested) and the poetry.lock being regenerated with a newer Poetry than the one pinned across the toolchain. The remaining comments are smaller documentation/cleanliness items. I could not execute PyModbus 3.16.1 to validate the +1 datastore offset and the hand-written payload encoder at runtime, so those warrant a maintainer's confirmation.

Review effort: Balanced

Comment thread tox.ini
[tox]
skipsdist = true
envlist = py38, py39, py310, py311, py312
envlist = py310, py311, py312, py313, py314

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the CI matrix in .github/workflows/main.yml is now ["3.10", "3.11", "3.12", "3.13", "3.14"].

Comment thread modsim/compat.py Outdated
Comment thread modsim/compat.py Outdated
Comment on lines +81 to +83
fmt = f">{chr(102)}" # ">f" for big-endian float
packed = struct.pack(fmt, value)
value_int = struct.unpack(f">I", packed)[0]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced the obfuscated format strings with literal ">f" and ">I" strings.

Comment thread modsim/main.py Outdated
Comment thread modsim/utils.py
parser.add_argument(
"--framer",
choices=["ascii", "binary", "rtu", "socket", "tls"],
choices=["ascii", "rtu", "socket", "tls"],

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated both README.md and docs/index.md to drop the binary framing option from the serial transport description.

Comment thread tests/test_modsim.py Outdated
response = b""
while len(response) < 6:
part = client.recv(6 - len(response))
# Expect MBAP header (6 bytes) + PDU response (at least 1 byte)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the comment to read "MBAP header (7 bytes)" to match the actual 7-byte MBAP header structure.

…ocs, test comment

Co-authored-by: gavinying <10823762+gavinying@users.noreply.github.com>
@gavinying gavinying changed the title Upgrade PyModbus 3.6.9 → 3.16.1 with comprehensive API migration feat: Upgrade PyModbus 3.6.9 → 3.16.1 with comprehensive API migration Oct 28, 2026
@gavinying gavinying changed the title feat: Upgrade PyModbus 3.6.9 → 3.16.1 with comprehensive API migration Upgrade PyModbus 3.6.9 → 3.16.1 with comprehensive API migration Oct 28, 2026
@gavinying gavinying changed the title Upgrade PyModbus 3.6.9 → 3.16.1 with comprehensive API migration feat: Upgrade PyModbus 3.6.9 → 3.16.1 with comprehensive API migration Oct 28, 2026
@gavinying gavinying changed the title feat: Upgrade PyModbus 3.6.9 → 3.16.1 with comprehensive API migration chore: Upgrade PyModbus 3.6.9 → 3.16.1 with comprehensive API migration Oct 28, 2026
@gavinying
gavinying marked this pull request as ready for review October 28, 2026 05:21
@gavinying
gavinying merged commit efda8de into main Oct 28, 2026
9 of 11 checks passed
@gavinying
gavinying deleted the copilot/upgrade-pymodbus-migrate-api branch October 28, 2026 05:21
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.

[deps] Upgrade PyModbus and migrate the application API

3 participants