Opened 8 months ago
Last modified 3 months ago
#31626 needs_review defect
ModuleNotFoundError in doctesting src/sage/misc/sageinspect.py
Reported by: | strogdon | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | sage-9.5 |
Component: | doctest framework | Keywords: | |
Cc: | Merged in: | ||
Authors: | Steven Trogdon | Reviewers: | |
Report Upstream: | N/A | Work issues: | |
Branch: | u/strogdon/ModuleNotFound_doctest_sageinspect (Commits, GitHub, GitLab) | Commit: | 926359ed07b1ec49c646e8f25389f183875f5a8e |
Dependencies: | Stopgaps: |
Description (last modified by )
The two main failures are:
File "src/sage/misc/sageinspect.py", line 2102, in sage.misc.sageinspect._sage_getsourcelines_name_with_dot Failed example: cython(''' class A: def __init__(self): "some init doc" pass class B: "some class doc" class A(A): pass ''') Exception raised: Traceback (most recent call last): File "/local/sage-git/sage/local/lib/python3.9/site-packages/sage/doctest/forker.py", line 714, in _run self.compile_and_execute(example, compiler, test.globs) File "/local/sage-git/sage/local/lib/python3.9/site-packages/sage/doctest/forker.py", line 1133, in compile_and_execute exec(compiled, globs) File "<doctest sage.misc.sageinspect._sage_getsourcelines_name_with_dot[3]>", line 1, in <module> cython(''' File "sage/misc/lazy_import.pyx", line 360, in sage.misc.lazy_import.LazyImport.__call__ (build/cythonized/sage/misc/lazy_import.c:4032) return self.get_object()(*args, **kwds) File "/local/sage-git/sage/local/lib/python3.9/site-packages/sage/misc/cython.py", line 659, in cython_compile return cython_import_all(tmpfile, get_globals(), **kwds) File "/local/sage-git/sage/local/lib/python3.9/site-packages/sage/misc/cython.py", line 549, in cython_import_all m = cython_import(filename, **kwds) File "/local/sage-git/sage/local/lib/python3.9/site-packages/sage/misc/cython.py", line 529, in cython_import return builtins.__import__(name) ModuleNotFoundError: No module named '_home_steven__sage_temp_hp_probook_2359_tmp_isl9jpcz_pyx_0'
and
File "src/sage/misc/sageinspect.py", line 2251, in sage.misc.sageinspect.sage_getsourcelines Failed example: cython('''cpdef test_funct(x,y): return''') Exception raised: Traceback (most recent call last): File "/local/sage-git/sage/local/lib/python3.9/site-packages/sage/doctest/forker.py", line 714, in _run self.compile_and_execute(example, compiler, test.globs) File "/local/sage-git/sage/local/lib/python3.9/site-packages/sage/doctest/forker.py", line 1133, in compile_and_execute exec(compiled, globs) File "<doctest sage.misc.sageinspect.sage_getsourcelines[6]>", line 1, in <module> cython('''cpdef test_funct(x,y): return''') File "sage/misc/lazy_import.pyx", line 360, in sage.misc.lazy_import.LazyImport.__call__ (build/cythonized/sage/misc/lazy_import.c:4032) return self.get_object()(*args, **kwds) File "/local/sage-git/sage/local/lib/python3.9/site-packages/sage/misc/cython.py", line 659, in cython_compile return cython_import_all(tmpfile, get_globals(), **kwds) File "/local/sage-git/sage/local/lib/python3.9/site-packages/sage/misc/cython.py", line 549, in cython_import_all m = cython_import(filename, **kwds) File "/local/sage-git/sage/local/lib/python3.9/site-packages/sage/misc/cython.py", line 529, in cython_import return builtins.__import__(name) ModuleNotFoundError: No module named '_home_steven__sage_temp_hp_probook_2359_tmp__qk8dlm5_pyx_0'
Hardware:
Linux hp-probook 5.4.97-gentoo-x86_64 #16 SMP Mon Mar 15 21:41:09 MDT 2021 x86_64 AMD Ryzen 7 4700U with Radeon Graphics AuthenticAMD GNU/Linux 04:00.0 Non-Volatile memory controller: Intel Corporation SSD 660P Series (rev 03) (prog-if 02 [NVM Express]) Subsystem: Intel Corporation SSD 660P Series
Attachments (1)
Change History (15)
Changed 8 months ago by
comment:1 Changed 8 months ago by
comment:2 Changed 8 months ago by
Usually the following will not fail
sage: cython(''' ....: ''', create_local_so_file=True) sage:
but even this will occasionally fail.
comment:3 Changed 8 months ago by
- Description modified (diff)
comment:4 Changed 8 months ago by
see also old ticket #28928
comment:5 follow-up: ↓ 6 Changed 7 months ago by
This hack seems to resolve things here
-
src/sage/misc/cython.py
diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index e72c97f5c3..f77d7d956b 100644
a b def cython_import(filename, **kwds): 523 523 """ 524 524 name, build_dir = cython(filename, **kwds) 525 525 526 build_dir = build_dir + '/' 527 526 528 oldpath = sys.path 527 529 try: 528 530 sys.path.append(build_dir)
$ ./sage -t src/sage/misc/sageinspect.py Running doctests with ID 2021-04-23-20-30-52-2178c446. Git branch: develop Using --optional=build,dochtml,gentoo,pip,sage,sage_spkg Doctesting 1 file. sage -t --warn-long 95.9 --random-seed=0 src/sage/misc/sageinspect.py [340 tests, 106.40 s] ---------------------------------------------------------------------- All tests passed! ---------------------------------------------------------------------- Total time for all tests: 106.7 seconds cpu time: 103.9 seconds cumulative wall time: 106.4 seconds
And the above simple example:
sage: import sys sage: cython(''' ....: ''') sage: sys.path ['/local/sage-git/sage/src/bin', '/usr/lib/python39.zip', '/usr/lib/python3.9', '/usr/lib/python3.9/lib-dynload', '', '/local/sage-git/sage/local/lib/python3.9/site-packages', '/local/sage-git/sage/local/lib/python3.9/site-packages/IPython/extensions', '/home/steven/.sage/ipython-5.0.0', '/home/steven/.sage/temp/hp-probook/10953/spyx/_home_steven__sage_temp_hp_probook_10953_tmp_terjz7ms_pyx/'] sage:
So why is the /
needed?
comment:6 in reply to: ↑ 5 Changed 6 months ago by
"three dots magic" is too slow, it costs 130 seconds:
-
src/sage/misc/sageinspect.py
a b 2276 2276 ([...'class MPolynomialIdeal( MPolynomialIdeal_singular_repr, \\\n', 2277 2277 ...) 2278 2278 sage: x = var('x') 2279 sage: sage_getsourcelines(x) 2280 (['cdef class Expression(CommutativeRingElement):\n', 2281 ' cpdef object pyobject(self):\n', 2282 ...) 2283 sage: sage_getsourcelines(x)[0][-1] # last line 2279 sage: lines, lineno = sage_getsourcelines(x); lines[0:2] 2280 ['cdef class Expression(CommutativeRingElement):\n', 2281 ' cpdef object pyobject(self):\n'] 2282 sage: lines[-1] # last line 2284 2283 ' return S\n'
before:
sage -t --long --random-seed=0 src/sage/misc/sageinspect.py [340 tests, 158.98 s]
after:
sage -t --long --random-seed=0 src/sage/misc/sageinspect.py [340 tests, 34.82 s]
comment:7 Changed 6 months ago by
Same basic result here on hardware where there is no ModuleNotFoundError
:
before:
sage -t --long --warn-long 182.5 --random-seed=0 src/sage/misc/sageinspect.py [340 tests, 156.74 s]
after:
sage -t --long --warn-long 183.3 --random-seed=0 src/sage/misc/sageinspect.py [340 tests, 25.88 s]
However, this does not resolve the ModuleNotFoundError
on the hardware listed in the description.
comment:8 Changed 5 months ago by
Invalidating internal caches seems to resolve things here on the machine in the description (see https://docs.python.org/3/library/importlib.html#importlib.invalidate_caches
-
src/sage/misc/cython.py
diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index e72c97f5c3..ec67e6042c 100644
a b def cython_import(filename, **kwds): 526 526 oldpath = sys.path 527 527 try: 528 528 sys.path.append(build_dir) 529 import importlib 530 importlib.invalidate_caches() 529 531 return builtins.__import__(name) 530 532 finally: 531 533 sys.path = oldpath
I'm not sure why it's needed nor if this is a proper fix
, but sageinspect.py
does not fail with it
$ ./sage -t src/sage/misc/sageinspect.py Running doctests with ID 2021-06-17-15-51-51-0193a7dc. Git branch: trac_31626 Using --optional=build,dochtml,gentoo,pip,sage,sage_spkg Doctesting 1 file. sage -t --warn-long 95.3 --random-seed=0 src/sage/misc/sageinspect.py [340 tests, 152.35 s] ---------------------------------------------------------------------- All tests passed! ---------------------------------------------------------------------- Total time for all tests: 152.6 seconds cpu time: 149.9 seconds cumulative wall time: 152.4 seconds Pytest is not installed, skip checking tests that rely on it.
comment:9 Changed 5 months ago by
I actually like it. From https://docs.python.org/3/library/importlib.html :
"This function should be called if any modules are created/installed while your program is running to guarantee all finders will notice the new module’s existence."
So, it is actually highly appropriate because that's exactly what the code is doing. Create a temporary module and trying to load it.
comment:10 Changed 5 months ago by
- Branch set to u/strogdon/ModuleNotFound_doctest_sageinspect
comment:11 Changed 5 months ago by
- Commit set to 926359ed07b1ec49c646e8f25389f183875f5a8e
- Status changed from new to needs_review
Pushed the recent suggestion. Let's see what the Bots say - if there are any unintended consequences. This may be difficult to review since the issue seems rare.
New commits:
926359e | Fix for when cython created temporary modules throw a
|
comment:12 Changed 5 months ago by
Not every meta path finder
sage: sys.meta_path [<class '_frozen_importlib.BuiltinImporter'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib_external.PathFinder'>, <six._SixMetaPathImporter object at 0x7fd4688217c0>]
has an invalidate_caches
attribute, that allows applying the invalidate_caches()
method. The offending item here is PathFinder
.
sage: import _frozen_importlib_external sage: _frozen_importlib_external.PathFinder.__dict__ mappingproxy({'__module__': '_frozen_importlib_external', '__doc__': 'Meta path finder for sys.path and package __path__ attributes.', 'invalidate_caches': <classmethod object at 0x7fd468c713a0>, '_path_hooks': <classmethod object at 0x7fd468c713d0>, '_path_importer_cache': <classmethod object at 0x7fd468c71400>, '_legacy_get_spec': <classmethod object at 0x7fd468c71430>, '_get_spec': <classmethod object at 0x7fd468c71460>, 'find_spec': <classmethod object at 0x7fd468c71490>, 'find_module': <classmethod object at 0x7fd468c714c0>, 'find_distributions': <classmethod object at 0x7fd468c714f0>, '__dict__': <attribute '__dict__' of 'PathFinder' objects>, '__weakref__': <attribute '__weakref__' of 'PathFinder' objects>})
The following achieves the same as this branch
-
src/sage/misc/cython.py
diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index e72c97f5c3..b3fc341b05 100644
a b def cython_import(filename, **kwds): 526 526 oldpath = sys.path 527 527 try: 528 528 sys.path.append(build_dir) 529 import _frozen_importlib_external 530 _frozen_importlib_external.PathFinder.invalidate_caches() 529 531 return builtins.__import__(name) 530 532 finally: 531 533 sys.path = oldpath
Apparently, the ModuleNotFoundError
is the result of a race condition that can exit on certain archs when a module is created on the fly and then imported. This is a potential feature
since Python 3.3.
comment:13 Changed 4 months ago by
I'm convinced that I need to call
importlib.invalidate_caches()
in order to get things to work properly. From the documentation there appears to be no harm in making the call. However, it seems that the call is not always needed and making the call unconditionally may introduce overhead. Therefore I propose to make the call conditionally as
-
src/sage/misc/cython.py
diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index 8277842084..822d115660 100644
a b def cython_import(filename, **kwds): 529 529 try: 530 530 sys.path.append(build_dir) 531 531 return builtins.__import__(name) 532 except ModuleNotFoundError: 533 import importlib 534 importlib.invalidate_caches() 535 return builtins.__import__(name) 532 536 finally: 533 537 sys.path = oldpath
This fixed things for me. Comments are welcome.
comment:14 Changed 3 months ago by
- Milestone changed from sage-9.4 to sage-9.5
A simple example that demonstrates the failure is:
where the module is present
Occasionally, the above will not fail.