##// END OF EJS Templates
Drop Python 3.10
M Bussonnier -
Show More
@@ -19,10 +19,10 jobs:
19 19 strategy:
20 20 matrix:
21 21 os: [ubuntu-latest]
22 python-version: ["3.10"]
22 python-version: ["3.13"]
23 23 include:
24 24 - os: macos-13
25 python-version: "3.10"
25 python-version: "3.13"
26 26
27 27 steps:
28 28 - uses: actions/checkout@v4
@@ -17,7 +17,7 jobs:
17 17 - name: Set up Python
18 18 uses: actions/setup-python@v5
19 19 with:
20 python-version: "3.10"
20 python-version: "3.13"
21 21 cache: pip
22 22 cache-dependency-path: |
23 23 pyproject.toml
@@ -21,14 +21,11 jobs:
21 21 fail-fast: false
22 22 matrix:
23 23 os: [ubuntu-latest, windows-latest]
24 python-version: ["3.10", "3.11", "3.12","3.13"]
24 python-version: ["3.11", "3.12","3.13"]
25 25 deps: [test_extra]
26 26 # Test all on ubuntu, test ends on macos
27 27 include:
28 28 - os: macos-latest
29 python-version: "3.10"
30 deps: test_extra
31 - os: macos-latest
32 29 python-version: "3.11"
33 30 deps: test_extra
34 31 # Tests minimal dependencies set
@@ -41,13 +38,13 jobs:
41 38 deps: test
42 39 # Installing optional dependencies stuff takes ages on PyPy
43 40 - os: ubuntu-latest
44 python-version: "pypy-3.10"
41 python-version: "pypy-3.11"
45 42 deps: test
46 43 - os: windows-latest
47 python-version: "pypy-3.10"
44 python-version: "pypy-3.11"
48 45 deps: test
49 46 - os: macos-latest
50 python-version: "pypy-3.10"
47 python-version: "pypy-3.11"
51 48 deps: test
52 49 # Temporary CI run to use entry point compatible code in matplotlib-inline.
53 50 - os: ubuntu-latest
@@ -26,9 +26,10 import sys
26 26 #-----------------------------------------------------------------------------
27 27
28 28 # Don't forget to also update setup.py when this changes!
29 if sys.version_info < (3, 10):
29 if sys.version_info < (3, 11):
30 30 raise ImportError(
31 31 """
32 IPython 8.31+ supports Python 3.11 and above, following SPEC0
32 33 IPython 8.19+ supports Python 3.10 and above, following SPEC0.
33 34 IPython 8.13+ supports Python 3.9 and above, following NEP 29.
34 35 IPython 8.0-8.12 supports Python 3.8 and above, following NEP 29.
@@ -242,6 +242,10 from traitlets.config.configurable import Configurable
242 242
243 243 import __main__
244 244
245 from typing import cast
246 from typing_extensions import TypedDict, NotRequired, Protocol, TypeAlias, TypeGuard
247
248
245 249 # skip module docstests
246 250 __skip_doctest__ = True
247 251
@@ -256,22 +260,7 except ImportError:
256 260 JEDI_INSTALLED = False
257 261
258 262
259 if TYPE_CHECKING or GENERATING_DOCUMENTATION and sys.version_info >= (3, 11):
260 from typing import cast
261 from typing_extensions import TypedDict, NotRequired, Protocol, TypeAlias, TypeGuard
262 else:
263 from typing import Generic
264
265 def cast(type_, obj):
266 """Workaround for `TypeError: MatcherAPIv2() takes no arguments`"""
267 return obj
268 263
269 # do not require on runtime
270 NotRequired = Tuple # requires Python >=3.11
271 TypedDict = Dict # by extension of `NotRequired` requires 3.11 too
272 Protocol = object # requires Python >=3.8
273 TypeAlias = Any # requires Python >=3.10
274 TypeGuard = Generic # requires Python >=3.10
275 264 if GENERATING_DOCUMENTATION:
276 265 from typing import TypedDict
277 266
@@ -31,9 +31,6 from types import MethodDescriptorType, ModuleType
31 31 from IPython.utils.decorators import undoc
32 32
33 33
34 if sys.version_info < (3, 11):
35 from typing_extensions import Self, LiteralString
36 else:
37 34 from typing import Self, LiteralString
38 35
39 36 if sys.version_info < (3, 12):
@@ -149,8 +149,6 try:
149 149 except ImportError:
150 150 sphinxify = None
151 151
152 if sys.version_info[:2] < (3, 11):
153 from exceptiongroup import BaseExceptionGroup
154 152
155 153 class ProvisionalWarning(DeprecationWarning):
156 154 """
@@ -13,7 +13,6 def _exceptiongroup_common(
13 13 native: bool,
14 14 ) -> None:
15 15 pre_raise = "exceptiongroup." if not native else ""
16 pre_catch = pre_raise if sys.version_info < (3, 11) else ""
17 16 filestr = f"""
18 17 {"import exceptiongroup" if not native else ""}
19 18 import pytest
@@ -42,7 +41,7 def _exceptiongroup_common(
42 41 def outer(outer_chain, inner_chain):
43 42 try:
44 43 inner(inner_chain)
45 except {pre_catch}BaseExceptionGroup as e:
44 except BaseExceptionGroup as e:
46 45 if outer_chain == "none":
47 46 raise
48 47 if outer_chain == "from":
@@ -68,7 +67,7 def _exceptiongroup_common(
68 67
69 68 match_lines += [
70 69 " + Exception Group Traceback (most recent call last):",
71 f" | {pre_catch}BaseExceptionGroup: Oops (2 sub-exceptions)",
70 " | BaseExceptionGroup: Oops (2 sub-exceptions)",
72 71 " | ValueError: From f()",
73 72 " | BaseException: From g()",
74 73 ]
@@ -96,9 +95,6 def _exceptiongroup_common(
96 95 assert False, f"{expected} not found in cap.stderr"
97 96
98 97
99 @pytest.mark.skipif(
100 sys.version_info < (3, 11), reason="Native ExceptionGroup not implemented"
101 )
102 98 @pytest.mark.parametrize("outer_chain", ["none", "from", "another"])
103 99 @pytest.mark.parametrize("inner_chain", ["none", "from", "another"])
104 100 def test_native_exceptiongroup(outer_chain, inner_chain) -> None:
@@ -23,9 +23,6 from IPython.testing import decorators as dec
23 23 import pytest
24 24
25 25
26 if sys.version_info < (3, 11):
27 from typing_extensions import Self, LiteralString
28 else:
29 26 from typing import Self, LiteralString
30 27
31 28 if sys.version_info < (3, 12):
@@ -320,12 +320,6 class InputSplitterTestCase(unittest.TestCase):
320 320 self.isp.push(u'\xc3\xa9')
321 321 self.isp.push(u"u'\xc3\xa9'")
322 322
323 @pytest.mark.xfail(
324 reason="Bug in python 3.9.8 – bpo 45738",
325 condition=sys.version_info in [(3, 11, 0, "alpha", 2)],
326 raises=SystemError,
327 strict=True,
328 )
329 323 def test_line_continuation(self):
330 324 """ Test issue #2108."""
331 325 isp = self.isp
@@ -314,17 +314,7 examples = [
314 314 pytest.param("\\\r\n", "incomplete", 0),
315 315 pytest.param("a = '''\n hi", "incomplete", 3),
316 316 pytest.param("def a():\n x=1\n global x", "invalid", None),
317 pytest.param(
318 "a \\ ",
319 "invalid",
320 None,
321 marks=pytest.mark.xfail(
322 reason="Bug in python 3.9.8 – bpo 45738",
323 condition=sys.version_info in [(3, 11, 0, "alpha", 2)],
324 raises=SystemError,
325 strict=True,
326 ),
327 ), # Nothing allowed after backslash,
317 pytest.param("a \\ ", "invalid", None), # Nothing allowed after backslash,
328 318 pytest.param("1\\\n+2", "complete", None),
329 319 ]
330 320
@@ -336,12 +326,6 def test_check_complete_param(code, expected, number):
336 326
337 327
338 328 @pytest.mark.xfail(platform.python_implementation() == "PyPy", reason="fail on pypy")
339 @pytest.mark.xfail(
340 reason="Bug in python 3.9.8 – bpo 45738",
341 condition=sys.version_info in [(3, 11, 0, "alpha", 2)],
342 raises=SystemError,
343 strict=True,
344 )
345 329 def test_check_complete():
346 330 cc = ipt2.TransformerManager().check_complete
347 331
@@ -76,14 +76,9 def foo(self, args):
76 76
77 77
78 78 def test_magic_arguments():
79 # “optional arguments” was replaced with “options” in argparse help
80 # https://docs.python.org/3/whatsnew/3.10.html#argparse
81 # https://bugs.python.org/issue9694
82 options = "optional arguments" if sys.version_info < (3, 10) else "options"
83
84 79 assert (
85 80 magic_foo1.__doc__
86 == f"::\n\n %foo1 [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n"
81 == f"::\n\n %foo1 [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\noptions:\n -f FOO, --foo FOO an argument\n"
87 82 )
88 83 assert getattr(magic_foo1, "argcmd_name", None) == None
89 84 assert real_name(magic_foo1) == "foo1"
@@ -98,7 +93,7 def test_magic_arguments():
98 93
99 94 assert (
100 95 magic_foo3.__doc__
101 == f"::\n\n %foo3 [-f FOO] [-b BAR] [-z BAZ]\n\n{LEADING_SPACE}A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n\nGroup:\n -b BAR, --bar BAR a grouped argument\n\nSecond Group:\n -z BAZ, --baz BAZ another grouped argument\n"
96 == f"::\n\n %foo3 [-f FOO] [-b BAR] [-z BAZ]\n\n{LEADING_SPACE}A docstring.\n\noptions:\n -f FOO, --foo FOO an argument\n\nGroup:\n -b BAR, --bar BAR a grouped argument\n\nSecond Group:\n -z BAZ, --baz BAZ another grouped argument\n"
102 97 )
103 98 assert getattr(magic_foo3, "argcmd_name", None) == None
104 99 assert real_name(magic_foo3) == "foo3"
@@ -107,7 +102,7 def test_magic_arguments():
107 102
108 103 assert (
109 104 magic_foo4.__doc__
110 == f"::\n\n %foo4 [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n"
105 == f"::\n\n %foo4 [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\noptions:\n -f FOO, --foo FOO an argument\n"
111 106 )
112 107 assert getattr(magic_foo4, "argcmd_name", None) == None
113 108 assert real_name(magic_foo4) == "foo4"
@@ -116,7 +111,7 def test_magic_arguments():
116 111
117 112 assert (
118 113 magic_foo5.__doc__
119 == f"::\n\n %frobnicate [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n"
114 == f"::\n\n %frobnicate [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\noptions:\n -f FOO, --foo FOO an argument\n"
120 115 )
121 116 assert getattr(magic_foo5, "argcmd_name", None) == "frobnicate"
122 117 assert real_name(magic_foo5) == "frobnicate"
@@ -125,7 +120,7 def test_magic_arguments():
125 120
126 121 assert (
127 122 magic_magic_foo.__doc__
128 == f"::\n\n %magic_foo [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n"
123 == f"::\n\n %magic_foo [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\noptions:\n -f FOO, --foo FOO an argument\n"
129 124 )
130 125 assert getattr(magic_magic_foo, "argcmd_name", None) == None
131 126 assert real_name(magic_magic_foo) == "magic_foo"
@@ -134,7 +129,7 def test_magic_arguments():
134 129
135 130 assert (
136 131 foo.__doc__
137 == f"::\n\n %foo [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n"
132 == f"::\n\n %foo [-f FOO]\n\n{LEADING_SPACE}A docstring.\n\noptions:\n -f FOO, --foo FOO an argument\n"
138 133 )
139 134 assert getattr(foo, "argcmd_name", None) == None
140 135 assert real_name(foo) == "foo"
@@ -141,9 +141,7 def test_pprint_heap_allocated_type():
141 141 Test that pprint works for heap allocated types.
142 142 """
143 143 module_name = "xxlimited_35"
144 expected_output = (
145 "xxlimited.Null" if sys.version_info < (3, 10, 6) else "xxlimited_35.Null"
146 )
144 expected_output = "xxlimited_35.Null"
147 145 xxlimited = pytest.importorskip(module_name)
148 146 output = pretty.pretty(xxlimited.Null)
149 147 assert output == expected_output
@@ -19,10 +19,7
19 19 import sys, os
20 20 from pathlib import Path
21 21
22 if sys.version_info > (3, 11):
23 22 import tomllib
24 else:
25 import tomli as tomllib
26 23
27 24 with open("./sphinx.toml", "rb") as f:
28 25 config = tomllib.load(f)
@@ -20,11 +20,10 classifiers = [
20 20 "Programming Language :: Python :: 3 :: Only",
21 21 "Topic :: System :: Shells",
22 22 ]
23 requires-python = ">=3.10"
23 requires-python = ">=3.11"
24 24 dependencies = [
25 25 'colorama; sys_platform == "win32"',
26 26 "decorator",
27 "exceptiongroup; python_version<'3.11'",
28 27 "jedi>=0.16",
29 28 "matplotlib-inline",
30 29 'pexpect>4.3; sys_platform != "win32" and sys_platform != "emscripten"',
@@ -71,7 +70,6 doc = [
71 70 "sphinx-rtd-theme",
72 71 "sphinx>=1.3",
73 72 "sphinxcontrib-jquery",
74 "tomli ; python_version<'3.11'",
75 73 "typing_extensions",
76 74 ]
77 75 kernel = [
@@ -23,7 +23,7 import sys
23 23 #
24 24 # This check is also made in IPython/__init__, don't forget to update both when
25 25 # changing Python version requirements.
26 if sys.version_info < (3, 10):
26 if sys.version_info < (3, 11):
27 27 pip_message = 'This may be due to an out of date pip. Make sure you have pip >= 9.0.1.'
28 28 try:
29 29 import pip
@@ -39,18 +39,10 if sys.version_info < (3, 10):
39 39
40 40
41 41 error = """
42 (information not available for more recent version of IPython)
42 43 IPython 8.19+ supports Python 3.10 and above, following SPEC0
43 44 IPython 8.13+ supports Python 3.9 and above, following NEP 29.
44 45 IPython 8.0-8.12 supports Python 3.8 and above, following NEP 29.
45 When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
46 Python 3.3 and 3.4 were supported up to IPython 6.x.
47 Python 3.5 was supported with IPython 7.0 to 7.9.
48 Python 3.6 was supported with IPython up to 7.16.
49 Python 3.7 was still supported with the 7.x branch.
50
51 See IPython `README.rst` file for more information:
52
53 https://github.com/ipython/ipython/blob/main/README.rst
54 46
55 47 Python {py} detected.
56 48 {pip}
General Comments 0
You need to be logged in to leave comments. Login now