Skip to content

Commit

Permalink
gh-39251: Require Python 3.11 or newer; remove outdated workarounds
Browse files Browse the repository at this point in the history
    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes #12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes #12345". -->

In line with Spec 0, we remove support for Python 3.9 and 3.10. Many
outdated patches/workarounds for these older (or even older) Python
versions are removed, but I cannot guarantee that I've found all
obsolete ones. Nothing in sage-the-distro is touched.

For next years cleaning job:
- Search for `3.11`, `311`, `PY_VERSION`, `PY_MINOR_VERSION` and
`sys.version_info`
- Change version in `pyproject.toml`


### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->

- [ ] The title is concise and informative.
- [ ] The description explains in detail what this PR is about.
- [ ] I have linked a relevant issue or discussion.
- [ ] I have created tests covering the changes.
- [ ] I have updated the documentation and checked the documentation
preview.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on. For example,
-->
<!-- - #12345: short description why this is a dependency -->
<!-- - #34567: ... -->
    
URL: #39251
Reported by: Tobias Diez
Reviewer(s): Dima Pasechnik
  • Loading branch information
Release Manager committed Feb 21, 2025
2 parents ac8406f + 1884ebc commit e080610
Show file tree
Hide file tree
Showing 27 changed files with 48 additions and 506 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ on:
platform:
description: 'Platform'
required: true
default: 'ubuntu-jammy-standard'
default: 'ubuntu-noble-standard'
docker_tag:
description: 'Docker tag'
required: true
Expand Down Expand Up @@ -68,8 +68,8 @@ concurrency:

env:
# Adapted from docker.yml
TOX_ENV: "docker-${{ github.event.inputs.platform || 'ubuntu-jammy-standard' }}-incremental"
BUILD_IMAGE: "localhost:5000/${{ github.repository }}/sage-${{ github.event.inputs.platform || 'ubuntu-jammy-standard' }}-with-targets:ci"
TOX_ENV: "docker-${{ github.event.inputs.platform || 'ubuntu-noble-standard' }}-incremental"
BUILD_IMAGE: "localhost:5000/${{ github.repository }}/sage-${{ github.event.inputs.platform || 'ubuntu-noble-standard' }}-with-targets:ci"
FROM_DOCKER_REPOSITORY: "ghcr.io/sagemath/sage/"
FROM_DOCKER_TARGET: "with-targets"
FROM_DOCKER_TAG: ${{ github.event.inputs.docker_tag || 'dev'}}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ jobs:
#
CIBW_ARCHS: ${{ matrix.arch }}
# https://cibuildwheel.readthedocs.io/en/stable/options/#requires-python
CIBW_PROJECT_REQUIRES_PYTHON: ">=3.9, <3.13"
CIBW_PROJECT_REQUIRES_PYTHON: ">=3.11, <3.13"
# Environment during wheel build
CIBW_ENVIRONMENT: "PATH=$(pwd)/prefix/bin:$PATH CPATH=$(pwd)/prefix/include:$CPATH LIBRARY_PATH=$(pwd)/prefix/lib:$LIBRARY_PATH LD_LIBRARY_PATH=$(pwd)/prefix/lib:$LD_LIBRARY_PATH PKG_CONFIG_PATH=$(pwd)/prefix/share/pkgconfig:$PKG_CONFIG_PATH ACLOCAL_PATH=/usr/share/aclocal PIP_CONSTRAINT=$(pwd)/constraints.txt PIP_FIND_LINKS=file://$(pwd)/wheelhouse SAGE_NUM_THREADS=6"
# Use 'build', not 'pip wheel'
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/doc-build-pdf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
platform:
description: 'Platform'
required: true
default: 'ubuntu-jammy-standard'
default: 'ubuntu-noble-standard'
docker_tag:
description: 'Docker tag'
required: true
Expand All @@ -22,8 +22,8 @@ concurrency:

env:
# Same as in build.yml
TOX_ENV: "docker-${{ github.event.inputs.platform || 'ubuntu-jammy-standard' }}-incremental"
BUILD_IMAGE: "localhost:5000/${{ github.repository }}/sage-${{ github.event.inputs.platform || 'ubuntu-jammy-standard' }}-with-targets:ci"
TOX_ENV: "docker-${{ github.event.inputs.platform || 'ubuntu-noble-standard' }}-incremental"
BUILD_IMAGE: "localhost:5000/${{ github.repository }}/sage-${{ github.event.inputs.platform || 'ubuntu-noble-standard' }}-with-targets:ci"
FROM_DOCKER_REPOSITORY: "ghcr.io/sagemath/sage/"
FROM_DOCKER_TARGET: "with-targets"
FROM_DOCKER_TAG: ${{ github.event.inputs.docker_tag || 'dev'}}
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/doc-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ on:
platform:
description: 'Platform'
required: true
default: 'ubuntu-jammy-standard'
default: 'ubuntu-noble-standard'
docker_tag:
description: 'Docker tag'
required: true
Expand All @@ -33,8 +33,8 @@ concurrency:

env:
# Same as in build.yml
TOX_ENV: "docker-${{ github.event.inputs.platform || 'ubuntu-jammy-standard' }}-incremental"
BUILD_IMAGE: "localhost:5000/${{ github.repository }}/sage-${{ github.event.inputs.platform || 'ubuntu-jammy-standard' }}-with-targets:ci"
TOX_ENV: "docker-${{ github.event.inputs.platform || 'ubuntu-noble-standard' }}-incremental"
BUILD_IMAGE: "localhost:5000/${{ github.repository }}/sage-${{ github.event.inputs.platform || 'ubuntu-noble-standard' }}-with-targets:ci"
FROM_DOCKER_REPOSITORY: "ghcr.io/sagemath/sage/"
FROM_DOCKER_TARGET: "with-targets"
FROM_DOCKER_TAG: ${{ github.event.inputs.docker_tag || 'dev'}}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pyright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ concurrency:
jobs:
pyright:
runs-on: ubuntu-latest
container: ghcr.io/sagemath/sage/sage-ubuntu-jammy-standard-with-targets:dev
container: ghcr.io/sagemath/sage/sage-ubuntu-noble-standard-with-targets:dev
steps:
- name: Checkout
id: checkout
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ __pycache__/
/src/sage/modular/arithgroup/farey_symbol.h
# List of C and C++ files that are actual source files,
# NOT generated by Cython. The same list appears in src/MANIFEST.in
!/src/sage/cpython/debugimpl.c
!/src/sage/graphs/base/boost_interface.cpp
!/src/sage/graphs/cliquer/cl.c
!/src/sage/graphs/graph_decompositions/sage_tdlib.cpp
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ in the Installation Guide.
more details.

- Python 3.4 or later, or Python 2.7, a full installation including
`urllib`; but ideally version 3.9.x, 3.10.x, 3.11.x, 3.12.x, which
`urllib`; but ideally version 3.11.x or later, which
will avoid having to build Sage's own copy of Python 3.
See [build/pkgs/python3/SPKG.rst](build/pkgs/python3/SPKG.rst)
for more details.
Expand Down Expand Up @@ -557,11 +557,11 @@ SAGE_ROOT Root directory (create by git clone)
│ │ ├── installed/
│ │ │ Records of installed non-Python packages
│ │ ├── scripts/ Scripts for uninstalling installed packages
│ │ └── venv-python3.9 (SAGE_VENV)
│ │ └── venv-python (SAGE_VENV)
│ │ │ Installation hierarchy (virtual environment)
│ │ │ for Python packages
│ │ ├── bin/ Executables and installed scripts
│ │ ├── lib/python3.9/site-packages/
│ │ ├── lib/python/site-packages/
│ │ │ Python modules/packages are installed here
│ │ └── var/lib/sage/
│ │ └── wheels/
Expand Down
4 changes: 1 addition & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,14 @@ classifiers = [
"Operating System :: POSIX",
"Operating System :: MacOS :: MacOS X",
"Programming Language :: Python :: 3 :: Only",
"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 :: Implementation :: CPython",
"Topic :: Scientific/Engineering :: Mathematics",
]
urls = {Homepage = "https://www.sagemath.org"}
requires-python = ">=3.9, <3.14"
requires-python = ">=3.11, <3.14"

[project.optional-dependencies]
R = [
Expand Down
2 changes: 1 addition & 1 deletion pyrightconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"root": "src"
}
],
"pythonVersion": "3.9",
"pythonVersion": "3.11",
"exclude": ["venv"],
"venvPath": "./venv/",
"venv": "./",
Expand Down
4 changes: 2 additions & 2 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# https://docs.astral.sh/ruff/configuration/#config-file-discovery

# Assume Python 3.9
target-version = "py39"
# Python 3.11 is the minimum supported version
target-version = "py311"

lint.select = [
"E", # pycodestyle errors - https://docs.astral.sh/ruff/rules/#error-e
Expand Down
1 change: 0 additions & 1 deletion src/MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ global-exclude *.cpp
# List of C and C++ files that are actual source files,
# NOT generated by Cython. The same list appears in SAGE_ROOT/.gitignore
#
include sage/cpython/debugimpl.c
include sage/graphs/base/boost_interface.cpp
include sage/graphs/cliquer/cl.c
include sage/libs/eclib/wrap.cpp
Expand Down
37 changes: 11 additions & 26 deletions src/doc/en/developer/coding_in_python.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,14 @@ Sage.
Python language standard
========================

Sage library code needs to be compatible with all versions of Python
that Sage supports. The information regarding the supported versions
can be found in the files ``build/pkgs/python3/spkg-configure.m4`` and
``src/setup.cfg.m4``.

Python 3.9 is the oldest supported version. Hence,
all language and library features that are available in Python 3.9 can
be used; but features introduced in Python 3.10 cannot be used. If a
feature is deprecated in a newer supported version, it must be ensured
that deprecation warnings issued by Python do not lead to failures in
doctests.
Sage follows the time window-based support policy
`SPEC 0 — Minimum Supported Dependencies <https://scientific-python.org/specs/spec-0000/>`_
for Python versions.
The current minimum supported Python version can be found in the
``pyproject.toml`` file. Accordingly, only language and library features
available in this version can be used. If a feature is deprecated in a newer
supported version, it must be ensured that deprecation warnings issued by
Python do not lead to failures in doctests.

Some key language and library features have been backported to older Python versions
using one of two mechanisms:
Expand All @@ -34,21 +31,9 @@ using one of two mechanisms:
of annotations). All Sage library code that uses type annotations
should include this ``__future__`` import and follow PEP 563.

- Backport packages

- `importlib_metadata <../reference/spkg/importlib_metadata>`_
(to be used in place of ``importlib.metadata``),
- `importlib_resources <../reference/spkg/importlib_resources>`_
(to be used in place of ``importlib.resources``),
- `typing_extensions <../reference/spkg/typing_extensions>`_
(to be used in place of ``typing``).

The Sage library declares these packages as dependencies and ensures that
versions that provide features of Python 3.11 are available.

Meta :issue:`29756` keeps track of newer Python features and serves
as a starting point for discussions on how to make use of them in the
Sage library.
- The `typing_extensions <../reference/spkg/typing_extensions>`_ package
is used to backport features from newer versions of the ``typing`` module.
The Sage library declares this package as a dependency.


Design
Expand Down
18 changes: 9 additions & 9 deletions src/doc/en/installation/conda.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Create a new conda environment containing SageMath, either with ``mamba`` or ``c
$ conda create -n sage sage python=X
where ``X`` is version of Python, e.g. ``3.9``.
where ``X`` is version of Python, e.g. ``3.12``.

To use Sage from there,

Expand Down Expand Up @@ -86,22 +86,22 @@ Here we assume that you are using a git checkout.

.. code-block:: shell
$ mamba env create --file environment-3.11-linux.yml --name sage-dev
$ mamba env create --file environment-3.12-linux.yml --name sage-dev
$ conda activate sage-dev
.. tab:: conda

.. code-block:: shell
$ conda env create --file environment-3.11-linux.yml --name sage-dev
$ conda env create --file environment-3.12-linux.yml --name sage-dev
$ conda activate sage-dev
Alternatively, you can use ``environment-3.11-linux.yml`` or
``environment-optional-3.11-linux.yml``, which will only install standard
Alternatively, you can use ``environment-3.12-linux.yml`` or
``environment-optional-3.12-linux.yml``, which will only install standard
(and optional) packages without any additional developer tools.

A different Python version can be selected by replacing ``3.11`` by ``3.9``
or ``3.10`` in these commands.
A different Python version can be selected by replacing ``3.12`` with the
desired version.

- Bootstrap the source tree and install the build prerequisites and the Sage library::

Expand Down Expand Up @@ -137,7 +137,7 @@ After editing any Cython files, rebuild the Sage library using::

In order to update the conda environment later, you can run::

$ mamba env update --file environment-3.11-linux.yml --name sage-dev
$ mamba env update --file environment-3.12-linux.yml --name sage-dev

To build the documentation, use::

Expand All @@ -156,5 +156,5 @@ To build the documentation, use::

You can update the conda lock files by running
``.github/workflows/conda-lock-update.py`` or by running
``conda-lock --platform linux-64 --filename environment-3.11-linux.yml --lockfile environment-3.11-linux.lock``
``conda-lock --platform linux-64 --filename environment-3.12-linux.yml --lockfile environment-3.12-linux.lock``
manually.
5 changes: 2 additions & 3 deletions src/doc/en/installation/launching.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ Sage uses the following environment variables when it runs:

- See
https://docs.python.org/3/using/cmdline.html#environment-variables
for more variables used by Python (not an exhaustive list). With
Python 3.11 or later, a brief summary can also be obtained by
running `python3 --help-env`.
for more variables used by Python (not an exhaustive list).
A brief summary can also be obtained by running `python3 --help-env`.

Using a Jupyter Notebook remotely
---------------------------------
Expand Down
6 changes: 0 additions & 6 deletions src/sage/all__sagemath_repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,6 @@
message=r"Pickle, copy, and deepcopy support will be "
r"removed from itertools in Python 3.14.")

# triggered in Python 3.9 on Redhat-based distributions
# https://github.com/sagemath/sage/issues/37863
# https://github.com/networkx/networkx/issues/7101
warnings.filterwarnings('ignore', category=RuntimeWarning,
message="networkx backend defined more than once: nx-loopback")

from sage.all__sagemath_objects import *
from sage.all__sagemath_environment import *

Expand Down
25 changes: 0 additions & 25 deletions src/sage/cpython/atexit.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,6 @@ from cpython.ref cimport PyObject
# Implement "_atexit_callbacks()" for each supported python version
cdef extern from *:
"""
#if PY_VERSION_HEX >= 0x030a0000
/********** Python 3.10 **********/
#define Py_BUILD_CORE
#undef _PyGC_FINALIZED
#include "internal/pycore_interp.h"
Expand All @@ -163,29 +161,6 @@ cdef extern from *:
struct atexit_state state = interp->atexit;
return state.callbacks;
}
#else
/********** Python < 3.10 **********/
/* Internal structures defined in the CPython source in
* Modules/atexitmodule.c and subject to (but unlikely to) change. Watch
* https://bugs.python.org/issue32082 for a request to (eventually)
* re-expose more of the atexit module's internals to Python
* typedef struct
*/
typedef struct {
PyObject *func;
PyObject *args;
PyObject *kwargs;
} atexit_callback;
typedef struct {
atexit_callback **atexit_callbacks;
int ncallbacks;
int callback_len;
} atexitmodule_state;
static atexit_callback ** _atexit_callbacks(PyObject *self) {
atexitmodule_state *state = PyModule_GetState(self);
return state->atexit_callbacks;
}
#endif
"""
ctypedef struct atexit_callback:
PyObject* func
Expand Down
9 changes: 0 additions & 9 deletions src/sage/cpython/cython_metaclass.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@
* http://www.gnu.org/licenses/
*****************************************************************************/

/* Compatibility for python 3.8, can be removed later */
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type)
{ ob->ob_type = type; }
#define Py_SET_TYPE(ob, type) _Py_SET_TYPE((PyObject*)(ob), type)
#endif

/* Tuple (None, None, None), initialized as needed */
static PyObject* NoneNoneNone;

Expand Down Expand Up @@ -52,15 +45,13 @@ static CYTHON_INLINE int Sage_PyType_Ready(PyTypeObject* t)
if (r < 0)
return r;

#if PY_VERSION_HEX >= 0x03050000
// Cython 3 sets Py_TPFLAGS_HEAPTYPE before calling PyType_Ready,
// and resets just after the call. We need to reset it earlier,
// since otherwise the call to metaclass.__init__ below may have
// illegal memory accesses.
// See also:
// https://github.com/cython/cython/issues/3603
t->tp_flags &= ~Py_TPFLAGS_HEAPTYPE;
#endif

/* Set or get metaclass (the type of t) */
PyTypeObject* metaclass;
Expand Down
5 changes: 0 additions & 5 deletions src/sage/cpython/debug.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ cdef extern from "Python.h":
# Helper to get a pointer to an object's __dict__ slot, if any
PyObject** _PyObject_GetDictPtr(obj)

cdef extern from "debugimpl.c":
void _type_debug(PyTypeObject*)

from sage.cpython.getattr cimport AttributeErrorMessage


Expand Down Expand Up @@ -303,5 +300,3 @@ def type_debug(cls):
"""
if not isinstance(cls, type):
raise TypeError(f"{cls!r} is not a type")

_type_debug(<PyTypeObject*>cls)
Loading

0 comments on commit e080610

Please sign in to comment.