##// END OF EJS Templates
Drop Python 3.10
M Bussonnier -
Show More
@@ -19,10 +19,10 jobs:
19 strategy:
19 strategy:
20 matrix:
20 matrix:
21 os: [ubuntu-latest]
21 os: [ubuntu-latest]
22 python-version: ["3.10"]
22 python-version: ["3.13"]
23 include:
23 include:
24 - os: macos-13
24 - os: macos-13
25 python-version: "3.10"
25 python-version: "3.13"
26
26
27 steps:
27 steps:
28 - uses: actions/checkout@v4
28 - uses: actions/checkout@v4
@@ -17,7 +17,7 jobs:
17 - name: Set up Python
17 - name: Set up Python
18 uses: actions/setup-python@v5
18 uses: actions/setup-python@v5
19 with:
19 with:
20 python-version: "3.10"
20 python-version: "3.13"
21 cache: pip
21 cache: pip
22 cache-dependency-path: |
22 cache-dependency-path: |
23 pyproject.toml
23 pyproject.toml
@@ -21,14 +21,11 jobs:
21 fail-fast: false
21 fail-fast: false
22 matrix:
22 matrix:
23 os: [ubuntu-latest, windows-latest]
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 deps: [test_extra]
25 deps: [test_extra]
26 # Test all on ubuntu, test ends on macos
26 # Test all on ubuntu, test ends on macos
27 include:
27 include:
28 - os: macos-latest
28 - os: macos-latest
29 python-version: "3.10"
30 deps: test_extra
31 - os: macos-latest
32 python-version: "3.11"
29 python-version: "3.11"
33 deps: test_extra
30 deps: test_extra
34 # Tests minimal dependencies set
31 # Tests minimal dependencies set
@@ -41,13 +38,13 jobs:
41 deps: test
38 deps: test
42 # Installing optional dependencies stuff takes ages on PyPy
39 # Installing optional dependencies stuff takes ages on PyPy
43 - os: ubuntu-latest
40 - os: ubuntu-latest
44 python-version: "pypy-3.10"
41 python-version: "pypy-3.11"
45 deps: test
42 deps: test
46 - os: windows-latest
43 - os: windows-latest
47 python-version: "pypy-3.10"
44 python-version: "pypy-3.11"
48 deps: test
45 deps: test
49 - os: macos-latest
46 - os: macos-latest
50 python-version: "pypy-3.10"
47 python-version: "pypy-3.11"
51 deps: test
48 deps: test
52 # Temporary CI run to use entry point compatible code in matplotlib-inline.
49 # Temporary CI run to use entry point compatible code in matplotlib-inline.
53 - os: ubuntu-latest
50 - os: ubuntu-latest
@@ -26,9 +26,10 import sys
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27
27
28 # Don't forget to also update setup.py when this changes!
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 raise ImportError(
30 raise ImportError(
31 """
31 """
32 IPython 8.31+ supports Python 3.11 and above, following SPEC0
32 IPython 8.19+ supports Python 3.10 and above, following SPEC0.
33 IPython 8.19+ supports Python 3.10 and above, following SPEC0.
33 IPython 8.13+ supports Python 3.9 and above, following NEP 29.
34 IPython 8.13+ supports Python 3.9 and above, following NEP 29.
34 IPython 8.0-8.12 supports Python 3.8 and above, following NEP 29.
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 import __main__
243 import __main__
244
244
245 from typing import cast
246 from typing_extensions import TypedDict, NotRequired, Protocol, TypeAlias, TypeGuard
247
248
245 # skip module docstests
249 # skip module docstests
246 __skip_doctest__ = True
250 __skip_doctest__ = True
247
251
@@ -256,22 +260,7 except ImportError:
256 JEDI_INSTALLED = False
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 if GENERATING_DOCUMENTATION:
264 if GENERATING_DOCUMENTATION:
276 from typing import TypedDict
265 from typing import TypedDict
277
266
@@ -31,9 +31,6 from types import MethodDescriptorType, ModuleType
31 from IPython.utils.decorators import undoc
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 if sys.version_info < (3, 12):
36 if sys.version_info < (3, 12):
@@ -149,8 +149,6 try:
149 except ImportError:
149 except ImportError:
150 sphinxify = None
150 sphinxify = None
151
151
152 if sys.version_info[:2] < (3, 11):
153 from exceptiongroup import BaseExceptionGroup
154
152
155 class ProvisionalWarning(DeprecationWarning):
153 class ProvisionalWarning(DeprecationWarning):
156 """
154 """
@@ -13,7 +13,6 def _exceptiongroup_common(
13 native: bool,
13 native: bool,
14 ) -> None:
14 ) -> None:
15 pre_raise = "exceptiongroup." if not native else ""
15 pre_raise = "exceptiongroup." if not native else ""
16 pre_catch = pre_raise if sys.version_info < (3, 11) else ""
17 filestr = f"""
16 filestr = f"""
18 {"import exceptiongroup" if not native else ""}
17 {"import exceptiongroup" if not native else ""}
19 import pytest
18 import pytest
@@ -42,7 +41,7 def _exceptiongroup_common(
42 def outer(outer_chain, inner_chain):
41 def outer(outer_chain, inner_chain):
43 try:
42 try:
44 inner(inner_chain)
43 inner(inner_chain)
45 except {pre_catch}BaseExceptionGroup as e:
44 except BaseExceptionGroup as e:
46 if outer_chain == "none":
45 if outer_chain == "none":
47 raise
46 raise
48 if outer_chain == "from":
47 if outer_chain == "from":
@@ -68,7 +67,7 def _exceptiongroup_common(
68
67
69 match_lines += [
68 match_lines += [
70 " + Exception Group Traceback (most recent call last):",
69 " + Exception Group Traceback (most recent call last):",
71 f" | {pre_catch}BaseExceptionGroup: Oops (2 sub-exceptions)",
70 " | BaseExceptionGroup: Oops (2 sub-exceptions)",
72 " | ValueError: From f()",
71 " | ValueError: From f()",
73 " | BaseException: From g()",
72 " | BaseException: From g()",
74 ]
73 ]
@@ -96,9 +95,6 def _exceptiongroup_common(
96 assert False, f"{expected} not found in cap.stderr"
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 @pytest.mark.parametrize("outer_chain", ["none", "from", "another"])
98 @pytest.mark.parametrize("outer_chain", ["none", "from", "another"])
103 @pytest.mark.parametrize("inner_chain", ["none", "from", "another"])
99 @pytest.mark.parametrize("inner_chain", ["none", "from", "another"])
104 def test_native_exceptiongroup(outer_chain, inner_chain) -> None:
100 def test_native_exceptiongroup(outer_chain, inner_chain) -> None:
@@ -23,9 +23,6 from IPython.testing import decorators as dec
23 import pytest
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 if sys.version_info < (3, 12):
28 if sys.version_info < (3, 12):
@@ -320,12 +320,6 class InputSplitterTestCase(unittest.TestCase):
320 self.isp.push(u'\xc3\xa9')
320 self.isp.push(u'\xc3\xa9')
321 self.isp.push(u"u'\xc3\xa9'")
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 def test_line_continuation(self):
323 def test_line_continuation(self):
330 """ Test issue #2108."""
324 """ Test issue #2108."""
331 isp = self.isp
325 isp = self.isp
@@ -314,17 +314,7 examples = [
314 pytest.param("\\\r\n", "incomplete", 0),
314 pytest.param("\\\r\n", "incomplete", 0),
315 pytest.param("a = '''\n hi", "incomplete", 3),
315 pytest.param("a = '''\n hi", "incomplete", 3),
316 pytest.param("def a():\n x=1\n global x", "invalid", None),
316 pytest.param("def a():\n x=1\n global x", "invalid", None),
317 pytest.param(
317 pytest.param("a \\ ", "invalid", None), # Nothing allowed after backslash,
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,
328 pytest.param("1\\\n+2", "complete", None),
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 @pytest.mark.xfail(platform.python_implementation() == "PyPy", reason="fail on pypy")
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 def test_check_complete():
329 def test_check_complete():
346 cc = ipt2.TransformerManager().check_complete
330 cc = ipt2.TransformerManager().check_complete
347
331
@@ -76,14 +76,9 def foo(self, args):
76
76
77
77
78 def test_magic_arguments():
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 assert (
79 assert (
85 magic_foo1.__doc__
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 assert getattr(magic_foo1, "argcmd_name", None) == None
83 assert getattr(magic_foo1, "argcmd_name", None) == None
89 assert real_name(magic_foo1) == "foo1"
84 assert real_name(magic_foo1) == "foo1"
@@ -98,7 +93,7 def test_magic_arguments():
98
93
99 assert (
94 assert (
100 magic_foo3.__doc__
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 assert getattr(magic_foo3, "argcmd_name", None) == None
98 assert getattr(magic_foo3, "argcmd_name", None) == None
104 assert real_name(magic_foo3) == "foo3"
99 assert real_name(magic_foo3) == "foo3"
@@ -107,7 +102,7 def test_magic_arguments():
107
102
108 assert (
103 assert (
109 magic_foo4.__doc__
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 assert getattr(magic_foo4, "argcmd_name", None) == None
107 assert getattr(magic_foo4, "argcmd_name", None) == None
113 assert real_name(magic_foo4) == "foo4"
108 assert real_name(magic_foo4) == "foo4"
@@ -116,7 +111,7 def test_magic_arguments():
116
111
117 assert (
112 assert (
118 magic_foo5.__doc__
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 assert getattr(magic_foo5, "argcmd_name", None) == "frobnicate"
116 assert getattr(magic_foo5, "argcmd_name", None) == "frobnicate"
122 assert real_name(magic_foo5) == "frobnicate"
117 assert real_name(magic_foo5) == "frobnicate"
@@ -125,7 +120,7 def test_magic_arguments():
125
120
126 assert (
121 assert (
127 magic_magic_foo.__doc__
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 assert getattr(magic_magic_foo, "argcmd_name", None) == None
125 assert getattr(magic_magic_foo, "argcmd_name", None) == None
131 assert real_name(magic_magic_foo) == "magic_foo"
126 assert real_name(magic_magic_foo) == "magic_foo"
@@ -134,7 +129,7 def test_magic_arguments():
134
129
135 assert (
130 assert (
136 foo.__doc__
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 assert getattr(foo, "argcmd_name", None) == None
134 assert getattr(foo, "argcmd_name", None) == None
140 assert real_name(foo) == "foo"
135 assert real_name(foo) == "foo"
@@ -141,9 +141,7 def test_pprint_heap_allocated_type():
141 Test that pprint works for heap allocated types.
141 Test that pprint works for heap allocated types.
142 """
142 """
143 module_name = "xxlimited_35"
143 module_name = "xxlimited_35"
144 expected_output = (
144 expected_output = "xxlimited_35.Null"
145 "xxlimited.Null" if sys.version_info < (3, 10, 6) else "xxlimited_35.Null"
146 )
147 xxlimited = pytest.importorskip(module_name)
145 xxlimited = pytest.importorskip(module_name)
148 output = pretty.pretty(xxlimited.Null)
146 output = pretty.pretty(xxlimited.Null)
149 assert output == expected_output
147 assert output == expected_output
@@ -19,10 +19,7
19 import sys, os
19 import sys, os
20 from pathlib import Path
20 from pathlib import Path
21
21
22 if sys.version_info > (3, 11):
23 import tomllib
22 import tomllib
24 else:
25 import tomli as tomllib
26
23
27 with open("./sphinx.toml", "rb") as f:
24 with open("./sphinx.toml", "rb") as f:
28 config = tomllib.load(f)
25 config = tomllib.load(f)
@@ -20,11 +20,10 classifiers = [
20 "Programming Language :: Python :: 3 :: Only",
20 "Programming Language :: Python :: 3 :: Only",
21 "Topic :: System :: Shells",
21 "Topic :: System :: Shells",
22 ]
22 ]
23 requires-python = ">=3.10"
23 requires-python = ">=3.11"
24 dependencies = [
24 dependencies = [
25 'colorama; sys_platform == "win32"',
25 'colorama; sys_platform == "win32"',
26 "decorator",
26 "decorator",
27 "exceptiongroup; python_version<'3.11'",
28 "jedi>=0.16",
27 "jedi>=0.16",
29 "matplotlib-inline",
28 "matplotlib-inline",
30 'pexpect>4.3; sys_platform != "win32" and sys_platform != "emscripten"',
29 'pexpect>4.3; sys_platform != "win32" and sys_platform != "emscripten"',
@@ -71,7 +70,6 doc = [
71 "sphinx-rtd-theme",
70 "sphinx-rtd-theme",
72 "sphinx>=1.3",
71 "sphinx>=1.3",
73 "sphinxcontrib-jquery",
72 "sphinxcontrib-jquery",
74 "tomli ; python_version<'3.11'",
75 "typing_extensions",
73 "typing_extensions",
76 ]
74 ]
77 kernel = [
75 kernel = [
@@ -23,7 +23,7 import sys
23 #
23 #
24 # This check is also made in IPython/__init__, don't forget to update both when
24 # This check is also made in IPython/__init__, don't forget to update both when
25 # changing Python version requirements.
25 # changing Python version requirements.
26 if sys.version_info < (3, 10):
26 if sys.version_info < (3, 11):
27 pip_message = 'This may be due to an out of date pip. Make sure you have pip >= 9.0.1.'
27 pip_message = 'This may be due to an out of date pip. Make sure you have pip >= 9.0.1.'
28 try:
28 try:
29 import pip
29 import pip
@@ -39,18 +39,10 if sys.version_info < (3, 10):
39
39
40
40
41 error = """
41 error = """
42 (information not available for more recent version of IPython)
42 IPython 8.19+ supports Python 3.10 and above, following SPEC0
43 IPython 8.19+ supports Python 3.10 and above, following SPEC0
43 IPython 8.13+ supports Python 3.9 and above, following NEP 29.
44 IPython 8.13+ supports Python 3.9 and above, following NEP 29.
44 IPython 8.0-8.12 supports Python 3.8 and above, following NEP 29.
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 Python {py} detected.
47 Python {py} detected.
56 {pip}
48 {pip}
General Comments 0
You need to be logged in to leave comments. Login now