Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions PyMemoryEditor/app/open_process_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ def _build_ui(self) -> None:
self._case_checkbox = QCheckBox("Case-sensitive name lookup")
self._case_checkbox.setChecked(False)
self._case_checkbox.setToolTip(
"When unchecked, OpenProcess(process_name=…) is called with "
"When unchecked, OpenProcess(name=…) is called with "
"case_sensitive=False — useful on Windows where process names "
"are case-insensitive."
)
Expand Down Expand Up @@ -375,7 +375,7 @@ def _try_open(self) -> None:
self.process = OpenProcess(pid=pid, **kwargs)
else:
self.process = OpenProcess(
process_name=entry,
name=entry,
case_sensitive=self._case_checkbox.isChecked(),
**kwargs,
)
Expand Down
10 changes: 5 additions & 5 deletions PyMemoryEditor/linux/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,30 +39,30 @@ class LinuxProcess(AbstractProcess):
def __init__(
self,
*,
process_name: Optional[str] = None,
name: Optional[str] = None,
pid: Optional[int] = None,
permission=None,
case_sensitive: bool = True,
exact_match: bool = True,
strict_bitness: bool = False,
):
"""
:param process_name: name of the target process.
:param name: name of the target process.
:param pid: process ID.
:param permission: accepted for cross-platform API parity; ignored on
Linux (access is governed by ptrace_scope and process ownership).
Passing a non-None value emits a ``UserWarning`` so a Windows-shaped
mask doesn't disappear silently here — pass ``None`` (or omit) on
non-Windows platforms.
:param case_sensitive: when False, process_name matching ignores case.
:param exact_match: when False, ``process_name`` is matched as a
:param case_sensitive: when False, name matching ignores case.
:param exact_match: when False, ``name`` is matched as a
substring (e.g. ``"chrome"`` finds ``"chromium-browser"``).
:param strict_bitness: raise ``BitnessDetectionError`` instead of
guessing the host word size when the target's ELF class can't be
read. See :class:`~PyMemoryEditor.AbstractProcess`.
"""
super().__init__(
process_name=process_name,
name=name,
pid=pid,
case_sensitive=case_sensitive,
exact_match=exact_match,
Expand Down
10 changes: 5 additions & 5 deletions PyMemoryEditor/macos/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,30 +50,30 @@ class MacProcess(AbstractProcess):
def __init__(
self,
*,
process_name: Optional[str] = None,
name: Optional[str] = None,
pid: Optional[int] = None,
permission=None,
case_sensitive: bool = True,
exact_match: bool = True,
strict_bitness: bool = False,
):
"""
:param process_name: name of the target process.
:param name: name of the target process.
:param pid: process ID.
:param permission: accepted for cross-platform API parity; ignored on
macOS (access is governed by entitlements / mach_task_self_).
Passing a non-None value emits a ``UserWarning`` so a Windows-shaped
mask doesn't disappear silently here — pass ``None`` (or omit) on
non-Windows platforms.
:param case_sensitive: when False, process_name matching ignores case.
:param exact_match: when False, ``process_name`` is matched as a
:param case_sensitive: when False, name matching ignores case.
:param exact_match: when False, ``name`` is matched as a
substring (e.g. ``"chrome"`` finds ``"Google Chrome"``).
:param strict_bitness: raise ``BitnessDetectionError`` instead of
defaulting to 64-bit when no Mach-O header can be read. See
:class:`~PyMemoryEditor.AbstractProcess`.
"""
super().__init__(
process_name=process_name,
name=name,
pid=pid,
case_sensitive=case_sensitive,
exact_match=exact_match,
Expand Down
16 changes: 8 additions & 8 deletions PyMemoryEditor/process/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,18 @@ class AbstractProcess(ABC):
def __init__(
self,
*,
process_name: Optional[str] = None,
name: Optional[str] = None,
pid: Optional[int] = None,
case_sensitive: bool = True,
exact_match: bool = True,
strict_bitness: bool = False,
):
"""
:param process_name: name of the target process.
:param name: name of the target process.
:param pid: process ID.
:param case_sensitive: when False, process_name matching ignores case
:param case_sensitive: when False, name matching ignores case
(recommended on Windows where process names are case-insensitive).
:param exact_match: when False, ``process_name`` is matched as a
:param exact_match: when False, ``name`` is matched as a
substring — ``"chrome"`` matches ``"chrome.exe"`` / ``"Google Chrome"``.
If more than one process matches, ``AmbiguousProcessNameError`` is
raised so you can pick a PID from the list.
Expand All @@ -72,16 +72,16 @@ def __init__(
if pid is not None:
self._process_info.pid = pid

elif process_name:
self._process_info.set_process_name(
process_name,
elif name:
self._process_info.set_name(
name,
case_sensitive=case_sensitive,
exact_match=exact_match,
)

else:
raise TypeError(
"You must pass an argument to one of these parameters (process_name, pid)."
"You must pass an argument to one of these parameters (name, pid)."
)

# Cache for the target's bitness — resolved lazily on first access of
Expand Down
26 changes: 13 additions & 13 deletions PyMemoryEditor/process/info.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-

from .errors import ProcessIDNotExistsError, ProcessNotFoundError
from .util import get_process_id_by_process_name, pid_exists
from .util import get_process_id_by_name, pid_exists


class ProcessInfo(object):
Expand All @@ -11,7 +11,7 @@ class ProcessInfo(object):

def __init__(self) -> None:
self.__pid: int = -1
self.__process_name: str = ""
self.__name: str = ""

@property
def pid(self) -> int:
Expand All @@ -31,27 +31,27 @@ def pid(self, pid: int) -> None:
self.__pid = pid

@property
def process_name(self) -> str:
return self.__process_name
def name(self) -> str:
return self.__name

@process_name.setter
def process_name(self, process_name: str) -> None:
self.set_process_name(process_name)
@name.setter
def name(self, name: str) -> None:
self.set_name(name)

def set_process_name(
def set_name(
self,
process_name: str,
name: str,
*,
case_sensitive: bool = True,
exact_match: bool = True,
) -> None:
pid = get_process_id_by_process_name(
process_name,
pid = get_process_id_by_name(
name,
case_sensitive=case_sensitive,
exact_match=exact_match,
)
if pid is None:
raise ProcessNotFoundError(process_name)
raise ProcessNotFoundError(name)

self.__pid = pid
self.__process_name = process_name
self.__name = name
22 changes: 11 additions & 11 deletions PyMemoryEditor/process/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,26 @@ def _backend_process_exists(pid: int) -> bool:
return False


def get_process_ids_by_process_name(
process_name: str,
def get_process_ids_by_name(
name: str,
*,
case_sensitive: bool = True,
exact_match: bool = True,
) -> List[int]:
"""
Return a list of all process IDs matching the provided name.

:param process_name: process name to search.
:param name: process name to search.
:param case_sensitive: when False, comparison ignores case (useful on Windows).
:param exact_match: when False, returns every process whose name *contains*
``process_name`` as a substring — handy when you don't know the exact
``name`` as a substring — handy when you don't know the exact
executable name (``"chrome"`` matches ``"chrome.exe"``, ``"Google Chrome"``,
``"Chromium"``, ...). Often combined with ``case_sensitive=False``.
"""
if not case_sensitive:
process_name_cmp = process_name.casefold()
process_name_cmp = name.casefold()
else:
process_name_cmp = process_name
process_name_cmp = name

matches: List[int] = []

Expand All @@ -70,8 +70,8 @@ def get_process_ids_by_process_name(
return matches


def get_process_id_by_process_name(
process_name: str,
def get_process_id_by_name(
name: str,
*,
case_sensitive: bool = True,
exact_match: bool = True,
Expand All @@ -82,14 +82,14 @@ def get_process_id_by_process_name(
Raises AmbiguousProcessNameError when more than one process matches.
Returns None when no process matches (callers should handle this).
"""
matches = get_process_ids_by_process_name(
process_name,
matches = get_process_ids_by_name(
name,
case_sensitive=case_sensitive,
exact_match=exact_match,
)

if len(matches) > 1:
raise AmbiguousProcessNameError(process_name, matches)
raise AmbiguousProcessNameError(name, matches)

return matches[0] if matches else None

Expand Down
10 changes: 5 additions & 5 deletions PyMemoryEditor/win32/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,29 +88,29 @@ class WindowsProcess(AbstractProcess):
def __init__(
self,
*,
process_name: Optional[str] = None,
name: Optional[str] = None,
pid: Optional[int] = None,
permission: Union[ProcessOperationsEnum, int] = DEFAULT_PERMISSION,
case_sensitive: bool = False,
exact_match: bool = True,
strict_bitness: bool = False,
):
"""
:param process_name: name of the target process.
:param name: name of the target process.
:param pid: process ID.
:param permission: access mode to the process. Defaults to the
read-and-write set: PROCESS_VM_READ | PROCESS_VM_WRITE |
PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION
(PROCESS_QUERY_INFORMATION is required by VirtualQueryEx, used
internally for region enumeration). Narrow the mask if you want
a read-only handle, or pass PROCESS_ALL_ACCESS for full control.
:param case_sensitive: when False (default on Windows), process_name
:param case_sensitive: when False (default on Windows), name
matching ignores case to align with the OS convention.
:param exact_match: when False, ``process_name`` is matched as a
:param exact_match: when False, ``name`` is matched as a
substring (e.g. ``"chrome"`` finds ``"chrome.exe"``).
"""
super().__init__(
process_name=process_name,
name=name,
pid=pid,
case_sensitive=case_sensitive,
exact_match=exact_match,
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pip install "PyMemoryEditor[speed]"
```python
from PyMemoryEditor import OpenProcess

with OpenProcess(process_name="game.exe") as process:
with OpenProcess(name="game.exe") as process:

# Scan the whole process for every address holding the value 100.
for address in process.search_by_value(int, value=100):
Expand Down
2 changes: 1 addition & 1 deletion docs/api/enums.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ from PyMemoryEditor import ScanTypesEnum
```python
from PyMemoryEditor import OpenProcess, ScanTypesEnum

with OpenProcess(process_name="game.exe") as process:
with OpenProcess(name="game.exe") as process:
for address in process.search_by_value(int, value=1000, scan_type=ScanTypesEnum.BIGGER_THAN):
print(hex(address))
```
Expand Down
12 changes: 6 additions & 6 deletions docs/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ inherit from `PyMemoryEditorError`, so you can catch the whole library:
from PyMemoryEditor import PyMemoryEditorError

try:
with OpenProcess(process_name="game.exe") as process:
with OpenProcess(name="game.exe") as process:
...
except PyMemoryEditorError as exc:
print("Library error:", exc)
Expand Down Expand Up @@ -70,7 +70,7 @@ Raised when the given `pid=` doesn't correspond to a running process.

### `ProcessNotFoundError`

Raised when no running process matches the given `process_name=`.
Raised when no running process matches the given `name=`.

```{eval-rst}
.. py:exception:: ProcessNotFoundError
Expand All @@ -84,7 +84,7 @@ Raised when no running process matches the given `process_name=`.
### `AmbiguousProcessNameError`

Raised when **more than one** running process matches the given
`process_name=` (typical when using `exact_match=False`).
`name=` (typical when using `exact_match=False`).

```{eval-rst}
.. py:exception:: AmbiguousProcessNameError
Expand All @@ -106,7 +106,7 @@ Example:
from PyMemoryEditor import OpenProcess, AmbiguousProcessNameError

try:
OpenProcess(process_name="chrome", exact_match=False)
OpenProcess(name="chrome", exact_match=False)
except AmbiguousProcessNameError as exc:
print("Multiple matches:", exc.pids)
process = OpenProcess(pid=exc.pids[0])
Expand All @@ -116,7 +116,7 @@ except AmbiguousProcessNameError as exc:

<table>
<tr><th>Exception</th><th>When it's raised</th></tr>
<tr><td><code>TypeError</code></td><td>Neither <code>process_name</code> nor <code>pid</code> provided to <code>OpenProcess</code>; or a scan pattern that is not <code>str</code>, <code>bytes</code> or a compiled <code>re.Pattern</code>.</td></tr>
<tr><td><code>TypeError</code></td><td>Neither <code>name</code> nor <code>pid</code> provided to <code>OpenProcess</code>; or a scan pattern that is not <code>str</code>, <code>bytes</code> or a compiled <code>re.Pattern</code>.</td></tr>
<tr><td><code>ValueError</code></td><td>Invalid <code>pytype</code>, missing <code>bufflength</code> for <code>str</code>/<code>bytes</code>, invalid <code>ptr_size</code>, malformed pattern, <code>byte_length</code> omitted for a regex pattern, etc.</td></tr>
<tr><td><code>PermissionError</code></td><td>OS denied access to the target process or a specific region.</td></tr>
<tr><td><code>OSError</code></td><td>Low-level read/write failure (e.g. page was freed between scan and read).</td></tr>
Expand All @@ -138,7 +138,7 @@ from PyMemoryEditor import (
)

try:
with OpenProcess(process_name="game.exe") as process:
with OpenProcess(name="game.exe") as process:
for address in process.search_by_value(int, value=100):
try:
value = process.read_process_memory(address, int)
Expand Down
2 changes: 1 addition & 1 deletion docs/api/memory-region.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ of memory with its address, size, permissions and backing path.
### Iterating regions

```python
with OpenProcess(process_name="game.exe") as process:
with OpenProcess(name="game.exe") as process:
for region in process.get_memory_regions():
print(f"0x{region.address:016X} {region.size:>12,}")
```
Expand Down
2 changes: 1 addition & 1 deletion docs/api/module-info.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Linux, `.dylib` on macOS).
### Listing every module

```python
with OpenProcess(process_name="game.exe") as process:
with OpenProcess(name="game.exe") as process:
for module in process.get_modules():
print(f"{module.name:32} 0x{module.base_address:016X} {module.size:>12}")
```
Expand Down
Loading
Loading