Description
Bug report
It seems that unit tests that use the image_comparison
decorator, specifically converting from SVG to PNG fail to cleanup after themselves in Windows 10.
Actual outcome
Specifically, the subprocess created to talk to inkscape doesn't close properly, and creates a ton of cascading Permission errors:
(mpldev) PS C:\Users\sjung\MPLdev\matplotlib> pytest .\lib\matplotlib\tests\test_backend_svg.py::test_bold_font_output
======================================================================= test session starts =======================================================================
platform win32 -- Python 3.8.3, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
rootdir: C:\Users\sjung\Documents\MyPrograms\Python-programs\Personal\MPLdev\matplotlib, configfile: pytest.ini
plugins: cov-2.11.1, rerunfailures-9.1.1, timeout-1.4.2
collected 1 item
lib\matplotlib\tests\test_backend_svg.py . [100%]
================================================================== 1 passed, 1 warning in 1.98s ===================================================================
Traceback (most recent call last):
File "c:\users\sjung\miniconda3\lib\shutil.py", line 617, in _rmtree_unsafe
os.rmdir(path)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\sjung\\AppData\\Local\\Temp\\tmpbqz_ngbr'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\users\sjung\miniconda3\lib\tempfile.py", line 803, in onerror
_os.unlink(path)
PermissionError: [WinError 5] Access is denied: 'C:\\Users\\sjung\\AppData\\Local\\Temp\\tmpbqz_ngbr'
[Above Error Repeats like 500 times, then we get]
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\users\sjung\miniconda3\lib\weakref.py", line 642, in _exitfunc
f()
File "c:\users\sjung\miniconda3\lib\weakref.py", line 566, in __call__
return info.func(*info.args, **(info.kwargs or {}))
File "c:\users\sjung\miniconda3\lib\tempfile.py", line 818, in _cleanup
cls._rmtree(name)
File "c:\users\sjung\miniconda3\lib\tempfile.py", line 814, in _rmtree
_shutil.rmtree(name, onerror=onerror)
File "c:\users\sjung\miniconda3\lib\shutil.py", line 737, in rmtree
return _rmtree_unsafe(path, onerror)
File "c:\users\sjung\miniconda3\lib\shutil.py", line 619, in _rmtree_unsafe
onerror(os.rmdir, path, sys.exc_info())
File "c:\users\sjung\miniconda3\lib\tempfile.py", line 806, in onerror
cls._rmtree(path)
[Repeated error]
File "c:\users\sjung\miniconda3\lib\tempfile.py", line 814, in _rmtree
_shutil.rmtree(name, onerror=onerror)
File "c:\users\sjung\miniconda3\lib\shutil.py", line 737, in rmtree
return _rmtree_unsafe(path, onerror)
File "c:\users\sjung\miniconda3\lib\shutil.py", line 594, in _rmtree_unsafe
entries = list(scandir_it)
RecursionError: maximum recursion depth exceeded while calling a Python object
The _SVGConverter
subclasses _Converter
(in lib/matplotlib/testing/compare.py) which should close the process atexit in it's __del__
method:
matplotlib/lib/matplotlib/testing/compare.py
Lines 107 to 115 in c81f58d
And from my tests, this does get called properly but the error persists. Adding this exact same logic to the end of _SVGConverter
's __call__
method seems to resolve the issue (although wastefull since a new process then gets created every time).
Expected outcome
I'd expect these test cases to cleanup after themselves and not leave empty temporary directories.
Matplotlib version
- Operating system: Windows 10
- Matplotlib version (
import matplotlib; print(matplotlib.__version__)
): 3.3.4.post2669+gce4c50de2.d20210328 (master as of today, installed from source) - Matplotlib backend (
print(matplotlib.get_backend())
): TkAgg - Python version: Happens with both Python 3.9.2 and 3.8.3
- Other libraries: Inkscape 1.0.2-2 (e86c870879, 2021-01-15)