##// END OF EJS Templates
typing: add basic type hints to stringutil.py
Matt Harbison -
r50470:bbbb5213 default
parent child Browse files
Show More
@@ -14,6 +14,11 b' import re as remod'
14 14 import textwrap
15 15 import types
16 16
17 from typing import (
18 Optional,
19 overload,
20 )
21
17 22 from ..i18n import _
18 23 from ..thirdparty import attr
19 24
@@ -30,6 +35,16 b' from .. import ('
30 35 regexbytesescapemap = {i: (b'\\' + i) for i in _respecial}
31 36
32 37
38 @overload
39 def reescape(pat: bytes) -> bytes:
40 ...
41
42
43 @overload
44 def reescape(pat: str) -> str:
45 ...
46
47
33 48 def reescape(pat):
34 49 """Drop-in replacement for re.escape."""
35 50 # NOTE: it is intentional that this works on unicodes and not
@@ -45,12 +60,12 b' def reescape(pat):'
45 60 return pat.encode('latin1')
46 61
47 62
48 def pprint(o, bprefix=False, indent=0, level=0):
63 def pprint(o, bprefix: bool = False, indent: int = 0, level: int = 0) -> bytes:
49 64 """Pretty print an object."""
50 65 return b''.join(pprintgen(o, bprefix=bprefix, indent=indent, level=level))
51 66
52 67
53 def pprintgen(o, bprefix=False, indent=0, level=0):
68 def pprintgen(o, bprefix: bool = False, indent: int = 0, level: int = 0):
54 69 """Pretty print an object to a generator of atoms.
55 70
56 71 ``bprefix`` is a flag influencing whether bytestrings are preferred with
@@ -250,7 +265,7 b' def pprintgen(o, bprefix=False, indent=0'
250 265 yield pycompat.byterepr(o)
251 266
252 267
253 def prettyrepr(o):
268 def prettyrepr(o) -> bytes:
254 269 """Pretty print a representation of a possibly-nested object"""
255 270 lines = []
256 271 rs = pycompat.byterepr(o)
@@ -281,7 +296,7 b' def prettyrepr(o):'
281 296 return b'\n'.join(b' ' * l + s for l, s in lines)
282 297
283 298
284 def buildrepr(r):
299 def buildrepr(r) -> bytes:
285 300 """Format an optional printable representation from unexpanded bits
286 301
287 302 ======== =================================
@@ -305,12 +320,12 b' def buildrepr(r):'
305 320 return pprint(r)
306 321
307 322
308 def binary(s):
323 def binary(s: bytes) -> bool:
309 324 """return true if a string is binary data"""
310 325 return bool(s and b'\0' in s)
311 326
312 327
313 def _splitpattern(pattern):
328 def _splitpattern(pattern: bytes):
314 329 if pattern.startswith(b're:'):
315 330 return b're', pattern[3:]
316 331 elif pattern.startswith(b'literal:'):
@@ -318,7 +333,7 b' def _splitpattern(pattern):'
318 333 return b'literal', pattern
319 334
320 335
321 def stringmatcher(pattern, casesensitive=True):
336 def stringmatcher(pattern: bytes, casesensitive: bool = True):
322 337 """
323 338 accepts a string, possibly starting with 're:' or 'literal:' prefix.
324 339 returns the matcher name, pattern, and matcher function.
@@ -379,7 +394,7 b' def stringmatcher(pattern, casesensitive'
379 394 raise error.ProgrammingError(b'unhandled pattern kind: %s' % kind)
380 395
381 396
382 def substringregexp(pattern, flags=0):
397 def substringregexp(pattern: bytes, flags: int = 0):
383 398 """Build a regexp object from a string pattern possibly starting with
384 399 're:' or 'literal:' prefix.
385 400
@@ -431,7 +446,7 b' def substringregexp(pattern, flags=0):'
431 446 raise error.ProgrammingError(b'unhandled pattern kind: %s' % kind)
432 447
433 448
434 def shortuser(user):
449 def shortuser(user: bytes) -> bytes:
435 450 """Return a short representation of a user name or email address."""
436 451 f = user.find(b'@')
437 452 if f >= 0:
@@ -448,7 +463,7 b' def shortuser(user):'
448 463 return user
449 464
450 465
451 def emailuser(user):
466 def emailuser(user: bytes) -> bytes:
452 467 """Return the user portion of an email address."""
453 468 f = user.find(b'@')
454 469 if f >= 0:
@@ -459,7 +474,7 b' def emailuser(user):'
459 474 return user
460 475
461 476
462 def email(author):
477 def email(author: bytes) -> bytes:
463 478 '''get email of author.'''
464 479 r = author.find(b'>')
465 480 if r == -1:
@@ -467,7 +482,7 b' def email(author):'
467 482 return author[author.find(b'<') + 1 : r]
468 483
469 484
470 def person(author):
485 def person(author: bytes) -> bytes:
471 486 """Returns the name before an email address,
472 487 interpreting it as per RFC 5322
473 488
@@ -612,7 +627,7 b' def parsemailmap(mailmapcontent):'
612 627 return mailmap
613 628
614 629
615 def mapname(mailmap, author):
630 def mapname(mailmap, author: bytes) -> bytes:
616 631 """Returns the author field according to the mailmap cache, or
617 632 the original author field.
618 633
@@ -663,7 +678,7 b' def mapname(mailmap, author):'
663 678 _correctauthorformat = remod.compile(br'^[^<]+\s<[^<>]+@[^<>]+>$')
664 679
665 680
666 def isauthorwellformed(author):
681 def isauthorwellformed(author: bytes) -> bool:
667 682 """Return True if the author field is well formed
668 683 (ie "Contributor Name <contrib@email.dom>")
669 684
@@ -685,7 +700,7 b' def isauthorwellformed(author):'
685 700 return _correctauthorformat.match(author) is not None
686 701
687 702
688 def firstline(text):
703 def firstline(text: bytes) -> bytes:
689 704 """Return the first line of the input"""
690 705 # Try to avoid running splitlines() on the whole string
691 706 i = text.find(b'\n')
@@ -697,12 +712,13 b' def firstline(text):'
697 712 return b''
698 713
699 714
700 def ellipsis(text, maxlength=400):
715 def ellipsis(text: bytes, maxlength: int = 400) -> bytes:
701 716 """Trim string to at most maxlength (default: 400) columns in display."""
702 717 return encoding.trim(text, maxlength, ellipsis=b'...')
703 718
704 719
705 def escapestr(s):
720 def escapestr(s: bytes) -> bytes:
721 # "bytes" is also a typing shortcut for bytes, bytearray, and memoryview
706 722 if isinstance(s, memoryview):
707 723 s = bytes(s)
708 724 # call underlying function of s.encode('string_escape') directly for
@@ -710,7 +726,7 b' def escapestr(s):'
710 726 return codecs.escape_encode(s)[0] # pytype: disable=module-attr
711 727
712 728
713 def unescapestr(s):
729 def unescapestr(s: bytes) -> bytes:
714 730 return codecs.escape_decode(s)[0] # pytype: disable=module-attr
715 731
716 732
@@ -724,7 +740,7 b' def forcebytestr(obj):'
724 740 return pycompat.bytestr(encoding.strtolocal(str(obj)))
725 741
726 742
727 def uirepr(s):
743 def uirepr(s: bytes) -> bytes:
728 744 # Avoid double backslash in Windows path repr()
729 745 return pycompat.byterepr(pycompat.bytestr(s)).replace(b'\\\\', b'\\')
730 746
@@ -838,7 +854,9 b' def _MBTextWrapper(**kwargs):'
838 854 return tw(**kwargs)
839 855
840 856
841 def wrap(line, width, initindent=b'', hangindent=b''):
857 def wrap(
858 line: bytes, width: int, initindent: bytes = b'', hangindent: bytes = b''
859 ) -> bytes:
842 860 maxindent = max(len(hangindent), len(initindent))
843 861 if width <= maxindent:
844 862 # adjust for weird terminal size
@@ -875,7 +893,7 b" def wrap(line, width, initindent=b'', ha"
875 893 }
876 894
877 895
878 def parsebool(s):
896 def parsebool(s: bytes) -> Optional[bool]:
879 897 """Parse s into a boolean.
880 898
881 899 If s is not a valid boolean, returns None.
@@ -883,7 +901,8 b' def parsebool(s):'
883 901 return _booleans.get(s.lower(), None)
884 902
885 903
886 def parselist(value):
904 # TODO: make arg mandatory (and fix code below?)
905 def parselist(value: Optional[bytes]):
887 906 """parse a configuration value as a list of comma/space separated strings
888 907
889 908 >>> parselist(b'this,is "a small" ,test')
@@ -973,7 +992,7 b' def parselist(value):'
973 992 return result or []
974 993
975 994
976 def evalpythonliteral(s):
995 def evalpythonliteral(s: bytes):
977 996 """Evaluate a string containing a Python literal expression"""
978 997 # We could backport our tokenizer hack to rewrite '' to u'' if we want
979 998 return ast.literal_eval(s.decode('latin1'))
General Comments 0
You need to be logged in to leave comments. Login now