scipy-doctest 1.1__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.
@@ -0,0 +1,12 @@
1
+ """
2
+ Doctests on steroids.
3
+
4
+ Whitespace-insensitive, numpy-aware, floating-point-aware doctest helpers.
5
+ """
6
+
7
+
8
+ __version__ = "1.1"
9
+
10
+ from .impl import DTChecker, DTFinder, DTParser, DTRunner, DebugDTRunner, DTConfig # noqa
11
+ from .frontend import testmod, testfile, find_doctests, run_docstring_examples # noqa
12
+
@@ -0,0 +1,6 @@
1
+ import sys
2
+
3
+ from .frontend import _main
4
+
5
+ if __name__ == "__main__":
6
+ sys.exit(_main())
@@ -0,0 +1,5 @@
1
+ from .impl import DTConfig
2
+
3
+
4
+ dt_config = DTConfig()
5
+
@@ -0,0 +1,468 @@
1
+ """ Copy-pasting my way through python/cpython/Lib/doctest.py. """
2
+
3
+ import sys
4
+ import os
5
+ import inspect
6
+ import doctest
7
+
8
+ from .impl import DTFinder, DTRunner, DebugDTRunner, DTParser, DTConfig
9
+ from .util import (matplotlib_make_nongui as mpl,
10
+ temp_cwd, np_errstate,
11
+ get_public_objects, _map_verbosity)
12
+
13
+
14
+ def find_doctests(module, strategy=None,
15
+ # doctest parameters. These fall through to the DocTestFinder
16
+ name=None, exclude_empty=True, globs=None, extraglobs=None,
17
+ # our configuration
18
+ config=None):
19
+ """Find doctests in a module.
20
+
21
+ Parameters
22
+ ----------
23
+ m : module
24
+ The base module to look into
25
+ strategy : str or list of objects, optional
26
+ The strategy to use to find doctests.
27
+ If "public", look into public, non-deprecated objects in the module.
28
+ If a list of objects, only look into the docstring of these objects
29
+ If None, use the standard `doctest` behavior.
30
+ Default is None.
31
+ name : str, optional
32
+ The name of the module. Is used to construct the names of DocTest
33
+ objects. Default is the `module.__name__`.
34
+ exclude_empty : bool, optional
35
+ Comes from the stdlib `doctest` module. See Notes.
36
+ Default is True.
37
+ globs : dict, optional
38
+ Comes from the stdlib `doctest` module. See Notes.
39
+ Default is None.
40
+ extraglobs : dict, optional
41
+ Comes from the stdlib `doctest` module. See Notes.
42
+ Default is None.
43
+ config
44
+ A `DTConfig` instance
45
+
46
+ Returns
47
+ -------
48
+ tests : list
49
+ A list of `doctest.DocTest`s that are defined by the module docstring,
50
+ and by its contained objects’ docstrings. The selection is controlled
51
+ by the `strategy` argument.
52
+
53
+ Notes
54
+ -----
55
+ See https://docs.python.org/3/library/doctest.html#doctestfinder-objects
56
+ for details on the `doctest`-inherited parameters (`name`, `globs`,
57
+ `extraglobs`). Note that these are provided mainly for compatibility with
58
+ the stdlib `doctest` and can be left with default values unless you are
59
+ doing something unusual.
60
+
61
+ """
62
+ if config is None:
63
+ config = DTConfig()
64
+
65
+ finder = DTFinder(exclude_empty=exclude_empty, config=config)
66
+
67
+ if strategy is None:
68
+ tests = finder.find(module, name, globs=globs, extraglobs=extraglobs)
69
+ tests = [t for t in tests if t.name not in config.skiplist]
70
+ return tests
71
+
72
+ if strategy == "api":
73
+ (items, names), failures = get_public_objects(module,
74
+ skiplist=config.skiplist)
75
+ if failures:
76
+ mesg = "\n".join([_[2] for _ in failures])
77
+ raise ValueError(mesg)
78
+ items.append(module)
79
+ names.append(module.__name__)
80
+ else:
81
+ # strategy must then be a list of objects to look at
82
+ if not isinstance(strategy, list):
83
+ raise ValueError(f"Expected a list of objects, got {strategy}.")
84
+ items = strategy[:]
85
+ names = [item.__name__ for item in items]
86
+
87
+ # Having collected the list of objects, extract doctests
88
+ tests = []
89
+ for item, name in zip(items, names):
90
+ full_name = module.__name__ + '.' + name
91
+ if inspect.ismodule(item):
92
+ # do not recurse, only inspect the module docstring
93
+ _finder = DTFinder(recurse=False, config=config)
94
+ t = _finder.find(item, name, globs=globs, extraglobs=extraglobs)
95
+ else:
96
+ t = finder.find(item, full_name, globs=globs, extraglobs=extraglobs)
97
+ tests += t
98
+
99
+ # If the skiplist contains methods of objects, their doctests may have been
100
+ # left in the `tests` list. Remove them.
101
+ tests = [t for t in tests if t.name not in config.skiplist]
102
+ return tests
103
+
104
+
105
+ def testmod(m=None, name=None, globs=None, verbose=None,
106
+ report=True, optionflags=None, extraglobs=None,
107
+ raise_on_error=False, exclude_empty=True,
108
+ strategy=None, config=None):
109
+ """Run modified doctesting on a module or on docstrings of a list of objects.
110
+
111
+ This function is an analog of the `testmod` driver from the standard library.
112
+
113
+ Parameters
114
+ ----------
115
+ m : module, optional
116
+ Test examples in docstrings in functions and classes reachable
117
+ from module `m` (or the current module if `m` is not supplied),
118
+ starting with ``m.__doc__``.
119
+ name : str, optional
120
+ Gives the name of the module; by default use ``m.__name__``.
121
+ globs : dict, optional
122
+ A dict to be used as the globals when executing examples; A copy of this
123
+ dict is actually used for each docstring, so that each docstring's
124
+ examples start with a clean slate.
125
+ By default, use `config.default_namespace`.
126
+ report : bool, optional
127
+ Prints a summary at the end when `True`, else prints nothing at the end.
128
+ In verbose mode, the summary is detailed, else very brief (in fact,
129
+ empty if all tests passed)
130
+ Default is True.
131
+ verbose : int
132
+ Control the run verbosity:
133
+ 0 means only report failures,
134
+ 1 means emit object names,
135
+ 2 is the max verbosity from doctest (print all examples/want/got).
136
+ Default is 0.
137
+ optionflags : int, optional
138
+ `doctest` module optionflags for checking examples. See the stdlib
139
+ `doctest` module documentation for details.
140
+ Default is to use `config.optionflags`.
141
+ extraglobs : dict, optional
142
+ Provided for compatibility with `doctest.testmod`. Default is None.
143
+ raise_on_error : bool, optional
144
+ Raise an exception on the first unexpected exception or failure.
145
+ This allows failures to be post-mortem debugged.
146
+ Default is `False`.
147
+ exclude_empty : bool, optional
148
+ Whether to exclude from consideration objects with no docstrings.
149
+ Comes from the stdlib `doctest` module. See Notes.
150
+ Default is True.
151
+ strategy : str or list of objects, optional
152
+ The strategy to use to find doctests.
153
+ If "api", look into public, non-deprecated objects in the module.
154
+ If a list of objects, only look into the docstring of these objects
155
+ If None, use the standard `doctest` behavior.
156
+ Default is None.
157
+ config : a DTConfig instance, optional
158
+ Various configuration options. See the `DTconfig` docstring for details.
159
+
160
+ Returns
161
+ -------
162
+ (result, history)
163
+ `result` is a namedtuple ``TestResult(failed, attempted)``
164
+ `history` is a dict with details of which objects were examined (the
165
+ keys are object names and values are individual objects' ``TestResult``s)
166
+
167
+ Examples
168
+ --------
169
+ >>> from scipy import constants
170
+ >>> from scpdt import testmod
171
+ >>> result, history = testmod(constants, strategy='api')
172
+ >>> result
173
+ TestResults(failed=0, attempted=25)
174
+ >>> len(history)
175
+ 160
176
+
177
+ Notes
178
+ -----
179
+ The signature is made to be (mostly) consistent with `doctest.testmod`.
180
+ For details on the `doctest`-inherited parameters see
181
+ https://docs.python.org/3/library/doctest.html.
182
+ For an overview, see ``help(doctest)``.
183
+
184
+ ** Doctest discovery **
185
+
186
+ The default doctest discovery strategy, `testmod(..., strategy=None)`, is
187
+ inherited from the stdlib `doctest` module with all its limitations.
188
+ For instance, it may have difficulties with complex packages, where the
189
+ implementation is spread across several modules.
190
+
191
+ For complex packages, prefer `strategy='api'`, which works as follows:
192
+ - take the names of public objects from the `__all__` attribute of the package.
193
+ - if `__all__` is not defined, take `dir(module)` and filter out names
194
+ which start with a leading underscore and dunders.
195
+ - filter out deprecated items, i.e. those which raise `DeprecationWarning`.
196
+
197
+ """
198
+ ### mimic `doctest.testmod` initial set-ups
199
+ # If no module was given, then use __main__.
200
+ if m is None:
201
+ m = sys.modules.get('__main__')
202
+
203
+ # Check that we were actually given a module.
204
+ if not inspect.ismodule(m):
205
+ raise TypeError("testmod: module required; %r" % (m,))
206
+
207
+ # If no name was given, then use the module's name.
208
+ if name is None:
209
+ name = m.__name__
210
+
211
+ ### Set up the configuration
212
+ if config is None:
213
+ config = DTConfig()
214
+
215
+ # pull the the namespace to run examples in, also optionflags from `config`
216
+ if globs is None:
217
+ globs = dict(config.default_namespace)
218
+ else:
219
+ globs = globs.copy()
220
+ flags = config.optionflags
221
+
222
+ output = sys.stderr
223
+
224
+ # Fail fast or run all tests
225
+ verbose, dtverbose = _map_verbosity(verbose)
226
+ if raise_on_error:
227
+ runner = DebugDTRunner(verbose=dtverbose, optionflags=flags, config=config)
228
+ else:
229
+ runner = DTRunner(verbose=dtverbose, optionflags=flags, config=config)
230
+
231
+ ### Find, parse, and run all tests in the given module.
232
+ tests = find_doctests(
233
+ m, strategy, name, exclude_empty, globs, extraglobs, config=config
234
+ )
235
+
236
+ for test in tests:
237
+ if verbose == 1:
238
+ output.write(test.name + '\n')
239
+ # restore the errstate/print state after each docstring.
240
+ # Also make MPL backend non-GUI and close the figures.
241
+ # The order of context managers is actually relevant. Consider
242
+ # a user_context_mgr that turns warnings into errors.
243
+ # Additionally, suppose that MPL deprecates something and plt.something
244
+ # starts issuing warngings. Now all of those become errors
245
+ # *unless* the `mpl()` context mgr has a chance to filter them out
246
+ # *before* they become errors in `config.user_context_mgr()`.
247
+ with np_errstate():
248
+ with config.user_context_mgr(test):
249
+ with mpl(), temp_cwd(test, config.local_resources):
250
+ runner.run(test, out=output.write)
251
+ if report:
252
+ runner.summarize()
253
+ return doctest.TestResults(runner.failures, runner.tries), runner.get_history()
254
+
255
+
256
+ def testfile(filename, module_relative=True, name=None, package=None,
257
+ globs=None, verbose=None, report=True, optionflags=None,
258
+ extraglobs=None, raise_on_error=False, parser=None,
259
+ encoding='utf-8', config=None):
260
+ """Test examples in the given file.
261
+
262
+ This function is an analog of the `doctest.testfile` driver from the
263
+ standard library.
264
+
265
+ Parameters
266
+ ----------
267
+ filename : str
268
+ The name of the file to run doctesting on.
269
+ module_relative: bool, optional
270
+ Whether the file name is relative to a module or a package.
271
+ This parameter is similar to the `doctest.testfile` parameter.
272
+ If True, then `filename` speficies a module-relative path (if `package`
273
+ is specified, then its relative to that package).
274
+ If False, then `filename` specifies an absolute path or a path relative
275
+ to the current working directory.
276
+ See `doctest.testfile` documentation for details.
277
+ Default is True.
278
+ name : str, optional
279
+ Give the name of the test; by default use the file basename.
280
+ package : str, optional
281
+ Gives a Python package or the name of a Python package whose directory
282
+ should be used as the base directory for a module relative filename.
283
+ If no package is specified, then the calling module's directory is used
284
+ as the base directory for module relative filenames. It is an error to
285
+ specify "package" if "module_relative" is False.
286
+ See `doctest.testfile` documentation for details.
287
+ Default is to specify no package.
288
+ globs : dict, optional
289
+ A dict to be used as the globals when executing examples;
290
+ By default, use `config.default_namespace`.
291
+ report : bool, optional
292
+ Prints a summary at the end when `True`, else prints nothing at the end.
293
+ In verbose mode, the summary is detailed, else very brief (in fact,
294
+ empty if all tests passed)
295
+ Default is True.
296
+ verbose : int
297
+ Control the run verbosity:
298
+ 0 means only report failures,
299
+ 1 means emit object names,
300
+ 2 is the max verbosity from doctest (print all examples/want/got).
301
+ Default is 0.
302
+ optionflags : int, optional
303
+ `doctest` module optionflags for checking examples. See the stdlib
304
+ `doctest` module documentation for details.
305
+ Default is to use `config.optionflags`.
306
+ extraglobs : dict, optional
307
+ Provided for compatibility with `doctest.testmod`. Default is None.
308
+ raise_on_error : bool, optional
309
+ Raise an exception on the first unexpected exception or failure.
310
+ This allows failures to be post-mortem debugged.
311
+ Default is `False`.
312
+ parser: a DTParser object, optional
313
+ By default, a `DTParser(config)` is used.
314
+ encoding : str, optional
315
+ Encoding to use when converting the `testfile` to unicode.
316
+ Default is 'utf-8'.
317
+ config : a DTConfig instance, optional
318
+ Various configuration options. See the `DTconfig` docstring for details.
319
+
320
+ Returns
321
+ -------
322
+ (result, history)
323
+ `result` is a namedtuple ``TestResult(failed, attempted)``
324
+ `history` is a dict with details of which objects were examined (the
325
+ keys are object names and values are individual objects' ``TestResult``s)
326
+ """
327
+ # initial configuration
328
+ if config is None:
329
+ config = DTConfig()
330
+ if globs is None:
331
+ globs = dict(config.default_namespace)
332
+ else:
333
+ globs = globs.copy()
334
+ if optionflags is None:
335
+ optionflags = config.optionflags
336
+
337
+ ######### mimic `doctest.tesfile` initial set-ups
338
+ # c.f. https://github.com/python/cpython/blob/3.10/Lib/doctest.py#L2064
339
+ if package and not module_relative:
340
+ raise ValueError("Package may only be specified for module-"
341
+ "relative paths.")
342
+
343
+ # Relativize the path
344
+ text, filename = doctest._load_testfile(filename, package, module_relative,
345
+ encoding or "utf-8")
346
+
347
+ # If no name was given, then use the file's name.
348
+ if name is None:
349
+ name = os.path.basename(filename)
350
+
351
+ # Assemble the globals.
352
+ if extraglobs is not None:
353
+ globs.update(extraglobs)
354
+ if '__name__' not in globs:
355
+ globs['__name__'] = '__main__'
356
+ ##### done copy-pasting from doctest.testfile
357
+
358
+ # Fail fast or run all tests
359
+ verbose, dtverbose = _map_verbosity(verbose)
360
+ if raise_on_error:
361
+ runner = DebugDTRunner(
362
+ verbose=dtverbose, optionflags=optionflags, config=config
363
+ )
364
+ else:
365
+ runner = DTRunner(
366
+ verbose=dtverbose, optionflags=optionflags, config=config
367
+ )
368
+
369
+ ### Parse doctest examples out of the input file and run them.
370
+ if parser is None:
371
+ parser = DTParser(config)
372
+ test = parser.get_doctest(text, globs, name, filename, 0)
373
+
374
+ if test.name in config.skiplist:
375
+ # nothing to do, bail out
376
+ return doctest.TestResults(0, 0), runner.get_history()
377
+
378
+ output = sys.stderr
379
+ if verbose == 1:
380
+ output.write(test.name + '\n')
381
+
382
+ # see testmod for discussion of these context managers
383
+ with np_errstate():
384
+ with config.user_context_mgr(test):
385
+ with mpl(), temp_cwd(test, config.local_resources):
386
+ runner.run(test, out=output.write)
387
+ if report:
388
+ runner.summarize()
389
+ return doctest.TestResults(runner.failures, runner.tries), runner.get_history()
390
+
391
+
392
+ def run_docstring_examples(f, globs=None, verbose=False, name='NoName',
393
+ optionflags=None, config=None):
394
+ """Run examples in the docstring of the object `f`.
395
+
396
+ Parameters
397
+ ----------
398
+ f
399
+ Can be a function, a class, a module etc
400
+ globs : dict, optional
401
+ A dict to be used as the globals when executing examples; A copy of this
402
+ dict is actually used for each docstring, so that each docstring's
403
+ examples start with a clean slate.
404
+ By default, use `config.default_namespace`.
405
+ verbose : bool, optional
406
+ Control the verbosity of the report.
407
+ name : str, optional
408
+ The object name.
409
+ optionflags : int, optional
410
+ `doctest` module optionflags for checking examples. See the stdlib
411
+ `doctest` module documentation for details.
412
+ Default is to use `config.optionflags`.
413
+ config : a DTConfig instance, optional
414
+ Various configuration options. See the `DTconfig` docstring for details.
415
+ """
416
+ if config is None:
417
+ config = DTConfig()
418
+ if globs is None:
419
+ globs = dict(config.default_namespace)
420
+ if verbose is None:
421
+ verbose = 0
422
+ if optionflags is None:
423
+ optionflags = config.optionflags
424
+
425
+ m = f.__module__
426
+ import importlib
427
+ module = importlib.import_module(m)
428
+
429
+ return testmod(module, name=name, globs=globs, verbose=verbose,
430
+ optionflags=optionflags, strategy=[f], config=config)
431
+
432
+
433
+ def _main():
434
+ """CLI for `$ python -m scpdt pythonfile.py`, cf `__main__.py`
435
+ """
436
+ import argparse
437
+
438
+ parser = argparse.ArgumentParser(description="doctest runner")
439
+ parser.add_argument('-v', '--verbose', action='count', default=0,
440
+ help='print verbose (`-v`) or very verbose (`-vv`) '
441
+ 'output for all tests')
442
+ parser.add_argument('-x', '--fail-fast', action='store_true',
443
+ help=('stop running tests after first failure'))
444
+ parser.add_argument('file', nargs='+',
445
+ help='file containing the tests to run')
446
+ args = parser.parse_args()
447
+ testfiles = args.file
448
+ verbose = args.verbose
449
+
450
+ for filename in testfiles:
451
+ if filename.endswith(".py"):
452
+ # It is a module -- insert its dir into sys.path and try to
453
+ # import it. If it is part of a package, that possibly
454
+ # won't work because of package imports.
455
+ dirname, filename = os.path.split(filename)
456
+ sys.path.insert(0, dirname)
457
+ m = __import__(filename[:-3])
458
+ del sys.path[0]
459
+ result, _ = testmod(m, verbose=verbose,
460
+ raise_on_error=args.fail_fast)
461
+ else:
462
+ result, _ = testfile(filename, module_relative=False,
463
+ verbose=verbose, raise_on_error=args.fail_fast)
464
+
465
+ if result.failed:
466
+ return 1
467
+ return 0
468
+