From 52842c0aeae82e6663475686a482a5b705b638bf Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Fri, 19 Jun 2026 10:10:06 -0700 Subject: [PATCH] Update gitcommit to 2.12 Signed-off-by: Tom Rix --- ...duce-polyfill-signature-mismatch-on-.patch | 110 ++++++++++++++++++ ...polyfill-signature-mismatch-on-Pytho.patch | 64 ++++++++++ inject.py | 44 +++++++ pyproject.toml | 102 +++++++++------- python-torch.spec | 50 ++++++-- 5 files changed, 323 insertions(+), 47 deletions(-) create mode 100644 0001-Fix-functools.reduce-polyfill-signature-mismatch-on-.patch create mode 100644 0001-Fix-struct.pack-polyfill-signature-mismatch-on-Pytho.patch create mode 100755 inject.py diff --git a/0001-Fix-functools.reduce-polyfill-signature-mismatch-on-.patch b/0001-Fix-functools.reduce-polyfill-signature-mismatch-on-.patch new file mode 100644 index 0000000..52748b4 --- /dev/null +++ b/0001-Fix-functools.reduce-polyfill-signature-mismatch-on-.patch @@ -0,0 +1,110 @@ +From a377729dc7fb711e43c0f59829580cc9c3f0522e Mon Sep 17 00:00:00 2001 +From: jassad095 +Date: Mon, 1 Jun 2026 05:06:50 +0000 +Subject: [PATCH] Fix functools.reduce polyfill signature mismatch on Python + 3.15 (#185682) + +## Summary + +Python 3.15 will expose an introspectable signature for `functools.reduce` using a PEP 661 sentinel default: `(function, iterable, /, initial=functools._initial_missing)`. The CPython change is [#149591](https://github.com/python/cpython/pull/149591), which merged into CPython main on 2026-05-10, after 3.15.0b1 was tagged. So on 3.15.0b1 the default is still `` and `inspect.signature()` raises `ValueError`, which `substitute_in_graph` swallows and skips the check. From 3.15.0b2 the check will run. + +When it runs, it compares positional parameter names, keyword-only names, and default values. The polyfill declares its own local sentinel: + +```python +_initial_missing = object() + +@substitute_in_graph(functools.reduce) +def reduce(function, iterable, initial=_initial_missing, /): + ... +``` + +That local `object()` is a different instance from `functools._initial_missing`, so the defaults dict compares unequal and `substitute_in_graph` raises: + +``` +File ".../torch/_dynamo/polyfills/functools.py", line N, in + @substitute_in_graph(functools.reduce) +TypeError: Signature mismatch between and : + (function, iterable, /, initial=_initial_missing) + != (function, iterable, initial=, /) +``` + +The polyfills loader imports every polyfill module, so this will break `import torch._dynamo` entirely on Python 3.15.0b2+. Same failure mode as #185403's `struct.pack` fix, just one step ahead of the next beta. + +The fix imports `functools._initial_missing` instead of declaring a local one. The polyfill's internal `if initial is _initial_missing` identity check still works because both sides now reference the same object. No behavior change on any Python version. `functools._initial_missing` has existed in `functools` since well before 3.10 (it's used by the pure-Python `functools.reduce` fallback), so the import is safe on every supported version. + +Part of #184352 (Python 3.15 support). Similar to #185403. + +## Test plan + +Verified on a locally-built Python 3.15-dev (CPython main at `heads/3.15:863c7e0`, which includes [#149591](https://github.com/python/cpython/pull/149591)). The upstream signature is exposed natively: + +``` +$ python3.15 -c "import functools, inspect; print(inspect.signature(functools.reduce))" +(function, iterable, /, initial=_initial_missing) +$ python3.15 -c "import functools, inspect; sig = inspect.signature(functools.reduce); print(sig.parameters['initial'].default is functools._initial_missing)" +True +``` + +Extracted the actual `substitute_in_graph` from `torch/_dynamo/decorators.py` and ran it against both polyfill versions with no monkey-patching. + +Unmodified polyfill (`_initial_missing = object()` declared locally): + +``` +TypeError: Signature mismatch between and : + (function, iterable, /, initial=_initial_missing) + != (function, iterable, initial=, /) +``` + +Fixed polyfill (`from functools import _initial_missing`): no `TypeError` at the signature check. + +Regression on Python 3.12.13 (oldest currently supported): + +``` +$ python3 -c "import inspect, functools; inspect.signature(functools.reduce)" +ValueError: no signature found for builtin +``` + +The signature check is silently skipped on Python <= 3.14, so the fix is a no-op there. `functools._initial_missing` is confirmed present on 3.12.13. Eager-vs-polyfill parity verified on every input shape: + +``` +reduce(lambda a, b: a+b, [1,2,3,4]) == 10 (matches functools.reduce) +reduce(lambda a, b: a+b, [1,2,3], 100) == 106 (matches) +reduce(lambda a, b: a+b, []) -> TypeError("reduce() of empty iterable with no initial value") (matches) +reduce(lambda a, b: a+b, [], 99) == 99 (matches) +``` + +Pre-commit checks: `python3 -m py_compile torch/_dynamo/polyfills/functools.py` and `git diff --staged --check` both clean. + +Pull Request resolved: https://github.com/pytorch/pytorch/pull/185682 +Approved by: https://github.com/ezyang + +Co-authored-by: Edward Z. Yang via mergedog +--- + torch/_dynamo/polyfills/functools.py | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/torch/_dynamo/polyfills/functools.py b/torch/_dynamo/polyfills/functools.py +index 6458b8080f93..9ba14888056b 100644 +--- a/torch/_dynamo/polyfills/functools.py ++++ b/torch/_dynamo/polyfills/functools.py +@@ -4,6 +4,7 @@ Python polyfills for functools + + import functools + from collections.abc import Callable, Iterable ++from functools import _initial_missing # type: ignore[attr-defined] + from typing import TypeVar + + from ..decorators import substitute_in_graph +@@ -16,9 +17,6 @@ _T = TypeVar("_T") + _U = TypeVar("_U") + + +-_initial_missing = object() +- +- + # Reference: https://docs.python.org/3/library/functools.html#functools.reduce + @substitute_in_graph(functools.reduce) + def reduce( +-- +2.53.0 + diff --git a/0001-Fix-struct.pack-polyfill-signature-mismatch-on-Pytho.patch b/0001-Fix-struct.pack-polyfill-signature-mismatch-on-Pytho.patch new file mode 100644 index 0000000..8f20a7b --- /dev/null +++ b/0001-Fix-struct.pack-polyfill-signature-mismatch-on-Pytho.patch @@ -0,0 +1,64 @@ +From 7b9106b6c4c1da71e30e7e63b2248b01c61a3210 Mon Sep 17 00:00:00 2001 +From: Klaus Zimmermann +Date: Fri, 29 May 2026 17:56:12 +0000 +Subject: [PATCH] Fix struct.pack polyfill signature mismatch on Python 3.15 + (#185403) + +## Summary + +Python 3.15 gives the builtin `struct.pack` an introspectable signature, `(format, /, *values)`. `substitute_in_graph` validates that a polyfill's signature matches the original builtin's, comparing positional-only parameter names. The `struct.pack` polyfill declared its positional-only parameter as `fmt`, mismatching `format`, so `substitute_in_graph` raised `TypeError` at import time: + +``` +File ".../torch/_dynamo/polyfills/struct.py", line 20, in + @substitute_in_graph(struct.pack, can_constant_fold_through=True) +TypeError: Signature mismatch between and : + (format, /, *values) != (fmt: 'bytes | str', /, *v: 'Any') -> 'bytes' +``` + +The polyfills loader eagerly imports every polyfill module, so this broke `import torch._dynamo` entirely on 3.15, failing every py3.15/3.15t binary test job (the smoke test imports `torch._dynamo`). On Python <= 3.14 the builtin has no introspectable signature, so the check is skipped and the mismatch went unnoticed. + +The fix renames the parameter to `format` to match the builtin. The sibling `unpack` polyfill already uses `format`. The var-positional name (`*v`) is irrelevant here because `substitute_in_graph` ignores `VAR_POSITIONAL` parameter names. + +Part of #184352 (Python 3.15 support). + +## Test plan + +Local introspection confirms there is no regression on older Pythons and that `format` is the canonical name where a signature is exposed: + +``` +$ python --version +Python 3.10.19 +$ python -c "import inspect, struct; print(inspect.signature(struct.pack))" +ValueError: no signature found for builtin +$ python -c "import inspect, struct; print(inspect.signature(struct.unpack))" +(format, buffer, /) +``` + +On <= 3.14 `struct.pack` has no signature, so the `substitute_in_graph` check is skipped and the rename is a no-op there. The 3.15 failure reproduces only in the py3.15 binary smoke test (`manywheel-py3_15-*-test`); needs `ciflow/binaries` to validate. + +Authored by Claude. + +Pull Request resolved: https://github.com/pytorch/pytorch/pull/185403 +Approved by: https://github.com/guilhermeleobas, https://github.com/rtimpe +--- + torch/_dynamo/polyfills/struct.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/torch/_dynamo/polyfills/struct.py b/torch/_dynamo/polyfills/struct.py +index f4522a12f732..4077a7f05788 100644 +--- a/torch/_dynamo/polyfills/struct.py ++++ b/torch/_dynamo/polyfills/struct.py +@@ -18,8 +18,8 @@ __all__ = [ + + + @substitute_in_graph(struct.pack, can_constant_fold_through=True) # type: ignore[arg-type] +-def pack(fmt: bytes | str, /, *v: Any) -> bytes: +- return struct.pack(fmt, *v) ++def pack(format: bytes | str, /, *v: Any) -> bytes: ++ return struct.pack(format, *v) + + + @substitute_in_graph(struct.unpack, can_constant_fold_through=True) # type: ignore[arg-type] +-- +2.53.0 + diff --git a/inject.py b/inject.py new file mode 100755 index 0000000..94da392 --- /dev/null +++ b/inject.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +""" +inject_build_options.py + +Runtime stub for injecting PyTorch CMake build flags. +Designed to be called pre-build (e.g., via a wrapper script or sitecustomize.py). +""" +import os +from typing import Dict, Any + +def read_environment() -> Dict[str, str]: + """Reads and prints environment variables in dictionary format.""" + # Using double quotes to match the MOCK_DEFAULTS dictionary style exactly + print("# Current Environment Variables (Formatted for injection):") + use_variables: Dict[str, Any] = {} + + for key in sorted(os.environ.keys()): + if key.startswith("USE_") or key.startswith("CMAKE_") : + value = os.environ[key] + print(f' "{key}": "{value}",') + use_variables[key] = value + return use_variables + +def build_options(build_options: Dict[str, Any]) -> Dict[str, Any] : + """ + Injects build configuration into the PyTorch CMake build process. + + """ + options = read_environment() + build_options.update(options) + return build_options + +if __name__ == "__main__": + MOCK_DEFAULTS = { + # Core CMake + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_FIND_PACKAGE_PREFER_CONFIG": "ON", + "CAFFE2_LINK_LOCAL_PROTOBUF": "OFF", + } + + new_options = build_options(MOCK_DEFAULTS) + + for key in new_options: + print(f"{key}: {new_options[key]}") diff --git a/pyproject.toml b/pyproject.toml index 925742b..73867a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ requires = [ # 70.1.0: min version for integrated bdist_wheel command from wheel package # 77.0.0: min version for SPDX expression support for project.license - "setuptools>=70.1.0,<80.0", + "setuptools>=70.1.0,<82", "cmake>=3.27", "ninja", "numpy", @@ -45,7 +45,7 @@ dev = [ "optree>=0.13.0", "psutil", "sympy>=1.13.3", - "typing-extensions>=4.13.2", + "typing-extensions>=4.15.0", "wheel", ] @@ -115,6 +115,10 @@ multi_line_output = 3 include_trailing_comma = true combine_as_imports = true +[tool.usort] +preserve_inline_comments = true +collapse_blank_lines_in_category = false + [tool.usort.known] first_party = ["caffe2", "torch", "torchgen", "functorch", "test"] standard_library = ["typing_extensions"] @@ -122,6 +126,10 @@ standard_library = ["typing_extensions"] [tool.ruff] line-length = 88 src = ["caffe2", "torch", "torchgen", "functorch", "test"] +extend-exclude = ["third_party", "test/dynamo/cpython"] + +[tool.ruff.per-file-target-version] +"**/py312_intrinsics.py" = "py312" [tool.ruff.format] docstring-code-format = true @@ -130,21 +138,29 @@ quote-style = "double" [tool.ruff.lint] # NOTE: Synchoronize the ignores with .flake8 external = [ - "B001", - "B902", - "B950", - "E121", - "E122", - "E128", - "E131", - "E704", - "E723", - "F723", - "F812", + # Codes from flake8-only plugins that ruff doesn't implement. "P201", "P204", "T484", "TOR901", + # Codes that are preview-only in ruff, so flake8 is still the enforcer. + # As ruff promotes these out of preview, move them to flake8's ignore list. + "B901", + "B909", + "E115", + "E201", + "E221", + "E225", + "E226", + "E227", + "E231", + "E241", + "E261", + "E262", + "E265", + "E266", + "E272", + "E306", ] ignore = [ # these ignores are from flake8-bugbear; please fix! @@ -155,13 +171,10 @@ ignore = [ "E402", "C408", # C408 ignored because we like the dict keyword argument syntax "E501", # E501 is not flexible enough, we're using B950 instead - "E721", "E741", "EXE001", "F405", "FURB122", # writelines - # these ignores are from flake8-logging-format; please fix! - "G101", # these ignores are from ruff NPY; please fix! "NPY002", # these ignores are from ruff PERF; please fix! @@ -175,22 +188,14 @@ ignore = [ "SIM102", "SIM103", "SIM112", # flake8-simplify code styles "SIM105", # these ignores are from flake8-simplify. please fix or ignore with commented reason "SIM108", # SIM108 ignored because we prefer if-else-block instead of ternary expression - "SIM110", + "SIM110", # Checks for for loops that can be replaced with a builtin function, like any or all. "SIM114", # Combine `if` branches using logical `or` operator - "SIM115", "SIM116", # Disable Use a dictionary instead of consecutive `if` statements "SIM117", - "SIM118", - "UP007", # keep-runtime-typing - "UP045", # keep-runtime-typing + "SIM300", # Yoda condition detected "TC006", # TODO: Remove Python-3.10 specific suppressions "B905", - "UP035", - "UP036", - "UP038", - "UP041", - "FURB161", ] select = [ "B", @@ -200,8 +205,7 @@ select = [ "E", "EXE", "F", - "SIM1", - "SIM911", + "SIM", "W", # Not included in flake8 "FURB", @@ -209,21 +213,19 @@ select = [ "NPY", "PERF", "PGH004", - "PIE790", - "PIE794", - "PIE800", - "PIE804", - "PIE807", - "PIE810", + "PIE", "PLC0131", # type bivariance "PLC0132", # type param mismatch + "PLC1802", # len({expression}) used as condition without comparison "PLC0205", # string as __slots__ "PLC3002", # unnecessary-direct-lambda-call + "PLC0414", # Import alias does not rename original package "PLE", "PLR0133", # constant comparison "PLR0206", # property with params "PLR1722", # use sys exit "PLR1736", # unnecessary list index + "PLW0127", # Self-assignment of variable "PLW0129", # assert on string literal "PLW0131", # named expr without context "PLW0133", # useless exception statement @@ -246,6 +248,7 @@ select = [ "Q003", # avoidable escaped quote "Q004", # unnecessary escaped quote "RSE", + "RUF007", # pairwise over zip "RUF008", # mutable dataclass default "RUF013", # ban implicit optional "RUF015", # access first ele in constant time @@ -269,12 +272,9 @@ select = [ "TRY401", # verbose-log-message "UP", "YTT", + "S101", ] -[tool.ruff.lint.pyupgrade] -# Preserve types, even if a file imports `from __future__ import annotations`. -keep-runtime-typing = true - [tool.ruff.lint.per-file-ignores] "__init__.py" = [ "F401", @@ -284,11 +284,11 @@ keep-runtime-typing = true "PYI021", # docstring-in-stub "PYI053", # string-or-bytes-too-long ] -"functorch/notebooks/**" = [ +"functorch/docs/source/tutorials/**" = [ "F401", ] "test/export/**" = [ - "PGH004" + "PGH004", ] "test/typing/**" = [ "PGH004" @@ -349,5 +349,27 @@ keep-runtime-typing = true "LOG015" # please fix ] +# torch/ folders still needing S101 migration +"torch/_dynamo/**" = ["S101"] +"torch/_inductor/**" = ["S101"] + [tool.codespell] ignore-words = "tools/linter/dictionary.txt" + +[tool.spin] +package = 'torch' + +[tool.spin.commands] +"Build" = [ + ".spin/cmds.py:clean", + ".spin/cmds.py:lint", + ".spin/cmds.py:fixlint", + ".spin/cmds.py:quicklint", + ".spin/cmds.py:quickfix", +] +"Regenerate" = [ + ".spin/cmds.py:regenerate_version", + ".spin/cmds.py:regenerate_type_stubs", + ".spin/cmds.py:regenerate_clangtidy_files", + ".spin/cmds.py:regenerate_github_workflows", +] diff --git a/python-torch.spec b/python-torch.spec index 94dd90e..879d843 100644 --- a/python-torch.spec +++ b/python-torch.spec @@ -6,15 +6,14 @@ # So pre releases can be tried %bcond_with gitcommit %if %{with gitcommit} -# v2.11.0-rc6 (really v2.11) -%global commit0 70d99e998b4955e0049d13a98d77ae1b14db1f45 +# v2.12.0 (really v2.12) +%global commit0 0d62256a2b23365f8e1604297eb23a6545102aa8 %global shortcommit0 %(c=%{commit0}; echo ${c:0:7}) -%global date0 20260320 -%global pypi_version 2.11.0 +%global date0 20260511 +%global pypi_version 2.12.0 %global flatbuffers_version 24.12.23 %global miniz_version 3.0.2 %global pybind11_version 3.0.1 -%global rc_tag -rc6 %else %global pypi_version 2.11.0 %global flatbuffers_version 24.12.23 @@ -53,8 +52,12 @@ %if 0%{?fedora} %bcond_without eigen3 %bcond_without onnx +%if %{with gitcommit} +%bcond_with protobuf +%else %bcond_without protobuf -%bcond_without setuptools +%endif +%bcond_with setuptools %bcond_without sympy %else %bcond_with eigen3 @@ -79,6 +82,12 @@ URL: https://pytorch.org/ %if %{with gitcommit} Source0: %{forgeurl}/archive/%{commit0}/pytorch-%{shortcommit0}.tar.gz Source1000: pyproject.toml +Source1001: inject.py + +# Problems with python 3.15 +Patch1: 0001-Fix-functools.reduce-polyfill-signature-mismatch-on-.patch +Patch2: 0001-Fix-struct.pack-polyfill-signature-mismatch-on-Pytho.patch + %else Source0: %{forgeurl}/releases/download/v%{version}/pytorch-v%{version}.tar.gz %endif @@ -108,7 +117,11 @@ Source70: https://github.com/yhirose/cpp-httplib/archive/%{hl_commit}/cpp- %endif %if %{without kineto} +%if %{with gitcommit} +%global ki_commit b2103f78d13fde4937af010c0ef8e24313568bc5 +%else %global ki_commit 7a731b6ae01cfc2b1fc75d83a91f84e682e43fd7 +%endif %global ki_scommit %(c=%{ki_commit}; echo ${c:0:7}) Source80: https://github.com/pytorch/kineto/archive/%{ki_commit}/kineto-%{ki_scommit}.tar.gz %endif @@ -217,6 +230,9 @@ BuildRequires: ninja-build %endif %if %{with rocm} +%if %{with gitcommit} +BuildRequires: amdsmi-devel +%endif BuildRequires: hipblas-devel BuildRequires: hipblaslt-devel BuildRequires: hipcub-devel @@ -313,6 +329,21 @@ Requires: python3-%{pypi_name}%{?_isa} = %{version}-%{release} # Overwrite with a git checkout of the pyproject.toml cp %{SOURCE1000} . +# to fix handling of environment variable +# comment out broken +sed -i -e 's@include(cmake/EnvVarForwarding.cmake)@#include(cmake/EnvVarForwarding.cmake)@' CMakeLists.txt +# copy new environment reading function in +cp %{SOURCE1001} tools/setup_helpers/ +# patch in the function +sed -i '/import sysconfig.*/afrom . import inject' tools/setup_helpers/cmake.py +# patch in the call +sed -i -E 's@# NVSHMEM .*@inject.build_options(build_options)@' tools/setup_helpers/cmake.py + +# System setuptools is too new +sed -i -e 's@setuptools>=70.1.0,<82@setuptools@' pyproject.toml +sed -i -e 's@setuptools>=70.1.0,<82@setuptools@' requirements-build.txt +sed -i -e 's@setuptools<82@setuptools@' setup.py + %else %autosetup -p1 -n pytorch-v%{version} @@ -577,6 +608,9 @@ sed -i -e 's@HIP 1.0@HIP MODULE@' cmake/public/LoadHIP.cmake # moodycamel include path needs adjusting to use the system's sed -i -e 's@${PROJECT_SOURCE_DIR}/third_party/concurrentqueue@/usr/include/concurrentqueue@' cmake/Dependencies.cmake +# Do not default on MSLK +sed -i -e 's@USE_MSLK_DEFAULT ON@USE_MSLK_DEFAULT OFF@' CMakeLists.txt + %build # Export the arches @@ -651,6 +685,7 @@ export USE_MSLK=OFF export USE_NCCL=OFF export USE_NNPACK=OFF export USE_NUMPY=ON +export USE_NVSHMEM=OFF export USE_OPENMP=ON export USE_PYTORCH_QNNPACK=OFF export USE_ROCM=OFF @@ -705,7 +740,8 @@ export ROCM_PATH=`hipconfig -R` # pytorch uses clang, not hipcc export HIP_CLANG_PATH=%{rocmllvm_bindir} -export PYTORCH_ROCM_ARCH=%{rocm_gpu_list_default} +# export PYTORCH_ROCM_ARCH=%{rocm_gpu_list_default} +export PYTORCH_ROCM_ARCH=gfx1151 %endif