decoy 2.3.0__py3-none-any.whl → 2.5.0__py3-none-any.whl
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.
- decoy/call_handler.py +7 -2
- decoy/errors.py +28 -26
- decoy/matchers.py +12 -17
- decoy/next/__init__.py +21 -0
- decoy/next/_internal/__init__.py +0 -0
- decoy/next/_internal/compare.py +138 -0
- decoy/next/_internal/decoy.py +231 -0
- decoy/next/_internal/errors.py +103 -0
- decoy/next/_internal/inspect.py +229 -0
- decoy/next/_internal/matcher.py +328 -0
- decoy/next/_internal/mock.py +220 -0
- decoy/next/_internal/state.py +265 -0
- decoy/next/_internal/stringify.py +80 -0
- decoy/next/_internal/values.py +96 -0
- decoy/next/_internal/verify.py +78 -0
- decoy/next/_internal/warnings.py +35 -0
- decoy/next/_internal/when.py +136 -0
- decoy/pytest_plugin.py +30 -5
- decoy/spy.py +1 -1
- {decoy-2.3.0.dist-info → decoy-2.5.0.dist-info}/METADATA +5 -4
- decoy-2.5.0.dist-info/RECORD +38 -0
- {decoy-2.3.0.dist-info → decoy-2.5.0.dist-info}/WHEEL +2 -2
- decoy-2.3.0.dist-info/RECORD +0 -24
- {decoy-2.3.0.dist-info → decoy-2.5.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
from typing import Any, Callable, Generic, ParamSpec, TypeVar
|
|
3
|
+
|
|
4
|
+
from .errors import createVerifyError
|
|
5
|
+
from .inspect import bind_args
|
|
6
|
+
from .state import DecoyState
|
|
7
|
+
from .values import (
|
|
8
|
+
AttributeEvent,
|
|
9
|
+
CallEvent,
|
|
10
|
+
Event,
|
|
11
|
+
EventMatcher,
|
|
12
|
+
MatchOptions,
|
|
13
|
+
MockInfo,
|
|
14
|
+
)
|
|
15
|
+
from .warnings import createRedundantVerifyWarning
|
|
16
|
+
|
|
17
|
+
SpecT = TypeVar("SpecT")
|
|
18
|
+
ParamsT = ParamSpec("ParamsT")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Verify(Generic[SpecT]):
|
|
22
|
+
"""[Verify](./verify.md) how a mock was called."""
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
state: DecoyState,
|
|
27
|
+
mock: MockInfo,
|
|
28
|
+
match_options: MatchOptions,
|
|
29
|
+
) -> None:
|
|
30
|
+
self._mock = mock
|
|
31
|
+
self._state = state
|
|
32
|
+
self._match_options = match_options
|
|
33
|
+
|
|
34
|
+
def _verify(self, expected: Event) -> None:
|
|
35
|
+
matcher = EventMatcher(expected, self._match_options)
|
|
36
|
+
result = self._state.use_verification(self._mock, matcher)
|
|
37
|
+
|
|
38
|
+
if not result.is_success:
|
|
39
|
+
raise createVerifyError(
|
|
40
|
+
self._mock.name,
|
|
41
|
+
self._match_options,
|
|
42
|
+
expected,
|
|
43
|
+
result.mock_events,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
if result.is_redundant:
|
|
47
|
+
warnings.warn(
|
|
48
|
+
createRedundantVerifyWarning(self._mock.name, expected),
|
|
49
|
+
stacklevel=3,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def called_with(
|
|
53
|
+
self: "Verify[Callable[ParamsT, Any]]",
|
|
54
|
+
*args: ParamsT.args,
|
|
55
|
+
**kwargs: ParamsT.kwargs,
|
|
56
|
+
) -> None:
|
|
57
|
+
"""Verify that a mock was called."""
|
|
58
|
+
bound_args = bind_args(
|
|
59
|
+
signature=self._mock.signature,
|
|
60
|
+
args=args,
|
|
61
|
+
kwargs=kwargs,
|
|
62
|
+
ignore_extra_args=self._match_options.ignore_extra_args,
|
|
63
|
+
)
|
|
64
|
+
expected = CallEvent(args=bound_args.args, kwargs=bound_args.kwargs)
|
|
65
|
+
|
|
66
|
+
self._verify(expected)
|
|
67
|
+
|
|
68
|
+
def set(self, value: SpecT) -> None:
|
|
69
|
+
"""Verify that an [attribute was set](./attributes.md#verify-a-setter)."""
|
|
70
|
+
expected = AttributeEvent.set(value)
|
|
71
|
+
|
|
72
|
+
self._verify(expected)
|
|
73
|
+
|
|
74
|
+
def delete(self) -> None:
|
|
75
|
+
"""Verify that an [attribute was deleted](./attributes.md#verify-a-deleter)."""
|
|
76
|
+
expected = AttributeEvent.delete()
|
|
77
|
+
|
|
78
|
+
self._verify(expected)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from ... import warnings
|
|
2
|
+
from .stringify import count, join_lines, stringify_event, stringify_event_list
|
|
3
|
+
from .values import CallEvent, Event
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def createMiscalledStubWarning(
|
|
7
|
+
name: str,
|
|
8
|
+
expected_events: list[Event],
|
|
9
|
+
actual_event: CallEvent,
|
|
10
|
+
) -> warnings.MiscalledStubWarning:
|
|
11
|
+
"""Create a MiscalledStubWarning."""
|
|
12
|
+
message = join_lines(
|
|
13
|
+
"Stub was called but no matching rehearsal found.",
|
|
14
|
+
f"Found {count(len(expected_events), 'rehearsal')}:",
|
|
15
|
+
stringify_event_list(name, expected_events),
|
|
16
|
+
"Found 1 call:",
|
|
17
|
+
f"1.\t{stringify_event(name, actual_event)}",
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
return warnings.MiscalledStubWarning(message)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def createRedundantVerifyWarning(
|
|
24
|
+
name: str,
|
|
25
|
+
event: Event,
|
|
26
|
+
) -> warnings.RedundantVerifyWarning:
|
|
27
|
+
"""Create a RedundantVerifyWarning."""
|
|
28
|
+
message = join_lines(
|
|
29
|
+
"The same rehearsal was used in both a `when` and a `verify`.",
|
|
30
|
+
"This is redundant and probably a misuse of the mock.",
|
|
31
|
+
f"\t{stringify_event(name, event)}",
|
|
32
|
+
"See https://michael.cousins.io/decoy/usage/errors-and-warnings/#redundantverifywarning",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
return warnings.RedundantVerifyWarning(message)
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
from contextlib import AbstractAsyncContextManager, AbstractContextManager
|
|
2
|
+
from typing import (
|
|
3
|
+
Any,
|
|
4
|
+
Awaitable,
|
|
5
|
+
Callable,
|
|
6
|
+
Generic,
|
|
7
|
+
NoReturn,
|
|
8
|
+
ParamSpec,
|
|
9
|
+
TypeVar,
|
|
10
|
+
overload,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from .inspect import bind_args, ensure_callable
|
|
14
|
+
from .state import DecoyState
|
|
15
|
+
from .values import (
|
|
16
|
+
AttributeEvent,
|
|
17
|
+
Behavior,
|
|
18
|
+
CallEvent,
|
|
19
|
+
Event,
|
|
20
|
+
EventMatcher,
|
|
21
|
+
MatchOptions,
|
|
22
|
+
MockInfo,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
CallableSpecT = TypeVar("CallableSpecT", covariant=True)
|
|
26
|
+
AttributeSpecT = TypeVar("AttributeSpecT")
|
|
27
|
+
ParamsT = ParamSpec("ParamsT")
|
|
28
|
+
ReturnT = TypeVar("ReturnT")
|
|
29
|
+
ContextValueT = TypeVar("ContextValueT")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Stub(Generic[ParamsT, ReturnT, ContextValueT]):
|
|
33
|
+
"""Configure how a mock behaves [when called](./when.md)."""
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
state: DecoyState,
|
|
38
|
+
mock: MockInfo,
|
|
39
|
+
matcher: EventMatcher,
|
|
40
|
+
) -> None:
|
|
41
|
+
self._state = state
|
|
42
|
+
self._mock = mock
|
|
43
|
+
self._matcher = matcher
|
|
44
|
+
|
|
45
|
+
def then_return(self, *values: ReturnT) -> None:
|
|
46
|
+
"""Mock a return value."""
|
|
47
|
+
behaviors = [Behavior(return_value=value) for value in values]
|
|
48
|
+
self._push_behaviors(behaviors)
|
|
49
|
+
|
|
50
|
+
def then_enter_with(self, *values: ContextValueT) -> None:
|
|
51
|
+
"""Mock a context manager value for a generator context manager."""
|
|
52
|
+
behaviors = [Behavior(context=value) for value in values]
|
|
53
|
+
self._push_behaviors(behaviors)
|
|
54
|
+
|
|
55
|
+
def then_raise(self, *errors: Exception) -> None:
|
|
56
|
+
"""Mock a raised exception."""
|
|
57
|
+
behaviors = [Behavior(error=error) for error in errors]
|
|
58
|
+
self._push_behaviors(behaviors)
|
|
59
|
+
|
|
60
|
+
def then_do(self, *actions: Callable[ParamsT, ReturnT]) -> None:
|
|
61
|
+
"""Trigger a callback function."""
|
|
62
|
+
behaviors = [
|
|
63
|
+
Behavior(action=ensure_callable(action, is_async=self._mock.is_async))
|
|
64
|
+
for action in actions
|
|
65
|
+
]
|
|
66
|
+
self._push_behaviors(behaviors)
|
|
67
|
+
|
|
68
|
+
def _push_behaviors(self, behaviors: list[Behavior]) -> None:
|
|
69
|
+
self._state.push_behaviors(self._mock, self._matcher, behaviors)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class When(Generic[CallableSpecT, AttributeSpecT]):
|
|
73
|
+
"""Configure [when a mock is triggered](./when.md)."""
|
|
74
|
+
|
|
75
|
+
def __init__(
|
|
76
|
+
self,
|
|
77
|
+
state: DecoyState,
|
|
78
|
+
mock: MockInfo,
|
|
79
|
+
match_options: MatchOptions,
|
|
80
|
+
) -> None:
|
|
81
|
+
self._state = state
|
|
82
|
+
self._mock = mock
|
|
83
|
+
self._match_options = match_options
|
|
84
|
+
|
|
85
|
+
@overload
|
|
86
|
+
def called_with(
|
|
87
|
+
self: "When[Callable[ParamsT, AbstractAsyncContextManager[ContextValueT] | AbstractContextManager[ContextValueT]], Callable[..., ReturnT]]",
|
|
88
|
+
*args: ParamsT.args,
|
|
89
|
+
**kwargs: ParamsT.kwargs,
|
|
90
|
+
) -> Stub[ParamsT, ReturnT, ContextValueT]: ...
|
|
91
|
+
|
|
92
|
+
@overload
|
|
93
|
+
def called_with(
|
|
94
|
+
self: "When[Callable[ParamsT, Awaitable[ReturnT]], Any]",
|
|
95
|
+
*args: ParamsT.args,
|
|
96
|
+
**kwargs: ParamsT.kwargs,
|
|
97
|
+
) -> Stub[ParamsT, ReturnT | Awaitable[ReturnT], NoReturn]: ...
|
|
98
|
+
|
|
99
|
+
@overload
|
|
100
|
+
def called_with(
|
|
101
|
+
self: "When[Callable[ParamsT, ReturnT], Any]",
|
|
102
|
+
*args: ParamsT.args,
|
|
103
|
+
**kwargs: ParamsT.kwargs,
|
|
104
|
+
) -> Stub[ParamsT, ReturnT, NoReturn]: ...
|
|
105
|
+
|
|
106
|
+
def called_with(
|
|
107
|
+
self,
|
|
108
|
+
*args: Any,
|
|
109
|
+
**kwargs: Any,
|
|
110
|
+
) -> Stub[Any, Any, Any]:
|
|
111
|
+
"""Configure a stub to react to certain passed-in arguments."""
|
|
112
|
+
bound_args = bind_args(
|
|
113
|
+
signature=self._mock.signature,
|
|
114
|
+
args=args,
|
|
115
|
+
kwargs=kwargs,
|
|
116
|
+
ignore_extra_args=self._match_options.ignore_extra_args,
|
|
117
|
+
)
|
|
118
|
+
event = CallEvent(args=bound_args.args, kwargs=bound_args.kwargs)
|
|
119
|
+
|
|
120
|
+
return self._create_stub(event)
|
|
121
|
+
|
|
122
|
+
def get(self) -> Stub[[], AttributeSpecT, NoReturn]:
|
|
123
|
+
"""Configure a stub to react to an attribute get."""
|
|
124
|
+
return self._create_stub(AttributeEvent.get())
|
|
125
|
+
|
|
126
|
+
def set(self, value: AttributeSpecT) -> Stub[[AttributeSpecT], None, NoReturn]:
|
|
127
|
+
"""Configure a stub to react to an attribute set."""
|
|
128
|
+
return self._create_stub(AttributeEvent.set(value))
|
|
129
|
+
|
|
130
|
+
def delete(self) -> Stub[[], None, NoReturn]:
|
|
131
|
+
"""Configure a stub to react to an attribute delete."""
|
|
132
|
+
return self._create_stub(AttributeEvent.delete())
|
|
133
|
+
|
|
134
|
+
def _create_stub(self, event: Event) -> Stub[Any, Any, NoReturn]:
|
|
135
|
+
matcher = EventMatcher(event=event, options=self._match_options)
|
|
136
|
+
return Stub(self._state, self._mock, matcher)
|
decoy/pytest_plugin.py
CHANGED
|
@@ -5,21 +5,32 @@ fixture without modifying any other pytest behavior. Its usage is optional
|
|
|
5
5
|
but highly recommended.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from typing import Iterable
|
|
8
|
+
from typing import TYPE_CHECKING, Iterable, Union, get_type_hints
|
|
9
9
|
|
|
10
10
|
import pytest
|
|
11
11
|
|
|
12
12
|
from decoy import Decoy
|
|
13
13
|
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from decoy.next import Decoy as DecoyNext
|
|
16
|
+
|
|
14
17
|
|
|
15
18
|
@pytest.fixture()
|
|
16
|
-
def decoy(
|
|
19
|
+
def decoy(
|
|
20
|
+
request: pytest.FixtureRequest,
|
|
21
|
+
) -> "Iterable[Union[Decoy, DecoyNext]]":
|
|
17
22
|
"""Get a [decoy.Decoy][] container and [reset it][decoy.Decoy.reset] after the test.
|
|
18
23
|
|
|
19
24
|
This function is function-scoped [pytest fixture][] that will be
|
|
20
25
|
automatically inserted by the plugin.
|
|
21
26
|
|
|
27
|
+
!!! tip
|
|
28
|
+
|
|
29
|
+
This fixture will automatically opt-into the [v3 preview API][v3-preview]
|
|
30
|
+
if annotated with `decoy.next.Decoy`.
|
|
31
|
+
|
|
22
32
|
[pytest fixture]: https://docs.pytest.org/en/latest/how-to/fixtures.html
|
|
33
|
+
[v3-preview]: ./v3/about.md
|
|
23
34
|
|
|
24
35
|
!!! example
|
|
25
36
|
```python
|
|
@@ -28,6 +39,20 @@ def decoy() -> Iterable[Decoy]:
|
|
|
28
39
|
# ...
|
|
29
40
|
```
|
|
30
41
|
"""
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
42
|
+
try:
|
|
43
|
+
decoy_hint = get_type_hints(request.function).get("decoy")
|
|
44
|
+
is_next = decoy_hint.__module__.startswith("decoy.next")
|
|
45
|
+
|
|
46
|
+
# purely defensive, probably won't ever raise
|
|
47
|
+
except Exception: # pragma: no cover
|
|
48
|
+
is_next = False
|
|
49
|
+
|
|
50
|
+
if is_next:
|
|
51
|
+
from decoy.next import Decoy as DecoyNext
|
|
52
|
+
|
|
53
|
+
with DecoyNext.create() as decoy_next:
|
|
54
|
+
yield decoy_next
|
|
55
|
+
else:
|
|
56
|
+
decoy = Decoy()
|
|
57
|
+
yield decoy
|
|
58
|
+
decoy.reset()
|
decoy/spy.py
CHANGED
|
@@ -10,7 +10,7 @@ from typing import Any, ContextManager, Dict, Optional, Type, Union, cast, overl
|
|
|
10
10
|
|
|
11
11
|
from .call_handler import CallHandler
|
|
12
12
|
from .spy_core import SpyCore
|
|
13
|
-
from .spy_events import SpyCall, SpyEvent, SpyPropAccess
|
|
13
|
+
from .spy_events import PropAccessType, SpyCall, SpyEvent, SpyPropAccess
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class BaseSpy(ContextManager[Any]):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: decoy
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: Opinionated mocking library for Python
|
|
5
5
|
Author: Michael Cousins
|
|
6
6
|
Author-email: Michael Cousins <michael@cousins.io>>
|
|
@@ -11,12 +11,13 @@ Classifier: Operating System :: OS Independent
|
|
|
11
11
|
Classifier: Topic :: Software Development :: Testing
|
|
12
12
|
Classifier: Topic :: Software Development :: Testing :: Mocking
|
|
13
13
|
Classifier: Typing :: Typed
|
|
14
|
+
Requires-Dist: typing-extensions>=4.10.0 ; python_full_version >= '3.10' and python_full_version < '3.13'
|
|
14
15
|
Requires-Python: >=3.7
|
|
15
|
-
Project-URL: Changelog, https://github.com/mcous/decoy/releases
|
|
16
|
-
Project-URL: Documentation, https://michael.cousins.io/decoy/
|
|
17
16
|
Project-URL: Homepage, https://michael.cousins.io/decoy/
|
|
18
|
-
Project-URL:
|
|
17
|
+
Project-URL: Documentation, https://michael.cousins.io/decoy/
|
|
19
18
|
Project-URL: Repository, https://github.com/mcous/decoy
|
|
19
|
+
Project-URL: Issues, https://github.com/mcous/decoy/issues
|
|
20
|
+
Project-URL: Changelog, https://github.com/mcous/decoy/releases
|
|
20
21
|
Description-Content-Type: text/markdown
|
|
21
22
|
|
|
22
23
|
<div align="center">
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
decoy/__init__.py,sha256=v3LUyAxuxFrO2M4Iw0VRX0IM6axFMxPmtgIbBemmwj8,11232
|
|
2
|
+
decoy/call_handler.py,sha256=3MixA4pQs4k_2osq1ug19rXXMafzLECGSZLhltSMoo0,1767
|
|
3
|
+
decoy/context_managers.py,sha256=oYsH99ZPmkaCcqjCrOWInueO5ympHm_ICWmbpFoQzqA,1287
|
|
4
|
+
decoy/core.py,sha256=0YsQFnL4Kw_oDX7jRgOVLw9BGsnNdekymQCd1aq-4sQ,5830
|
|
5
|
+
decoy/errors.py,sha256=3vadsAYM-xpoT_lpgiSJbemtjvomWslC9qLfn6FKQpo,2993
|
|
6
|
+
decoy/matchers.py,sha256=Y55oOJww3mhuCsGn9wzUsVMVw0IzxBAMuaSYwtWgOm4,11630
|
|
7
|
+
decoy/mypy/__init__.py,sha256=GdJCf-gXpYB4SBr-Rm8zCLZQxAUuLjPyUieIWgLmdwA,86
|
|
8
|
+
decoy/mypy/plugin.py,sha256=nCfo4XpDxBRDsInDsvCe6h8t7-1OV0ZCJzIJqTsAU0I,1359
|
|
9
|
+
decoy/next/__init__.py,sha256=RqW1Ry5FIw1nptiEqW9W15u1qCySn_ioTRRdu38GFEk,405
|
|
10
|
+
decoy/next/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
decoy/next/_internal/compare.py,sha256=ab9YY3Y4vJhwfw-Kfg-SHGvsaCkZZbmadSI5cJ4j7x8,4173
|
|
12
|
+
decoy/next/_internal/decoy.py,sha256=Mt8cgRVOofwmT0qP4eReUaTvSPFv765MeOCWP9VIR3M,6995
|
|
13
|
+
decoy/next/_internal/errors.py,sha256=E3gUBWY6O-fWt77YJG67bUpOPkV8ktql8VrnZv7UE6Q,3026
|
|
14
|
+
decoy/next/_internal/inspect.py,sha256=LPbm_3ub621KEr6KO1ODhPhbAyxgYnI8qVM2_jmayz8,6698
|
|
15
|
+
decoy/next/_internal/matcher.py,sha256=UDgPgfBfBM7x67AxBFRrm545U634s6YGcc3QsDTCh2M,9141
|
|
16
|
+
decoy/next/_internal/mock.py,sha256=CQrx3nvGFEJSs-r0VNFyHvojtrajFNIT4nQL3_jz9aM,6558
|
|
17
|
+
decoy/next/_internal/state.py,sha256=kFZweF02aG9yGByPa0gtjrheHQRVdFMJwgi19vj5g7o,8247
|
|
18
|
+
decoy/next/_internal/stringify.py,sha256=jQIi9ma7lO2m-Qc-eIth793KnBg7OTRuwr2fg-Q1h-A,2533
|
|
19
|
+
decoy/next/_internal/values.py,sha256=W5yUnDgVNsTfM5qdvc2JZaZKMZ0yC8WES3WIDNZM_WY,1871
|
|
20
|
+
decoy/next/_internal/verify.py,sha256=CEgb7Di-uJskObO2hIycvCgTLixVd4BYCZvHkTvWXRc,2203
|
|
21
|
+
decoy/next/_internal/warnings.py,sha256=59T3hs3x2AcGp6jAUEEbq2pLgFMKO2QatE-1ep0Tlxg,1182
|
|
22
|
+
decoy/next/_internal/when.py,sha256=WtV2U_LIvGbkYgo8CfocUxo3ZDjdlnbV8gtUp6lmBSU,4376
|
|
23
|
+
decoy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
+
decoy/pytest_plugin.py,sha256=y_5soxLEGJXo_EmPXcpw_axLcyStgVROkU-SDaVYCEM,1611
|
|
25
|
+
decoy/spy.py,sha256=G3rEHAx2yWQaucOs8fQoB-Hap8vejPrzYcxBca6XbeQ,7581
|
|
26
|
+
decoy/spy_core.py,sha256=b3PTgCkYnijT08ak_iRUKnA95FnmspSRmT8cs_YtjtM,7965
|
|
27
|
+
decoy/spy_events.py,sha256=PFTfkgN7CVWfbVoSSUMSaCSxfRrUMd7U419iwQ1Xofg,2383
|
|
28
|
+
decoy/spy_log.py,sha256=5JcjcH7zHrn12jp7xyrs_UWY7ATcWJkQ4v9oCR_Cclg,3929
|
|
29
|
+
decoy/stringify.py,sha256=6JA2VA9eK-4AtwSSZPnMYT8ucW7EMpGdbTXokbOpgOg,2240
|
|
30
|
+
decoy/stub_store.py,sha256=tVqKOW65NjotVdDhDDXpLfwagKHypMS4WMob71RYk1c,1744
|
|
31
|
+
decoy/types.py,sha256=LXzky6T0RXvS53NoPpVgCi3KVV6KCyB6EvnBl0NaKug,404
|
|
32
|
+
decoy/verifier.py,sha256=3ZVqaUJPjaNM9Nue3FK6Zzj15qWskX2CEQXoe_yjUEs,1586
|
|
33
|
+
decoy/warning_checker.py,sha256=OOkcrr_I98Pzs3o9UUNgaihJDHwNiu1LlcEK9hi5ZFs,3577
|
|
34
|
+
decoy/warnings.py,sha256=DLdX1ABPk6QvhJWt5s98uR7rCQFQdJJjSPPXRSX0nXA,3203
|
|
35
|
+
decoy-2.5.0.dist-info/WHEEL,sha256=iHtWm8nRfs0VRdCYVXocAWFW8ppjHL-uTJkAdZJKOBM,80
|
|
36
|
+
decoy-2.5.0.dist-info/entry_points.txt,sha256=En3V0KZt-83nTeWFpVB5KTotgxuUETePl7HesB81W64,40
|
|
37
|
+
decoy-2.5.0.dist-info/METADATA,sha256=s_d-w2xrobK880yLspMDWUQ78cXP2QIJBcwetW-jX0Y,6980
|
|
38
|
+
decoy-2.5.0.dist-info/RECORD,,
|
decoy-2.3.0.dist-info/RECORD
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
decoy/__init__.py,sha256=v3LUyAxuxFrO2M4Iw0VRX0IM6axFMxPmtgIbBemmwj8,11232
|
|
2
|
-
decoy/call_handler.py,sha256=fuhWr9VAnh0FUvbfWw11fpdQ_GCUE3Hah-EXvdk3gGw,1512
|
|
3
|
-
decoy/context_managers.py,sha256=oYsH99ZPmkaCcqjCrOWInueO5ympHm_ICWmbpFoQzqA,1287
|
|
4
|
-
decoy/core.py,sha256=0YsQFnL4Kw_oDX7jRgOVLw9BGsnNdekymQCd1aq-4sQ,5830
|
|
5
|
-
decoy/errors.py,sha256=mmUAOoQQyXhCLjMcf_3bHMz3PjU7bingIU6sC3hk2B4,3119
|
|
6
|
-
decoy/matchers.py,sha256=2zO0F4tbxvLeRlm9BMIAQr_nxX5PBKA4CRJ5Hy5eukU,11724
|
|
7
|
-
decoy/mypy/__init__.py,sha256=GdJCf-gXpYB4SBr-Rm8zCLZQxAUuLjPyUieIWgLmdwA,86
|
|
8
|
-
decoy/mypy/plugin.py,sha256=nCfo4XpDxBRDsInDsvCe6h8t7-1OV0ZCJzIJqTsAU0I,1359
|
|
9
|
-
decoy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
decoy/pytest_plugin.py,sha256=muiWN6zwQPD-AaL4YH6usp-25P4EYjrROTx6wdLE9hM,853
|
|
11
|
-
decoy/spy.py,sha256=cxlwDFxd2dcTb6vFJJGc0B3IuFCPJs2cgVMeB0qNXW4,7581
|
|
12
|
-
decoy/spy_core.py,sha256=b3PTgCkYnijT08ak_iRUKnA95FnmspSRmT8cs_YtjtM,7965
|
|
13
|
-
decoy/spy_events.py,sha256=PFTfkgN7CVWfbVoSSUMSaCSxfRrUMd7U419iwQ1Xofg,2383
|
|
14
|
-
decoy/spy_log.py,sha256=5JcjcH7zHrn12jp7xyrs_UWY7ATcWJkQ4v9oCR_Cclg,3929
|
|
15
|
-
decoy/stringify.py,sha256=6JA2VA9eK-4AtwSSZPnMYT8ucW7EMpGdbTXokbOpgOg,2240
|
|
16
|
-
decoy/stub_store.py,sha256=tVqKOW65NjotVdDhDDXpLfwagKHypMS4WMob71RYk1c,1744
|
|
17
|
-
decoy/types.py,sha256=LXzky6T0RXvS53NoPpVgCi3KVV6KCyB6EvnBl0NaKug,404
|
|
18
|
-
decoy/verifier.py,sha256=3ZVqaUJPjaNM9Nue3FK6Zzj15qWskX2CEQXoe_yjUEs,1586
|
|
19
|
-
decoy/warning_checker.py,sha256=OOkcrr_I98Pzs3o9UUNgaihJDHwNiu1LlcEK9hi5ZFs,3577
|
|
20
|
-
decoy/warnings.py,sha256=DLdX1ABPk6QvhJWt5s98uR7rCQFQdJJjSPPXRSX0nXA,3203
|
|
21
|
-
decoy-2.3.0.dist-info/WHEEL,sha256=KSLUh82mDPEPk0Bx0ScXlWL64bc8KmzIPNcpQZFV-6E,79
|
|
22
|
-
decoy-2.3.0.dist-info/entry_points.txt,sha256=En3V0KZt-83nTeWFpVB5KTotgxuUETePl7HesB81W64,40
|
|
23
|
-
decoy-2.3.0.dist-info/METADATA,sha256=3QTINwIfutMyuMNSY0m7TFMHA8Kt5Bl-ijDIqD1I7jA,6874
|
|
24
|
-
decoy-2.3.0.dist-info/RECORD,,
|
|
File without changes
|