provide-testkit 0.5.1__tar.gz → 0.5.2__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.
- {provide_testkit-0.5.1/src/provide_testkit.egg-info → provide_testkit-0.5.2}/PKG-INFO +1 -1
- provide_testkit-0.5.2/VERSION +1 -0
- provide_testkit-0.5.2/src/provide/testkit/_capture.py +81 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/pytest_plugin.py +7 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2/src/provide_testkit.egg-info}/PKG-INFO +1 -1
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide_testkit.egg-info/SOURCES.txt +2 -0
- provide_testkit-0.5.2/tests/test_capture_stream_swap.py +142 -0
- provide_testkit-0.5.1/VERSION +0 -1
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/LICENSE +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/README.md +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/pyproject.toml +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/setup.cfg +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/__main__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/_blocker.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/_early_init.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/_install_blocker.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/_install_pth.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/_streams.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/base/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/base/foundation.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/base/harness.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/base/minimal.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/chaos/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/chaos/concurrency_strategies.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/chaos/fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/chaos/io_strategies.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/chaos/strategies.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/chaos/time_strategies.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/cli/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/cli/runner.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/cli/testing.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/common/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/common/fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/conftest.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/crypto/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/crypto/fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/file/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/file/content_fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/file/directory_fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/file/fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/file/special_fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/file/temp.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/hub/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/hub/fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/logger/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/logger/hooks.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/logger/mocks.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/logger/reset.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/main.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/mocking/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/mocking/fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/mocking/time.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/process/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/process/async_fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/process/fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/process/script_assertions.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/process/script_fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/process/subprocess_fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/process/system_fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/provide_testkit_init.pth +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/py.typed +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/artifacts.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/base.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/cli.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/complexity/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/complexity/analyzer.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/complexity/fixture.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/coverage/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/coverage/fixture.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/coverage/reporter.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/coverage/tracker.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/decorators.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/documentation/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/documentation/checker.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/documentation/fixture.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/profiling/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/profiling/fixture.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/profiling/profiler.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/report.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/runner.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/security/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/security/fixture.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/security/gitleaks_scanner.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/security/pip_audit_scanner.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/security/safety_scanner.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/security/scanner.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/security/semgrep_scanner.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/security/trufflehog_scanner.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/streams/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/streams/testing.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/threading/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/threading/basic_fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/threading/data_fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/threading/execution_fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/threading/fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/threading/sync_fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/time/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/time/classes.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/time/controlled.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/time/fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/time/freezing.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/time/measurement.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/time/mocking.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/time/rate_limiting.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/transport/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/transport/fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/utils/__init__.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/utils/environment.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/utils/temp_env.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide_testkit.egg-info/dependency_links.txt +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide_testkit.egg-info/entry_points.txt +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide_testkit.egg-info/requires.txt +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide_testkit.egg-info/top_level.txt +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/tests/test_async_fixtures.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/tests/test_early_init.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/tests/test_placeholder.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/tests/test_pth_installation.py +0 -0
- {provide_testkit-0.5.1 → provide_testkit-0.5.2}/tests/test_stream_encoding.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.5.2
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#
|
|
2
|
+
# SPDX-FileCopyrightText: Copyright (c) provide.io llc. All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
"""Capture that gives back the stream it took, not the one it remembers.
|
|
7
|
+
|
|
8
|
+
``SysCaptureBase.suspend`` hands ``sys.stdout`` back to the stream pytest saved
|
|
9
|
+
before capture started, and ``resume`` reinstates ``tmpfile`` -- the stream
|
|
10
|
+
capture installed at ``start``. Neither looks at what is actually there. A test
|
|
11
|
+
that swaps the stream after capture started owns something pytest has no record
|
|
12
|
+
of, so the swap is discarded on the first suspend and every write after it lands
|
|
13
|
+
in pytest's buffer instead of the caller's.
|
|
14
|
+
|
|
15
|
+
``log_cli = true`` makes that ordinary: pytest's live-log handler sits on the
|
|
16
|
+
root logger and suspends global capture around each record. One log line emitted
|
|
17
|
+
from inside ``CliRunner.invoke`` -- from any library, at any depth -- leaves
|
|
18
|
+
``result.output`` empty while the text itself is real and lands in pytest's own
|
|
19
|
+
capture. ``contextlib.redirect_stdout`` and hand-rolled stream fixtures lose
|
|
20
|
+
their swap the same way.
|
|
21
|
+
|
|
22
|
+
The pair below remembers the stream that was in place at suspend and returns it
|
|
23
|
+
at resume, which is what the two methods already claim to do. Teardown is
|
|
24
|
+
untouched: ``done`` still restores the stream capture replaced, so a swap left
|
|
25
|
+
behind by a test cannot outlive it.
|
|
26
|
+
|
|
27
|
+
This belongs in pytest, and the tests in ``tests/test_capture_stream_swap.py``
|
|
28
|
+
drive the real ``SysCapture``, so they fail loudly once pytest changes the
|
|
29
|
+
methods underneath -- whether it fixes this or reshapes the class. Drop this
|
|
30
|
+
module when the pytest floor carries the fix.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import sys
|
|
36
|
+
from typing import Any
|
|
37
|
+
|
|
38
|
+
from _pytest.capture import SysCaptureBase
|
|
39
|
+
|
|
40
|
+
__all__ = ["install_capture_swap_fix"]
|
|
41
|
+
|
|
42
|
+
_INSTALLED_MARKER = "_provide_testkit_swap_safe"
|
|
43
|
+
# The stream is parked on pytest's object, so the name says whose it is.
|
|
44
|
+
_SWAPPED_IN = "_provide_testkit_swapped_in"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _suspend(self: SysCaptureBase[Any]) -> None:
|
|
48
|
+
self._assert_state("suspend", ("started", "suspended"))
|
|
49
|
+
# Suspending while suspended is legal, and the stream sitting there then is
|
|
50
|
+
# the one suspend itself installed -- not a swap worth remembering.
|
|
51
|
+
if self._state == "started":
|
|
52
|
+
setattr(self, _SWAPPED_IN, getattr(sys, self.name))
|
|
53
|
+
setattr(sys, self.name, self._old)
|
|
54
|
+
self._state = "suspended"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _resume(self: SysCaptureBase[Any]) -> None:
|
|
58
|
+
self._assert_state("resume", ("started", "suspended"))
|
|
59
|
+
if self._state == "started":
|
|
60
|
+
return
|
|
61
|
+
# A capture resumed without ever suspending has nothing recorded, and the
|
|
62
|
+
# stream capture installed is the right answer for it.
|
|
63
|
+
setattr(sys, self.name, getattr(self, _SWAPPED_IN, self.tmpfile))
|
|
64
|
+
self._state = "started"
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def install_capture_swap_fix() -> bool:
|
|
68
|
+
"""Make pytest's stream capture preserve a swap made after it started.
|
|
69
|
+
|
|
70
|
+
Returns whether this call is the one that installed it. Declining leaves
|
|
71
|
+
pytest exactly as found: the fix is worth having, and silently layering it
|
|
72
|
+
over a patch someone else installed is not.
|
|
73
|
+
"""
|
|
74
|
+
if getattr(SysCaptureBase, _INSTALLED_MARKER, False):
|
|
75
|
+
return False
|
|
76
|
+
if any(getattr(SysCaptureBase, name).__module__ != "_pytest.capture" for name in ("suspend", "resume")):
|
|
77
|
+
return False
|
|
78
|
+
SysCaptureBase.suspend = _suspend # type: ignore[method-assign]
|
|
79
|
+
SysCaptureBase.resume = _resume # type: ignore[method-assign]
|
|
80
|
+
setattr(SysCaptureBase, _INSTALLED_MARKER, True)
|
|
81
|
+
return True
|
|
@@ -29,6 +29,7 @@ import sys
|
|
|
29
29
|
|
|
30
30
|
import structlog
|
|
31
31
|
|
|
32
|
+
from provide.testkit._capture import install_capture_swap_fix
|
|
32
33
|
from provide.testkit._streams import unicode_safe
|
|
33
34
|
|
|
34
35
|
# Configure structlog with test-safe defaults BEFORE Foundation imports.
|
|
@@ -84,6 +85,12 @@ from provide.testkit._install_blocker import install_setproctitle_blocker # noq
|
|
|
84
85
|
|
|
85
86
|
install_setproctitle_blocker(force=True)
|
|
86
87
|
|
|
88
|
+
# Pytest hands a suspended stream back to whatever it saved at start, so a test
|
|
89
|
+
# that swaps sys.stdout after that -- CliRunner.isolation, redirect_stdout --
|
|
90
|
+
# loses the swap the first time a live log record suspends capture, and its
|
|
91
|
+
# output lands in pytest's buffer instead. See provide.testkit._capture.
|
|
92
|
+
install_capture_swap_fix()
|
|
93
|
+
|
|
87
94
|
__all__ = ["SetproctitleImportBlocker", "pytest_load_initial_conftests"]
|
|
88
95
|
|
|
89
96
|
|
|
@@ -6,6 +6,7 @@ src/provide/__init__.py
|
|
|
6
6
|
src/provide/testkit/__init__.py
|
|
7
7
|
src/provide/testkit/__main__.py
|
|
8
8
|
src/provide/testkit/_blocker.py
|
|
9
|
+
src/provide/testkit/_capture.py
|
|
9
10
|
src/provide/testkit/_early_init.py
|
|
10
11
|
src/provide/testkit/_install_blocker.py
|
|
11
12
|
src/provide/testkit/_install_pth.py
|
|
@@ -110,6 +111,7 @@ src/provide_testkit.egg-info/entry_points.txt
|
|
|
110
111
|
src/provide_testkit.egg-info/requires.txt
|
|
111
112
|
src/provide_testkit.egg-info/top_level.txt
|
|
112
113
|
tests/test_async_fixtures.py
|
|
114
|
+
tests/test_capture_stream_swap.py
|
|
113
115
|
tests/test_early_init.py
|
|
114
116
|
tests/test_placeholder.py
|
|
115
117
|
tests/test_pth_installation.py
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#
|
|
2
|
+
# SPDX-FileCopyrightText: Copyright (c) provide.io llc. All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
"""Pytest's capture must give back the stream it took, not the one it remembers.
|
|
7
|
+
|
|
8
|
+
``SysCaptureBase.resume`` reinstates the stream capture installed at ``start``.
|
|
9
|
+
Anything that swapped ``sys.stdout`` after that point -- ``CliRunner.isolation``,
|
|
10
|
+
``redirect_stdout``, a fixture of one's own -- is dropped the first time capture
|
|
11
|
+
suspends, and every write after that lands in pytest's buffer. Live logging
|
|
12
|
+
(``log_cli = true``) suspends capture per record, so one log line emitted from
|
|
13
|
+
inside a Click command empties ``result.output`` while the text itself is real.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from collections.abc import Iterator
|
|
19
|
+
import io
|
|
20
|
+
import sys
|
|
21
|
+
|
|
22
|
+
from _pytest.capture import SysCapture
|
|
23
|
+
import pytest
|
|
24
|
+
|
|
25
|
+
from provide.testkit._capture import install_capture_swap_fix
|
|
26
|
+
|
|
27
|
+
STDOUT_FD = 1
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@pytest.fixture
|
|
31
|
+
def stdout_restored() -> Iterator[None]:
|
|
32
|
+
"""Put ``sys.stdout`` back, however the test under it leaves things."""
|
|
33
|
+
saved = sys.stdout
|
|
34
|
+
try:
|
|
35
|
+
yield
|
|
36
|
+
finally:
|
|
37
|
+
sys.stdout = saved
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.mark.usefixtures("stdout_restored")
|
|
41
|
+
def test_resume_returns_a_swap_made_after_capture_started() -> None:
|
|
42
|
+
"""The case behind an empty ``CliRunner.result.output``."""
|
|
43
|
+
capture = SysCapture(STDOUT_FD)
|
|
44
|
+
capture.start()
|
|
45
|
+
swapped_in = io.StringIO()
|
|
46
|
+
sys.stdout = swapped_in
|
|
47
|
+
|
|
48
|
+
capture.suspend()
|
|
49
|
+
capture.resume()
|
|
50
|
+
|
|
51
|
+
assert sys.stdout is swapped_in
|
|
52
|
+
capture.done()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@pytest.mark.usefixtures("stdout_restored")
|
|
56
|
+
def test_resume_returns_the_capture_stream_when_nothing_swapped_it() -> None:
|
|
57
|
+
"""The ordinary path stays exactly as pytest wrote it."""
|
|
58
|
+
capture = SysCapture(STDOUT_FD)
|
|
59
|
+
capture.start()
|
|
60
|
+
|
|
61
|
+
capture.suspend()
|
|
62
|
+
capture.resume()
|
|
63
|
+
|
|
64
|
+
assert sys.stdout is capture.tmpfile
|
|
65
|
+
capture.done()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@pytest.mark.usefixtures("stdout_restored")
|
|
69
|
+
def test_a_second_suspend_does_not_overwrite_the_remembered_swap() -> None:
|
|
70
|
+
"""Suspending while suspended is legal, and must not record ``_old`` as the swap."""
|
|
71
|
+
capture = SysCapture(STDOUT_FD)
|
|
72
|
+
capture.start()
|
|
73
|
+
swapped_in = io.StringIO()
|
|
74
|
+
sys.stdout = swapped_in
|
|
75
|
+
|
|
76
|
+
capture.suspend()
|
|
77
|
+
capture.suspend()
|
|
78
|
+
capture.resume()
|
|
79
|
+
|
|
80
|
+
assert sys.stdout is swapped_in
|
|
81
|
+
capture.done()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@pytest.mark.usefixtures("stdout_restored")
|
|
85
|
+
def test_done_restores_the_stream_capture_replaced() -> None:
|
|
86
|
+
"""Teardown belongs to pytest: a foreign swap does not outlive the capture."""
|
|
87
|
+
original = sys.stdout
|
|
88
|
+
capture = SysCapture(STDOUT_FD)
|
|
89
|
+
capture.start()
|
|
90
|
+
sys.stdout = io.StringIO()
|
|
91
|
+
|
|
92
|
+
capture.done()
|
|
93
|
+
|
|
94
|
+
assert sys.stdout is original
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_installing_the_fix_again_reports_that_it_was_already_there() -> None:
|
|
98
|
+
"""The plugin installs it at import; a second call must not stack a layer."""
|
|
99
|
+
assert install_capture_swap_fix() is False
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
CLI_UNDER_LIVE_LOGGING = """
|
|
103
|
+
import logging
|
|
104
|
+
|
|
105
|
+
import click
|
|
106
|
+
from click.testing import CliRunner
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@click.group(invoke_without_command=True)
|
|
110
|
+
@click.pass_context
|
|
111
|
+
def cli(ctx: click.Context) -> None:
|
|
112
|
+
# Any library logging from inside the command does this; the record only has
|
|
113
|
+
# to reach the root logger, where live logging is listening.
|
|
114
|
+
logging.getLogger("some.library").warning("a record reaches the root logger")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@cli.command()
|
|
118
|
+
def sub() -> None:
|
|
119
|
+
click.echo("SUBCOMMAND OUTPUT")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def test_the_runner_sees_what_the_command_printed() -> None:
|
|
123
|
+
assert CliRunner().invoke(cli, ["sub"]).output != ""
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def test_a_cli_runner_keeps_its_output_across_a_live_log_record(pytester: pytest.Pytester) -> None:
|
|
128
|
+
"""The reported symptom, through the real Click and the real live-log handler."""
|
|
129
|
+
pytester.makepyfile(CLI_UNDER_LIVE_LOGGING)
|
|
130
|
+
|
|
131
|
+
result = pytester.runpytest_subprocess("-o", "log_cli=true")
|
|
132
|
+
|
|
133
|
+
result.assert_outcomes(passed=1)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def test_the_same_run_loses_its_output_without_this_plugin(pytester: pytest.Pytester) -> None:
|
|
137
|
+
"""Without this, the test above could pass for the wrong reason."""
|
|
138
|
+
pytester.makepyfile(CLI_UNDER_LIVE_LOGGING)
|
|
139
|
+
|
|
140
|
+
result = pytester.runpytest_subprocess("-o", "log_cli=true", "-p", "no:provide_testkit")
|
|
141
|
+
|
|
142
|
+
result.assert_outcomes(failed=1)
|
provide_testkit-0.5.1/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.5.1
|
|
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
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/chaos/concurrency_strategies.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/chaos/time_strategies.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
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/file/content_fixtures.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/file/directory_fixtures.py
RENAMED
|
File without changes
|
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/file/special_fixtures.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
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/process/async_fixtures.py
RENAMED
|
File without changes
|
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/process/script_assertions.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/process/script_fixtures.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/process/subprocess_fixtures.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/process/system_fixtures.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/provide_testkit_init.pth
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/complexity/__init__.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/complexity/analyzer.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/complexity/fixture.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/coverage/__init__.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/coverage/fixture.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/coverage/reporter.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/coverage/tracker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/documentation/checker.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/documentation/fixture.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/profiling/__init__.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/profiling/fixture.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/profiling/profiler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/security/__init__.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/security/fixture.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/quality/security/scanner.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/threading/basic_fixtures.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/threading/data_fixtures.py
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/threading/execution_fixtures.py
RENAMED
|
File without changes
|
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide/testkit/threading/sync_fixtures.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
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide_testkit.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{provide_testkit-0.5.1 → provide_testkit-0.5.2}/src/provide_testkit.egg-info/entry_points.txt
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
|