-
-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
doctest.testmod(empty_package) raises TypeError in 3.7 (and no errors in 3.6) #80587
Comments
In recent Python, a directory without __init__.py is also a package, and hence can be imported. When this directory/package is empty, and a doctest.testmod() is executed, the behaviour changed from 3.6 to 3.7, which I didn't find in the "what's new" documentation. Minimal example:
>>> import doctest, os
>>> os.mkdir('empty_package')
>>> import empty_package
>>> doctest.testmod(empty_package) Python 3.6.8 on Windows 7 prints Python 3.7.2 on Windows 7 raises below TypeError in doctest
Traceback (most recent call last):
File "bug_empty_package.py", line 4, in <module>
print(doctest.testmod(empty_package))
File "...\Python37\lib\doctest.py", line 1949, in testmod
for test in finder.find(m, name, globs=globs, extraglobs=extraglobs):
File "...\Python37\lib\doctest.py", line 932, in find
self._find(tests, obj, name, module, source_lines, globs, {})
File "...\Python37\lib\doctest.py", line 982, in _find
test = self._get_test(obj, name, module, globs, source_lines)
File "...\Python37\lib\doctest.py", line 1063, in _get_test
if filename[-4:] == ".pyc":
TypeError: 'NoneType' object is not subscriptable |
This might be due to changes introduced in a23d30f where __file__ is set to None. Hence the below returns None but before the commit this used to return an AttributeError and print "missing" . This was not handled in doctest causing error. Adding Barry for confirmation. # foo.py import empty_package
print(getattr(empty_package, '__file__', 'missing')) ➜ cpython git:(2b5937e) ✗ git checkout a23d30f && make -s -j4 > /dev/null There is a unittest with empty package and it's just that doctest.testmod(mod) was not called on the empty package causing this not to be found. A simple patch would be to check for None where None is a valid value for DocTest. Another possible fix would be to have module.__name__ for None but since this is for empty packages I assume there won't be any doctest to parse in DocTest constructor. diff --git a/Lib/doctest.py b/Lib/doctest.py
index 79d91a040c..e97555ed2f 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -1060,7 +1060,7 @@ class DocTestFinder:
filename = None
else:
filename = getattr(module, '__file__', module.__name__)
- if filename[-4:] == ".pyc":
+ if filename and filename[-4:] == ".pyc":
filename = filename[:-1]
return self._parser.get_doctest(docstring, globs, name,
filename, lineno)
diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py
index f1013f2572..b99f2aea2f 100644
--- a/Lib/test/test_doctest.py
+++ b/Lib/test/test_doctest.py
@@ -699,6 +699,7 @@ class TestDocTestFinder(unittest.TestCase):
support.forget(pkg_name)
sys.path.pop()
assert doctest.DocTestFinder().find(mod) == []
+ doctest.testmod(mod) def test_DocTestParser(): r""" Without patch the line doctest.testmod(mod) in unittest fails as below with TypeError and with patch the tests pass $ ./python.exe Lib/test/test_doctest.py
doctest (doctest) ... 66 tests with zero failures
doctest (test.test_doctest) ... 516 tests with zero failures
test_empty_namespace_package (__main__.TestDocTestFinder) ... ERROR ====================================================================== Traceback (most recent call last):
File "Lib/test/test_doctest.py", line 702, in test_empty_namespace_package
doctest.testmod(mod)
File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 1947, in testmod
for test in finder.find(m, name, globs=globs, extraglobs=extraglobs):
File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 932, in find
self._find(tests, obj, name, module, source_lines, globs, {})
File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 982, in _find
test = self._get_test(obj, name, module, globs, source_lines)
File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 1063, in _get_test
if filename[-4:] == ".pyc":
TypeError: 'NoneType' object is not subscriptable Ran 1 test in 0.027s FAILED (errors=1)
Traceback (most recent call last):
File "Lib/test/test_doctest.py", line 3032, in <module>
test_main()
File "Lib/test/test_doctest.py", line 3015, in test_main
support.run_unittest(__name__)
File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/test/support/__init__.py", line 2064, in run_unittest
_run_suite(suite)
File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/test/support/__init__.py", line 1983, in _run_suite
raise TestFailed(err)
test.support.TestFailed: Traceback (most recent call last):
File "Lib/test/test_doctest.py", line 702, in test_empty_namespace_package
doctest.testmod(mod)
File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 1947, in testmod
for test in finder.find(m, name, globs=globs, extraglobs=extraglobs):
File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 932, in find
self._find(tests, obj, name, module, source_lines, globs, {})
File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 982, in _find
test = self._get_test(obj, name, module, globs, source_lines)
File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 1063, in _get_test
if filename[-4:] == ".pyc":
TypeError: 'NoneType' object is not subscriptable |
So this was backported to 3.6 too with but caused similar issues reported in bpo-32872 to be reverted back. |
A subscriptable object is any object that implements the __getitem__ special method (think lists, dictionaries). It is an object that records the operations done to it and it can store them as a "script" which can be replayed. You are trying to subscript an object which you think is a list or dict, but actually is None. NoneType is the type of the None object which represents a lack of value, for example, a function that does not explicitly return a value will return None. 'NoneType' object is not subscriptable is the one thrown by python when you use the square bracket notation object[key] where an object doesn't define the __getitem__ method . You might have noticed that the method sort() that only modify the list have no return value printed – they return the default None. This is a design principle for all mutable data structures in Python. http://net-informations.com/python/err/nonetype.htm |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: