Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace atomicwrites with os.replace #10115

Merged
merged 1 commit into from Jul 9, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion .pre-commit-config.yaml
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
@@ -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
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
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
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