diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 94fbdfe5..00000000 --- a/.flake8 +++ /dev/null @@ -1,16 +0,0 @@ -# flake8 doesn't allow for pyproject.toml configuration. -[flake8] -# https://flake8.readthedocs.org/en/latest/ -exclude=\ - venv*/*,\ - local/*,\ - docs/*,\ - build/*,\ - tests/apps/*,\ - .eggs/*,\ - .tox/* -max-line-length = 119 -extend-ignore = - # whitespace before : - # See https://github.com/PyCQA/pycodestyle/issues/373 - E203, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97ee4564..12e9ea21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,13 +30,13 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ] + python-version: [ "3.10", "3.11", "3.12", "3.13" ] runs-on: [ "macos-latest" ] - exclude: + include: # Don't need to run x86 tests on every Python version - python-version: "3.13" - runs-on: "macos-13" + runs-on: "macos-15-intel" steps: - name: Checkout diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4b75309e..8609db37 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,31 +13,18 @@ repos: rev: v0.11.0.1 hooks: - id: shellcheck - - repo: https://github.com/PyCQA/isort - rev: 7.0.0 - hooks: - - id: isort - additional_dependencies: [toml] - - repo: https://github.com/asottile/pyupgrade - rev: v3.21.0 - hooks: - - id: pyupgrade - args: [--py39-plus] # Docformatter 1.7.5 isn't compatible with Pre-commit 4.0 # - repo: https://github.com/PyCQA/docformatter # rev: v1.7.5 # hooks: # - id: docformatter # args: [--in-place, --black] - - repo: https://github.com/psf/black-pre-commit-mirror - rev: 25.9.0 - hooks: - - id: black - language_version: python3 - - repo: https://github.com/PyCQA/flake8 - rev: 7.3.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.14.2 hooks: - - id: flake8 + - id: ruff-format + - id: ruff-check + args: [ --fix ] - repo: https://github.com/codespell-project/codespell rev: v2.4.1 hooks: diff --git a/pyproject.toml b/pyproject.toml index 05de5cbc..6dc69f4e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "mobile-forge" version = "2024.0.0" description = "A tool to manage building cross-platform binary wheels for mobile devices" readme = { file = "README.md", content-type = "text/x-rst"} -requires-python = ">=3.9" +requires-python = ">=3.10" license = { file = "LICENSE" } authors = [ {name = "Russell Keith-Magee", email = "russell@keith-magee.com"} @@ -20,10 +20,10 @@ classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3 :: Only", "Topic :: Software Development", ] @@ -54,14 +54,23 @@ Tracker = "https://github.com/beeware/briefcase/issues" forge = "forge.__main__:main" forge-env = "forge.cross:main" -[tool.isort] -profile = "black" -skip_glob = [ - "docs/conf.py", - "venv*", - "local", +[tool.ruff.lint] +# In addition to the default rules, these additional rules will be used: +extend-select = [ + "E", # pycodestyle + "W", # pycodestyle + "F", # pyflakes + "UP", # pyupgrade + "B", # flake8-bugbear + "YTT", # flake8-2020 + "ASYNC", # flake8-async + "C4", # flake8-comprehensions + "I", # isort + # The SIM rules are *very* opinionated, and don't necessarily make for better code. + # They may be worth occasionally turning on just to see if something could actually + # use improvement. + # "SIM", # flake8-simplify ] -multi_line_output = 3 [tool.codespell] skip = '.git,*.pdf,*.svg' diff --git a/recipes/numpy/test_numpy.py b/recipes/numpy/test_numpy.py index ee7122bf..ba133d66 100644 --- a/recipes/numpy/test_numpy.py +++ b/recipes/numpy/test_numpy.py @@ -15,8 +15,8 @@ def test_performance(): b = np.random.rand(SIZE, SIZE) np.dot(a, b) - # With OpenBLAS, the test devices take at most 0.4 seconds. Without OpenBLAS, they take - # at least 1.0 seconds. + # With OpenBLAS, the test devices take at most 0.4 seconds. + # Without OpenBLAS, they take at least 1.0 seconds. duration = time() - start_time print(f"{duration:.3f}") assert duration < 0.7 diff --git a/recipes/pandas/test_pandas.py b/recipes/pandas/test_pandas.py index f1c703e8..9708408a 100644 --- a/recipes/pandas/test_pandas.py +++ b/recipes/pandas/test_pandas.py @@ -6,5 +6,8 @@ def test_basic(): columns=["Letter", "Number"], ) assert df.to_csv() == ( - ",Letter,Number\n" "0,alpha,1\n" "1,bravo,2\n" "2,charlie,3\n" + ",Letter,Number\n", + "0,alpha,1\n", + "1,bravo,2\n", + "2,charlie,3\n", ) diff --git a/src/forge/__main__.py b/src/forge/__main__.py index 4c86fc00..6d7b949a 100644 --- a/src/forge/__main__.py +++ b/src/forge/__main__.py @@ -230,7 +230,8 @@ def main() -> int: # subsequent builds will be isolated by first = True - # Packages that generate -py3-none-any wheels only need to be built on a single platform. + # Packages that generate -py3-none-any wheels only need to be built + # on a single platform. if package_name_or_recipe in py_any_targets: build_platforms = platforms[:1] else: diff --git a/src/forge/build.py b/src/forge/build.py index 3f458647..9ca24072 100644 --- a/src/forge/build.py +++ b/src/forge/build.py @@ -221,11 +221,13 @@ def compile_env(self, **kwargs) -> dict[str:str]: cflags = self.cross_venv.sysconfig_data["CFLAGS"] - # Pre Python 3.11 versions included BZip2 and XZ includes in CFLAGS. Remove them. + # Pre Python 3.11 versions included BZip2 and XZ includes in CFLAGS. + # The should be removed. cflags = re.sub(r"-I.*/merge/iOS/.*/bzip2-.*/include", "", cflags) cflags = re.sub(r"-I.*/merge/iOS/.*/xs-.*/include", "", cflags) - # Replace any hard-coded reference to --sysroot= with the actual reference + # Replace any hard-coded reference to --sysroot= + # with the actual reference cflags = re.sub(r"--sysroot=\w+", f"--sysroot={sdk_root}", cflags) # Add the install root and SDK root includes @@ -240,7 +242,8 @@ def compile_env(self, **kwargs) -> dict[str:str]: ldflags = self.cross_venv.sysconfig_data["LDFLAGS"] - # Replace any hard-coded reference to -isysroot with the actual reference + # Replace any hard-coded reference to -isysroot + # with the actual reference ldflags = re.sub(r"-isysroot \w+", f"-isysroot={sdk_root}", ldflags) # Add the framework path @@ -489,7 +492,10 @@ def log_file_path(self) -> Path: return ( Path.cwd() / "logs" - / f"{self.package.name}-{self.package.version}-cp3{sys.version_info.minor}-{self.cross_venv.tag}.log" + / ( + f"{self.package.name}-{self.package.version}-" + f"cp3{sys.version_info.minor}-{self.cross_venv.tag}.log" + ) ) def download_source_url(self): diff --git a/src/forge/cross.py b/src/forge/cross.py index e1b9ffda..88c755ad 100644 --- a/src/forge/cross.py +++ b/src/forge/cross.py @@ -244,8 +244,10 @@ def create( ], **self.cross_kwargs({}), ) - except subprocess.CalledProcessError: - raise RuntimeError(f"Unable to create cross platform environment {self}.") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"Unable to create cross platform environment {self}." + ) from e print("Verifying cross-platform environment...") self.verify() @@ -294,7 +296,8 @@ def verify(self): ).strip() if output != self.platform_identifier: raise RuntimeError( - f"Cross platform python should be {self.platform_identifier}; got {output}" + f"Cross platform python should be {self.platform_identifier}; " + f"got {output}" ) # python is the same version as the local python @@ -305,7 +308,8 @@ def verify(self): ).strip() if python_version != local_python_version: raise RuntimeError( - f"Cross platform python should be {local_python_version!r}; got {python_version!r}" + f"Cross platform python should be {local_python_version!r}; " + f"got {python_version!r}" ) # build-python returns the build environment tag. @@ -315,7 +319,8 @@ def verify(self): ).strip() if output != sysconfig.get_platform(): raise RuntimeError( - f"Cross platform build-python should be {sysconfig.get_platform()}; got {output}" + f"Cross platform build-python should be {sysconfig.get_platform()}; " + f"got {output}" ) # build-python is the same version as the local python @@ -325,7 +330,8 @@ def verify(self): ).strip() if build_python_version != local_python_version: raise RuntimeError( - f"Cross platform build-python should be {local_python_version}; got {build_python_version}" + f"Cross platform build-python should be {local_python_version}; " + f"got {build_python_version}" ) # cross-python returns the cross-platform host tag. @@ -335,7 +341,8 @@ def verify(self): ).strip() if output != self.platform_identifier: raise RuntimeError( - f"Cross platform cross-python should be {self.platform_identifier}; got {output}" + f"Cross platform cross-python should be {self.platform_identifier}; " + f"got {output}" ) # cross-python is the same version as the local python @@ -345,7 +352,8 @@ def verify(self): ).strip() if cross_python_version != local_python_version: raise RuntimeError( - f"Cross platform python should be {local_python_version}; got {cross_python_version}" + f"Cross platform python should be {local_python_version}; " + f"got {cross_python_version}" ) def cross_kwargs(self, kwargs):