microproduct/atmosphericDelay/ISCEApp/site-packages/hypothesis/internal/escalation.py

146 lines
4.9 KiB
Python

# This file is part of Hypothesis, which may be found at
# https://github.com/HypothesisWorks/hypothesis/
#
# Most of this work is copyright (C) 2013-2021 David R. MacIver
# (david@drmaciver.com), but it contains contributions by others. See
# CONTRIBUTING.rst for a full list of people who may hold copyright, and
# consult the git log if you need to determine who owns an individual
# contribution.
#
# 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/.
#
# END HEADER
import os
import sys
import traceback
from inspect import getframeinfo
from pathlib import Path
from typing import Dict
import hypothesis
from hypothesis.errors import (
DeadlineExceeded,
HypothesisException,
StopTest,
UnsatisfiedAssumption,
_Trimmable,
)
from hypothesis.utils.dynamicvariables import DynamicVariable
def belongs_to(package):
if not hasattr(package, "__file__"): # pragma: no cover
return lambda filepath: False
root = Path(package.__file__).resolve().parent
cache = {str: {}, bytes: {}}
def accept(filepath):
ftype = type(filepath)
try:
return cache[ftype][filepath]
except KeyError:
pass
try:
Path(filepath).resolve().relative_to(root)
result = True
except Exception:
result = False
cache[ftype][filepath] = result
return result
accept.__name__ = f"is_{package.__name__}_file"
return accept
PREVENT_ESCALATION = os.getenv("HYPOTHESIS_DO_NOT_ESCALATE") == "true"
FILE_CACHE: Dict[bytes, bool] = {}
is_hypothesis_file = belongs_to(hypothesis)
HYPOTHESIS_CONTROL_EXCEPTIONS = (DeadlineExceeded, StopTest, UnsatisfiedAssumption)
def escalate_hypothesis_internal_error():
if PREVENT_ESCALATION:
return
error_type, e, tb = sys.exc_info()
if getattr(e, "hypothesis_internal_never_escalate", False):
return
filepath = traceback.extract_tb(tb)[-1][0]
if is_hypothesis_file(filepath) and not isinstance(
e, (HypothesisException,) + HYPOTHESIS_CONTROL_EXCEPTIONS
):
raise
def get_trimmed_traceback(exception=None):
"""Return the current traceback, minus any frames added by Hypothesis."""
if exception is None:
_, exception, tb = sys.exc_info()
else:
tb = exception.__traceback__
# Avoid trimming the traceback if we're in verbose mode, or the error
# was raised inside Hypothesis (and is not a MultipleFailures)
if hypothesis.settings.default.verbosity >= hypothesis.Verbosity.debug or (
is_hypothesis_file(traceback.extract_tb(tb)[-1][0])
and not isinstance(exception, _Trimmable)
):
return tb
while tb.tb_next is not None and (
# If the frame is from one of our files, it's been added by Hypothesis.
is_hypothesis_file(getframeinfo(tb.tb_frame)[0])
# But our `@proxies` decorator overrides the source location,
# so we check for an attribute it injects into the frame too.
or tb.tb_frame.f_globals.get("__hypothesistracebackhide__") is True
):
tb = tb.tb_next
return tb
def get_interesting_origin(exception):
# The `interesting_origin` is how Hypothesis distinguishes between multiple
# failures, for reporting and also to replay from the example database (even
# if report_multiple_bugs=False). We traditionally use the exception type and
# location, but have extracted this logic in order to see through `except ...:`
# blocks and understand the __cause__ (`raise x from y`) or __context__ that
# first raised an exception.
tb = get_trimmed_traceback(exception)
filename, lineno, *_ = traceback.extract_tb(tb)[-1]
return (
type(exception),
filename,
lineno,
# Note that if __cause__ is set it is always equal to __context__, explicitly
# to support introspection when debugging, so we can use that unconditionally.
get_interesting_origin(exception.__context__) if exception.__context__ else (),
)
current_pytest_item = DynamicVariable(None)
def format_exception(err, tb):
# Try using Pytest to match the currently configured traceback style
if current_pytest_item.value is not None and "_pytest._code" in sys.modules:
item = current_pytest_item.value
ExceptionInfo = sys.modules["_pytest._code"].ExceptionInfo
return str(item.repr_failure(ExceptionInfo((type(err), err, tb)))) + "\n"
# Or use better_exceptions, if that's installed and enabled
if "better_exceptions" in sys.modules:
better_exceptions = sys.modules["better_exceptions"]
if sys.excepthook is better_exceptions.excepthook:
return "".join(better_exceptions.format_exception(type(err), err, tb))
# If all else fails, use the standard-library formatting tools
return "".join(traceback.format_exception(type(err), err, tb))