From 9e9175bac4505951456c0cbac16e9afc00b3cd10 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Tue, 12 Nov 2024 01:20:51 -0500 Subject: [PATCH] fix: include encoding for consistent behavior (default in Python 3.15+) Signed-off-by: Henry Schreiner --- nox/_version.py | 2 +- nox/tasks.py | 2 +- nox/tox_to_nox.py | 4 ++-- nox/virtualenv.py | 3 ++- noxfile.py | 1 + tests/conftest.py | 2 +- tests/test__version.py | 2 +- tests/test_main.py | 4 ++-- tests/test_tasks.py | 6 +++--- tests/test_toml.py | 12 ++++++++---- tests/test_tox_to_nox.py | 4 ++-- tests/test_virtualenv.py | 15 ++++++++++----- 12 files changed, 34 insertions(+), 23 deletions(-) diff --git a/nox/_version.py b/nox/_version.py index 3d1026d3..1137e5df 100644 --- a/nox/_version.py +++ b/nox/_version.py @@ -61,7 +61,7 @@ def _parse_needs_version(source: str, filename: str = "") -> str | None def _read_needs_version(filename: str) -> str | None: """Read ``nox.needs_version`` from the user's Noxfile.""" - with open(filename) as io: + with open(filename, encoding="utf-8") as io: source = io.read() return _parse_needs_version(source, filename=filename) diff --git a/nox/tasks.py b/nox/tasks.py index 62bee9b5..129ef158 100644 --- a/nox/tasks.py +++ b/nox/tasks.py @@ -416,7 +416,7 @@ def create_report( return results # Write the JSON report. - with open(global_config.report, "w") as report_file: + with open(global_config.report, "w", encoding="utf-8") as report_file: json.dump( { "result": int(all(results)), diff --git a/nox/tox_to_nox.py b/nox/tox_to_nox.py index ec81b706..8a806be7 100644 --- a/nox/tox_to_nox.py +++ b/nox/tox_to_nox.py @@ -63,7 +63,7 @@ def fixname(envname: str) -> str: def write_output_to_file(output: str, filename: str) -> None: """Write output to a file.""" - with open(filename, "w") as outfile: + with open(filename, "w", encoding="utf-8") as outfile: outfile.write(output) @@ -74,7 +74,7 @@ def main() -> None: args = parser.parse_args() if TOX4: - output = check_output(["tox", "config"], text=True) + output = check_output(["tox", "config"], text=True, encoding="utf-8") original_config = ConfigParser() original_config.read_string(output) config: dict[str, dict[str, Any]] = {} diff --git a/nox/virtualenv.py b/nox/virtualenv.py index 8b9525c6..606816ed 100644 --- a/nox/virtualenv.py +++ b/nox/virtualenv.py @@ -77,6 +77,7 @@ def uv_version() -> version.Version: check=False, text=True, capture_output=True, + encoding="utf-8", ) except FileNotFoundError: logger.info("uv binary not found.") @@ -452,7 +453,7 @@ def _clean_location(self) -> bool: def _read_pyvenv_cfg(self) -> dict[str, str] | None: """Read a pyvenv.cfg file into dict, returns None if missing.""" path = os.path.join(self.location, "pyvenv.cfg") - with contextlib.suppress(FileNotFoundError), open(path) as fp: + with contextlib.suppress(FileNotFoundError), open(path, encoding="utf-8") as fp: parts = (x.partition("=") for x in fp if "=" in x) return {k.strip(): v.strip() for k, _, v in parts} return None diff --git a/noxfile.py b/noxfile.py index 81cf3c5e..b9c84c94 100644 --- a/noxfile.py +++ b/noxfile.py @@ -69,6 +69,7 @@ def tests(session: nox.Session, tox_version: str) -> None: *session.posargs, env={ "COVERAGE_FILE": coverage_file, + "PYTHONWARNDEFAULTENCODING": "1", }, ) diff --git a/tests/conftest.py b/tests/conftest.py index 160beae4..0d9e77f0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -48,7 +48,7 @@ def generate_noxfile(**option_mapping: str | bool) -> str: text = re.sub(rf"(# )?nox.options.{opt}", f"nox.options.{opt}", text) text = Template(text).safe_substitute(**option_mapping) path = tmp_path / "noxfile.py" - path.write_text(text) + path.write_text(text, encoding="utf8") return str(path) return generate_noxfile diff --git a/tests/test__version.py b/tests/test__version.py index a2c7520a..1e37f194 100644 --- a/tests/test__version.py +++ b/tests/test__version.py @@ -33,7 +33,7 @@ def temp_noxfile(tmp_path: Path): def make_temp_noxfile(content: str) -> str: path = tmp_path / "noxfile.py" - path.write_text(content) + path.write_text(content, encoding="utf8") return str(path) return make_temp_noxfile diff --git a/tests/test_main.py b/tests/test_main.py index 72bbe755..76ec1609 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -639,14 +639,14 @@ def generate_noxfile_options_pythons(tmp_path): def generate_noxfile(default_session, default_python, alternate_python): path = Path(RESOURCES) / "noxfile_options_pythons.py" - text = path.read_text() + text = path.read_text(encoding="utf-8") text = text.format( default_session=default_session, default_python=default_python, alternate_python=alternate_python, ) path = tmp_path / "noxfile.py" - path.write_text(text) + path.write_text(text, encoding="utf-8") return str(path) return generate_noxfile diff --git a/tests/test_tasks.py b/tests/test_tasks.py index 67b8e9be..c08bca84 100644 --- a/tests/test_tasks.py +++ b/tests/test_tasks.py @@ -124,7 +124,7 @@ def test_load_nox_module_needs_version_static(reset_needs_version, tmp_path): """ ) noxfile = tmp_path / "noxfile.py" - noxfile.write_text(text) + noxfile.write_text(text, encoding="utf-8") config = _options.options.namespace(noxfile=str(noxfile)) assert tasks.load_nox_module(config) == 2 @@ -138,7 +138,7 @@ def test_load_nox_module_needs_version_dynamic(reset_needs_version, tmp_path): """ ) noxfile = tmp_path / "noxfile.py" - noxfile.write_text(text) + noxfile.write_text(text, encoding="utf-8") config = _options.options.namespace(noxfile=str(noxfile)) tasks.load_nox_module(config) # Dynamic version requirements are not checked. @@ -705,7 +705,7 @@ def test_create_report(): mock.ANY, indent=2, ) - open_.assert_called_once_with("/path/to/report", "w") + open_.assert_called_once_with("/path/to/report", "w", encoding="utf-8") def test_final_reduce(): diff --git a/tests/test_toml.py b/tests/test_toml.py index ef2e60ed..25b13d33 100644 --- a/tests/test_toml.py +++ b/tests/test_toml.py @@ -14,7 +14,8 @@ def test_load_pyproject(tmp_path: Path) -> None: name = "hi" version = "1.0" dependencies = ["numpy", "requests"] - """ + """, + encoding="utf-8", ) toml = nox.project.load_toml(filepath) @@ -43,7 +44,8 @@ def test_load_script_block(tmp_path: Path, example: str) -> None: data = resp.json() pprint([(k, v["title"]) for k, v in data.items()][:10]) """ - ) + ), + encoding="utf-8", ) toml = nox.project.load_toml(filepath) @@ -64,7 +66,8 @@ def test_load_no_script_block(tmp_path: Path) -> None: data = resp.json() pprint([(k, v["title"]) for k, v in data.items()][:10]) """ - ) + ), + encoding="utf-8", ) with pytest.raises(ValueError, match="No script block found"): @@ -94,7 +97,8 @@ def test_load_multiple_script_block(tmp_path: Path) -> None: data = resp.json() pprint([(k, v["title"]) for k, v in data.items()][:10]) """ - ) + ), + encoding="utf-8", ) with pytest.raises(ValueError, match="Multiple script blocks found"): diff --git a/tests/test_tox_to_nox.py b/tests/test_tox_to_nox.py index 50ab4f25..de5d87f1 100644 --- a/tests/test_tox_to_nox.py +++ b/tests/test_tox_to_nox.py @@ -29,12 +29,12 @@ @pytest.fixture def makeconfig(tmpdir): def makeconfig(toxini_content): - tmpdir.join("tox.ini").write(toxini_content) + tmpdir.join("tox.ini").write_text(toxini_content, encoding="utf8") old = tmpdir.chdir() try: sys.argv = [sys.executable] tox_to_nox.main() - return tmpdir.join("noxfile.py").read() + return tmpdir.join("noxfile.py").read_text(encoding="utf8") finally: old.chdir() diff --git a/tests/test_virtualenv.py b/tests/test_virtualenv.py index 962f3e93..161f279b 100644 --- a/tests/test_virtualenv.py +++ b/tests/test_virtualenv.py @@ -441,7 +441,7 @@ def test_create_reuse_stale_venv_environment(make_one): version = 3.9.6 uv = 0.1.9 """ - location.join("pyvenv.cfg").write(dedent(pyvenv_cfg)) + location.join("pyvenv.cfg").write_text(dedent(pyvenv_cfg), encoding="utf-8") reused = not venv.create() @@ -574,7 +574,7 @@ def test_create_reuse_stale_virtualenv_environment(make_one, monkeypatch): base-exec-prefix = /usr base-executable = /usr/bin/python3.9 """ - location.join("pyvenv.cfg").write(dedent(pyvenv_cfg)) + location.join("pyvenv.cfg").write_text(dedent(pyvenv_cfg), encoding="utf-8") reused = not venv.create() @@ -590,7 +590,9 @@ def test_create_reuse_uv_environment(make_one): # Place a spurious occurrence of "uv" in the pyvenv.cfg. pyvenv_cfg = location.join("pyvenv.cfg") - pyvenv_cfg.write(pyvenv_cfg.read() + "bogus = uv\n") + pyvenv_cfg.write_text( + pyvenv_cfg.read_text(encoding="utf-8") + "bogus = uv\n", encoding="utf-8" + ) reused = not venv.create() @@ -678,7 +680,10 @@ def test_create_reuse_venv_environment(make_one, monkeypatch): # Place a spurious occurrence of "virtualenv" in the pyvenv.cfg. pyvenv_cfg = location.join("pyvenv.cfg") - pyvenv_cfg.write(pyvenv_cfg.read() + "bogus = virtualenv\n") + pyvenv_cfg.write_text( + pyvenv_cfg.read_text(encoding="utf-8") + "bogus = virtualenv\n", + encoding="utf-8", + ) reused = not venv.create() @@ -717,7 +722,7 @@ def test_inner_functions_reusing_venv(make_one, monkeypatch): version = 3.10 base-prefix = foo """ - location.join("pyvenv.cfg").write(dedent(pyvenv_cfg)) + location.join("pyvenv.cfg").write_text(dedent(pyvenv_cfg), encoding="utf-8") base_prefix = venv._read_pyvenv_cfg()["base-prefix"] assert base_prefix == "foo"