##// END OF EJS Templates
Drop Python 3.10 (#14589)
M Bussonnier -
r28984:f32e1b2a merge
parent child Browse files
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
@@ -40,15 +37,15 jobs:
40 37 python-version: "3.13"
41 38 deps: test
42 39 # Installing optional dependencies stuff takes ages on PyPy
43 - os: ubuntu-latest
44 python-version: "pypy-3.10"
45 deps: test
46 - os: windows-latest
47 python-version: "pypy-3.10"
48 deps: test
49 - os: macos-latest
50 python-version: "pypy-3.10"
51 deps: test
40 # - os: ubuntu-latest
41 # python-version: "pypy-3.11"
42 # deps: test
43 # - os: windows-latest
44 # python-version: "pypy-3.11"
45 # deps: test
46 # - os: macos-latest
47 # python-version: "pypy-3.11"
48 # deps: test
52 49 # Temporary CI run to use entry point compatible code in matplotlib-inline.
53 50 - os: ubuntu-latest
54 51 python-version: "3.12"
@@ -88,7 +85,7 jobs:
88 85 if: runner.os != 'Windows' # setup.py does not support sdist on Windows
89 86 run: check-manifest
90 87
91 - name: Install entry point compatible code (TEMPORARY)
88 - name: Install entry point compatible code (TEMPORARY, April 2024)
92 89 if: matrix.want-latest-entry-point-code
93 90 run: |
94 91 python -m pip list
@@ -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.
@@ -243,6 +243,14 from traitlets.config.configurable import Configurable
243 243
244 244 import __main__
245 245
246 from typing import cast
247
248 if sys.version_info < (3, 12):
249 from typing_extensions import TypedDict, NotRequired, Protocol, TypeAlias, TypeGuard
250 else:
251 from typing import TypedDict, NotRequired, Protocol, TypeAlias, TypeGuard
252
253
246 254 # skip module docstests
247 255 __skip_doctest__ = True
248 256
@@ -257,25 +265,6 except ImportError:
257 265 JEDI_INSTALLED = False
258 266
259 267
260 if TYPE_CHECKING or GENERATING_DOCUMENTATION and sys.version_info >= (3, 11):
261 from typing import cast
262 from typing_extensions import TypedDict, NotRequired, Protocol, TypeAlias, TypeGuard
263 else:
264 from typing import Generic
265
266 def cast(type_, obj):
267 """Workaround for `TypeError: MatcherAPIv2() takes no arguments`"""
268 return obj
269
270 # do not require on runtime
271 NotRequired = Tuple # requires Python >=3.11
272 TypedDict = Dict # by extension of `NotRequired` requires 3.11 too
273 Protocol = object # requires Python >=3.8
274 TypeAlias = Any # requires Python >=3.10
275 TypeGuard = Generic # requires Python >=3.10
276 if GENERATING_DOCUMENTATION:
277 from typing import TypedDict
278
279 268 # -----------------------------------------------------------------------------
280 269 # Globals
281 270 #-----------------------------------------------------------------------------
@@ -31,10 +31,7 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 from typing import Self, LiteralString
34 from typing import Self, LiteralString
38 35
39 36 if sys.version_info < (3, 12):
40 37 from typing_extensions import TypeAliasType
@@ -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,10 +23,7 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 from typing import Self, LiteralString
26 from typing import Self, LiteralString
30 27
31 28 if sys.version_info < (3, 12):
32 29 from typing_extensions import TypeAliasType
@@ -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 import tomllib
24 else:
25 import tomli as tomllib
22 import 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,8 +70,6 doc = [
71 70 "sphinx-rtd-theme",
72 71 "sphinx>=1.3",
73 72 "sphinxcontrib-jquery",
74 "tomli ; python_version<'3.11'",
75 "typing_extensions",
76 73 ]
77 74 kernel = [
78 75 "ipykernel",
@@ -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