ENH: improve doctest class item discovery to include members
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 77.2k
- Forks
- 35.9k
- PR merge metrics
- PR metrics pending
Description
Feature or enhancement
Proposal:
>>> import numpy as np
>>> import doctest, pprint
>>> finder = doctest.DocTestFinder()
>>> pprint.pprint(finder.find(np.dtype))
[<DocTest dtype from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (11 examples)>,
<DocTest dtype.__bool__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__class_getitem__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (2 examples)>,
<DocTest dtype.__eq__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__ge__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__getitem__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__gt__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__hash__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__le__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__len__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__lt__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__mul__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__ne__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__repr__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__rmul__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.__str__ from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (no examples)>,
<DocTest dtype.newbyteorder from /home/matti/oss/numpy/build-install/usr/lib/python3.11/site-packages/numpy/__init__.py:None (17 examples)>]
But this does not discover many other items in np.dtype.__dict__ since they are members:
>>> pprint.pprint([(v, type(v)) for k, v in np.dtype.__dict__.items() if k not in ('__doc__',) ])
[(<built-in method __new__ of numpy._DTypeMeta object at 0x74f8bcb40920>,
<class 'builtin_function_or_method'>),
(<slot wrapper '__repr__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__hash__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__str__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__lt__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__le__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__eq__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__ne__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__gt__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__ge__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__bool__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__len__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__getitem__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__mul__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<slot wrapper '__rmul__' of 'numpy.dtype' objects>,
<class 'wrapper_descriptor'>),
(<method '__reduce__' of 'numpy.dtype' objects>, <class 'method_descriptor'>),
(<method '__setstate__' of 'numpy.dtype' objects>,
<class 'method_descriptor'>),
(<method 'newbyteorder' of 'numpy.dtype' objects>,
<class 'method_descriptor'>),
(<method '__class_getitem__' of 'numpy.dtype' objects>,
<class 'classmethod_descriptor'>),
(<member 'type' of 'numpy.dtype' objects>, <class 'member_descriptor'>),
(<member 'kind' of 'numpy.dtype' objects>, <class 'member_descriptor'>),
(<member 'char' of 'numpy.dtype' objects>, <class 'member_descriptor'>),
(<member 'num' of 'numpy.dtype' objects>, <class 'member_descriptor'>),
(<member 'byteorder' of 'numpy.dtype' objects>, <class 'member_descriptor'>),
(<member 'itemsize' of 'numpy.dtype' objects>, <class 'member_descriptor'>),
(<member 'alignment' of 'numpy.dtype' objects>, <class 'member_descriptor'>),
(<member 'flags' of 'numpy.dtype' objects>, <class 'member_descriptor'>),
(<attribute 'subdtype' of 'numpy.dtype' objects>, <class 'getset_descriptor'>),
(<attribute 'descr' of 'numpy.dtype' objects>, <class 'getset_descriptor'>),
(<attribute 'str' of 'numpy.dtype' objects>, <class 'getset_descriptor'>),
(<attribute 'name' of 'numpy.dtype' objects>, <class 'getset_descriptor'>),
(<attribute 'base' of 'numpy.dtype' objects>, <class 'getset_descriptor'>),
(<attribute 'shape' of 'numpy.dtype' objects>, <class 'getset_descriptor'>),
(<attribute 'ndim' of 'numpy.dtype' objects>, <class 'getset_descriptor'>),
(<attribute 'isbuiltin' of 'numpy.dtype' objects>,
<class 'getset_descriptor'>),
(<attribute 'isnative' of 'numpy.dtype' objects>, <class 'getset_descriptor'>),
(<attribute 'isalignedstruct' of 'numpy.dtype' objects>,
<class 'getset_descriptor'>),
(<attribute 'fields' of 'numpy.dtype' objects>, <class 'getset_descriptor'>),
(<attribute 'metadata' of 'numpy.dtype' objects>, <class 'getset_descriptor'>),
(<attribute 'names' of 'numpy.dtype' objects>, <class 'getset_descriptor'>),
(<attribute 'hasobject' of 'numpy.dtype' objects>,
<class 'getset_descriptor'>)]
I think the problem is here where only certain kinds of items are checked. Adding inspect.isdatadescriptor() I think would fix this.
Has this already been discussed elsewhere?
No response given
Links to previous discussion of this feature:
numpy/numpy#28002
scipy/scipy_doctest#178
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in Lib/doctest.py around line 1064, where DocTestFinder checks which class items to discover. Compare the current item checks with the proposed inspect.isdatadescriptor() addition and review the linked NumPy and SciPy discussions. Done means doctest discovery includes the relevant class members without breaking existing discovery behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- testing-qa, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100