Skip to content

Commit

Permalink
Remove _CallOutcome; embrace _Result
Browse files Browse the repository at this point in the history
`_CallOutcome` limits usage due the constructor calling a function
input. Instead add a `classmethod` constructor `_Result.from_call()`
which can be used to get the same behaviour and avoids duplicate types.
  • Loading branch information
Tyler Goodlet committed Jul 11, 2017
1 parent 21fd6c4 commit 07715f5
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 44 deletions.
48 changes: 6 additions & 42 deletions pluggy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import sys
import inspect
import warnings
from .callers import _MultiCall, HookCallError, _raise_wrapfail
from .callers import _MultiCall, HookCallError, _raise_wrapfail, _Result

__version__ = '0.5.0'

__all__ = ["PluginManager", "PluginValidationError", "HookCallError",
"HookspecMarker", "HookimplMarker"]

_py3 = sys.version_info > (3, 0)


class PluginValidationError(Exception):
""" plugin failed validation. """
Expand Down Expand Up @@ -83,7 +80,7 @@ def __call__(self, function=None, hookwrapper=False, optionalhook=False,
If hookwrapper is True the hook implementations needs to execute exactly
one "yield". The code before the yield is run early before any non-hookwrapper
function is run. The code after the yield is run after all non-hookwrapper
function have run. The yield receives an ``_CallOutcome`` object representing
function have run. The yield receives a ``_Result`` object representing
the exception or result outcome of the inner calls (including other hookwrapper
calls).
Expand Down Expand Up @@ -172,14 +169,14 @@ def get(self, name):
def _wrapped_call(wrap_controller, func):
""" Wrap calling to a function with a generator which needs to yield
exactly once. The yield point will trigger calling the wrapped function
and return its _CallOutcome to the yield point. The generator then needs
and return its ``_Result`` to the yield point. The generator then needs
to finish (raise StopIteration) in order for the wrapped call to complete.
"""
try:
next(wrap_controller) # first yield
except StopIteration:
_raise_wrapfail(wrap_controller, "did not yield")
call_outcome = _CallOutcome(func)
call_outcome = _Result(func)
try:
wrap_controller.send(call_outcome)
_raise_wrapfail(wrap_controller, "has second yield")
Expand All @@ -188,39 +185,6 @@ def _wrapped_call(wrap_controller, func):
return call_outcome.get_result()


class _CallOutcome(object):
""" Outcome of a function call, either an exception or a proper result.
Calling the ``get_result`` method will return the result or reraise
the exception raised when the function was called. """
excinfo = None

def __init__(self, func):
try:
self.result = func()
except BaseException:
self.excinfo = sys.exc_info()

def force_result(self, result):
self.result = result
self.excinfo = None

def get_result(self):
if self.excinfo is None:
return self.result
else:
ex = self.excinfo
if _py3:
raise ex[1].with_traceback(ex[2])
_reraise(*ex) # noqa


if not _py3:
exec("""
def _reraise(cls, val, tb):
raise cls, val, tb
""")


class _TracedHookExecution(object):
def __init__(self, pluginmanager, before, after):
self.pluginmanager = pluginmanager
Expand All @@ -232,7 +196,7 @@ def __init__(self, pluginmanager, before, after):

def __call__(self, hook, hook_impls, kwargs):
self.before(hook.name, hook_impls, kwargs)
outcome = _CallOutcome(lambda: self.oldcall(hook, hook_impls, kwargs))
outcome = _Result.from_call(lambda: self.oldcall(hook, hook_impls, kwargs))
self.after(outcome, hook.name, hook_impls, kwargs)
return outcome.get_result()

Expand Down Expand Up @@ -481,7 +445,7 @@ def add_hookcall_monitoring(self, before, after):
of HookImpl instances and the keyword arguments for the hook call.
``after(outcome, hook_name, hook_impls, kwargs)`` receives the
same arguments as ``before`` but also a :py:class:`_CallOutcome`` object
same arguments as ``before`` but also a :py:class:`_Result`` object
which represents the result of the overall hook call.
"""
return _TracedHookExecution(self, before, after).undo
Expand Down
14 changes: 12 additions & 2 deletions pluggy/callers.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,21 @@ class HookCallError(Exception):
""" Hook was called wrongly. """


class Result(object):
class _Result(object):
def __init__(self, result, excinfo):
self.result = result
self.excinfo = excinfo

@classmethod
def from_call(cls, func):
result = excinfo = None
try:
result = func()
except BaseException:
excinfo = sys.exc_info()

return cls(result, excinfo)

def force_result(self, result):
self.result = result
self.excinfo = None
Expand Down Expand Up @@ -86,7 +96,7 @@ def execute(self):
except BaseException:
excinfo = sys.exc_info()
finally:
outcome = Result(results, excinfo)
outcome = _Result(results, excinfo)

# run all wrapper post-yield blocks
for gen in reversed(teardowns):
Expand Down

0 comments on commit 07715f5

Please sign in to comment.