Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ repos:
- attrs>=19.2.0
- packaging
- tomli
- types-atomicwrites
- types-pkg_resources
- repo: local
hooks:
Expand Down
1 change: 1 addition & 0 deletions changelog/10114.trivial.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Replace `atomicwrites <https://github.com/untitaker/python-atomicwrites>`__ dependency on windows with `os.replace`.
1 change: 0 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ install_requires =
packaging
pluggy>=0.12,<2.0
py>=1.8.2
atomicwrites>=1.0;sys_platform=="win32"
colorama;sys_platform=="win32"
importlib-metadata>=0.12;python_version<"3.8"
tomli>=1.0.0;python_version<"3.11"
Expand Down
30 changes: 3 additions & 27 deletions src/_pytest/assertion/rewrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,28 +302,6 @@ def _write_pyc_fp(
fp.write(marshal.dumps(co))


if sys.platform == "win32":
from atomicwrites import atomic_write

def _write_pyc(
state: "AssertionState",
co: types.CodeType,
source_stat: os.stat_result,
pyc: Path,
) -> 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,
Expand All @@ -332,22 +310,20 @@ def _write_pyc(
) -> bool:
proc_pyc = f"{pyc}.{os.getpid()}"
try:
fp = open(proc_pyc, "wb")
with open(proc_pyc, "wb") as fp:
_write_pyc_fp(fp, source_stat, co)
except OSError as e:
state.trace(f"error writing pyc file at {proc_pyc}: errno={e.errno}")
return False

try:
_write_pyc_fp(fp, source_stat, co)
os.rename(proc_pyc, pyc)
os.replace(proc_pyc, pyc)
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
finally:
fp.close()
return True


Expand Down
23 changes: 2 additions & 21 deletions testing/test_assertrewrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,7 @@ def test_meta_path():
)
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 import AssertionState

Expand All @@ -1021,26 +1021,7 @@ def test_write_pyc(self, pytester: Pytester, tmp_path, monkeypatch) -> None:
co = compile("1", "f.py", "single")
assert _write_pyc(state, co, os.stat(source_path), pycpath)

if sys.platform == "win32":
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)

with mock.patch.object(os, "replace", side_effect=OSError):
assert not _write_pyc(state, co, os.stat(source_path), pycpath)

def test_resources_provider_for_loader(self, pytester: Pytester) -> None:
Expand Down