# Path: jsonapi/exceptions.py
# class JSONAPIError(Exception):
# 
#     """ Exception class for JSONAPI.
# 
#     .. versionadded:: 0.6.9
#     .. versionchanged:: 0.8.4
#       Use JSON-API Specification http://jsonapi.org/format/#errors
# 
#     Error codes are from 0 to 32767.
#     Error codes 32000 - 32767 are reserved fro jsonapi usage.
#     It is recommended for user to use codes from 0 to 32000, in this case codes
#     could be stored within django.PositiveSmallIntegerField field
# 
#     """
# 
#     ATTRIBUTES = [
#         "id",
#         "href",
#         "status",
#         "code",
#         "title",
#         "detail",
#         "links",
#         "paths",
#         "data",
#     ]
# 
#     REQUIRED_ATTRIBUTES = ["code", "title"]
#     CODE = 32000
#     STATUS = statuses.HTTP_400_BAD_REQUEST
#     TITLE = "General JSONAPI Error"
# 
#     def __init__(self, **kwargs):
#         kwargs["code"] = self.CODE
#         kwargs["title"] = self.TITLE
#         kwargs["status"] = self.STATUS
#         kwargs["detail"] = kwargs.get("detail", "")
# 
#         for required_attribut in self.REQUIRED_ATTRIBUTES:
#             if required_attribut not in kwargs:
#                 raise ValueError("{} should have {} attribute".format(
#                     self.__class__.__name__, required_attribut
#                 ))
# 
#         for kwarg_key, kwarg_value in kwargs.items():
#             if kwarg_key not in self.ATTRIBUTES:
#                 raise ValueError(
#                     "Attribute {} is not allowed".format(kwarg_key))
# 
#         self.data = kwargs
# 
#     def __str__(self):
#         return json.dumps(self.data)
# 
#     def __getattr__(self, key):
#         if key == "data":
#             return self.data
#         else:
#             return self.data[key]
# 
# Path: jsonapi/serializers.py
# class DatetimeDecimalEncoder(json.JSONEncoder):
# 
#     """ Encoder for datetime and decimal serialization.
# 
#     Usage: json.dumps(object, cls=DatetimeDecimalEncoder)
#     NOTE: _iterencode does not work
# 
#     """
# 
#     def default(self, o):
#         """ Encode JSON.
# 
#         :return str: A JSON encoded string
# 
#         """
#         if isinstance(o, (datetime.datetime, datetime.date, datetime.time)):
#             return o.isoformat()
# 
#         if isinstance(o, decimal.Decimal):
#             return float(o)
# 
#         return json.JSONEncoder.default(self, o)
# 
# Path: jsonapi/signals.py



import json
import logging
import time
from django.http import HttpResponse, HttpResponseNotAllowed
from django.shortcuts import render
from .exceptions import JSONAPIError
from .serializers import DatetimeDecimalEncoder
from .signals import signal_request, signal_response
        from django.conf.urls import url
            json.dumps(data, cls=DatetimeDecimalEncoder),
            content_type=self.CONTENT_TYPE, status=200)
        return response

    def handler_view_delete(self, resource, **kwargs):
        if 'ids' not in kwargs:
            return HttpResponse("Request SHOULD have resource ids", status=400)

        response = resource.delete(**kwargs)
        return HttpResponse(
            response, content_type=self.CONTENT_TYPE, status=204)

    def handler_view(self, request, resource_name, ids=None):
        """ Handler for resources.

        .. versionadded:: 0.5.7
            Content-Type check

        :return django.http.HttpResponse

        """
        signal_request.send(sender=self, request=request)
        time_start = time.time()
        self.update_urls(request, resource_name=resource_name, ids=ids)
        resource = self.resource_map[resource_name]

        allowed_http_methods = resource.Meta.allowed_methods
        if request.method not in allowed_http_methods:
            response = HttpResponseNotAllowed(
                permitted_methods=allowed_http_methods)

# Path: jsonapi/exceptions.py
# class JSONAPIError(Exception):
# 
#     """ Exception class for JSONAPI.
# 
#     .. versionadded:: 0.6.9
#     .. versionchanged:: 0.8.4
#       Use JSON-API Specification http://jsonapi.org/format/#errors
# 
#     Error codes are from 0 to 32767.
#     Error codes 32000 - 32767 are reserved fro jsonapi usage.
#     It is recommended for user to use codes from 0 to 32000, in this case codes
#     could be stored within django.PositiveSmallIntegerField field
# 
#     """
# 
#     ATTRIBUTES = [
#         "id",
#         "href",
#         "status",
#         "code",
#         "title",
#         "detail",
#         "links",
#         "paths",
#         "data",
#     ]
# 
#     REQUIRED_ATTRIBUTES = ["code", "title"]
#     CODE = 32000
#     STATUS = statuses.HTTP_400_BAD_REQUEST
#     TITLE = "General JSONAPI Error"
# 
#     def __init__(self, **kwargs):
#         kwargs["code"] = self.CODE
#         kwargs["title"] = self.TITLE
#         kwargs["status"] = self.STATUS
#         kwargs["detail"] = kwargs.get("detail", "")
# 
#         for required_attribut in self.REQUIRED_ATTRIBUTES:
#             if required_attribut not in kwargs:
#                 raise ValueError("{} should have {} attribute".format(
#                     self.__class__.__name__, required_attribut
#                 ))
# 
#         for kwarg_key, kwarg_value in kwargs.items():
#             if kwarg_key not in self.ATTRIBUTES:
#                 raise ValueError(
#                     "Attribute {} is not allowed".format(kwarg_key))
# 
#         self.data = kwargs
# 
#     def __str__(self):
#         return json.dumps(self.data)
# 
#     def __getattr__(self, key):
#         if key == "data":
#             return self.data
#         else:
#             return self.data[key]
# 
# Path: jsonapi/serializers.py
# class DatetimeDecimalEncoder(json.JSONEncoder):
# 
#     """ Encoder for datetime and decimal serialization.
# 
#     Usage: json.dumps(object, cls=DatetimeDecimalEncoder)
#     NOTE: _iterencode does not work
# 
#     """
# 
#     def default(self, o):
#         """ Encode JSON.
# 
#         :return str: A JSON encoded string
# 
#         """
#         if isinstance(o, (datetime.datetime, datetime.date, datetime.time)):
#             return o.isoformat()
# 
#         if isinstance(o, decimal.Decimal):
#             return float(o)
# 
#         return json.JSONEncoder.default(self, o)
# 
# Path: jsonapi/signals.py



# Path: jsonapi/api.py
import json
import logging
import time
from django.http import HttpResponse, HttpResponseNotAllowed
from django.shortcuts import render
from .exceptions import JSONAPIError
from .serializers import DatetimeDecimalEncoder
from .signals import signal_request, signal_response
        from django.conf.urls import url

            json.dumps(data, cls=DatetimeDecimalEncoder),
            content_type=self.CONTENT_TYPE, status=200)
        return response

    def handler_view_delete(self, resource, **kwargs):
        if 'ids' not in kwargs:
            return HttpResponse("Request SHOULD have resource ids", status=400)

        response = resource.delete(**kwargs)
        return HttpResponse(
            response, content_type=self.CONTENT_TYPE, status=204)

    def handler_view(self, request, resource_name, ids=None):
        """ Handler for resources.

        .. versionadded:: 0.5.7
            Content-Type check

        :return django.http.HttpResponse

        """
        signal_request.send(sender=self, request=request)
        time_start = time.time()
        self.update_urls(request, resource_name=resource_name, ids=ids)
        resource = self.resource_map[resource_name]

        allowed_http_methods = resource.Meta.allowed_methods
        if request.method not in allowed_http_methods:
            response = HttpResponseNotAllowed(
                permitted_methods=allowed_http_methods)

            signal_response.send(