resolving merge between ephelon's fork and the rest, all tests pass

This commit is contained in:
Jesper Noehr 2009-08-17 16:46:26 +03:00
Родитель c934ccdca7 b1d070f3f7
Коммит 15202e9b15
10 изменённых файлов: 111 добавлений и 27 удалений

Просмотреть файл

@ -16,3 +16,5 @@ Brian McMurray for contributing a patch for #41
James Emerton for making the OAuth parts more usable/friendly
Anton Tsigularov for providing a patch for incorrect multipart detection
Remco Wendt for fixing up the example blog server to conform with 0.2.2, et. al
Benoit Garret for providing a fix for oauth headers, issue #56
Stephan Preeker for providing some fixes to documentation generation

Просмотреть файл

@ -1,6 +1,7 @@
import inspect, handler
from piston.handler import typemapper
from piston.handler import handler_tracker
from django.core.urlresolvers import get_resolver, get_callable, get_script_prefix
from django.shortcuts import render_to_response
@ -36,7 +37,8 @@ class HandlerMethod(object):
else:
yield (arg, None)
def get_signature(self, parse_optional=True):
@property
def signature(self, parse_optional=True):
spec = ""
for argn, argdef in self.iter_args():
@ -53,18 +55,25 @@ class HandlerMethod(object):
return spec.replace("=None", "=<optional>")
return spec
signature = property(get_signature)
def get_doc(self):
@property
def doc(self):
return inspect.getdoc(self.method)
doc = property(get_doc)
def get_name(self):
@property
def name(self):
return self.method.__name__
name = property(get_name)
@property
def http_name(self):
if self.name == 'read':
return 'GET'
elif self.name == 'create':
return 'POST'
elif self.name == 'delete':
return 'DELETE'
elif self.name == 'update':
return 'PUT'
def __repr__(self):
return "<Method: %s>" % self.name
@ -97,11 +106,19 @@ class HandlerDocumentation(object):
def get_model(self):
return getattr(self, 'model', None)
def get_doc(self):
@property
def has_anonymous(self):
return self.handler.anonymous
@property
def anonymous(self):
if self.has_anonymous:
return HandlerDocumentation(self.handler.anonymous)
@property
def doc(self):
return self.handler.__doc__
doc = property(get_doc)
@property
def name(self):
return self.handler.__name__
@ -159,8 +176,16 @@ def documentation_view(request):
"""
docs = [ ]
for handler, (model, anonymous) in typemapper.iteritems():
for handler in handler_tracker:
docs.append(generate_doc(handler))
def _compare(doc1, doc2):
#handlers and their anonymous counterparts are put next to each other.
name1 = doc1.name.replace("Anonymous", "")
name2 = doc2.name.replace("Anonymous", "")
return cmp(name1, name2)
docs.sort(_compare)
return render_to_response('documentation.html',
{ 'docs': docs }, RequestContext(request))

Просмотреть файл

@ -1,6 +1,7 @@
from __future__ import generators
import decimal, re, inspect
import copy
try:
# yaml isn't standard with python. It shouldn't be required if it
@ -68,7 +69,7 @@ class Emitter(object):
ret = dict()
for field in fields:
if field in has:
if field in has and callable(field):
ret[field] = getattr(data, field)
return ret
@ -171,7 +172,7 @@ class Emitter(object):
get_fields = set(fields)
met_fields = self.method_fields(handler, get_fields)
for f in data._meta.local_fields:
if f.serialize and not any([ p in met_fields for p in [ f.attname, f.name ]]):
if not f.rel:
@ -191,7 +192,6 @@ class Emitter(object):
# try to get the remainder of fields
for maybe_field in get_fields:
if isinstance(maybe_field, (list, tuple)):
model, fields = maybe_field
inst = getattr(data, model, None)

Просмотреть файл

@ -23,7 +23,7 @@ class ModelForm(forms.ModelForm):
class OAuthAuthenticationForm(forms.Form):
oauth_token = forms.CharField(widget=forms.HiddenInput)
oauth_callback = forms.URLField(widget=forms.HiddenInput)
oauth_callback = forms.CharField(widget=forms.HiddenInput)
authorize_access = forms.BooleanField(required=True)
csrf_signature = forms.CharField(widget=forms.HiddenInput)

Просмотреть файл

@ -2,6 +2,7 @@ from utils import rc
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
typemapper = { }
handler_tracker = [ ]
class HandlerMetaClass(type):
"""
@ -14,6 +15,9 @@ class HandlerMetaClass(type):
if hasattr(new_cls, 'model'):
typemapper[new_cls] = (new_cls.model, new_cls.is_anonymous)
if name not in ('BaseHandler', 'AnonymousBaseHandler'):
handler_tracker.append(new_cls)
return new_cls
class BaseHandler(object):

Просмотреть файл

@ -247,10 +247,11 @@ class OAuthRequest(object):
@staticmethod
def _split_header(header):
params = {}
header = header.replace('OAuth ', '', 1)
parts = header.split(',')
for param in parts:
# ignore realm parameter
if param.find('OAuth realm') > -1:
if param.find('realm') > -1:
continue
# remove whitespace
param = param.strip()

Просмотреть файл

@ -3,11 +3,10 @@ from django.core.paginator import Paginator
from piston.handler import BaseHandler
from piston.utils import rc, validate
from models import TestModel, ExpressiveTestModel, Comment, InheritedModel, PlainOldObject, ListFieldsModel
from models import TestModel, ExpressiveTestModel, Comment, InheritedModel, PlainOldObject, Issue58Model, ListFieldsModel
from forms import EchoForm
from test_project.apps.testapp import signals
class EntryHandler(BaseHandler):
model = TestModel
allowed_methods = ['GET', 'PUT', 'POST']
@ -82,3 +81,17 @@ class ListFieldsHandler(BaseHandler):
fields = ('id','kind','variety','color')
list_fields = ('id','variety')
class Issue58Handler(BaseHandler):
model = Issue58Model
def read(self, request):
return Issue58Model.objects.all()
def create(self, request):
if request.content_type:
data = request.data
em = self.model(read=data['read'], model=data['model'])
em.save()
return rc.CREATED
else:
super(Issue58Model, self).create(request)

Просмотреть файл

@ -30,8 +30,11 @@ class PlainOldObject(object):
return {'type': 'plain',
'field': 'a field'}
class ListFieldsModel(models.Model):
kind = models.CharField(max_length=15)
variety = models.CharField(max_length=15)
color = models.CharField(max_length=15)
class Issue58Model(models.Model):
read = models.BooleanField(default=False)
model = models.CharField(max_length=1, blank=True, null=True)

Просмотреть файл

@ -15,7 +15,7 @@ except ImportError:
import urllib, base64
from test_project.apps.testapp.models import TestModel, ExpressiveTestModel, Comment, InheritedModel, ListFieldsModel
from test_project.apps.testapp.models import TestModel, ExpressiveTestModel, Comment, InheritedModel, Issue58Model, ListFieldsModel
from test_project.apps.testapp import signals
class MainTests(TestCase):
@ -370,8 +370,6 @@ class PlainOldObject(MainTests):
resp = self.client.get('/api/popo')
self.assertEquals(resp.status_code, 200)
self.assertEquals({'type': 'plain', 'field': 'a field'}, simplejson.loads(resp.content))
class ListFieldsTest(MainTests):
def init_delegate(self):
@ -410,3 +408,39 @@ class ListFieldsTest(MainTests):
self.assertEquals(resp.status_code, 200)
self.assertEquals(resp.content, expect)
class Issue58ModelTests(MainTests):
"""
This testcase addresses #58 in django-piston where if a model
has one of the ['read','update','delete','create'] defined
it make piston crash with a `TypeError`
"""
def init_delegate(self):
m1 = Issue58Model(read=True,model='t')
m1.save()
m2 = Issue58Model(read=False,model='f')
m2.save()
def test_incoming_json(self):
outgoing = simplejson.dumps({ 'read': True, 'model': 'T'})
expected = """[
{
"read": true,
"model": "t"
},
{
"read": false,
"model": "f"
}
]"""
# test GET
result = self.client.get('/api/issue58.json',
HTTP_AUTHORIZATION=self.auth_string).content
self.assertEquals(result, expected)
# test POST
resp = self.client.post('/api/issue58.json', outgoing, content_type='application/json',
HTTP_AUTHORIZATION=self.auth_string)
self.assertEquals(resp.status_code, 201)

Просмотреть файл

@ -2,7 +2,7 @@ from django.conf.urls.defaults import *
from piston.resource import Resource
from piston.authentication import HttpBasicAuthentication
from test_project.apps.testapp.handlers import EntryHandler, ExpressiveHandler, AbstractHandler, EchoHandler, PlainOldObjectHandler, ListFieldsHandler
from test_project.apps.testapp.handlers import EntryHandler, ExpressiveHandler, AbstractHandler, EchoHandler, PlainOldObjectHandler, Issue58Handler, ListFieldsHandler
auth = HttpBasicAuthentication(realm='TestApplication')
@ -12,7 +12,7 @@ abstract = Resource(handler=AbstractHandler, authentication=auth)
echo = Resource(handler=EchoHandler)
popo = Resource(handler=PlainOldObjectHandler)
list_fields = Resource(handler=ListFieldsHandler)
issue58 = Resource(handler=Issue58Handler)
urlpatterns = patterns('',
url(r'^entries/$', entries),
@ -20,6 +20,8 @@ urlpatterns = patterns('',
url(r'^entries\.(?P<emitter_format>.+)', entries),
url(r'^entry-(?P<pk>.+)\.(?P<emitter_format>.+)', entries),
url(r'^issue58\.(?P<emitter_format>.+)$', issue58),
url(r'^expressive\.(?P<emitter_format>.+)$', expressive),
url(r'^abstract\.(?P<emitter_format>.+)$', abstract),