Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pyproject-api for 
openSUSE:Factory checked in at 2023-08-30 10:20:40
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pyproject-api (Old)
 and      /work/SRC/openSUSE:Factory/.python-pyproject-api.new.1766 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pyproject-api"

Wed Aug 30 10:20:40 2023 rev:2 rq:1107822 version:1.5.4

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-pyproject-api/python-pyproject-api.changes    
    2023-05-06 22:09:45.676906979 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-pyproject-api.new.1766/python-pyproject-api.changes
      2023-08-30 10:23:22.354335689 +0200
@@ -1,0 +2,21 @@
+Mon Aug 28 21:46:05 UTC 2023 - Matej Cepl <mc...@suse.com>
+
+- Update to 1.5.4:
+  - Exclude dependabot and pre-commit ci from release notes
+  - Bump tools and deps
+  - Make sure that the order of Requires-Dist does not matter
+- Update to 1.5.3:
+  - Bump pypa/gh-action-pypi-publish from 1.8.6 to 1.8.7
+  - Fix read_line to raise EOFError if nothing was read
+- Update to 1.5.2:
+  - Add pyproject-fmt
+  - docs: remove (dynamic) years from copyright
+  - Drop 2.7 test
+  - Add trusted-publish
+  - Add 3.12 support
+  - Bump pypa/gh-action-pypi-publish from 1.8.5 to 1.8.6
+    git ls-files -z -- .github/workflows/check.yml \
+        | xargs -0 sed -i 's|3.12.0-alpha.7|3.12.0-beta.1|g'
+  - Add ruff
+
+-------------------------------------------------------------------

Old:
----
  pyproject_api-1.5.1.tar.gz

New:
----
  pyproject_api-1.5.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pyproject-api.spec ++++++
--- /var/tmp/diff_new_pack.kRBT9m/_old  2023-08-30 10:23:23.314369957 +0200
+++ /var/tmp/diff_new_pack.kRBT9m/_new  2023-08-30 10:23:23.318370099 +0200
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-pyproject-api
-Version:        1.5.1
+Version:        1.5.4
 Release:        0
 Summary:        API to interact with the python pyproject.toml based projects
 License:        MIT
@@ -28,11 +28,11 @@
 BuildRequires:  %{python_module hatch-vcs >= 0.3}
 BuildRequires:  %{python_module hatchling >= 1.12.2}
 BuildRequires:  %{python_module importlib-metadata >= 6 if %python-base < 3.8}
-BuildRequires:  %{python_module packaging >= 23}
+BuildRequires:  %{python_module packaging >= 23.1}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module setuptools_scm}
 BuildRequires:  %{python_module tomli >= 2.0.1 if %python-base < 3.11}
-BuildRequires:  %{python_module wheel >= 0.38.4}
+BuildRequires:  %{python_module wheel >= 0.40.0}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
 BuildRequires:  unzip
@@ -43,9 +43,9 @@
 BuildArch:      noarch
 # SECTION testing=
 # (except for pytest-cov and -randomly)
-BuildRequires:  %{python_module covdefaults >= 2.2.2}
-BuildRequires:  %{python_module pytest >= 7.2.0}
-BuildRequires:  %{python_module pytest-mock >= 3.10.0}
+BuildRequires:  %{python_module covdefaults >= 2.3}
+BuildRequires:  %{python_module pytest >= 7.4}
+BuildRequires:  %{python_module pytest-mock >= 3.11.1}
 BuildRequires:  %{python_module virtualenv >= 20.17.1}
 # /SECTION
 %python_subpackages

++++++ pyproject_api-1.5.1.tar.gz -> pyproject_api-1.5.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/.github/release.yml 
new/pyproject_api-1.5.4/.github/release.yml
--- old/pyproject_api-1.5.1/.github/release.yml 1970-01-01 01:00:00.000000000 
+0100
+++ new/pyproject_api-1.5.4/.github/release.yml 2020-02-02 01:00:00.000000000 
+0100
@@ -0,0 +1,5 @@
+changelog:
+  exclude:
+    authors:
+      - dependabot
+      - pre-commit-ci
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/.github/workflows/check.yml 
new/pyproject_api-1.5.4/.github/workflows/check.yml
--- old/pyproject_api-1.5.1/.github/workflows/check.yml 2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/.github/workflows/check.yml 2020-02-02 
01:00:00.000000000 +0100
@@ -1,6 +1,7 @@
 name: check
 on:
   push:
+    tags-ignore: ["**"]
   pull_request:
   schedule:
     - cron: "0 8 * * *"
@@ -17,15 +18,15 @@
       fail-fast: false
       matrix:
         py:
+          - "3.12.0-rc.1"
           - "3.11"
           - "3.10"
           - "3.9"
           - "3.8"
-          - "3.7"
         os:
-          - ubuntu-20.04
-          - windows-2022
-          - macos-12
+          - ubuntu-latest
+          - windows-latest
+          - macos-latest
     steps:
       - name: Setup python for tox
         uses: actions/setup-python@v4
@@ -36,10 +37,6 @@
           fetch-depth: 0
       - name: Install tox
         run: python -m pip install tox
-      - name: Setup python2.7 as test dependency
-        uses: actions/setup-python@v4
-        with:
-          python-version: 2.7
       - name: Setup python for test ${{ matrix.py }}
         uses: actions/setup-python@v4
         with:
@@ -73,10 +70,10 @@
           - docs
           - pkg_meta
         os:
-          - ubuntu-22.04
-          - windows-2022
+          - ubuntu-latest
+          - windows-latest
         exclude:
-          - { os: windows-2022, tox_env: pkg_meta }
+          - { os: windows-latest, tox_env: pkg_meta }
     steps:
       - uses: actions/checkout@v3
         with:
@@ -91,26 +88,3 @@
         run: tox -e ${{ matrix.tox_env }}
         env:
           UPGRADE_ADVISORY: "yes"
-
-  publish:
-    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
-    needs: [check, test]
-    runs-on: ubuntu-22.04
-    steps:
-      - name: Setup python to build package
-        uses: actions/setup-python@v4
-        with:
-          python-version: "3.11"
-      - name: Install build
-        run: python -m pip install build
-      - uses: actions/checkout@v3
-        with:
-          fetch-depth: 0
-      - name: Build package
-        run: pyproject-build -s -w . -o dist
-      - name: Publish to PyPI
-        uses: pypa/gh-action-pypi-publish@v1.6.5
-        with:
-          skip_existing: true
-          user: __token__
-          password: ${{ secrets.pypi_password }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/.github/workflows/release.yml 
new/pyproject_api-1.5.4/.github/workflows/release.yml
--- old/pyproject_api-1.5.1/.github/workflows/release.yml       1970-01-01 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/.github/workflows/release.yml       2020-02-02 
01:00:00.000000000 +0100
@@ -0,0 +1,27 @@
+name: Release to PyPI
+on:
+  push:
+    tags: ["*"]
+
+jobs:
+  release:
+    runs-on: ubuntu-latest
+    environment:
+      name: release
+      url: https://pypi.org/p/pyproject-api
+    permissions:
+      id-token: write
+    steps:
+      - name: Setup python to build package
+        uses: actions/setup-python@v4
+        with:
+          python-version: "3.11"
+      - name: Install build
+        run: python -m pip install build
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+      - name: Build package
+        run: pyproject-build -s -w . -o dist
+      - name: Publish to PyPI
+        uses: pypa/gh-action-pypi-publish@v1.8.10
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/.markdownlint.yaml 
new/pyproject_api-1.5.4/.markdownlint.yaml
--- old/pyproject_api-1.5.1/.markdownlint.yaml  2020-02-02 01:00:00.000000000 
+0100
+++ new/pyproject_api-1.5.4/.markdownlint.yaml  1970-01-01 01:00:00.000000000 
+0100
@@ -1,12 +0,0 @@
-MD013:
-  code_blocks: false
-  headers: false
-  line_length: 120
-  tables: false
-
-MD046:
-  style: fenced
-
-MD033:
-  allowed_elements:
-    - a
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/.pre-commit-config.yaml 
new/pyproject_api-1.5.4/.pre-commit-config.yaml
--- old/pyproject_api-1.5.1/.pre-commit-config.yaml     2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/.pre-commit-config.yaml     2020-02-02 
01:00:00.000000000 +0100
@@ -2,69 +2,42 @@
   - repo: https://github.com/pre-commit/pre-commit-hooks
     rev: v4.4.0
     hooks:
-      - id: check-ast
-      - id: check-builtin-literals
-      - id: check-docstring-first
-      - id: check-merge-conflict
-      - id: check-yaml
-      - id: check-toml
-      - id: debug-statements
       - id: end-of-file-fixer
       - id: trailing-whitespace
-  - repo: https://github.com/asottile/pyupgrade
-    rev: v3.3.1
+  - repo: https://github.com/astral-sh/ruff-pre-commit
+    rev: "v0.0.284"
     hooks:
-      - id: pyupgrade
-        args: ["--py37-plus"]
-        exclude: 
"^(src/pyproject_api/_backend.py|tests/demo_pkg_inline/build.py)$"
-  - repo: https://github.com/PyCQA/isort
-    rev: 5.12.0
-    hooks:
-      - id: isort
+      - id: ruff
+        exclude: src/pyproject_api/_backend.py
+        args: [--fix, --exit-non-zero-on-fix]
   - repo: https://github.com/psf/black
-    rev: 23.1.0
+    rev: 23.7.0
     hooks:
       - id: black
-        args: [--safe]
-  - repo: https://github.com/asottile/blacken-docs
-    rev: 1.13.0
-    hooks:
-      - id: blacken-docs
-        additional_dependencies: [black==23.1]
-  - repo: https://github.com/pre-commit/pygrep-hooks
-    rev: v1.10.0
-    hooks:
-      - id: rst-backticks
   - repo: https://github.com/tox-dev/tox-ini-fmt
-    rev: "0.6.1"
+    rev: "1.3.1"
     hooks:
       - id: tox-ini-fmt
         args: ["-p", "fix"]
-  - repo: https://github.com/PyCQA/flake8
-    rev: 6.0.0
+  - repo: https://github.com/tox-dev/pyproject-fmt
+    rev: "0.13.1"
     hooks:
-      - id: flake8
-        additional_dependencies:
-          - flake8-bugbear==23.1.20
-          - flake8-comprehensions==3.10.1
-          - flake8-pytest-style==1.6
-          - flake8-spellcheck==0.28
-          - flake8-unused-arguments==0.0.13
-          - flake8-noqa==1.3
-          - pep8-naming==0.13.3
-          - flake8-pyproject==1.2.2
+      - id: pyproject-fmt
+        additional_dependencies: ["tox>=4.6.4"]
   - repo: https://github.com/pre-commit/mirrors-prettier
-    rev: "v2.7.1"
+    rev: "v3.0.1"
     hooks:
       - id: prettier
-        additional_dependencies:
-          - prettier@2.7.1
-          - "@prettier/plugin-xml@2.2"
         args: ["--print-width=120", "--prose-wrap=always"]
-  - repo: https://github.com/igorshubovych/markdownlint-cli
-    rev: v0.33.0
+  - repo: https://github.com/asottile/blacken-docs
+    rev: 1.15.0
     hooks:
-      - id: markdownlint
+      - id: blacken-docs
+        additional_dependencies: [black==23.7]
+  - repo: https://github.com/pre-commit/pygrep-hooks
+    rev: v1.10.0
+    hooks:
+      - id: rst-backticks
   - repo: meta
     hooks:
       - id: check-hooks-apply
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/PKG-INFO 
new/pyproject_api-1.5.4/PKG-INFO
--- old/pyproject_api-1.5.1/PKG-INFO    2020-02-02 01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/PKG-INFO    2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
-Name: pyproject_api
-Version: 1.5.1
+Name: pyproject-api
+Version: 1.5.4
 Summary: API to interact with the python pyproject.toml based projects
 Project-URL: Homepage, http://pyproject_api.readthedocs.org
 Project-URL: Source, https://github.com/tox-dev/pyproject-api
@@ -17,24 +17,29 @@
 Classifier: Operating System :: MacOS :: MacOS X
 Classifier: Operating System :: Microsoft :: Windows
 Classifier: Operating System :: POSIX
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
 Classifier: Topic :: Software Development :: Libraries
 Classifier: Topic :: Software Development :: Testing
 Classifier: Topic :: Utilities
-Requires-Python: >=3.7
-Requires-Dist: packaging>=23
+Requires-Python: >=3.8
+Requires-Dist: packaging>=23.1
 Requires-Dist: tomli>=2.0.1; python_version < '3.11'
 Provides-Extra: docs
-Requires-Dist: furo>=2022.12.7; extra == 'docs'
-Requires-Dist: sphinx-autodoc-typehints!=1.23.4,>=1.22; extra == 'docs'
-Requires-Dist: sphinx>=6.1.3; extra == 'docs'
+Requires-Dist: furo>=2023.7.26; extra == 'docs'
+Requires-Dist: sphinx-autodoc-typehints>=1.24; extra == 'docs'
+Requires-Dist: sphinx<7.2; extra == 'docs'
 Provides-Extra: testing
-Requires-Dist: covdefaults>=2.2.2; extra == 'testing'
-Requires-Dist: importlib-metadata>=6; python_version < '3.8' and extra == 
'testing'
-Requires-Dist: pytest-cov>=4; extra == 'testing'
-Requires-Dist: pytest-mock>=3.10; extra == 'testing'
-Requires-Dist: pytest>=7.2.1; extra == 'testing'
-Requires-Dist: virtualenv>=20.17.1; extra == 'testing'
-Requires-Dist: wheel>=0.38.4; extra == 'testing'
+Requires-Dist: covdefaults>=2.3; extra == 'testing'
+Requires-Dist: pytest-cov>=4.1; extra == 'testing'
+Requires-Dist: pytest-mock>=3.11.1; extra == 'testing'
+Requires-Dist: pytest>=7.4; extra == 'testing'
+Requires-Dist: setuptools>=68; extra == 'testing'
+Requires-Dist: wheel>=0.41.1; extra == 'testing'
 Description-Content-Type: text/markdown
 
 # [`pyproject-api`](https://pyproject-api.readthedocs.io/en/latest/)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/docs/conf.py 
new/pyproject_api-1.5.4/docs/conf.py
--- old/pyproject_api-1.5.1/docs/conf.py        2020-02-02 01:00:00.000000000 
+0100
+++ new/pyproject_api-1.5.4/docs/conf.py        2020-02-02 01:00:00.000000000 
+0100
@@ -1,12 +1,11 @@
+# noqa: D100
 from __future__ import annotations
 
-from datetime import datetime
-
 from pyproject_api import __version__
 
 project = name = "pyproject_api"
 company = "tox-dev"
-copyright = f"2021-{datetime.today().year}, {company}"
+copyright = f"{company}"  # noqa: A001
 version, release = __version__, __version__.split("+")[0]
 
 extensions = [
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/pyproject.toml 
new/pyproject_api-1.5.4/pyproject.toml
--- old/pyproject_api-1.5.1/pyproject.toml      2020-02-02 01:00:00.000000000 
+0100
+++ new/pyproject_api-1.5.4/pyproject.toml      2020-02-02 01:00:00.000000000 
+0100
@@ -2,11 +2,11 @@
 build-backend = "hatchling.build"
 requires = [
   "hatch-vcs>=0.3",
-  "hatchling>=1.12.2",
+  "hatchling>=1.18",
 ]
 
 [project]
-name = "pyproject_api"
+name = "pyproject-api"
 description = "API to interact with the python pyproject.toml based projects"
 readme.content-type = "text/markdown"
 readme.file = "README.md"
@@ -19,7 +19,7 @@
 license = "MIT"
 maintainers = [{ name = "Bernát Gábor", email = "gaborjber...@gmail.com" }]
 authors = [{ name = "Bernát Gábor", email = "gaborjber...@gmail.com" }]
-requires-python = ">=3.7"
+requires-python = ">=3.8"
 classifiers = [
   "Development Status :: 5 - Production/Stable",
   "Framework :: tox",
@@ -28,6 +28,12 @@
   "Operating System :: MacOS :: MacOS X",
   "Operating System :: Microsoft :: Windows",
   "Operating System :: POSIX",
+  "Programming Language :: Python :: 3 :: Only",
+  "Programming Language :: Python :: 3.8",
+  "Programming Language :: Python :: 3.9",
+  "Programming Language :: Python :: 3.10",
+  "Programming Language :: Python :: 3.11",
+  "Programming Language :: Python :: 3.12",
   "Topic :: Software Development :: Libraries",
   "Topic :: Software Development :: Testing",
   "Topic :: Utilities",
@@ -36,22 +42,21 @@
   "version",
 ]
 dependencies = [
-  "packaging>=23",
+  "packaging>=23.1",
   'tomli>=2.0.1; python_version < "3.11"',
 ]
 optional-dependencies.docs = [
-  "furo>=2022.12.7",
-  "sphinx>=6.1.3",
-  "sphinx-autodoc-typehints!=1.23.4,>=1.22",
+  "furo>=2023.7.26",
+  "sphinx<7.2",
+  "sphinx-autodoc-typehints>=1.24",
 ]
 optional-dependencies.testing = [
-  "covdefaults>=2.2.2",
-  'importlib-metadata>=6; python_version < "3.8"',
-  "pytest>=7.2.1",
-  "pytest-cov>=4",
-  "pytest-mock>=3.10",
-  "virtualenv>=20.17.1",
-  "wheel>=0.38.4",
+  "covdefaults>=2.3",
+  "pytest>=7.4",
+  "pytest-cov>=4.1",
+  "pytest-mock>=3.11.1",
+  "setuptools>=68",
+  "wheel>=0.41.1",
 ]
 urls.Homepage = "http://pyproject_api.readthedocs.org";
 urls.Source = "https://github.com/tox-dev/pyproject-api";
@@ -64,6 +69,30 @@
 [tool.black]
 line-length = 120
 
+[tool.ruff]
+select = ["ALL"]
+line-length = 120
+target-version = "py38"
+isort = {known-first-party = ["pyproject_api"], required-imports = ["from 
__future__ import annotations"]}
+ignore = [
+  "INP001",  # no implicit namespaces here
+  "ANN101",  # Missing type annotation for `self` in method
+  "ANN102",  # Missing type annotation for `cls` in classmethod"
+  "ANN401",  # Dynamically typed expressions
+  "D203",  # `one-blank-line-before-class` (D203) and 
`no-blank-line-before-class` (D211) are incompatible
+  "D212",  # `multi-line-summary-first-line` (D212) and 
`multi-line-summary-second-line` (D213) are incompatible
+  "S104",  # Possible binding to all interface
+]
+[tool.ruff.per-file-ignores]
+"tests/**/*.py" = [
+  "S101",  # asserts allowed in tests...
+  "FBT",  # don"t care about booleans as positional arguments in tests
+  "INP001", # no implicit namespace
+  "D",  # don"t care about documentation in tests
+  "S603",  # `subprocess` call: check for execution of untrusted input
+  "PLR2004",  # Magic value used in comparison, consider replacing with a 
constant variable
+]
+
 [tool.coverage]
 html.show_contexts = true
 html.skip_covered = false
@@ -75,28 +104,13 @@
   "*/src",
   "*\\src",
 ]
-report.fail_under = 88
+report.fail_under = 98
 report.omit = []
 run.parallel = true
 run.plugins = ["covdefaults"]
 
-[tool.isort]
-known_first_party = ["pyproject_api"]
-profile = "black"
-line_length = 120
-
 [tool.mypy]
 python_version = "3.11"
 show_error_codes = true
 strict = true
 overrides = [{ module = ["virtualenv.*"], ignore_missing_imports = true }]
-
-[tool.pep8]
-max-line-length = "120"
-
-[tool.flake8]
-max-complexity = 22
-max-line-length = 120
-unused-arguments-ignore-abstract-functions = true
-noqa-require-code = true
-dictionaries = ["en_US", "python", "technical", "django"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/src/pyproject_api/__init__.py 
new/pyproject_api-1.5.4/src/pyproject_api/__init__.py
--- old/pyproject_api-1.5.1/src/pyproject_api/__init__.py       2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/src/pyproject_api/__init__.py       2020-02-02 
01:00:00.000000000 +0100
@@ -1,3 +1,4 @@
+"""PyProject API interface."""
 from __future__ import annotations
 
 from ._frontend import (
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/src/pyproject_api/__main__.py 
new/pyproject_api-1.5.4/src/pyproject_api/__main__.py
--- old/pyproject_api-1.5.1/src/pyproject_api/__main__.py       2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/src/pyproject_api/__main__.py       2020-02-02 
01:00:00.000000000 +0100
@@ -1,15 +1,18 @@
-from __future__ import annotations
+from __future__ import annotations  # noqa: D100
 
 import argparse
 import os
 import pathlib
 import sys
+from typing import TYPE_CHECKING
 
-from ._frontend import EditableResult, SdistResult, WheelResult
 from ._via_fresh_subprocess import SubprocessFrontend
 
+if TYPE_CHECKING:
+    from ._frontend import EditableResult, SdistResult, WheelResult
 
-def main_parser() -> argparse.ArgumentParser:
+
+def main_parser() -> argparse.ArgumentParser:  # noqa: D103
     parser = argparse.ArgumentParser(
         description=(
             "A pyproject.toml-based build frontend. "
@@ -58,7 +61,7 @@
     return parser
 
 
-def main(argv: list[str]) -> None:
+def main(argv: list[str]) -> None:  # noqa: D103
     parser = main_parser()
     args = parser.parse_args(argv)
 
@@ -70,22 +73,22 @@
     res: SdistResult | WheelResult | EditableResult
 
     if "sdist" in distributions:
-        print("Building sdist...")
+        print("Building sdist...")  # noqa: T201
         res = frontend.build_sdist(outdir)
-        print(res.out)
-        print(res.err, file=sys.stderr)
+        print(res.out)  # noqa: T201
+        print(res.err, file=sys.stderr)  # noqa: T201
 
     if "wheel" in distributions:
-        print("Building wheel...")
+        print("Building wheel...")  # noqa: T201
         res = frontend.build_wheel(outdir)
-        print(res.out)
-        print(res.err, file=sys.stderr)
+        print(res.out)  # noqa: T201
+        print(res.err, file=sys.stderr)  # noqa: T201
 
     if "editable" in distributions:
-        print("Building editable wheel...")
+        print("Building editable wheel...")  # noqa: T201
         res = frontend.build_editable(outdir)
-        print(res.out)
-        print(res.err, file=sys.stderr)
+        print(res.out)  # noqa: T201
+        print(res.err, file=sys.stderr)  # noqa: T201
 
 
 if __name__ == "__main__":
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/src/pyproject_api/_backend.py 
new/pyproject_api-1.5.4/src/pyproject_api/_backend.py
--- old/pyproject_api-1.5.1/src/pyproject_api/_backend.py       2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/src/pyproject_api/_backend.py       2020-02-02 
01:00:00.000000000 +0100
@@ -112,17 +112,18 @@
     return 0
 
 
-def read_line():
+def read_line(fd=0):
     # for some reason input() seems to break (hangs forever) so instead we 
read byte by byte the unbuffered stream
     content = bytearray()
     while True:
-        try:
-            char = os.read(0, 1)
-        except EOFError:  # pragma: no cover # when the stdout is closed 
without exit
-            break  # pragma: no cover
-        if char == b"\n":  # pragma: no cover
+        char = os.read(fd, 1)
+        if not char:
+            if not content:
+                raise EOFError("EOF without reading anything")  # we didn't 
get a line at all, let the caller know
             break
-        if char != b"\r":  # pragma: win32 cover
+        if char == b"\n":
+            break
+        if char != b"\r":
             content += char
     return content
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/src/pyproject_api/_backend.pyi 
new/pyproject_api-1.5.4/src/pyproject_api/_backend.pyi
--- old/pyproject_api-1.5.1/src/pyproject_api/_backend.pyi      2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/src/pyproject_api/_backend.pyi      2020-02-02 
01:00:00.000000000 +0100
@@ -1,18 +1,16 @@
-"""Handles communication on the backend side between frontend and backend"""
-from typing import Any, Optional, Sequence
+from typing import Any, Sequence
 
-class MissingCommand(TypeError): ...
+class MissingCommand(TypeError): ...  # noqa: N818
 
 class BackendProxy:
     backend_module: str
-    backend_object: Optional[str]
+    backend_object: str | None
     backend: Any
-    def __init__(self, backend_module: str, backend_obj: Optional[str]) -> 
None: ...
+    def __init__(self, backend_module: str, backend_obj: str | None) -> None: 
...
     def __call__(self, name: str, *args: Any, **kwargs: Any) -> Any: ...
-    def __str__(self) -> str: ...
     def _exit(self) -> None: ...
     def _optional_commands(self) -> dict[str, bool]: ...
 
 def run(argv: Sequence[str]) -> int: ...
-def read_line() -> bytearray: ...
+def read_line(fd: int = 0) -> bytearray: ...
 def flush() -> None: ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/src/pyproject_api/_frontend.py 
new/pyproject_api-1.5.4/src/pyproject_api/_frontend.py
--- old/pyproject_api-1.5.1/src/pyproject_api/_frontend.py      2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/src/pyproject_api/_frontend.py      2020-02-02 
01:00:00.000000000 +0100
@@ -1,4 +1,4 @@
-"""Build frontend for PEP-517"""
+"""Build frontend for PEP-517."""
 from __future__ import annotations
 
 import json
@@ -8,18 +8,13 @@
 from pathlib import Path
 from tempfile import NamedTemporaryFile, TemporaryDirectory
 from time import sleep
-from typing import Any, Dict, Iterator, List, NamedTuple, NoReturn, Optional, 
cast
+from typing import Any, Dict, Iterator, List, NamedTuple, NoReturn, Optional, 
TypedDict, cast
 from zipfile import ZipFile
 
 from packaging.requirements import Requirement
 
 from pyproject_api._util import ensure_empty_dir
 
-if sys.version_info >= (3, 8):  # pragma: no cover (py38+)
-    from typing import TypedDict
-else:  # pragma: no cover (py38+)
-    from typing_extensions import TypedDict
-
 if sys.version_info >= (3, 11):  # pragma: no cover (py311+)
     import tomllib
 else:  # pragma: no cover (py311+)
@@ -30,7 +25,7 @@
 
 
 class OptionalHooks(TypedDict, total=True):
-    """A flag indicating if the backend supports the optional hook or not"""
+    """A flag indicating if the backend supports the optional hook or not."""
 
     get_requires_for_build_sdist: bool
     prepare_metadata_for_build_wheel: bool
@@ -54,7 +49,7 @@
 
 
 class RequiresBuildSdistResult(NamedTuple):
-    """Information collected while acquiring the source distribution build 
dependencies"""
+    """Information collected while acquiring the source distribution build 
dependencies."""
 
     #: wheel build dependencies
     requires: tuple[Requirement, ...]
@@ -65,7 +60,7 @@
 
 
 class RequiresBuildWheelResult(NamedTuple):
-    """Information collected while acquiring the wheel build dependencies"""
+    """Information collected while acquiring the wheel build dependencies."""
 
     #: wheel build dependencies
     requires: tuple[Requirement, ...]
@@ -76,7 +71,7 @@
 
 
 class RequiresBuildEditableResult(NamedTuple):
-    """Information collected while acquiring the wheel build dependencies"""
+    """Information collected while acquiring the wheel build dependencies."""
 
     #: editable wheel build dependencies
     requires: tuple[Requirement, ...]
@@ -87,7 +82,7 @@
 
 
 class MetadataForBuildWheelResult(NamedTuple):
-    """Information collected while acquiring the wheel metadata"""
+    """Information collected while acquiring the wheel metadata."""
 
     #: path to the wheel metadata
     metadata: Path
@@ -98,7 +93,7 @@
 
 
 class MetadataForBuildEditableResult(NamedTuple):
-    """Information collected while acquiring the editable metadata"""
+    """Information collected while acquiring the editable metadata."""
 
     #: path to the wheel metadata
     metadata: Path
@@ -109,7 +104,7 @@
 
 
 class SdistResult(NamedTuple):
-    """Information collected while building a source distribution"""
+    """Information collected while building a source distribution."""
 
     #: path to the built source distribution
     sdist: Path
@@ -120,7 +115,7 @@
 
 
 class WheelResult(NamedTuple):
-    """Information collected while building a wheel"""
+    """Information collected while building a wheel."""
 
     #: path to the built wheel artifact
     wheel: Path
@@ -131,7 +126,7 @@
 
 
 class EditableResult(NamedTuple):
-    """Information collected while building an editable wheel"""
+    """Information collected while building an editable wheel."""
 
     #: path to the built wheel artifact
     wheel: Path
@@ -141,7 +136,7 @@
     err: str
 
 
-class BackendFailed(RuntimeError):
+class BackendFailed(RuntimeError):  # noqa: N818
     """An error of the build backend."""
 
     def __init__(self, result: dict[str, Any], out: str, err: str) -> None:
@@ -172,23 +167,21 @@
 
 
 class Frontend(ABC):
-    """
-    Abstract base class for a pyproject frontend.
-    """
+    """Abstract base class for a pyproject frontend."""
 
     #: backend key when the ``pyproject.toml`` does not specify it
     LEGACY_BUILD_BACKEND: str = "setuptools.build_meta:__legacy__"
     #: backend requirements when the ``pyproject.toml`` does not specify it
     LEGACY_REQUIRES: tuple[Requirement, ...] = (Requirement("setuptools >= 
40.8.0"), Requirement("wheel"))
 
-    def __init__(
+    def __init__(  # noqa: PLR0913
         self,
         root: Path,
         backend_paths: tuple[Path, ...],
         backend_module: str,
         backend_obj: str | None,
         requires: tuple[Requirement, ...],
-        reuse_backend: bool = True,
+        reuse_backend: bool = True,  # noqa: FBT001, FBT002
     ) -> None:
         """
         Create a new frontend.
@@ -210,7 +203,8 @@
 
     @classmethod
     def create_args_from_folder(
-        cls, folder: Path
+        cls,
+        folder: Path,
     ) -> tuple[Path, tuple[Path, ...], str, str | None, tuple[Requirement, 
...], bool]:
         """
         Frontend creation arguments from a python project folder (thould have 
a ``pypyproject.toml`` file per PEP-518).
@@ -299,7 +293,8 @@
         return RequiresBuildWheelResult(tuple(Requirement(r) for r in 
cast(List[str], result)), out, err)
 
     def get_requires_for_build_editable(
-        self, config_settings: ConfigSettings | None = None
+        self,
+        config_settings: ConfigSettings | None = None,
     ) -> RequiresBuildEditableResult:
         """
         Get build requirements for an editable wheel build (per PEP-660).
@@ -316,7 +311,9 @@
         return RequiresBuildEditableResult(tuple(Requirement(r) for r in 
cast(List[str], result)), out, err)
 
     def prepare_metadata_for_build_wheel(
-        self, metadata_directory: Path, config_settings: ConfigSettings | None 
= None
+        self,
+        metadata_directory: Path,
+        config_settings: ConfigSettings | None = None,
     ) -> MetadataForBuildWheelResult:
         """
         Build wheel metadata (per PEP-517).
@@ -343,13 +340,16 @@
 
     def _check_metadata_dir(self, metadata_directory: Path) -> None:
         if metadata_directory == self._root:
-            raise RuntimeError(f"the project root and the metadata directory 
can't be the same {self._root}")
+            msg = f"the project root and the metadata directory can't be the 
same {self._root}"
+            raise RuntimeError(msg)
         if metadata_directory.exists():  # start with fresh
             ensure_empty_dir(metadata_directory)
         metadata_directory.mkdir(parents=True, exist_ok=True)
 
     def prepare_metadata_for_build_editable(
-        self, metadata_directory: Path, config_settings: ConfigSettings | None 
= None
+        self,
+        metadata_directory: Path,
+        config_settings: ConfigSettings | None = None,
     ) -> MetadataForBuildEditableResult:
         """
         Build editable wheel metadata (per PEP-660).
@@ -442,12 +442,22 @@
             self._unexpected_response("build_editable", basename, str, out, 
err)
         return EditableResult(wheel_directory / basename, out, err)
 
-    def _unexpected_response(self, cmd: str, got: Any, expected_type: Any, 
out: str, err: str) -> NoReturn:
+    def _unexpected_response(  # noqa: PLR0913
+        self,
+        cmd: str,
+        got: Any,
+        expected_type: Any,
+        out: str,
+        err: str,
+    ) -> NoReturn:
         msg = f"{cmd!r} on {self.backend!r} returned {got!r} but expected type 
{expected_type!r}"
         raise BackendFailed({"code": None, "exc_type": TypeError.__name__, 
"exc_msg": msg}, out, err)
 
     def _metadata_from_built_wheel(
-        self, config_settings: ConfigSettings | None, metadata_directory: Path 
| None, cmd: str
+        self,
+        config_settings: ConfigSettings | None,
+        metadata_directory: Path | None,
+        cmd: str,
     ) -> tuple[str, str, str]:
         with self._wheel_directory() as wheel_directory:
             wheel_result = getattr(self, cmd)(
@@ -457,7 +467,8 @@
             )
             wheel = wheel_result.wheel
             if not wheel.exists():
-                raise RuntimeError(f"missing wheel file return by backed 
{wheel!r}")
+                msg = f"missing wheel file return by backed {wheel!r}"
+                raise RuntimeError(msg)
             out, err = wheel_result.out, wheel_result.err
             extract_to = str(metadata_directory)
             basename = None
@@ -468,7 +479,8 @@
                         basename = path.parts[0]
                         zip_file.extract(name, extract_to)
             if basename is None:  # pragma: no branch
-                raise RuntimeError(f"no .dist-info found inside generated 
wheel {wheel}")
+                msg = f"no .dist-info found inside generated wheel {wheel}"
+                raise RuntimeError(msg)
         return basename, err, out
 
     @contextmanager
@@ -484,7 +496,7 @@
                     "cmd": cmd,
                     "kwargs": {k: (str(v) if isinstance(v, Path) else v) for 
k, v in kwargs.items()},
                     "result": str(result_file),
-                }
+                },
             )
             with self._send_msg(cmd, result_file, msg) as status:
                 while not status.done:  # pragma: no branch
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/src/pyproject_api/_util.py 
new/pyproject_api-1.5.4/src/pyproject_api/_util.py
--- old/pyproject_api-1.5.1/src/pyproject_api/_util.py  2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/src/pyproject_api/_util.py  2020-02-02 
01:00:00.000000000 +0100
@@ -1,7 +1,10 @@
 from __future__ import annotations
 
-from pathlib import Path
 from shutil import rmtree
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+    from pathlib import Path
 
 
 def ensure_empty_dir(path: Path) -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/src/pyproject_api/_version.py 
new/pyproject_api-1.5.4/src/pyproject_api/_version.py
--- old/pyproject_api-1.5.1/src/pyproject_api/_version.py       2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/src/pyproject_api/_version.py       2020-02-02 
01:00:00.000000000 +0100
@@ -1,4 +1,4 @@
 # file generated by setuptools_scm
 # don't change, don't track in version control
-__version__ = version = '1.5.1'
-__version_tuple__ = version_tuple = (1, 5, 1)
+__version__ = version = '1.5.4'
+__version_tuple__ = version_tuple = (1, 5, 4)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pyproject_api-1.5.1/src/pyproject_api/_via_fresh_subprocess.py 
new/pyproject_api-1.5.4/src/pyproject_api/_via_fresh_subprocess.py
--- old/pyproject_api-1.5.1/src/pyproject_api/_via_fresh_subprocess.py  
2020-02-02 01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/src/pyproject_api/_via_fresh_subprocess.py  
2020-02-02 01:00:00.000000000 +0100
@@ -3,15 +3,17 @@
 import os
 import sys
 from contextlib import contextmanager
-from pathlib import Path
 from subprocess import PIPE, Popen
 from threading import Thread
-from typing import IO, Any, Iterator, Tuple, cast
-
-from packaging.requirements import Requirement
+from typing import IO, TYPE_CHECKING, Any, Iterator, Tuple, cast
 
 from ._frontend import CmdStatus, Frontend
 
+if TYPE_CHECKING:
+    from pathlib import Path
+
+    from packaging.requirements import Requirement
+
 
 class SubprocessCmdStatus(CmdStatus, Thread):
     def __init__(self, process: Popen[str]) -> None:
@@ -34,15 +36,17 @@
 class SubprocessFrontend(Frontend):
     """A frontend that creates fresh subprocess at every call to communicate 
with the backend."""
 
-    def __init__(
+    def __init__(  # noqa: PLR0913
         self,
         root: Path,
         backend_paths: tuple[Path, ...],
         backend_module: str,
         backend_obj: str | None,
         requires: tuple[Requirement, ...],
-    ):
+    ) -> None:
         """
+        Create a subprocess frontend.
+
         :param root: the root path to the built project
         :param backend_paths: paths that are available on the python path for 
the backend
         :param backend_module: module where the backend is located
@@ -53,13 +57,13 @@
         self.executable = sys.executable
 
     @contextmanager
-    def _send_msg(self, cmd: str, result_file: Path, msg: str) -> 
Iterator[SubprocessCmdStatus]:  # noqa: U100
+    def _send_msg(self, cmd: str, result_file: Path, msg: str) -> 
Iterator[SubprocessCmdStatus]:  # noqa: ARG002
         env = os.environ.copy()
         backend = os.pathsep.join(str(i) for i in self._backend_paths).strip()
         if backend:
             env["PYTHONPATH"] = backend
         process = Popen(
-            args=[self.executable] + self.backend_args,
+            args=[self.executable, *self.backend_args],
             stdout=PIPE,
             stderr=PIPE,
             stdin=PIPE,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/tests/demo_pkg_inline/build.py 
new/pyproject_api-1.5.4/tests/demo_pkg_inline/build.py
--- old/pyproject_api-1.5.1/tests/demo_pkg_inline/build.py      2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/tests/demo_pkg_inline/build.py      2020-02-02 
01:00:00.000000000 +0100
@@ -2,10 +2,12 @@
 Please keep this file Python 2.7 compatible.
 See https://tox.readthedocs.io/en/rewrite/development.html#code-style-guide
 """
+from __future__ import annotations
 
 import os
 import sys
 import tarfile
+from pathlib import Path
 from textwrap import dedent
 from zipfile import ZipFile
 
@@ -13,19 +15,19 @@
 pkg_name = name.replace("_", "-")
 
 version = "1.0.0"
-dist_info = "{}-{}.dist-info".format(name, version)
-logic = "{}/__init__.py".format(name)
-metadata = "{}/METADATA".format(dist_info)
-wheel = "{}/WHEEL".format(dist_info)
-record = "{}/RECORD".format(dist_info)
+dist_info = f"{name}-{version}.dist-info"
+logic = f"{name}/__init__.py"
+metadata_file = f"{dist_info}/METADATA"
+wheel = f"{dist_info}/WHEEL"
+record = f"{dist_info}/RECORD"
 content = {
-    logic: "def do():\n    print('greetings from {}')".format(name),
+    logic: f"def do():\n    print('greetings from {name}')",
 }
 metadata = {
-    metadata: """
+    metadata_file: f"""
         Metadata-Version: 2.1
-        Name: {}
-        Version: {}
+        Name: {pkg_name}
+        Version: {version}
         Summary: UNKNOWN
         Home-page: UNKNOWN
         Author: UNKNOWN
@@ -34,89 +36,93 @@
         Platform: UNKNOWN
 
         UNKNOWN
-       """.format(
-        pkg_name, version
-    ),
-    wheel: """
+       """,
+    wheel: f"""
         Wheel-Version: 1.0
-        Generator: {}-{}
+        Generator: {name}-{version}
         Root-Is-Purelib: true
-        Tag: py{}-none-any
-       """.format(
-        name, version, sys.version_info[0]
-    ),
-    "{}/top_level.txt".format(dist_info): name,
-    record: """
-        {0}/__init__.py,,
-        {1}/METADATA,,
-        {1}/WHEEL,,
-        {1}/top_level.txt,,
-        {1}/RECORD,,
-       """.format(
-        name, dist_info
-    ),
+        Tag: py{sys.version_info[0]}-none-any
+       """,
+    f"{dist_info}/top_level.txt": name,
+    record: f"""
+        {name}/__init__.py,,
+        {dist_info}/METADATA,,
+        {dist_info}/WHEEL,,
+        {dist_info}/top_level.txt,,
+        {dist_info}/RECORD,,
+       """,
 }
 
 
-def build_wheel(wheel_directory, metadata_directory=None, 
config_settings=None):  # noqa: U100
-    base_name = "{}-{}-py{}-none-any.whl".format(name, version, 
sys.version_info[0])
-    path = os.path.join(wheel_directory, base_name)
-    with ZipFile(path, "w") as zip_file_handler:
+def build_wheel(
+    wheel_directory: str,
+    metadata_directory: str | None = None,
+    config_settings: dict[str, str] | None = None,  # noqa: ARG001
+) -> str:
+    base_name = f"{name}-{version}-py{sys.version_info[0]}-none-any.whl"
+    path = Path(wheel_directory) / base_name
+    with ZipFile(str(path), "w") as zip_file_handler:
         for arc_name, data in content.items():  # pragma: no branch
             zip_file_handler.writestr(arc_name, dedent(data).strip())
         if metadata_directory is not None:
             for sub_directory, _, filenames in os.walk(metadata_directory):
                 for filename in filenames:
                     zip_file_handler.write(
-                        os.path.join(metadata_directory, sub_directory, 
filename),
-                        os.path.join(sub_directory, filename),
+                        str(Path(metadata_directory) / sub_directory / 
filename),
+                        str(Path(sub_directory) / filename),
                     )
         else:
             for arc_name, data in metadata.items():  # pragma: no branch
                 zip_file_handler.writestr(arc_name, dedent(data).strip())
-    print("created wheel {}".format(path))
+    print(f"created wheel {path}")  # noqa: T201
     return base_name
 
 
-def get_requires_for_build_wheel(config_settings=None):  # noqa: U100
+def get_requires_for_build_wheel(config_settings: dict[str, str] | None = 
None) -> list[str]:  # noqa: ARG001
     return []  # pragma: no cover # only executed in non-host pythons
 
 
-def build_sdist(sdist_directory, config_settings=None):  # noqa: U100
-    result = "{}-{}.tar.gz".format(name, version)
-    with tarfile.open(os.path.join(sdist_directory, result), "w:gz") as tar:
-        root = os.path.dirname(os.path.abspath(__file__))
-        tar.add(os.path.join(root, "build.py"), "build.py")
-        tar.add(os.path.join(root, "pyproject.toml"), "pyproject.toml")
+def build_sdist(sdist_directory: str, config_settings: dict[str, str] | None = 
None) -> str:  # noqa: ARG001
+    result = f"{name}-{version}.tar.gz"
+    with tarfile.open(str(Path(sdist_directory) / result), "w:gz") as tar:
+        root = Path(__file__).parent
+        tar.add(str(root / "build.py"), "build.py")
+        tar.add(str(root / "pyproject.toml"), "pyproject.toml")
     return result
 
 
-def get_requires_for_build_sdist(config_settings=None):  # noqa: U100
+def get_requires_for_build_sdist(config_settings: dict[str, str] | None = 
None) -> list[str]:  # noqa: ARG001
     return []  # pragma: no cover # only executed in non-host pythons
 
 
 if "HAS_REQUIRES_EDITABLE" in os.environ:
 
-    def get_requires_for_build_editable(config_settings=None):  # noqa: U100
-        return [1] if "REQUIRES_EDITABLE_BAD_RETURN" in os.environ else 
["editables"]
+    def get_requires_for_build_editable(config_settings: dict[str, str] | None 
= None) -> list[str]:  # noqa: ARG001
+        return [1] if "REQUIRES_EDITABLE_BAD_RETURN" in os.environ else 
["editables"]  # type: ignore[list-item]
 
 
 if "HAS_PREPARE_EDITABLE" in os.environ:
 
-    def prepare_metadata_for_build_editable(metadata_directory, 
config_settings=None):  # noqa: U100
-        dest = os.path.join(metadata_directory, dist_info)
-        os.mkdir(dest)
+    def prepare_metadata_for_build_editable(
+        metadata_directory: str,
+        config_settings: dict[str, str] | None = None,  # noqa: ARG001
+    ) -> str:
+        dest = Path(metadata_directory) / dist_info
+        dest.mkdir(parents=True)
         for arc_name, data in content.items():
             if arc_name.startswith(dist_info):
-                with open(os.path.join(metadata_directory, arc_name), "w") as 
file_handler:
-                    file_handler.write(dedent(data).strip())
-        print("created metadata {}".format(dest))
+                (dest.parent / arc_name).write_text(dedent(data).strip())
+        print(f"created metadata {dest}")  # noqa: T201
         if "PREPARE_EDITABLE_BAD" in os.environ:
-            return 1  # type: ignore # checking bad type on purpose
+            return 1  # type: ignore[return-value] # checking bad type on 
purpose
         return dist_info
 
 
-def build_editable(wheel_directory, metadata_directory=None, 
config_settings=None):
+def build_editable(
+    wheel_directory: str,
+    metadata_directory: str | None = None,
+    config_settings: dict[str, str] | None = None,
+) -> str:
     if "BUILD_EDITABLE_BAD" in os.environ:
-        return 1  # type: ignore # checking bad type on purpose
+        return 1  # type: ignore[return-value] # checking bad type on purpose
     return build_wheel(wheel_directory, metadata_directory, config_settings)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/tests/demo_pkg_inline/build.pyi 
new/pyproject_api-1.5.4/tests/demo_pkg_inline/build.pyi
--- old/pyproject_api-1.5.1/tests/demo_pkg_inline/build.pyi     2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/tests/demo_pkg_inline/build.pyi     1970-01-01 
01:00:00.000000000 +0100
@@ -1,19 +0,0 @@
-name: str = ...
-pkg_name: str = ...
-version: str = ...
-dist_info: str = ...
-content: dict[str, str] = ...
-
-def build_wheel(
-    wheel_directory: str, metadata_directory: str | None = ..., 
config_settings: dict[str, str] | None = ...
-) -> str: ...
-def get_requires_for_build_wheel(config_settings: dict[str, str] | None = ...) 
-> list[str]: ...
-def build_sdist(sdist_directory: str, config_settings: dict[str, str] | None = 
...) -> str: ...
-def get_requires_for_build_sdist(config_settings: dict[str, str] | None = ...) 
-> list[str]: ...
-def get_requires_for_build_editable(config_settings: dict[str, str] | None = 
...) -> list[str]: ...
-def prepare_metadata_for_build_editable(
-    metadata_directory: str, config_settings: dict[str, str] | None = None
-) -> str: ...
-def build_editable(
-    wheel_directory: str, metadata_directory: str | None = ..., 
config_settings: dict[str, str] | None = ...
-) -> str: ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pyproject_api-1.5.1/tests/demo_pkg_inline/pyproject.toml 
new/pyproject_api-1.5.4/tests/demo_pkg_inline/pyproject.toml
--- old/pyproject_api-1.5.1/tests/demo_pkg_inline/pyproject.toml        
2020-02-02 01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/tests/demo_pkg_inline/pyproject.toml        
2020-02-02 01:00:00.000000000 +0100
@@ -1,7 +1,10 @@
-[build-system]
-requires = []
+[build-system]  # noqa: D100
 build-backend = "build"
-backend-path = ["."]
+requires = [
+]
+backend-path = [
+  ".",
+]
 
 [tool.black]
 line-length = 120
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/tests/test_backend.py 
new/pyproject_api-1.5.4/tests/test_backend.py
--- old/pyproject_api-1.5.1/tests/test_backend.py       2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/tests/test_backend.py       2020-02-02 
01:00:00.000000000 +0100
@@ -1,13 +1,17 @@
 from __future__ import annotations
 
 import json
-from pathlib import Path
-from typing import Any
+import os
+from typing import TYPE_CHECKING, Any
 
 import pytest
-import pytest_mock
 
-from pyproject_api._backend import BackendProxy, run
+from pyproject_api._backend import BackendProxy, read_line, run
+
+if TYPE_CHECKING:
+    from pathlib import Path
+
+    import pytest_mock
 
 
 def test_invalid_module(capsys: pytest.CaptureFixture[str]) -> None:
@@ -76,7 +80,7 @@
     assert "started backend FakeBackendProxy" in captured.out
     assert "Backend: run command dummy_command with args {'foo': 'bar'}" in 
captured.out
     assert "Backend: Wrote response " in captured.out
-    assert "" == captured.err
+    assert not captured.err
 
 
 def test_reuse_process(mocker: pytest_mock.MockerFixture, capsys: 
pytest.CaptureFixture[str], tmp_path: Path) -> None:
@@ -101,7 +105,7 @@
         json.dumps({"cmd": "_exit", "kwargs": {}, "result": results[3]}),
     ]
 
-    def fake_backend(name: str, *args: Any, **kwargs: Any) -> Any:  # noqa: 
U100
+    def fake_backend(name: str, *args: Any, **kwargs: Any) -> Any:  # noqa: 
ARG001
         if name == "dummy_command_b":
             raise SystemExit(2)
 
@@ -124,3 +128,37 @@
     assert "Backend: run command dummy_command_b with args {'baz': 'qux'}" in 
captured.out
     assert "Backend: run command dummy_command_c with args {'win': 'wow'}" in 
captured.out
     assert "SystemExit: 2" in captured.err
+
+
+def test_read_line_success() -> None:
+    r, w = os.pipe()
+    try:
+        line_in = b"this is a line\r\n"
+        os.write(w, line_in)
+        line_out = read_line(fd=r)
+        assert line_out == bytearray(b"this is a line")
+    finally:
+        os.close(r)
+        os.close(w)
+
+
+def test_read_line_eof_before_newline() -> None:
+    r, w = os.pipe()
+    try:
+        line_in = b"this is a line"
+        os.write(w, line_in)
+        os.close(w)
+        line_out = read_line(fd=r)
+        assert line_out == bytearray(b"this is a line")
+    finally:
+        os.close(r)
+
+
+def test_read_line_eof_at_the_beginning() -> None:
+    r, w = os.pipe()
+    try:
+        os.close(w)
+        with pytest.raises(EOFError):
+            read_line(fd=r)
+    finally:
+        os.close(r)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/tests/test_frontend.py 
new/pyproject_api-1.5.4/tests/test_frontend.py
--- old/pyproject_api-1.5.1/tests/test_frontend.py      2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/tests/test_frontend.py      2020-02-02 
01:00:00.000000000 +0100
@@ -6,7 +6,6 @@
 
 import pytest
 from packaging.requirements import Requirement
-from virtualenv import session_via_cli
 
 from pyproject_api._frontend import BackendFailed
 from pyproject_api._via_fresh_subprocess import SubprocessFrontend
@@ -307,12 +306,3 @@
     assert not exc.args
     assert exc.exc_type == "TypeError"
     assert exc.exc_msg == "'build_editable' on 'build' returned 1 but expected 
type <class 'str'>"
-
-
-def test_can_build_on_python_2(demo_pkg_inline: Path, tmp_path: Path) -> None:
-    frontend = 
SubprocessFrontend(*SubprocessFrontend.create_args_from_folder(demo_pkg_inline)[:-1])
-    env = session_via_cli(["-p", "2.7", str(tmp_path / "venv")])
-    env.run()
-    frontend.executable = str(env.creator.exe)
-
-    frontend.build_sdist(tmp_path)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pyproject_api-1.5.1/tests/test_frontend_setuptools.py 
new/pyproject_api-1.5.4/tests/test_frontend_setuptools.py
--- old/pyproject_api-1.5.1/tests/test_frontend_setuptools.py   2020-02-02 
01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/tests/test_frontend_setuptools.py   2020-02-02 
01:00:00.000000000 +0100
@@ -2,29 +2,29 @@
 
 import sys
 from contextlib import contextmanager
-from pathlib import Path
 from stat import S_IWGRP, S_IWOTH, S_IWUSR
-from typing import Iterator, NamedTuple
+from typing import TYPE_CHECKING, Iterator, NamedTuple
 
 import pytest
-from _pytest.tmpdir import TempPathFactory
 from packaging.requirements import Requirement
-from pytest_mock import MockerFixture
 
 from pyproject_api._frontend import BackendFailed
 from pyproject_api._via_fresh_subprocess import SubprocessFrontend
 
-if sys.version_info >= (3, 8):  # pragma: no cover (py38+)
-    from importlib.metadata import Distribution, EntryPoint
-else:  # pragma: no cover (<py38)
-    from importlib_metadata import Distribution, EntryPoint
+if TYPE_CHECKING:
+    from pathlib import Path
+
+    from _pytest.tmpdir import TempPathFactory
+    from pytest_mock import MockerFixture
+
+from importlib.metadata import Distribution, EntryPoint
 
 
 @pytest.fixture(scope="session")
 def frontend_setuptools(tmp_path_factory: TempPathFactory) -> 
SubprocessFrontend:
     prj = tmp_path_factory.mktemp("proj")
     (prj / "pyproject.toml").write_text(
-        '[build-system]\nrequires=["setuptools","wheel"]\nbuild-backend = 
"setuptools.build_meta"'
+        '[build-system]\nrequires=["setuptools","wheel"]\nbuild-backend = 
"setuptools.build_meta"',
     )
     cfg = """
         [metadata]
@@ -73,9 +73,9 @@
     assert list(dist.entry_points) == [EntryPoint(name="demo_exe", 
value="demo:a", group="console_scripts")]
     assert dist.version == "1.0"
     assert dist.metadata["Name"] == "demo"
-    values = [v for k, v in dist.metadata.items() if k == "Requires-Dist"]  # 
type: ignore
+    values = [v for k, v in dist.metadata.items() if k == "Requires-Dist"]  # 
type: ignore[attr-defined]
     # ignore because "PackageMetadata" has no attribute "items"
-    assert values == ["requests (>2)", "magic (>3)"]
+    assert sorted(values) == ["magic >3", "requests >2"]
     assert isinstance(result.out, str)
     assert isinstance(result.err, str)
 
@@ -135,7 +135,7 @@
 
 
 def test_bad_message(frontend_setuptools: SubprocessFrontend, tmp_path: Path) 
-> None:
-    with frontend_setuptools._send_msg("bad_cmd", tmp_path / "a", "{{") as 
status:
+    with frontend_setuptools._send_msg("bad_cmd", tmp_path / "a", "{{") as 
status:  # noqa: SLF001
         while not status.done:  # pragma: no branch
             pass
     out, err = status.out_err()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/tests/test_main.py 
new/pyproject_api-1.5.4/tests/test_main.py
--- old/pyproject_api-1.5.1/tests/test_main.py  2020-02-02 01:00:00.000000000 
+0100
+++ new/pyproject_api-1.5.4/tests/test_main.py  2020-02-02 01:00:00.000000000 
+0100
@@ -1,13 +1,16 @@
 from __future__ import annotations
 
 from pathlib import Path
+from typing import TYPE_CHECKING
 
 import pytest
-import pytest_mock
 
 import pyproject_api.__main__
 from pyproject_api._frontend import EditableResult, SdistResult, WheelResult
 
+if TYPE_CHECKING:
+    import pytest_mock
+
 
 @pytest.mark.parametrize(
     ("cli_args", "srcdir", "outdir", "hooks"),
@@ -56,7 +59,7 @@
         ),
     ],
 )
-def test_parse_args(
+def test_parse_args(  # noqa: PLR0913
     mocker: pytest_mock.MockerFixture,
     capsys: pytest.CaptureFixture[str],
     cli_args: list[str],
@@ -72,7 +75,9 @@
         err="sdist err",
     )
     subprocess_frontend.return_value.build_wheel.return_value = WheelResult(
-        wheel=outdir / "foo.whl", out="wheel out", err="wheel err"
+        wheel=outdir / "foo.whl",
+        out="wheel out",
+        err="wheel err",
     )
     subprocess_frontend.return_value.build_editable.return_value = 
EditableResult(
         wheel=outdir / "foo.whl",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/tests/test_util.py 
new/pyproject_api-1.5.4/tests/test_util.py
--- old/pyproject_api-1.5.1/tests/test_util.py  2020-02-02 01:00:00.000000000 
+0100
+++ new/pyproject_api-1.5.4/tests/test_util.py  2020-02-02 01:00:00.000000000 
+0100
@@ -1,9 +1,12 @@
 from __future__ import annotations
 
-from pathlib import Path
+from typing import TYPE_CHECKING
 
 from pyproject_api._util import ensure_empty_dir
 
+if TYPE_CHECKING:
+    from pathlib import Path
+
 
 def test_ensure_empty_dir_on_empty(tmp_path: Path) -> None:
     ensure_empty_dir(tmp_path)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/tox.ini 
new/pyproject_api-1.5.4/tox.ini
--- old/pyproject_api-1.5.1/tox.ini     2020-02-02 01:00:00.000000000 +0100
+++ new/pyproject_api-1.5.4/tox.ini     2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,9 @@
 [tox]
-envlist =
+requires =
+    tox>=4.2
+env_list =
     fix
+    py312
     py311
     py310
     py39
@@ -9,19 +12,19 @@
     type
     docs
     pkg_meta
-isolated_build = true
 skip_missing_interpreters = true
-minversion = 3.22
 
 [testenv]
 description = run the tests with pytest under {envname}
-passenv =
+package = wheel
+wheel_build_env = .pkg
+extras =
+    testing
+pass_env =
     PYTEST_*
     SSL_CERT_FILE
-setenv =
+set_env =
     COVERAGE_FILE = {env:COVERAGE_FILE:{toxworkdir}{/}.coverage.{envname}}
-extras =
-    testing
 commands =
     pytest {tty:--color=yes} {posargs: --no-cov-on-fail --cov-context=test \
       --cov={envsitepackagesdir}{/}pyproject_api --cov={toxinidir}{/}tests 
--cov-config={toxinidir}{/}pyproject.toml \
@@ -29,26 +32,24 @@
       --cov-report=xml:{toxworkdir}{/}coverage.{envname}.xml 
--junitxml={toxworkdir}{/}junit.{envname}.xml \
       tests}
 labels = test
-package = wheel
-wheel_build_env = .pkg
 
 [testenv:fix]
 description = run formatter and linters
-passenv =
-    {[testenv]passenv}
-    PROGRAMDATA
 skip_install = true
 deps =
-    pre-commit>=3.0.4
+    pre-commit>=3.3.3
+pass_env =
+    {[testenv]passenv}
+    PROGRAMDATA
 commands =
     pre-commit run --all-files --show-diff-on-failure {tty:--color=always} 
{posargs}
 
 [testenv:type]
 description = run type check on code base
-setenv =
-    {tty:MYPY_FORCE_COLOR = 1}
 deps =
-    mypy==0.991
+    mypy==1.4.1
+set_env =
+    {tty:MYPY_FORCE_COLOR = 1}
 commands =
     mypy src/pyproject_api --strict
     mypy tests --strict
@@ -75,7 +76,7 @@
 
 [testenv:dev]
 description = dev environment with all deps at {envdir}
-usedevelop = true
+package = editable
 extras =
     docs
     testing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pyproject_api-1.5.1/whitelist.txt 
new/pyproject_api-1.5.4/whitelist.txt
--- old/pyproject_api-1.5.1/whitelist.txt       2020-02-02 01:00:00.000000000 
+0100
+++ new/pyproject_api-1.5.4/whitelist.txt       1970-01-01 01:00:00.000000000 
+0100
@@ -1,33 +0,0 @@
-autoclass
-autodoc
-capsys
-cfg
-delenv
-exe
-extlinks
-intersphinx
-iterdir
-iwgrp
-iwoth
-iwusr
-mktemp
-namelist
-nitpicky
-outdir
-prj
-py311
-py38
-pygments
-pyproject
-readouterr
-sdist
-setenv
-srcdir
-tmpdir
-toml
-tomli
-tomllib
-typehints
-unbuffered
-virtualenv
-win32

Reply via email to