--- a/mercurial/pycompat.py Tue Oct 15 22:30:10 2024 -0400
+++ b/mercurial/pycompat.py Thu Oct 24 15:23:52 2024 +0200
@@ -349,12 +349,46 @@
raise exc.with_traceback(tb)
+# Copied over from the 3.13 Python stdlib `inspect.cleandoc`, with a couple
+# of removals explained inline.
+# It differs slightly from the 3.8+ version, so it's better to use the same
+# version to remove any potential for variation.
+def cleandoc(doc):
+ """Clean up indentation from docstrings.
+
+ Any whitespace that can be uniformly removed from the second line
+ onwards is removed."""
+ lines = doc.expandtabs().split('\n')
+
+ # Find minimum indentation of any non-blank lines after first line.
+ margin = sys.maxsize
+ for line in lines[1:]:
+ content = len(line.lstrip(' '))
+ if content:
+ indent = len(line) - content
+ margin = min(margin, indent)
+ # Remove indentation.
+ if lines:
+ lines[0] = lines[0].lstrip(' ')
+ if margin < sys.maxsize:
+ for i in range(1, len(lines)):
+ lines[i] = lines[i][margin:]
+ # Here the upstream *Python* version does newline trimming, but it looks
+ # like the compiler (written in C) does not, so go with what the compiler
+ # does.
+ return '\n'.join(lines)
+
+
def getdoc(obj: object) -> Optional[bytes]:
"""Get docstring as bytes; may be None so gettext() won't confuse it
with _('')"""
doc = builtins.getattr(obj, '__doc__', None)
if doc is None:
return doc
+ if sys.version_info < (3, 13):
+ # Python 3.13+ "cleans up" the docstring at compile time, let's
+ # normalize this behavior for previous versions
+ doc = cleandoc(doc)
return sysbytes(doc)