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

Fix encoding warnings with PEP 597 enabled #8893

Merged
merged 3 commits into from
Aug 15, 2024
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
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
Loading