Skip to content

Commit

Permalink
Resolve more EncodingWarning not caught by Ruff
Browse files Browse the repository at this point in the history
  • Loading branch information
Avasam committed Feb 24, 2024
1 parent c749b49 commit 41d7d29
Show file tree
Hide file tree
Showing 20 changed files with 121 additions and 62 deletions.
3 changes: 2 additions & 1 deletion setuptools/_imp.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import importlib.machinery

from importlib.util import module_from_spec
from .compat.encoding import encoding_for_open


PY_SOURCE = 1
Expand Down Expand Up @@ -66,7 +67,7 @@ def find_module(module, paths=None):
kind = C_EXTENSION

if kind in {PY_SOURCE, PY_COMPILED}:
file = open(path, mode)
file = open(path, mode, encoding=encoding_for_open)
else:
path = None
suffix = mode = ''
Expand Down
2 changes: 1 addition & 1 deletion setuptools/command/easy_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,7 @@ def write_script(self, script_name, contents, mode="t", blockers=()):
ensure_directory(target)
if os.path.exists(target):
os.unlink(target)
with open(target, "w" + mode) as f:
with open(target, "w" + mode, encoding=encoding_for_open) as f:
f.write(contents)
chmod(target, 0o777 - mask)

Expand Down
9 changes: 8 additions & 1 deletion setuptools/command/editable_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
List,
Mapping,
Optional,
Protocol,
Tuple,
TypeVar,
Union,
Expand All @@ -43,6 +42,7 @@
errors,
namespaces,
)
from ..compat.encoding import encoding_for_pth
from ..discovery import find_package_path
from ..dist import Distribution
from ..warnings import (
Expand All @@ -55,6 +55,13 @@
if TYPE_CHECKING:
from wheel.wheelfile import WheelFile # noqa

if sys.version_info >= (3, 8):
from typing import Protocol
elif TYPE_CHECKING:
from typing_extensions import Protocol
else:
from abc import ABC as Protocol

_Path = Union[str, Path]
_P = TypeVar("_P", bound=_Path)
_logger = logging.getLogger(__name__)
Expand Down
3 changes: 2 additions & 1 deletion setuptools/command/install_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import sys

from .._path import ensure_directory
from ..compat.encoding import encoding_for_open


class install_scripts(orig.install_scripts):
Expand Down Expand Up @@ -60,7 +61,7 @@ def write_script(self, script_name, contents, mode="t", *ignored):
mask = current_umask()
if not self.dry_run:
ensure_directory(target)
f = open(target, "w" + mode)
f = open(target, "w" + mode, encoding=encoding_for_open)
f.write(contents)
f.close()
chmod(target, 0o777 - mask)
2 changes: 1 addition & 1 deletion setuptools/command/setopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def edit_config(filename, settings, dry_run=False):
log.debug("Reading configuration from %s", filename)
opts = configparser.RawConfigParser()
opts.optionxform = lambda x: x
opts.read([filename])
opts.read([filename], encoding=encoding_for_open)
for section, options in settings.items():
if options is None:
log.info("Deleting section [%s] from %s", section, filename)
Expand Down
2 changes: 1 addition & 1 deletion setuptools/package_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -1016,7 +1016,7 @@ def __init__(self):

rc = os.path.join(os.path.expanduser('~'), '.pypirc')
if os.path.exists(rc):
self.read(rc)
self.read(rc, encoding=encoding_for_open)

@property
def creds_by_repository(self):
Expand Down
3 changes: 2 additions & 1 deletion setuptools/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import pkg_resources
from distutils.errors import DistutilsError
from pkg_resources import working_set
from .compat.encoding import encoding_for_open

if sys.platform.startswith('java'):
import org.python.modules.posix.PosixModule as _os
Expand Down Expand Up @@ -450,7 +451,7 @@ def _file(self, path, mode='r', *args, **kw):
def _open(self, path, mode='r', *args, **kw):
if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path):
self._violation("open", path, mode, *args, **kw)
return _open(path, mode, *args, **kw)
return _open(path, mode, *args, **kw, encoding=encoding_for_open)

def tmpnam(self):
self._violation("tmpnam")
Expand Down
9 changes: 5 additions & 4 deletions setuptools/tests/config/test_apply_pyprojecttoml.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import setuptools # noqa ensure monkey patch to metadata
from setuptools.dist import Distribution
from setuptools.compat.encoding import encoding_for_open
from setuptools.config import setupcfg, pyprojecttoml
from setuptools.config import expand
from setuptools.config._apply_pyprojecttoml import _MissingDynamic, _some_attrgetter
Expand Down Expand Up @@ -174,11 +175,11 @@ def _pep621_example_project(
replacements = {'readme = "README.rst"': f'readme = "{readme}"'}
for orig, subst in replacements.items():
text = text.replace(orig, subst)
pyproject.write_text(text, encoding="utf-8")
pyproject.write_text(text, encoding="utf-8", encoding=encoding_for_open)

(tmp_path / readme).write_text("hello world")
(tmp_path / "LICENSE.txt").write_text("--- LICENSE stub ---")
(tmp_path / "spam.py").write_text(PEP621_EXAMPLE_SCRIPT)
(tmp_path / readme).write_text("hello world", encoding=encoding_for_open)
(tmp_path / "LICENSE.txt").write_text("--- LICENSE stub ---", encoding=encoding_for_open)
(tmp_path / "spam.py").write_text(PEP621_EXAMPLE_SCRIPT, encoding=encoding_for_open)
return pyproject


Expand Down
3 changes: 2 additions & 1 deletion setuptools/tests/config/test_expand.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pytest

from distutils.errors import DistutilsOptionError
from setuptools.compat.encoding import encoding_for_open
from setuptools.config import expand
from setuptools.discovery import find_package_path

Expand All @@ -12,7 +13,7 @@ def write_files(files, root_dir):
for file, content in files.items():
path = root_dir / file
path.parent.mkdir(exist_ok=True, parents=True)
path.write_text(content)
path.write_text(content, encoding=encoding_for_open)


def test_glob_relative(tmp_path, monkeypatch):
Expand Down
43 changes: 28 additions & 15 deletions setuptools/tests/config/test_pyprojecttoml.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,17 @@ def create_example(path, pkg_root):
(path / file).parent.mkdir(exist_ok=True, parents=True)
(path / file).touch()

pyproject.write_text(EXAMPLE)
(path / "README.md").write_text("hello world")
(path / f"{pkg_root}/pkg/mod.py").write_text("class CustomSdist: pass")
(path / f"{pkg_root}/pkg/__version__.py").write_text("VERSION = (3, 10)")
(path / f"{pkg_root}/pkg/__main__.py").write_text("def exec(): print('hello')")
pyproject.write_text(EXAMPLE, encoding=encoding_for_open)
(path / "README.md").write_text("hello world", encoding=encoding_for_open)
(path / f"{pkg_root}/pkg/mod.py").write_text(
"class CustomSdist: pass", encoding=encoding_for_open
)
(path / f"{pkg_root}/pkg/__version__.py").write_text(
"VERSION = (3, 10)", encoding=encoding_for_open
)
(path / f"{pkg_root}/pkg/__main__.py").write_text(
"def exec(): print('hello')", encoding=encoding_for_open
)


def verify_example(config, path, pkg_root):
Expand Down Expand Up @@ -218,7 +224,9 @@ def test_dynamic(self, tmp_path):
Framework :: Flask
Programming Language :: Haskell
"""
(tmp_path / "classifiers.txt").write_text(cleandoc(classifiers))
(tmp_path / "classifiers.txt").write_text(
cleandoc(classifiers), encoding=encoding_for_open
)

pyproject = tmp_path / "pyproject.toml"
config = read_configuration(pyproject, expand=False)
Expand Down Expand Up @@ -246,7 +254,7 @@ def test_dynamic_without_config(self, tmp_path):
"""

pyproject = tmp_path / "pyproject.toml"
pyproject.write_text(cleandoc(config))
pyproject.write_text(cleandoc(config), encoding=encoding_for_open)
with pytest.raises(OptionError, match="No configuration .* .classifiers."):
read_configuration(pyproject)

Expand All @@ -258,7 +266,7 @@ def test_dynamic_readme_from_setup_script_args(self, tmp_path):
dynamic = ["readme"]
"""
pyproject = tmp_path / "pyproject.toml"
pyproject.write_text(cleandoc(config))
pyproject.write_text(cleandoc(config), encoding=encoding_for_open)
dist = Distribution(attrs={"long_description": "42"})
# No error should occur because of missing `readme`
dist = apply_configuration(dist, pyproject)
Expand All @@ -276,7 +284,7 @@ def test_dynamic_without_file(self, tmp_path):
"""

pyproject = tmp_path / "pyproject.toml"
pyproject.write_text(cleandoc(config))
pyproject.write_text(cleandoc(config), encoding=encoding_for_open)
with pytest.warns(UserWarning, match="File .*classifiers.txt. cannot be found"):
expanded = read_configuration(pyproject)
assert "classifiers" not in expanded["project"]
Expand All @@ -297,7 +305,7 @@ def test_dynamic_without_file(self, tmp_path):
)
def test_ignore_unrelated_config(tmp_path, example):
pyproject = tmp_path / "pyproject.toml"
pyproject.write_text(cleandoc(example))
pyproject.write_text(cleandoc(example), encoding=encoding_for_open)

# Make sure no error is raised due to 3rd party configs in pyproject.toml
assert read_configuration(pyproject) is not None
Expand All @@ -319,7 +327,7 @@ def test_ignore_unrelated_config(tmp_path, example):
)
def test_invalid_example(tmp_path, example, error_msg):
pyproject = tmp_path / "pyproject.toml"
pyproject.write_text(cleandoc(example))
pyproject.write_text(cleandoc(example), encoding=encoding_for_open)

pattern = re.compile(f"invalid pyproject.toml.*{error_msg}.*", re.M | re.S)
with pytest.raises(ValueError, match=pattern):
Expand All @@ -329,7 +337,7 @@ def test_invalid_example(tmp_path, example, error_msg):
@pytest.mark.parametrize("config", ("", "[tool.something]\nvalue = 42"))
def test_empty(tmp_path, config):
pyproject = tmp_path / "pyproject.toml"
pyproject.write_text(config)
pyproject.write_text(config, encoding=encoding_for_open)

# Make sure no error is raised
assert read_configuration(pyproject) == {}
Expand All @@ -341,7 +349,7 @@ def test_include_package_data_by_default(tmp_path, config):
default.
"""
pyproject = tmp_path / "pyproject.toml"
pyproject.write_text(config)
pyproject.write_text(config, encoding=encoding_for_open)

config = read_configuration(pyproject)
assert config["tool"]["setuptools"]["include-package-data"] is True
Expand All @@ -354,9 +362,14 @@ def test_include_package_data_in_setuppy(tmp_path):
See https://github.com/pypa/setuptools/issues/3197#issuecomment-1079023889
"""
pyproject = tmp_path / "pyproject.toml"
pyproject.write_text("[project]\nname = 'myproj'\nversion='42'\n")
pyproject.write_text(
"[project]\nname = 'myproj'\nversion='42'\n", encoding=encoding_for_open
)
setuppy = tmp_path / "setup.py"
setuppy.write_text("__import__('setuptools').setup(include_package_data=False)")
setuppy.write_text(
"__import__('setuptools').setup(include_package_data=False)",
encoding=encoding_for_open,
)

with _Path(tmp_path):
dist = distutils.core.run_setup("setup.py", {}, stop_after="config")
Expand Down
26 changes: 15 additions & 11 deletions setuptools/tests/config/test_pyprojecttoml_dynamic_deps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest

from setuptools.compat.encoding import encoding_for_open
from setuptools.config.pyprojecttoml import apply_configuration
from setuptools.dist import Distribution
from setuptools.tests.textwrap import DALS
Expand All @@ -23,19 +24,21 @@ def test_dynamic_dependencies(tmp_path):
[tool.setuptools.dynamic.dependencies]
file = ["requirements.txt"]
"""
)
),
encoding=encoding_for_open,
)
dist = Distribution()
dist = apply_configuration(dist, pyproject)
assert dist.install_requires == ["six"]


def test_dynamic_optional_dependencies(tmp_path):
(tmp_path / "requirements-docs.txt").write_text("sphinx\n # comment\n")
(tmp_path / "requirements-docs.txt").write_text(
"sphinx\n # comment\n", encoding=encoding_for_open
)
pyproject = tmp_path / "pyproject.toml"
pyproject.write_text(
DALS(
"""
DALS("""
[project]
name = "myproj"
version = "1.0"
Expand All @@ -47,8 +50,8 @@ def test_dynamic_optional_dependencies(tmp_path):
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
"""
)
"""),
encoding=encoding_for_open,
)
dist = Distribution()
dist = apply_configuration(dist, pyproject)
Expand All @@ -61,11 +64,12 @@ def test_mixed_dynamic_optional_dependencies(tmp_path):
configurations in the case of fields containing sub-fields (groups),
things would work out.
"""
(tmp_path / "requirements-images.txt").write_text("pillow~=42.0\n # comment\n")
(tmp_path / "requirements-images.txt").write_text(
"pillow~=42.0\n # comment\n", encoding=encoding_for_open
)
pyproject = tmp_path / "pyproject.toml"
pyproject.write_text(
DALS(
"""
DALS("""
[project]
name = "myproj"
version = "1.0"
Expand All @@ -80,8 +84,8 @@ def test_mixed_dynamic_optional_dependencies(tmp_path):
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
"""
)
"""),
encoding=encoding_for_open,
)
# Test that the mix-and-match doesn't currently validate.
with pytest.raises(ValueError, match="project.optional-dependencies"):
Expand Down
6 changes: 4 additions & 2 deletions setuptools/tests/config/test_setupcfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
import pytest

from distutils.errors import DistutilsOptionError, DistutilsFileError
from setuptools.dist import Distribution, _Distribution
from setuptools.compat.encoding import encoding_for_open
from setuptools.config.setupcfg import ConfigHandler, read_configuration
from setuptools.dist import Distribution, _Distribution
from setuptools.extern.packaging.requirements import InvalidRequirement
from setuptools.warnings import SetuptoolsDeprecationWarning
from ..textwrap import DALS
Expand Down Expand Up @@ -904,7 +905,8 @@ def test_cmdclass(self, tmpdir):
module_path = Path(tmpdir, "src/custom_build.py") # auto discovery for src
module_path.parent.mkdir(parents=True, exist_ok=True)
module_path.write_text(
"from distutils.core import Command\n" "class CustomCmd(Command): pass\n"
"from distutils.core import Command\n" "class CustomCmd(Command): pass\n",
encoding=encoding_for_open,
)

setup_cfg = """
Expand Down
3 changes: 3 additions & 0 deletions setuptools/tests/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import subprocess
import unicodedata
from subprocess import Popen as _Popen, PIPE as _PIPE
from ..compat.encoding import encoding_for_open

import jaraco.envs

Expand Down Expand Up @@ -31,6 +32,8 @@ def run(self, cmd, *args, **kwargs):
if "PYTHONPATH" in env:
del env["PYTHONPATH"]
kwargs["env"] = env
if "encoding" not in kwargs:
kwargs["encoding"] = encoding_for_open
return subprocess.check_output(cmd, *args, **kwargs)


Expand Down
2 changes: 2 additions & 0 deletions setuptools/tests/integration/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import tarfile
from zipfile import ZipFile
from pathlib import Path
from setuptools.compat.encoding import encoding_for_open


def run(cmd, env=None):
Expand All @@ -19,6 +20,7 @@ def run(cmd, env=None):
text=True,
env={**os.environ, **(env or {})},
# ^-- allow overwriting instead of discarding the current env
encoding=encoding_for_open,
)

out = r.stdout + "\n" + r.stderr
Expand Down
Loading

0 comments on commit 41d7d29

Please sign in to comment.