Repository navigation
pytest hangs if it tries to rewrite modules without having access rights on Windows 10 #5844
Copy link
Copy link
Closed
Labels
platform: windowswindows platform-specific problemwindows platform-specific problemplugin: debuggingrelated to the debugging builtin pluginrelated to the debugging builtin plugintopic: rewriterelated to the assertion rewrite mechanismrelated to the assertion rewrite mechanism
Description
Basically, it seems that if:
- python is installed in
C:\Program files(in a situation that you also have to runpip installfrom an elevated command prompt in order to install packages) - pytest runs (as a normal user) for the first time and tries to rewrite assertions, without having elevation
Then pytest just hangs. CTRL+C shows the following traceback:
Traceback (most recent call last):
File "c:\program files\python36\lib\tempfile.py", line 262, in _mkstemp_inner
fd = _os.open(file, flags, 0o600)
PermissionError: [Errno 13] Permission denied: 'c:\\program files\\python36\\lib\\site-packages\\typhoon\\__pycache__\\tmpu12vgv2e'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\program files\python36\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "c:\program files\python36\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Program Files\Python36\Scripts\pytest.exe\__main__.py", line 9, in <module>
File "c:\program files\python36\lib\site-packages\_pytest\config\__init__.py", line 55, in main
config = _prepareconfig(args, plugins)
File "c:\program files\python36\lib\site-packages\_pytest\config\__init__.py", line 200, in _prepareconfig
pluginmanager=pluginmanager, args=args
File "c:\program files\python36\lib\site-packages\pluggy\hooks.py", line 289, in __call__
return self._hookexec(self, self.get_hookimpls(), kwargs)
File "c:\program files\python36\lib\site-packages\pluggy\manager.py", line 87, in _hookexec
return self._inner_hookexec(hook, methods, kwargs)
File "c:\program files\python36\lib\site-packages\pluggy\manager.py", line 81, in <lambda>
firstresult=hook.spec.opts.get("firstresult") if hook.spec else False,
File "c:\program files\python36\lib\site-packages\pluggy\callers.py", line 203, in _multicall
gen.send(outcome)
File "c:\program files\python36\lib\site-packages\_pytest\helpconfig.py", line 89, in pytest_cmdline_parse
config = outcome.get_result()
File "c:\program files\python36\lib\site-packages\pluggy\callers.py", line 80, in get_result
raise ex[1].with_traceback(ex[2])
File "c:\program files\python36\lib\site-packages\pluggy\callers.py", line 187, in _multicall
res = hook_impl.function(*args)
File "c:\program files\python36\lib\site-packages\_pytest\config\__init__.py", line 661, in pytest_cmdline_parse
self.parse(args)
File "c:\program files\python36\lib\site-packages\_pytest\config\__init__.py", line 869, in parse
self._preparse(args, addopts=addopts)
File "c:\program files\python36\lib\site-packages\_pytest\config\__init__.py", line 815, in _preparse
self.pluginmanager.load_setuptools_entrypoints("pytest11")
File "c:\program files\python36\lib\site-packages\pluggy\manager.py", line 292, in load_setuptools_entrypoints
plugin = ep.load()
File "c:\program files\python36\lib\site-packages\importlib_metadata\__init__.py", line 90, in load
module = import_module(match.group('module'))
File "c:\program files\python36\lib\importlib\__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 941, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 941, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "<frozen importlib._bootstrap>", line 994, in _gcd_import
File "<frozen importlib._bootstrap>", line 971, in _find_and_load
File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
File "c:\program files\python36\lib\site-packages\_pytest\assertion\rewrite.py", line 144, in exec_module
_write_pyc(state, co, source_stat, pyc)
File "c:\program files\python36\lib\site-packages\_pytest\assertion\rewrite.py", line 267, in _write_pyc
with atomicwrites.atomic_write(pyc, mode="wb", overwrite=True) as fp:
File "c:\program files\python36\lib\contextlib.py", line 81, in __enter__
return next(self.gen)
File "c:\program files\python36\lib\site-packages\atomicwrites\__init__.py", line 156, in _open
with get_fileobject(**self._open_kwargs) as f:
File "c:\program files\python36\lib\site-packages\atomicwrites\__init__.py", line 172, in get_fileobject
descriptor, name = tempfile.mkstemp(dir=dir)
File "c:\program files\python36\lib\tempfile.py", line 344, in mkstemp
return _mkstemp_inner(dir, prefix, suffix, flags, output_type)
File "c:\program files\python36\lib\tempfile.py", line 268, in _mkstemp_inner
if (_os.name == 'nt' and _os.path.isdir(dir) and
KeyboardInterrupt
I would expect it not to hang, but for it to terminate with a Permission denied message instead.
Using Windows 10, python 3.6.8 and pytest 5.0.0
Reacted by Tom Sparrow and Alexandre
Metadata
Metadata
Assignees
Labels
platform: windowswindows platform-specific problemwindows platform-specific problemplugin: debuggingrelated to the debugging builtin pluginrelated to the debugging builtin plugintopic: rewriterelated to the assertion rewrite mechanismrelated to the assertion rewrite mechanism
Activity
nicoddemus commentedon Sep 13, 2019
Hi @Sup3rGeo!
atomicwritestries to create the temporary directory'c:\\program files\\python36\\lib\\site-packages\\typhoon\\__pycache__\\tmpu12vgv2e'usingtempfile.mkstemp, which in turn calls_mkstemp_inner:The traceback shows it is hanging on the
PermissionErrorhandling, which does call_os.access(dir, _os.W_OK)to check if it should keep retrying to create the temporary directory, otherwise it fails. It seems for some reason it is keeping looping there, instead of_os.access(dir, _os.W_OK)returningFalseand we getting the expectedPermissionError.Strange, unfortunately this is hard to debug. 😕
sparrowt commentedon Sep 17, 2019
Hopefully #4730 would help (see also #4755)
Edit: now done in #5864
Sup3rGeo commentedon Sep 17, 2019
According to this stackoverflow question, it seems this is a long lasting issue for windows that has not been yet fixed:
https://bugs.python.org/issue22107
Let's hope the items mentioned by @sparrowt above will help workaround the issue for pytest.
nicoddemus commentedon Sep 17, 2019
It would definitely help, but only for py38 users I'm afraid... 🤔
Blubbaa commentedon Nov 12, 2020
sadly this issue still exists on Windows 10, Python 3.8.6, pytest 6.1.2 😖
nicoddemus commentedon Nov 14, 2020
I guess a workaround would be to check for permission before calling into
atomic_write.I've spent a few minutes trying to write a test for it:
But unfortunately couldn't get
cached_dirto throw aPermissionErrorfor some reason. I'm leaving this here in case someone has some tips, as I'm short on time right now to investigate further. 👍marcel-kanter commentedon Dec 29, 2020
Stumbled across this too... There are two issues:
os.fspath(pyc) may be read-only (on linux too?)
and this arguments does not go to get_fileobject (this is called with dir empty) and then is replaces it (which is dangerous, since this may be read-only too)
printing dir after these two lines in atomicwrites/init.py
gives me C:\Program Files\Python38\lib\site-packages\hypothesis_pycache_
with is write protected.
File "C:\Program Files\Python38\lib\site-packages_pytest\assertion\rewrite.py", line 165, in exec_module
_write_pyc(state, co, source_stat, pyc)
File "C:\Program Files\Python38\lib\site-packages_pytest\assertion\rewrite.py", line 308, in write_pyc
with atomic_write(os.fspath(pyc), mode="wb", overwrite=True) as fp:
File "C:\Program Files\Python38\lib\contextlib.py", line 113, in enter
return next(self.gen)
File "C:\Program Files\Python38\lib\site-packages\atomicwrites_init.py", line 166, in _open
with get_fileobject(**self.open_kwargs) as f:
File "C:\Program Files\Python38\lib\site-packages\atomicwrites_init.py", line 190, in get_fileobject
Calling pytest with --assert=plain is a work-around.
crazyjurich commentedon Jul 26, 2021
Still broken on Win10, Python 3.9.6, pytest-6.2.4
Calling pytest with --assert=plain indeed works.
And in my case pytest was trying to rewrite allure-pytest module under site-packages. I don't think pytest has to rewrite libraries.
On my other env with python 3.8 pytest is working Ok, I have found that python itself is owned by system and some folders under site-packages are owned by my user, this is the reason of not failing.
Did some more experiments and found out that:
And I think other workaround is not installing python under program files, but under your user. Didn't test it though.
IMHO pytest should detect if it has write access, and either skip rewriting for modules he doesn't have access to, either write PYCs somewhere else in this case, either don't rewrite libraries within python at all.
marcel-kanter commentedon Sep 14, 2021
Another workaround maybe to use virtual environments (which have the user's rights).
But how do the Linux guys handle this? They should get the same problem...
notgriffin commentedon Feb 1, 2022
Ran into this issue but couldn't use virtual environments out of the box since I am using a program that depends on using system-wide installed packages. The solution ended up being installing all my needed packages to the system and then creating a virtual environment with the command
virtualenv --system-site-packagesto use all of the system packages. Then I installed pytest on its own to the virtual environment withpip install --ignore-installed pytest. This forced pytest to not be able to write to system-installed packages. Hopefully this workaround will help someone out. Credit: https://stackoverflow.com/a/19459977pawelszramowski commentedon Mar 31, 2022
I have also been experiencing this issue (currently on Windows 10, Python 3.9.7, and pytest 7.1.1).
I've observed that it happens after I've used
pipto update packages. My workaround is to delete all the__pycache__directories in the Python installation directory. Thenpyteststarts working even without elevated permissions.Zac-HD commentedon Jul 22, 2026
Closing as resolved: the assertion-rewrite pyc writer no longer uses the
atomicwrites/tempfile.mkstempcode path that caused the Windows hang - it was replaced with a directopen/os.replaceimplementation wrapped in a plainOSErrorhandler in #10115 (tracked by #10114, with cleanup in #10116), shipped in pytest 7.1.3. Verified against current main: permission errors during pyc writing now returnFalseinstead of hanging, and there's a dedicated regression test (test_write_pyc) covering this.