Skip to content

Commit 84221b6

Browse files
committed
Added Docstring and Whitespace
1 parent d0c0f2e commit 84221b6

1 file changed

Lines changed: 30 additions & 3 deletions

File tree

classmods/method_spy.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import Any, Dict, List, Tuple, Type, Callable
22
from functools import wraps
33

4-
HandlerCallable = Callable[[object, Any], None]
4+
SpyCallable = Callable[..., None]
55

66
class MethodSpy:
77
# Dictionary to store spies for each (class, method) pair
@@ -10,16 +10,40 @@ class MethodSpy:
1010
def __init__(
1111
self,
1212
target: Type,
13-
spy_callable: HandlerCallable,
13+
spy_callable: SpyCallable,
1414
spy_args: tuple = (),
1515
spy_kwargs: dict = {},
1616
*,
1717
target_method: str = '__init__',
1818
active: bool = True,
1919
) -> None:
2020
"""
21-
Method Spy
21+
A class to spy on method calls of a target class, triggering a handler function after the method is called.
22+
23+
The MethodSpy wraps a target method of a class and executes a spy handler whenever the method is invoked.
24+
Multiple spies can be registered for the same (class, method) pair, and all active spies will be triggered
25+
sequentially after the original method call.
26+
27+
Args:
28+
target (Type): The target class whose method will be spied on.
29+
spy_callable (SpyCallable): A callable to execute when the target method is called.
30+
Signature: spy_callable(instance: object, *spy_args, **spy_kwargs).
31+
spy_args (tuple): Positional arguments to pass to `spy_callable` (default: empty tuple).
32+
spy_kwargs (dict): Keyword arguments to pass to `spy_callable` (default: empty dict).
33+
target_method (str): Name of the method to spy on (default: '__init__').
34+
active (bool): Whether the spy is active initially (default: True).
35+
36+
Example:
37+
>>> class MyClass:
38+
... def my_method(self):
39+
... pass
40+
>>> def my_handler(instance):
41+
... print(f"Spy triggered on {instance}")
42+
>>> spy = MethodSpy(MyClass, my_handler, target_method='my_method')
43+
>>> obj = MyClass()
44+
>>> obj.my_method() # Calls my_handler(obj)
2245
"""
46+
2347
self._target = target
2448
self._spy_callable = spy_callable
2549
self._spy_args = spy_args
@@ -35,12 +59,14 @@ def __init__(
3559

3660
self.spies_registery[key].append(self)
3761

62+
3863
def _create_registery_key(self) -> Tuple[Type, str]:
3964
return (self._target, self._target_method)
4065

4166
def _create_original_name(self, method_name: str) -> str:
4267
return f'__original_{method_name}'
4368

69+
4470
def _wrap_class_method(self, target: Type, method_name: str) -> None:
4571
"""Wrap the target method to call all Spies."""
4672
original_name = self._create_original_name(method_name)
@@ -66,6 +92,7 @@ def new_method(instance: Any, *args, **kwargs) -> Any:
6692

6793
setattr(target, method_name, new_method)
6894

95+
6996
def activate(self) -> None:
7097
"""Activate the spy."""
7198
self._active = True

0 commit comments

Comments
 (0)