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

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

47 statements  

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

2 

3import importlib.metadata 

4import itertools 

5import string 

6from typing import Dict, List, Tuple 

7 

8 

9def _tuple_from_text(version: str) -> Tuple: 

10 text_parts = version.split(".") 

11 int_parts = [] 

12 for text_part in text_parts: 

13 digit_prefix = "".join( 

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

15 ) 

16 try: 

17 int_parts.append(int(digit_prefix)) 

18 except Exception: 

19 break 

20 return tuple(int_parts) 

21 

22 

23def _version_check( 

24 requirement: str, 

25) -> bool: 

26 """Is the requirement fulfilled? 

27 

28 The requirement must be of the form 

29 

30 package>=version 

31 """ 

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

33 try: 

34 version = importlib.metadata.version(package) 

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

36 if version is None: 

37 return False 

38 except Exception: 

39 return False 

40 t_version = _tuple_from_text(version) 

41 t_minimum = _tuple_from_text(minimum) 

42 if t_version < t_minimum: 

43 return False 

44 return True 

45 

46 

47_cache: Dict[str, bool] = {} 

48 

49 

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

51 """Is *feature* available? 

52 

53 This tests if all optional packages needed for the 

54 feature are available and recent enough. 

55 

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

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

58 missing. 

59 """ 

60 value = _cache.get(feature) 

61 if value is not None: 

62 return value 

63 requirements = _requirements.get(feature) 

64 if requirements is None: 

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

66 _cache[feature] = False 

67 return False 

68 ok = True 

69 for requirement in requirements: 

70 if not _version_check(requirement): 

71 ok = False 

72 break 

73 _cache[feature] = ok 

74 return ok 

75 

76 

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

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

79 

80 This method is provided as a workaround for any cases 

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

82 """ 

83 _cache[feature] = enabled 

84 

85 

86_requirements: Dict[str, List[str]] = { 

87 ### BEGIN generated requirements 

88 "dnssec": ["cryptography>=43"], 

89 "doh": ["httpcore>=1.0.0", "httpx>=0.26.0", "h2>=4.1.0"], 

90 "doq": ["aioquic>=1.0.0"], 

91 "idna": ["idna>=3.7"], 

92 "trio": ["trio>=0.23"], 

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

94 ### END generated requirements 

95}