diff --git a/nibabel/deprecator.py b/nibabel/deprecator.py index 779fdb462..a80fa2569 100644 --- a/nibabel/deprecator.py +++ b/nibabel/deprecator.py @@ -3,8 +3,10 @@ import functools import re +import sys import typing as ty import warnings +from textwrap import dedent if ty.TYPE_CHECKING: # pragma: no cover T = ty.TypeVar('T') @@ -12,6 +14,15 @@ _LEADING_WHITE = re.compile(r'^(\s*)') + +def _dedent_docstring(docstring): + """Compatibility with Python 3.13+. + + xref: https://github.com/python/cpython/issues/81283 + """ + return '\n'.join([dedent(line) for line in docstring.split('\n')]) + + TESTSETUP = """ .. testsetup:: @@ -32,6 +43,10 @@ """ +if sys.version_info >= (3, 13): + TESTSETUP = _dedent_docstring(TESTSETUP) + TESTCLEANUP = _dedent_docstring(TESTCLEANUP) + class ExpiredDeprecationError(RuntimeError): """Error for expired deprecation diff --git a/nibabel/tests/test_deprecator.py b/nibabel/tests/test_deprecator.py index 833908af9..4303ff673 100644 --- a/nibabel/tests/test_deprecator.py +++ b/nibabel/tests/test_deprecator.py @@ -14,6 +14,7 @@ Deprecator, ExpiredDeprecationError, _add_dep_doc, + _dedent_docstring, _ensure_cr, ) @@ -21,6 +22,14 @@ _OWN_MODULE = sys.modules[__name__] +func_docstring = ( + f'A docstring\n \n foo\n \n{indent(TESTSETUP, " ", lambda x: True)}' + f' Some text\n{indent(TESTCLEANUP, " ", lambda x: True)}' +) + +if sys.version_info >= (3, 13): + func_docstring = _dedent_docstring(func_docstring) + def test__ensure_cr(): # Make sure text ends with carriage return @@ -92,11 +101,7 @@ def test_dep_func(self): with pytest.deprecated_call() as w: assert func(1, 2) is None assert len(w) == 1 - assert ( - func.__doc__ - == f'A docstring\n \n foo\n \n{indent(TESTSETUP, " ", lambda x: True)}' - f' Some text\n{indent(TESTCLEANUP, " ", lambda x: True)}' - ) + assert func.__doc__ == func_docstring # Try some since and until versions func = dec('foo', '1.1')(func_no_doc)