wrapture 1.0.0.dev4__tar.gz → 1.0.0.dev6__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.
- {wrapture-1.0.0.dev4/src/wrapture.egg-info → wrapture-1.0.0.dev6}/PKG-INFO +5 -2
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/README.md +4 -1
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/__init__.py +1 -1
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/events.py +11 -3
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/timeline.py +5 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6/src/wrapture.egg-info}/PKG-INFO +5 -2
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_events.py +25 -1
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_timeline.py +12 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/LICENSE +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/pyproject.toml +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/setup.cfg +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/__main__.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/asgi.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/attributes.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/behaviours.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/bindings.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/bootstrap.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/capture.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/collectors.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/config.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/eventlogs.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/exceptions.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/export.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/iterators.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/lifecycle.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/observed.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/outputs.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/py.typed +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/pytest_plugin.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/scheduler.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/sinks.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/stacks.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/tools/__init__.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/tools/__main__.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/tools/convert.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/windows.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture/wsgi.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture.egg-info/SOURCES.txt +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture.egg-info/dependency_links.txt +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture.egg-info/entry_points.txt +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture.egg-info/not-zip-safe +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture.egg-info/requires.txt +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/src/wrapture.egg-info/top_level.txt +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_asgi.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_attribute_events.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_attributes.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_behaviours.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_bindings.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_bootstrap.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_capture.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_collectors.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_config.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_eventlogs.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_export.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_generator_events.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_iterators.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_jsonlines.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_observed.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_outputs.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_predicates.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_pytest_plugin.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_recording.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_runner.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_sink_library.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_sinks.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_stacks.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_targets.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_testing_patterns.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_threads.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_tools.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_version.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_windows.py +0 -0
- {wrapture-1.0.0.dev4 → wrapture-1.0.0.dev6}/tests/test_wsgi.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wrapture
|
|
3
|
-
Version: 1.0.0.
|
|
3
|
+
Version: 1.0.0.dev6
|
|
4
4
|
Summary: Monkey patch, test, and trace Python by attaching bindings to call sites, without modifying the code being observed. Built on wrapt.
|
|
5
5
|
Author-email: Graham Dumpleton <Graham.Dumpleton@gmail.com>
|
|
6
6
|
License-Expression: BSD-2-Clause
|
|
@@ -70,7 +70,10 @@ Start with the [getting started](https://wrapture.readthedocs.io/en/latest/getti
|
|
|
70
70
|
page: everything on it can be pasted into a Python interpreter. Coming
|
|
71
71
|
from `unittest.mock`? There is a
|
|
72
72
|
[comparison page](https://wrapture.readthedocs.io/en/latest/coming-from-mock.html)
|
|
73
|
-
mapping each mock idiom to its wrapture counterpart.
|
|
73
|
+
mapping each mock idiom to its wrapture counterpart. After that, the
|
|
74
|
+
worked examples, starting with
|
|
75
|
+
[testing code that calls external services](https://wrapture.readthedocs.io/en/latest/example-external-services.html),
|
|
76
|
+
each take one question you might arrive with and answer it end to end.
|
|
74
77
|
|
|
75
78
|
## Thirty seconds of it
|
|
76
79
|
|
|
@@ -39,7 +39,10 @@ Start with the [getting started](https://wrapture.readthedocs.io/en/latest/getti
|
|
|
39
39
|
page: everything on it can be pasted into a Python interpreter. Coming
|
|
40
40
|
from `unittest.mock`? There is a
|
|
41
41
|
[comparison page](https://wrapture.readthedocs.io/en/latest/coming-from-mock.html)
|
|
42
|
-
mapping each mock idiom to its wrapture counterpart.
|
|
42
|
+
mapping each mock idiom to its wrapture counterpart. After that, the
|
|
43
|
+
worked examples, starting with
|
|
44
|
+
[testing code that calls external services](https://wrapture.readthedocs.io/en/latest/example-external-services.html),
|
|
45
|
+
each take one question you might arrive with and answer it end to end.
|
|
43
46
|
|
|
44
47
|
## Thirty seconds of it
|
|
45
48
|
|
|
@@ -181,9 +181,17 @@ def _format_time(seconds: float) -> str:
|
|
|
181
181
|
def _own_time(event: Event) -> float | None:
|
|
182
182
|
# The execution-time basis for self-time arithmetic. A generator's
|
|
183
183
|
# wall duration includes the consumer's time between yields, so its
|
|
184
|
-
# accumulated body time is the honest measure of the code itself
|
|
185
|
-
#
|
|
186
|
-
#
|
|
184
|
+
# accumulated body time is the honest measure of the code itself. A
|
|
185
|
+
# request has two phases of application code, the synchronous call
|
|
186
|
+
# and the body it then streams, and its own time is their sum, again
|
|
187
|
+
# leaving out the server's time between chunks. Everything else uses
|
|
188
|
+
# its duration. None when the event has not closed with a time.
|
|
189
|
+
|
|
190
|
+
if event.kind == "request" and event.body_duration is not None:
|
|
191
|
+
app_duration = event.data.get("app_duration")
|
|
192
|
+
if app_duration is None:
|
|
193
|
+
return event.duration
|
|
194
|
+
return float(app_duration) + event.body_duration
|
|
187
195
|
|
|
188
196
|
if event.body_duration is not None:
|
|
189
197
|
return event.body_duration
|
|
@@ -246,8 +246,13 @@ class Tape(Sink):
|
|
|
246
246
|
def emit(event: Event) -> None:
|
|
247
247
|
injected = " (injected)" if event.injected else ""
|
|
248
248
|
|
|
249
|
+
# A get event's str() already carries its value, so only the
|
|
250
|
+
# injected mark is added to it.
|
|
251
|
+
|
|
249
252
|
if event.exception is not None:
|
|
250
253
|
marker = f" !! {type(event.exception).__name__}{injected}"
|
|
254
|
+
elif event.kind == "get":
|
|
255
|
+
marker = injected
|
|
251
256
|
elif event.result is not MISSING:
|
|
252
257
|
marker = f" -> {event.result!r}{injected}"
|
|
253
258
|
else:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wrapture
|
|
3
|
-
Version: 1.0.0.
|
|
3
|
+
Version: 1.0.0.dev6
|
|
4
4
|
Summary: Monkey patch, test, and trace Python by attaching bindings to call sites, without modifying the code being observed. Built on wrapt.
|
|
5
5
|
Author-email: Graham Dumpleton <Graham.Dumpleton@gmail.com>
|
|
6
6
|
License-Expression: BSD-2-Clause
|
|
@@ -70,7 +70,10 @@ Start with the [getting started](https://wrapture.readthedocs.io/en/latest/getti
|
|
|
70
70
|
page: everything on it can be pasted into a Python interpreter. Coming
|
|
71
71
|
from `unittest.mock`? There is a
|
|
72
72
|
[comparison page](https://wrapture.readthedocs.io/en/latest/coming-from-mock.html)
|
|
73
|
-
mapping each mock idiom to its wrapture counterpart.
|
|
73
|
+
mapping each mock idiom to its wrapture counterpart. After that, the
|
|
74
|
+
worked examples, starting with
|
|
75
|
+
[testing code that calls external services](https://wrapture.readthedocs.io/en/latest/example-external-services.html),
|
|
76
|
+
each take one question you might arrive with and answer it end to end.
|
|
74
77
|
|
|
75
78
|
## Thirty seconds of it
|
|
76
79
|
|
|
@@ -9,10 +9,16 @@ import gc
|
|
|
9
9
|
import weakref
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
+
import pytest
|
|
12
13
|
from wrapt import MISSING
|
|
13
14
|
|
|
14
15
|
from wrapture import Event
|
|
15
|
-
from wrapture.events import
|
|
16
|
+
from wrapture.events import (
|
|
17
|
+
_own_time,
|
|
18
|
+
_signature,
|
|
19
|
+
_signature_cache,
|
|
20
|
+
normalized_arguments,
|
|
21
|
+
)
|
|
16
22
|
|
|
17
23
|
|
|
18
24
|
def charge(amount: int, currency: str = "USD", *, retries: int = 3) -> None:
|
|
@@ -189,3 +195,21 @@ def test_cache_does_not_keep_the_function_alive() -> None:
|
|
|
189
195
|
|
|
190
196
|
gc.collect()
|
|
191
197
|
assert alive() is None
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def test_own_time_of_a_request_sums_both_application_phases() -> None:
|
|
201
|
+
# A request's own time is the synchronous call plus the body it
|
|
202
|
+
# produced, not the wall time that includes the server between chunks.
|
|
203
|
+
|
|
204
|
+
request = Event(kind="request", path="app:wsgi_app", duration=1.0)
|
|
205
|
+
request.body_duration = 0.2
|
|
206
|
+
request.data["app_duration"] = 0.3
|
|
207
|
+
|
|
208
|
+
assert _own_time(request) == pytest.approx(0.5)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def test_own_time_of_a_generator_is_its_body_time() -> None:
|
|
212
|
+
call = Event(kind="call", path="mod:gen", duration=1.0)
|
|
213
|
+
call.body_duration = 0.25
|
|
214
|
+
|
|
215
|
+
assert _own_time(call) == 0.25
|
|
@@ -354,6 +354,18 @@ def test_tree_renders_nesting_results_and_failures() -> None:
|
|
|
354
354
|
assert lines[2] == "Gateway.refund(amount=100) !! TimeoutError (injected)"
|
|
355
355
|
|
|
356
356
|
|
|
357
|
+
def test_tree_shows_a_get_event_value_once() -> None:
|
|
358
|
+
class Settings:
|
|
359
|
+
retries = 3
|
|
360
|
+
|
|
361
|
+
retries = binding(Settings, "retries")
|
|
362
|
+
|
|
363
|
+
with timeline(retries) as tape:
|
|
364
|
+
_ = Settings().retries
|
|
365
|
+
|
|
366
|
+
assert tape.tree() == "get Settings.retries -> 3"
|
|
367
|
+
|
|
368
|
+
|
|
357
369
|
def test_tree_of_an_empty_tape_is_empty() -> None:
|
|
358
370
|
with timeline() as tape:
|
|
359
371
|
pass
|
|
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
|