"""This module defines all OS-Conductor API endpoints"""

from __future__ import unicode_literals
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from future import standard_library

standard_library.install_aliases()

from munch import Munch
from requests import Session
from urllib.parse import urlencode, urlunsplit, urlsplit, urljoin

from gobble.configuration import config
from gobble.logger import log


# One session for all API calls
session = Session()


def build_request_caller(verb, *path):
    """Return a function that calls an API endpoint"""

    def send_request(headers=None, json=None, **query):
        """Send a request to an API endpoint"""

        method = verb.lower()
        caller = getattr(session, method)
        endpoint = urljoin(config.OS_URL, '/'.join(path))
        parts = urlsplit(endpoint)

        parameters = tuple(query.items())
        safe_query = urlencode(parameters)
        updated_parts = parts._replace(query=safe_query)

        url = urlunsplit(updated_parts)

        log.debug('Request endpoint: %s', endpoint)
        log.debug('Request query: %s', safe_query)
        log.debug('Request payload: %s', json)
        log.debug('Request headers: %s', headers)

        return caller(url, json=json, headers=headers)

    return send_request

# I would like to expose the function with an ordinary class
# but it fails in python2. This is a quick dirty hack.
API = Munch()

API.authenticate_user = build_request_caller('GET', 'user', 'check')
API.authorize_user = build_request_caller('GET', 'user', 'authorize')
API.oauth_callback = build_request_caller('GET', 'oauth', 'callback')
API.update_user = build_request_caller('POST', 'user', 'update')
API.search_users = build_request_caller('GET', 'search', 'user')
API.search_packages = build_request_caller('GET', 'search', 'package')
API.request_upload = build_request_caller('POST', 'datastore/')

@@ -200,16 +200,42 @@
 _import%0A
+%60from builtins import str%0A
 from fut
@@ -262,17 +262,16 @@
 library%0A
-%0A
 standard
@@ -298,16 +298,75 @@
 ases()%0A%0A
+from collections import OrderedDict%0Afrom json import dumps%0A
 from mun
@@ -381,16 +381,47 @@
 t Munch%0A
+from requests import HTTPError%0A
 from req
@@ -466,16 +466,17 @@
  import 
+(
 urlencod
@@ -481,38 +481,284 @@
 ode,
- urlunsplit, urlsplit, urljoin
+%0A                          urljoin,%0A                          urlunsplit,%0A                          parse_qs,%0A                          urlsplit,%0A                          urlparse)%0Atry:%0A    from json import JSONDecodeError%0Aexcept ImportError:%0A    JSONDecodeError = ValueError
 %0A%0Afr
@@ -1713,16 +1713,17 @@
 equest%0A%0A
+%0A
 # I woul
@@ -1808,21 +1808,31 @@
 . Th
-is is a quick
+e Munch class is just a
  dir
@@ -2329,8 +2329,1411 @@
 tore/')%0A
+%0A%0Adef handle(response):%0A    %22%22%22Handle a response from the os-conductor API%0A%0A    If all is okay, return the json payload of the response%0A    as a dictionary. If the status code is in the range 400 to 599,%0A    raise an HTTPError. Log the response, whatever happens.%0A    %22%22%22%0A    try:%0A        response.raise_for_status()%0A    except HTTPError as error:%0A        log.error(error)%0A        log.error(to_json(response))%0A        raise error%0A    else:%0A        log.debug(response)%0A        log.debug(to_json(response))%0A        return response.json()%0A%0A%0Adef to_json(response, indent=4):%0A    %22%22%22Return a JSON representation of a response object%22%22%22%0A%0A    url_parts = urlparse(response.url)%0A    properties = OrderedDict()%0A%0A    properties%5B'ok'%5D = bool(response)%0A    properties%5B'status_code'%5D = response.status_code%0A    properties%5B'reason'%5D = response.reason%0A    properties%5B'encoding'%5D = response.encoding%0A    properties%5B'headers'%5D = %7Bk: str(v) for k, v in response.headers.items()%7D%0A    properties%5B'url'%5D = response.url%0A    properties%5B'scheme'%5D = str(url_parts.scheme)%0A    properties%5B'host'%5D = str(url_parts.netloc)%0A    properties%5B'path'%5D = str(url_parts.path)%0A    properties%5B'query'%5D = parse_qs(url_parts.query)%0A    properties%5B'json'%5D = None%0A%0A    try:%0A        properties%5B'json'%5D = response.json()%0A    except JSONDecodeError:%0A        properties%5B'json'%5D = None%0A%0A    return dumps(properties, ensure_ascii=False, indent=indent)%0A

Add a helper function that handles responses properly.