# Path: rebulk/utils.py
# class IdentitySet(MutableSet):  # pragma: no cover
#     """
#     Set based on identity
#     """
#     def __init__(self, items=None):  # pylint: disable=super-init-not-called
#         if items is None:
#             items = []
#         self.refs = set(map(_Ref, items))
# 
#     def __contains__(self, elem):
#         return _Ref(elem) in self.refs
# 
#     def __iter__(self):
#         return (ref.value for ref in self.refs)
# 
#     def __len__(self):
#         return len(self.refs)
# 
#     def add(self, value):
#         self.refs.add(_Ref(value))
# 
#     def discard(self, value):
#         self.refs.discard(_Ref(value))
# 
#     def update(self, iterable):
#         """
#         Update set with iterable
#         :param iterable:
#         :type iterable:
#         :return:
#         :rtype:
#         """
#         for elem in iterable:
#             self.add(elem)
# 
#     def __repr__(self):  # pragma: no cover
#         return f"{type(self).__name__}({list(self)})"
# 
# Path: rebulk/rules.py
# class Rule(CustomRule):
#     """
#     Definition of a rule to apply
#     """
#     # pylint:disable=abstract-method
#     consequence = None
# 
#     def then(self, matches, when_response, context):
#         assert self.consequence
#         if is_iterable(self.consequence):
#             if not is_iterable(when_response):
#                 when_response = [when_response]
#             iterator = iter(when_response)
#             for cons in self.consequence:  #pylint: disable=not-an-iterable
#                 if inspect.isclass(cons):
#                     cons = cons()
#                 cons.then(matches, next(iterator), context)
#         else:
#             cons = self.consequence
#             if inspect.isclass(cons):
#                 cons = cons()  # pylint:disable=not-callable
#             cons.then(matches, when_response, context)
# 
# class RemoveMatch(Consequence):  # pylint: disable=abstract-method
#     """
#     Remove matches returned by then
#     """
#     def then(self, matches, when_response, context):
#         if is_iterable(when_response):
#             ret = []
#             when_response = list(when_response)
#             for match in when_response:
#                 if match in matches:
#                     matches.remove(match)
#                     ret.append(match)
#             return ret
#         if when_response in matches:
#             matches.remove(when_response)
#             return when_response


from logging import getLogger
from .utils import IdentitySet
from .rules import Rule, RemoveMatch
                    if conflicting_match.conflict_solver:
                        conflict_solvers.append((conflicting_match.conflict_solver, True))

                    for conflict_solver, reverse in reversed(conflict_solvers):
                        if reverse:
                            to_remove = conflict_solver(conflicting_match, match)
                        else:
                            to_remove = conflict_solver(match, conflicting_match)
                        if to_remove == DEFAULT:
                            continue
                        if to_remove and to_remove not in to_remove_matches:
                            both_matches = [match, conflicting_match]
                            both_matches.remove(to_remove)
                            to_keep = both_matches[0]

                            if to_keep not in to_remove_matches:
                                log(self.log_level, "Conflicting match %s will be removed in favor of match %s",
                                    to_remove, to_keep)

                                to_remove_matches.add(to_remove)
                        break
        return to_remove_matches


class PrivateRemover(Rule):
    """
    Removes private matches rule.
    """
    priority = POST_PROCESS


# Path: rebulk/utils.py
# class IdentitySet(MutableSet):  # pragma: no cover
#     """
#     Set based on identity
#     """
#     def __init__(self, items=None):  # pylint: disable=super-init-not-called
#         if items is None:
#             items = []
#         self.refs = set(map(_Ref, items))
# 
#     def __contains__(self, elem):
#         return _Ref(elem) in self.refs
# 
#     def __iter__(self):
#         return (ref.value for ref in self.refs)
# 
#     def __len__(self):
#         return len(self.refs)
# 
#     def add(self, value):
#         self.refs.add(_Ref(value))
# 
#     def discard(self, value):
#         self.refs.discard(_Ref(value))
# 
#     def update(self, iterable):
#         """
#         Update set with iterable
#         :param iterable:
#         :type iterable:
#         :return:
#         :rtype:
#         """
#         for elem in iterable:
#             self.add(elem)
# 
#     def __repr__(self):  # pragma: no cover
#         return f"{type(self).__name__}({list(self)})"
# 
# Path: rebulk/rules.py
# class Rule(CustomRule):
#     """
#     Definition of a rule to apply
#     """
#     # pylint:disable=abstract-method
#     consequence = None
# 
#     def then(self, matches, when_response, context):
#         assert self.consequence
#         if is_iterable(self.consequence):
#             if not is_iterable(when_response):
#                 when_response = [when_response]
#             iterator = iter(when_response)
#             for cons in self.consequence:  #pylint: disable=not-an-iterable
#                 if inspect.isclass(cons):
#                     cons = cons()
#                 cons.then(matches, next(iterator), context)
#         else:
#             cons = self.consequence
#             if inspect.isclass(cons):
#                 cons = cons()  # pylint:disable=not-callable
#             cons.then(matches, when_response, context)
# 
# class RemoveMatch(Consequence):  # pylint: disable=abstract-method
#     """
#     Remove matches returned by then
#     """
#     def then(self, matches, when_response, context):
#         if is_iterable(when_response):
#             ret = []
#             when_response = list(when_response)
#             for match in when_response:
#                 if match in matches:
#                     matches.remove(match)
#                     ret.append(match)
#             return ret
#         if when_response in matches:
#             matches.remove(when_response)
#             return when_response


# Path: rebulk/processors.py
from logging import getLogger
from .utils import IdentitySet
from .rules import Rule, RemoveMatch

                    if conflicting_match.conflict_solver:
                        conflict_solvers.append((conflicting_match.conflict_solver, True))

                    for conflict_solver, reverse in reversed(conflict_solvers):
                        if reverse:
                            to_remove = conflict_solver(conflicting_match, match)
                        else:
                            to_remove = conflict_solver(match, conflicting_match)
                        if to_remove == DEFAULT:
                            continue
                        if to_remove and to_remove not in to_remove_matches:
                            both_matches = [match, conflicting_match]
                            both_matches.remove(to_remove)
                            to_keep = both_matches[0]

                            if to_keep not in to_remove_matches:
                                log(self.log_level, "Conflicting match %s will be removed in favor of match %s",
                                    to_remove, to_keep)

                                to_remove_matches.add(to_remove)
                        break
        return to_remove_matches


class PrivateRemover(Rule):
    """
    Removes private matches rule.
    """
    priority = POST_PROCESS


    consequence = RemoveMatch