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

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

70 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, Optional, 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) # pyright: ignore 

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

30 val._value_ = value # pyright: ignore 

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 return cls(value) 

57 raise cls._unknown_exception_class() 

58 

59 @classmethod 

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

61 cls._check_value(value) 

62 try: 

63 text = cls(value).name 

64 except ValueError: 

65 text = None 

66 text = cls._extra_to_text(value, text) 

67 if text is None: 

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

69 return text 

70 

71 @classmethod 

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

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

74 

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

76 

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

78 cannot be converted. 

79 

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

81 

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) -> Optional[Any]: # 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