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

72 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-02-02 06:07 +0000

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 Type, TypeVar, Union 

20 

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

22 

23 

24class IntEnum(enum.IntEnum): 

25 @classmethod 

26 def _missing_(cls, value): 

27 cls._check_value(value) 

28 val = int.__new__(cls, value) 

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

30 val._value_ = value 

31 return val 

32 

33 @classmethod 

34 def _check_value(cls, value): 

35 max = cls._maximum() 

36 if not isinstance(value, int): 

37 raise TypeError 

38 if value < 0 or value > max: 

39 name = cls._short_name() 

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

41 

42 @classmethod 

43 def from_text(cls: Type[TIntEnum], text: str) -> TIntEnum: 

44 text = text.upper() 

45 try: 

46 return cls[text] 

47 except KeyError: 

48 pass 

49 value = cls._extra_from_text(text) 

50 if value: 

51 return value 

52 prefix = cls._prefix() 

53 if text.startswith(prefix) and text[len(prefix) :].isdigit(): 

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

55 cls._check_value(value) 

56 try: 

57 return cls(value) 

58 except ValueError: 

59 return value 

60 raise cls._unknown_exception_class() 

61 

62 @classmethod 

63 def to_text(cls: Type[TIntEnum], value: int) -> str: 

64 cls._check_value(value) 

65 try: 

66 text = cls(value).name 

67 except ValueError: 

68 text = None 

69 text = cls._extra_to_text(value, text) 

70 if text is None: 

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

72 return text 

73 

74 @classmethod 

75 def make(cls: Type[TIntEnum], value: Union[int, str]) -> TIntEnum: 

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

77 

78 *value*, the ``int`` or ``str`` to convert. 

79 

80 Raises a class-specific exception if a ``str`` is provided that 

81 cannot be converted. 

82 

83 Raises ``ValueError`` if the value is out of range. 

84 

85 Returns an enumeration from the calling class corresponding to the 

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

87 """ 

88 

89 if isinstance(value, str): 

90 return cls.from_text(value) 

91 cls._check_value(value) 

92 return cls(value) 

93 

94 @classmethod 

95 def _maximum(cls): 

96 raise NotImplementedError # pragma: no cover 

97 

98 @classmethod 

99 def _short_name(cls): 

100 return cls.__name__.lower() 

101 

102 @classmethod 

103 def _prefix(cls): 

104 return "" 

105 

106 @classmethod 

107 def _extra_from_text(cls, text): # pylint: disable=W0613 

108 return None 

109 

110 @classmethod 

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

112 return current_text 

113 

114 @classmethod 

115 def _unknown_exception_class(cls): 

116 return ValueError