approval-utilities 14.4.0__tar.gz → 14.6.0__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.
Potentially problematic release.
This version of approval-utilities might be problematic. Click here for more details.
- {approval_utilities-14.4.0/approval_utilities.egg-info → approval_utilities-14.6.0}/PKG-INFO +1 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/README.md +8 -6
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/approvaltests/core/executable_command.py +1 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/approvaltests/core/verifiable.py +1 -0
- approval_utilities-14.6.0/approval_utilities/approvaltests/core/verify_parameters.py +9 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/list_utils.py +3 -3
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/clipboard_utilities.py +1 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/deprecated.py +2 -2
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/exceptions/exception_collector.py +5 -5
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/exceptions/exception_utils.py +1 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/logger/logging_instance.py +57 -35
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/logger/simple_logger.py +17 -13
- approval_utilities-14.6.0/approval_utilities/utilities/map_reduce.py +17 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/markdown_table.py +10 -3
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/multiline_string_utils.py +2 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/persistence/loader.py +1 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/persistence/saver.py +1 -1
- approval_utilities-14.6.0/approval_utilities/utilities/string_wrapper.py +17 -0
- approval_utilities-14.6.0/approval_utilities/utilities/time_utilities.py +28 -0
- approval_utilities-14.6.0/approval_utilities/utilities/wrapper.py +34 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utils.py +9 -7
- {approval_utilities-14.4.0 → approval_utilities-14.6.0/approval_utilities.egg-info}/PKG-INFO +1 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/setup.py +4 -2
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/setup_utils.py +11 -5
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_approvaltests_temp_dir.py +1 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_asserts.py +12 -8
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_build.py +2 -2
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_combinations.py +9 -5
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_compare_file_lists.py +11 -6
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_custom_printers.py +7 -3
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_example_numpy.py +9 -5
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_exception_utils.py +4 -4
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_fileapprover.py +12 -12
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_find_stale_approved_files.py +13 -8
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_inline_approvals.py +24 -36
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_list.py +4 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_multiline_string_utils.py +3 -3
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_namer.py +13 -13
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_options.py +16 -13
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_pairwise_combinations.py +2 -2
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_parse_inputs.py +11 -9
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_python_patterns.py +3 -3
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_scenarios.py +3 -2
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_simple_logger.py +44 -20
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_split_code.py +1 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_verify.py +27 -18
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_verify_all.py +1 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_verify_argument_parser.py +1 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/tests/test_writer.py +3 -3
- approval_utilities-14.6.0/version.py +1 -0
- approval_utilities-14.4.0/approval_utilities/approvaltests/core/verify_parameters.py +0 -3
- approval_utilities-14.4.0/approval_utilities/utilities/map_reduce.py +0 -6
- approval_utilities-14.4.0/approval_utilities/utilities/string_wrapper.py +0 -12
- approval_utilities-14.4.0/approval_utilities/utilities/time_utilities.py +0 -21
- approval_utilities-14.4.0/approval_utilities/utilities/wrapper.py +0 -27
- approval_utilities-14.4.0/version.py +0 -1
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/LICENSE +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/MANIFEST.in +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/__init__.py +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/approvaltests/__init__.py +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/approvaltests/core/__init__.py +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/py.typed +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/__init__.py +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/exceptions/__init__.py +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/exceptions/multiple_exceptions.py +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/logger/__init__.py +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/os_utilities.py +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/persistence/__init__.py +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/stack_frame_utilities.py +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities.egg-info/SOURCES.txt +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities.egg-info/dependency_links.txt +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities.egg-info/top_level.txt +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/requirements.prod.extras.txt +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/requirements.prod.required.txt +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/requirements.prod.txt +0 -0
- {approval_utilities-14.4.0 → approval_utilities-14.6.0}/setup.cfg +0 -0
|
@@ -37,6 +37,7 @@ For more information see: [www.approvaltests.com](http://approvaltests.com/).
|
|
|
37
37
|
[](https://github.com/approvals/ApprovalTests.Python/actions)
|
|
38
38
|
[](https://github.com/approvals/ApprovalTests.Python/actions?query=workflow%3Aon-push-do-doco)
|
|
39
39
|
[](https://github.com/approvals/ApprovalTests.Python/actions?query=workflow%3A%22Upload+Python+Package%22)
|
|
40
|
+
[](https://discord.gg/XDrgy6x6Se)
|
|
40
41
|
|
|
41
42
|
## What can I use ApprovalTests for?
|
|
42
43
|
|
|
@@ -84,7 +85,7 @@ golden master.
|
|
|
84
85
|
from approvaltests.approvals import verify
|
|
85
86
|
|
|
86
87
|
|
|
87
|
-
def test_simple():
|
|
88
|
+
def test_simple() -> None:
|
|
88
89
|
result = "Hello ApprovalTests"
|
|
89
90
|
verify(result)
|
|
90
91
|
```
|
|
@@ -111,7 +112,7 @@ from approvaltests.approvals import verify
|
|
|
111
112
|
|
|
112
113
|
|
|
113
114
|
class GettingStartedTest(unittest.TestCase):
|
|
114
|
-
def test_simple(self):
|
|
115
|
+
def test_simple(self) -> None:
|
|
115
116
|
verify("Hello ApprovalTests")
|
|
116
117
|
|
|
117
118
|
|
|
@@ -170,7 +171,7 @@ class TestSelectReporterFromClass(unittest.TestCase):
|
|
|
170
171
|
def test_simple(self):
|
|
171
172
|
verify("Hello", options=Options().with_reporter(report_with_beyond_compare()))
|
|
172
173
|
```
|
|
173
|
-
<sup><a href='/tests/samples/test_getting_started.py#
|
|
174
|
+
<sup><a href='/tests/samples/test_getting_started.py#L28-L34' title='Snippet source file'>snippet source</a> | <a href='#snippet-select_reporter_from_class' title='Start of snippet'>anchor</a></sup>
|
|
174
175
|
<!-- endSnippet -->
|
|
175
176
|
|
|
176
177
|
You can also use the `GenericDiffReporterFactory` to find and select the first diff utility that exists on our system.
|
|
@@ -181,6 +182,7 @@ An advantage of this method is you can modify the reporters.json file directly t
|
|
|
181
182
|
<a id='snippet-select_reporter_from_factory'></a>
|
|
182
183
|
```py
|
|
183
184
|
class TestSelectReporter(unittest.TestCase):
|
|
185
|
+
@override
|
|
184
186
|
def setUp(self):
|
|
185
187
|
self.factory = GenericDiffReporterFactory()
|
|
186
188
|
|
|
@@ -189,7 +191,7 @@ class TestSelectReporter(unittest.TestCase):
|
|
|
189
191
|
"Hello", options=Options().with_reporter(self.factory.get("BeyondCompare"))
|
|
190
192
|
)
|
|
191
193
|
```
|
|
192
|
-
<sup><a href='/tests/samples/test_getting_started.py#
|
|
194
|
+
<sup><a href='/tests/samples/test_getting_started.py#L13-L25' title='Snippet source file'>snippet source</a> | <a href='#snippet-select_reporter_from_factory' title='Start of snippet'>anchor</a></sup>
|
|
193
195
|
<!-- endSnippet -->
|
|
194
196
|
|
|
195
197
|
Or you can build your own GenericDiffReporter on the fly
|
|
@@ -206,7 +208,7 @@ class GettingStartedTest(unittest.TestCase):
|
|
|
206
208
|
),
|
|
207
209
|
)
|
|
208
210
|
```
|
|
209
|
-
<sup><a href='/tests/samples/test_getting_started.py#
|
|
211
|
+
<sup><a href='/tests/samples/test_getting_started.py#L37-L48' title='Snippet source file'>snippet source</a> | <a href='#snippet-custom_generic_diff_reporter' title='Start of snippet'>anchor</a></sup>
|
|
210
212
|
<!-- endSnippet -->
|
|
211
213
|
|
|
212
214
|
As long as `C:/my/favorite/diff/utility.exe` can be invoked from the command line using the format `utility.exe file1 file2`
|
|
@@ -314,7 +316,7 @@ The best way to contribute is to [join our weekly mob/ensemble](./docs/Contribut
|
|
|
314
316
|
Pull requests are welcomed, particularly those accompanied by automated tests.
|
|
315
317
|
|
|
316
318
|
To run the self-tests:
|
|
317
|
-
`./
|
|
319
|
+
`./build_and_test.sh`
|
|
318
320
|
|
|
319
321
|
This will run the self-tests on several python versions. We support python 3.8 and above.
|
|
320
322
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from typing import Callable, List, Optional
|
|
1
|
+
from typing import Any, Callable, List, Optional
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def format_list(alist: List[
|
|
4
|
+
def format_list(alist: List[Any], formatter: Optional[Callable], header: str) -> str:
|
|
5
5
|
if formatter is None:
|
|
6
6
|
formatter = FormatLineItem().print_item
|
|
7
7
|
text = (header + "\n\n") if header else ""
|
|
@@ -14,7 +14,7 @@ class FormatLineItem(object):
|
|
|
14
14
|
def __init__(self) -> None:
|
|
15
15
|
self.index = 0
|
|
16
16
|
|
|
17
|
-
def print_item(self, item:
|
|
17
|
+
def print_item(self, item: Any) -> str:
|
|
18
18
|
text = str(self.index) + ") " + str(item)
|
|
19
19
|
self.index += 1
|
|
20
20
|
return text
|
{approval_utilities-14.4.0 → approval_utilities-14.6.0}/approval_utilities/utilities/deprecated.py
RENAMED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import warnings
|
|
2
1
|
import functools
|
|
2
|
+
import warnings
|
|
3
3
|
from typing import Callable
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def deprecated(reason: str) -> Callable:
|
|
7
|
-
def decorator(func):
|
|
7
|
+
def decorator(func: Callable) -> Callable:
|
|
8
8
|
"""This is a decorator which can be used to mark functions
|
|
9
9
|
as deprecated. It will result in a warning being emitted
|
|
10
10
|
when the function is used."""
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Callable,
|
|
1
|
+
from typing import Any, Callable, List, Sequence
|
|
2
2
|
|
|
3
3
|
from approval_utilities.utilities.exceptions.multiple_exceptions import (
|
|
4
4
|
MultipleExceptions,
|
|
@@ -6,16 +6,16 @@ from approval_utilities.utilities.exceptions.multiple_exceptions import (
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class ExceptionCollector:
|
|
9
|
-
def __init__(self):
|
|
10
|
-
self._exceptions = []
|
|
9
|
+
def __init__(self) -> None:
|
|
10
|
+
self._exceptions: List[Exception] = []
|
|
11
11
|
|
|
12
|
-
def gather(self, code_to_execute: Callable):
|
|
12
|
+
def gather(self, code_to_execute: Callable[[], Any]) -> None:
|
|
13
13
|
try:
|
|
14
14
|
code_to_execute()
|
|
15
15
|
except Exception as exception:
|
|
16
16
|
self._exceptions.append(exception)
|
|
17
17
|
|
|
18
|
-
def release(self):
|
|
18
|
+
def release(self) -> None:
|
|
19
19
|
if len(self._exceptions) == 0:
|
|
20
20
|
return
|
|
21
21
|
if len(self._exceptions) == 1:
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
def to_string(exception:
|
|
1
|
+
def to_string(exception: BaseException) -> str:
|
|
2
2
|
return f"{type(exception).__name__}: {str(exception)}"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import inspect
|
|
3
3
|
import traceback
|
|
4
|
-
from
|
|
5
|
-
|
|
4
|
+
from types import TracebackType
|
|
5
|
+
from typing import Any, Callable, ContextManager, Iterable, Optional, Type, Union
|
|
6
6
|
|
|
7
7
|
from approval_utilities.utilities.exceptions.exception_utils import to_string
|
|
8
|
-
from approval_utilities.utilities.string_wrapper import StringWrapper
|
|
9
8
|
from approval_utilities.utilities.stack_frame_utilities import get_class_name_for_frame
|
|
9
|
+
from approval_utilities.utilities.string_wrapper import StringWrapper
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class Toggles:
|
|
@@ -19,21 +19,21 @@ class Toggles:
|
|
|
19
19
|
self.events = show
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
def _is_iterable(arg):
|
|
22
|
+
def _is_iterable(arg: Any) -> bool:
|
|
23
23
|
return isinstance(arg, Iterable) and not isinstance(arg, str)
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
def print_type(value):
|
|
26
|
+
def print_type(value: Any) -> str:
|
|
27
27
|
return f"<{type(value).__name__}>"
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class LoggingInstance:
|
|
31
|
-
def __init__(self):
|
|
31
|
+
def __init__(self) -> None:
|
|
32
32
|
self.log_stack_traces = True
|
|
33
33
|
self.toggles = Toggles(True)
|
|
34
|
-
self.previous_timestamp = None
|
|
35
|
-
self.logger = lambda t: print(t, end="")
|
|
36
|
-
self.tabbing = 0
|
|
34
|
+
self.previous_timestamp: Optional[datetime.datetime] = None
|
|
35
|
+
self.logger: Callable[[str], None] = lambda t: print(t, end="")
|
|
36
|
+
self.tabbing: int = 0
|
|
37
37
|
self.counter = 0
|
|
38
38
|
self.log_with_timestamps = True
|
|
39
39
|
self.timer: Callable[[], datetime.datetime] = datetime.datetime.now
|
|
@@ -45,53 +45,71 @@ class LoggingInstance:
|
|
|
45
45
|
self.log_stack_traces = False
|
|
46
46
|
return buffer
|
|
47
47
|
|
|
48
|
-
def indent(self) -> ContextManager:
|
|
48
|
+
def indent(self) -> ContextManager[None]:
|
|
49
49
|
class Indent:
|
|
50
|
-
def __init__(self, log):
|
|
50
|
+
def __init__(self, log: "LoggingInstance") -> None:
|
|
51
51
|
self.log = log
|
|
52
52
|
|
|
53
|
-
def __enter__(self):
|
|
53
|
+
def __enter__(self) -> None:
|
|
54
54
|
self.log.tabbing += 1
|
|
55
55
|
|
|
56
|
-
def __exit__(
|
|
56
|
+
def __exit__(
|
|
57
|
+
self,
|
|
58
|
+
exc_type: Optional[Type[BaseException]],
|
|
59
|
+
exc_val: Optional[BaseException],
|
|
60
|
+
exc_tb: Optional[TracebackType],
|
|
61
|
+
) -> None:
|
|
57
62
|
self.log.tabbing -= 1
|
|
58
63
|
|
|
59
64
|
return Indent(self)
|
|
60
65
|
|
|
61
66
|
def use_markers(
|
|
62
|
-
self,
|
|
63
|
-
|
|
67
|
+
self,
|
|
68
|
+
parameter_text: Optional[Union[str, Callable[[], str]]] = None,
|
|
69
|
+
additional_stack: int = 0,
|
|
70
|
+
) -> ContextManager[None]:
|
|
64
71
|
class Nothing:
|
|
65
|
-
def __enter__(self):
|
|
72
|
+
def __enter__(self) -> None:
|
|
66
73
|
pass
|
|
67
74
|
|
|
68
|
-
def __exit__(
|
|
75
|
+
def __exit__(
|
|
76
|
+
self,
|
|
77
|
+
exc_type: Optional[type],
|
|
78
|
+
exc_val: Optional[BaseException],
|
|
79
|
+
exc_tb: Optional[TracebackType],
|
|
80
|
+
) -> None:
|
|
69
81
|
pass
|
|
70
82
|
|
|
71
83
|
if not self.toggles.markers:
|
|
72
84
|
return Nothing()
|
|
73
85
|
|
|
74
86
|
class Markers:
|
|
75
|
-
def __init__(
|
|
87
|
+
def __init__(
|
|
88
|
+
self, log: "LoggingInstance", method_name: str, filename: str
|
|
89
|
+
) -> None:
|
|
76
90
|
self.log = log
|
|
77
91
|
self.method_name = method_name
|
|
78
92
|
self.filename = filename
|
|
79
|
-
self.parameter_text = parameter_text
|
|
80
93
|
|
|
81
|
-
def __enter__(self):
|
|
94
|
+
def __enter__(self) -> None:
|
|
82
95
|
expected = f"-> in: {self.method_name}({self.get_parameters(False)}) in {self.filename}"
|
|
83
96
|
self.log.log_line(expected)
|
|
84
97
|
self.log.tabbing = self.log.tabbing + 1
|
|
85
98
|
|
|
86
|
-
def __exit__(
|
|
99
|
+
def __exit__(
|
|
100
|
+
self,
|
|
101
|
+
exc_type: Optional[type],
|
|
102
|
+
exc_val: Optional[BaseException],
|
|
103
|
+
exc_tb: Optional[TracebackType],
|
|
104
|
+
) -> None:
|
|
87
105
|
self.log.tabbing = self.log.tabbing - 1
|
|
88
106
|
expected = f"<- out: {self.method_name}({self.get_parameters(True)})"
|
|
89
107
|
self.log.log_line(expected)
|
|
90
108
|
|
|
91
|
-
def get_parameters(self, is_exit: bool):
|
|
92
|
-
if
|
|
109
|
+
def get_parameters(self, is_exit: bool) -> str:
|
|
110
|
+
if callable(parameter_text):
|
|
93
111
|
return parameter_text()
|
|
94
|
-
elif
|
|
112
|
+
elif parameter_text is None or is_exit:
|
|
95
113
|
return ""
|
|
96
114
|
else:
|
|
97
115
|
return str(parameter_text)
|
|
@@ -101,9 +119,9 @@ class LoggingInstance:
|
|
|
101
119
|
method_name = stack.function
|
|
102
120
|
|
|
103
121
|
filename = get_class_name_for_frame(stack)
|
|
104
|
-
return Markers(self, method_name, filename
|
|
122
|
+
return Markers(self, method_name, filename)
|
|
105
123
|
|
|
106
|
-
def log_line(self, text: str, use_timestamps=True) -> None:
|
|
124
|
+
def log_line(self, text: str, use_timestamps: bool = True) -> None:
|
|
107
125
|
if self.counter != 0:
|
|
108
126
|
self.logger("\n")
|
|
109
127
|
self.counter = 0
|
|
@@ -152,7 +170,7 @@ class LoggingInstance:
|
|
|
152
170
|
if not self.toggles.variables:
|
|
153
171
|
return
|
|
154
172
|
|
|
155
|
-
def to_type(value: Any, spacing=" ") -> str:
|
|
173
|
+
def to_type(value: Any, spacing: str = " ") -> str:
|
|
156
174
|
return f"{spacing}{print_type(value)}" if show_types else ""
|
|
157
175
|
|
|
158
176
|
if _is_iterable(value):
|
|
@@ -176,12 +194,16 @@ class LoggingInstance:
|
|
|
176
194
|
return
|
|
177
195
|
self.log_line(f"Sql: {query_text}")
|
|
178
196
|
|
|
179
|
-
def message(self, message):
|
|
197
|
+
def message(self, message: str) -> None:
|
|
180
198
|
if not self.toggles.messages:
|
|
181
199
|
return
|
|
182
200
|
self.log_line(f"message: {message}")
|
|
183
201
|
|
|
184
|
-
def warning(
|
|
202
|
+
def warning(
|
|
203
|
+
self,
|
|
204
|
+
text: Union[str, BaseException] = "",
|
|
205
|
+
exception: Optional[BaseException] = None,
|
|
206
|
+
) -> None:
|
|
185
207
|
if isinstance(text, Exception):
|
|
186
208
|
temp = ""
|
|
187
209
|
if exception:
|
|
@@ -206,23 +228,23 @@ class LoggingInstance:
|
|
|
206
228
|
self.log_line(stack_trace, use_timestamps=False)
|
|
207
229
|
self.log_line(warning_stars, use_timestamps=False)
|
|
208
230
|
|
|
209
|
-
def show_queries(self, show):
|
|
231
|
+
def show_queries(self, show: bool) -> None:
|
|
210
232
|
self.toggles.queries = show
|
|
211
233
|
|
|
212
234
|
def show_all(self, show: bool) -> None:
|
|
213
235
|
self.toggles = Toggles(show)
|
|
214
236
|
|
|
215
|
-
def show_messages(self, show):
|
|
237
|
+
def show_messages(self, show: bool) -> None:
|
|
216
238
|
self.toggles.messages = show
|
|
217
239
|
|
|
218
|
-
def show_variables(self, show):
|
|
240
|
+
def show_variables(self, show: bool) -> None:
|
|
219
241
|
self.toggles.variables = show
|
|
220
242
|
|
|
221
|
-
def show_hour_glass(self, show):
|
|
243
|
+
def show_hour_glass(self, show: bool) -> None:
|
|
222
244
|
self.toggles.hour_glass = show
|
|
223
245
|
|
|
224
|
-
def show_markers(self, show):
|
|
246
|
+
def show_markers(self, show: bool) -> None:
|
|
225
247
|
self.toggles.markers = show
|
|
226
248
|
|
|
227
|
-
def show_events(self, show):
|
|
249
|
+
def show_events(self, show: bool) -> None:
|
|
228
250
|
self.toggles.events = show
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import threading
|
|
2
|
-
from typing import Iterator,
|
|
2
|
+
from typing import Any, Callable, ContextManager, Iterator, Optional, Union
|
|
3
3
|
|
|
4
4
|
from approval_utilities.utilities.logger.logging_instance import LoggingInstance
|
|
5
5
|
from approval_utilities.utilities.string_wrapper import StringWrapper
|
|
6
|
-
from approval_utilities.utilities.wrapper import SingleWrapper, ThreadedWrapper
|
|
6
|
+
from approval_utilities.utilities.wrapper import SingleWrapper, ThreadedWrapper, Wrapper
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class SimpleLogger:
|
|
10
|
-
_wrapper = SingleWrapper(LoggingInstance())
|
|
10
|
+
_wrapper: Wrapper[LoggingInstance] = SingleWrapper(LoggingInstance())
|
|
11
11
|
|
|
12
12
|
@staticmethod
|
|
13
13
|
def register_logger(log_method: Callable[[str], None]) -> None:
|
|
14
14
|
SimpleLogger._wrapper.get().logger = log_method
|
|
15
15
|
|
|
16
16
|
@staticmethod
|
|
17
|
-
def log_to_string(log_separate_threads=True) -> StringWrapper:
|
|
17
|
+
def log_to_string(log_separate_threads: bool = True) -> StringWrapper:
|
|
18
18
|
with threading.Lock():
|
|
19
19
|
if log_separate_threads and not isinstance(
|
|
20
20
|
SimpleLogger._wrapper, ThreadedWrapper
|
|
@@ -23,7 +23,9 @@ class SimpleLogger:
|
|
|
23
23
|
return SimpleLogger._wrapper.get().log_to_string()
|
|
24
24
|
|
|
25
25
|
@staticmethod
|
|
26
|
-
def use_markers(
|
|
26
|
+
def use_markers(
|
|
27
|
+
parameter_text: Optional[Union[str, Callable[[], str]]] = None,
|
|
28
|
+
) -> ContextManager[None]:
|
|
27
29
|
return SimpleLogger._wrapper.get().use_markers(
|
|
28
30
|
parameter_text, additional_stack=1
|
|
29
31
|
)
|
|
@@ -53,33 +55,35 @@ class SimpleLogger:
|
|
|
53
55
|
SimpleLogger._wrapper.get().message(message)
|
|
54
56
|
|
|
55
57
|
@staticmethod
|
|
56
|
-
def warning(
|
|
58
|
+
def warning(
|
|
59
|
+
text: Union[str, BaseException] = "", exception: Optional[BaseException] = None
|
|
60
|
+
) -> None:
|
|
57
61
|
SimpleLogger._wrapper.get().warning(text, exception)
|
|
58
62
|
|
|
59
63
|
@staticmethod
|
|
60
|
-
def show_queries(show: bool):
|
|
64
|
+
def show_queries(show: bool) -> None:
|
|
61
65
|
SimpleLogger._wrapper.get().show_queries(show)
|
|
62
66
|
|
|
63
67
|
@staticmethod
|
|
64
|
-
def show_all(show: bool):
|
|
68
|
+
def show_all(show: bool) -> None:
|
|
65
69
|
SimpleLogger._wrapper.get().show_all(show)
|
|
66
70
|
|
|
67
71
|
@staticmethod
|
|
68
|
-
def show_messages(show: bool):
|
|
72
|
+
def show_messages(show: bool) -> None:
|
|
69
73
|
SimpleLogger._wrapper.get().show_messages(show)
|
|
70
74
|
|
|
71
75
|
@staticmethod
|
|
72
|
-
def show_variables(show: bool):
|
|
76
|
+
def show_variables(show: bool) -> None:
|
|
73
77
|
SimpleLogger._wrapper.get().show_variables(show)
|
|
74
78
|
|
|
75
79
|
@staticmethod
|
|
76
|
-
def show_hour_glass(show: bool):
|
|
80
|
+
def show_hour_glass(show: bool) -> None:
|
|
77
81
|
SimpleLogger._wrapper.get().show_hour_glass(show)
|
|
78
82
|
|
|
79
83
|
@staticmethod
|
|
80
|
-
def show_markers(show: bool):
|
|
84
|
+
def show_markers(show: bool) -> None:
|
|
81
85
|
SimpleLogger._wrapper.get().show_markers(show)
|
|
82
86
|
|
|
83
87
|
@staticmethod
|
|
84
|
-
def show_events(show: bool):
|
|
88
|
+
def show_events(show: bool) -> None:
|
|
85
89
|
SimpleLogger._wrapper.get().show_events(show)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import itertools
|
|
2
|
+
from typing import Any, Callable, Dict, Generator, Sequence
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def first(sequence: Sequence[Any], predicate: Callable[[Any], bool]) -> Any:
|
|
6
|
+
matching = filter(predicate, sequence)
|
|
7
|
+
return next(matching, None)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def product_dict(**kwargs: Sequence[Any]) -> Generator[Dict[str, Any], None, None]:
|
|
11
|
+
"""
|
|
12
|
+
Similar to `itertools.product`, but the resulting combinations retain the names.
|
|
13
|
+
"""
|
|
14
|
+
keys = kwargs.keys()
|
|
15
|
+
vals = kwargs.values()
|
|
16
|
+
for instance in itertools.product(*vals):
|
|
17
|
+
yield dict(zip(keys, instance))
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
from typing import Any, Callable, Iterable
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Callable, Iterable
|
|
2
|
+
|
|
3
|
+
from typing_extensions import override
|
|
2
4
|
|
|
3
5
|
from approval_utilities.approvaltests.core.verifiable import Verifiable
|
|
4
6
|
from approval_utilities.approvaltests.core.verify_parameters import VerifyParameters
|
|
5
7
|
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from approvaltests.core.options import Options
|
|
10
|
+
|
|
6
11
|
|
|
7
12
|
class MarkdownTable(Verifiable):
|
|
8
|
-
def __init__(self):
|
|
9
|
-
self.markdown = ""
|
|
13
|
+
def __init__(self) -> None:
|
|
14
|
+
self.markdown: str = ""
|
|
10
15
|
|
|
16
|
+
@override
|
|
11
17
|
def get_verify_parameters(self, options: "Options") -> VerifyParameters:
|
|
12
18
|
return VerifyParameters(options.for_file.with_extension(".md"))
|
|
13
19
|
|
|
@@ -23,6 +29,7 @@ class MarkdownTable(Verifiable):
|
|
|
23
29
|
self.markdown += MarkdownTable.print_row(*column_names)
|
|
24
30
|
return self
|
|
25
31
|
|
|
32
|
+
@override
|
|
26
33
|
def __str__(self) -> str:
|
|
27
34
|
return self.markdown
|
|
28
35
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import textwrap
|
|
2
|
+
from typing import Optional
|
|
2
3
|
|
|
3
4
|
from approval_utilities.utilities.logger.simple_logger import SimpleLogger
|
|
4
5
|
|
|
5
6
|
|
|
6
|
-
def remove_indentation_from(text: str) -> str:
|
|
7
|
+
def remove_indentation_from(text: Optional[str]) -> str:
|
|
7
8
|
SimpleLogger.variable("text", text)
|
|
8
9
|
if not text:
|
|
9
10
|
return ""
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from typing_extensions import override
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class StringWrapper:
|
|
5
|
+
def __init__(self) -> None:
|
|
6
|
+
self.string = ""
|
|
7
|
+
|
|
8
|
+
def append(self, text: str) -> None:
|
|
9
|
+
self.string += text
|
|
10
|
+
|
|
11
|
+
@override
|
|
12
|
+
def __str__(self) -> str:
|
|
13
|
+
return self.string
|
|
14
|
+
|
|
15
|
+
@override
|
|
16
|
+
def __repr__(self) -> str:
|
|
17
|
+
return self.string
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from types import TracebackType
|
|
3
|
+
from typing import Optional, Type
|
|
4
|
+
|
|
5
|
+
from typing_extensions import ContextManager
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def use_utc_timezone() -> ContextManager[None]:
|
|
9
|
+
class TimeZoneSwap:
|
|
10
|
+
def __init__(self) -> None:
|
|
11
|
+
self.timezone: Optional[str] = ""
|
|
12
|
+
|
|
13
|
+
def __enter__(self) -> None:
|
|
14
|
+
self.timezone = os.environ.get("TZ")
|
|
15
|
+
os.environ["TZ"] = "UTC"
|
|
16
|
+
|
|
17
|
+
def __exit__(
|
|
18
|
+
self,
|
|
19
|
+
exc_type: Optional[Type[BaseException]],
|
|
20
|
+
exc_val: Optional[BaseException],
|
|
21
|
+
exc_tb: Optional[TracebackType],
|
|
22
|
+
) -> bool:
|
|
23
|
+
if self.timezone is None:
|
|
24
|
+
os.environ.pop("TZ")
|
|
25
|
+
else:
|
|
26
|
+
os.environ["TZ"] = self.timezone
|
|
27
|
+
|
|
28
|
+
return TimeZoneSwap()
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
from typing import Callable, Generic, TypeVar, cast
|
|
4
|
+
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
7
|
+
_T = TypeVar("_T")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Wrapper(ABC, Generic[_T]):
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def get(self) -> _T:
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SingleWrapper(Wrapper[_T]):
|
|
17
|
+
def __init__(self, instance: _T):
|
|
18
|
+
self.instance = instance
|
|
19
|
+
|
|
20
|
+
@override
|
|
21
|
+
def get(self) -> _T:
|
|
22
|
+
return self.instance
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ThreadedWrapper(Wrapper[_T]):
|
|
26
|
+
def __init__(self, generator: Callable[[], _T]):
|
|
27
|
+
self.generator = generator
|
|
28
|
+
self.local = threading.local()
|
|
29
|
+
|
|
30
|
+
@override
|
|
31
|
+
def get(self) -> _T:
|
|
32
|
+
if not hasattr(self.local, "value"):
|
|
33
|
+
self.local.value = self.generator()
|
|
34
|
+
return cast(_T, self.local.value)
|