From 9fa116b3ddfb8065421fd6a5a9320bf7bd1646e3 Mon Sep 17 00:00:00 2001 From: Sandro Date: Mon, 1 Apr 2024 15:59:57 +0200 Subject: [PATCH] Python 3.13: Account for dedented docstrings - Dedent docstrings in Python 3.13+ - Fix #1311 - Ref: https://github.com/python/cpython/issues/81283 --- nibabel/deprecator.py | 15 +++++++++++++++ nibabel/tests/test_deprecator.py | 15 ++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/nibabel/deprecator.py b/nibabel/deprecator.py index 779fdb462d..a80fa25692 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 833908af94..4303ff6737 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)