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

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

71 statements  

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

2 

3# Copyright (C) 2003-2017 Nominum, Inc. 

4# 

5# Permission to use, copy, modify, and distribute this software and its 

6# documentation for any purpose with or without fee is hereby granted, 

7# provided that the above copyright notice and this permission notice 

8# appear in all copies. 

9# 

10# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 

11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 

12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 

13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 

14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 

15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 

16# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 

17 

18import enum 

19from typing import Any, TypeVar 

20 

21import dns._text_util 

22 

23TIntEnum = TypeVar("TIntEnum", bound="IntEnum") 

24 

25 

26class IntEnum(enum.IntEnum): 

27 @classmethod 

28 def _missing_(cls, value): 

29 cls._check_value(value) 

30 val = int.__new__(cls, value) # pyright: ignore 

31 val._name_ = cls._extra_to_text(value, None) or f"{cls._prefix()}{value}" 

32 val._value_ = value # pyright: ignore 

33 return val 

34 

35 @classmethod 

36 def _check_value(cls, value): 

37 max = cls._maximum() 

38 if not isinstance(value, int): 

39 raise TypeError 

40 if value < 0 or value > max: 

41 name = cls._short_name() 

42 raise ValueError(f"{name} must be an int between >= 0 and <= {max}") 

43 

44 @classmethod 

45 def from_text(cls: type[TIntEnum], text: str) -> TIntEnum: 

46 text = text.upper() 

47 try: 

48 return cls[text] 

49 except KeyError: 

50 pass 

51 value = cls._extra_from_text(text) 

52 if value: 

53 return value 

54 prefix = cls._prefix() 

55 if text.startswith(prefix) and dns._text_util.is_ascii_digits( 

56 text[len(prefix) :] 

57 ): 

58 value = int(text[len(prefix) :]) 

59 cls._check_value(value) 

60 return cls(value) 

61 raise cls._unknown_exception_class() 

62 

63 @classmethod 

64 def to_text(cls: type[TIntEnum], value: int) -> str: 

65 cls._check_value(value) 

66 try: 

67 text = cls(value).name 

68 except ValueError: 

69 text = None 

70 text = cls._extra_to_text(value, text) 

71 if text is None: 

72 text = f"{cls._prefix()}{value}" 

73 return text 

74 

75 @classmethod 

76 def make(cls: type[TIntEnum], value: int | str) -> TIntEnum: 

77 """Convert text or a value into an enumerated type, if possible. 

78 

79 :param value: The value to convert. 

80 :type value: int or str 

81 :raises ValueError: If the value is out of range. 

82 :returns: An enumeration from the calling class corresponding to the 

83 value, if one is defined, or an ``int`` otherwise. 

84 """ 

85 

86 if isinstance(value, str): 

87 return cls.from_text(value) 

88 cls._check_value(value) 

89 return cls(value) 

90 

91 @classmethod 

92 def _maximum(cls): 

93 raise NotImplementedError # pragma: no cover 

94 

95 @classmethod 

96 def _short_name(cls): 

97 return cls.__name__.lower() 

98 

99 @classmethod 

100 def _prefix(cls) -> str: 

101 return "" 

102 

103 @classmethod 

104 def _extra_from_text(cls, text: str) -> Any | None: # pylint: disable=W0613 

105 return None 

106 

107 @classmethod 

108 def _extra_to_text(cls, value, current_text): # pylint: disable=W0613 

109 return current_text 

110 

111 @classmethod 

112 def _unknown_exception_class(cls) -> type[Exception]: 

113 return ValueError