Skip to content

Commit b5dd4fb

Browse files
committed
feat: Python 3.7+
Signed-off-by: Henry Schreiner <[email protected]>
1 parent f3b4a78 commit b5dd4fb

File tree

13 files changed

+134
-70
lines changed

13 files changed

+134
-70
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
fail-fast: false
4141
matrix:
4242
include:
43-
- os: ubuntu-20.04
43+
- os: ubuntu-22.04
4444
arch: "x86_64"
4545
- os: ubuntu-22.04
4646
arch: "i686"
@@ -78,16 +78,6 @@ jobs:
7878
name: cibw-wheels-${{ matrix.os }}-${{ matrix.arch }}
7979
path: ./wheelhouse/*.whl
8080

81-
- name: Install Ubuntu Python 2.7
82-
if: matrix.os == 'ubuntu-20.04'
83-
run: |
84-
sudo apt-get update
85-
sudo apt-get install -y --no-install-recommends python2 python3-virtualenv
86-
virtualenv -p python2 ${HOME}/cp27
87-
${HOME}/cp27/bin/python -m pip install -U pip
88-
${HOME}/cp27/bin/python -m pip install -U setuptools wheel
89-
echo "${HOME}/cp27/bin" >> $GITHUB_PATH
90-
9181
- name: Test wheel on host Linux
9282
if: runner.os == 'Linux' && matrix.arch == 'x86_64'
9383
run: |

.pre-commit-config.yaml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,29 @@ repos:
1212
- id: mixed-line-ending
1313
- id: requirements-txt-fixer
1414
- id: trailing-whitespace
15-
- id: fix-encoding-pragma
1615

1716
- repo: https://github.com/astral-sh/ruff-pre-commit
1817
rev: "v0.3.4"
1918
hooks:
2019
- id: ruff
2120
args: [--fix, --show-fixes]
21+
22+
- repo: https://github.com/pre-commit/mirrors-mypy
23+
rev: "v1.10.0"
24+
hooks:
25+
- id: mypy
26+
files: src
27+
args: []
28+
29+
- repo: https://github.com/abravalheri/validate-pyproject
30+
rev: "v0.16"
31+
hooks:
32+
- id: validate-pyproject
33+
additional_dependencies: ["validate-pyproject-schema-store[all]"]
34+
35+
- repo: https://github.com/python-jsonschema/check-jsonschema
36+
rev: "0.28.2"
37+
hooks:
38+
- id: check-dependabot
39+
- id: check-github-workflows
40+
- id: check-readthedocs

CONTRIBUTING.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ Before you submit a pull request, check that it meets these guidelines:
102102
your new functionality into a function with a docstring, and add the
103103
feature to the list in `README.rst`.
104104

105-
3. The pull request should work for Python 2.7, and 3.6+.
105+
3. The pull request should work for Python 3.7+.
106106
Check `GitHub Actions`_
107107
and make sure that the tests pass for all supported Python versions.
108108

noxfile.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
# -*- coding: utf-8 -*-
1+
from __future__ import annotations
2+
23
import argparse
34
import sys
45
from pathlib import Path
56

67
import nox
78

9+
nox.needs_version = ">=2024.4.15"
10+
nox.options.default_venv_backend = "uv|virtualenv"
811
nox.options.sessions = ["lint", "build", "tests"]
912

1013
if sys.platform.startswith("darwin"):
@@ -25,7 +28,7 @@ def build(session: nox.Session) -> str:
2528
"""
2629
Make an SDist and a wheel. Only runs once.
2730
"""
28-
global built
31+
global built # noqa: PLW0603
2932
if not built:
3033
session.log(
3134
"The files produced locally by this job are not intended to be redistributable"
@@ -48,7 +51,7 @@ def lint(session: nox.Session) -> str:
4851
Run linters on the codebase.
4952
"""
5053
session.install("pre-commit")
51-
session.run("pre-commit", "run", "-a")
54+
session.run("pre-commit", "run", "-a", *session.posargs)
5255

5356

5457
@nox.session
@@ -92,7 +95,8 @@ def bump(session: nox.Session) -> None:
9295
else:
9396
version = args.version
9497

95-
session.install("requests")
98+
deps = nox.project.load_toml("scripts/update_ninja_version.py")["dependencies"]
99+
session.install(*deps)
96100

97101
extra = ["--quiet"] if args.commit else []
98102
session.run("python", "scripts/update_ninja_version.py", "--upstream-repository", args.upstream_repository, version, *extra)

pyproject.toml

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,14 @@ classifiers = [
3131
"Topic :: Software Development :: Build Tools",
3232
"Typing :: Typed",
3333
]
34+
requires-python = ">=3.7"
3435

3536
[project.optional-dependencies]
3637
test = [
3738
"coverage>=4.2",
3839
"importlib_metadata>=2.0",
39-
"pytest-cov>=2.7.1",
40-
"pytest>=4.5.0",
40+
"pytest-cov>=3",
41+
"pytest>=6.0",
4142
]
4243

4344
[project.urls]
@@ -101,41 +102,58 @@ MACOSX_DEPLOYMENT_TARGET = "10.9"
101102
select = "*-musllinux_*"
102103
environment = { LDFLAGS = "-static-libstdc++ -static-libgcc" }
103104

105+
106+
[tool.pytest.ini_options]
107+
minversion = "6.0"
108+
addopts = ["-ra", "--strict-markers", "--strict-config"]
109+
xfail_strict = true
110+
filterwarnings = ["error"]
111+
log_cli_level = "info"
112+
testpaths = [ "tests" ]
113+
114+
115+
[tool.mypy]
116+
warn_unused_configs = true
117+
files = "src"
118+
python_version = "3.8"
119+
strict = true
120+
enable_error_code = ["ignore-without-code", "truthy-bool", "redundant-expr"]
121+
warn_unreachable = true
122+
123+
104124
[tool.ruff]
105125
src = ["src"]
106126

107127
[tool.ruff.lint]
108128
extend-select = [
109-
"B", # flake8-bugbear
110-
"I", # isort
111129
"ARG", # flake8-unused-arguments
130+
"B", # flake8-bugbear
112131
"C4", # flake8-comprehensions
132+
"EXE", # flake8-executable
133+
"G", # flake8-logging-format
134+
"I", # isort
113135
"ICN", # flake8-import-conventions
114136
"ISC", # flake8-implicit-str-concat
115-
"G", # flake8-logging-format
137+
"NPY", # NumPy specific rules
138+
"PD", # pandas-vet
116139
"PGH", # pygrep-hooks
117140
"PIE", # flake8-pie
118141
"PL", # pylint
119142
"PT", # flake8-pytest-style
120143
"RET", # flake8-return
121144
"RUF", # Ruff-specific
122145
"SIM", # flake8-simplify
123-
"EXE", # flake8-executable
124-
"NPY", # NumPy specific rules
125-
"PD", # pandas-vet
146+
"UP", # pyupgrade
126147
]
127148
ignore = [
128149
"PLR", # Design related pylint codes
129150
"E501", # Line too long
130-
"RUF005", # Python 3 needed
131-
"B904", # Python 3 needed
132-
# "SIM105", # Python 3 needed
133151
]
152+
isort.required-imports = ["from __future__ import annotations"]
134153
flake8-unused-arguments.ignore-variadic-names = true
135154

136155
[tool.ruff.lint.per-file-ignores]
137156
"*.pyi" = ["ARG001"]
138-
"noxfile.py" = ["PLW0603"] # Could be fixed if Python 2 dropped
139157

140158
[tool.pytest.ini_config]
141159
testpaths = ["tests"]

scripts/repair_wheel.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
# -*- coding: utf-8 -*-
1+
from __future__ import annotations
2+
23
import argparse
34
import re
45
import shutil

scripts/update_ninja_version.py

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
# -*- coding: utf-8 -*-
1+
# /// script
2+
# dependencies = ["requests"]
3+
# ///
4+
25
"""
36
Command line executable allowing to update NinjaUrls.cmake, documentation
47
and tests given a Ninja version.
58
"""
9+
from __future__ import annotations
610

711
import argparse
812
import contextlib
@@ -12,13 +16,7 @@
1216
import tempfile
1317
import textwrap
1418

15-
try:
16-
from requests import request
17-
except ImportError:
18-
raise SystemExit(
19-
"requests not available: "
20-
"consider installing it running 'pip install requests'"
21-
)
19+
from requests import request
2220

2321
ROOT_DIR = os.path.join(os.path.dirname(__file__), "..")
2422

@@ -31,7 +29,7 @@ def _log(txt, verbose=True):
3129
print(txt)
3230
yield
3331
if verbose:
34-
print("%s - done" % txt)
32+
print(f"{txt} - done")
3533

3634

3735
def _download_file(download_url, filename):
@@ -67,7 +65,7 @@ def _hash_sum(filepath, algorithm="sha256", block_size=2 ** 20):
6765

6866
def _download_and_compute_sha256(url, filename):
6967
filepath = os.path.join(tempfile.gettempdir(), filename)
70-
with _log("Downloading %s" % url):
68+
with _log(f"Downloading {url}"):
7169
_download_file(url, filepath)
7270
sha256 = _hash_sum(filepath, algorithm="sha256")
7371
return url, sha256
@@ -77,7 +75,7 @@ def get_ninja_archive_urls_and_sha256s(upstream_repository, version, verbose=Fal
7775
tag_name = f"v{version}"
7876
files_base_url = f"https://github.com/{upstream_repository}/archive/{tag_name}"
7977

80-
with _log("Collecting URLs and SHA256s from '%s'" % files_base_url):
78+
with _log(f"Collecting URLs and SHA256s from '{files_base_url}'"):
8179

8280
# Get SHA256s and URLs
8381
urls = {
@@ -87,7 +85,7 @@ def get_ninja_archive_urls_and_sha256s(upstream_repository, version, verbose=Fal
8785

8886
if verbose:
8987
for identifier, (url, sha256) in urls.items():
90-
print("[{}]\n{}\n{}\n".format(identifier, url, sha256))
88+
print(f"[{identifier}]\n{url}\n{sha256}\n")
9189

9290
return urls
9391

@@ -97,8 +95,8 @@ def generate_cmake_variables(urls_and_sha256s):
9795

9896
# Get SHA256s and URLs
9997
for var_prefix, urls_and_sha256s_values in urls_and_sha256s.items():
100-
template_inputs["%s_url" % var_prefix] = urls_and_sha256s_values[0]
101-
template_inputs["%s_sha256" % var_prefix] = urls_and_sha256s_values[1]
98+
template_inputs[f"{var_prefix}_url"] = urls_and_sha256s_values[0]
99+
template_inputs[f"{var_prefix}_sha256"] = urls_and_sha256s_values[1]
102100

103101
return textwrap.dedent(
104102
"""
@@ -118,16 +116,16 @@ def update_cmake_urls_script(upstream_repository, version):
118116
cmake_urls_filename = "NinjaUrls.cmake"
119117
cmake_urls_filepath = os.path.join(ROOT_DIR, cmake_urls_filename)
120118

121-
msg = "Updating '{}' with Ninja version {}".format(cmake_urls_filename, version)
119+
msg = f"Updating '{cmake_urls_filename}' with Ninja version {version}"
122120
with _log(msg), open(cmake_urls_filepath, "w") as cmake_file:
123121
cmake_file.write(content)
124122

125123

126124
def _update_file(filepath, regex, replacement, verbose=True):
127-
msg = "Updating %s" % os.path.relpath(filepath, ROOT_DIR)
125+
msg = f"Updating {os.path.relpath(filepath, ROOT_DIR)}"
128126
with _log(msg, verbose=verbose):
129127
pattern = re.compile(regex)
130-
with open(filepath, "r") as doc_file:
128+
with open(filepath) as doc_file:
131129
lines = doc_file.readlines()
132130
updated_content = []
133131
for line in lines:
@@ -138,7 +136,7 @@ def _update_file(filepath, regex, replacement, verbose=True):
138136

139137
def update_docs(upstream_repository, version):
140138
pattern = re.compile(r"ninja \d+.\d+.\d+(\.[\w\-]+)*")
141-
replacement = "ninja %s" % version
139+
replacement = f"ninja {version}"
142140
_update_file(
143141
os.path.join(ROOT_DIR, "README.rst"),
144142
pattern, replacement)
@@ -171,7 +169,7 @@ def update_tests(version):
171169
version = ".".join(parts)
172170

173171
pattern = re.compile(r'expected_version = "\d+.\d+.\d+(\.[\w\-]+)*"')
174-
replacement = 'expected_version = "%s"' % version
172+
replacement = f'expected_version = "{version}"'
175173
_update_file(os.path.join(
176174
ROOT_DIR, "tests/test_ninja.py"), pattern, replacement)
177175

src/ninja/__init__.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
1-
# -*- coding: utf-8 -*-
1+
from __future__ import annotations
2+
23
import os
34
import subprocess
45
import sys
56
import sysconfig
7+
from collections.abc import Iterable
8+
from typing import NoReturn
69

710
from ._version import version as __version__
811
from .ninja_syntax import Writer, escape, expand
912

1013
__all__ = ["__version__", "DATA", "BIN_DIR", "ninja", "Writer", "escape", "expand"]
1114

1215

13-
def __dir__():
16+
def __dir__() -> list[str]:
1417
return __all__
1518

1619

17-
def _get_ninja_dir():
20+
def _get_ninja_dir() -> str:
1821
ninja_exe = "ninja" + sysconfig.get_config_var("EXE")
1922

2023
# Default path
@@ -27,7 +30,7 @@ def _get_ninja_dir():
2730
user_scheme = sysconfig.get_preferred_scheme("user")
2831
elif os.name == "nt":
2932
user_scheme = "nt_user"
30-
elif sys.platform.startswith("darwin") and sys._framework:
33+
elif sys.platform.startswith("darwin") and getattr(sys, "_framework", None):
3134
user_scheme = "osx_framework_user"
3235
else:
3336
user_scheme = "posix_user"
@@ -47,10 +50,11 @@ def _get_ninja_dir():
4750

4851
BIN_DIR = _get_ninja_dir()
4952

50-
def _program(name, args):
53+
54+
def _program(name: str, args: Iterable[str]) -> int:
5155
cmd = os.path.join(BIN_DIR, name)
52-
return subprocess.call([cmd] + args, close_fds=False)
56+
return subprocess.call([cmd, *args], close_fds=False)
5357

5458

55-
def ninja():
59+
def ninja() -> NoReturn:
5660
raise SystemExit(_program('ninja', sys.argv[1:]))

src/ninja/__init__.pyi

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/ninja/__main__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
# -*- coding: utf-8 -*-
1+
from __future__ import annotations
2+
23
from ninja import ninja
34

45
if __name__ == '__main__':

0 commit comments

Comments
 (0)