From 2425e4f8f32abe36fddfbbd3aaebe32390cef777 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Mon, 21 Nov 2022 10:32:22 -0500 Subject: [PATCH 1/4] STYLE: consistently use single quotes in pyproject.toml Signed-off-by: Henry Schreiner fixup --- pyproject.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 78636bd03..bbab39252 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,7 +70,7 @@ strict = true lines_between_types = 1 lines_after_imports = 2 multi_line_output = 5 -known_first_party = "mesonpy" +known_first_party = 'mesonpy' [tool.coverage.html] @@ -78,8 +78,8 @@ show_contexts = true [tool.pytest.ini_options] -minversion = "6.0" -addopts = ["-ra", "--strict-markers", "--strict-config"] -log_cli_level = "info" -norecursedirs = "tests/packages/*" -testpaths = ["tests"] +minversion = '6.0' +addopts = ['-ra', '--strict-markers', '--strict-config'] +log_cli_level = 'info' +norecursedirs = 'tests/packages/*' +testpaths = ['tests'] From cb5f1befc4aef2838516abb9cccbdcaa8d7cce00 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Mon, 21 Nov 2022 10:35:25 -0500 Subject: [PATCH 2/4] TST: stricter warning checks Signed-off-by: Henry Schreiner --- pyproject.toml | 4 ++++ tests/conftest.py | 8 +++++++- tests/test_metadata.py | 15 +++++++++------ tests/test_sdist.py | 29 ++++++++++++++++------------- tests/test_wheelfile.py | 13 ++++++++----- 5 files changed, 44 insertions(+), 25 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bbab39252..fbc6137e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,3 +83,7 @@ addopts = ['-ra', '--strict-markers', '--strict-config'] log_cli_level = 'info' norecursedirs = 'tests/packages/*' testpaths = ['tests'] +xfail_strict = true +filterwarnings = [ + 'error', +] diff --git a/tests/conftest.py b/tests/conftest.py index 17c16a64e..9b859dce3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,6 +9,7 @@ import subprocess import sys import tempfile +import warnings from venv import EnvBuilder @@ -71,7 +72,12 @@ def tmp_dir_session(tmpdir_factory): class VEnv(EnvBuilder): def __init__(self, env_dir): super().__init__(with_pip=True) - self.create(env_dir) + # This warning is mistakenly generated by CPython 3.11.0 + # https://github.com/python/cpython/pull/98743 + with warnings.catch_warnings(): + if sys.version_info[:3] == (3, 11, 0): + warnings.filterwarnings('ignore', 'check_home argument is deprecated and ignored.', DeprecationWarning) + self.create(env_dir) def ensure_directories(self, env_dir): context = super().ensure_directories(env_dir) diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 75f0e3268..0aa239d6d 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -5,9 +5,10 @@ def test_no_pep621(sdist_library): - sdist = tarfile.open(sdist_library, 'r:gz') + with tarfile.open(sdist_library, 'r:gz') as sdist: + sdist_pkg_info = sdist.extractfile('library-1.0.0/PKG-INFO').read().decode() - assert sdist.extractfile('library-1.0.0/PKG-INFO').read().decode() == textwrap.dedent(''' + assert sdist_pkg_info == textwrap.dedent(''' Metadata-Version: 2.1 Name: library Version: 1.0.0 @@ -15,9 +16,10 @@ def test_no_pep621(sdist_library): def test_pep621(sdist_full_metadata): - sdist = tarfile.open(sdist_full_metadata, 'r:gz') + with tarfile.open(sdist_full_metadata, 'r:gz') as sdist: + sdist_pkg_info = sdist.extractfile('full_metadata-1.2.3/PKG-INFO').read().decode() - assert sdist.extractfile('full_metadata-1.2.3/PKG-INFO').read().decode() == textwrap.dedent('''\ + assert sdist_pkg_info == textwrap.dedent('''\ Metadata-Version: 2.1 Name: full-metadata Version: 1.2.3 @@ -50,9 +52,10 @@ def test_pep621(sdist_full_metadata): def test_dynamic_version(sdist_dynamic_version): - sdist = tarfile.open(sdist_dynamic_version, 'r:gz') + with tarfile.open(sdist_dynamic_version, 'r:gz') as sdist: + sdist_pkg_info = sdist.extractfile('dynamic_version-1.0.0/PKG-INFO').read().decode().strip() - assert sdist.extractfile('dynamic_version-1.0.0/PKG-INFO').read().decode().strip() == textwrap.dedent(''' + assert sdist_pkg_info == textwrap.dedent(''' Metadata-Version: 2.1 Name: dynamic-version Version: 1.0.0 diff --git a/tests/test_sdist.py b/tests/test_sdist.py index fdda7218d..5defd3aba 100644 --- a/tests/test_sdist.py +++ b/tests/test_sdist.py @@ -14,9 +14,10 @@ def test_contents(sdist_library): - sdist = tarfile.open(sdist_library, 'r:gz') + with tarfile.open(sdist_library, 'r:gz') as sdist: + names = set(sdist.getnames()) - assert set(sdist.getnames()) == { + assert names == { 'library-1.0.0/example.c', 'library-1.0.0/examplelib.c', 'library-1.0.0/examplelib.h', @@ -27,9 +28,10 @@ def test_contents(sdist_library): def test_contents_subdirs(sdist_subdirs): - sdist = tarfile.open(sdist_subdirs, 'r:gz') + with tarfile.open(sdist_subdirs, 'r:gz') as sdist: + names = set(sdist.getnames()) - assert set(sdist.getnames()) == { + assert names == { 'subdirs-1.0.0/PKG-INFO', 'subdirs-1.0.0/meson.build', 'subdirs-1.0.0/pyproject.toml', @@ -60,22 +62,21 @@ def bar(): f.write(old_data) os.unlink('crap') - sdist = tarfile.open(tmpdir / sdist_path, 'r:gz') + with tarfile.open(tmpdir / sdist_path, 'r:gz') as sdist: + names = set(sdist.getnames()) + read_data = sdist.extractfile('pure-1.0.0/pure.py').read().replace(b'\r\n', b'\n') - assert set(sdist.getnames()) == { + assert names == { 'pure-1.0.0/PKG-INFO', 'pure-1.0.0/meson.build', 'pure-1.0.0/pure.py', 'pure-1.0.0/pyproject.toml', } - read_data = sdist.extractfile('pure-1.0.0/pure.py').read().replace(b'\r\n', b'\n') assert read_data == new_data.encode() @pytest.mark.skipif(sys.platform in {'win32', 'cygwin'}, reason='Platform does not support executable bit') def test_executable_bit(sdist_executable_bit): - sdist = tarfile.open(sdist_executable_bit, 'r:gz') - expected = { 'executable_bit-1.0.0/PKG-INFO': False, 'executable_bit-1.0.0/example-script.py': True, @@ -84,12 +85,13 @@ def test_executable_bit(sdist_executable_bit): 'executable_bit-1.0.0/meson.build': False, 'executable_bit-1.0.0/pyproject.toml': False, } - for member in sdist.getmembers(): - assert bool(member.mode & stat.S_IXUSR) == expected[member.name] + + with tarfile.open(sdist_executable_bit, 'r:gz') as sdist: + for member in sdist.getmembers(): + assert bool(member.mode & stat.S_IXUSR) == expected[member.name] def test_generated_files(sdist_generated_files): - sdist = tarfile.open(sdist_generated_files, 'r:gz') expected = { 'executable_bit-1.0.0/PKG-INFO', 'executable_bit-1.0.0/example-script.py', @@ -100,4 +102,5 @@ def test_generated_files(sdist_generated_files): 'executable_bit-1.0.0/_version_meson.py', 'executable_bit-1.0.0/generate_version.py', } - assert set(tar.name for tar in sdist.getmembers()) == expected + with tarfile.open(sdist_generated_files, 'r:gz') as sdist: + assert set(tar.name for tar in sdist.getmembers()) == expected diff --git a/tests/test_wheelfile.py b/tests/test_wheelfile.py index 7dc8199b2..f2c57aaeb 100644 --- a/tests/test_wheelfile.py +++ b/tests/test_wheelfile.py @@ -1,3 +1,4 @@ +import contextlib import time import wheel.wheelfile @@ -8,16 +9,18 @@ def test_basic(tmp_path): path = tmp_path / 'test-1.0-py3-any-none.whl' bar = tmp_path / 'bar' - open(bar, 'wb').write(b'bar') + bar.write_bytes(b'bar') with mesonpy._wheelfile.WheelFile(path, 'w') as w: assert w.name == 'test' assert w.version == '1.0' w.writestr('foo', b'test') w.write(bar, 'bar') - with wheel.wheelfile.WheelFile(path, 'r') as w: + with contextlib.closing(wheel.wheelfile.WheelFile(path, 'r')) as w: assert set(w.namelist()) == {'foo', 'bar', 'test-1.0.dist-info/RECORD'} - w.open('foo').read() == b'test' - w.open('bar').read() == b'bar' + with w.open('foo') as foo: + assert foo.read() == b'test' + with w.open('bar') as bar: + assert bar.read() == b'bar' def test_source_date_epoch(tmp_path, monkeypatch): @@ -27,7 +30,7 @@ def test_source_date_epoch(tmp_path, monkeypatch): assert epoch % 2 == 0 monkeypatch.setenv('SOURCE_DATE_EPOCH', str(epoch)) bar = tmp_path / 'bar' - open(bar, 'wb').write(b'bar') + bar.write_bytes(b'bar') with mesonpy._wheelfile.WheelFile(path, 'w') as w: w.writestr('foo', b'test') w.write(bar, 'bar') From 67f376ca3f5fa155e7299bface53dac8048a844c Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Mon, 21 Nov 2022 10:35:55 -0500 Subject: [PATCH 3/4] TST: clarify pep518 fixture does not need to be accessed Signed-off-by: Henry Schreiner --- tests/conftest.py | 1 - tests/test_pep518.py | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 9b859dce3..9b72f522f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -156,4 +156,3 @@ def pep518_wheelhouse(tmpdir_factory): def pep518(pep518_wheelhouse, monkeypatch): monkeypatch.setenv('PIP_FIND_LINKS', pep518_wheelhouse) monkeypatch.setenv('PIP_NO_INDEX', 'true') - return pep518_wheelhouse diff --git a/tests/test_pep518.py b/tests/test_pep518.py index 6498362bf..d596866e0 100644 --- a/tests/test_pep518.py +++ b/tests/test_pep518.py @@ -6,6 +6,7 @@ from .conftest import cd_package, in_git_repo_context +@pytest.mark.usefixtures('pep518') @pytest.mark.parametrize( ('package'), [ @@ -15,7 +16,7 @@ @pytest.mark.parametrize( 'build_arg', ['', '--wheel'], ids=['sdist_to_wheel', 'wheel_directly'] ) -def test_pep518(pep518, package, build_arg, tmp_path): +def test_pep518(package, build_arg, tmp_path): dist = tmp_path / 'dist' with cd_package(package), in_git_repo_context(): From 31012f45c12431b9c5815279b75cfa655ae46c33 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Mon, 21 Nov 2022 10:33:23 -0500 Subject: [PATCH 4/4] TST: prefer tmp_path fixture to the tmpdir one The former returns a pathlib.Path, the latter a py.path. Signed-off-by: Henry Schreiner --- tests/conftest.py | 16 ++++++++-------- tests/docs/examples/test_spam.py | 6 +++--- tests/test_pep517.py | 6 +++--- tests/test_project.py | 12 ++++++------ tests/test_sdist.py | 6 +++--- tests/test_wheel.py | 12 ++++++------ 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 9b72f522f..249304d68 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -62,10 +62,10 @@ def in_git_repo_context(path=os.path.curdir): @pytest.fixture(scope='session') -def tmp_dir_session(tmpdir_factory): +def tmp_path_session(tmp_path_factory): return pathlib.Path(tempfile.mkdtemp( prefix='mesonpy-test-', - dir=tmpdir_factory.mktemp('test'), + dir=tmp_path_factory.mktemp('test'), )) @@ -107,17 +107,17 @@ def fixture(): def generate_sdist_fixture(package): @pytest.fixture(scope='session') - def fixture(tmp_dir_session): + def fixture(tmp_path_session): with cd_package(package), in_git_repo_context(): - return tmp_dir_session / mesonpy.build_sdist(tmp_dir_session) + return tmp_path_session / mesonpy.build_sdist(tmp_path_session) return fixture def generate_wheel_fixture(package): @pytest.fixture(scope='session') - def fixture(tmp_dir_session): + def fixture(tmp_path_session): with cd_package(package), in_git_repo_context(): - return tmp_dir_session / mesonpy.build_wheel(tmp_dir_session) + return tmp_path_session / mesonpy.build_wheel(tmp_path_session) return fixture @@ -138,8 +138,8 @@ def disable_pip_version_check(): @pytest.fixture(scope='session') -def pep518_wheelhouse(tmpdir_factory): - wheelhouse = tmpdir_factory.mktemp('wheelhouse') +def pep518_wheelhouse(tmp_path_factory): + wheelhouse = tmp_path_factory.mktemp('wheelhouse') meson_python = str(package_dir.parent.parent) # Populate wheelhouse with wheel for the following packages and # their dependencies. Wheels are downloaded from PyPI or built diff --git a/tests/docs/examples/test_spam.py b/tests/docs/examples/test_spam.py index 4e6101831..932b3dd20 100644 --- a/tests/docs/examples/test_spam.py +++ b/tests/docs/examples/test_spam.py @@ -8,16 +8,16 @@ from .conftest import build_project_wheel, examples_dir -def test_build_and_import(venv, tmp_dir_session): +def test_build_and_import(venv, tmp_path_session): """Test that the wheel for the spam example builds, installs, and imports.""" if sys.version_info < (3, 8): # The test project requires Python >= 3.8. with pytest.raises(mesonpy.MesonBuilderError, match=r'Unsupported Python version `3.7.\d+`'): - build_project_wheel(package=examples_dir / 'spam', outdir=tmp_dir_session) + build_project_wheel(package=examples_dir / 'spam', outdir=tmp_path_session) else: - wheel = build_project_wheel(package=examples_dir / 'spam', outdir=tmp_dir_session) + wheel = build_project_wheel(package=examples_dir / 'spam', outdir=tmp_path_session) subprocess.run( [venv.executable, '-m', 'pip', 'install', wheel], diff --git a/tests/test_pep517.py b/tests/test_pep517.py index f77163ebf..e05840ce7 100644 --- a/tests/test_pep517.py +++ b/tests/test_pep517.py @@ -53,10 +53,10 @@ def run(cmd: List[str], *args: object, **kwargs: object) -> subprocess.Completed assert set(mesonpy.get_requires_for_build_wheel()) == expected -def test_invalid_config_settings(package_pure, tmp_dir_session): +def test_invalid_config_settings(package_pure, tmp_path_session): raises_error = pytest.raises(mesonpy.ConfigError, match='Unknown config setting: invalid') with raises_error: - mesonpy.build_sdist(tmp_dir_session, {'invalid': ()}) + mesonpy.build_sdist(tmp_path_session, {'invalid': ()}) with raises_error: - mesonpy.build_wheel(tmp_dir_session, {'invalid': ()}) + mesonpy.build_wheel(tmp_path_session, {'invalid': ()}) diff --git a/tests/test_project.py b/tests/test_project.py index 663b18391..f35abf99b 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -55,7 +55,7 @@ def test_unsupported_python_version(package_unsupported_python_version): sys.version_info < (3, 8), reason="unittest.mock doesn't support the required APIs for this test", ) -def test_user_args(package_user_args, mocker, tmp_dir_session): +def test_user_args(package_user_args, mocker, tmp_path_session): mocker.patch('mesonpy.Project._meson') def last_two_meson_args(): @@ -64,7 +64,7 @@ def last_two_meson_args(): ] # create the build directory ourselves because Project._meson is mocked - builddir = str(tmp_dir_session / 'build') + builddir = str(tmp_path_session / 'build') subprocess.run(['meson', 'setup', '.', builddir], check=True) config_settings = { @@ -76,9 +76,9 @@ def last_two_meson_args(): } with contextlib.suppress(Exception): - mesonpy.build_sdist(tmp_dir_session / 'dist', config_settings) + mesonpy.build_sdist(tmp_path_session / 'dist', config_settings) with contextlib.suppress(Exception): - mesonpy.build_wheel(tmp_dir_session / 'dist', config_settings) + mesonpy.build_wheel(tmp_path_session / 'dist', config_settings) assert last_two_meson_args() == [ # sdist @@ -92,6 +92,6 @@ def last_two_meson_args(): @pytest.mark.parametrize('package', ('top-level', 'meson-args')) -def test_unknown_user_args(package, tmp_dir_session): +def test_unknown_user_args(package, tmp_path_session): with pytest.raises(mesonpy.ConfigError): - mesonpy.Project(package_dir / f'unknown-user-args-{package}', tmp_dir_session) + mesonpy.Project(package_dir / f'unknown-user-args-{package}', tmp_path_session) diff --git a/tests/test_sdist.py b/tests/test_sdist.py index 5defd3aba..99c17d51b 100644 --- a/tests/test_sdist.py +++ b/tests/test_sdist.py @@ -42,7 +42,7 @@ def test_contents_subdirs(sdist_subdirs): } -def test_contents_unstaged(package_pure, tmpdir): +def test_contents_unstaged(package_pure, tmp_path): new_data = textwrap.dedent(''' def bar(): return 'foo' @@ -56,13 +56,13 @@ def bar(): with open('pure.py', 'w') as f, open('crap', 'x'): f.write(new_data) - sdist_path = mesonpy.build_sdist(os.fspath(tmpdir)) + sdist_path = mesonpy.build_sdist(os.fspath(tmp_path)) finally: with open('pure.py', 'w') as f: f.write(old_data) os.unlink('crap') - with tarfile.open(tmpdir / sdist_path, 'r:gz') as sdist: + with tarfile.open(tmp_path / sdist_path, 'r:gz') as sdist: names = set(sdist.getnames()) read_data = sdist.extractfile('pure-1.0.0/pure.py').read().replace(b'\r\n', b'\n') diff --git a/tests/test_wheel.py b/tests/test_wheel.py index c151ddef7..2ee12091c 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -188,20 +188,20 @@ def test_detect_wheel_tag_script(wheel_executable): @pytest.mark.skipif(platform.system() != 'Linux', reason='Unsupported on this platform for now') -def test_rpath(wheel_link_against_local_lib, tmpdir): +def test_rpath(wheel_link_against_local_lib, tmp_path): artifact = wheel.wheelfile.WheelFile(wheel_link_against_local_lib) - artifact.extractall(tmpdir) + artifact.extractall(tmp_path) - elf = mesonpy._elf.ELF(tmpdir / f'example{EXT_SUFFIX}') + elf = mesonpy._elf.ELF(tmp_path / f'example{EXT_SUFFIX}') assert '$ORIGIN/.link_against_local_lib.mesonpy.libs' in elf.rpath @pytest.mark.skipif(platform.system() != 'Linux', reason='Unsupported on this platform for now') -def test_uneeded_rpath(wheel_purelib_and_platlib, tmpdir): +def test_uneeded_rpath(wheel_purelib_and_platlib, tmp_path): artifact = wheel.wheelfile.WheelFile(wheel_purelib_and_platlib) - artifact.extractall(tmpdir) + artifact.extractall(tmp_path) - elf = mesonpy._elf.ELF(tmpdir / f'plat{EXT_SUFFIX}') + elf = mesonpy._elf.ELF(tmp_path / f'plat{EXT_SUFFIX}') if elf.rpath: # elf.rpath is a frozenset, so iterate over it. An rpath may be # present, e.g. when conda is used (rpath will be /lib/)