Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/cryptography/utils.py: 62%
76 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:05 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:05 +0000
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.
5from __future__ import annotations
7import enum
8import sys
9import types
10import typing
11import warnings
14# We use a UserWarning subclass, instead of DeprecationWarning, because CPython
15# decided deprecation warnings should be invisble by default.
16class CryptographyDeprecationWarning(UserWarning):
17 pass
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
29def _check_bytes(name: str, value: bytes) -> None:
30 if not isinstance(value, bytes):
31 raise TypeError(f"{name} must be bytes")
34def _check_byteslike(name: str, value: bytes) -> None:
35 try:
36 memoryview(value)
37 except TypeError:
38 raise TypeError(f"{name} must be bytes-like")
41def int_to_bytes(integer: int, length: typing.Optional[int] = None) -> bytes:
42 return integer.to_bytes(
43 length or (integer.bit_length() + 7) // 8 or 1, "big"
44 )
47def _extract_buffer_length(obj: typing.Any) -> typing.Tuple[typing.Any, int]:
48 from cryptography.hazmat.bindings._rust import _openssl
50 buf = _openssl.ffi.from_buffer(obj)
51 return buf, int(_openssl.ffi.cast("uintptr_t", buf))
54class InterfaceNotImplemented(Exception):
55 pass
58class _DeprecatedValue:
59 def __init__(self, value: object, message: str, warning_class):
60 self.value = value
61 self.message = message
62 self.warning_class = warning_class
65class _ModuleWithDeprecations(types.ModuleType):
66 def __init__(self, module: types.ModuleType):
67 super().__init__(module.__name__)
68 self.__dict__["_module"] = module
70 def __getattr__(self, attr: str) -> object:
71 obj = getattr(self._module, attr)
72 if isinstance(obj, _DeprecatedValue):
73 warnings.warn(obj.message, obj.warning_class, stacklevel=2)
74 obj = obj.value
75 return obj
77 def __setattr__(self, attr: str, value: object) -> None:
78 setattr(self._module, attr, value)
80 def __delattr__(self, attr: str) -> None:
81 obj = getattr(self._module, attr)
82 if isinstance(obj, _DeprecatedValue):
83 warnings.warn(obj.message, obj.warning_class, stacklevel=2)
85 delattr(self._module, attr)
87 def __dir__(self) -> typing.Sequence[str]:
88 return ["_module"] + dir(self._module)
91def deprecated(
92 value: object,
93 module_name: str,
94 message: str,
95 warning_class: typing.Type[Warning],
96 name: typing.Optional[str] = None,
97) -> _DeprecatedValue:
98 module = sys.modules[module_name]
99 if not isinstance(module, _ModuleWithDeprecations):
100 sys.modules[module_name] = module = _ModuleWithDeprecations(module)
101 dv = _DeprecatedValue(value, message, warning_class)
102 # Maintain backwards compatibility with `name is None` for pyOpenSSL.
103 if name is not None:
104 setattr(module, name, dv)
105 return dv
108def cached_property(func: typing.Callable) -> property:
109 cached_name = f"_cached_{func}"
110 sentinel = object()
112 def inner(instance: object):
113 cache = getattr(instance, cached_name, sentinel)
114 if cache is not sentinel:
115 return cache
116 result = func(instance)
117 setattr(instance, cached_name, result)
118 return result
120 return property(inner)
123# Python 3.10 changed representation of enums. We use well-defined object
124# representation and string representation from Python 3.9.
125class Enum(enum.Enum):
126 def __repr__(self) -> str:
127 return f"<{self.__class__.__name__}.{self._name_}: {self._value_!r}>"
129 def __str__(self) -> str:
130 return f"{self.__class__.__name__}.{self._name_}"