扫码登录,获取cookies
This commit is contained in:
235
backend/venv/Lib/site-packages/hypothesis/internal/compat.py
Normal file
235
backend/venv/Lib/site-packages/hypothesis/internal/compat.py
Normal file
@@ -0,0 +1,235 @@
|
||||
# This file is part of Hypothesis, which may be found at
|
||||
# https://github.com/HypothesisWorks/hypothesis/
|
||||
#
|
||||
# Copyright the Hypothesis Authors.
|
||||
# Individual contributors are listed in AUTHORS.rst and the git log.
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
# obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
import codecs
|
||||
import copy
|
||||
import dataclasses
|
||||
import inspect
|
||||
import platform
|
||||
import sys
|
||||
import typing
|
||||
from functools import partial
|
||||
from typing import Any, ForwardRef, get_args
|
||||
|
||||
try:
|
||||
BaseExceptionGroup = BaseExceptionGroup
|
||||
ExceptionGroup = ExceptionGroup # pragma: no cover
|
||||
except NameError:
|
||||
from exceptiongroup import (
|
||||
BaseExceptionGroup as BaseExceptionGroup,
|
||||
ExceptionGroup as ExceptionGroup,
|
||||
)
|
||||
if typing.TYPE_CHECKING: # pragma: no cover
|
||||
from typing_extensions import Concatenate as Concatenate, ParamSpec as ParamSpec
|
||||
else:
|
||||
try:
|
||||
from typing import Concatenate as Concatenate, ParamSpec as ParamSpec
|
||||
except ImportError:
|
||||
try:
|
||||
from typing_extensions import (
|
||||
Concatenate as Concatenate,
|
||||
ParamSpec as ParamSpec,
|
||||
)
|
||||
except ImportError:
|
||||
Concatenate, ParamSpec = None, None
|
||||
|
||||
PYPY = platform.python_implementation() == "PyPy"
|
||||
GRAALPY = platform.python_implementation() == "GraalVM"
|
||||
WINDOWS = platform.system() == "Windows"
|
||||
|
||||
|
||||
def add_note(exc, note):
|
||||
try:
|
||||
exc.add_note(note)
|
||||
except AttributeError:
|
||||
if not hasattr(exc, "__notes__"):
|
||||
exc.__notes__ = []
|
||||
exc.__notes__.append(note)
|
||||
|
||||
|
||||
def escape_unicode_characters(s: str) -> str:
|
||||
return codecs.encode(s, "unicode_escape").decode("ascii")
|
||||
|
||||
|
||||
def int_from_bytes(data: typing.Union[bytes, bytearray]) -> int:
|
||||
return int.from_bytes(data, "big")
|
||||
|
||||
|
||||
def int_to_bytes(i: int, size: int) -> bytes:
|
||||
return i.to_bytes(size, "big")
|
||||
|
||||
|
||||
def int_to_byte(i: int) -> bytes:
|
||||
return bytes([i])
|
||||
|
||||
|
||||
def is_typed_named_tuple(cls):
|
||||
"""Return True if cls is probably a subtype of `typing.NamedTuple`.
|
||||
|
||||
Unfortunately types created with `class T(NamedTuple):` actually
|
||||
subclass `tuple` directly rather than NamedTuple. This is annoying,
|
||||
and means we just have to hope that nobody defines a different tuple
|
||||
subclass with similar attributes.
|
||||
"""
|
||||
return (
|
||||
issubclass(cls, tuple)
|
||||
and hasattr(cls, "_fields")
|
||||
and (hasattr(cls, "_field_types") or hasattr(cls, "__annotations__"))
|
||||
)
|
||||
|
||||
|
||||
def _hint_and_args(x):
|
||||
return (x, *get_args(x))
|
||||
|
||||
|
||||
def get_type_hints(thing):
|
||||
"""Like the typing version, but tries harder and never errors.
|
||||
|
||||
Tries harder: if the thing to inspect is a class but typing.get_type_hints
|
||||
raises an error or returns no hints, then this function will try calling it
|
||||
on the __init__ method. This second step often helps with user-defined
|
||||
classes on older versions of Python. The third step we take is trying
|
||||
to fetch types from the __signature__ property.
|
||||
They override any other ones we found earlier.
|
||||
|
||||
Never errors: instead of raising TypeError for uninspectable objects, or
|
||||
NameError for unresolvable forward references, just return an empty dict.
|
||||
"""
|
||||
if isinstance(thing, partial):
|
||||
from hypothesis.internal.reflection import get_signature
|
||||
|
||||
bound = set(get_signature(thing.func).parameters).difference(
|
||||
get_signature(thing).parameters
|
||||
)
|
||||
return {k: v for k, v in get_type_hints(thing.func).items() if k not in bound}
|
||||
|
||||
kwargs = {} if sys.version_info[:2] < (3, 9) else {"include_extras": True}
|
||||
|
||||
try:
|
||||
hints = typing.get_type_hints(thing, **kwargs)
|
||||
except (AttributeError, TypeError, NameError): # pragma: no cover
|
||||
hints = {}
|
||||
|
||||
if inspect.isclass(thing):
|
||||
try:
|
||||
hints.update(typing.get_type_hints(thing.__init__, **kwargs))
|
||||
except (TypeError, NameError, AttributeError):
|
||||
pass
|
||||
|
||||
try:
|
||||
if hasattr(thing, "__signature__"):
|
||||
# It is possible for the signature and annotations attributes to
|
||||
# differ on an object due to renamed arguments.
|
||||
from hypothesis.internal.reflection import get_signature
|
||||
from hypothesis.strategies._internal.types import is_a_type
|
||||
|
||||
vkinds = (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD)
|
||||
for p in get_signature(thing).parameters.values():
|
||||
if (
|
||||
p.kind not in vkinds
|
||||
and is_a_type(p.annotation)
|
||||
and p.annotation is not p.empty
|
||||
):
|
||||
p_hint = p.annotation
|
||||
|
||||
# Defer to `get_type_hints` if signature annotation is, or
|
||||
# contains, a forward reference that is otherwise resolved.
|
||||
if any(
|
||||
isinstance(sig_hint, ForwardRef)
|
||||
and not isinstance(hint, ForwardRef)
|
||||
for sig_hint, hint in zip(
|
||||
_hint_and_args(p.annotation),
|
||||
_hint_and_args(hints.get(p.name, Any)),
|
||||
)
|
||||
):
|
||||
p_hint = hints[p.name]
|
||||
if p.default is None:
|
||||
hints[p.name] = typing.Optional[p_hint]
|
||||
else:
|
||||
hints[p.name] = p_hint
|
||||
except (AttributeError, TypeError, NameError): # pragma: no cover
|
||||
pass
|
||||
|
||||
return hints
|
||||
|
||||
|
||||
# Under Python 2, math.floor and math.ceil returned floats, which cannot
|
||||
# represent large integers - eg `float(2**53) == float(2**53 + 1)`.
|
||||
# We therefore implement them entirely in (long) integer operations.
|
||||
# We still use the same trick on Python 3, because Numpy values and other
|
||||
# custom __floor__ or __ceil__ methods may convert via floats.
|
||||
# See issue #1667, Numpy issue 9068.
|
||||
def floor(x):
|
||||
y = int(x)
|
||||
if y != x and x < 0:
|
||||
return y - 1
|
||||
return y
|
||||
|
||||
|
||||
def ceil(x):
|
||||
y = int(x)
|
||||
if y != x and x > 0:
|
||||
return y + 1
|
||||
return y
|
||||
|
||||
|
||||
def bad_django_TestCase(runner):
|
||||
if runner is None or "django.test" not in sys.modules:
|
||||
return False
|
||||
else: # pragma: no cover
|
||||
if not isinstance(runner, sys.modules["django.test"].TransactionTestCase):
|
||||
return False
|
||||
|
||||
from hypothesis.extra.django._impl import HypothesisTestCase
|
||||
|
||||
return not isinstance(runner, HypothesisTestCase)
|
||||
|
||||
|
||||
# see issue #3812
|
||||
if sys.version_info[:2] < (3, 12):
|
||||
|
||||
def dataclass_asdict(obj, *, dict_factory=dict):
|
||||
"""
|
||||
A vendored variant of dataclasses.asdict. Includes the bugfix for
|
||||
defaultdicts (cpython/32056) for all versions. See also issues/3812.
|
||||
|
||||
This should be removed whenever we drop support for 3.11. We can use the
|
||||
standard dataclasses.asdict after that point.
|
||||
"""
|
||||
if not dataclasses._is_dataclass_instance(obj): # pragma: no cover
|
||||
raise TypeError("asdict() should be called on dataclass instances")
|
||||
return _asdict_inner(obj, dict_factory)
|
||||
|
||||
else: # pragma: no cover
|
||||
dataclass_asdict = dataclasses.asdict
|
||||
|
||||
|
||||
def _asdict_inner(obj, dict_factory):
|
||||
if dataclasses._is_dataclass_instance(obj):
|
||||
return dict_factory(
|
||||
(f.name, _asdict_inner(getattr(obj, f.name), dict_factory))
|
||||
for f in dataclasses.fields(obj)
|
||||
)
|
||||
elif isinstance(obj, tuple) and hasattr(obj, "_fields"):
|
||||
return type(obj)(*[_asdict_inner(v, dict_factory) for v in obj])
|
||||
elif isinstance(obj, (list, tuple)):
|
||||
return type(obj)(_asdict_inner(v, dict_factory) for v in obj)
|
||||
elif isinstance(obj, dict):
|
||||
if hasattr(type(obj), "default_factory"):
|
||||
result = type(obj)(obj.default_factory)
|
||||
for k, v in obj.items():
|
||||
result[_asdict_inner(k, dict_factory)] = _asdict_inner(v, dict_factory)
|
||||
return result
|
||||
return type(obj)(
|
||||
(_asdict_inner(k, dict_factory), _asdict_inner(v, dict_factory))
|
||||
for k, v in obj.items()
|
||||
)
|
||||
else:
|
||||
return copy.deepcopy(obj)
|
||||
Reference in New Issue
Block a user