From 83dc218437c7603e6106d546c4d203a7662b7add Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sat, 1 Nov 2025 12:13:08 +0800 Subject: [PATCH 1/3] Miscellaneous config updates. --- .flake8 | 16 ---------------- .github/workflows/ci.yml | 4 ++-- .pre-commit-config.yaml | 18 +++++------------- pyproject.toml | 27 ++++++++++++++++++--------- 4 files changed, 25 insertions(+), 40 deletions(-) delete mode 100644 .flake8 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..d3a295cd 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: # 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 1e199c30..8b2c9696 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,26 +18,18 @@ repos: hooks: - id: isort additional_dependencies: [toml] - - repo: https://github.com/asottile/pyupgrade - rev: v3.20.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.1.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 a89d18f7..38c26b60 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' From c080396998a3bc2ab5eba75867fde89bb1230ddb Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sat, 1 Nov 2025 12:16:47 +0800 Subject: [PATCH 2/3] Ruff cleanups. --- .pre-commit-config.yaml | 5 ----- recipes/numpy/test_numpy.py | 4 ++-- recipes/pandas/test_pandas.py | 4 +--- src/forge/__main__.py | 3 ++- src/forge/build.py | 14 ++++++++++---- src/forge/cross.py | 24 ++++++++++++++++-------- 6 files changed, 31 insertions(+), 23 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8b2c9696..01093b6e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,11 +13,6 @@ repos: rev: v0.10.0.1 hooks: - id: shellcheck - - repo: https://github.com/PyCQA/isort - rev: 6.0.1 - hooks: - - id: isort - additional_dependencies: [toml] # Docformatter 1.7.5 isn't compatible with Pre-commit 4.0 # - repo: https://github.com/PyCQA/docformatter # rev: v1.7.5 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..da0736af 100644 --- a/recipes/pandas/test_pandas.py +++ b/recipes/pandas/test_pandas.py @@ -5,6 +5,4 @@ def test_basic(): [("alpha", 1), ("bravo", 2), ("charlie", 3)], columns=["Letter", "Number"], ) - assert df.to_csv() == ( - ",Letter,Number\n" "0,alpha,1\n" "1,bravo,2\n" "2,charlie,3\n" - ) + assert df.to_csv() == (",Letter,Number\n0,alpha,1\n1,bravo,2\n2,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): From b8138493e000dc4dd01c26a6b797ec2467d45924 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 3 Nov 2025 12:30:43 +0800 Subject: [PATCH 3/3] Correct the config to ensure there's a live test on intel. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3a295cd..12e9ea21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: 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-15-intel"