# Path: pyknow/fieldconstraint.py
# class FieldConstraint(ConditionalElement):
#     def __and__(self, other):
#         if isinstance(self, ANDFC) and isinstance(other, ANDFC):
#             return ANDFC(*[x for x in chain(self, other)])
#         elif isinstance(self, ANDFC):
#             return ANDFC(*[x for x in self]+[other])
#         elif isinstance(other, ANDFC):
#             return ANDFC(*[self]+[x for x in other])
#         else:
#             return ANDFC(self, other)
# 
#     def __or__(self, other):
#         if isinstance(self, ORFC) and isinstance(other, ORFC):
#             return ORFC(*[x for x in chain(self, other)])
#         elif isinstance(self, ORFC):
#             return ORFC(*[x for x in self]+[other])
#         elif isinstance(other, ORFC):
#             return ORFC(*[self]+[x for x in other])
#         else:
#             return ORFC(self, other)
# 
#     def __invert__(self):
#         return NOTFC(self)
# 
# Path: pyknow/fieldconstraint.py
# class L(Bindable, FieldConstraint):
#     """Literal Field Constraint"""
#     def __new__(cls, value, __bind__=None):
#         obj = super(L, cls).__new__(cls, value)
#         obj.__bind__ = __bind__
#         return obj
# 
#     @property
#     def value(self):
#         return self[0]
# 
#     def __repr__(self):  # pragma: no cover
#         return "L(%r)" % self.value
# 
# class P(Bindable, FieldConstraint):
#     """Predicate Field Constraint"""
#     def __new__(cls, match, __bind__=None):
#         if not isinstance(match, Callable):
#             raise TypeError("PredicateFC needs a callable.")
#         else:
#             obj = super(P, cls).__new__(cls, match)
#             obj.__bind__ = __bind__
#             return obj
# 
#     @property
#     def match(self):
#         return self[0]
# 
# class W(Bindable, FieldConstraint):
#     """Wildcard Field Constraint"""
#     def __new__(cls, __bind__=None):
#         obj = super(W, cls).__new__(cls)
#         obj.__bind__ = __bind__
#         return obj
# 
#     def __repr__(self):  # pragma: no cover
#         return "W()" if self.__bind__ is None else "W(%r)" % self.__bind__
# 
# Path: pyknow/fieldconstraint.py
# class ANDFC(FieldConstraint):
#     pass
# 
# class ORFC(FieldConstraint):
#     pass
# 
# class NOTFC(FieldConstraint):
#     def __rlshift__(self, other):
#         """Pass the binding to the internal element."""
#         self[0].__rlshift__(other)
#         return self
# 
# Path: pyknow/matchers/rete/abstract.py
# class Check(metaclass=abc.ABCMeta):
#     @abc.abstractmethod
#     def __call__(self, fact):  # pragma: no cover
#         """
#         Given a `Fact` or a subclass of `Fact`, return:
# 
#             * `True` if the check matched.
#             * `False` if the check didn't match.
#             * A non empty `Mapping` meaning the check matched and yield
#               some context.
# 
#         """
#         pass
# 
#     def __str__(self):  # pragma: no cover
#         return self.__class__.__name__
# 
# Path: pyknow/watchers.py
# MATCH = define_watcher('MATCH')


from collections import namedtuple
from collections.abc import Mapping
from functools import singledispatch
from pyknow.fieldconstraint import FieldConstraint
from pyknow.fieldconstraint import L, P, W
from pyknow.fieldconstraint import ANDFC, ORFC, NOTFC
from .abstract import Check
from pyknow.watchers import MATCH
import dis
import inspect
                what,
                how,
                check_function.check,
                check_function.expected)

        return cls._instances[key]

    def __call__(self, data, is_fact=True):
        if is_fact:
            if isinstance(self.what, str):
                record = data
                if (not self.what.startswith('__')
                        and not self.what.endswith('__')):
                    try:
                        for p in self.what.split('__'):
                            if p.isnumeric():
                                p = int(p)
                            record = record[p]
                    except (IndexError, KeyError, TypeError):
                        return False
            else:
                try:
                    record = data[self.what]
                except (IndexError, KeyError, TypeError):
                    return False
        else:
            record = data

        res = self.check(record, self.expected)


# Path: pyknow/fieldconstraint.py
# class FieldConstraint(ConditionalElement):
#     def __and__(self, other):
#         if isinstance(self, ANDFC) and isinstance(other, ANDFC):
#             return ANDFC(*[x for x in chain(self, other)])
#         elif isinstance(self, ANDFC):
#             return ANDFC(*[x for x in self]+[other])
#         elif isinstance(other, ANDFC):
#             return ANDFC(*[self]+[x for x in other])
#         else:
#             return ANDFC(self, other)
# 
#     def __or__(self, other):
#         if isinstance(self, ORFC) and isinstance(other, ORFC):
#             return ORFC(*[x for x in chain(self, other)])
#         elif isinstance(self, ORFC):
#             return ORFC(*[x for x in self]+[other])
#         elif isinstance(other, ORFC):
#             return ORFC(*[self]+[x for x in other])
#         else:
#             return ORFC(self, other)
# 
#     def __invert__(self):
#         return NOTFC(self)
# 
# Path: pyknow/fieldconstraint.py
# class L(Bindable, FieldConstraint):
#     """Literal Field Constraint"""
#     def __new__(cls, value, __bind__=None):
#         obj = super(L, cls).__new__(cls, value)
#         obj.__bind__ = __bind__
#         return obj
# 
#     @property
#     def value(self):
#         return self[0]
# 
#     def __repr__(self):  # pragma: no cover
#         return "L(%r)" % self.value
# 
# class P(Bindable, FieldConstraint):
#     """Predicate Field Constraint"""
#     def __new__(cls, match, __bind__=None):
#         if not isinstance(match, Callable):
#             raise TypeError("PredicateFC needs a callable.")
#         else:
#             obj = super(P, cls).__new__(cls, match)
#             obj.__bind__ = __bind__
#             return obj
# 
#     @property
#     def match(self):
#         return self[0]
# 
# class W(Bindable, FieldConstraint):
#     """Wildcard Field Constraint"""
#     def __new__(cls, __bind__=None):
#         obj = super(W, cls).__new__(cls)
#         obj.__bind__ = __bind__
#         return obj
# 
#     def __repr__(self):  # pragma: no cover
#         return "W()" if self.__bind__ is None else "W(%r)" % self.__bind__
# 
# Path: pyknow/fieldconstraint.py
# class ANDFC(FieldConstraint):
#     pass
# 
# class ORFC(FieldConstraint):
#     pass
# 
# class NOTFC(FieldConstraint):
#     def __rlshift__(self, other):
#         """Pass the binding to the internal element."""
#         self[0].__rlshift__(other)
#         return self
# 
# Path: pyknow/matchers/rete/abstract.py
# class Check(metaclass=abc.ABCMeta):
#     @abc.abstractmethod
#     def __call__(self, fact):  # pragma: no cover
#         """
#         Given a `Fact` or a subclass of `Fact`, return:
# 
#             * `True` if the check matched.
#             * `False` if the check didn't match.
#             * A non empty `Mapping` meaning the check matched and yield
#               some context.
# 
#         """
#         pass
# 
#     def __str__(self):  # pragma: no cover
#         return self.__class__.__name__
# 
# Path: pyknow/watchers.py
# MATCH = define_watcher('MATCH')


# Path: pyknow/matchers/rete/check.py
from collections import namedtuple
from collections.abc import Mapping
from functools import singledispatch
from pyknow.fieldconstraint import FieldConstraint
from pyknow.fieldconstraint import L, P, W
from pyknow.fieldconstraint import ANDFC, ORFC, NOTFC
from .abstract import Check
from pyknow.watchers import MATCH
import dis
import inspect

                what,
                how,
                check_function.check,
                check_function.expected)

        return cls._instances[key]

    def __call__(self, data, is_fact=True):
        if is_fact:
            if isinstance(self.what, str):
                record = data
                if (not self.what.startswith('__')
                        and not self.what.endswith('__')):
                    try:
                        for p in self.what.split('__'):
                            if p.isnumeric():
                                p = int(p)
                            record = record[p]
                    except (IndexError, KeyError, TypeError):
                        return False
            else:
                try:
                    record = data[self.what]
                except (IndexError, KeyError, TypeError):
                    return False
        else:
            record = data

        res = self.check(record, self.expected)


        log = MATCH.info if res else MATCH.debug