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

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

46 statements  

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

2 

3import importlib.metadata 

4import itertools 

5import string 

6 

7 

8def _tuple_from_text(version: str) -> tuple: 

9 text_parts = version.split(".") 

10 int_parts = [] 

11 for text_part in text_parts: 

12 digit_prefix = "".join( 

13 itertools.takewhile(lambda x: x in string.digits, text_part) 

14 ) 

15 try: 

16 int_parts.append(int(digit_prefix)) 

17 except Exception: 

18 break 

19 return tuple(int_parts) 

20 

21 

22def _version_check( 

23 requirement: str, 

24) -> bool: 

25 """Is the requirement fulfilled? 

26 

27 The requirement must be of the form 

28 

29 package>=version 

30 """ 

31 package, minimum = requirement.split(">=") 

32 try: 

33 version = importlib.metadata.version(package) 

34 # This shouldn't happen, but it apparently can. 

35 if version is None: 

36 return False 

37 except Exception: 

38 return False 

39 t_version = _tuple_from_text(version) 

40 t_minimum = _tuple_from_text(minimum) 

41 if t_version < t_minimum: 

42 return False 

43 return True 

44 

45 

46_cache: dict[str, bool] = {} 

47 

48 

49def have(feature: str) -> bool: 

50 """Is *feature* available? 

51 

52 This tests if all optional packages needed for the 

53 feature are available and recent enough. 

54 

55 Returns ``True`` if the feature is available, 

56 and ``False`` if it is not or if metadata is 

57 missing. 

58 """ 

59 value = _cache.get(feature) 

60 if value is not None: 

61 return value 

62 requirements = _requirements.get(feature) 

63 if requirements is None: 

64 # we make a cache entry here for consistency not performance 

65 _cache[feature] = False 

66 return False 

67 ok = True 

68 for requirement in requirements: 

69 if not _version_check(requirement): 

70 ok = False 

71 break 

72 _cache[feature] = ok 

73 return ok 

74 

75 

76def force(feature: str, enabled: bool) -> None: 

77 """Force the status of *feature* to be *enabled*. 

78 

79 This method is provided as a workaround for any cases 

80 where importlib.metadata is ineffective, or for testing. 

81 """ 

82 _cache[feature] = enabled 

83 

84 

85_requirements: dict[str, list[str]] = { 

86 ### BEGIN generated requirements 

87 "dnssec": ["cryptography>=45"], 

88 "doh": ["httpcore>=1.0.0", "httpx>=0.28.0", "h2>=4.2.0"], 

89 "doq": ["aioquic>=1.2.0"], 

90 "idna": ["idna>=3.10"], 

91 "trio": ["trio>=0.30"], 

92 "wmi": ["wmi>=1.5.1"], 

93 ### END generated requirements 

94}