Skip to content

Commit

Permalink
Fix encoding warnings with PEP 597 enabled (#8893)
Browse files Browse the repository at this point in the history
Co-authored-by: Randy Döring <[email protected]>
  • Loading branch information
danyeaw and radoering authored Aug 15, 2024
1 parent 3ea8a5d commit eb97d90
Show file tree
Hide file tree
Showing 26 changed files with 133 additions and 72 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/.tests-matrix.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ defaults:
run:
shell: bash

env:
PYTHONWARNDEFAULTENCODING: 'true'

jobs:
mypy:
name: mypy
Expand Down
7 changes: 4 additions & 3 deletions src/poetry/masonry/builders/editable.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import csv
import hashlib
import json
import locale
import os

from base64 import urlsafe_b64encode
Expand All @@ -16,6 +15,7 @@

from poetry.utils._compat import WINDOWS
from poetry.utils._compat import decode
from poetry.utils._compat import getencoding
from poetry.utils.env import build_environment
from poetry.utils.helpers import is_dir_writable
from poetry.utils.pip import pip_install
Expand Down Expand Up @@ -125,7 +125,7 @@ def _add_pth(self) -> list[Path]:

try:
pth_file = self._env.site_packages.write_text(
pth_file, content, encoding=locale.getpreferredencoding()
pth_file, content, encoding=getencoding()
)
self._debug(
f" - Adding <c2>{pth_file.name}</c2> to <b>{pth_file.parent}</b> for"
Expand Down Expand Up @@ -252,7 +252,8 @@ def _add_dist_info(self, added_files: list[Path]) -> None:
"dir_info": {"editable": True},
"url": self._poetry.file.path.parent.absolute().as_uri(),
}
)
),
encoding="utf-8",
)
added_files.append(direct_url_json)

Expand Down
3 changes: 2 additions & 1 deletion src/poetry/repositories/installed_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from poetry.core.utils.helpers import module_name

from poetry.repositories.repository import Repository
from poetry.utils._compat import getencoding
from poetry.utils._compat import metadata


Expand Down Expand Up @@ -58,7 +59,7 @@ def get_package_paths(cls, env: Env, name: str) -> set[Path]:
if not pth_file.exists():
continue

with pth_file.open() as f:
with pth_file.open(encoding=getencoding()) as f:
for line in f:
line = line.strip()
if line and not line.startswith(("#", "import ", "import\t")):
Expand Down
9 changes: 9 additions & 0 deletions src/poetry/utils/_compat.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import locale
import sys

from contextlib import suppress
Expand Down Expand Up @@ -52,6 +53,13 @@ def encode(string: str, encodings: list[str] | None = None) -> bytes:
return string.encode(encodings[0], errors="ignore")


def getencoding() -> str:
if sys.version_info < (3, 11):
return locale.getpreferredencoding()
else:
return locale.getencoding()


def is_relative_to(this: Path, other: Path) -> bool:
"""
Return whether `this` path is relative to the `other` path. This is compatibility wrapper around
Expand All @@ -72,6 +80,7 @@ def is_relative_to(this: Path, other: Path) -> bool:
"WINDOWS",
"decode",
"encode",
"getencoding",
"is_relative_to",
"metadata",
"tomllib",
Expand Down
3 changes: 2 additions & 1 deletion src/poetry/utils/env/base_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,9 @@ def _run(self, cmd: list[str], **kwargs: Any) -> str:
subprocess.check_call(cmd, stderr=stderr, env=env, **kwargs)
output = ""
else:
encoding = "locale" if sys.version_info >= (3, 10) else None
output = subprocess.check_output(
cmd, stderr=stderr, env=env, text=True, **kwargs
cmd, stderr=stderr, env=env, text=True, encoding=encoding, **kwargs
)
except CalledProcessError as e:
raise EnvCommandError(e)
Expand Down
30 changes: 24 additions & 6 deletions src/poetry/utils/env/env_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,11 @@ def _full_python_path(python: str) -> Path | None:
return None

try:
encoding = "locale" if sys.version_info >= (3, 10) else None
executable = subprocess.check_output(
[path_python, "-c", "import sys; print(sys.executable)"], text=True
[path_python, "-c", "import sys; print(sys.executable)"],
text=True,
encoding=encoding,
).strip()
return Path(executable)

Expand Down Expand Up @@ -147,8 +150,11 @@ def get_python_version(
executable = EnvManager._detect_active_python(io)

if executable:
encoding = "locale" if sys.version_info >= (3, 10) else None
python_patch = subprocess.check_output(
[executable, "-c", GET_PYTHON_VERSION_ONELINER], text=True
[executable, "-c", GET_PYTHON_VERSION_ONELINER],
text=True,
encoding=encoding,
).strip()

version = ".".join(str(v) for v in python_patch.split(".")[:precision])
Expand Down Expand Up @@ -188,8 +194,11 @@ def activate(self, python: str) -> Env:
raise PythonVersionNotFound(python)

try:
encoding = "locale" if sys.version_info >= (3, 10) else None
python_version_string = subprocess.check_output(
[python_path, "-c", GET_PYTHON_VERSION_ONELINER], text=True
[python_path, "-c", GET_PYTHON_VERSION_ONELINER],
text=True,
encoding=encoding,
)
except CalledProcessError as e:
raise EnvCommandError(e)
Expand Down Expand Up @@ -354,8 +363,9 @@ def remove(self, python: str) -> Env:
if python_path.is_file():
# Validate env name if provided env is a full path to python
try:
encoding = "locale" if sys.version_info >= (3, 10) else None
env_dir = subprocess.check_output(
[python, "-c", GET_ENV_PATH_ONELINER], text=True
[python, "-c", GET_ENV_PATH_ONELINER], text=True, encoding=encoding
).strip("\n")
env_name = Path(env_dir).name
if not self.check_env_is_for_current_project(
Expand Down Expand Up @@ -398,8 +408,11 @@ def remove(self, python: str) -> Env:
pass

try:
encoding = "locale" if sys.version_info >= (3, 10) else None
python_version_string = subprocess.check_output(
[python, "-c", GET_PYTHON_VERSION_ONELINER], text=True
[python, "-c", GET_PYTHON_VERSION_ONELINER],
text=True,
encoding=encoding,
)
except CalledProcessError as e:
raise EnvCommandError(e)
Expand Down Expand Up @@ -481,8 +494,11 @@ def create_venv(
python_patch = ".".join([str(v) for v in sys.version_info[:3]])
python_minor = ".".join([str(v) for v in sys.version_info[:2]])
if executable:
encoding = "locale" if sys.version_info >= (3, 10) else None
python_patch = subprocess.check_output(
[executable, "-c", GET_PYTHON_VERSION_ONELINER], text=True
[executable, "-c", GET_PYTHON_VERSION_ONELINER],
text=True,
encoding=encoding,
).strip()
python_minor = ".".join(python_patch.split(".")[:2])

Expand Down Expand Up @@ -527,10 +543,12 @@ def create_venv(
continue

try:
encoding = "locale" if sys.version_info >= (3, 10) else None
python_patch = subprocess.check_output(
[python, "-c", GET_PYTHON_VERSION_ONELINER],
stderr=subprocess.STDOUT,
text=True,
encoding=encoding,
).strip()
except CalledProcessError:
continue
Expand Down
2 changes: 1 addition & 1 deletion src/poetry/utils/env/virtual_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def includes_system_site_packages(self) -> bool:
return pyvenv_cfg.exists() and (
re.search(
r"^\s*include-system-site-packages\s*=\s*true\s*$",
pyvenv_cfg.read_text(),
pyvenv_cfg.read_text(encoding="utf-8"),
re.IGNORECASE | re.MULTILINE,
)
is not None
Expand Down
Empty file.
3 changes: 2 additions & 1 deletion src/poetry/vcs/git/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ def run(*args: Any, **kwargs: Any) -> None:
git_command = find_git_command()
env = os.environ.copy()
env["GIT_TERMINAL_PROMPT"] = "0"
subprocess.check_call(
subprocess.check_call( # type: ignore[call-arg]
git_command + list(args),
stderr=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
env=env,
text=True,
encoding="utf-8",
)

@staticmethod
Expand Down
13 changes: 9 additions & 4 deletions tests/console/commands/env/test_remove.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,18 @@ def test_remove_all(
if envs_file == "empty":
envs_file_path.touch()
elif envs_file == "self":
envs_file_path.write_text(f'[{venv_name}]\nminor = "3.9"\npatch = "3.9.1"\n')
envs_file_path.write_text(
f'[{venv_name}]\nminor = "3.9"\npatch = "3.9.1"\n', encoding="utf-8"
)
elif envs_file == "other":
envs_file_path.write_text('[other-abcdefgh]\nminor = "3.9"\npatch = "3.9.1"\n')
envs_file_path.write_text(
'[other-abcdefgh]\nminor = "3.9"\npatch = "3.9.1"\n', encoding="utf-8"
)
elif envs_file == "self_and_other":
envs_file_path.write_text(
f'[{venv_name}]\nminor = "3.9"\npatch = "3.9.1"\n'
'[other-abcdefgh]\nminor = "3.9"\npatch = "3.9.1"\n'
'[other-abcdefgh]\nminor = "3.9"\npatch = "3.9.1"\n',
encoding="utf-8",
)
else:
# no envs file -> nothing to prepare
Expand All @@ -97,7 +102,7 @@ def test_remove_all(

if envs_file is not None:
assert envs_file_path.exists()
envs_file_content = envs_file_path.read_text()
envs_file_content = envs_file_path.read_text(encoding="utf-8")
assert venv_name not in envs_file_content
if "other" in envs_file:
assert "other-abcdefgh" in envs_file_content
Expand Down
2 changes: 1 addition & 1 deletion tests/console/commands/self/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def test_self_install(
assert isinstance(command, SelfInstallCommand)
pyproject_path = command.system_pyproject
if pyproject_content:
pyproject_path.write_text(pyproject_content)
pyproject_path.write_text(pyproject_content, encoding="utf-8")
else:
assert not pyproject_path.exists()

Expand Down
12 changes: 8 additions & 4 deletions tests/console/commands/self/test_self_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ def test_generate_system_pyproject_trailing_newline(
example_system_pyproject: str,
) -> None:
cmd = SelfCommand()
cmd.system_pyproject.write_text(example_system_pyproject + "\n" * existing_newlines)
cmd.system_pyproject.write_text(
example_system_pyproject + "\n" * existing_newlines, encoding="utf-8"
)
cmd.generate_system_pyproject()
generated = cmd.system_pyproject.read_text()
generated = cmd.system_pyproject.read_text(encoding="utf-8")

assert len(generated) - len(generated.rstrip("\n")) == existing_newlines

Expand All @@ -40,10 +42,12 @@ def test_generate_system_pyproject_carriage_returns(
example_system_pyproject: str,
) -> None:
cmd = SelfCommand()
cmd.system_pyproject.write_text(example_system_pyproject + "\n")
cmd.system_pyproject.write_text(example_system_pyproject + "\n", encoding="utf-8")
cmd.generate_system_pyproject()

with open(cmd.system_pyproject, newline="") as f: # do not translate newlines
with open(
cmd.system_pyproject, newline="", encoding="utf-8"
) as f: # do not translate newlines
generated = f.read()

assert "\r\r" not in generated
24 changes: 14 additions & 10 deletions tests/console/commands/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def test_noninteractive(
assert tester.io.fetch_output() == expected
assert tester.io.fetch_error() == ""

toml_content = (tmp_path / "pyproject.toml").read_text()
toml_content = (tmp_path / "pyproject.toml").read_text(encoding="utf-8")
assert 'name = "my-package"' in toml_content
assert 'pytest = "^3.6.0"' in toml_content

Expand Down Expand Up @@ -853,9 +853,11 @@ def test_init_existing_pyproject_simple(
[tool.black]
line-length = 88
"""
pyproject_file.write_text(existing_section)
pyproject_file.write_text(existing_section, encoding="utf-8")
tester.execute(inputs=init_basic_inputs)
assert f"{existing_section}\n{init_basic_toml}" in pyproject_file.read_text()
assert f"{existing_section}\n{init_basic_toml}" in pyproject_file.read_text(
encoding="utf-8"
)


@pytest.mark.parametrize("linesep", ["\n", "\r\n"])
Expand All @@ -871,10 +873,10 @@ def test_init_existing_pyproject_consistent_linesep(
[tool.black]
line-length = 88
""".replace("\n", linesep)
with open(pyproject_file, "w", newline="") as f:
with open(pyproject_file, "w", newline="", encoding="utf-8") as f:
f.write(existing_section)
tester.execute(inputs=init_basic_inputs)
with open(pyproject_file, newline="") as f:
with open(pyproject_file, newline="", encoding="utf-8") as f:
content = f.read()
init_basic_toml = init_basic_toml.replace("\n", linesep)
assert f"{existing_section}{linesep}{init_basic_toml}" in content
Expand All @@ -891,7 +893,7 @@ def test_init_non_interactive_existing_pyproject_add_dependency(
[tool.black]
line-length = 88
"""
pyproject_file.write_text(existing_section)
pyproject_file.write_text(existing_section, encoding="utf-8")

repo.add_package(get_package("foo", "1.19.2"))

Expand All @@ -915,7 +917,9 @@ def test_init_non_interactive_existing_pyproject_add_dependency(
python = "^3.6"
foo = "^1.19.2"
"""
assert f"{existing_section}\n{expected}" in pyproject_file.read_text()
assert f"{existing_section}\n{expected}" in pyproject_file.read_text(
encoding="utf-8"
)


def test_init_existing_pyproject_with_build_system_fails(
Expand All @@ -927,13 +931,13 @@ def test_init_existing_pyproject_with_build_system_fails(
requires = ["setuptools >= 40.6.0", "wheel"]
build-backend = "setuptools.build_meta"
"""
pyproject_file.write_text(existing_section)
pyproject_file.write_text(existing_section, encoding="utf-8")
tester.execute(inputs=init_basic_inputs)
assert (
tester.io.fetch_error().strip()
== "A pyproject.toml file with a defined build-system already exists."
)
assert existing_section in pyproject_file.read_text()
assert existing_section in pyproject_file.read_text(encoding="utf-8")


@pytest.mark.parametrize(
Expand Down Expand Up @@ -1069,7 +1073,7 @@ def mock_check_output(cmd: str, *_: Any, **__: Any) -> str:
python = ">={python}"
"""

assert expected in pyproject_file.read_text()
assert expected in pyproject_file.read_text(encoding="utf-8")


def test_get_pool(mocker: MockerFixture, source_dir: Path) -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/console/commands/test_new.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def mock_check_output(cmd: str, *_: Any, **__: Any) -> str:
python = ">={python}"
"""

assert expected in pyproject_file.read_text()
assert expected in pyproject_file.read_text(encoding="utf-8")


def test_basic_interactive_new(
Expand Down
4 changes: 3 additions & 1 deletion tests/console/commands/test_run.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import subprocess
import sys

from typing import TYPE_CHECKING

Expand Down Expand Up @@ -116,7 +117,8 @@ def test_run_console_scripts_of_editable_dependencies_on_windows(

cmd_script_file = tmp_venv._bin_dir / "quix.cmd"
# `/b` ensures we only exit the script instead of any cmd.exe proc that called it
cmd_script_file.write_text("exit /b 123")
encoding = "locale" if sys.version_info >= (3, 10) else None
cmd_script_file.write_text("exit /b 123", encoding=encoding)
# We prove that the CMD script executed successfully by verifying the exit code
# matches what we wrote in the script
assert tester.execute("quix") == 123
Expand Down
Loading

0 comments on commit eb97d90

Please sign in to comment.