diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bbecdf481b6..564b3e5464e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -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 @@ -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'}} diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index b8800c8854b..ccd3e9f1a94 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -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' diff --git a/.github/workflows/doc-build-pdf.yml b/.github/workflows/doc-build-pdf.yml index dce25a132c9..f8d30cd32b6 100644 --- a/.github/workflows/doc-build-pdf.yml +++ b/.github/workflows/doc-build-pdf.yml @@ -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 @@ -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'}} diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index f46317ecda7..3d80d4c30a8 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -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 @@ -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'}} diff --git a/.github/workflows/pyright.yml b/.github/workflows/pyright.yml index eef1aad5976..97e12442b03 100644 --- a/.github/workflows/pyright.yml +++ b/.github/workflows/pyright.yml @@ -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 diff --git a/.gitignore b/.gitignore index b8bfc364a26..e274a25c738 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/README.md b/README.md index f54d7ad34b6..0964e22a5e0 100644 --- a/README.md +++ b/README.md @@ -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. @@ -551,11 +551,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/ diff --git a/pyproject.toml b/pyproject.toml index a1febc07917..117a5006067 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,8 +62,6 @@ 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", @@ -71,7 +69,7 @@ classifiers = [ "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 = [ diff --git a/pyrightconfig.json b/pyrightconfig.json index 643c56360c9..826c3aabe86 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -7,7 +7,7 @@ "root": "src" } ], - "pythonVersion": "3.9", + "pythonVersion": "3.11", "exclude": ["venv"], "venvPath": "./venv/", "venv": "./", diff --git a/ruff.toml b/ruff.toml index 15def717a4e..1c21d484455 100644 --- a/ruff.toml +++ b/ruff.toml @@ -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 diff --git a/src/MANIFEST.in b/src/MANIFEST.in index f6231401294..8428dfff314 100644 --- a/src/MANIFEST.in +++ b/src/MANIFEST.in @@ -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 diff --git a/src/doc/en/developer/coding_in_python.rst b/src/doc/en/developer/coding_in_python.rst index 1ea6eebb317..f86ab9a09c3 100644 --- a/src/doc/en/developer/coding_in_python.rst +++ b/src/doc/en/developer/coding_in_python.rst @@ -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 `_ +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: @@ -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 diff --git a/src/doc/en/installation/conda.rst b/src/doc/en/installation/conda.rst index ae560bb5a38..65f03583af6 100644 --- a/src/doc/en/installation/conda.rst +++ b/src/doc/en/installation/conda.rst @@ -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, @@ -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:: @@ -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:: @@ -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. diff --git a/src/doc/en/installation/launching.rst b/src/doc/en/installation/launching.rst index b612a89a9c1..bb99fbcfb00 100644 --- a/src/doc/en/installation/launching.rst +++ b/src/doc/en/installation/launching.rst @@ -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 --------------------------------- diff --git a/src/sage/all__sagemath_repl.py b/src/sage/all__sagemath_repl.py index c830950c26b..13efd115e1c 100644 --- a/src/sage/all__sagemath_repl.py +++ b/src/sage/all__sagemath_repl.py @@ -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 * diff --git a/src/sage/cpython/atexit.pyx b/src/sage/cpython/atexit.pyx index 8f833ab1437..c74c1d0308a 100644 --- a/src/sage/cpython/atexit.pyx +++ b/src/sage/cpython/atexit.pyx @@ -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" @@ -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 diff --git a/src/sage/cpython/cython_metaclass.h b/src/sage/cpython/cython_metaclass.h index ecf7f973c3e..f7b6f345fa3 100644 --- a/src/sage/cpython/cython_metaclass.h +++ b/src/sage/cpython/cython_metaclass.h @@ -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; @@ -52,7 +45,6 @@ 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 @@ -60,7 +52,6 @@ static CYTHON_INLINE int Sage_PyType_Ready(PyTypeObject* t) // 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; diff --git a/src/sage/cpython/debug.pyx b/src/sage/cpython/debug.pyx index f4e0a44046f..a11dfc085f3 100644 --- a/src/sage/cpython/debug.pyx +++ b/src/sage/cpython/debug.pyx @@ -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 @@ -303,5 +300,3 @@ def type_debug(cls): """ if not isinstance(cls, type): raise TypeError(f"{cls!r} is not a type") - - _type_debug(cls) diff --git a/src/sage/cpython/debugimpl.c b/src/sage/cpython/debugimpl.c deleted file mode 100644 index 176e93900c2..00000000000 --- a/src/sage/cpython/debugimpl.c +++ /dev/null @@ -1,348 +0,0 @@ -#include - -#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 9 - -static void _type_debug(PyTypeObject* tp) -{ - printf("Not implemented for CPython >= 3.9\n"); -} - -#else - -#define HAVE_WEAKREFS(tp) (1) -#define HAVE_CLASS(tp) (1) -#define HAVE_ITER(tp) (1) -#define HAVE_RICHCOMPARE(tp) (1) -#define HAVE_INPLACEOPS(tp) (1) -#define HAVE_SEQUENCE_IN(tp) (1) -#define HAVE_GETCHARBUFFER(tp) (1) -#define HAVE_NEW_DIVISION(tp) (1) -#define HAVE_INDEX(tp) (1) -#define HAVE_NEWBUFFER(tp) (1) -#define HAVE_FINALIZE(tp) (tp->tp_flags & Py_TPFLAGS_HAVE_FINALIZE) - -static void print_object(void* pyobj) -{ - if (pyobj == NULL) - { - printf("NULL\n"); - return; - } - - PyObject* obj = (PyObject*)pyobj; - - if (PyTuple_Check(obj)) - { - printf("%s:\n", Py_TYPE(obj)->tp_name); - - Py_ssize_t i, n = PyTuple_GET_SIZE(obj); - for (i = 0; i < n; i++) - { - printf(" "); - PyObject_Print(PyTuple_GET_ITEM(obj, i), stdout, 0); - printf("\n"); - } - } - else if (PyDict_Check(obj)) - { - printf("%s:\n", Py_TYPE(obj)->tp_name); - - Py_ssize_t pos = 0; - PyObject* key; - PyObject* value; - while (PyDict_Next(obj, &pos, &key, &value)) - { - printf(" "); - PyObject_Print(key, stdout, 0); - printf(": "); - PyObject_Print(value, stdout, 0); - printf("\n"); - } - } - else - { - PyObject_Print(obj, stdout, 0); - printf("\n"); - } -} - - -#define pointer_check_constant(ptr, val) \ - if (ptr == (void*)(val)) \ - { \ - special = 0; \ - printf(#val "\n"); \ - } - -#define subattr_pointer_value(sub, attr) \ - special = 1; \ - pointer_check_constant(tp->attr, NULL) \ - else pointer_check_constant(tp->attr, PyType_GenericAlloc) \ - else pointer_check_constant(tp->attr, PyType_GenericNew) \ - else pointer_check_constant(tp->attr, PyObject_Del) \ - else pointer_check_constant(tp->attr, PyObject_GC_Del) \ - else pointer_check_constant(tp->attr, PyObject_GenericGetAttr) \ - else pointer_check_constant(tp->attr, PyObject_GenericSetAttr) \ - else pointer_check_constant(tp->attr, _Py_HashPointer) \ - else pointer_check_constant(tp->attr, PyObject_HashNotImplemented) \ - else pointer_check_constant(tp->attr, subtype_traverse) \ - else pointer_check_constant(tp->attr, subtype_clear) \ - else pointer_check_constant(tp->attr, subtype_dealloc) \ - else \ - { \ - PyObject* mro = tp->tp_mro; \ - PyTypeObject* subtp; \ - Py_ssize_t i, n = PyTuple_GET_SIZE(mro); \ - for (i = n-1; i >= 0; i--) \ - { \ - subtp = (PyTypeObject*)PyTuple_GET_ITEM(mro, i); \ - if (subtp != tp && PyType_Check(subtp)) \ - { \ - if (subtp->sub && tp->attr == subtp->attr) \ - { \ - special = 0; \ - printf("== %s\n", subtp->tp_name); \ - break; \ - } \ - } \ - } \ - } \ - if (special) printf("%p\n", tp->attr); - -#define attr_pointer_value(attr) subattr_pointer_value(tp_name, attr); - -#define attr_pointer(attr) \ - printf(" " #attr ": "); \ - attr_pointer_value(attr); -#define attr_pointer_meth(attr, method) \ - printf(" " #attr " (" method "): "); \ - attr_pointer_value(attr); -#define subattr_pointer(sub, attr) \ - printf(" " #attr ": "); \ - subattr_pointer_value(sub, sub->attr); -#define subattr_pointer_meth(sub, attr, method) \ - printf(" " #attr " (" method "): "); \ - subattr_pointer_value(sub, sub->attr); - -#define attr_object(attr) \ - printf(" " #attr ": "); \ - print_object(tp->attr); -#define attr_object_meth(attr, method) \ - printf(" " #attr " (" method "): "); \ - print_object(tp->attr); - -#define attr_flag(flag) \ - if (tp->tp_flags & Py_TPFLAGS_ ## flag) \ - printf(" " #flag "\n"); - - -static void _type_debug(PyTypeObject* tp) -{ - int special; - - PyObject_Print((PyObject*)tp, stdout, 0); - printf(" (%p)\n", tp); - printf(" ob_refcnt: %ld\n", (long)Py_REFCNT(tp)); - printf(" ob_type: "); print_object(Py_TYPE(tp)); - printf(" tp_name: %s\n", tp->tp_name); - printf(" tp_basicsize: %ld\n", (long)tp->tp_basicsize); - printf(" tp_itemsize: %ld\n", (long)tp->tp_itemsize); - printf(" tp_dictoffset: %ld\n", (long)tp->tp_dictoffset); - if HAVE_WEAKREFS(tp) - { - printf(" tp_weaklistoffset: %ld\n", (long)tp->tp_weaklistoffset); - } - - if HAVE_CLASS(tp) - { - attr_object_meth(tp_base, "__base__"); - attr_object_meth(tp_bases, "__bases__"); - attr_object_meth(tp_mro, "__mro__"); - attr_object_meth(tp_dict, "__dict__"); - } - - attr_pointer(tp_alloc); - attr_pointer_meth(tp_new, "__new__"); - attr_pointer_meth(tp_init, "__init__"); - attr_pointer_meth(tp_dealloc, "__dealloc__"); - if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) - { - attr_pointer_meth(tp_del, "__del__"); - } - #if PY_MAJOR_VERSION >= 3 - if HAVE_FINALIZE(tp) - { - attr_pointer_meth(tp_finalize, "__del__"); - } - #endif - attr_pointer(tp_free); - - attr_pointer_meth(tp_repr, "__repr__"); - attr_pointer(tp_print); - attr_pointer_meth(tp_hash, "__hash__"); - attr_pointer_meth(tp_call, "__call__"); - attr_pointer_meth(tp_str, "__str__"); - #if PY_MAJOR_VERSION <= 2 - attr_pointer_meth(tp_compare, "cmp"); - #endif - attr_pointer_meth(tp_richcompare, "__richcmp__"); - attr_pointer_meth(tp_getattr, "__getattribute__"); - attr_pointer_meth(tp_setattr, "__setattribute__"); - attr_pointer_meth(tp_getattro, "__getattribute__"); - attr_pointer_meth(tp_setattro, "__setattribute__"); - if HAVE_ITER(tp) - { - attr_pointer_meth(tp_iter, "__iter__"); - attr_pointer_meth(tp_iternext, "__next__"); - } - if HAVE_CLASS(tp) - { - attr_pointer_meth(tp_descr_get, "__get__"); - attr_pointer_meth(tp_descr_set, "__set__"); - - attr_object(tp_cache); - attr_object(tp_weaklist); - } - if HAVE_RICHCOMPARE(tp) - { - attr_pointer(tp_traverse); - attr_pointer(tp_clear); - } - if HAVE_CLASS(tp) - { - attr_pointer(tp_is_gc); - } - - attr_pointer(tp_as_number); - if (special) - { - subattr_pointer_meth(tp_as_number, nb_add, "__add__"); - subattr_pointer_meth(tp_as_number, nb_subtract, "__sub__"); - subattr_pointer_meth(tp_as_number, nb_multiply, "__mul__"); - #if PY_MAJOR_VERSION <= 2 - subattr_pointer_meth(tp_as_number, nb_divide, "__div__"); - #endif - if HAVE_NEW_DIVISION(tp) - { - subattr_pointer_meth(tp_as_number, nb_floor_divide, "__floordiv__"); - subattr_pointer_meth(tp_as_number, nb_true_divide, "__truediv__"); - } - subattr_pointer_meth(tp_as_number, nb_remainder, "__mod__"); - subattr_pointer_meth(tp_as_number, nb_divmod, "__divmod__"); - subattr_pointer_meth(tp_as_number, nb_power, "__pow__"); - subattr_pointer_meth(tp_as_number, nb_negative, "__neg__"); - subattr_pointer_meth(tp_as_number, nb_positive, "__pos__"); - subattr_pointer_meth(tp_as_number, nb_absolute, "__abs__"); - subattr_pointer_meth(tp_as_number, nb_bool, "__bool__"); - subattr_pointer_meth(tp_as_number, nb_invert, "__invert__"); - subattr_pointer_meth(tp_as_number, nb_lshift, "__lshift__"); - subattr_pointer_meth(tp_as_number, nb_rshift, "__rshift__"); - subattr_pointer_meth(tp_as_number, nb_and, "__and__"); - subattr_pointer_meth(tp_as_number, nb_or, "__or__"); - subattr_pointer_meth(tp_as_number, nb_xor, "__xor__"); - subattr_pointer_meth(tp_as_number, nb_int, "__int__"); - #if PY_MAJOR_VERSION <= 2 - subattr_pointer_meth(tp_as_number, nb_long, "__long__"); - #endif - if HAVE_INDEX(tp) - { - subattr_pointer_meth(tp_as_number, nb_index, "__index__"); - } - subattr_pointer_meth(tp_as_number, nb_float, "__float__"); - #if PY_MAJOR_VERSION <= 2 - subattr_pointer_meth(tp_as_number, nb_oct, "__oct__"); - subattr_pointer_meth(tp_as_number, nb_hex, "__hex__"); - subattr_pointer(tp_as_number, nb_coerce); - #endif - - if HAVE_INPLACEOPS(tp) - { - subattr_pointer_meth(tp_as_number, nb_inplace_add, "__iadd__"); - subattr_pointer_meth(tp_as_number, nb_inplace_subtract, "__isub__"); - subattr_pointer_meth(tp_as_number, nb_inplace_multiply, "__imul__"); - #if PY_MAJOR_VERSION <= 2 - subattr_pointer_meth(tp_as_number, nb_inplace_divide, "__idiv__"); - #endif - if HAVE_NEW_DIVISION(tp) - { - subattr_pointer_meth(tp_as_number, nb_inplace_floor_divide, "__ifloordiv__"); - subattr_pointer_meth(tp_as_number, nb_inplace_true_divide, "__itruediv__"); - } - subattr_pointer_meth(tp_as_number, nb_inplace_remainder, "__imod__"); - subattr_pointer_meth(tp_as_number, nb_inplace_power, "__ipow__"); - subattr_pointer_meth(tp_as_number, nb_inplace_lshift, "__ilshift__"); - subattr_pointer_meth(tp_as_number, nb_inplace_rshift, "__irshift__"); - subattr_pointer_meth(tp_as_number, nb_inplace_and, "__iand__"); - subattr_pointer_meth(tp_as_number, nb_inplace_or, "__ior__"); - subattr_pointer_meth(tp_as_number, nb_inplace_xor, "__ixor__"); - } - } - - attr_pointer(tp_as_sequence); - if (special) - { - subattr_pointer_meth(tp_as_sequence, sq_length, "__len__"); - subattr_pointer_meth(tp_as_sequence, sq_concat, "__add__"); - if HAVE_INPLACEOPS(tp) - { - subattr_pointer_meth(tp_as_sequence, sq_inplace_concat, "__iadd__"); - } - subattr_pointer_meth(tp_as_sequence, sq_repeat, "__mul__"); - if HAVE_INPLACEOPS(tp) - { - subattr_pointer_meth(tp_as_sequence, sq_inplace_repeat, "__imul__"); - } - subattr_pointer_meth(tp_as_sequence, sq_item, "__getitem__"); - subattr_pointer_meth(tp_as_sequence, sq_ass_item, "__setitem__"); - if HAVE_SEQUENCE_IN(tp) - { - subattr_pointer_meth(tp_as_sequence, sq_contains, "__contains__"); - } - } - - attr_pointer(tp_as_mapping); - if (special) - { - subattr_pointer_meth(tp_as_mapping, mp_length, "__len__"); - subattr_pointer_meth(tp_as_mapping, mp_subscript, "__getitem__"); - subattr_pointer_meth(tp_as_mapping, mp_ass_subscript, "__setitem__"); - } - - attr_pointer(tp_as_buffer); - if (special) - { - #if PY_MAJOR_VERSION <= 2 - subattr_pointer(tp_as_buffer, bf_getreadbuffer); - subattr_pointer(tp_as_buffer, bf_getwritebuffer); - subattr_pointer(tp_as_buffer, bf_getsegcount); - if HAVE_GETCHARBUFFER(tp) - { - subattr_pointer(tp_as_buffer, bf_getcharbuffer); - } - #endif - if HAVE_NEWBUFFER(tp) - { - subattr_pointer_meth(tp_as_buffer, bf_getbuffer, "__getbuffer__"); - subattr_pointer_meth(tp_as_buffer, bf_releasebuffer, "__releasebuffer__"); - } - } - - printf(" tp_flags:\n"); - attr_flag(HEAPTYPE); - attr_flag(BASETYPE); - attr_flag(READY); - attr_flag(READYING); - attr_flag(HAVE_GC); - #if PY_MAJOR_VERSION <= 2 - attr_flag(CHECKTYPES); - #endif - attr_flag(HAVE_VERSION_TAG); - attr_flag(VALID_VERSION_TAG); - attr_flag(IS_ABSTRACT); - if (tp->tp_flags & Py_TPFLAGS_HAVE_VERSION_TAG) - { - printf(" tp_version_tag: %lu\n", (unsigned long)tp->tp_version_tag); - } -} - -#endif diff --git a/src/sage/cpython/pycore_long.h b/src/sage/cpython/pycore_long.h index 99561f1ba96..bbe9d3964bd 100644 --- a/src/sage/cpython/pycore_long.h +++ b/src/sage/cpython/pycore_long.h @@ -2,12 +2,14 @@ #include #if PY_VERSION_HEX >= 0x030C00A5 +// For Python 3.12 compatibility #define ob_digit(o) (((PyLongObject*)o)->long_value.ob_digit) #else #define ob_digit(o) (((PyLongObject*)o)->ob_digit) #endif #if PY_VERSION_HEX >= 0x030C00A7 +// For Python 3.12 compatibility // taken from cpython:Include/internal/pycore_long.h @ 3.12 /* Long value tag bits: @@ -87,12 +89,7 @@ _PyLong_DigitCount(const PyLongObject *op) static inline void _PyLong_SetSignAndDigitCount(PyLongObject *op, int sign, Py_ssize_t size) { -#if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION < 9) -// The function Py_SET_SIZE is defined starting with python 3.9. - Py_SIZE(op) = size; -#else Py_SET_SIZE(op, sign < 0 ? -size : size); -#endif } #endif diff --git a/src/sage/doctest/forker.py b/src/sage/doctest/forker.py index f3950cde06b..df55ad9f6a0 100644 --- a/src/sage/doctest/forker.py +++ b/src/sage/doctest/forker.py @@ -1097,7 +1097,7 @@ def compile_and_execute(self, example, compiler, globs): False sage: doctests, extras = FDS.create_doctests(globs) sage: ex0 = doctests[0].examples[0] - sage: flags = 32768 if sys.version_info.minor < 8 else 524288 + sage: flags = 524288 sage: def compiler(ex): ....: return compile(ex.source, '', ....: 'single', flags, 1) diff --git a/src/sage/libs/gmp/pylong.pyx b/src/sage/libs/gmp/pylong.pyx index 41587396120..a6049232443 100644 --- a/src/sage/libs/gmp/pylong.pyx +++ b/src/sage/libs/gmp/pylong.pyx @@ -32,14 +32,6 @@ from sage.cpython.pycore_long cimport (ob_digit, _PyLong_IsNegative, from sage.libs.gmp.mpz cimport * cdef extern from *: - """ - /* Compatibility for python 3.8, can be removed later */ - #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE) - static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) - { ob->ob_size = size; } - #define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size) - #endif - """ void Py_SET_SIZE(object, Py_ssize_t) int hash_bits """ #ifdef _PyHASH_BITS diff --git a/src/sage/misc/fpickle.pyx b/src/sage/misc/fpickle.pyx index 1dd438de210..a17a92f0636 100644 --- a/src/sage/misc/fpickle.pyx +++ b/src/sage/misc/fpickle.pyx @@ -44,18 +44,13 @@ def reduce_code(co): raise ValueError("Cannot pickle code objects from closures") co_args = (co.co_argcount,) - if sys.version_info.minor >= 8: - co_args += (co.co_posonlyargcount,) + co_args += (co.co_posonlyargcount,) co_args += (co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code, co.co_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name) - if sys.version_info.minor >= 11: - co_args += (co.co_qualname, co.co_firstlineno, - co.co_linetable, co.co_exceptiontable) - else: - co_args += (co.co_firstlineno, co.co_lnotab) - + co_args += (co.co_qualname, co.co_firstlineno, + co.co_linetable, co.co_exceptiontable) return (code_ctor, co_args) diff --git a/src/sage/misc/inherit_comparison_impl.c b/src/sage/misc/inherit_comparison_impl.c index f12dc2a6976..2854beab87c 100644 --- a/src/sage/misc/inherit_comparison_impl.c +++ b/src/sage/misc/inherit_comparison_impl.c @@ -8,14 +8,8 @@ static CYTHON_INLINE void inherit_comparison(PyTypeObject* dst, const PyTypeObject* src) { /* Do nothing if "dst" already has comparison defined */ -#if (PY_MAJOR_VERSION < 3) - if (dst->tp_compare) return; -#endif if (dst->tp_richcompare) return; /* Copy comparison method(s) */ -#if (PY_MAJOR_VERSION < 3) - dst->tp_compare = src->tp_compare; -#endif dst->tp_richcompare = src->tp_richcompare; } diff --git a/src/sage_docbuild/ext/sage_autodoc.py b/src/sage_docbuild/ext/sage_autodoc.py index 94e7d076fa9..8b80350585c 100644 --- a/src/sage_docbuild/ext/sage_autodoc.py +++ b/src/sage_docbuild/ext/sage_autodoc.py @@ -1969,28 +1969,6 @@ def get_doc(self) -> list[list[str]] | None: if isinstance(self.object, TypeVar): if self.object.__doc__ == TypeVar.__doc__: return [] - # ------------------------------------------------------------------ - # This section is kept for compatibility with python 3.9 - # see https://github.com/sagemath/sage/pull/38549#issuecomment-2327790930 - if sys.version_info[:2] < (3, 10): - if inspect.isNewType(self.object) or isinstance(self.object, TypeVar): - parts = self.modname.strip('.').split('.') - orig_objpath = self.objpath - for i in range(len(parts)): - new_modname = '.'.join(parts[:len(parts) - i]) - new_objpath = parts[len(parts) - i:] + orig_objpath - try: - analyzer = ModuleAnalyzer.for_module(new_modname) - analyzer.analyze() - key = ('', new_objpath[-1]) - comment = list(analyzer.attr_docs.get(key, [])) - if comment: - self.objpath = new_objpath - self.modname = new_modname - return [comment] - except PycodeError: - pass - # ------------------------------------------------------------------ if self.doc_as_attr: # Don't show the docstring of the class when it is an alias. if self.get_variable_comment(): diff --git a/src/sage_setup/command/sage_build_cython.py b/src/sage_setup/command/sage_build_cython.py index 880ce7383e2..2e04bd80f87 100644 --- a/src/sage_setup/command/sage_build_cython.py +++ b/src/sage_setup/command/sage_build_cython.py @@ -104,8 +104,7 @@ def finalize_options(self): ('force', 'force')] # Python 3.5 now has a parallel option as well - if sys.version_info[:2] >= (3, 5): - inherit_opts.append(('parallel', 'parallel')) + inherit_opts.append(('parallel', 'parallel')) self.set_undefined_options('build_ext', *inherit_opts) diff --git a/src/setup.cfg.m4 b/src/setup.cfg.m4 index 3a4ec930b8f..6ad88107ce4 100644 --- a/src/setup.cfg.m4 +++ b/src/setup.cfg.m4 @@ -9,7 +9,7 @@ license_files = LICENSE.txt include(`setup_cfg_metadata.m4')dnl' [options] -python_requires = >=3.9, <3.14 +python_requires = >=3.11, <3.14 install_requires = SPKG_INSTALL_REQUIRES_six dnl From build/pkgs/sagelib/dependencies