Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/utils.py: 62%

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

77 statements  

1# This file is dual licensed under the terms of the Apache License, Version 

2# 2.0, and the BSD License. See the LICENSE file in the root of this repository 

3# for complete details. 

4 

5from __future__ import annotations 

6 

7import enum 

8import sys 

9import types 

10import typing 

11import warnings 

12 

13 

14# We use a UserWarning subclass, instead of DeprecationWarning, because CPython 

15# decided deprecation warnings should be invisible by default. 

16class CryptographyDeprecationWarning(UserWarning): 

17 pass 

18 

19 

20# Several APIs were deprecated with no specific end-of-life date because of the 

21# ubiquity of their use. They should not be removed until we agree on when that 

22# cycle ends. 

23DeprecatedIn36 = CryptographyDeprecationWarning 

24DeprecatedIn37 = CryptographyDeprecationWarning 

25DeprecatedIn40 = CryptographyDeprecationWarning 

26DeprecatedIn41 = CryptographyDeprecationWarning 

27DeprecatedIn42 = CryptographyDeprecationWarning 

28 

29 

30def _check_bytes(name: str, value: bytes) -> None: 

31 if not isinstance(value, bytes): 

32 raise TypeError(f"{name} must be bytes") 

33 

34 

35def _check_byteslike(name: str, value: bytes) -> None: 

36 try: 

37 memoryview(value) 

38 except TypeError: 

39 raise TypeError(f"{name} must be bytes-like") 

40 

41 

42def int_to_bytes(integer: int, length: int | None = None) -> bytes: 

43 return integer.to_bytes( 

44 length or (integer.bit_length() + 7) // 8 or 1, "big" 

45 ) 

46 

47 

48def _extract_buffer_length(obj: typing.Any) -> tuple[typing.Any, int]: 

49 from cryptography.hazmat.bindings._rust import _openssl 

50 

51 buf = _openssl.ffi.from_buffer(obj) 

52 return buf, int(_openssl.ffi.cast("uintptr_t", buf)) 

53 

54 

55class InterfaceNotImplemented(Exception): 

56 pass 

57 

58 

59class _DeprecatedValue: 

60 def __init__(self, value: object, message: str, warning_class): 

61 self.value = value 

62 self.message = message 

63 self.warning_class = warning_class 

64 

65 

66class _ModuleWithDeprecations(types.ModuleType): 

67 def __init__(self, module: types.ModuleType): 

68 super().__init__(module.__name__) 

69 self.__dict__["_module"] = module 

70 

71 def __getattr__(self, attr: str) -> object: 

72 obj = getattr(self._module, attr) 

73 if isinstance(obj, _DeprecatedValue): 

74 warnings.warn(obj.message, obj.warning_class, stacklevel=2) 

75 obj = obj.value 

76 return obj 

77 

78 def __setattr__(self, attr: str, value: object) -> None: 

79 setattr(self._module, attr, value) 

80 

81 def __delattr__(self, attr: str) -> None: 

82 obj = getattr(self._module, attr) 

83 if isinstance(obj, _DeprecatedValue): 

84 warnings.warn(obj.message, obj.warning_class, stacklevel=2) 

85 

86 delattr(self._module, attr) 

87 

88 def __dir__(self) -> typing.Sequence[str]: 

89 return ["_module", *dir(self._module)] 

90 

91 

92def deprecated( 

93 value: object, 

94 module_name: str, 

95 message: str, 

96 warning_class: type[Warning], 

97 name: str | None = None, 

98) -> _DeprecatedValue: 

99 module = sys.modules[module_name] 

100 if not isinstance(module, _ModuleWithDeprecations): 

101 sys.modules[module_name] = module = _ModuleWithDeprecations(module) 

102 dv = _DeprecatedValue(value, message, warning_class) 

103 # Maintain backwards compatibility with `name is None` for pyOpenSSL. 

104 if name is not None: 

105 setattr(module, name, dv) 

106 return dv 

107 

108 

109def cached_property(func: typing.Callable) -> property: 

110 cached_name = f"_cached_{func}" 

111 sentinel = object() 

112 

113 def inner(instance: object): 

114 cache = getattr(instance, cached_name, sentinel) 

115 if cache is not sentinel: 

116 return cache 

117 result = func(instance) 

118 setattr(instance, cached_name, result) 

119 return result 

120 

121 return property(inner) 

122 

123 

124# Python 3.10 changed representation of enums. We use well-defined object 

125# representation and string representation from Python 3.9. 

126class Enum(enum.Enum): 

127 def __repr__(self) -> str: 

128 return f"<{self.__class__.__name__}.{self._name_}: {self._value_!r}>" 

129 

130 def __str__(self) -> str: 

131 return f"{self.__class__.__name__}.{self._name_}"