tpcp 2.2.0__tar.gz → 2.2.1__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.
- {tpcp-2.2.0 → tpcp-2.2.1}/PKG-INFO +1 -1
- {tpcp-2.2.0 → tpcp-2.2.1}/pyproject.toml +1 -1
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/__init__.py +1 -1
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/testing/_regression_utils.py +65 -15
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/validate/_validate.py +11 -13
- {tpcp-2.2.0 → tpcp-2.2.1}/README.md +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/skills/tpcp/tpcp-basics/SKILL.md +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/skills/tpcp/tpcp-builder/SKILL.md +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/skills/tpcp/tpcp-datasets/SKILL.md +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/skills/tpcp/tpcp-multiprocessing/SKILL.md +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/skills/tpcp/tpcp-optimization/SKILL.md +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/_algorithm.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/_algorithm_utils.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/_base.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/_cli.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/_dataset.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/_hash.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/_optimize.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/_parameters.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/_pipeline.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/_utils/__init__.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/_utils/_general.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/_utils/_score.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/caching.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/exceptions.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/misc/__init__.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/misc/_class_utils.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/misc/_typed_iterator.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/optimize/__init__.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/optimize/_optimize.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/optimize/optuna.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/parallel.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/testing/__init__.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/testing/_algorithm_test_mixin.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/types.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/validate/__init__.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/validate/_cross_val_helper.py +0 -0
- {tpcp-2.2.0 → tpcp-2.2.1}/src/tpcp/validate/_scorer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: tpcp
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: Pipeline and Dataset helpers for complex algorithm evaluation.
|
|
5
5
|
Author: Arne Küderle, Robert Richer, Raul C. Sîmpetru, Björn Eskofier
|
|
6
6
|
Author-email: Arne Küderle <arne.kuederle@fau.de>, Robert Richer <robert.richer@fau.de>, Raul C. Sîmpetru <raul.simpetru@fau.de>, Björn Eskofier <bjoern.eskofier@fau.de>
|
|
@@ -4,6 +4,7 @@ This is inspired by github.com/syrusakbary/snapshottest.
|
|
|
4
4
|
Note that it can not be used in combination with this module!
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
import difflib
|
|
7
8
|
import re
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from typing import Optional, Union
|
|
@@ -18,6 +19,10 @@ class SnapshotNotFoundError(Exception):
|
|
|
18
19
|
pass
|
|
19
20
|
|
|
20
21
|
|
|
22
|
+
class SnapshotAssertionError(AssertionError):
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
|
|
21
26
|
class PyTestSnapshotTest:
|
|
22
27
|
"""Perform snapshot tests in pytest.
|
|
23
28
|
|
|
@@ -82,6 +87,15 @@ class PyTestSnapshotTest:
|
|
|
82
87
|
def _file_name_txt(self):
|
|
83
88
|
return self._snapshot_folder / f"{self._test_name}.txt"
|
|
84
89
|
|
|
90
|
+
def _snapshot_file(self, dtype):
|
|
91
|
+
if dtype is pd.DataFrame:
|
|
92
|
+
return self._file_name_json
|
|
93
|
+
if dtype is np.ndarray:
|
|
94
|
+
return self._file_name_csv
|
|
95
|
+
if dtype is str:
|
|
96
|
+
return self._file_name_txt
|
|
97
|
+
raise ValueError(f"The dtype {dtype} is not supported for snapshot testing")
|
|
98
|
+
|
|
85
99
|
@property
|
|
86
100
|
def _test_name(self):
|
|
87
101
|
cls_name = getattr(self.request.node.cls, "__name__", "")
|
|
@@ -143,6 +157,50 @@ class PyTestSnapshotTest:
|
|
|
143
157
|
return value
|
|
144
158
|
raise ValueError(f"The dtype {dtype} is not supported for snapshot testing")
|
|
145
159
|
|
|
160
|
+
@staticmethod
|
|
161
|
+
def _format_string_difference(value: str, prev_snapshot: str) -> str:
|
|
162
|
+
diff = "".join(
|
|
163
|
+
difflib.unified_diff(
|
|
164
|
+
prev_snapshot.splitlines(keepends=True),
|
|
165
|
+
value.splitlines(keepends=True),
|
|
166
|
+
fromfile="stored",
|
|
167
|
+
tofile="current",
|
|
168
|
+
)
|
|
169
|
+
)
|
|
170
|
+
if diff:
|
|
171
|
+
return diff
|
|
172
|
+
return f"stored={prev_snapshot!r}\ncurrent={value!r}"
|
|
173
|
+
|
|
174
|
+
def _format_mismatch(self, dtype, value, prev_snapshot, error: Optional[AssertionError] = None) -> str:
|
|
175
|
+
if dtype is str:
|
|
176
|
+
details = self._format_string_difference(value, prev_snapshot)
|
|
177
|
+
else:
|
|
178
|
+
details = str(error) if error else "The snapshot content does not match the current value."
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
f"Snapshot mismatch for '{self._test_name}'.\n"
|
|
182
|
+
f"Snapshot file: {self._snapshot_file(dtype)}\n\n"
|
|
183
|
+
f"{details}\n\n"
|
|
184
|
+
"Run pytest with --snapshot-update to accept the new snapshot."
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
def _compare(self, value, prev_snapshot, value_dtype, **kwargs):
|
|
188
|
+
__tracebackhide__ = True
|
|
189
|
+
|
|
190
|
+
if isinstance(value, pd.DataFrame):
|
|
191
|
+
# convert datetime columns to match with the stored format
|
|
192
|
+
value = self._sanitize_datetime_entries(value)
|
|
193
|
+
assert_frame_equal(value, prev_snapshot, **kwargs)
|
|
194
|
+
return
|
|
195
|
+
if isinstance(value, np.ndarray):
|
|
196
|
+
np.testing.assert_array_almost_equal(value, prev_snapshot, **kwargs)
|
|
197
|
+
return
|
|
198
|
+
if isinstance(value, str):
|
|
199
|
+
if value != prev_snapshot:
|
|
200
|
+
raise SnapshotAssertionError(self._format_mismatch(value_dtype, value, prev_snapshot))
|
|
201
|
+
return
|
|
202
|
+
raise TypeError(f"The dtype {value_dtype} is not supported for snapshot testing")
|
|
203
|
+
|
|
146
204
|
def assert_match(self, value: Union[str, pd.DataFrame, np.ndarray], name: Optional[str] = None, **kwargs):
|
|
147
205
|
"""Assert that the value matches the snapshot.
|
|
148
206
|
|
|
@@ -171,6 +229,7 @@ class PyTestSnapshotTest:
|
|
|
171
229
|
There they will be passed to `assert_frame_equal` and `assert_array_almost_equal` respectively.
|
|
172
230
|
|
|
173
231
|
"""
|
|
232
|
+
__tracebackhide__ = True
|
|
174
233
|
self.curr_snapshot = name or str(self.curr_snapshot_number)
|
|
175
234
|
if self._update:
|
|
176
235
|
self._store(value)
|
|
@@ -189,21 +248,12 @@ class PyTestSnapshotTest:
|
|
|
189
248
|
except:
|
|
190
249
|
raise
|
|
191
250
|
else:
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
elif isinstance(value, str):
|
|
199
|
-
# Display the string diff line by line as part of error message using difflib
|
|
200
|
-
import difflib
|
|
201
|
-
|
|
202
|
-
diff = difflib.ndiff(value.splitlines(keepends=True), prev_snapshot.splitlines(keepends=True))
|
|
203
|
-
diff = "".join(diff)
|
|
204
|
-
assert value == prev_snapshot, diff
|
|
205
|
-
else:
|
|
206
|
-
raise TypeError(f"The dtype {value_dtype} is not supported for snapshot testing")
|
|
251
|
+
try:
|
|
252
|
+
self._compare(value, prev_snapshot, value_dtype, **kwargs)
|
|
253
|
+
except SnapshotAssertionError:
|
|
254
|
+
raise
|
|
255
|
+
except AssertionError as e:
|
|
256
|
+
raise SnapshotAssertionError(self._format_mismatch(value_dtype, value, prev_snapshot, e)) from None
|
|
207
257
|
|
|
208
258
|
self.curr_snapshot_number += 1
|
|
209
259
|
|
|
@@ -195,25 +195,23 @@ def validate(
|
|
|
195
195
|
True/False to enable/disable a `tqdm` progress bar.
|
|
196
196
|
"""
|
|
197
197
|
scoring_args = {"n_jobs": n_jobs, "verbose": verbose, "pre_dispatch": pre_dispatch, "progress_bar": progress_bar}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
raise ValueError(
|
|
198
|
+
if isinstance(scoring, Scorer):
|
|
199
|
+
for arg, value in scoring_args.items():
|
|
200
|
+
if isinstance(value, _Default):
|
|
201
|
+
continue
|
|
202
|
+
raise ValueError(
|
|
203
203
|
"You passed a explicit Scorer object for the scoring parameter. In this case, we expect "
|
|
204
204
|
f"multiprocessing parameters ({list(scoring_args.keys())}) to be configured directly on the "
|
|
205
205
|
f"Scorer instance. However, you specified {arg}={value} by passing it directly "
|
|
206
206
|
"to the validate function. Instead, pass multiprocessing parameters to your Scorer during "
|
|
207
207
|
"initialization or by using `set_params`."
|
|
208
208
|
)
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
scoring.set_params(**scoring_args)
|
|
209
|
+
scoring = _validate_scorer(scoring)
|
|
210
|
+
else:
|
|
211
|
+
scoring = _validate_scorer(scoring)
|
|
212
|
+
scoring.set_params(
|
|
213
|
+
**{arg: value.get_value() if isinstance(value, _Default) else value for arg, value in scoring_args.items()}
|
|
214
|
+
)
|
|
217
215
|
|
|
218
216
|
results = _score(
|
|
219
217
|
pipeline.clone(),
|
|
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
|