1# -*- coding: utf-8 -*-
2"""Base class to query a webservice and parse the result to py objects."""
3
4import json
5import logging
6from time import sleep
7from time import time as timestamp
8
9from . import webservice
10from ._exceptions import DataNotFoundAtServiceError, ServiceIsDownError
11
12UA = 'isbnlib (gzip)'
13OUT_OF_SERVICE = 'Temporarily out of service'
14BOOK_NOT_FOUND = 'No results match your search'
15LOGGER = logging.getLogger(__name__)
16THROTTLING = 1
17
18
19# pylint: disable=useless-object-inheritance
20class WEBQuery(object):
21    """Base class to query a webservice and parse the result to py objects."""
22
23    T = {'id': timestamp()}  # noqa
24
25    def __init__(self, service_url, ua=UA, throttling=THROTTLING):
26        """Initialize & call webservice."""
27        srv = service_url[8:20]
28        last = WEBQuery.T[srv] if srv in WEBQuery.T else 0.0
29        wait = 0 if timestamp() - last > throttling else throttling
30        sleep(wait)
31        self.url = service_url
32        self.data = webservice.query(service_url, ua)
33        WEBQuery.T[srv] = timestamp()
34
35    def check_data(self, data_checker=None):  # pragma: no cover
36        """Check the data & handle errors."""
37        if data_checker:
38            return data_checker(self.data)
39        if self.data == '{}':  # noqa
40            LOGGER.warning('DataNotFoundAtServiceError for %s', self.url)
41            raise DataNotFoundAtServiceError(self.url)
42        if BOOK_NOT_FOUND in self.data:
43            LOGGER.warning('DataNotFoundAtServiceError for %s', self.url)
44            raise DataNotFoundAtServiceError(self.url)
45        if OUT_OF_SERVICE in self.data:
46            LOGGER.critical('ServiceIsDownError for %s', self.url)
47            raise ServiceIsDownError(self.url)
48        return True
49
50    def parse_data(self, parser=json.loads):
51        """Parse the data (default JSON -> PY)."""
52        if parser is None:  # pragma: no cover
53            return self.data
54        return parser(self.data)  # <-- data is now unicode
55
56
57def query(
58    url,
59    user_agent=UA,
60    data_checker=None,
61    parser=json.loads,
62    throttling=THROTTLING,
63):
64    """Put call and return the data from the web service."""
65    wq = WEBQuery(url, user_agent, throttling)
66    return wq.parse_data(parser) if wq.check_data(data_checker) else None
67