comparison mercurial/pycompat.py @ 52084:51057ab0dffa stable

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 7e6aae033d8d
children b5efb7a7d2a5
comparison
equal deleted inserted replaced
52083:888e00b2c3ee 52084:51057ab0dffa
346 def raisewithtb(exc: BaseException, tb) -> NoReturn: 346 def raisewithtb(exc: BaseException, tb) -> NoReturn:
347 """Raise exception with the given traceback""" 347 """Raise exception with the given traceback"""
348 raise exc.with_traceback(tb) 348 raise exc.with_traceback(tb)
349 349
350 350
351 # Copied over from the 3.13 Python stdlib `inspect.cleandoc`, with a couple
352 # of removals explained inline.
353 # It differs slightly from the 3.8+ version, so it's better to use the same
354 # version to remove any potential for variation.
355 def cleandoc(doc):
356 """Clean up indentation from docstrings.
357
358 Any whitespace that can be uniformly removed from the second line
359 onwards is removed."""
360 lines = doc.expandtabs().split('\n')
361
362 # Find minimum indentation of any non-blank lines after first line.
363 margin = sys.maxsize
364 for line in lines[1:]:
365 content = len(line.lstrip(' '))
366 if content:
367 indent = len(line) - content
368 margin = min(margin, indent)
369 # Remove indentation.
370 if lines:
371 lines[0] = lines[0].lstrip(' ')
372 if margin < sys.maxsize:
373 for i in range(1, len(lines)):
374 lines[i] = lines[i][margin:]
375 # Here the upstream *Python* version does newline trimming, but it looks
376 # like the compiler (written in C) does not, so go with what the compiler
377 # does.
378 return '\n'.join(lines)
379
380
351 def getdoc(obj: object) -> Optional[bytes]: 381 def getdoc(obj: object) -> Optional[bytes]:
352 """Get docstring as bytes; may be None so gettext() won't confuse it 382 """Get docstring as bytes; may be None so gettext() won't confuse it
353 with _('')""" 383 with _('')"""
354 doc = builtins.getattr(obj, '__doc__', None) 384 doc = builtins.getattr(obj, '__doc__', None)
355 if doc is None: 385 if doc is None:
356 return doc 386 return doc
387 if sys.version_info < (3, 13):
388 # Python 3.13+ "cleans up" the docstring at compile time, let's
389 # normalize this behavior for previous versions
390 doc = cleandoc(doc)
357 return sysbytes(doc) 391 return sysbytes(doc)
358 392
359 393
360 # these wrappers are automagically imported by hgloader 394 # these wrappers are automagically imported by hgloader
361 delattr = builtins.delattr 395 delattr = builtins.delattr