Skip to content

Commit cfaa38e

Browse files
claudeCarreau
authored andcommitted
Restore Python 3.11 support
Reverts the Python 3.11 drop from PR #15121. This restores: - requires-python >= 3.11 in pyproject.toml - typing_extensions conditional dependency for Python < 3.12 - Conditional imports for TypedDict, Protocol, TypeAliasType from typing_extensions on Python < 3.12 - The find_pre_312 tokenizer path in inputtransformer2.py for system assignments (a = !foo) where ! is ERRORTOKEN on 3.11 - Version-gated sys.last_exc usage (added in Python 3.12) - Python 3.11 in CI test matrix and oldest-deps job - Version check in setup.py and IPython/__init__.py - Enum autoreload test for Python < 3.12 Add tip about D.E. Shaw funding Python 3.11 support On Python < 3.12, include a random tip noting that IPython support for Python versions outside of SPEC-0 is funded by D.E. Shaw. Partial revert of #15121
1 parent 77ad39a commit cfaa38e

14 files changed

Lines changed: 126 additions & 22 deletions

File tree

.github/workflows/test.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ jobs:
2222
fail-fast: false
2323
matrix:
2424
os: [ubuntu-latest, windows-latest]
25-
python-version: ["3.12", "3.13", "3.14"]
25+
python-version: ["3.11", "3.12", "3.13", "3.14"]
2626
deps: [test_extra]
2727
# Test all on ubuntu, test ends on macos
2828
include:
2929
- os: macos-latest
30-
python-version: "3.12"
30+
python-version: "3.11"
3131
deps: test_extra
3232
# free threaded, not with all dependencies
3333
- os: ubuntu-latest
@@ -114,10 +114,10 @@ jobs:
114114

115115
steps:
116116
- uses: actions/checkout@v6
117-
- name: Set up uv with Python 3.12
117+
- name: Set up uv with Python 3.11
118118
uses: astral-sh/setup-uv@v7
119119
with:
120-
python-version: '3.12'
120+
python-version: '3.11'
121121
enable-cache: true
122122
activate-environment: true
123123
prune-cache: false

IPython/__init__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,10 @@
2727
#-----------------------------------------------------------------------------
2828

2929
# Don't forget to also update setup.py when this changes!
30-
if sys.version_info < (3, 12):
30+
if sys.version_info < (3, 11):
3131
raise ImportError(
3232
"""
33-
IPython 9.x supports Python 3.12 and above, following SPEC0
34-
IPython 8.31+ supports Python 3.11 and above, following SPEC0
33+
IPython 9.x supports Python 3.11 and above, following SPEC0
3534
IPython 8.19+ supports Python 3.10 and above, following SPEC0.
3635
IPython 8.13+ supports Python 3.9 and above, following NEP 29.
3736
When using Python 2.7, please install IPython 5.x LTS Long Term Support version.

IPython/core/completer.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,11 @@
243243

244244
from typing import cast
245245

246-
from typing import TypedDict, NotRequired, Protocol, TypeAlias, TypeGuard
246+
if sys.version_info < (3, 12):
247+
from typing_extensions import TypedDict, Protocol
248+
from typing import NotRequired, TypeAlias, TypeGuard
249+
else:
250+
from typing import TypedDict, NotRequired, Protocol, TypeAlias, TypeGuard
247251

248252

249253
# skip module docstests

IPython/core/guarded_eval.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@
3232
import types
3333
from typing import Self, LiteralString, get_type_hints
3434

35-
from typing import TypeAliasType
35+
if sys.version_info < (3, 12):
36+
from typing_extensions import TypeAliasType
37+
else:
38+
from typing import TypeAliasType
3639

3740

3841
@undoc

IPython/core/inputtransformer2.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,24 @@ def transform(self, lines: List[str]):
356356
class SystemAssign(TokenTransformBase):
357357
"""Transformer for assignments from system commands (a = !foo)"""
358358
@classmethod
359-
def find(cls, tokens_by_line):
360-
"""Find the first system assignment (a = !foo) in the cell."""
359+
def find_pre_312(cls, tokens_by_line):
360+
for line in tokens_by_line:
361+
assign_ix = _find_assign_op(line)
362+
if (assign_ix is not None) \
363+
and not line[assign_ix].line.strip().startswith('=') \
364+
and (len(line) >= assign_ix + 2) \
365+
and (line[assign_ix + 1].type == tokenize.ERRORTOKEN):
366+
ix = assign_ix + 1
367+
368+
while ix < len(line) and line[ix].type == tokenize.ERRORTOKEN:
369+
if line[ix].string == '!':
370+
return cls(line[ix].start)
371+
elif not line[ix].string.isspace():
372+
break
373+
ix += 1
374+
375+
@classmethod
376+
def find_post_312(cls, tokens_by_line):
361377
for line in tokens_by_line:
362378
assign_ix = _find_assign_op(line)
363379
if (
@@ -369,6 +385,13 @@ def find(cls, tokens_by_line):
369385
):
370386
return cls(line[assign_ix + 1].start)
371387

388+
@classmethod
389+
def find(cls, tokens_by_line):
390+
"""Find the first system assignment (a = !foo) in the cell."""
391+
if sys.version_info < (3, 12):
392+
return cls.find_pre_312(tokens_by_line)
393+
return cls.find_post_312(tokens_by_line)
394+
372395
def transform(self, lines: List[str]):
373396
"""Transform a system assignment found by the ``find()`` classmethod.
374397
"""

IPython/core/interactiveshell.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2140,7 +2140,8 @@ def _get_exc_info(self, exc_tuple=None):
21402140
sys.last_type = etype
21412141
sys.last_value = value
21422142
sys.last_traceback = tb
2143-
sys.last_exc = value
2143+
if sys.version_info >= (3, 12):
2144+
sys.last_exc = value
21442145

21452146
return etype, value, tb
21462147

IPython/core/tips.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from datetime import datetime
22
import os
3+
import sys
34
from random import choice
45
from typing import Any
56

@@ -107,6 +108,11 @@
107108
]
108109
)
109110

111+
if sys.version_info < (3, 12):
112+
_tips["random"].append(
113+
"IPython support for Python versions outside of SPEC-0 is funded by the D.E. Shaw group: https://deshaw.com"
114+
)
115+
110116
# Check if argcomplete is installed and add tip
111117
try:
112118
import argcomplete

IPython/core/ultratb.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,11 @@ def debugger(self, force: bool = False) -> None:
994994
self.pdb.botframe = etb.tb_frame
995995
# last_value should be deprecated, but last-exc sometimme not set
996996
# please check why later and remove the getattr.
997-
exc = getattr(sys, "last_exc", sys.last_value)
997+
exc = (
998+
sys.last_value
999+
if sys.version_info < (3, 12)
1000+
else getattr(sys, "last_exc", sys.last_value)
1001+
) # type: ignore[attr-defined]
9981002
if exc:
9991003
self.pdb.interaction(None, exc)
10001004
else:

README.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ IPython (Interactive Python) is a command shell for interactive computing in mul
3131

3232
**Python Support**
3333

34-
Starting after IPython 8.16, we progressively transition to `Spec-0000 <https://scientific-python.org/specs/spec-0000/>`_.
34+
Starting after IPython 8.16, we follow `SPEC-0 <https://scientific-python.org/specs/spec-0000/>`_
35+
for determining the minimum supported Python version. Python 3.11 support is
36+
additionally maintained thanks to funding from the
37+
`D. E. Shaw group <https://deshaw.com/>`_.
3538

3639
IPython requires Python 3.11 or newer.
3740

docs/source/whatsnew/version9.rst

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,27 @@
22
9.x Series
33
============
44

5+
.. _version 9.13:
6+
7+
IPython 9.13
8+
============
9+
10+
Python 3.11 Support Restored
11+
-----------------------------
12+
13+
Python 3.11 support has been restored. While IPython follows `SPEC-0
14+
<https://scientific-python.org/specs/spec-0000/>`__ for determining the minimum
15+
supported Python version, continued Python 3.11 support is funded by the
16+
`D. E. Shaw group <https://deshaw.com/>`_.
17+
18+
19+
Thanks
20+
------
21+
22+
Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`_ for sponsoring
23+
work on IPython including extended Python 3.11 support.
24+
25+
526
.. _version 9.12:
627

728
IPython 9.12
@@ -103,12 +124,12 @@ helps with reproducible builds and packaging workflows that may capture this sta
103124
`jupyterlab/jupyterlab#18552 <https://github.com/jupyterlab/jupyterlab/issues/18552>`_).
104125

105126

106-
Python 3.11 Deprecation
107-
------------------------
127+
Python 3.11 Deprecation (Reverted in 9.13)
128+
--------------------------------------------
108129

109-
IPython has begun the process of dropping support for Python 3.11. Users
110-
still running Python 3.11 should plan to upgrade to a supported Python
111-
version.
130+
The deprecation of Python 3.11 announced in 9.11 has been reverted in 9.13.
131+
Python 3.11 support is maintained thanks to funding from the
132+
`D. E. Shaw group <https://deshaw.com/>`_.
112133

113134

114135
Autoreload Encoding Fix

0 commit comments

Comments
 (0)