import json
import logging
from urllib.parse import urlencode, urljoin
import requests


log = logging.getLogger("atlassian")


class AtlassianRestAPI:

    default_headers={'Content-Type': 'application/json', 'Accept': 'application/json'}

    def __init__(self, url, username, password, timeout=60, api_root='rest/api', api_version='latest'):
        self.url = url
        self.username = username
        self.password = password
        self.timeout = timeout
        self.api_root = api_root
        self.api_version = api_version
        self._session = requests.Session()
        if username and password:
            self._session.auth = (username, password)

    def log_curl_debug(self, method, path, data=None, headers={}, level=logging.DEBUG):
        message = "curl --silent -X {method} -u '{username}':'{password}' -H {headers} {data} '{url}'".format(
            method=method,
            username=self.username,
            password=self.password,
            headers=' -H '.join(["'{0}: {1}'".format(key, value) for key, value in headers.items()]),
            data='' if not data else "--data '{0}'".format(json.dumps(data)),
            url='{0}{1}'.format(self.url, path))
        log.log(level=level, msg=message)

    def resource_url(self, resource):
        return '/'.join([self.api_root, self.api_version, resource])

    def request(self, method='GET', path='/', data=None, flags=None, params=None,
                headers={'Content-Type': 'application/json', 'Accept': 'application/json'}):
        self.log_curl_debug(method=method, path=path, headers=headers, data=data)
        url = urljoin(self.url, path)
        if params or flags:
            url += '?'
        if params:
            url += urlencode(params or {})
        if flags:
            url += ('&' if params else '') + '&'.join(flags or [])

        response = requests.request(
        response = self._session.request(
            method=method,
            url=url,
            headers=headers,
            data=json.dumps(data),
            auth=(self.username, self.password),
            timeout=self.timeout
        )
        if response.status_code == 200:
            log.debug('Received: {0}'.format(response.json()))
        elif response.status_code == 204:
            log.debug('Received "204 No Content" response')
        else:
            self.log_curl_debug(method=method, path=path, headers=headers, data=data, level=logging.DEBUG)
            log.info(response.json())
            response.raise_for_status()
        return response

    def get(self, path, data=None, flags=None, params=None, headers={'Content-Type': 'application/json', 'Accept': 'application/json'}):
        return self.request('GET', path=path, flags=flags, params=params, data=data, headers=headers).json()

    def post(self, path, data=None, headers={'Content-Type': 'application/json', 'Accept': 'application/json'}):
        try:
            return self.request('POST', path=path, data=data, headers=headers).json()
        except ValueError:
            log.debug('Received response with no content')
            return None

    def put(self, path, data=None, headers={'Content-Type': 'application/json', 'Accept': 'application/json'}):
        try:
            return self.request('PUT', path=path, data=data, headers=headers).json()
        except ValueError:
            log.debug('Received response with no content')
            return None

    def delete(self, path, data=None, headers={'Content-Type': 'application/json', 'Accept': 'application/json'}):
        """
        Deletes resources at given paths.
        :rtype: dict
        :return: Empty dictionary to have consistent interface. Some of Atlassian rest resources don't return any content.
        """
        self.request('DELETE', path=path, data=data, headers=headers)
@@ -110,19 +110,16 @@
 ger(
-%22atlassian%22
+__name__
 )%0A%0A%0A
@@ -721,18 +721,20 @@
 headers=
-%7B%7D
+None
 , level=
@@ -749,16 +749,66 @@
 DEBUG):%0A
+        headers = headers or self.default_headers%0A
         
@@ -1474,99 +1474,21 @@
 one,
-%0A                headers=%7B'Content-Type': 'application/json', 'Accept': 'application/json'%7D
+ headers=None
 ):%0A 
@@ -1817,36 +1817,49 @@
     
-response = requests.request(
+headers = headers or self.default_headers
 %0A   
@@ -2602,74 +2602,12 @@
 ers=
-%7B'Content-Type': 'application/json', 'Accept': 'application/json'%7D
+None
 ):%0A 
@@ -2763,74 +2763,12 @@
 ers=
-%7B'Content-Type': 'application/json', 'Accept': 'application/json'%7D
+None
 ):%0A 
@@ -3023,74 +3023,12 @@
 ers=
-%7B'Content-Type': 'application/json', 'Accept': 'application/json'%7D
+None
 ):%0A 
@@ -3285,74 +3285,12 @@
 ers=
-%7B'Content-Type': 'application/json', 'Accept': 'application/json'%7D
+None
 ):%0A 

Remove mutable dict as header default value