Skip to content

Tests that use "image_comparison" fail to cleanup on Windows  #19809

Closed
@jungerm2

Description

@jungerm2

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:

def __del__(self):
if self._proc:
self._proc.kill()
self._proc.wait()
for stream in filter(None, [self._proc.stdin,
self._proc.stdout,
self._proc.stderr]):
stream.close()
self._proc = None

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)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions