Mercurial > public > mercurial-scm > hg-stable
diff mercurial/pycompat.py @ 52113:31076a2301f1
py-3-13: stabilize the docstring output across all supported Python versions
Python 3.13 now trims indents from docstrings at compilation time
(to save space in .pyc), so all of our helptext is affected.
The indentation has never served a user-facing purpose and was more here
because nobody cared enough to remove it: we gain some screen space this way.
Rather than undo the transformation (which isn't really possible since the
transform also deletes leading/trailing whitespace), we align the behavior
of older Python versions with that of 3.13.
Unfortunately, this means breaking some of the translations. I've only
touched the ones that need to work for some tooling tests to pass, but
I do not have the time to fix the rest of them across all languages, since
they cannot be done in an automated way. i18n updates have been basically
abandonned for a good while now, hopefully someone cares enough to bring them
back.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Thu, 24 Oct 2024 15:23:52 +0200 |
parents | f4733654f144 |
children | 19ae7730636a |
line wrap: on
line diff
--- 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)