scipy-doctest 1.3__py3-none-any.whl → 1.4__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.
- scipy_doctest/__init__.py +1 -1
- scipy_doctest/impl.py +28 -4
- scipy_doctest/tests/failure_cases.py +8 -0
- scipy_doctest/tests/local_file_cases.py +1 -1
- scipy_doctest/tests/test_pytest_configuration.py +1 -3
- scipy_doctest/tests/test_skipmarkers.py +18 -1
- scipy_doctest/tests/test_testmod.py +10 -0
- {scipy_doctest-1.3.dist-info → scipy_doctest-1.4.dist-info}/METADATA +16 -9
- {scipy_doctest-1.3.dist-info → scipy_doctest-1.4.dist-info}/RECORD +12 -12
- {scipy_doctest-1.3.dist-info → scipy_doctest-1.4.dist-info}/LICENSE +0 -0
- {scipy_doctest-1.3.dist-info → scipy_doctest-1.4.dist-info}/WHEEL +0 -0
- {scipy_doctest-1.3.dist-info → scipy_doctest-1.4.dist-info}/entry_points.txt +0 -0
scipy_doctest/__init__.py
CHANGED
scipy_doctest/impl.py
CHANGED
|
@@ -40,6 +40,11 @@ class DTConfig:
|
|
|
40
40
|
rtol : float
|
|
41
41
|
Absolute and relative tolerances to check doctest examples with.
|
|
42
42
|
Specifically, the check is ``np.allclose(want, got, atol=atol, rtol=rtol)``
|
|
43
|
+
strict_check : bool
|
|
44
|
+
Whether to check that dtypes match or rely on the lax definition of
|
|
45
|
+
equality of numpy objects. For instance, `3 == np.float64(3)`, but
|
|
46
|
+
dtypes do not match.
|
|
47
|
+
Default is False.
|
|
43
48
|
optionflags : int
|
|
44
49
|
doctest optionflags
|
|
45
50
|
Default is ``NORMALIZE_WHITESPACE | ELLIPSIS | IGNORE_EXCEPTION_DETAIL``
|
|
@@ -107,6 +112,7 @@ class DTConfig:
|
|
|
107
112
|
rndm_markers=None,
|
|
108
113
|
atol=1e-8,
|
|
109
114
|
rtol=1e-2,
|
|
115
|
+
strict_check=False,
|
|
110
116
|
# DTRunner configuration
|
|
111
117
|
optionflags=None,
|
|
112
118
|
# DTFinder/DTParser configuration
|
|
@@ -161,8 +167,8 @@ class DTConfig:
|
|
|
161
167
|
'#random', '#Random',
|
|
162
168
|
"# may vary"}
|
|
163
169
|
self.rndm_markers = rndm_markers
|
|
164
|
-
|
|
165
170
|
self.atol, self.rtol = atol, rtol
|
|
171
|
+
self.strict_check = strict_check
|
|
166
172
|
|
|
167
173
|
### DTRunner configuration ###
|
|
168
174
|
|
|
@@ -363,23 +369,35 @@ class DTChecker(doctest.OutputChecker):
|
|
|
363
369
|
return False
|
|
364
370
|
|
|
365
371
|
# ... and defer to numpy
|
|
372
|
+
strict = self.config.strict_check
|
|
366
373
|
try:
|
|
367
|
-
return self._do_check(a_want, a_got)
|
|
374
|
+
return self._do_check(a_want, a_got, strict)
|
|
368
375
|
except Exception:
|
|
369
376
|
# heterog tuple, eg (1, np.array([1., 2.]))
|
|
370
377
|
try:
|
|
371
|
-
return all(
|
|
378
|
+
return all(
|
|
379
|
+
self._do_check(w, g, strict) for w, g in zip_longest(a_want, a_got)
|
|
380
|
+
)
|
|
372
381
|
except (TypeError, ValueError):
|
|
373
382
|
return False
|
|
374
383
|
|
|
375
|
-
def _do_check(self, want, got):
|
|
384
|
+
def _do_check(self, want, got, strict_check):
|
|
376
385
|
# This should be done exactly as written to correctly handle all of
|
|
377
386
|
# numpy-comparable objects, strings, and heterogeneous tuples
|
|
387
|
+
|
|
388
|
+
# NB: 3 == np.float64(3.0) but dtypes differ
|
|
389
|
+
if strict_check:
|
|
390
|
+
want_dtype = np.asarray(want).dtype
|
|
391
|
+
got_dtype = np.asarray(got).dtype
|
|
392
|
+
if want_dtype != got_dtype:
|
|
393
|
+
return False
|
|
394
|
+
|
|
378
395
|
try:
|
|
379
396
|
if want == got:
|
|
380
397
|
return True
|
|
381
398
|
except Exception:
|
|
382
399
|
pass
|
|
400
|
+
|
|
383
401
|
with warnings.catch_warnings():
|
|
384
402
|
# NumPy's ragged array deprecation of np.array([1, (2, 3)])
|
|
385
403
|
warnings.simplefilter('ignore', VisibleDeprecationWarning)
|
|
@@ -514,6 +532,7 @@ class DTParser(doctest.DocTestParser):
|
|
|
514
532
|
"""
|
|
515
533
|
stopwords = self.config.stopwords
|
|
516
534
|
pseudocode = self.config.pseudocode
|
|
535
|
+
rndm_markers = self.config.rndm_markers
|
|
517
536
|
|
|
518
537
|
SKIP = doctest.OPTIONFLAGS_BY_NAME['SKIP']
|
|
519
538
|
keep_skipping_this_block = False
|
|
@@ -537,6 +556,11 @@ class DTParser(doctest.DocTestParser):
|
|
|
537
556
|
# NB: Could have just skipped it via `continue`.
|
|
538
557
|
example.options[SKIP] = True
|
|
539
558
|
|
|
559
|
+
if any(word in example.source for word in rndm_markers):
|
|
560
|
+
# Found a `# may vary`. Do not check the output (but do check
|
|
561
|
+
# that the source is valid python).
|
|
562
|
+
example.want += " # _ignore\n"
|
|
563
|
+
|
|
540
564
|
if any(word in example.source for word in stopwords):
|
|
541
565
|
# Found a stopword. Do not check the output (but do check
|
|
542
566
|
# that the source is valid python).
|
|
@@ -3,7 +3,7 @@ from ..conftest import dt_config
|
|
|
3
3
|
# Specify local files required by doctests
|
|
4
4
|
dt_config.local_resources = {
|
|
5
5
|
'scipy_doctest.tests.local_file_cases.local_files': ['local_file.txt'],
|
|
6
|
-
'scipy_doctest.local_file_cases.sio': ['octave_a.mat']
|
|
6
|
+
'scipy_doctest.tests.local_file_cases.sio': ['octave_a.mat']
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
|
|
@@ -49,11 +49,9 @@ def test_stopword_cases(pytester):
|
|
|
49
49
|
assert result.ret == pytest.ExitCode.OK
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
@pytest.mark.xfail(reason="XXX: passes locally, fails on CI")
|
|
53
52
|
@pytest.mark.skipif(not HAVE_SCIPY, reason='need scipy')
|
|
54
53
|
def test_local_file_cases(pytester):
|
|
55
|
-
"""Test that local files are found for use in doctests.
|
|
56
|
-
"""
|
|
54
|
+
"""Test that local files are found for use in doctests."""
|
|
57
55
|
path_str = local_file_cases.__file__
|
|
58
56
|
python_file = Path(path_str)
|
|
59
57
|
result = pytester.inline_run(python_file, "--doctest-modules")
|
|
@@ -161,8 +161,25 @@ class TestMayVary:
|
|
|
161
161
|
filename='none', lineno=0)
|
|
162
162
|
|
|
163
163
|
runner = DebugDTRunner()
|
|
164
|
-
|
|
164
|
+
runner.run(test)
|
|
165
|
+
|
|
166
|
+
# one example tried, of which zero failed
|
|
167
|
+
assert runner.get_history() == {'may_vary_source': (0, 1)}
|
|
168
|
+
|
|
169
|
+
def test_may_vary_syntax_error(self):
|
|
170
|
+
# `# may vary` markers do not mask syntax errors, unlike `# doctest: +SKIP`
|
|
171
|
+
string = ">>> 1 += 2 # may vary\n"
|
|
172
|
+
string += "42\n"
|
|
173
|
+
|
|
174
|
+
parser = DTParser()
|
|
175
|
+
test = parser.get_doctest(string, globs={},
|
|
176
|
+
name='may_vary_err',
|
|
177
|
+
filename='none', lineno=0)
|
|
178
|
+
|
|
179
|
+
runner = DebugDTRunner()
|
|
180
|
+
with pytest.raises(Exception) as exc_info:
|
|
165
181
|
runner.run(test)
|
|
182
|
+
assert exc_info.type == doctest.UnexpectedException
|
|
166
183
|
|
|
167
184
|
|
|
168
185
|
string='''\
|
|
@@ -117,6 +117,16 @@ def test_tuple_and_list():
|
|
|
117
117
|
assert res.failed == 2
|
|
118
118
|
|
|
119
119
|
|
|
120
|
+
@pytest.mark.parametrize('strict, num_fails', [(True, 1), (False, 0)])
|
|
121
|
+
class TestStrictDType:
|
|
122
|
+
def test_np_fix(self, strict, num_fails):
|
|
123
|
+
config = DTConfig(strict_check=strict)
|
|
124
|
+
res, _ = _testmod(failure_cases,
|
|
125
|
+
strategy=[failure_cases.dtype_mismatch],
|
|
126
|
+
config=config)
|
|
127
|
+
assert res.failed == num_fails
|
|
128
|
+
|
|
129
|
+
|
|
120
130
|
class TestLocalFiles:
|
|
121
131
|
def test_local_files(self):
|
|
122
132
|
# A doctest tries to open a local file. Test that it works
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: scipy_doctest
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4
|
|
4
4
|
Summary: Configurable, whitespace-insensitive, floating-point-aware doctest helpers.
|
|
5
5
|
Maintainer-email: SciPy developers <scipy-dev@python.org>
|
|
6
6
|
Requires-Python: >=3.8
|
|
@@ -67,8 +67,8 @@ Its main features are
|
|
|
67
67
|
>>> np.random.randint(100)
|
|
68
68
|
42 # may vary
|
|
69
69
|
```
|
|
70
|
-
Note that the markers (by default, `"# may vary"` and `"# random"`)
|
|
71
|
-
to an example's output,
|
|
70
|
+
Note that the markers (by default, `"# may vary"` and `"# random"`) can be applied
|
|
71
|
+
to either an example's output, or its source.
|
|
72
72
|
|
|
73
73
|
Also note a difference with respect to the standard `# doctest: +SKIP`: the latter
|
|
74
74
|
skips the example entirely, while these additional markers only skip checking
|
|
@@ -291,12 +291,6 @@ and [a doctest example](https://github.com/scipy/scipy_doctest/blob/main/scipy_d
|
|
|
291
291
|
for more details.
|
|
292
292
|
|
|
293
293
|
|
|
294
|
-
### The SciPy Doctest Pytest Plugin
|
|
295
|
-
|
|
296
|
-
The pytest plugin enables the use of `scipy_doctest` tools to perform doctests.
|
|
297
|
-
|
|
298
|
-
Follow the given instructions to utilize the pytest plugin for doctesting.
|
|
299
|
-
|
|
300
294
|
### NumPy and SciPy wrappers
|
|
301
295
|
|
|
302
296
|
|
|
@@ -382,6 +376,19 @@ leads to
|
|
|
382
376
|
- `scipy.linalg.det`, collected from `scipy/linalg/__init__.py`, is public.
|
|
383
377
|
|
|
384
378
|
|
|
379
|
+
- *`pytest`'s assertion rewriting*
|
|
380
|
+
|
|
381
|
+
In some rare cases you may need to either explicitly register the `scipy_doctest`
|
|
382
|
+
package with the `pytest` assertion rewriting machinery, or ask it to avoid rewriting
|
|
383
|
+
completely, via `pytest --assert=plain`.
|
|
384
|
+
See [the `pytest documentation`](https://docs.pytest.org/en/7.1.x/how-to/assert.html)
|
|
385
|
+
for more details.
|
|
386
|
+
|
|
387
|
+
In general, rewriting assertions is not very useful for doctests, as the
|
|
388
|
+
output on error is fixed by the doctest machinery anyway. Therefore, we believe
|
|
389
|
+
adding `--assert=plain` is reasonable.
|
|
390
|
+
|
|
391
|
+
|
|
385
392
|
## Prior art and related work
|
|
386
393
|
|
|
387
394
|
- `pytest` provides some limited floating-point aware `NumericLiteralChecker`.
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
scipy_doctest/__init__.py,sha256=
|
|
1
|
+
scipy_doctest/__init__.py,sha256=IyY6n7Dj46DJxtsOi2DOMvw4NDmIWOJSIT9Mx97Szvk,649
|
|
2
2
|
scipy_doctest/__main__.py,sha256=H8jTO13GlOLzexbgu7lHMJW1y3_NhLOSArARFZ5WS7o,90
|
|
3
3
|
scipy_doctest/conftest.py,sha256=5vZxzuH042urYIToiKWANDJHQPoGkfQI-ppQ_cuHgM0,53
|
|
4
4
|
scipy_doctest/frontend.py,sha256=7Vz9VIRmzdkmwPD1OtI9sJSxCXIF7jmSxXyt6asjaI0,18628
|
|
5
|
-
scipy_doctest/impl.py,sha256=
|
|
5
|
+
scipy_doctest/impl.py,sha256=tYJnNBuBBwdrnxyk8iy07qucTQGa5TzLqGEuFNNNzNU,22980
|
|
6
6
|
scipy_doctest/plugin.py,sha256=DzTPBCDIre5b2e8JLiTGw7d9zhCP9hYqXcxeKpFTtys,12900
|
|
7
7
|
scipy_doctest/util.py,sha256=R-pS9FSL5hQNmOA0nhRDLOL1riFVAoK-OhG70ilaKhw,8057
|
|
8
8
|
scipy_doctest/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
scipy_doctest/tests/failure_cases.py,sha256=
|
|
9
|
+
scipy_doctest/tests/failure_cases.py,sha256=ReSRSugjKDNoWO5M4h-vwCbX_7BwkktlwEjFiGWI3F4,732
|
|
10
10
|
scipy_doctest/tests/failure_cases_2.py,sha256=gupqwSICvzurGIiKVNJRJX9jkmtFR7_Rf3snWU-4Nac,784
|
|
11
11
|
scipy_doctest/tests/finder_cases.py,sha256=s4sq5HZ7m5mXEi1N8dbkgCRY6AxEGcirFRYhEyEG7rw,872
|
|
12
12
|
scipy_doctest/tests/local_file.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
scipy_doctest/tests/local_file_cases.py,sha256=
|
|
13
|
+
scipy_doctest/tests/local_file_cases.py,sha256=xQeD809EoLxY-QIb0X7ZPl6Ecyme3zjnf95AHJ_8gp0,914
|
|
14
14
|
scipy_doctest/tests/module_cases.py,sha256=Ui3rjM0a08rQE28w2Wl_pMs4aWshOL_MkrIVm49KXs0,5470
|
|
15
15
|
scipy_doctest/tests/octave_a.mat,sha256=lOfXBSOdMG7_kruTnOHjixXkPy3zSUt10A1FSVjfngI,288
|
|
16
16
|
scipy_doctest/tests/scipy_ndimage_tutorial_clone.rst,sha256=uCtH99RQM0hvDK2_5lgBO2hqtMUOUQhPKxWn4zwHjSs,81594
|
|
17
17
|
scipy_doctest/tests/stopwords_cases.py,sha256=OEZkoFW3B9nHUCG_5adSkLI91avSwNjw-NeUS0D6Yz0,156
|
|
18
18
|
scipy_doctest/tests/test_finder.py,sha256=9bBa3OvB8aTPixMkAFAPlCul7Bm7J95GKri0npOMp9M,6136
|
|
19
19
|
scipy_doctest/tests/test_parser.py,sha256=cmK5kXqTWPUdSVor4bPu6yoikIukDIkVXjIjk1TTPI8,925
|
|
20
|
-
scipy_doctest/tests/test_pytest_configuration.py,sha256=
|
|
20
|
+
scipy_doctest/tests/test_pytest_configuration.py,sha256=2aesrRyHFdMcRMjARXJ5g8nMtaYC0gb_48Mh8U58RzE,2573
|
|
21
21
|
scipy_doctest/tests/test_runner.py,sha256=qP4u8ngbUK946HhMM6Py70hi0W0DcZGcCN258phhM7g,2936
|
|
22
|
-
scipy_doctest/tests/test_skipmarkers.py,sha256=
|
|
22
|
+
scipy_doctest/tests/test_skipmarkers.py,sha256=C5U8BKF3Ti-nPWekt2yK6a3j3Tcg_pq-Z5IuiR-F9eU,7835
|
|
23
23
|
scipy_doctest/tests/test_testfile.py,sha256=66ZHUpEGGg8MfQT8EKSZ8Zx5pV55gP__TZejGMYwBHA,733
|
|
24
|
-
scipy_doctest/tests/test_testmod.py,sha256=
|
|
25
|
-
scipy_doctest-1.
|
|
26
|
-
scipy_doctest-1.
|
|
27
|
-
scipy_doctest-1.
|
|
28
|
-
scipy_doctest-1.
|
|
29
|
-
scipy_doctest-1.
|
|
24
|
+
scipy_doctest/tests/test_testmod.py,sha256=PoOI0o2_dXjWDmDkUUKqcJiyZvh46YpjlmMxyW6PXyI,5874
|
|
25
|
+
scipy_doctest-1.4.dist-info/entry_points.txt,sha256=dFda3z6PjFL7pEWokv_QmoLwE8X1HETCY1H60xopQ-s,47
|
|
26
|
+
scipy_doctest-1.4.dist-info/LICENSE,sha256=xH5PVX8bm8e1JxkmJ-e5FsZsOa7FsNOMfepmCvMoR9g,1523
|
|
27
|
+
scipy_doctest-1.4.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
|
|
28
|
+
scipy_doctest-1.4.dist-info/METADATA,sha256=y5qj7KF7WLeVmI37bLi0v0MCUzWJY-z1c8UmaDyGhnM,14867
|
|
29
|
+
scipy_doctest-1.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|