text: # AUTOGENERATED! DO NOT EDIT! File to edit: 03_api.ipynb (unless otherwise specified).
  
  __all__ = ['log_request', 'API', 'logger', 'default_headers']
  
  # Cell
  from types import SimpleNamespace
  import functools
  
  import requests
  
  # TODO: Break this out into import
  logger = SimpleNamespace(debug=print)
  
  default_headers = {
      "Content-Type": "application/json",
      "Accept": "*/*",
      "Accept-Language": "en-US,en;q=0.5",
      "Accept-Encoding": "gzip,deflate",
  }
  
  
  # TODO: Wrap this one layer deeper and allow for
  # passing in a custom logging function as a parameterized
  # decorator.
  
  
  def log_request(func):
      @functools.wraps(func)
      def wrapper(*args, **kwargs):
          response = func(*args, **kwargs)
          # TODO: Add error handling and input validation for this
          request_method = response.request.method
          request_url = response.url
          request_headers = response.request.headers
          if logger:
              logger.debug(
                  f"{request_method} sent to: {request_url}\n"
                  f"with headers: {request_headers}\n"
                  f"Response Status: {response.status_code}"
              )
          return response
  
      return wrapper
  
  
  class API(object):
      def __init__(self, api_url, headers=None):
          self.api_url = api_url
          headers = headers or default_headers
          self.headers = headers.copy()
          self.is_authenticated = False
          self.jar = requests.cookies.RequestsCookieJar()
  
          self.delete = log_request(self._delete)
          self.get = log_request(self._get)
          self.post = log_request(self._post)
          self.put = log_request(self._put)
  
      def get_path(self, url):
          api_url = self.api_url if not self.api_url.endswith("/") else self.api_url[:-1]
          template = "{}{}" if url.startswith("/") else "{}/{}"
          return template.format(api_url, url)
  
      def _post(
          self,
          url,
          json=None,
          params=None,
          files=None,
          data=None,
          cookies=None,
          verify=False,
          non_default_headers=None,
      ):
          if not cookies:
              cookies = self.jar
          path = self.get_path(url)
  
          if non_default_headers:
              headers = non_default_headers
          else:
              headers = self.headers
  
          response = requests.post(
              path,
              json=json,
              params=params,
              headers=headers,
              files=files,
              data=data,
              cookies=cookies,
              verify=verify,
          )
  
          return response
  
      def _put(self, url, json=None, params=None):
          path = self.get_path(url)
          logger.debug(
              "PUT request sent to: {} \n\theaders: {}\n\tjson: {}\n\tparams: {}".format(
                  path, self.headers, json, params
              )
          )
          response = requests.put(path, json=json, params=params, headers=self.headers)
          return response
  
      def _get(
          self,
          url,
          json=None,
          params=None,
          files=None,
          data=None,
          cookies=None,
          verify=False,
      ):
          if not cookies:
              cookies = self.jar
          path = self.get_path(url)
          response = requests.get(
              path,
              params=params,
              headers=self.headers,
              json=json,
              files=files,
              data=data,
              cookies=cookies,
              verify=verify,
          )
          return response
  
      def _delete(self, url, json=None, params=None):
          path = self.get_path(url)
          response = requests.delete(path, params=params, headers=self.headers, json=json)
          return response