grappa/assertion.py
# -*- coding: utf-8 -*-
from .base import BaseTest
class AssertionProxy(BaseTest):
"""
AssertionProxy is used as proxy delegator call chain for test
definitions.
"""
def __init__(self, resolver, operator, fn):
self._called = False
self._accessed = False
self._fn = fn
self._op = operator
self._resolver = resolver
self._test = resolver.test
def __call__(self, expected, *args, **kw):
if self._called:
raise RuntimeError('grappa: operator already called')
if not self._called:
self._called = True
return self._fn(expected, *args, **kw)
def _match_alias(self, name):
return hasattr(self._op, 'aliases') and name in self._op.aliases
def _match_suboperator(self, name):
def create(operator):
return self._resolver.run_matcher(operator(self._test._ctx))
# Check that operator has suboperators
if not getattr(self._op, 'suboperators', None):
return False
# Match parent operators
for op in self._op.suboperators:
# Match suboperator names ignoring first words
for opname in op.operators:
if name == opname:
return create(op)
if '_' in opname and name == '_'.join(opname.split('_')[1:]):
return create(op)
def _on_access(self):
# Define on_access operator function
def on_access(subject):
try:
self._op.on_access(subject)
finally:
return True
# Add assertion function
self._test._engine.add_assertion(on_access)
# Flag proxy state as accessed operator
self._accessed = True
def is_on_access(self):
# Trigger operator on_access operator event method, if available
return hasattr(self._op, 'on_access') and not self._accessed
def __getattr__(self, name):
"""
Overloads attribute accessor in order to load the assertion
operator dynamically.
"""
# Match operator aliases for chaining
if self._match_alias(name):
self._test._engine.add_keyword(name)
return self
# Trigger operator on_access operator event method, if available
if self.is_on_access():
self._on_access()
# Match suboperator, if needed
suboperator = self._match_suboperator(name)
if suboperator:
# Register keyword for suboperator
self._test._engine.add_keyword(name)
# Trigger suboperator on_access event method, if available
if suboperator.is_on_access():
suboperator._on_access()
# Return suboperator proxy
return suboperator
# Delegate access to global assertion instance
return getattr(self._test, name)
def __ror__(self, value):
"""
Overloads ``|`` operator.
"""
return self._fn(value)._trigger()
def __gt__(self, value):
"""
Overloads ``>`` operator.
"""
return self.__ror_(value)