# Path: xpaw/spider.py
# class Spider:
# 
#     @classmethod
#     def from_crawler(cls, crawler):
#         cls.crawler = crawler
#         cls.config = crawler.config
#         spider = cls()
#         crawler.event_bus.subscribe(spider.open, events.crawler_start)
#         crawler.event_bus.subscribe(spider.close, events.crawler_shutdown)
#         return spider
# 
#     @property
#     def logger(self):
#         return log
# 
#     def log(self, message, *args, level=logging.INFO, **kwargs):
#         self.logger.log(level, message, *args, **kwargs)
# 
#     def parse(self, response):
#         raise NotImplementedError
# 
#     def start_requests(self):
#         raise NotImplementedError
# 
#     def open(self):
#         pass
# 
#     def close(self):
#         pass
# 
#     async def request_success(self, response):
#         callback = response.request.callback
#         if callback:
#             res = self._get_mothod(callback)(response)
#         else:
#             res = self.parse(response)
#         if inspect.iscoroutine(res):
#             res = await res
#         return res
# 
#     async def request_error(self, request, error):
#         try:
#             if request and request.errback:
#                 r = self._get_mothod(request.errback)(request, error)
#                 if inspect.iscoroutine(r):
#                     await r
#         except CancelledError:
#             raise
#         except Exception:
#             log.warning("Error occurred in the error callback of spider", exc_info=True)
# 
#     def _get_mothod(self, method):
#         if isinstance(method, str):
#             method = getattr(self, method)
#         return method
# 
# Path: xpaw/events.py

# 
# Path: tests/crawler.py
# class Crawler:
#     def __init__(self, **kwargs):
#         self.event_bus = EventBus()
#         self.config = Config(DEFAULT_CONFIG, **kwargs)


import pytest
from xpaw.spider import Spider
from xpaw import events
from .crawler import Crawler
# coding=utf-8





class FooSpider(Spider):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.data = self.config['data']

    def open(self):
        super().open()
        self.data['open'] = ''

    def close(self):
        super().close()
        self.data['close'] = ''


@pytest.mark.asyncio
async def test_spider():
    data = {}
    crawler = Crawler(data=data)
    spider = FooSpider.from_crawler(crawler)
    await crawler.event_bus.send(events.crawler_start)
    with pytest.raises(NotImplementedError):
        spider.start_requests()
    with pytest.raises(NotImplementedError):
        spider.parse(None)

# Path: xpaw/spider.py
# class Spider:
# 
#     @classmethod
#     def from_crawler(cls, crawler):
#         cls.crawler = crawler
#         cls.config = crawler.config
#         spider = cls()
#         crawler.event_bus.subscribe(spider.open, events.crawler_start)
#         crawler.event_bus.subscribe(spider.close, events.crawler_shutdown)
#         return spider
# 
#     @property
#     def logger(self):
#         return log
# 
#     def log(self, message, *args, level=logging.INFO, **kwargs):
#         self.logger.log(level, message, *args, **kwargs)
# 
#     def parse(self, response):
#         raise NotImplementedError
# 
#     def start_requests(self):
#         raise NotImplementedError
# 
#     def open(self):
#         pass
# 
#     def close(self):
#         pass
# 
#     async def request_success(self, response):
#         callback = response.request.callback
#         if callback:
#             res = self._get_mothod(callback)(response)
#         else:
#             res = self.parse(response)
#         if inspect.iscoroutine(res):
#             res = await res
#         return res
# 
#     async def request_error(self, request, error):
#         try:
#             if request and request.errback:
#                 r = self._get_mothod(request.errback)(request, error)
#                 if inspect.iscoroutine(r):
#                     await r
#         except CancelledError:
#             raise
#         except Exception:
#             log.warning("Error occurred in the error callback of spider", exc_info=True)
# 
#     def _get_mothod(self, method):
#         if isinstance(method, str):
#             method = getattr(self, method)
#         return method
# 
# Path: xpaw/events.py

# 
# Path: tests/crawler.py
# class Crawler:
#     def __init__(self, **kwargs):
#         self.event_bus = EventBus()
#         self.config = Config(DEFAULT_CONFIG, **kwargs)


# Path: tests/test_spider.py
import pytest
from xpaw.spider import Spider
from xpaw import events
from .crawler import Crawler

# coding=utf-8





class FooSpider(Spider):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.data = self.config['data']

    def open(self):
        super().open()
        self.data['open'] = ''

    def close(self):
        super().close()
        self.data['close'] = ''


@pytest.mark.asyncio
async def test_spider():
    data = {}
    crawler = Crawler(data=data)
    spider = FooSpider.from_crawler(crawler)
    await crawler.event_bus.send(events.crawler_start)
    with pytest.raises(NotImplementedError):
        spider.start_requests()
    with pytest.raises(NotImplementedError):
        spider.parse(None)

    await crawler.event_bus.send(events.crawler_shutdown)