Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
52582d0
feat: add macOS support and harden cross-platform memory scanner
JeanExtreme002 May 19, 2026
8b07ec4
ci: add workflow_dispatch trigger to python-package
JeanExtreme002 May 19, 2026
b25d94a
test: request write permission explicitly in test_editor (Windows fix)
JeanExtreme002 May 19, 2026
8addc04
ci: silence mypy errors in cross-platform code
JeanExtreme002 May 19, 2026
e76221b
test: tolerate OSError in scan-then-read loops
JeanExtreme002 May 19, 2026
9662c59
fix(win32): include PROCESS_QUERY_INFORMATION in default permission
JeanExtreme002 May 19, 2026
ed5af2b
ci: cap macOS matrix to a single Python to avoid runner-pool queueing
JeanExtreme002 May 19, 2026
a1be879
ci: drop Python 3.13 from the test matrix
JeanExtreme002 May 19, 2026
c154120
ci: switch macOS runner to macos-13 (Intel) for shorter queue
JeanExtreme002 May 19, 2026
95887de
ci: make macOS job non-blocking + 25min timeout
JeanExtreme002 May 19, 2026
75c34e9
ci: move macOS to push/cron/dispatch only (skip on pull_request)
JeanExtreme002 May 19, 2026
6f95e00
ci: remove macOS job entirely
JeanExtreme002 May 19, 2026
a47f073
feat(app): replace Tk sample with Cheat-Engine-style Qt app
JeanExtreme002 May 19, 2026
4e6c83d
style: apply auto-formatter pass across library, tests and app
JeanExtreme002 May 19, 2026
cf1290b
fix(linux): set explicit argtypes on process_vm_readv/writev
JeanExtreme002 May 20, 2026
37b9679
ci(linux): install Qt system libs so pytest-qt can import PySide6
JeanExtreme002 May 20, 2026
657e242
feat: macOS support + cross-platform hardening (v2.0)
JeanExtreme002 May 21, 2026
ed13c4e
chore: bump minimum Python to 3.10 and clean up version refs
JeanExtreme002 May 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions .flake8
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
[flake8]

max-line-length = 130
ignore = E701, E722
# E203: whitespace before ':' (black-compatible — black puts spaces around the
# colon in slices like data[i : i + n], which conflicts with PEP 8).
# E701: multiple statements on one line (colon) — used pervasively as a style choice.
# W503: line break before binary operator (black-compatible).
ignore = E203, E701, W503

per-file-ignores =
# __init__.py files are allowed to have unused imports and lines-too-long
*/__init__.py:F401

# Unused imports are allowed in the tests/package.py module and they must come after setting the current working directory.
tests/package.py:F401, E402
# __init__.py files are allowed to have unused imports and lines-too-long.
*/__init__.py:F401, E501
32 changes: 32 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Set this input '....'
3. Run the '....'
4. Scroll down to '....'
5. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**System (please complete the following information):**
- OS: [e.g. Windows]
- Python Version [e.g. 1.10]

**Additional context**
Add any other context about the problem here.
19 changes: 19 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
- A clear and concise description of what you want to happen.
- A clear and concise description of any alternative solutions or features you've considered.

**Is not your feature request related to a problem? Please describe**
A clear and concise description of how your feature can positively impact the project.

**Additional context**
Add any other context or screenshots about the feature request here.
35 changes: 35 additions & 0 deletions .github/ISSUE_TEMPLATE/questioning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: Questioning
about: Ask a question about the project
title: ''
labels: question
assignees: ''

---

**Is your problem described in the documentation? If so, please describe**
A clear and concise description of what is confusing in the documentation.

**Describe your question**
A clear and concise description of what the bug is.

**Is your question reproducible? Please describe**
Steps to reproduce the behavior:

1. Go to '...'
2. Set this input '....'
3. Run the '....'
4. Scroll down to '....'
5. See behavior

**Screenshots**
If applicable, add screenshots to help explain your problem.

**System**
If applicable, please complete the following information:

1. OS: [e.g. Windows]
2. Python Version [e.g. 1.10]

**Additional context**
Add any other context about the problem here.
21 changes: 21 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
#
# `open-pull-requests-limit: 0` disables routine version-update PRs (no weekly
# bump churn). Dependabot security advisories still surface via the Security
# tab and security-update PRs are unaffected by this limit, so vulnerabilities
# in psutil et al. remain visible.

version: 2

updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 0

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
27 changes: 27 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
**Why is this PR necessary, what does it do?**

<!--
IMPORTANT! Explain the **motivation** for making this change: what existing
problem the pull request solves or what new features it implements.
-->

**Checklist (complete all items)**:

- [ ] Added tests as necessary.
- [ ] There is no breaking change for existing features.

**References:**

<!-- (Nice to have)
Link tasks, issues, PRs that are related to this pull request, etc.
-->

No references to be shared.

**Notes:**

<!-- (Optional)
Explain some changes that can be useful when reviewing this pull request.
-->

No notes to be shared.
41 changes: 41 additions & 0 deletions .github/workflows/delete-pr-branch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Delete PR branch

on:
pull_request:
types: [closed]

permissions:
contents: write

jobs:
delete:
name: Delete head branch after PR close
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const ref = pr.head.ref;

const protectedBranches = new Set(["main", "gh-pages"]);
if (protectedBranches.has(ref)) {
core.info(`Refusing to delete protected branch: ${ref}`);
return;
}

try {
await github.rest.git.deleteRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `heads/${ref}`,
});
core.info(`Deleted branch: ${ref}`);
} catch (err) {
if (err.status === 422 || err.status === 404) {
core.info(`Branch already gone: ${ref}`);
return;
}
throw err;
}
46 changes: 46 additions & 0 deletions .github/workflows/lint-pr-title.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Lint PR title

on:
pull_request_target:
types:
- opened
- edited
- synchronize
- reopened

concurrency:
group: ${{ github.workflow }}-${{ github.event.number || github.ref }}
cancel-in-progress: true

permissions:
pull-requests: read

jobs:
lint:
name: Conventional commit title
runs-on: ubuntu-latest
steps:
- name: Lint PR title
uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
# Conventional commit types accepted in titles. Mirrors the set the
# PR labeler recognizes in .github/workflows/labeler.yml.
types: |
feat
fix
perf
refactor
revert
docs
ci
build
chore
test
style
# Subject must start lowercase and not end with a period.
subjectPattern: ^(?![A-Z])(?!.*\.$).+$
subjectPatternError: |
The subject "{subject}" found in "{title}" must start with a
lowercase letter and must not end with a period.
92 changes: 82 additions & 10 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,107 @@
name: Python Package

on:
# `push` restricted to `main` so feature branches only run via `pull_request`.
# Otherwise every push to a branch with an open PR would trigger the workflow
# twice (once for `push`, once for `pull_request`) — doubling CI cost and
# latency for no benefit.
push:
branches: [main]
pull_request:
# Allow re-running the workflow without an empty push (handy after the
# workflow gets `disabled_inactivity` after 60 days idle).
workflow_dispatch:
schedule:
- cron: '0 0 */7 * *'

# Cancel an in-flight run when a newer commit lands on the same ref. Keeps the
# queue lean and stops stale runs from blocking the merge button.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install lint deps
run: |
python -m pip install --upgrade pip
pip install flake8
- name: Lint
run: |
flake8 PyMemoryEditor tests

type-check:
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dev deps
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run mypy
run: |
mypy PyMemoryEditor

build:
needs: lint
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ['3.10', '3.11', '3.12', '3.13']
os:
- ubuntu-latest
- windows-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install Qt system libraries (Linux)
# PySide6 links against libEGL/libGL/libxkbcommon/libfontconfig and the
# XCB stack at import time, even when running under the `offscreen`
# platform plugin. The Ubuntu runner ships without them, so pytest-qt's
# `import QtGui` crashes with `libEGL.so.1: cannot open shared object`.
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
libegl1 \
libgl1 \
libxkbcommon0 \
libfontconfig1 \
libdbus-1-3 \
libxcb-cursor0 \
libxcb-icccm4 \
libxcb-image0 \
libxcb-keysyms1 \
libxcb-randr0 \
libxcb-render-util0 \
libxcb-shape0 \
libxcb-sync1 \
libxcb-xfixes0 \
libxcb-xinerama0 \
libxcb-xkb1 \
libxkbcommon-x11-0
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -e ".[dev]"
- name: Test with pytest
env:
QT_QPA_PLATFORM: offscreen
run: |
pytest tests -v -s -x
- name: Install package
run: |
pip install PyMemoryEditor
pytest tests -v -s -x --cov=PyMemoryEditor --cov-report=term
Loading
Loading