Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

utils.py 3.9KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. # We use a UserWarning subclass, instead of DeprecationWarning, because CPython
  11. # decided deprecation warnings should be invisble by default.
  12. class CryptographyDeprecationWarning(UserWarning):
  13. pass
  14. # Several APIs were deprecated with no specific end-of-life date because of the
  15. # ubiquity of their use. They should not be removed until we agree on when that
  16. # cycle ends.
  17. DeprecatedIn36 = CryptographyDeprecationWarning
  18. DeprecatedIn37 = CryptographyDeprecationWarning
  19. DeprecatedIn40 = CryptographyDeprecationWarning
  20. DeprecatedIn41 = CryptographyDeprecationWarning
  21. def _check_bytes(name: str, value: bytes) -> None:
  22. if not isinstance(value, bytes):
  23. raise TypeError(f"{name} must be bytes")
  24. def _check_byteslike(name: str, value: bytes) -> None:
  25. try:
  26. memoryview(value)
  27. except TypeError:
  28. raise TypeError(f"{name} must be bytes-like")
  29. def int_to_bytes(integer: int, length: typing.Optional[int] = None) -> bytes:
  30. return integer.to_bytes(
  31. length or (integer.bit_length() + 7) // 8 or 1, "big"
  32. )
  33. def _extract_buffer_length(obj: typing.Any) -> typing.Tuple[typing.Any, int]:
  34. from cryptography.hazmat.bindings._rust import _openssl
  35. buf = _openssl.ffi.from_buffer(obj)
  36. return buf, int(_openssl.ffi.cast("uintptr_t", buf))
  37. class InterfaceNotImplemented(Exception):
  38. pass
  39. class _DeprecatedValue:
  40. def __init__(self, value: object, message: str, warning_class):
  41. self.value = value
  42. self.message = message
  43. self.warning_class = warning_class
  44. class _ModuleWithDeprecations(types.ModuleType):
  45. def __init__(self, module: types.ModuleType):
  46. super().__init__(module.__name__)
  47. self.__dict__["_module"] = module
  48. def __getattr__(self, attr: str) -> object:
  49. obj = getattr(self._module, attr)
  50. if isinstance(obj, _DeprecatedValue):
  51. warnings.warn(obj.message, obj.warning_class, stacklevel=2)
  52. obj = obj.value
  53. return obj
  54. def __setattr__(self, attr: str, value: object) -> None:
  55. setattr(self._module, attr, value)
  56. def __delattr__(self, attr: str) -> None:
  57. obj = getattr(self._module, attr)
  58. if isinstance(obj, _DeprecatedValue):
  59. warnings.warn(obj.message, obj.warning_class, stacklevel=2)
  60. delattr(self._module, attr)
  61. def __dir__(self) -> typing.Sequence[str]:
  62. return ["_module"] + dir(self._module)
  63. def deprecated(
  64. value: object,
  65. module_name: str,
  66. message: str,
  67. warning_class: typing.Type[Warning],
  68. name: typing.Optional[str] = None,
  69. ) -> _DeprecatedValue:
  70. module = sys.modules[module_name]
  71. if not isinstance(module, _ModuleWithDeprecations):
  72. sys.modules[module_name] = module = _ModuleWithDeprecations(module)
  73. dv = _DeprecatedValue(value, message, warning_class)
  74. # Maintain backwards compatibility with `name is None` for pyOpenSSL.
  75. if name is not None:
  76. setattr(module, name, dv)
  77. return dv
  78. def cached_property(func: typing.Callable) -> property:
  79. cached_name = f"_cached_{func}"
  80. sentinel = object()
  81. def inner(instance: object):
  82. cache = getattr(instance, cached_name, sentinel)
  83. if cache is not sentinel:
  84. return cache
  85. result = func(instance)
  86. setattr(instance, cached_name, result)
  87. return result
  88. return property(inner)
  89. # Python 3.10 changed representation of enums. We use well-defined object
  90. # representation and string representation from Python 3.9.
  91. class Enum(enum.Enum):
  92. def __repr__(self) -> str:
  93. return f"<{self.__class__.__name__}.{self._name_}: {self._value_!r}>"
  94. def __str__(self) -> str:
  95. return f"{self.__class__.__name__}.{self._name_}"