diff --git a/djangorestframework/authentication.py b/djangorestframework/authentication.py index 1c5c832f3..7d6e21145 100644 --- a/djangorestframework/authentication.py +++ b/djangorestframework/authentication.py @@ -4,7 +4,7 @@ The :mod:`authentication` module provides a set of pluggable authentication clas Authentication behavior is provided by mixing the :class:`mixins.AuthMixin` class into a :class:`View` class. The set of authentication methods which are used is then specified by setting the -:attr:`authentication` attribute on the :class:`View` class, and listing a set of authentication classes. +:attr:`authentication` attribute on the :class:`View` class, and listing a set of :class:`authentication` classes. """ from django.contrib.auth import authenticate @@ -26,20 +26,20 @@ class BaseAuthenticaton(object): def __init__(self, view): """ - :param view: :class:`Authentication` classes are always passed the current view on creation. + :class:`Authentication` classes are always passed the current view on creation. """ self.view = view def authenticate(self, request): """ - :param request: Request to be authenticated - :rtype: :obj:`User` or None [*]_ + Authenticate the :obj:`request` and return a :obj:`User` or :const:`None`. [*]_ .. [*] The authentication context *will* typically be a :obj:`User`, but it need not be. It can be any user-like object so long as the - permissions classes on the view can handle the object and use - it to determine if the request has the required permissions or not. - + permissions classes (see the :mod:`permissions` module) on the view can + handle the object and use it to determine if the request has the required + permissions or not. + This can be an important distinction if you're implementing some token based authentication mechanism, where the authentication context may be more involved than simply mapping to a :obj:`User`. @@ -55,7 +55,7 @@ class BasicAuthenticaton(BaseAuthenticaton): def authenticate(self, request): """ Returns a :obj:`User` if a correct username and password have been supplied - using HTTP Basic authentication. Otherwise returns `None`. + using HTTP Basic authentication. Otherwise returns :const:`None`. """ from django.utils.encoding import smart_unicode, DjangoUnicodeDecodeError @@ -85,7 +85,8 @@ class UserLoggedInAuthenticaton(BaseAuthenticaton): def authenticate(self, request): """ - Returns a :obj:`User` if the request session currently has a logged in user, otherwise `None`. + Returns a :obj:`User` if the request session currently has a logged in user. + Otherwise returns :const:`None`. """ # TODO: Switch this back to request.POST, and let FormParser/MultiPartParser deal with the consequences. if getattr(request, 'user', None) and request.user.is_active: diff --git a/djangorestframework/compat.py b/djangorestframework/compat.py index 98fbbb62c..45a695c8c 100644 --- a/djangorestframework/compat.py +++ b/djangorestframework/compat.py @@ -1,4 +1,6 @@ -"""Compatability module to provide support for backwards compatability with older versions of django/python""" +""" +Compatability module to provide support for backwards compatability with older versions of django/python +""" # cStringIO only if it's available try: @@ -27,24 +29,25 @@ except ImportError: # Lovely stuff class RequestFactory(Client): """ - Class that lets you create mock Request objects for use in testing. + Class that lets you create mock :obj:`Request` objects for use in testing. - Usage: + Usage:: - rf = RequestFactory() - get_request = rf.get('/hello/') - post_request = rf.post('/submit/', {'foo': 'bar'}) + rf = RequestFactory() + get_request = rf.get('/hello/') + post_request = rf.post('/submit/', {'foo': 'bar'}) - This class re-uses the django.test.client.Client interface, docs here: - http://www.djangoproject.com/documentation/testing/#the-test-client + This class re-uses the :class:`django.test.client.Client` interface. Of which + you can find the docs here__. - Once you have a request object you can pass it to any view function, - just as if that view had been hooked up using a URLconf. + __ http://www.djangoproject.com/documentation/testing/#the-test-client + Once you have a :obj:`request` object you can pass it to any :func:`view` function, + just as if that :func:`view` had been hooked up using a URLconf. """ def request(self, **request): """ - Similar to parent class, but returns the request object as soon as it + Similar to parent class, but returns the :obj:`request` object as soon as it has created it. """ environ = { @@ -148,9 +151,11 @@ try: import re class CustomSetextHeaderProcessor(markdown.blockprocessors.BlockProcessor): - """Override markdown's SetextHeaderProcessor, so that ==== headers are

and ---- headers are

. + """ + Override `markdown`'s :class:`SetextHeaderProcessor`, so that ==== headers are

and ---- headers are

. - We use

for the resource name.""" + We use

for the resource name. + """ # Detect Setext-style header. Must be first 2 lines of block. RE = re.compile(r'^.*?\n[=-]{3,}', re.MULTILINE) @@ -172,8 +177,11 @@ try: blocks.insert(0, '\n'.join(lines[2:])) def apply_markdown(text): - """Simple wrapper around markdown.markdown to apply our CustomSetextHeaderProcessor, - and also set the base level of '#' style headers to

.""" + """ + Simple wrapper around :func:`markdown.markdown` to apply our :class:`CustomSetextHeaderProcessor`, + and also set the base level of '#' style headers to

. + """ + extensions = ['headerid(level=2)'] safe_mode = False, output_format = markdown.DEFAULT_OUTPUT_FORMAT diff --git a/djangorestframework/mixins.py b/djangorestframework/mixins.py index 3b2f72424..73ffbec26 100644 --- a/djangorestframework/mixins.py +++ b/djangorestframework/mixins.py @@ -1,5 +1,6 @@ """ -The mixins module provides a set of reusable mixin classes that can be added to a ``View``. +The :mod:`mixins` module provides a set of reusable `mixin` +classes that can be added to a `View`. """ from django.contrib.auth.models import AnonymousUser @@ -41,7 +42,7 @@ __all__ = ( class RequestMixin(object): """ - Mixin class to provide request parsing behavior. + `Mixin` class to provide request parsing behavior. """ _USE_FORM_OVERLOADING = True @@ -52,7 +53,7 @@ class RequestMixin(object): """ The set of request parsers that the view can handle. - Should be a tuple/list of classes as described in the ``parsers`` module. + Should be a tuple/list of classes as described in the :mod:`parsers` module. """ parsers = () @@ -61,8 +62,8 @@ class RequestMixin(object): """ Returns the HTTP method. - This should be used instead of ``request.method``, as it allows the method - to be overridden by using a hidden form field on a form POST request. + This should be used instead of just reading :const:`request.method`, as it allows the `method` + to be overridden by using a hidden `form` field on a form POST request. """ if not hasattr(self, '_method'): self._load_method_and_content_type() @@ -100,7 +101,7 @@ class RequestMixin(object): def FILES(self): """ Parses the request body and returns the files. - Similar to request.FILES, except that it handles arbitrary parsers, + Similar to ``request.FILES``, except that it handles arbitrary parsers, and also works on methods other than POST (eg PUT). """ if not hasattr(self, '_files'): @@ -215,10 +216,10 @@ class RequestMixin(object): class ResponseMixin(object): """ - Adds behavior for pluggable Renderers to a :class:`.BaseView` or Django :class:`View`. class. + Adds behavior for pluggable `Renderers` to a :class:`views.BaseView` or Django :class:`View` class. Default behavior is to use standard HTTP Accept header content negotiation. - Also supports overriding the content type by specifying an _accept= parameter in the URL. + Also supports overriding 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. """ @@ -228,7 +229,7 @@ class ResponseMixin(object): """ The set of response renderers that the view can handle. - Should be a tuple/list of classes as described in the ``renderers`` module. + Should be a tuple/list of classes as described in the :mod:`renderers` module. """ renderers = () @@ -237,7 +238,7 @@ class ResponseMixin(object): # out of the box with existing Django classes that use render_to_response. def render(self, response): """ - Takes a ``Response`` object and returns an ``HttpResponse``. + Takes a :obj:`Response` object and returns an :obj:`HttpResponse`. """ self.response = response @@ -354,20 +355,20 @@ class ResponseMixin(object): class AuthMixin(object): """ - Simple mixin class to add authentication and permission checking to a ``View`` class. + Simple :class:`mixin` class to add authentication and permission checking to a :class:`View` class. """ """ The set of authentication types that this view can handle. - - Should be a tuple/list of classes as described in the ``authentication`` module. + + Should be a tuple/list of classes as described in the :mod:`authentication` module. """ authentication = () """ The set of permissions that will be enforced on this view. - Should be a tuple/list of classes as described in the ``permissions`` module. + Should be a tuple/list of classes as described in the :mod:`permissions` module. """ permissions = () @@ -375,8 +376,8 @@ class AuthMixin(object): @property def user(self): """ - Returns the user for the current request, as determined by the set of - authentication classes applied to the ``View``. + Returns the :obj:`user` for the current request, as determined by the set of + :class:`authentication` classes applied to the :class:`View`. """ if not hasattr(self, '_user'): self._user = self._authenticate() @@ -412,12 +413,10 @@ class AuthMixin(object): class ResourceMixin(object): """ Provides request validation and response filtering behavior. - """ - """ - Should be a class as described in the ``resources`` module. + Should be a class as described in the :mod:`resources` module. - The ``resource`` is an object that maps a view onto it's representation on the server. + The :obj:`resource` is an object that maps a view onto it's representation on the server. It provides validation on the content of incoming requests, and filters the object representation into a serializable object for the response. @@ -435,8 +434,8 @@ class ResourceMixin(object): def validate_request(self, data, files): """ - Given the request data return the cleaned, validated content. - Typically raises a ErrorResponse with status code 400 (Bad Request) on failure. + Given the request *data* return the cleaned, validated content. + Typically raises an :class:`response.ErrorResponse` with status code 400 (Bad Request) on failure. """ resource = self.resource(self) return resource.validate_request(data, files) @@ -458,8 +457,8 @@ class ResourceMixin(object): class InstanceMixin(object): """ - Mixin class that is used to identify a view class as being the canonical identifier - for the resources it is mapped too. + `Mixin` class that is used to identify a `View` class as being the canonical identifier + for the resources it is mapped to. """ @classmethod @@ -481,7 +480,7 @@ class InstanceMixin(object): class ReadModelMixin(object): """ - Behavior to read a model instance on GET requests + Behavior to read a `model` instance on GET requests """ def get(self, request, *args, **kwargs): model = self.resource.model @@ -500,7 +499,7 @@ class ReadModelMixin(object): class CreateModelMixin(object): """ - Behavior to create a model instance on POST requests + Behavior to create a `model` instance on POST requests """ def post(self, request, *args, **kwargs): model = self.resource.model @@ -524,7 +523,7 @@ class CreateModelMixin(object): class UpdateModelMixin(object): """ - Behavior to update a model instance on PUT requests + Behavior to update a `model` instance on PUT requests """ def put(self, request, *args, **kwargs): model = self.resource.model @@ -549,7 +548,7 @@ class UpdateModelMixin(object): class DeleteModelMixin(object): """ - Behavior to delete a model instance on DELETE requests + Behavior to delete a `model` instance on DELETE requests """ def delete(self, request, *args, **kwargs): model = self.resource.model @@ -569,7 +568,7 @@ class DeleteModelMixin(object): class ListModelMixin(object): """ - Behavior to list a set of model instances on GET requests + Behavior to list a set of `model` instances on GET requests """ # NB. Not obvious to me if it would be better to set this on the resource? diff --git a/djangorestframework/parsers.py b/djangorestframework/parsers.py index 2fd1e15df..7c76bcc69 100644 --- a/djangorestframework/parsers.py +++ b/djangorestframework/parsers.py @@ -5,8 +5,9 @@ to general HTTP requests. We need a method to be able to: -1) Determine the parsed content on a request for methods other than POST (eg typically also PUT) -2) Determine the parsed content on a request for media types other than application/x-www-form-urlencoded +1.) Determine the parsed content on a request for methods other than POST (eg typically also PUT) + +2.) Determine the parsed content on a request for media types other than application/x-www-form-urlencoded and multipart/form-data. (eg also handle multipart/json) """ @@ -23,40 +24,41 @@ __all__ = ( 'JSONParser', 'PlainTextParser', 'FormParser', - 'MultiPartParser' + 'MultiPartParser', ) class BaseParser(object): """ - All parsers should extend BaseParser, specifying a media_type attribute, - and overriding the parse() method. + All parsers should extend :class:`BaseParser`, specifying a :attr:`media_type` attribute, + and overriding the :meth:`parse` method. """ + media_type = None def __init__(self, view): """ Initialize the parser with the ``View`` instance as state, - in case the parser needs to access any metadata on the ``View`` object. + in case the parser needs to access any metadata on the :obj:`View` object. """ self.view = view def can_handle_request(self, content_type): """ - Returns `True` if this parser is able to deal with the given media type. + Returns :const:`True` if this parser is able to deal with the given *content_type*. - The default implementation for this function is to check the ``media_type`` - argument against the ``media_type`` attribute set on the class to see if + The default implementation for this function is to check the *content_type* + argument against the :attr:`media_type` attribute set on the class to see if they match. This may be overridden to provide for other behavior, but typically you'll - instead want to just set the ``media_type`` attribute on the class. + instead want to just set the :attr:`media_type` attribute on the class. """ return media_type_matches(content_type, self.media_type) def parse(self, stream): """ - Given a stream to read from, return the deserialized output. + Given a *stream* to read from, return the deserialized output. Should return a 2-tuple of (data, files). """ raise NotImplementedError("BaseParser.parse() Must be overridden to be implemented.") @@ -64,8 +66,9 @@ class BaseParser(object): class JSONParser(BaseParser): """ - JSON parser. + Parses JSON-serialized data. """ + media_type = 'application/json' def parse(self, stream): @@ -82,10 +85,12 @@ class JSONParser(BaseParser): {'detail': 'JSON parse error - %s' % unicode(exc)}) + class PlainTextParser(BaseParser): """ Plain text parser. """ + media_type = 'text/plain' def parse(self, stream): @@ -109,8 +114,8 @@ class FormParser(BaseParser): """ Returns a 2-tuple of `(data, files)`. - `data` will be a `QueryDict` containing all the form parameters. - `files` will always be `None`. + `data` will be a :class:`QueryDict` containing all the form parameters. + `files` will always be :const:`None`. """ data = parse_qs(stream.read(), keep_blank_values=True) return (data, None) @@ -127,8 +132,8 @@ class MultiPartParser(BaseParser): """ Returns a 2-tuple of `(data, files)`. - `data` will be a `QueryDict` containing all the form parameters. - `files` will be a `QueryDict` containing all the form files. + `data` will be a :class:`QueryDict` containing all the form parameters. + `files` will be a :class:`QueryDict` containing all the form files. """ upload_handlers = self.view.request._get_upload_handlers() django_parser = DjangoMultiPartParser(self.view.request.META, stream, upload_handlers) diff --git a/djangorestframework/permissions.py b/djangorestframework/permissions.py index ae550f252..3831424f7 100644 --- a/djangorestframework/permissions.py +++ b/djangorestframework/permissions.py @@ -36,7 +36,7 @@ class BasePermission(object): def check_permission(self, auth): """ - Should simply return, or raise an ErrorResponse. + Should simply return, or raise an :class:`response.ErrorResponse`. """ pass @@ -60,7 +60,7 @@ class IsAuthenticated(BasePermission): raise _403_FORBIDDEN_RESPONSE -class IsAdminUser(): +class IsAdminUser(BasePermission): """ Allows access only to admin users. """ @@ -86,7 +86,7 @@ class PerUserThrottling(BasePermission): """ Rate throttling of requests on a per-user basis. - The rate is set by a 'throttle' attribute on the ``View`` class. + The rate (requests / seconds) is set by a :attr:`throttle` attribute on the ``View`` class. The attribute is a two tuple of the form (number of requests, duration in seconds). The user id will be used as a unique identifier if the user is authenticated. diff --git a/djangorestframework/renderers.py b/djangorestframework/renderers.py index 112736d2f..3e59511c3 100644 --- a/djangorestframework/renderers.py +++ b/djangorestframework/renderers.py @@ -36,8 +36,8 @@ __all__ = ( class BaseRenderer(object): """ - All renderers must extend this class, set the media_type attribute, - and override the render() function. + All renderers must extend this class, set the :attr:`media_type` attribute, + and override the :meth:`render` method. """ media_type = None @@ -51,7 +51,7 @@ class BaseRenderer(object): The requested media type is also passed to this method, as it may contain parameters relevant to how the parser should render the output. - EG: 'application/json; indent=4' + EG: ``application/json; indent=4`` By default render simply returns the output as-is. Override this method to provide for other behavior. @@ -102,8 +102,8 @@ class TemplateRenderer(BaseRenderer): A Base class provided for convenience. Render the object simply by using the given template. - To create a template renderer, subclass this, and set - the ``media_type`` and ``template`` attributes + To create a template renderer, subclass this class, and set + the :attr:`media_type` and `:attr:template` attributes. """ media_type = None template = None