PyMemoryEditor 2.2.0__tar.gz → 2.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PKG-INFO +6 -5
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/__init__.py +1 -1
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/macos/functions.py +35 -2
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/README.md +5 -4
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/index.md +1 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/platforms/test_macos_transient_reads.py +39 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/.flake8 +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/.gitignore +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/.readthedocs.yaml +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/CODE_OF_CONDUCT.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/CONTRIBUTING.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/LICENSE +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/Makefile +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/__main__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/__init__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/_auto_refresh_dialog.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/_icon.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/_widgets.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/application.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/assets/icon.svg +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/cheat_entry.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/cheat_poll_worker.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/cheat_table.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/log_console_dialog.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/main_window.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/memory_map_dialog.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/memory_viewer_dialog.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/modules_dialog.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/open_process_dialog.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/pointer_chain_dialog.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/pointer_scan_dialog.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/results_view.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/scan_types.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/scan_worker.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/scanner_panel.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/threads_dialog.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/app/value_types.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/enums.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/linux/functions.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/linux/libc.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/linux/process.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/linux/types.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/macos/__init__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/macos/libsystem.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/macos/process.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/macos/types.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/process/__init__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/process/abstract.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/process/errors.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/process/info.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/process/module_info.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/process/pointer_scan.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/process/region.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/process/remote_pointer.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/process/scanning.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/process/thread_info.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/process/util.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/py.typed +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/util/__init__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/util/convert.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/util/pattern.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/util/scan.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/util/scan_numpy.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/enums/__init__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/enums/memory_allocation_states.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/enums/memory_protections.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/enums/memory_types.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/enums/process_operations.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/enums/standard_access_rights.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/functions.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/process.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/types.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/SECURITY.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/assets/screenshots/app.png +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/assets/social-preview.html +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/assets/social-preview.png +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/_static/.gitkeep +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/_static/custom.css +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/_templates/layout.html +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/api/enums.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/api/errors.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/api/index.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/api/memory-region.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/api/module-info.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/api/openprocess.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/api/pointer-path.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/api/remote-pointer.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/api/thread-info.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/api/utilities.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/app.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/conf.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/contributing.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/funding.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/glossary.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/guide/allocate-free.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/guide/index.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/guide/logging.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/guide/memory-regions.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/guide/modules-threads.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/guide/opening-process.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/guide/pattern-scan.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/guide/pointer-scan.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/guide/pointers.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/guide/read-write.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/guide/searching.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/installation.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/license.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/platform-notes.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/quickstart.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/requirements.txt +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/troubleshooting.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/docs/why.md +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/pyproject.toml +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/app/__init__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/app/test_app_cheat_entry.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/app/test_app_pointer_parsing.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/app/test_app_scan_request.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/app/test_app_smoke.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/app/test_app_value_types.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/app/test_app_widgets.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/app/test_auto_refresh_dialog.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/app/test_cheat_poll_worker.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/app/test_open_process_dialog.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/app/test_refine_scan_worker.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/conftest.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/core/__init__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/core/test_errors.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/core/test_logger.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/memory/__init__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/memory/test_allocate_free.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/memory/test_bufflength_inference.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/memory/test_editor.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/memory/test_partial_io.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/memory/test_read_into.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/memory/test_str_boundary.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/memory/test_str_decode_consistency.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/memory/test_typed_accessors.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/memory/test_write_safety.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/memory/test_write_str_bytes_width.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/platforms/__init__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/platforms/test_bitness.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/platforms/test_bitness_fallback_warns.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/platforms/test_linux_types.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/platforms/test_macos_protect.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/platforms/test_win32_permissions.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/pointer/__init__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/pointer/test_pointer_chain.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/pointer/test_pointer_scan.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/pointer/test_remote_pointer.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/process/__init__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/process/test_memory_region.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/process/test_module_enumeration.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/process/test_partial_name_match.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/process/test_process_enumeration.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/process/test_process_lookup.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/process/test_thread_enumeration.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/scan/__init__.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/scan/test_chunking_integration.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/scan/test_pattern_compile.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/scan/test_pattern_scan.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/scan/test_region_snapshot.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/scan/test_scan.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/scan/test_scan_numpy.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/scan/test_scan_properties.py +0 -0
- {pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/scan/test_scanning_helper.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: PyMemoryEditor
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: Read, write and scan process memory in a few lines of Python — Cheat Engine-style scans, pointer chains and AOB search on Windows, Linux and macOS.
|
|
5
5
|
Project-URL: Homepage, https://github.com/JeanExtreme002/PyMemoryEditor
|
|
6
6
|
Project-URL: Documentation, https://pymemoryeditor.readthedocs.io
|
|
@@ -71,18 +71,19 @@ A pure-Python library (built on [ctypes](https://docs.python.org/3/library/ctype
|
|
|
71
71
|
<i>One unified API. Three operating systems. No C compiler. No native build step.</i>
|
|
72
72
|
</p>
|
|
73
73
|
|
|
74
|
-
<p align="center">
|
|
75
|
-
Runs on <b>🪟 Windows</b> · <b>🐧 Linux</b> · <b>🍎 macOS</b> — 32-bit and 64-bit.
|
|
76
|
-
</p>
|
|
77
|
-
|
|
78
74
|
<p align="center">
|
|
79
75
|
<a href="https://github.com/JeanExtreme002/PyMemoryEditor/actions/workflows/python-package.yml"><img src="https://github.com/JeanExtreme002/PyMemoryEditor/actions/workflows/python-package.yml/badge.svg" alt="Python Package" /></a>
|
|
76
|
+
<a href="https://codecov.io/gh/JeanExtreme002/PyMemoryEditor"><img src="https://codecov.io/gh/JeanExtreme002/PyMemoryEditor/branch/main/graph/badge.svg" alt="Coverage" /></a>
|
|
80
77
|
<a href="https://pypi.org/project/PyMemoryEditor/"><img src="https://img.shields.io/pypi/v/PyMemoryEditor" alt="Pypi" /></a>
|
|
81
78
|
<a href="https://github.com/JeanExtreme002/PyMemoryEditor"><img src="https://img.shields.io/pypi/l/PyMemoryEditor" alt="License" /></a>
|
|
82
79
|
<a href="https://github.com/JeanExtreme002/PyMemoryEditor"><img src="https://img.shields.io/badge/python-3.10+-8A2BE2" alt="Python Version" /></a>
|
|
83
80
|
<a href="https://pypi.org/project/PyMemoryEditor/"><img src="https://static.pepy.tech/personalized-badge/pymemoryeditor?period=total&units=international_system&left_color=grey&right_color=orange&left_text=Downloads" alt="Downloads" /></a>
|
|
84
81
|
</p>
|
|
85
82
|
|
|
83
|
+
<p align="center">
|
|
84
|
+
Runs on <b>Windows</b> · <b>Linux</b> · <b>macOS</b> — 32-bit and 64-bit.
|
|
85
|
+
</p>
|
|
86
|
+
|
|
86
87
|
<p align="center">
|
|
87
88
|
<img src="https://raw.githubusercontent.com/JeanExtreme002/PyMemoryEditor/main/assets/screenshots/app.png" alt="PyMemoryEditor app attached to a running process" width="820" />
|
|
88
89
|
</p>
|
|
@@ -311,6 +311,31 @@ _PAGE_GONE_KRS = (
|
|
|
311
311
|
KERN_MEMORY_ERROR,
|
|
312
312
|
)
|
|
313
313
|
|
|
314
|
+
# KERN_PROTECTION_FAILURE is tolerated by a full-address-space *sweep* only,
|
|
315
|
+
# never by a read of caller-supplied addresses — hence a second tuple rather
|
|
316
|
+
# than another entry above.
|
|
317
|
+
#
|
|
318
|
+
# The sweeps walk every region the filter accepted and have no opinion about
|
|
319
|
+
# any single one: a range the kernel declines to hand over is a range with no
|
|
320
|
+
# matches in it, and aborting the whole scan over it loses every region that
|
|
321
|
+
# came after. `search_values_by_addresses` is the opposite case — the caller
|
|
322
|
+
# named those addresses, and its documented `raise_error=True` must still be
|
|
323
|
+
# able to report that one of them could not be read. Anything in the tuple
|
|
324
|
+
# above is swallowed even when `raise_error` is set (see
|
|
325
|
+
# process.scanning.iter_values_for_addresses), so putting kr=2 there would
|
|
326
|
+
# silently turn "permission denied" into the same `(address, None)` the caller
|
|
327
|
+
# gets for an address in a gap.
|
|
328
|
+
#
|
|
329
|
+
# Honest limits of what is known here. This was added because a plain
|
|
330
|
+
# search_by_value over the current process died with kr=2 on GitHub's
|
|
331
|
+
# virtualized macOS runners, on a 22 MB region that reported VM_PROT_READ and
|
|
332
|
+
# Shared=False. The mechanism was not established. It does *not* reproduce
|
|
333
|
+
# locally: probing all 135 scannable regions of a live process yields only kr=1
|
|
334
|
+
# and kr=10, and a page deliberately re-protected to PROT_NONE (or never
|
|
335
|
+
# mapped) answers KERN_INVALID_ADDRESS, not kr=2 — so the usual
|
|
336
|
+
# "protection changed under us" story does not explain it.
|
|
337
|
+
_SWEEP_SKIPPABLE_KRS = _PAGE_GONE_KRS + (KERN_PROTECTION_FAILURE,)
|
|
338
|
+
|
|
314
339
|
|
|
315
340
|
class MachReadError(OSError):
|
|
316
341
|
"""OSError subclass that carries the underlying kern_return_t."""
|
|
@@ -494,6 +519,14 @@ def _is_transient(exc: BaseException) -> bool:
|
|
|
494
519
|
return isinstance(exc, MachReadError) and exc.kr in _PAGE_GONE_KRS
|
|
495
520
|
|
|
496
521
|
|
|
522
|
+
def _is_skippable_by_sweep(exc: BaseException) -> bool:
|
|
523
|
+
"""
|
|
524
|
+
Same as :func:`_is_transient`, plus the codes only a full-address-space
|
|
525
|
+
sweep may skip. See :data:`_SWEEP_SKIPPABLE_KRS`.
|
|
526
|
+
"""
|
|
527
|
+
return isinstance(exc, MachReadError) and exc.kr in _SWEEP_SKIPPABLE_KRS
|
|
528
|
+
|
|
529
|
+
|
|
497
530
|
def _query_region(task: int, address: int):
|
|
498
531
|
"""Return the region containing `address`, or None when the query fails."""
|
|
499
532
|
addr = mach_vm_address_t(address)
|
|
@@ -683,7 +716,7 @@ def search_addresses_by_value(
|
|
|
683
716
|
scan_type,
|
|
684
717
|
_make_read_chunk(task),
|
|
685
718
|
progress_information=progress_information,
|
|
686
|
-
transient_error_check=
|
|
719
|
+
transient_error_check=_is_skippable_by_sweep,
|
|
687
720
|
)
|
|
688
721
|
|
|
689
722
|
|
|
@@ -1044,7 +1077,7 @@ def search_addresses_by_pattern(
|
|
|
1044
1077
|
length,
|
|
1045
1078
|
_make_read_chunk(task),
|
|
1046
1079
|
progress_information=progress_information,
|
|
1047
|
-
transient_error_check=
|
|
1080
|
+
transient_error_check=_is_skippable_by_sweep,
|
|
1048
1081
|
)
|
|
1049
1082
|
|
|
1050
1083
|
|
|
@@ -13,18 +13,19 @@ A pure-Python library (built on [ctypes](https://docs.python.org/3/library/ctype
|
|
|
13
13
|
<i>One unified API. Three operating systems. No C compiler. No native build step.</i>
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
|
-
<p align="center">
|
|
17
|
-
Runs on <b>🪟 Windows</b> · <b>🐧 Linux</b> · <b>🍎 macOS</b> — 32-bit and 64-bit.
|
|
18
|
-
</p>
|
|
19
|
-
|
|
20
16
|
<p align="center">
|
|
21
17
|
<a href="https://github.com/JeanExtreme002/PyMemoryEditor/actions/workflows/python-package.yml"><img src="https://github.com/JeanExtreme002/PyMemoryEditor/actions/workflows/python-package.yml/badge.svg" alt="Python Package" /></a>
|
|
18
|
+
<a href="https://codecov.io/gh/JeanExtreme002/PyMemoryEditor"><img src="https://codecov.io/gh/JeanExtreme002/PyMemoryEditor/branch/main/graph/badge.svg" alt="Coverage" /></a>
|
|
22
19
|
<a href="https://pypi.org/project/PyMemoryEditor/"><img src="https://img.shields.io/pypi/v/PyMemoryEditor" alt="Pypi" /></a>
|
|
23
20
|
<a href="https://github.com/JeanExtreme002/PyMemoryEditor"><img src="https://img.shields.io/pypi/l/PyMemoryEditor" alt="License" /></a>
|
|
24
21
|
<a href="https://github.com/JeanExtreme002/PyMemoryEditor"><img src="https://img.shields.io/badge/python-3.10+-8A2BE2" alt="Python Version" /></a>
|
|
25
22
|
<a href="https://pypi.org/project/PyMemoryEditor/"><img src="https://static.pepy.tech/personalized-badge/pymemoryeditor?period=total&units=international_system&left_color=grey&right_color=orange&left_text=Downloads" alt="Downloads" /></a>
|
|
26
23
|
</p>
|
|
27
24
|
|
|
25
|
+
<p align="center">
|
|
26
|
+
Runs on <b>Windows</b> · <b>Linux</b> · <b>macOS</b> — 32-bit and 64-bit.
|
|
27
|
+
</p>
|
|
28
|
+
|
|
28
29
|
<p align="center">
|
|
29
30
|
<img src="https://raw.githubusercontent.com/JeanExtreme002/PyMemoryEditor/main/assets/screenshots/app.png" alt="PyMemoryEditor app attached to a running process" width="820" />
|
|
30
31
|
</p>
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
<p align="center">
|
|
17
17
|
<a href="https://github.com/JeanExtreme002/PyMemoryEditor/actions/workflows/python-package.yml"><img src="https://github.com/JeanExtreme002/PyMemoryEditor/actions/workflows/python-package.yml/badge.svg" alt="Python Package" /></a>
|
|
18
|
+
<a href="https://codecov.io/gh/JeanExtreme002/PyMemoryEditor"><img src="https://codecov.io/gh/JeanExtreme002/PyMemoryEditor/branch/main/graph/badge.svg" alt="Coverage" /></a>
|
|
18
19
|
<a href="https://pypi.org/project/PyMemoryEditor/"><img src="https://img.shields.io/pypi/v/PyMemoryEditor" alt="Pypi" /></a>
|
|
19
20
|
<a href="https://github.com/JeanExtreme002/PyMemoryEditor"><img src="https://img.shields.io/pypi/l/PyMemoryEditor" alt="License" /></a>
|
|
20
21
|
<a href="https://github.com/JeanExtreme002/PyMemoryEditor"><img src="https://img.shields.io/badge/python-3.10+-8A2BE2" alt="Python Version" /></a>
|
|
@@ -25,6 +25,7 @@ if sys.platform != "darwin":
|
|
|
25
25
|
from PyMemoryEditor.macos.functions import ( # noqa: E402
|
|
26
26
|
MachPartialReadError,
|
|
27
27
|
MachReadError,
|
|
28
|
+
_is_skippable_by_sweep,
|
|
28
29
|
_is_transient,
|
|
29
30
|
)
|
|
30
31
|
from PyMemoryEditor.macos.types import ( # noqa: E402
|
|
@@ -59,6 +60,12 @@ def test_a_vanished_page_lets_the_scan_continue(kr):
|
|
|
59
60
|
# KERN_MEMORY_FAILURE directly above KERN_MEMORY_ERROR and documents it as
|
|
60
61
|
# permanent, which is exactly the distinction being drawn here; KERN_FAILURE is
|
|
61
62
|
# what task_for_pid returns without the debugger entitlement.
|
|
63
|
+
#
|
|
64
|
+
# KERN_PROTECTION_FAILURE stays here even though a *sweep* skips it (see
|
|
65
|
+
# test_a_sweep_may_skip_a_protected_range below): this classifier also drives
|
|
66
|
+
# search_values_by_addresses, whose caller named the addresses and whose
|
|
67
|
+
# documented raise_error=True must still be able to report one it could not
|
|
68
|
+
# read.
|
|
62
69
|
@pytest.mark.parametrize(
|
|
63
70
|
"kr", (KERN_FAILURE, KERN_PROTECTION_FAILURE, KERN_MEMORY_FAILURE)
|
|
64
71
|
)
|
|
@@ -79,3 +86,35 @@ def test_a_short_read_lets_the_scan_continue():
|
|
|
79
86
|
def test_a_non_mach_error_is_never_transient():
|
|
80
87
|
assert not _is_transient(OSError("some unrelated failure"))
|
|
81
88
|
assert not _is_transient(ValueError("not an OSError at all"))
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# A full-address-space sweep is the one caller allowed to skip a range the
|
|
92
|
+
# kernel refuses to hand over. It has no opinion about any single region, and
|
|
93
|
+
# aborting on one loses every region that came after it — which is how a plain
|
|
94
|
+
# search_by_value died on a virtualized macOS CI runner.
|
|
95
|
+
@pytest.mark.parametrize(
|
|
96
|
+
"kr",
|
|
97
|
+
(
|
|
98
|
+
KERN_INVALID_ADDRESS,
|
|
99
|
+
KERN_INVALID_ARGUMENT,
|
|
100
|
+
KERN_NO_ACCESS,
|
|
101
|
+
KERN_MEMORY_ERROR,
|
|
102
|
+
KERN_PROTECTION_FAILURE,
|
|
103
|
+
),
|
|
104
|
+
)
|
|
105
|
+
def test_a_sweep_may_skip_a_protected_range(kr):
|
|
106
|
+
assert _is_skippable_by_sweep(MachReadError(kr, "read failed (kr=%d)" % kr))
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# The sweep is more tolerant, not unconditionally tolerant: a task-level
|
|
110
|
+
# failure still has to stop it.
|
|
111
|
+
@pytest.mark.parametrize("kr", (KERN_FAILURE, KERN_MEMORY_FAILURE))
|
|
112
|
+
def test_a_sweep_still_stops_on_a_task_level_failure(kr):
|
|
113
|
+
assert not _is_skippable_by_sweep(MachReadError(kr, "read failed (kr=%d)" % kr))
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def test_only_the_sweep_skips_a_protected_range():
|
|
117
|
+
"""The two classifiers must disagree on exactly one code, and this is it."""
|
|
118
|
+
exc = MachReadError(KERN_PROTECTION_FAILURE, "read failed")
|
|
119
|
+
assert _is_skippable_by_sweep(exc)
|
|
120
|
+
assert not _is_transient(exc)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/enums/memory_allocation_states.py
RENAMED
|
File without changes
|
{pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/enums/memory_protections.py
RENAMED
|
File without changes
|
|
File without changes
|
{pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/enums/process_operations.py
RENAMED
|
File without changes
|
{pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/PyMemoryEditor/win32/enums/standard_access_rights.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pymemoryeditor-2.2.0 → pymemoryeditor-2.2.1}/tests/platforms/test_bitness_fallback_warns.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|