diff --git a/djangorestframework/emitters.py b/djangorestframework/emitters.py index 0adddca95..2702758bc 100644 --- a/djangorestframework/emitters.py +++ b/djangorestframework/emitters.py @@ -7,151 +7,11 @@ from django import forms from django.conf import settings from django.template import RequestContext, loader from django.utils import simplejson as json -<<<<<<< local from django import forms -======= ->>>>>>> other -from djangorestframework.response import ErrorResponse -from djangorestframework.utils import dict2xml, url_resolves -from djangorestframework.markdownwrapper import apply_markdown -from djangorestframework.breadcrumbs import get_breadcrumbs -from djangorestframework.description import get_name, get_description -from djangorestframework import status - -from urllib import quote_plus -import string -import re -<<<<<<< local -======= from decimal import Decimal -_MSIE_USER_AGENT = re.compile(r'^Mozilla/[0-9]+\.[0-9]+ \([^)]*; MSIE [0-9]+\.[0-9]+[a-z]?;[^)]*\)(?!.* Opera )') - - -class EmitterMixin(object): - """Adds behaviour for pluggable Emitters to a :class:`.Resource` or Django :class:`View`. class. - - Default behaviour is to use standard HTTP Accept header content negotiation. - Also supports overidding the content type by specifying an _accept= parameter in the URL. - Ignores Accept headers from Internet Explorer user agents and uses a sensible browser Accept header instead.""" - - ACCEPT_QUERY_PARAM = '_accept' # Allow override of Accept header in URL query params - REWRITE_IE_ACCEPT_HEADER = True - - request = None - response = None - emitters = () - - def emit(self, response): - """Takes a :class:`Response` object and returns a Django :class:`HttpResponse`.""" - self.response = response - - try: - emitter = self._determine_emitter(self.request) - except ResponseException, exc: - emitter = self.default_emitter - response = exc.response - - # Serialize the response content - if response.has_content_body: - content = emitter(self).emit(output=response.cleaned_content) - else: - content = emitter(self).emit() - - # Munge DELETE Response code to allow us to return content - # (Do this *after* we've rendered the template so that we include the normal deletion response code in the output) - if response.status == 204: - response.status = 200 - - # Build the HTTP Response - # TODO: Check if emitter.mimetype is underspecified, or if a content-type header has been set - resp = HttpResponse(content, mimetype=emitter.media_type, status=response.status) - for (key, val) in response.headers.items(): - resp[key] = val - - return resp - - - def _determine_emitter(self, request): - """Return the appropriate emitter for the output, given the client's 'Accept' header, - and the content types that this Resource knows how to serve. - - See: RFC 2616, Section 14 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html""" - - if self.ACCEPT_QUERY_PARAM and request.GET.get(self.ACCEPT_QUERY_PARAM, None): - # Use _accept parameter override - accept_list = [request.GET.get(self.ACCEPT_QUERY_PARAM)] - elif self.REWRITE_IE_ACCEPT_HEADER and request.META.has_key('HTTP_USER_AGENT') and _MSIE_USER_AGENT.match(request.META['HTTP_USER_AGENT']): - accept_list = ['text/html', '*/*'] - elif request.META.has_key('HTTP_ACCEPT'): - # Use standard HTTP Accept negotiation - accept_list = request.META["HTTP_ACCEPT"].split(',') - else: - # No accept header specified - return self.default_emitter - - # Parse the accept header into a dict of {qvalue: set of media types} - # We ignore mietype parameters - accept_dict = {} - for token in accept_list: - components = token.split(';') - mimetype = components[0].strip() - qvalue = Decimal('1.0') - - if len(components) > 1: - # Parse items that have a qvalue eg text/html;q=0.9 - try: - (q, num) = components[-1].split('=') - if q == 'q': - qvalue = Decimal(num) - except: - # Skip malformed entries - continue - - if accept_dict.has_key(qvalue): - accept_dict[qvalue].add(mimetype) - else: - accept_dict[qvalue] = set((mimetype,)) - - # Convert to a list of sets ordered by qvalue (highest first) - accept_sets = [accept_dict[qvalue] for qvalue in sorted(accept_dict.keys(), reverse=True)] - - for accept_set in accept_sets: - # Return any exact match - for emitter in self.emitters: - if emitter.media_type in accept_set: - return emitter - - # Return any subtype match - for emitter in self.emitters: - if emitter.media_type.split('/')[0] + '/*' in accept_set: - return emitter - - # Return default - if '*/*' in accept_set: - return self.default_emitter - - - raise ResponseException(status.HTTP_406_NOT_ACCEPTABLE, - {'detail': 'Could not statisfy the client\'s Accept header', - 'available_types': self.emitted_media_types}) - - @property - def emitted_media_types(self): - """Return an list of all the media types that this resource can emit.""" - return [emitter.media_type for emitter in self.emitters] - - @property - def default_emitter(self): - """Return the resource's most prefered emitter. - (This emitter is used if the client does not send and Accept: header, or sends Accept: */*)""" - return self.emitters[0] ->>>>>>> other - - - # TODO: Rename verbose to something more appropriate # TODO: Maybe None could be handled more cleanly. It'd be nice if it was handled by default, # and only have an emitter output anything if it explicitly provides support for that. diff --git a/djangorestframework/parsers.py b/djangorestframework/parsers.py index 03f8bf8f7..96b29a66b 100644 --- a/djangorestframework/parsers.py +++ b/djangorestframework/parsers.py @@ -11,60 +11,12 @@ We need a method to be able to: from django.http.multipartparser import MultiPartParser as DjangoMPParser from django.utils import simplejson as json -<<<<<<< local from djangorestframework.response import ErrorResponse -======= -from djangorestframework.response import ResponseException ->>>>>>> other from djangorestframework import status from djangorestframework.utils import as_tuple from djangorestframework.mediatypes import MediaType from djangorestframework.compat import parse_qs -<<<<<<< local -======= -try: - from urlparse import parse_qs -except ImportError: - from cgi import parse_qs - -class ParserMixin(object): - parsers = () - - def parse(self, stream, content_type): - """ - Parse the request content. - - May raise a 415 ResponseException (Unsupported Media Type), - or a 400 ResponseException (Bad Request). - """ - parsers = as_tuple(self.parsers) - - parser = None - for parser_cls in parsers: - if parser_cls.handles(content_type): - parser = parser_cls(self) - break - - if parser is None: - raise ResponseException(status.HTTP_415_UNSUPPORTED_MEDIA_TYPE, - {'error': 'Unsupported media type in request \'%s\'.' % - content_type.media_type}) - - return parser.parse(stream) - - @property - def parsed_media_types(self): - """Return an list of all the media types that this ParserMixin can parse.""" - return [parser.media_type for parser in self.parsers] - - @property - def default_parser(self): - """Return the ParerMixin's most prefered emitter. - (This has no behavioural effect, but is may be used by documenting emitters)""" - return self.parsers[0] ->>>>>>> other - class BaseParser(object): """All parsers should extend BaseParser, specifying a media_type attribute, diff --git a/djangorestframework/tests/authentication.py b/djangorestframework/tests/authentication.py index a43a87b37..248bd87a6 100644 --- a/djangorestframework/tests/authentication.py +++ b/djangorestframework/tests/authentication.py @@ -1,12 +1,8 @@ from django.conf.urls.defaults import patterns -<<<<<<< local -from django.test import TestCase -from django.test import Client from django.contrib.auth.models import User from django.contrib.auth import login -======= from django.test import Client, TestCase ->>>>>>> other + from django.utils import simplejson as json from djangorestframework.compat import RequestFactory diff --git a/djangorestframework/tests/reverse.py b/djangorestframework/tests/reverse.py index 63e2080a2..49939d0e9 100644 --- a/djangorestframework/tests/reverse.py +++ b/djangorestframework/tests/reverse.py @@ -5,10 +5,6 @@ from django.utils import simplejson as json from djangorestframework.resource import Resource -<<<<<<< local - -======= ->>>>>>> other class MockResource(Resource): """Mock resource which simply returns a URL, so that we can ensure that reversed URLs are fully qualified"""