Skip to content

Commit ed801fc

Browse files
committed
DEP: Support Python 3.13
1 parent 730358c commit ed801fc

File tree

6 files changed

+59
-45
lines changed

6 files changed

+59
-45
lines changed

.github/workflows/tests.yml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ jobs:
5656
fail-fast: false
5757
matrix:
5858
include:
59+
- os: ubuntu-latest
60+
python: '3.13'
61+
kind: pip
5962
- os: ubuntu-latest
6063
python: '3.12'
6164
kind: pip-pre
@@ -92,13 +95,6 @@ jobs:
9295
with:
9396
python-version: ${{ matrix.python }}
9497
if: startswith(matrix.kind, 'pip')
95-
# Python (if conda)
96-
- name: Remove numba and dipy
97-
run: | # TODO: Remove when numba 0.59 and dipy 1.8 land on conda-forge
98-
sed -i '/numba/d' environment.yml
99-
sed -i '/dipy/d' environment.yml
100-
sed -i 's/- mne$/- mne-base/' environment.yml
101-
if: matrix.os == 'ubuntu-latest' && startswith(matrix.kind, 'conda') && matrix.python == '3.12'
10298
- uses: mamba-org/setup-micromamba@v2
10399
with:
104100
environment-file: ${{ env.CONDA_ENV }}

doc/changes/devel/dependency.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Compatibility improved for Python 3.13, by `Eric Larson`.

mne/utils/docs.py

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5109,6 +5109,8 @@ def copy_doc(source):
51095109
This is useful when inheriting from a class and overloading a method. This
51105110
decorator can be used to copy the docstring of the original method.
51115111
5112+
Docstrings are processed by :func:`python:inspect.cleandoc` before being used.
5113+
51125114
Parameters
51135115
----------
51145116
source : function
@@ -5131,15 +5133,16 @@ def copy_doc(source):
51315133
... ''' this gets appended'''
51325134
... pass
51335135
>>> print(B.m1.__doc__)
5134-
Docstring for m1 this gets appended
5136+
Docstring for m1
5137+
this gets appended
51355138
"""
51365139

51375140
def wrapper(func):
51385141
if source.__doc__ is None or len(source.__doc__) == 0:
51395142
raise ValueError("Cannot copy docstring: docstring was empty.")
51405143
doc = source.__doc__
51415144
if func.__doc__ is not None:
5142-
doc += func.__doc__
5145+
doc += f"\n{inspect.cleandoc(func.__doc__)}"
51435146
func.__doc__ = doc
51445147
return func
51455148

@@ -5158,6 +5161,10 @@ def copy_function_doc_to_method_doc(source):
51585161
function. This pattern is prevalent in for example the plotting functions
51595162
of MNE.
51605163
5164+
Docstrings are parsed by :func:`python:inspect.cleandoc` before being used.
5165+
If indentation and newlines are important, make the first line ``.``, and the dot
5166+
will be removed and all following lines dedented jointly.
5167+
51615168
Parameters
51625169
----------
51635170
source : function
@@ -5193,7 +5200,8 @@ def copy_function_doc_to_method_doc(source):
51935200
>>> class A:
51945201
... @copy_function_doc_to_method_doc(plot_function)
51955202
... def plot(self, a, b):
5196-
... '''
5203+
... '''.
5204+
...
51975205
... Notes
51985206
... -----
51995207
... .. versionadded:: 0.13.0
@@ -5202,26 +5210,31 @@ def copy_function_doc_to_method_doc(source):
52025210
>>> print(A.plot.__doc__)
52035211
Docstring for plotting function.
52045212
<BLANKLINE>
5205-
Parameters
5206-
----------
5207-
a : int
5208-
Some parameter
5209-
b : int
5210-
Some parameter
5211-
<BLANKLINE>
5212-
Notes
5213-
-----
5214-
.. versionadded:: 0.13.0
5213+
Parameters
5214+
----------
5215+
a : int
5216+
Some parameter
5217+
b : int
5218+
Some parameter
52155219
<BLANKLINE>
5220+
Notes
5221+
-----
5222+
.. versionadded:: 0.13.0
52165223
""" # noqa: D410, D411, D214, D215
52175224

52185225
def wrapper(func):
5219-
doc = source.__doc__.split("\n")
5226+
# Work with cleandoc'ed sources (py3.13-compat)
5227+
doc = inspect.cleandoc(source.__doc__).split("\n")
5228+
if func.__doc__ is not None:
5229+
func_doc = inspect.cleandoc(func.__doc__)
5230+
if func_doc[:2] == ".\n":
5231+
func_doc = func_doc[2:]
5232+
func_doc = f"\n{func_doc}"
5233+
else:
5234+
func_doc = ""
5235+
52205236
if len(doc) == 1:
5221-
doc = doc[0]
5222-
if func.__doc__ is not None:
5223-
doc += func.__doc__
5224-
func.__doc__ = doc
5237+
func.__doc__ = f"{doc[0]}{func_doc}"
52255238
return func
52265239

52275240
# Find parameter block
@@ -5269,7 +5282,7 @@ def wrapper(func):
52695282
break
52705283
else:
52715284
# End of docstring reached
5272-
first_parameter_end = line
5285+
first_parameter_end = line + 1
52735286
first_parameter = parameter_block
52745287

52755288
# Copy the docstring, but remove the first parameter
@@ -5278,9 +5291,7 @@ def wrapper(func):
52785291
+ "\n"
52795292
+ "\n".join(doc[first_parameter_end:])
52805293
)
5281-
if func.__doc__ is not None:
5282-
doc += func.__doc__
5283-
func.__doc__ = doc
5294+
func.__doc__ = f"{doc}{func_doc}"
52845295
return func
52855296

52865297
return wrapper

mne/utils/tests/test_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def test_sys_info_complete():
129129
pyproject = tomllib.loads(pyproject.read_text("utf-8"))
130130
deps = pyproject["project"]["optional-dependencies"]["test_extra"]
131131
for dep in deps:
132-
dep = dep.split("[")[0].split(">")[0]
132+
dep = dep.split("[")[0].split(">")[0].strip()
133133
assert f" {dep}" in out, f"Missing in dev config: {dep}"
134134

135135

mne/utils/tests/test_docs.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -195,28 +195,29 @@ def method_f3(self):
195195

196196
assert (
197197
A.method_f1.__doc__
198-
== """Docstring for f1.
199-
200-
Parameters
201-
----------
202-
a : int
203-
Parameter a
204-
b : int
205-
Parameter b
206-
"""
198+
== """\
199+
Docstring for f1.
200+
201+
Parameters
202+
----------
203+
a : int
204+
Parameter a
205+
b : int
206+
Parameter b"""
207207
)
208208

209209
assert (
210210
A.method_f2.__doc__
211-
== """Docstring for f2.
211+
== """\
212+
Docstring for f2.
212213
213-
Returns
214-
-------
215-
nothing.
216-
method_f3 own docstring"""
214+
Returns
215+
-------
216+
nothing.
217+
method_f3 own docstring"""
217218
)
218219

219-
assert A.method_f3.__doc__ == "Docstring for f3.\n\n "
220+
assert A.method_f3.__doc__ == "Docstring for f3.\n\n"
220221
pytest.raises(ValueError, copy_function_doc_to_method_doc(f5), A.method_f1)
221222

222223

tools/github_actions_dependencies.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ if [ ! -z "$CONDA_ENV" ]; then
2020
INSTALL_KIND="test"
2121
STD_ARGS="--progress-bar off"
2222
fi
23+
elif [[ "${MNE_CI_KIND}" == "pip" ]]; then
24+
# Only used for 3.13 at the moment, just get test deps plus a few extras
25+
# that we know are available
26+
INSTALL_ARGS="nibabel scikit-learn numpydoc PySide6 mne-qt-browser"
27+
INSTALL_KIND="test"
2328
else
2429
test "${MNE_CI_KIND}" == "pip-pre"
2530
STD_ARGS="$STD_ARGS --pre"

0 commit comments

Comments
 (0)