Commit f7b7778a by Tom Christie

pull in markos changes, minor tweaks to yaml stuff

parents c3babe75 f67c0651
......@@ -156,6 +156,7 @@ except ImportError:
def head(self, request, *args, **kwargs):
return self.get(request, *args, **kwargs)
# Markdown is optional
try:
import markdown
import re
......@@ -204,3 +205,9 @@ try:
except ImportError:
apply_markdown = None
# Yaml is optional
try:
import yaml
except ImportError:
yaml = None
......@@ -16,15 +16,18 @@ from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
from django.http.multipartparser import MultiPartParserError
from django.utils import simplejson as json
from djangorestframework import status
from djangorestframework.compat import yaml
from djangorestframework.response import ErrorResponse
from djangorestframework.utils.mediatypes import media_type_matches
__all__ = (
'BaseParser',
'JSONParser',
'PlainTextParser',
'FormParser',
'MultiPartParser',
'YAMLParser',
)
......@@ -85,6 +88,27 @@ class JSONParser(BaseParser):
{'detail': 'JSON parse error - %s' % unicode(exc)})
if yaml:
class YAMLParser(BaseParser):
"""
Parses YAML-serialized data.
"""
media_type = 'application/yaml'
def parse(self, stream):
"""
Returns a 2-tuple of `(data, files)`.
`data` will be an object which is the parsed content of the response.
`files` will always be `None`.
"""
try:
return (yaml.safe_load(stream), None)
except ValueError, exc:
raise ErrorResponse(status.HTTP_400_BAD_REQUEST,
{'detail': 'YAML parse error - %s' % unicode(exc)})
class PlainTextParser(BaseParser):
"""
......
......@@ -11,16 +11,14 @@ from django.core.serializers.json import DateTimeAwareJSONEncoder
from django.template import RequestContext, loader
from django.utils import simplejson as json
from djangorestframework import status
from djangorestframework.compat import apply_markdown
from djangorestframework.compat import apply_markdown, yaml
from djangorestframework.utils import dict2xml, url_resolves
from djangorestframework.utils.breadcrumbs import get_breadcrumbs
from djangorestframework.utils.description import get_name, get_description
from djangorestframework.utils.mediatypes import get_media_type_params, add_media_type_param, media_type_matches
from djangorestframework import VERSION
from decimal import Decimal
import re
import string
from urllib import quote_plus
......@@ -31,7 +29,8 @@ __all__ = (
'DocumentingHTMLRenderer',
'DocumentingXHTMLRenderer',
'DocumentingPlainTextRenderer',
'XMLRenderer'
'XMLRenderer',
'YAMLRenderer'
)
......@@ -131,6 +130,27 @@ class XMLRenderer(BaseRenderer):
return dict2xml(obj)
if yaml:
class YAMLRenderer(BaseRenderer):
"""
Renderer which serializes to YAML.
"""
media_type = 'application/yaml'
format = 'yaml'
def render(self, obj=None, media_type=None):
"""
Renders *obj* into serialized YAML.
"""
if obj is None:
return ''
return yaml.dump(obj)
else:
YAMLRenderer = None
class TemplateRenderer(BaseRenderer):
"""
A Base class provided for convenience.
......@@ -361,4 +381,5 @@ DEFAULT_RENDERERS = ( JSONRenderer,
DocumentingPlainTextRenderer,
XMLRenderer )
if YAMLRenderer:
DEFAULT_RENDERERS += (YAMLRenderer,)
......@@ -8,6 +8,8 @@
#site-name a {color: #F4F379 !important;}
.errorlist {display: inline !important}
.errorlist li {display: inline !important; background: white !important; color: black !important; border: 0 !important;}
/* Custom styles */
.version{font-size:8px;}
</style>
<link rel="stylesheet" type="text/css" href='{{ADMIN_MEDIA_PREFIX}}css/base.css'/>
<link rel="stylesheet" type="text/css" href='{{ADMIN_MEDIA_PREFIX}}css/forms.css'/>
......@@ -18,7 +20,7 @@
<div id="header">
<div id="branding">
<h1 id="site-name"><a href='http://django-rest-framework.org'>Django REST framework</a> <small>{{ version }}</small></h1>
<h1 id="site-name"><a href='http://django-rest-framework.org'>Django REST framework</a> <span class="version"> v {{ version }}</span></h1>
</div>
<div id="user-tools">
{% if user.is_active %}Welcome, {{ user }}.{% if logout_url %} <a href='{{ logout_url }}'>Log out</a>{% endif %}{% else %}Anonymous {% if login_url %}<a href='{{ login_url }}'>Log in</a>{% endif %}{% endif %}
......@@ -58,8 +60,8 @@
</form>
{% endif %}
{# Only display the POST/PUT/DELETE forms if method tunneling via POST forms is enabled. #}
{% if METHOD_PARAM %}
{# Only display the POST/PUT/DELETE forms if method tunneling via POST forms is enabled and the user has permissions on this view. #}
{% if METHOD_PARAM and response.status != 403 %}
{% if 'POST' in view.allowed_methods %}
<form action="{{ request.get_full_path }}" method="post" {% if post_form.is_multipart %}enctype="multipart/form-data"{% endif %}>
......
......@@ -4,8 +4,8 @@ from django.test import TestCase
from djangorestframework import status
from djangorestframework.compat import View as DjangoView
from djangorestframework.renderers import BaseRenderer, JSONRenderer
from djangorestframework.parsers import JSONParser
from djangorestframework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer
from djangorestframework.parsers import JSONParser, YAMLParser
from djangorestframework.mixins import ResponseMixin
from djangorestframework.response import Response
from djangorestframework.utils.mediatypes import add_media_type_param
......@@ -189,3 +189,38 @@ class JSONRendererTests(TestCase):
content = renderer.render(obj, 'application/json')
(data, files) = parser.parse(StringIO(content))
self.assertEquals(obj, data)
if YAMLRenderer:
_yaml_repr = 'foo: [bar, baz]\n'
class YAMLRendererTests(TestCase):
"""
Tests specific to the JSON Renderer
"""
def test_render(self):
"""
Test basic YAML rendering.
"""
obj = {'foo':['bar','baz']}
renderer = YAMLRenderer(None)
content = renderer.render(obj, 'application/yaml')
self.assertEquals(content, _yaml_repr)
def test_render_and_parse(self):
"""
Test rendering and then parsing returns the original object.
IE obj -> render -> parse -> obj.
"""
obj = {'foo':['bar','baz']}
renderer = YAMLRenderer(None)
parser = YAMLParser(None)
content = renderer.render(obj, 'application/yaml')
(data, files) = parser.parse(StringIO(content))
self.assertEquals(obj, data)
\ No newline at end of file
......@@ -44,7 +44,8 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
renderers.DocumentingHTMLRenderer,
renderers.DocumentingXHTMLRenderer,
renderers.DocumentingPlainTextRenderer,
renderers.XMLRenderer )
renderers.XMLRenderer,
renderers.YAMLRenderer )
"""
List of parsers the resource can parse the request with.
......
- fields:
first_name: ''
groups: []
is_active: true
is_staff: true
is_superuser: true
last_name: ''
password: sha1$b3dff$671b4ab97f2714446da32670d27576614e176758
user_permissions: []
username: test
model: auth.user
pk: 2
#for fixture loading
\ No newline at end of file
from django.conf.urls.defaults import patterns, url
from permissionsexample.views import ThrottlingExampleView
from permissionsexample.views import PermissionsExampleView, ThrottlingExampleView, LoggedInExampleView
urlpatterns = patterns('',
url(r'^$', ThrottlingExampleView.as_view(), name='throttled-resource'),
url(r'^$', PermissionsExampleView.as_view(), name='permissions-example'),
url(r'^throttling$', ThrottlingExampleView.as_view(), name='throttled-resource'),
url(r'^loggedin$', LoggedInExampleView.as_view(), name='loggedin-resource'),
)
from djangorestframework.views import View
from djangorestframework.permissions import PerUserThrottling
from djangorestframework.permissions import PerUserThrottling, IsAuthenticated
from django.core.urlresolvers import reverse
class PermissionsExampleView(View):
"""
A container view for permissions examples.
"""
def get(self, request):
return [{'name': 'Throttling Example', 'url': reverse('throttled-resource')},
{'name': 'Logged in example', 'url': reverse('loggedin-resource')},]
class ThrottlingExampleView(View):
......@@ -18,3 +28,11 @@ class ThrottlingExampleView(View):
Handle GET requests.
"""
return "Successful response to GET request because throttle is not yet active."
class LoggedInExampleView(View):
"""
You can login with **'test', 'test'.**
"""
permissions = (IsAuthenticated, )
def get(self, request):
return 'Logged in or not?'
\ No newline at end of file
......@@ -4,3 +4,4 @@
Pygments==1.4
Markdown==2.0.3
......@@ -22,6 +22,7 @@ class Sandbox(View):
4. A generic object store API.
5. A code highlighting API.
6. A blog posts and comments API.
7. A basic example using permissions.
Please feel free to browse, create, edit and delete the resources in these examples."""
......@@ -32,5 +33,5 @@ class Sandbox(View):
{'name': 'Object store API', 'url': reverse('object-store-root')},
{'name': 'Code highlighting API', 'url': reverse('pygments-root')},
{'name': 'Blog posts API', 'url': reverse('blog-posts-root')},
{'name': 'Permissions example', 'url': reverse('throttled-resource')}
{'name': 'Permissions example', 'url': reverse('permissions-example')}
]
......@@ -89,6 +89,12 @@ TEMPLATE_DIRS = (
# Don't forget to use absolute paths, not relative paths.
)
# for loading initial data
##SERIALIZATION_MODULES = {
# 'yml': "django.core.serializers.pyyaml"
#}
INSTALLED_APPS = (
'django.contrib.auth',
......@@ -104,6 +110,7 @@ INSTALLED_APPS = (
'objectstore',
'pygments_api',
'blogpost',
'permissionsexample',
)
import os
......
# We need Django. Duh.
# coverage isn't strictly a requirement, but it's useful.
Django==1.2.4
wsgiref==0.1.2
coverage==3.4
......@@ -29,6 +29,7 @@ deps=
django==1.2.4
coverage==3.4
unittest-xml-reporting==1.2
Pyyaml==3.10
[testenv:py26-django12]
basepython=python2.6
......@@ -36,6 +37,7 @@ deps=
django==1.2.4
coverage==3.4
unittest-xml-reporting==1.2
Pyyaml==3.10
[testenv:py27-django12]
basepython=python2.7
......@@ -43,6 +45,7 @@ deps=
django==1.2.4
coverage==3.4
unittest-xml-reporting==1.2
Pyyaml==3.10
[testenv:py25-django13]
basepython=python2.5
......@@ -50,6 +53,7 @@ deps=
django==1.3
coverage==3.4
unittest-xml-reporting==1.2
Pyyaml==3.10
[testenv:py26-django13]
basepython=python2.6
......@@ -57,6 +61,7 @@ deps=
django==1.3
coverage==3.4
unittest-xml-reporting==1.2
Pyyaml==3.10
[testenv:py27-django13]
basepython=python2.7
......@@ -64,6 +69,7 @@ deps=
django==1.3
coverage==3.4
unittest-xml-reporting==1.2
Pyyaml==3.10
####################################### EXAMPLES ################################################
......@@ -79,6 +85,7 @@ deps=
httplib2==0.6.0
Markdown==2.0.3
unittest-xml-reporting==1.2
Pyyaml==3.10
[testenv:py26-django12e]
basepython=python2.6
......@@ -92,6 +99,7 @@ deps=
httplib2==0.6.0
Markdown==2.0.3
unittest-xml-reporting==1.2
Pyyaml==3.10
[testenv:py27-django12e]
basepython=python2.7
......@@ -105,6 +113,7 @@ deps=
httplib2==0.6.0
Markdown==2.0.3
unittest-xml-reporting==1.2
Pyyaml==3.10
[testenv:py25-django13e]
basepython=python2.5
......@@ -118,6 +127,7 @@ deps=
httplib2==0.6.0
Markdown==2.0.3
unittest-xml-reporting==1.2
Pyyaml==3.10
[testenv:py26-django13e]
basepython=python2.6
......@@ -131,6 +141,7 @@ deps=
httplib2==0.6.0
Markdown==2.0.3
unittest-xml-reporting==1.2
Pyyaml==3.10
[testenv:py27-django13e]
basepython=python2.7
......@@ -144,3 +155,4 @@ deps=
httplib2==0.6.0
Markdown==2.0.3
unittest-xml-reporting==1.2
Pyyaml==3.10
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment