# Path: xpaw/eventbus.py
# class EventBus:
#     def __init__(self):
#         self._refs = {}
# 
#     def subscribe(self, receiver, event):
#         if event not in self._refs:
#             self._refs[event] = {}
#         if not hasattr(receiver, '__func__') or not hasattr(receiver, '__self__'):
#             raise ValueError("Failed to subscribe, {} has no attribute '__func__' or '__self__'".format(receiver))
#         i = self._calc_id(receiver)
#         if i in self._refs[event]:
#             f = self._refs[event][i]()
#             if f is not None:
#                 return
#         self._refs[event][i] = weakref.WeakMethod(receiver)
# 
#     def unsubscribe(self, receiver, event):
#         if event in self._refs:
#             i = self._calc_id(receiver)
#             if i in self._refs[event]:
#                 del self._refs[event][i]
# 
#     async def send(self, event, **kwargs):
#         if event not in self._refs:
#             return
#         del_list = []
#         for i in self._refs[event]:
#             f = self._refs[event][i]()
#             if f is None:
#                 del_list.append(i)
#             else:
#                 try:
#                     res = f(**kwargs)
#                     if inspect.iscoroutine(res):
#                         await res
#                 except CancelledError:
#                     raise
#                 except Exception:
#                     log.warning("Failed to send the event", exc_info=True)
#         for i in del_list:
#             del self._refs[event][i]
#         del del_list
# 
#     def _calc_id(self, receiver):
#         return hash((id(receiver.__func__), id(receiver.__self__)))
# 
# Path: xpaw/config.py
# class Config(MutableMapping):
#     def __init__(self, __values=None, **kwargs):
#         self.attrs = {}
#         self.update(__values, **kwargs)
# 
#     def __getitem__(self, name):
#         if name not in self:
#             return None
#         return self.attrs[name]
# 
#     def __contains__(self, name):
#         return name in self.attrs
# 
#     def get(self, name, default=None):
#         return self[name] if self[name] is not None else default
# 
#     def getbool(self, name, default=None):
#         v = self.get(name, default)
#         return getbool(v)
# 
#     def getint(self, name, default=None):
#         v = self.get(name, default)
#         return getint(v)
# 
#     def getfloat(self, name, default=None):
#         v = self.get(name, default)
#         return getfloat(v)
# 
#     def getlist(self, name, default=None):
#         v = self.get(name, default)
#         return getlist(v)
# 
#     def __setitem__(self, name, value):
#         self.attrs[name] = value
# 
#     def set(self, name, value):
#         self[name] = value
# 
#     def setdefault(self, k, default=None):
#         if k not in self:
#             self[k] = default
# 
#     def update(self, __values=None, **kwargs):
#         if __values is not None:
#             if isinstance(__values, Config):
#                 for name in __values:
#                     self[name] = __values[name]
#             else:
#                 for name, value in __values.items():
#                     self[name] = value
#         for k, v in kwargs.items():
#             self[k] = v
# 
#     def delete(self, name):
#         del self.attrs[name]
# 
#     def __delitem__(self, name):
#         del self.attrs[name]
# 
#     def copy(self):
#         return copy.deepcopy(self)
# 
#     def __iter__(self):
#         return iter(self.attrs)
# 
#     def __len__(self):
#         return len(self.attrs)
# 
# DEFAULT_CONFIG = {
#     'daemon': False,
#     'log_level': 'info',
#     'log_format': '%(asctime)s %(name)s [%(levelname)s] %(message)s',
#     'log_dateformat': '[%Y-%m-%d %H:%M:%S %z]',
#     'downloader': 'xpaw.downloader.Downloader',
#     'user_agent': ':desktop',
#     'random_user_agent': False,
#     'retry_enabled': True,
#     'stats_collector': 'xpaw.stats.StatsCollector',
#     'queue': 'xpaw.queue.PriorityQueue',
#     'dupe_filter': 'xpaw.dupefilter.HashDupeFilter',
#     'default_extensions': [
#         'xpaw.extensions.DefaultHeadersMiddleware',
#         'xpaw.extensions.UserAgentMiddleware',
#         'xpaw.extensions.RetryMiddleware',
#         'xpaw.extensions.ProxyMiddleware',
#         'xpaw.extensions.SpeedLimitMiddleware',
#         'xpaw.extensions.DepthMiddleware',
#     ]
# }


from xpaw.eventbus import EventBus
from xpaw.config import Config, DEFAULT_CONFIG
# coding=utf-8



class Crawler:
    def __init__(self, **kwargs):
        self.event_bus = EventBus()

# Path: xpaw/eventbus.py
# class EventBus:
#     def __init__(self):
#         self._refs = {}
# 
#     def subscribe(self, receiver, event):
#         if event not in self._refs:
#             self._refs[event] = {}
#         if not hasattr(receiver, '__func__') or not hasattr(receiver, '__self__'):
#             raise ValueError("Failed to subscribe, {} has no attribute '__func__' or '__self__'".format(receiver))
#         i = self._calc_id(receiver)
#         if i in self._refs[event]:
#             f = self._refs[event][i]()
#             if f is not None:
#                 return
#         self._refs[event][i] = weakref.WeakMethod(receiver)
# 
#     def unsubscribe(self, receiver, event):
#         if event in self._refs:
#             i = self._calc_id(receiver)
#             if i in self._refs[event]:
#                 del self._refs[event][i]
# 
#     async def send(self, event, **kwargs):
#         if event not in self._refs:
#             return
#         del_list = []
#         for i in self._refs[event]:
#             f = self._refs[event][i]()
#             if f is None:
#                 del_list.append(i)
#             else:
#                 try:
#                     res = f(**kwargs)
#                     if inspect.iscoroutine(res):
#                         await res
#                 except CancelledError:
#                     raise
#                 except Exception:
#                     log.warning("Failed to send the event", exc_info=True)
#         for i in del_list:
#             del self._refs[event][i]
#         del del_list
# 
#     def _calc_id(self, receiver):
#         return hash((id(receiver.__func__), id(receiver.__self__)))
# 
# Path: xpaw/config.py
# class Config(MutableMapping):
#     def __init__(self, __values=None, **kwargs):
#         self.attrs = {}
#         self.update(__values, **kwargs)
# 
#     def __getitem__(self, name):
#         if name not in self:
#             return None
#         return self.attrs[name]
# 
#     def __contains__(self, name):
#         return name in self.attrs
# 
#     def get(self, name, default=None):
#         return self[name] if self[name] is not None else default
# 
#     def getbool(self, name, default=None):
#         v = self.get(name, default)
#         return getbool(v)
# 
#     def getint(self, name, default=None):
#         v = self.get(name, default)
#         return getint(v)
# 
#     def getfloat(self, name, default=None):
#         v = self.get(name, default)
#         return getfloat(v)
# 
#     def getlist(self, name, default=None):
#         v = self.get(name, default)
#         return getlist(v)
# 
#     def __setitem__(self, name, value):
#         self.attrs[name] = value
# 
#     def set(self, name, value):
#         self[name] = value
# 
#     def setdefault(self, k, default=None):
#         if k not in self:
#             self[k] = default
# 
#     def update(self, __values=None, **kwargs):
#         if __values is not None:
#             if isinstance(__values, Config):
#                 for name in __values:
#                     self[name] = __values[name]
#             else:
#                 for name, value in __values.items():
#                     self[name] = value
#         for k, v in kwargs.items():
#             self[k] = v
# 
#     def delete(self, name):
#         del self.attrs[name]
# 
#     def __delitem__(self, name):
#         del self.attrs[name]
# 
#     def copy(self):
#         return copy.deepcopy(self)
# 
#     def __iter__(self):
#         return iter(self.attrs)
# 
#     def __len__(self):
#         return len(self.attrs)
# 
# DEFAULT_CONFIG = {
#     'daemon': False,
#     'log_level': 'info',
#     'log_format': '%(asctime)s %(name)s [%(levelname)s] %(message)s',
#     'log_dateformat': '[%Y-%m-%d %H:%M:%S %z]',
#     'downloader': 'xpaw.downloader.Downloader',
#     'user_agent': ':desktop',
#     'random_user_agent': False,
#     'retry_enabled': True,
#     'stats_collector': 'xpaw.stats.StatsCollector',
#     'queue': 'xpaw.queue.PriorityQueue',
#     'dupe_filter': 'xpaw.dupefilter.HashDupeFilter',
#     'default_extensions': [
#         'xpaw.extensions.DefaultHeadersMiddleware',
#         'xpaw.extensions.UserAgentMiddleware',
#         'xpaw.extensions.RetryMiddleware',
#         'xpaw.extensions.ProxyMiddleware',
#         'xpaw.extensions.SpeedLimitMiddleware',
#         'xpaw.extensions.DepthMiddleware',
#     ]
# }


# Path: tests/crawler.py
from xpaw.eventbus import EventBus
from xpaw.config import Config, DEFAULT_CONFIG

# coding=utf-8



class Crawler:
    def __init__(self, **kwargs):
        self.event_bus = EventBus()

        self.config = Config(DEFAULT_CONFIG, **kwargs)