Merge pull request #10115 from pytest-dev/atomicwrites-windows
replace atomicwrites with os.replace
This commit is contained in:
commit
7dc540f258
|
@ -67,7 +67,6 @@ repos:
|
||||||
- attrs>=19.2.0
|
- attrs>=19.2.0
|
||||||
- packaging
|
- packaging
|
||||||
- tomli
|
- tomli
|
||||||
- types-atomicwrites
|
|
||||||
- types-pkg_resources
|
- types-pkg_resources
|
||||||
- repo: local
|
- repo: local
|
||||||
hooks:
|
hooks:
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Replace `atomicwrites <https://github.com/untitaker/python-atomicwrites>`__ dependency on windows with `os.replace`.
|
|
@ -46,7 +46,6 @@ install_requires =
|
||||||
packaging
|
packaging
|
||||||
pluggy>=0.12,<2.0
|
pluggy>=0.12,<2.0
|
||||||
py>=1.8.2
|
py>=1.8.2
|
||||||
atomicwrites>=1.0;sys_platform=="win32"
|
|
||||||
colorama;sys_platform=="win32"
|
colorama;sys_platform=="win32"
|
||||||
importlib-metadata>=0.12;python_version<"3.8"
|
importlib-metadata>=0.12;python_version<"3.8"
|
||||||
tomli>=1.0.0;python_version<"3.11"
|
tomli>=1.0.0;python_version<"3.11"
|
||||||
|
|
|
@ -302,52 +302,28 @@ def _write_pyc_fp(
|
||||||
fp.write(marshal.dumps(co))
|
fp.write(marshal.dumps(co))
|
||||||
|
|
||||||
|
|
||||||
if sys.platform == "win32":
|
def _write_pyc(
|
||||||
from atomicwrites import atomic_write
|
|
||||||
|
|
||||||
def _write_pyc(
|
|
||||||
state: "AssertionState",
|
state: "AssertionState",
|
||||||
co: types.CodeType,
|
co: types.CodeType,
|
||||||
source_stat: os.stat_result,
|
source_stat: os.stat_result,
|
||||||
pyc: Path,
|
pyc: Path,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
try:
|
|
||||||
with atomic_write(os.fspath(pyc), mode="wb", overwrite=True) as fp:
|
|
||||||
_write_pyc_fp(fp, source_stat, co)
|
|
||||||
except OSError as e:
|
|
||||||
state.trace(f"error writing pyc file at {pyc}: {e}")
|
|
||||||
# we ignore any failure to write the cache file
|
|
||||||
# there are many reasons, permission-denied, pycache dir being a
|
|
||||||
# file etc.
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
def _write_pyc(
|
|
||||||
state: "AssertionState",
|
|
||||||
co: types.CodeType,
|
|
||||||
source_stat: os.stat_result,
|
|
||||||
pyc: Path,
|
|
||||||
) -> bool:
|
|
||||||
proc_pyc = f"{pyc}.{os.getpid()}"
|
proc_pyc = f"{pyc}.{os.getpid()}"
|
||||||
try:
|
try:
|
||||||
fp = open(proc_pyc, "wb")
|
with open(proc_pyc, "wb") as fp:
|
||||||
|
_write_pyc_fp(fp, source_stat, co)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
state.trace(f"error writing pyc file at {proc_pyc}: errno={e.errno}")
|
state.trace(f"error writing pyc file at {proc_pyc}: errno={e.errno}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_write_pyc_fp(fp, source_stat, co)
|
os.replace(proc_pyc, pyc)
|
||||||
os.rename(proc_pyc, pyc)
|
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
state.trace(f"error writing pyc file at {pyc}: {e}")
|
state.trace(f"error writing pyc file at {pyc}: {e}")
|
||||||
# we ignore any failure to write the cache file
|
# we ignore any failure to write the cache file
|
||||||
# there are many reasons, permission-denied, pycache dir being a
|
# there are many reasons, permission-denied, pycache dir being a
|
||||||
# file etc.
|
# file etc.
|
||||||
return False
|
return False
|
||||||
finally:
|
|
||||||
fp.close()
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1009,7 +1009,7 @@ class TestAssertionRewriteHookDetails:
|
||||||
)
|
)
|
||||||
assert pytester.runpytest().ret == 0
|
assert pytester.runpytest().ret == 0
|
||||||
|
|
||||||
def test_write_pyc(self, pytester: Pytester, tmp_path, monkeypatch) -> None:
|
def test_write_pyc(self, pytester: Pytester, tmp_path) -> None:
|
||||||
from _pytest.assertion.rewrite import _write_pyc
|
from _pytest.assertion.rewrite import _write_pyc
|
||||||
from _pytest.assertion import AssertionState
|
from _pytest.assertion import AssertionState
|
||||||
|
|
||||||
|
@ -1021,26 +1021,7 @@ class TestAssertionRewriteHookDetails:
|
||||||
co = compile("1", "f.py", "single")
|
co = compile("1", "f.py", "single")
|
||||||
assert _write_pyc(state, co, os.stat(source_path), pycpath)
|
assert _write_pyc(state, co, os.stat(source_path), pycpath)
|
||||||
|
|
||||||
if sys.platform == "win32":
|
with mock.patch.object(os, "replace", side_effect=OSError):
|
||||||
from contextlib import contextmanager
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def atomic_write_failed(fn, mode="r", overwrite=False):
|
|
||||||
e = OSError()
|
|
||||||
e.errno = 10
|
|
||||||
raise e
|
|
||||||
yield # type:ignore[unreachable]
|
|
||||||
|
|
||||||
monkeypatch.setattr(
|
|
||||||
_pytest.assertion.rewrite, "atomic_write", atomic_write_failed
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
|
|
||||||
def raise_oserror(*args):
|
|
||||||
raise OSError()
|
|
||||||
|
|
||||||
monkeypatch.setattr("os.rename", raise_oserror)
|
|
||||||
|
|
||||||
assert not _write_pyc(state, co, os.stat(source_path), pycpath)
|
assert not _write_pyc(state, co, os.stat(source_path), pycpath)
|
||||||
|
|
||||||
def test_resources_provider_for_loader(self, pytester: Pytester) -> None:
|
def test_resources_provider_for_loader(self, pytester: Pytester) -> None:
|
||||||
|
|
Loading…
Reference in New Issue