Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/dns/_text_util.py: 47%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

19 statements  

1# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 

2 

3"""Internal text-processing helpers.""" 

4 

5import functools 

6import string 

7 

8_ASCII_DIGITS = frozenset(string.digits) 

9 

10_ALL_ASCII_DIGITS = string.digits + string.ascii_lowercase 

11 

12 

13def is_ascii_digit(c: str) -> bool: 

14 """Is *c* one of the ASCII digits "0" through "9"? 

15 

16 Unlike ``str.isdigit()`` and ``str.isdecimal()``, this returns ``False`` 

17 for non-ASCII digits such as U+0967 DEVANAGARI DIGIT ONE. 

18 """ 

19 return c in _ASCII_DIGITS 

20 

21 

22@functools.cache 

23def _ascii_digits_for_base(base: int) -> frozenset[str]: 

24 if base < 2 or base > 36: 

25 raise ValueError(f"invalid base {base}") 

26 digits = _ALL_ASCII_DIGITS[:base] 

27 return frozenset(digits + digits.upper()) 

28 

29 

30def is_ascii_digits(text: str, base: int = 10) -> bool: 

31 """Is *text* a non-empty string consisting only of ASCII digits valid in 

32 *base*? 

33 

34 Digits greater than 9 are the ASCII letters, in either case, as with 

35 ``int()``. Unlike ``int()``, a sign, whitespace, underscores, and base 

36 prefixes such as ``0x`` are not allowed. Unlike ``str.isdigit()`` and 

37 ``str.isdecimal()``, non-ASCII digits such as U+0967 DEVANAGARI DIGIT ONE 

38 are not allowed. 

39 

40 Raises ``ValueError`` if *base* is not between 2 and 36 inclusive. 

41 """ 

42 if base == 10: 

43 return text.isascii() and text.isdecimal() 

44 digits = _ascii_digits_for_base(base) 

45 return len(text) > 0 and all(c in digits for c in text)