# Path: unicampi/repositories/base.py
# class Repository(object):
#     """Repository.
# 
#     Base contract for repository classes.
# 
#     """
# 
#     def __init__(self, **query):
#         self.query = query
# 
#     def all(self):
#         raise NotImplementedError
# 
#     def find(self, id):
#         raise NotImplementedError
# 
#     def where(self, **query):
#         """Filter a repository and return all entries that match the filter.
# 
#         :param query: dict, parameters that will be used to filter the
#                          entries of the repository.
#         :return: list, collection of entries.
#         """
#         return self.filter(**query).all()
# 
#     def filter(self, **query):
#         """Filter repository entries, resulting in a new repository with a
#         different query set.
# 
#         :param query: dict, parameters that will be used to filter the
#                       entries of the repository.
#         :return: Repository-like
#         """
#         # Transfer old query parameters to new instance.
#         new_query = self.query.copy()
#         # New parameters override previous ones.
#         new_query.update(query)
#         # Instantiate a new repository, of this class, with the new query.
#         return self.__class__(**new_query)
# 
# Path: unicampi/repositories/crawlers/utils.py
# class OnlineFilter(object):
#     """Online Filter.
# 
#     Provides a filtering interface for entries, allowing the user to perform
#     more complex queries such as `...Repository.filter(id__not_in=[1, 2])`.
# 
#     Example
#     -------
#     >>> users = [{'name': n} for n in ('lucas', 'kelly', 'adam', 'jessica')]
#     >>> OnlineFilter(name__in=['lucas', 'jessica']).commit(users)
#     >>> [{'name': 'lucas'}, {'name': 'jessica'}]
# 
#     """
# 
#     VALID_OPERATORS = {
#         'equals': lambda entry, field, value: entry.get(field) == value,
#         'not_equals': lambda entry, field, value: entry.get(field) != value,
#         'in': lambda entry, field, value: entry.get(field) in value,
#         'not_in': lambda entry, field, value: entry.get(field) not in value,
#         'contains': lambda entry, field, value: value in entry.get(field),
#         'not_contains': (lambda entry, field, value:
#                          value not in entry.get(field)),
#     }
# 
#     def __init__(self, **query):
#         self.query = query
#         self.entries = None
# 
#     def commit(self, entries):
#         matched_entries = []
# 
#         for entry in entries:
#             matches = True
# 
#             for field_and_maybe_operator, value in self.query.items():
#                 parts = field_and_maybe_operator.split('__')
# 
#                 if len(parts) == 1:
#                     # No operator specified, assume equals.
#                     field = '__'.join(parts)
#                     operator = 'equals'
#                 else:
#                     field = '__'.join(parts[:-1])
#                     operator = parts[-1]
# 
#                 if operator not in self.VALID_OPERATORS:
#                     raise RuntimeError('unknown operator {%s}' % operator)
# 
#                 matches = self.VALID_OPERATORS[operator](entry, field, value)
#                 if not matches:
#                     break
# 
#             if matches:
#                 matched_entries.append(entry)
#         return matched_entries


from ..base import Repository
from .utils import OnlineFilter


class CrawlerRepository(Repository):
    """Crawler Repository.

    Base repository class for test_crawlers.

    """

    _required_querying_fields = set()

    def _assert_valid_query(self):
        if not self._required_querying_fields.issubset(self.query.keys()):
            raise RuntimeError('Offerings must be filtered by %s. '
                               'Only then they be fetched.'
                               % self._required_querying_fields)

    def all(self):
        self._assert_valid_query()
        entries = self._fetch_and_parse_all()
        new_query = {k: v for k, v in self.query.items() if
                     k not in self._required_querying_fields}

# Path: unicampi/repositories/base.py
# class Repository(object):
#     """Repository.
# 
#     Base contract for repository classes.
# 
#     """
# 
#     def __init__(self, **query):
#         self.query = query
# 
#     def all(self):
#         raise NotImplementedError
# 
#     def find(self, id):
#         raise NotImplementedError
# 
#     def where(self, **query):
#         """Filter a repository and return all entries that match the filter.
# 
#         :param query: dict, parameters that will be used to filter the
#                          entries of the repository.
#         :return: list, collection of entries.
#         """
#         return self.filter(**query).all()
# 
#     def filter(self, **query):
#         """Filter repository entries, resulting in a new repository with a
#         different query set.
# 
#         :param query: dict, parameters that will be used to filter the
#                       entries of the repository.
#         :return: Repository-like
#         """
#         # Transfer old query parameters to new instance.
#         new_query = self.query.copy()
#         # New parameters override previous ones.
#         new_query.update(query)
#         # Instantiate a new repository, of this class, with the new query.
#         return self.__class__(**new_query)
# 
# Path: unicampi/repositories/crawlers/utils.py
# class OnlineFilter(object):
#     """Online Filter.
# 
#     Provides a filtering interface for entries, allowing the user to perform
#     more complex queries such as `...Repository.filter(id__not_in=[1, 2])`.
# 
#     Example
#     -------
#     >>> users = [{'name': n} for n in ('lucas', 'kelly', 'adam', 'jessica')]
#     >>> OnlineFilter(name__in=['lucas', 'jessica']).commit(users)
#     >>> [{'name': 'lucas'}, {'name': 'jessica'}]
# 
#     """
# 
#     VALID_OPERATORS = {
#         'equals': lambda entry, field, value: entry.get(field) == value,
#         'not_equals': lambda entry, field, value: entry.get(field) != value,
#         'in': lambda entry, field, value: entry.get(field) in value,
#         'not_in': lambda entry, field, value: entry.get(field) not in value,
#         'contains': lambda entry, field, value: value in entry.get(field),
#         'not_contains': (lambda entry, field, value:
#                          value not in entry.get(field)),
#     }
# 
#     def __init__(self, **query):
#         self.query = query
#         self.entries = None
# 
#     def commit(self, entries):
#         matched_entries = []
# 
#         for entry in entries:
#             matches = True
# 
#             for field_and_maybe_operator, value in self.query.items():
#                 parts = field_and_maybe_operator.split('__')
# 
#                 if len(parts) == 1:
#                     # No operator specified, assume equals.
#                     field = '__'.join(parts)
#                     operator = 'equals'
#                 else:
#                     field = '__'.join(parts[:-1])
#                     operator = parts[-1]
# 
#                 if operator not in self.VALID_OPERATORS:
#                     raise RuntimeError('unknown operator {%s}' % operator)
# 
#                 matches = self.VALID_OPERATORS[operator](entry, field, value)
#                 if not matches:
#                     break
# 
#             if matches:
#                 matched_entries.append(entry)
#         return matched_entries


# Path: unicampi/repositories/crawlers/base.py
from ..base import Repository
from .utils import OnlineFilter



class CrawlerRepository(Repository):
    """Crawler Repository.

    Base repository class for test_crawlers.

    """

    _required_querying_fields = set()

    def _assert_valid_query(self):
        if not self._required_querying_fields.issubset(self.query.keys()):
            raise RuntimeError('Offerings must be filtered by %s. '
                               'Only then they be fetched.'
                               % self._required_querying_fields)

    def all(self):
        self._assert_valid_query()
        entries = self._fetch_and_parse_all()
        new_query = {k: v for k, v in self.query.items() if
                     k not in self._required_querying_fields}

        return OnlineFilter(**new_query).commit(entries)