scipy-doctest 1.1__tar.gz → 1.2.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.
Files changed (29) hide show
  1. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/PKG-INFO +32 -24
  2. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/README.md +31 -23
  3. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/__init__.py +1 -1
  4. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/frontend.py +5 -2
  5. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/impl.py +35 -3
  6. scipy_doctest-1.2.0/scipy_doctest/tests/failure_cases.py +47 -0
  7. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/module_cases.py +42 -0
  8. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/test_testmod.py +18 -0
  9. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/util.py +2 -2
  10. scipy_doctest-1.1/scipy_doctest/tests/failure_cases.py +0 -17
  11. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/LICENSE +0 -0
  12. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/pyproject.toml +0 -0
  13. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/__main__.py +0 -0
  14. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/conftest.py +0 -0
  15. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/plugin.py +0 -0
  16. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/__init__.py +0 -0
  17. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/failure_cases_2.py +0 -0
  18. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/finder_cases.py +0 -0
  19. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/local_file.txt +0 -0
  20. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/local_file_cases.py +0 -0
  21. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/octave_a.mat +0 -0
  22. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/scipy_ndimage_tutorial_clone.rst +0 -0
  23. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/stopwords_cases.py +0 -0
  24. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/test_finder.py +0 -0
  25. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/test_parser.py +0 -0
  26. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/test_pytest_configuration.py +0 -0
  27. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/test_runner.py +0 -0
  28. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/test_skipmarkers.py +0 -0
  29. {scipy_doctest-1.1 → scipy_doctest-1.2.0}/scipy_doctest/tests/test_testfile.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scipy_doctest
3
- Version: 1.1
3
+ Version: 1.2.0
4
4
  Summary: Doctests on steroids.
5
5
  Maintainer-email: SciPy developers <scipy-dev@python.org>
6
6
  Requires-Python: >=3.8
@@ -19,6 +19,15 @@ Provides-Extra: test
19
19
 
20
20
  # Floating-point aware, human readable, numpy-compatible doctesting.
21
21
 
22
+ ## TL;DR
23
+
24
+ This project extends the standard library `doctest` module to allow flexibility
25
+ and easy customization of finding, parsing and checking code examples in
26
+ documentation.
27
+
28
+ Can be used either as drop-in `doctest` replacement or through the `pytest`
29
+ integration. Uses a floating-point aware doctest checker by default.
30
+
22
31
  ## Motivation and scope
23
32
 
24
33
  Having examples in the documentation is great. Having wrong examples in the
@@ -92,7 +101,7 @@ the output. Thus the example source needs to be valid python code still.
92
101
 
93
102
  ```
94
103
  $ pip install -e .
95
- $ pytest --pyargs scpdt
104
+ $ pytest --pyargs scipy_doctest
96
105
  ```
97
106
 
98
107
  ## Usage
@@ -110,7 +119,7 @@ For example,
110
119
 
111
120
  ```
112
121
  >>> from scipy import linalg
113
- >>> from scpdt import testmod
122
+ >>> from scipy_doctest import testmod
114
123
  >>> res, hist = testmod(linalg, strategy='api')
115
124
  >>> res
116
125
  TestResults(failed=0, attempted=764)
@@ -126,7 +135,7 @@ the behavior of the eponymous functions of the `doctest` module).
126
135
 
127
136
  There is a basic CLI, which also mimics that of the `doctest` module:
128
137
  ```
129
- $ python -m scpdt foo.py
138
+ $ python -m scipy_doctest foo.py
130
139
  ```
131
140
 
132
141
  Note that, just like `$ python -m doctest foo.py`, this may
@@ -134,7 +143,7 @@ fail if `foo.py` is a part of a package due to package imports.
134
143
 
135
144
  Text files can also be CLI-checked:
136
145
  ```
137
- $ python -m scpdt bar.rst
146
+ $ python -m scipy_doctest bar.rst
138
147
  ```
139
148
 
140
149
 
@@ -158,25 +167,24 @@ passing the instance to `testmod` or constructors of `DT*` objects. Defaults
158
167
  are provided, based on a long-term usage in SciPy.
159
168
 
160
169
 
161
- ### The Scpdt Pytest Plugin
170
+ ### The SciPy Doctest Pytest Plugin
162
171
 
163
- The pytest plugin enables the use of scpdt tools to perform doctests.
172
+ The pytest plugin enables the use of `scipy_doctest` tools to perform doctests.
164
173
 
165
174
  Follow the given instructions to utilize the pytest plugin for doctesting.
166
175
 
167
- ### Running doctests on Scipy
168
- 1. **Install plugin**
176
+ ### Running Doctests on SciPy
169
177
 
170
- Start by installing the pytest plugin via pip:
178
+ 1. **Install plugin**
171
179
 
172
180
  ```bash
173
- pip install git+https://github.com/ev-br/scpdt.git@main
181
+ pip install scipy-doctest
174
182
  ```
175
183
 
176
184
  2. **Configure Your Doctesting Experience**
177
185
 
178
186
  To tailor your doctesting experience, you can utilize an instance of `DTConfig`.
179
- An in-depth explanation is given in the [tailoring your doctesting experience](https://github.com/ev-br/scpdt#tailoring-your-doctesting-experience) section.
187
+ An in-depth explanation is given in the [tailoring your doctesting experience](https://github.com/scipy/scipy_doctest#tailoring-your-doctesting-experience) section.
180
188
 
181
189
  3. **Run Doctests**
182
190
 
@@ -184,13 +192,13 @@ Doctesting is configured to execute on SciPy using the `dev.py` module.
184
192
 
185
193
  To run all doctests, use the following command:
186
194
  ```bash
187
- python dev.py test --doctests
195
+ python dev.py smoke-docs
188
196
  ```
189
197
 
190
198
  To run doctests on specific SciPy modules, e.g: `cluster`, use the following command:
191
199
 
192
200
  ```bash
193
- python dev.py test --doctests -s cluster
201
+ python dev.py smoke-docs -s cluster
194
202
  ```
195
203
 
196
204
  ### Running Doctests on Other Packages/Projects
@@ -200,7 +208,7 @@ If you want to run doctests on packages or projects other than SciPy, follow the
200
208
  1. **Install the plugin**
201
209
 
202
210
  ```bash
203
- pip install git+https://github.com/ev-br/scpdt.git@main
211
+ pip install scipy-doctest
204
212
  ```
205
213
 
206
214
  2. **Register or Load the Plugin**
@@ -212,14 +220,14 @@ To do this, add the following line of code:
212
220
  ```python
213
221
  # In your conftest.py file or test module
214
222
 
215
- pytest_plugins = "scpdt"
223
+ pytest_plugins = "scipy_doctest"
216
224
  ```
217
225
 
218
226
  Check out the [pytest documentation](https://docs.pytest.org/en/stable/how-to/writing_plugins.html#requiring-loading-plugins-in-a-test-module-or-conftest-file) for more information on requiring/loading plugins in a test module or `conftest.py` file.
219
227
 
220
228
  3. **Configure your doctesting experience**
221
229
 
222
- An in-depth explanation is given in the [tailoring your doctesting experience](https://github.com/ev-br/scpdt#tailoring-your-doctesting-experience) section.
230
+ An in-depth explanation is given in the [tailoring your doctesting experience](https://github.com/scipy/scipy_doctest#tailoring-your-doctesting-experience) section.
223
231
 
224
232
  4. **Run doctests**
225
233
 
@@ -242,7 +250,7 @@ $ pytest --pyargs <your-package> --doctest-modules --doctest-collect=api
242
250
 
243
251
  ### Tailoring Your Doctesting Experience
244
252
 
245
- [DTConfig](https://github.com/ev-br/scpdt/blob/671083d65b54111770cee71c9bc790ac652d59ab/scpdt/impl.py#L16) offers a variety of attributes that allow you to fine-tune your doctesting experience.
253
+ [DTConfig](https://github.com/scipy/scipy_doctest/blob/main/scipy_doctest/impl.py#L23) offers a variety of attributes that allow you to fine-tune your doctesting experience.
246
254
 
247
255
  These attributes include:
248
256
  1. **default_namespace (dict):** Defines the namespace in which examples are executed.
@@ -262,7 +270,7 @@ Typically, it is entered for each DocTest (especially in API documentation), ens
262
270
  12. **nameerror_after_exception (bool):** Controls whether subsequent examples in the same test, after one has failed, may raise spurious NameErrors. Set to `True` if you want to observe these errors or if your test is expected to raise NameErrors. The default is `False`.
263
271
 
264
272
  To set any of these attributes, create an instance of `DTConfig` called `dt_config`.
265
- This instance is already set as an [attribute of pytest's `Config` object](https://github.com/ev-br/scpdt/blob/671083d65b54111770cee71c9bc790ac652d59ab/scpdt/plugin.py#L27).
273
+ This instance is already set as an [attribute of pytest's `Config` object](https://github.com/scipy/scipy_doctest/blob/58ff06a837b7bff1dbac6560013fc6fd07952ae2/scipy_doctest/plugin.py#L39).
266
274
 
267
275
  **Example:**
268
276
 
@@ -270,8 +278,8 @@ This instance is already set as an [attribute of pytest's `Config` object](https
270
278
  dt_config = DTConfig()
271
279
  dt_config.stopwords = {'plt.', '.hist', '.show'}
272
280
  dt_config.local_resources = {
273
- 'scpdt.tests.local_file_cases.local_files': ['scpdt/tests/local_file.txt'],
274
- 'scpdt.tests.local_file_cases.sio': ['scpdt/tests/octave_a.mat']
281
+ 'scipy_doctest.tests.local_file_cases.local_files': ['scipy_doctest/tests/local_file.txt'],
282
+ 'scipy_doctest.tests.local_file_cases.sio': ['scipy_doctest/tests/octave_a.mat']
275
283
  }
276
284
  dt_config.skiplist = {
277
285
  'scipy.special.sinc',
@@ -280,9 +288,9 @@ dt_config.skiplist = {
280
288
  }
281
289
  ```
282
290
 
283
- If you don't set these attributes, the [default settings](https://github.com/ev-br/scpdt/blob/671083d65b54111770cee71c9bc790ac652d59ab/scpdt/impl.py#L73) of the attributes are used.
291
+ If you don't set these attributes, the [default settings](https://github.com/scipy/scipy_doctest/blob/58ff06a837b7bff1dbac6560013fc6fd07952ae2/scipy_doctest/impl.py#L94) of the attributes are used.
284
292
 
285
- By following these steps, you will be able to effectively use the Scpdt pytest plugin for doctests in your Python projects.
293
+ By following these steps, you will be able to effectively use the SciPy Doctest pytest plugin for doctests in your Python projects.
286
294
 
287
295
  Happy testing!
288
296
 
@@ -309,7 +317,7 @@ instead of `$ pytest --pyargs scipy`.
309
317
  If push comes to shove, you may try using the magic env variable:
310
318
  ` PY_IGNORE_IMPORTMISMATCH=1 pytest ...`,
311
319
  however the need usually indicates an issue with the package itself.
312
- (see [gh-107](https://github.com/ev-br/scpdt/pull/107) for an example).
320
+ (see [gh-107](https://github.com/scipy/scipy_doctest/pull/107) for an example).
313
321
 
314
322
  - *Optional dependencies are not that optional*
315
323
 
@@ -1,5 +1,14 @@
1
1
  # Floating-point aware, human readable, numpy-compatible doctesting.
2
2
 
3
+ ## TL;DR
4
+
5
+ This project extends the standard library `doctest` module to allow flexibility
6
+ and easy customization of finding, parsing and checking code examples in
7
+ documentation.
8
+
9
+ Can be used either as drop-in `doctest` replacement or through the `pytest`
10
+ integration. Uses a floating-point aware doctest checker by default.
11
+
3
12
  ## Motivation and scope
4
13
 
5
14
  Having examples in the documentation is great. Having wrong examples in the
@@ -73,7 +82,7 @@ the output. Thus the example source needs to be valid python code still.
73
82
 
74
83
  ```
75
84
  $ pip install -e .
76
- $ pytest --pyargs scpdt
85
+ $ pytest --pyargs scipy_doctest
77
86
  ```
78
87
 
79
88
  ## Usage
@@ -91,7 +100,7 @@ For example,
91
100
 
92
101
  ```
93
102
  >>> from scipy import linalg
94
- >>> from scpdt import testmod
103
+ >>> from scipy_doctest import testmod
95
104
  >>> res, hist = testmod(linalg, strategy='api')
96
105
  >>> res
97
106
  TestResults(failed=0, attempted=764)
@@ -107,7 +116,7 @@ the behavior of the eponymous functions of the `doctest` module).
107
116
 
108
117
  There is a basic CLI, which also mimics that of the `doctest` module:
109
118
  ```
110
- $ python -m scpdt foo.py
119
+ $ python -m scipy_doctest foo.py
111
120
  ```
112
121
 
113
122
  Note that, just like `$ python -m doctest foo.py`, this may
@@ -115,7 +124,7 @@ fail if `foo.py` is a part of a package due to package imports.
115
124
 
116
125
  Text files can also be CLI-checked:
117
126
  ```
118
- $ python -m scpdt bar.rst
127
+ $ python -m scipy_doctest bar.rst
119
128
  ```
120
129
 
121
130
 
@@ -139,25 +148,24 @@ passing the instance to `testmod` or constructors of `DT*` objects. Defaults
139
148
  are provided, based on a long-term usage in SciPy.
140
149
 
141
150
 
142
- ### The Scpdt Pytest Plugin
151
+ ### The SciPy Doctest Pytest Plugin
143
152
 
144
- The pytest plugin enables the use of scpdt tools to perform doctests.
153
+ The pytest plugin enables the use of `scipy_doctest` tools to perform doctests.
145
154
 
146
155
  Follow the given instructions to utilize the pytest plugin for doctesting.
147
156
 
148
- ### Running doctests on Scipy
149
- 1. **Install plugin**
157
+ ### Running Doctests on SciPy
150
158
 
151
- Start by installing the pytest plugin via pip:
159
+ 1. **Install plugin**
152
160
 
153
161
  ```bash
154
- pip install git+https://github.com/ev-br/scpdt.git@main
162
+ pip install scipy-doctest
155
163
  ```
156
164
 
157
165
  2. **Configure Your Doctesting Experience**
158
166
 
159
167
  To tailor your doctesting experience, you can utilize an instance of `DTConfig`.
160
- An in-depth explanation is given in the [tailoring your doctesting experience](https://github.com/ev-br/scpdt#tailoring-your-doctesting-experience) section.
168
+ An in-depth explanation is given in the [tailoring your doctesting experience](https://github.com/scipy/scipy_doctest#tailoring-your-doctesting-experience) section.
161
169
 
162
170
  3. **Run Doctests**
163
171
 
@@ -165,13 +173,13 @@ Doctesting is configured to execute on SciPy using the `dev.py` module.
165
173
 
166
174
  To run all doctests, use the following command:
167
175
  ```bash
168
- python dev.py test --doctests
176
+ python dev.py smoke-docs
169
177
  ```
170
178
 
171
179
  To run doctests on specific SciPy modules, e.g: `cluster`, use the following command:
172
180
 
173
181
  ```bash
174
- python dev.py test --doctests -s cluster
182
+ python dev.py smoke-docs -s cluster
175
183
  ```
176
184
 
177
185
  ### Running Doctests on Other Packages/Projects
@@ -181,7 +189,7 @@ If you want to run doctests on packages or projects other than SciPy, follow the
181
189
  1. **Install the plugin**
182
190
 
183
191
  ```bash
184
- pip install git+https://github.com/ev-br/scpdt.git@main
192
+ pip install scipy-doctest
185
193
  ```
186
194
 
187
195
  2. **Register or Load the Plugin**
@@ -193,14 +201,14 @@ To do this, add the following line of code:
193
201
  ```python
194
202
  # In your conftest.py file or test module
195
203
 
196
- pytest_plugins = "scpdt"
204
+ pytest_plugins = "scipy_doctest"
197
205
  ```
198
206
 
199
207
  Check out the [pytest documentation](https://docs.pytest.org/en/stable/how-to/writing_plugins.html#requiring-loading-plugins-in-a-test-module-or-conftest-file) for more information on requiring/loading plugins in a test module or `conftest.py` file.
200
208
 
201
209
  3. **Configure your doctesting experience**
202
210
 
203
- An in-depth explanation is given in the [tailoring your doctesting experience](https://github.com/ev-br/scpdt#tailoring-your-doctesting-experience) section.
211
+ An in-depth explanation is given in the [tailoring your doctesting experience](https://github.com/scipy/scipy_doctest#tailoring-your-doctesting-experience) section.
204
212
 
205
213
  4. **Run doctests**
206
214
 
@@ -223,7 +231,7 @@ $ pytest --pyargs <your-package> --doctest-modules --doctest-collect=api
223
231
 
224
232
  ### Tailoring Your Doctesting Experience
225
233
 
226
- [DTConfig](https://github.com/ev-br/scpdt/blob/671083d65b54111770cee71c9bc790ac652d59ab/scpdt/impl.py#L16) offers a variety of attributes that allow you to fine-tune your doctesting experience.
234
+ [DTConfig](https://github.com/scipy/scipy_doctest/blob/main/scipy_doctest/impl.py#L23) offers a variety of attributes that allow you to fine-tune your doctesting experience.
227
235
 
228
236
  These attributes include:
229
237
  1. **default_namespace (dict):** Defines the namespace in which examples are executed.
@@ -243,7 +251,7 @@ Typically, it is entered for each DocTest (especially in API documentation), ens
243
251
  12. **nameerror_after_exception (bool):** Controls whether subsequent examples in the same test, after one has failed, may raise spurious NameErrors. Set to `True` if you want to observe these errors or if your test is expected to raise NameErrors. The default is `False`.
244
252
 
245
253
  To set any of these attributes, create an instance of `DTConfig` called `dt_config`.
246
- This instance is already set as an [attribute of pytest's `Config` object](https://github.com/ev-br/scpdt/blob/671083d65b54111770cee71c9bc790ac652d59ab/scpdt/plugin.py#L27).
254
+ This instance is already set as an [attribute of pytest's `Config` object](https://github.com/scipy/scipy_doctest/blob/58ff06a837b7bff1dbac6560013fc6fd07952ae2/scipy_doctest/plugin.py#L39).
247
255
 
248
256
  **Example:**
249
257
 
@@ -251,8 +259,8 @@ This instance is already set as an [attribute of pytest's `Config` object](https
251
259
  dt_config = DTConfig()
252
260
  dt_config.stopwords = {'plt.', '.hist', '.show'}
253
261
  dt_config.local_resources = {
254
- 'scpdt.tests.local_file_cases.local_files': ['scpdt/tests/local_file.txt'],
255
- 'scpdt.tests.local_file_cases.sio': ['scpdt/tests/octave_a.mat']
262
+ 'scipy_doctest.tests.local_file_cases.local_files': ['scipy_doctest/tests/local_file.txt'],
263
+ 'scipy_doctest.tests.local_file_cases.sio': ['scipy_doctest/tests/octave_a.mat']
256
264
  }
257
265
  dt_config.skiplist = {
258
266
  'scipy.special.sinc',
@@ -261,9 +269,9 @@ dt_config.skiplist = {
261
269
  }
262
270
  ```
263
271
 
264
- If you don't set these attributes, the [default settings](https://github.com/ev-br/scpdt/blob/671083d65b54111770cee71c9bc790ac652d59ab/scpdt/impl.py#L73) of the attributes are used.
272
+ If you don't set these attributes, the [default settings](https://github.com/scipy/scipy_doctest/blob/58ff06a837b7bff1dbac6560013fc6fd07952ae2/scipy_doctest/impl.py#L94) of the attributes are used.
265
273
 
266
- By following these steps, you will be able to effectively use the Scpdt pytest plugin for doctests in your Python projects.
274
+ By following these steps, you will be able to effectively use the SciPy Doctest pytest plugin for doctests in your Python projects.
267
275
 
268
276
  Happy testing!
269
277
 
@@ -290,7 +298,7 @@ instead of `$ pytest --pyargs scipy`.
290
298
  If push comes to shove, you may try using the magic env variable:
291
299
  ` PY_IGNORE_IMPORTMISMATCH=1 pytest ...`,
292
300
  however the need usually indicates an issue with the package itself.
293
- (see [gh-107](https://github.com/ev-br/scpdt/pull/107) for an example).
301
+ (see [gh-107](https://github.com/scipy/scipy_doctest/pull/107) for an example).
294
302
 
295
303
  - *Optional dependencies are not that optional*
296
304
 
@@ -5,7 +5,7 @@ Whitespace-insensitive, numpy-aware, floating-point-aware doctest helpers.
5
5
  """
6
6
 
7
7
 
8
- __version__ = "1.1"
8
+ __version__ = "1.2.0"
9
9
 
10
10
  from .impl import DTChecker, DTFinder, DTParser, DTRunner, DebugDTRunner, DTConfig # noqa
11
11
  from .frontend import testmod, testfile, find_doctests, run_docstring_examples # noqa
@@ -70,8 +70,11 @@ def find_doctests(module, strategy=None,
70
70
  return tests
71
71
 
72
72
  if strategy == "api":
73
- (items, names), failures = get_public_objects(module,
74
- skiplist=config.skiplist)
73
+
74
+ with config.user_context_mgr():
75
+ # user_context_mgr may want to e.g. filter warnings on imports?
76
+ (items, names), failures = get_public_objects(module,
77
+ skiplist=config.skiplist)
75
78
  if failures:
76
79
  mesg = "\n".join([_[2] for _ in failures])
77
80
  raise ValueError(mesg)
@@ -2,6 +2,7 @@ import re
2
2
  import warnings
3
3
  import doctest
4
4
  from doctest import NORMALIZE_WHITESPACE, ELLIPSIS, IGNORE_EXCEPTION_DETAIL
5
+ from itertools import zip_longest
5
6
 
6
7
  import numpy as np
7
8
 
@@ -219,6 +220,30 @@ def try_convert_namedtuple(got):
219
220
  return got_again
220
221
 
221
222
 
223
+ def try_convert_printed_array(got):
224
+ """Printed arrays: reinsert commas.
225
+ """
226
+ # a minimal version is `s_got = ", ".join(got[1:-1].split())`
227
+ # but it fails if there's a space after the opening bracket: "[ 0 1 2 ]"
228
+ # For 2D arrays, split into rows, drop spurious entries, then reassemble.
229
+ if not got.startswith('['):
230
+ return got
231
+
232
+ g1 = got[1:-1] # strip outer "[...]"-s
233
+ rows = [x for x in g1.split("[") if x]
234
+ rows2 = [", ".join(row.split()) for row in rows]
235
+
236
+ if got.startswith("[["):
237
+ # was a 2D array, restore the opening brackets in rows; XXX clean up
238
+ rows3 = ["[" + row for row in rows2]
239
+ else:
240
+ rows3 = rows2
241
+
242
+ # add back the outer brackets
243
+ s_got = "[" + ", ".join(rows3) + "]"
244
+ return s_got
245
+
246
+
222
247
  def has_masked(got):
223
248
  return 'masked_array' in got and '--' in got
224
249
 
@@ -280,8 +305,9 @@ class DTChecker(doctest.OutputChecker):
280
305
  cond = (s_want.startswith("[") and s_want.endswith("]") and
281
306
  s_got.startswith("[") and s_got.endswith("]"))
282
307
  if cond:
283
- s_want = ", ".join(s_want[1:-1].split())
284
- s_got = ", ".join(s_got[1:-1].split())
308
+ s_want = try_convert_printed_array(s_want)
309
+ s_got = try_convert_printed_array(s_got)
310
+
285
311
  return self.check_output(s_want, s_got, optionflags)
286
312
 
287
313
  #handle array abbreviation for n-dimensional arrays, n >= 1
@@ -322,13 +348,19 @@ class DTChecker(doctest.OutputChecker):
322
348
  else:
323
349
  return self.check_output(want_again, got_again, optionflags)
324
350
 
351
+ # Validate data type if list or tuple
352
+ is_list_or_tuple = (isinstance(a_want, (list, tuple)) and
353
+ isinstance(a_got, (list, tuple)))
354
+ if is_list_or_tuple and type(a_want) is not type(a_got):
355
+ return False
356
+
325
357
  # ... and defer to numpy
326
358
  try:
327
359
  return self._do_check(a_want, a_got)
328
360
  except Exception:
329
361
  # heterog tuple, eg (1, np.array([1., 2.]))
330
362
  try:
331
- return all(self._do_check(w, g) for w, g in zip(a_want, a_got))
363
+ return all(self._do_check(w, g) for w, g in zip_longest(a_want, a_got))
332
364
  except (TypeError, ValueError):
333
365
  return False
334
366
 
@@ -0,0 +1,47 @@
1
+ __all__ = ['func9', 'func10', 'iterable_length_1', 'iterable_length_2',
2
+ 'tuple_and_list_1', 'tuple_and_list_2']
3
+
4
+
5
+ def func9():
6
+ """
7
+ Wrong output.
8
+ >>> import numpy as np
9
+ >>> np.array([1, 2, 3])
10
+ array([2, 3, 4])
11
+ """
12
+
13
+
14
+ def func10():
15
+ """
16
+ NameError
17
+ >>> import numpy as np
18
+ >>> np.arraY([1, 2, 3])
19
+ """
20
+
21
+
22
+ def iterable_length_1():
23
+ """
24
+ >>> [1, 2, 3]
25
+ [1, 2, 3, 4]
26
+ """
27
+
28
+
29
+ def iterable_length_2():
30
+ """
31
+ >>> [1, 2, 3]
32
+ [1, 2]
33
+ """
34
+
35
+
36
+ def tuple_and_list_1():
37
+ """
38
+ >>> [0, 1, 2]
39
+ (0, 1, 2)
40
+ """
41
+
42
+
43
+ def tuple_and_list_2():
44
+ """
45
+ >>> (0, 1, 2)
46
+ [0, 1, 2]
47
+ """
@@ -44,6 +44,32 @@ def func3():
44
44
  """
45
45
 
46
46
 
47
+ def func_printed_arrays():
48
+ """
49
+ Check various ways handling of printed arrays can go wrong.
50
+
51
+ >>> import numpy as np
52
+ >>> a = np.arange(8).reshape(2, 4) / 3
53
+ >>> print(a) # numpy 1.26.4
54
+ [[0. 0.33333333 0.66666667 1. ]
55
+ [1.33333333 1.66666667 2. 2.33333333]]
56
+
57
+ >>> print(a) # add spaces (older repr?)
58
+ [[ 0. 0.33333333 0.66666667 1. ]
59
+ [ 1.33333333 1.66666667 2. 2.33333333 ]]
60
+
61
+ Also check 1D arrays
62
+ >>> a1 = np.arange(3)
63
+ >>> print(a1)
64
+ [0 1 2]
65
+ >>> print(a1)
66
+ [ 0 1 2]
67
+ >>> print(a1)
68
+ [ 0 1 2 ]
69
+
70
+ """
71
+
72
+
47
73
  def func4():
48
74
  """
49
75
  Test `# may vary` markers : these should not break doctests (but the code
@@ -190,3 +216,19 @@ def test_cmplx_nan():
190
216
  >>> 1j*np.complex128(np.nan)
191
217
  np.complex128(nan+nanj)
192
218
  """
219
+
220
+
221
+ def array_and_list_1():
222
+ """
223
+ >>> import numpy as np
224
+ >>> np.array([1, 2, 3])
225
+ [1, 2, 3]
226
+ """
227
+
228
+
229
+ def array_and_list_2():
230
+ """
231
+ >>> import numpy as np
232
+ >>> [1, 2, 3]
233
+ array([1, 2, 3])
234
+ """
@@ -99,6 +99,24 @@ def test_user_context():
99
99
  config=config)
100
100
 
101
101
 
102
+ def test_wrong_lengths():
103
+ config = DTConfig()
104
+ res, _ = _testmod(failure_cases,
105
+ strategy=[failure_cases.iterable_length_1,
106
+ failure_cases.iterable_length_2],
107
+ config=config)
108
+ assert res.failed == 2
109
+
110
+
111
+ def test_tuple_and_list():
112
+ config = DTConfig()
113
+ res, _ = _testmod(failure_cases,
114
+ strategy=[failure_cases.tuple_and_list_1,
115
+ failure_cases.tuple_and_list_2],
116
+ config=config)
117
+ assert res.failed == 2
118
+
119
+
102
120
  class TestLocalFiles:
103
121
  def test_local_files(self):
104
122
  # A doctest tries to open a local file. Test that it works
@@ -98,7 +98,7 @@ def numpy_rndm_state():
98
98
 
99
99
 
100
100
  @contextmanager
101
- def noop_context_mgr(test):
101
+ def noop_context_mgr(test=None):
102
102
  """Do nothing.
103
103
 
104
104
  This is a stub context manager to serve as a default for
@@ -117,7 +117,7 @@ def np_errstate():
117
117
 
118
118
 
119
119
  @contextmanager
120
- def warnings_errors(test):
120
+ def warnings_errors(test=None):
121
121
  """Temporarily turn all warnings to errors."""
122
122
  with warnings.catch_warnings():
123
123
  warnings.simplefilter('error', Warning)
@@ -1,17 +0,0 @@
1
- __all__ = ['func9', 'func10']
2
-
3
- def func9():
4
- """
5
- Wrong output.
6
- >>> import numpy as np
7
- >>> np.array([1, 2, 3])
8
- array([2, 3, 4])
9
- """
10
-
11
-
12
- def func10():
13
- """
14
- NameError
15
- >>> import numpy as np
16
- >>> np.arraY([1, 2, 3])
17
- """
File without changes