# Path: ckan_api_client/exceptions.py
# class HTTPError(Exception):
#     """
#     Exception representing an HTTP response error.
# 
#     .. attribute:: status_code
# 
#         HTTP status code
# 
#     .. attribute:: message
# 
#         Informative error message, if available
#     """
# 
#     def __init__(self, status_code, message, original=None):
#         self.args = (status_code, message, original)
# 
#     @property
#     def status_code(self):
#         return self.args[0]
# 
#     @property
#     def message(self):
#         return self.args[1]
# 
#     @property
#     def original(self):
#         return self.args[2]
# 
#     def __str__(self):
#         return ("{0}({1!r}, {2!r}, original={3!r})"
#                 .format(self.__class__.__name__,
#                         self.status_code, self.message, self.original))
# 
# class BadApiError(Exception):
#     """Exception used to mark bad behavior from the API"""
#     pass
# 
# Path: ckan_api_client/utils.py
# class SuppressExceptionIf(object):
#     """
#     Context manager used to suppress exceptions if they match
#     a given condition.
# 
#     Usage example::
# 
#         is_404 = lambda x: isinstance(x, HTTPError) and x.status_code == 404
#         with SuppressExceptionIf(is_404):
#             client.request(...)
#     """
# 
#     def __init__(self, cond):
#         self.cond = cond
# 
#     def __enter__(self):
#         pass
# 
#     def __exit__(self, exc_type, exc_value, traceback):
#         if exc_value is None:
#             return
#         if callable(self.cond):
#             # If the callable returns True, exception
#             # will be suppressed
#             return self.cond(exc_value)
#         return self.cond


import json
import urlparse
import requests
from .exceptions import HTTPError, BadApiError
from .utils import SuppressExceptionIf
        :return: a requests response object
        """

        headers = kwargs.get('headers') or {}
        kwargs['headers'] = headers

        # Update headers for authorization
        if self.api_key is not None:
            headers['Authorization'] = self.api_key

        # Serialize data to json, if not already
        if 'data' in kwargs:
            if not isinstance(kwargs['data'], basestring):
                kwargs['data'] = json.dumps(kwargs['data'])
                headers['content-type'] = 'application/json'

        if isinstance(path, (list, tuple)):
            path = '/'.join(path)

        url = urlparse.urljoin(self.base_url, path)
        response = requests.request(method, url, **kwargs)
        if not response.ok:
            # ------------------------------------------------------------
            # todo: attach message, if any available..
            # ------------------------------------------------------------
            # todo: we should find a way to figure out how to attach
            #       original text message to the exception
            #       as it might be: json string, part of json object,
            #       part of html document
            # ------------------------------------------------------------

# Path: ckan_api_client/exceptions.py
# class HTTPError(Exception):
#     """
#     Exception representing an HTTP response error.
# 
#     .. attribute:: status_code
# 
#         HTTP status code
# 
#     .. attribute:: message
# 
#         Informative error message, if available
#     """
# 
#     def __init__(self, status_code, message, original=None):
#         self.args = (status_code, message, original)
# 
#     @property
#     def status_code(self):
#         return self.args[0]
# 
#     @property
#     def message(self):
#         return self.args[1]
# 
#     @property
#     def original(self):
#         return self.args[2]
# 
#     def __str__(self):
#         return ("{0}({1!r}, {2!r}, original={3!r})"
#                 .format(self.__class__.__name__,
#                         self.status_code, self.message, self.original))
# 
# class BadApiError(Exception):
#     """Exception used to mark bad behavior from the API"""
#     pass
# 
# Path: ckan_api_client/utils.py
# class SuppressExceptionIf(object):
#     """
#     Context manager used to suppress exceptions if they match
#     a given condition.
# 
#     Usage example::
# 
#         is_404 = lambda x: isinstance(x, HTTPError) and x.status_code == 404
#         with SuppressExceptionIf(is_404):
#             client.request(...)
#     """
# 
#     def __init__(self, cond):
#         self.cond = cond
# 
#     def __enter__(self):
#         pass
# 
#     def __exit__(self, exc_type, exc_value, traceback):
#         if exc_value is None:
#             return
#         if callable(self.cond):
#             # If the callable returns True, exception
#             # will be suppressed
#             return self.cond(exc_value)
#         return self.cond


# Path: ckan_api_client/low_level.py
import json
import urlparse
import requests
from .exceptions import HTTPError, BadApiError
from .utils import SuppressExceptionIf

        :return: a requests response object
        """

        headers = kwargs.get('headers') or {}
        kwargs['headers'] = headers

        # Update headers for authorization
        if self.api_key is not None:
            headers['Authorization'] = self.api_key

        # Serialize data to json, if not already
        if 'data' in kwargs:
            if not isinstance(kwargs['data'], basestring):
                kwargs['data'] = json.dumps(kwargs['data'])
                headers['content-type'] = 'application/json'

        if isinstance(path, (list, tuple)):
            path = '/'.join(path)

        url = urlparse.urljoin(self.base_url, path)
        response = requests.request(method, url, **kwargs)
        if not response.ok:
            # ------------------------------------------------------------
            # todo: attach message, if any available..
            # ------------------------------------------------------------
            # todo: we should find a way to figure out how to attach
            #       original text message to the exception
            #       as it might be: json string, part of json object,
            #       part of html document
            # ------------------------------------------------------------

            raise HTTPError(