選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

140 行
4.3 KiB

  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. from __future__ import annotations
  5. import enum
  6. import sys
  7. import types
  8. import typing
  9. import warnings
  10. from collections.abc import Callable, Sequence
  11. # We use a UserWarning subclass, instead of DeprecationWarning, because CPython
  12. # decided deprecation warnings should be invisible by default.
  13. class CryptographyDeprecationWarning(UserWarning):
  14. pass
  15. # Several APIs were deprecated with no specific end-of-life date because of the
  16. # ubiquity of their use. They should not be removed until we agree on when that
  17. # cycle ends.
  18. DeprecatedIn36 = CryptographyDeprecationWarning
  19. DeprecatedIn37 = CryptographyDeprecationWarning
  20. DeprecatedIn40 = CryptographyDeprecationWarning
  21. DeprecatedIn41 = CryptographyDeprecationWarning
  22. DeprecatedIn42 = CryptographyDeprecationWarning
  23. DeprecatedIn43 = CryptographyDeprecationWarning
  24. DeprecatedIn45 = CryptographyDeprecationWarning
  25. # If you're wondering why we don't use `Buffer`, it's because `Buffer` would
  26. # be more accurately named: Bufferable. It means something which has an
  27. # `__buffer__`. Which means you can't actually treat the result as a buffer
  28. # (and do things like take a `len()`).
  29. if sys.version_info >= (3, 9):
  30. Buffer = typing.Union[bytes, bytearray, memoryview]
  31. else:
  32. Buffer = typing.ByteString
  33. def _check_bytes(name: str, value: bytes) -> None:
  34. if not isinstance(value, bytes):
  35. raise TypeError(f"{name} must be bytes")
  36. def _check_byteslike(name: str, value: Buffer) -> None:
  37. try:
  38. memoryview(value)
  39. except TypeError:
  40. raise TypeError(f"{name} must be bytes-like")
  41. def int_to_bytes(integer: int, length: int | None = None) -> bytes:
  42. if length == 0:
  43. raise ValueError("length argument can't be 0")
  44. return integer.to_bytes(
  45. length or (integer.bit_length() + 7) // 8 or 1, "big"
  46. )
  47. class InterfaceNotImplemented(Exception):
  48. pass
  49. class _DeprecatedValue:
  50. def __init__(self, value: object, message: str, warning_class):
  51. self.value = value
  52. self.message = message
  53. self.warning_class = warning_class
  54. class _ModuleWithDeprecations(types.ModuleType):
  55. def __init__(self, module: types.ModuleType):
  56. super().__init__(module.__name__)
  57. self.__dict__["_module"] = module
  58. def __getattr__(self, attr: str) -> object:
  59. obj = getattr(self._module, attr)
  60. if isinstance(obj, _DeprecatedValue):
  61. warnings.warn(obj.message, obj.warning_class, stacklevel=2)
  62. obj = obj.value
  63. return obj
  64. def __setattr__(self, attr: str, value: object) -> None:
  65. setattr(self._module, attr, value)
  66. def __delattr__(self, attr: str) -> None:
  67. obj = getattr(self._module, attr)
  68. if isinstance(obj, _DeprecatedValue):
  69. warnings.warn(obj.message, obj.warning_class, stacklevel=2)
  70. delattr(self._module, attr)
  71. def __dir__(self) -> Sequence[str]:
  72. return ["_module", *dir(self._module)]
  73. def deprecated(
  74. value: object,
  75. module_name: str,
  76. message: str,
  77. warning_class: type[Warning],
  78. name: str | None = None,
  79. ) -> _DeprecatedValue:
  80. module = sys.modules[module_name]
  81. if not isinstance(module, _ModuleWithDeprecations):
  82. sys.modules[module_name] = module = _ModuleWithDeprecations(module)
  83. dv = _DeprecatedValue(value, message, warning_class)
  84. # Maintain backwards compatibility with `name is None` for pyOpenSSL.
  85. if name is not None:
  86. setattr(module, name, dv)
  87. return dv
  88. def cached_property(func: Callable) -> property:
  89. cached_name = f"_cached_{func}"
  90. sentinel = object()
  91. def inner(instance: object):
  92. cache = getattr(instance, cached_name, sentinel)
  93. if cache is not sentinel:
  94. return cache
  95. result = func(instance)
  96. setattr(instance, cached_name, result)
  97. return result
  98. return property(inner)
  99. # Python 3.10 changed representation of enums. We use well-defined object
  100. # representation and string representation from Python 3.9.
  101. class Enum(enum.Enum):
  102. def __repr__(self) -> str:
  103. return f"<{self.__class__.__name__}.{self._name_}: {self._value_!r}>"
  104. def __str__(self) -> str:
  105. return f"{self.__class__.__name__}.{self._name_}"