Skip to content

chore: bump version to 3.0.0 - #99

Merged
JeanExtreme002 merged 1 commit into
mainfrom
chore/bump-3.0.0
Sep 8, 2026
Merged

chore: bump version to 3.0.0#99
JeanExtreme002 merged 1 commit into
mainfrom
chore/bump-3.0.0

Conversation

@JeanExtreme002

Copy link
Copy Markdown
Owner

Bumps PyMemoryEditor/__init__.py to 3.0.0. Hatch reads the version from
there ([tool.hatch.version]), so it is the only place it lives — confirmed by
building an sdist, which came out as pymemoryeditor-3.0.0.tar.gz.

Why major and not minor

One change forces it. read_process_memory(addr, int, N) with N in 3, 5, 6 or
7 and the value's top bit set returns a different number now — on every
platform, with no exception raised.

bytes in memory: FF FF FF   (a 24-bit unsigned field at its maximum)

2.2.1  ->  16777215
3.0.0  ->  -1

Cheat Engine offers a "3 Bytes" type precisely because games cap money and
score in 24-bit fields, and this library exists to reproduce that workflow — so
a reader following a tutorial lands exactly there. An existing script, with no
line changed:

money = process.read_process_memory(addr, int, 3)
if money < 1000:
    process.write_process_memory(addr, int, 3, 16777215)   # "top up"
value read money < 1000 result
2.2.1 16777215 False does nothing — correct
3.0.0 −1 True tops up a field already at maximum

The guard inverted, and in a memory editor the branch that flips is the one
that writes. The round trip also stops closing: the write path's range
check accepts the union of the signed and unsigned ranges, so 16777215 is
still a valid 3-byte write and reads back as -1.

Half the value space of each affected width changes sign (8388608–16777215
at width 3, and the equivalent band at 5, 6 and 7). Widths 1, 2, 4 and 8 are
untouched, and so is the int default of 4.

Why the other five behaviour changes would not have needed one

Measured across 220 read combinations, only 4 change a value silently — the
ones above. Of the rest, 88 turn a value into a ValueError, and no working
code depends on what they returned before:

  • a width wider than the type's largest C representation overflowed the
    caller's buffer — get_c_type_of(bool, 8) sized 1 byte for an 8-byte read,
    and int at 16 overflowed 8;
  • float at any width but 4 or 8 returned a plausible-looking number decoded
    from bytes nobody read (5.5e-318);
  • Linux read and wrote sizeof(buffer) instead of the width asked for, so the
    same call answered differently per platform.

str and bytes did not change at all — none of their 44 combinations.

Also shipping

The MCP server (14 tools, opt-in through the mcp extra — the core library
stays dependency-free), iter_processes() as a dependency-free counterpart to
psutil.process_iter(), and decode_scan_target / make_predicate promoted
from private.

Ordering

Merge #96 first. It is still open, and it adds a session cap whose refusal
is new behaviour an embedder could hit. This branch is a one-line change and
rebases trivially, so it should be the last thing in before the release is cut.

Major, not minor, because of one change: `read_process_memory(addr, int, N)`
with N in 3, 5, 6 or 7 and the value's top bit set now returns a different
number, on every platform, with no exception raised.

    bytes in memory: FF FF FF   (a 24-bit unsigned field at its maximum)

    2.2.1  ->  16777215
    3.0.0  ->  -1

Half the value space of each affected width changes sign. A guard like
`if money < 1000` silently inverts, and in a memory editor the branch that
flips is the one that writes. The round trip also stops closing: the range
check on the write path accepts the union of the signed and unsigned ranges,
so 16777215 is still a valid 3-byte write and reads back as -1.

Nothing in the API signals it. Measured across 220 read combinations, the
whole surface of the change is four of them — but semver is not about how many
callers break, it is about whether they can break without knowing.

The five other behaviour changes do not on their own need a major. Their
previous behaviour was memory-unsafe or meaningless, so no working code
depends on it: a width wider than the type's C representation overflowed the
caller's buffer (`get_c_type_of(bool, 8)` sized 1 byte for an 8-byte read),
`float` at 3 bytes returned a plausible-looking number from unread bytes, and
Linux read and wrote `sizeof(buffer)` rather than the width asked for, which
made the same call answer differently per platform.

Also in this release: the MCP server (14 tools, opt-in via the `mcp` extra),
`iter_processes()`, and `decode_scan_target` / `make_predicate` promoted from
private.
@github-actions github-actions Bot added the lib Library changes (PyMemoryEditor/) label Sep 8, 2026
@codecov

codecov Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.89%. Comparing base (23422f9) to head (56ee11e).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main      #99   +/-   ##
=======================================
  Coverage   89.89%   89.89%           
=======================================
  Files          41       41           
  Lines        3632     3632           
=======================================
  Hits         3265     3265           
  Misses        367      367           
Flag Coverage Δ
Linux-py3.10 64.94% <100.00%> (ø)
Linux-py3.11 64.94% <100.00%> (ø)
Linux-py3.12 64.94% <100.00%> (ø)
Linux-py3.13 64.94% <100.00%> (ø)
Windows-py3.10 66.51% <100.00%> (ø)
Windows-py3.11 66.51% <100.00%> (ø)
Windows-py3.12 66.51% <100.00%> (ø)
Windows-py3.13 66.51% <100.00%> (ø)
macOS-py3.12 87.22% <100.00%> (ø)
mcp-Linux-py3.12 91.42% <ø> (ø)
mcp-Windows-py3.12 91.63% <ø> (ø)
mcp-macOS-py3.12 91.52% <ø> (ø)
speed-Linux-py3.12 66.54% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
PyMemoryEditor/__init__.py 96.66% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@JeanExtreme002
JeanExtreme002 merged commit ce0eda9 into main Sep 8, 2026
19 checks passed
@github-actions
github-actions Bot deleted the chore/bump-3.0.0 branch September 8, 2026 23:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lib Library changes (PyMemoryEditor/)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant