scipy-doctest 1.3__tar.gz → 1.4__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.
Files changed (28) hide show
  1. {scipy_doctest-1.3 → scipy_doctest-1.4}/PKG-INFO +16 -9
  2. {scipy_doctest-1.3 → scipy_doctest-1.4}/README.md +15 -8
  3. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/__init__.py +1 -1
  4. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/impl.py +28 -4
  5. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/failure_cases.py +8 -0
  6. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/local_file_cases.py +1 -1
  7. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/test_pytest_configuration.py +1 -3
  8. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/test_skipmarkers.py +18 -1
  9. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/test_testmod.py +10 -0
  10. {scipy_doctest-1.3 → scipy_doctest-1.4}/LICENSE +0 -0
  11. {scipy_doctest-1.3 → scipy_doctest-1.4}/pyproject.toml +0 -0
  12. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/__main__.py +0 -0
  13. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/conftest.py +0 -0
  14. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/frontend.py +0 -0
  15. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/plugin.py +0 -0
  16. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/__init__.py +0 -0
  17. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/failure_cases_2.py +0 -0
  18. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/finder_cases.py +0 -0
  19. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/local_file.txt +0 -0
  20. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/module_cases.py +0 -0
  21. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/octave_a.mat +0 -0
  22. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/scipy_ndimage_tutorial_clone.rst +0 -0
  23. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/stopwords_cases.py +0 -0
  24. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/test_finder.py +0 -0
  25. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/test_parser.py +0 -0
  26. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/test_runner.py +0 -0
  27. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/tests/test_testfile.py +0 -0
  28. {scipy_doctest-1.3 → scipy_doctest-1.4}/scipy_doctest/util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scipy_doctest
3
- Version: 1.3
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"`) are applied
71
- to an example's output, not its source.
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`.
@@ -48,8 +48,8 @@ Its main features are
48
48
  >>> np.random.randint(100)
49
49
  42 # may vary
50
50
  ```
51
- Note that the markers (by default, `"# may vary"` and `"# random"`) are applied
52
- to an example's output, not its source.
51
+ Note that the markers (by default, `"# may vary"` and `"# random"`) can be applied
52
+ to either an example's output, or its source.
53
53
 
54
54
  Also note a difference with respect to the standard `# doctest: +SKIP`: the latter
55
55
  skips the example entirely, while these additional markers only skip checking
@@ -272,12 +272,6 @@ and [a doctest example](https://github.com/scipy/scipy_doctest/blob/main/scipy_d
272
272
  for more details.
273
273
 
274
274
 
275
- ### The SciPy Doctest Pytest Plugin
276
-
277
- The pytest plugin enables the use of `scipy_doctest` tools to perform doctests.
278
-
279
- Follow the given instructions to utilize the pytest plugin for doctesting.
280
-
281
275
  ### NumPy and SciPy wrappers
282
276
 
283
277
 
@@ -363,6 +357,19 @@ leads to
363
357
  - `scipy.linalg.det`, collected from `scipy/linalg/__init__.py`, is public.
364
358
 
365
359
 
360
+ - *`pytest`'s assertion rewriting*
361
+
362
+ In some rare cases you may need to either explicitly register the `scipy_doctest`
363
+ package with the `pytest` assertion rewriting machinery, or ask it to avoid rewriting
364
+ completely, via `pytest --assert=plain`.
365
+ See [the `pytest documentation`](https://docs.pytest.org/en/7.1.x/how-to/assert.html)
366
+ for more details.
367
+
368
+ In general, rewriting assertions is not very useful for doctests, as the
369
+ output on error is fixed by the doctest machinery anyway. Therefore, we believe
370
+ adding `--assert=plain` is reasonable.
371
+
372
+
366
373
  ## Prior art and related work
367
374
 
368
375
  - `pytest` provides some limited floating-point aware `NumericLiteralChecker`.
@@ -3,7 +3,7 @@ Configurable, whitespace-insensitive, floating-point-aware doctest helpers.
3
3
  """
4
4
 
5
5
 
6
- __version__ = "1.3"
6
+ __version__ = "1.4"
7
7
 
8
8
  try:
9
9
  # register internal modules with pytest; obscure errors galore otherwise
@@ -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(self._do_check(w, g) for w, g in zip_longest(a_want, a_got))
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).
@@ -45,3 +45,11 @@ def tuple_and_list_2():
45
45
  >>> (0, 1, 2)
46
46
  [0, 1, 2]
47
47
  """
48
+
49
+
50
+ def dtype_mismatch():
51
+ """
52
+ >>> import numpy as np
53
+ >>> 3.0
54
+ 3
55
+ """
@@ -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
- with pytest.raises(doctest.DocTestFailure):
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
File without changes
File without changes