Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added binary plist support, which yield super-fast parsing on iOS dev…

…ices. Thanks to jacobian for the suggestion!
  • Loading branch information...
commit ed0fe0928f608e83dee86662fe613a079b101b64 1 parent 30cf7f9
@toastdriven toastdriven authored
View
20 docs/serialization.rst
@@ -19,6 +19,7 @@ The default ``Serializer`` supports the following formats:
* xml
* yaml
* html
+* plist
Usage
=====
@@ -84,13 +85,14 @@ like::
class CSVSerializer(Serializer):
- formats = ['json', 'jsonp', 'xml', 'yaml', 'html', 'csv']
+ formats = ['json', 'jsonp', 'xml', 'yaml', 'html', 'plist', 'csv']
content_types = {
'json': 'application/json',
'jsonp': 'text/javascript',
'xml': 'application/xml',
'yaml': 'text/yaml',
'html': 'text/html',
+ 'plist': 'application/x-plist',
'csv': 'text/csv',
}
@@ -112,6 +114,7 @@ like::
data.append(item)
return data
+
``Serializer`` Methods
======================
@@ -124,6 +127,7 @@ This handles most types of data as well as the following output formats::
* xml
* yaml
* html
+ * plist
It was designed to make changing behavior easy, either by overridding the
various format methods (i.e. ``to_json``), by changing the
@@ -270,6 +274,20 @@ Given some Python data, produces YAML output.
Given some YAML data, returns a Python dictionary of the decoded data.
+``to_plist``
+~~~~~~~~~~~~
+
+.. method:: Serializer.to_plist(self, data, options=None):
+
+Given some Python data, produces binary plist output.
+
+``from_plist``
+~~~~~~~~~~~~~~
+
+.. method:: Serializer.from_plist(self, content):
+
+Given some binary plist data, returns a Python dictionary of the decoded data.
+
``to_html``
~~~~~~~~~~~
View
1  requirements.txt
@@ -4,3 +4,4 @@ python-dateutil==1.5
lxml
PyYAML
python_digest
+biplist
View
28 tastypie/serializers.py
@@ -21,6 +21,10 @@
from django.core.serializers import pyyaml
except ImportError:
yaml = None
+try:
+ import biplist
+except ImportError:
+ biplist = None
class Serializer(object):
@@ -34,18 +38,20 @@ class Serializer(object):
* xml
* yaml
* html
+ * plist
It was designed to make changing behavior easy, either by overridding the
various format methods (i.e. ``to_json``), by changing the
``formats/content_types`` options or by altering the other hook methods.
"""
- formats = ['json', 'jsonp', 'xml', 'yaml', 'html']
+ formats = ['json', 'jsonp', 'xml', 'yaml', 'html', 'plist']
content_types = {
'json': 'application/json',
'jsonp': 'text/javascript',
'xml': 'application/xml',
'yaml': 'text/yaml',
'html': 'text/html',
+ 'plist': 'application/x-plist',
}
def __init__(self, formats=None, content_types=None, datetime_formatting=None):
@@ -352,6 +358,26 @@ def from_yaml(self, content):
return yaml.load(content)
+ def to_plist(self, data, options=None):
+ """
+ Given some Python data, produces binary plist output.
+ """
+ options = options or {}
+
+ if biplist is None:
+ raise ImproperlyConfigured("Usage of the plist aspects requires biplist.")
+
+ return biplist.writePlistToString(self.to_simple(data, options))
+
+ def from_plist(self, content):
+ """
+ Given some binary plist data, returns a Python dictionary of the decoded data.
+ """
+ if biplist is None:
+ raise ImproperlyConfigured("Usage of the plist aspects requires biplist.")
+
+ return biplist.readPlistFromString(content)
+
def to_html(self, data, options=None):
"""
Reserved for future usage.
View
29 tests/core/tests/serializers.py
@@ -34,13 +34,13 @@ def dehydrate(self, bundle):
class SerializerTestCase(TestCase):
def test_init(self):
serializer_1 = Serializer()
- self.assertEqual(serializer_1.formats, ['json', 'jsonp', 'xml', 'yaml', 'html'])
- self.assertEqual(serializer_1.content_types, {'xml': 'application/xml', 'yaml': 'text/yaml', 'json': 'application/json', 'jsonp': 'text/javascript', 'html': 'text/html'})
- self.assertEqual(serializer_1.supported_formats, ['application/json', 'text/javascript', 'application/xml', 'text/yaml', 'text/html'])
+ self.assertEqual(serializer_1.formats, ['json', 'jsonp', 'xml', 'yaml', 'html', 'plist'])
+ self.assertEqual(serializer_1.content_types, {'xml': 'application/xml', 'yaml': 'text/yaml', 'json': 'application/json', 'jsonp': 'text/javascript', 'html': 'text/html', 'plist': 'application/x-plist'})
+ self.assertEqual(serializer_1.supported_formats, ['application/json', 'text/javascript', 'application/xml', 'text/yaml', 'text/html', 'application/x-plist'])
serializer_2 = Serializer(formats=['json', 'xml'])
self.assertEqual(serializer_2.formats, ['json', 'xml'])
- self.assertEqual(serializer_2.content_types, {'xml': 'application/xml', 'yaml': 'text/yaml', 'json': 'application/json', 'jsonp': 'text/javascript', 'html': 'text/html'})
+ self.assertEqual(serializer_2.content_types, {'xml': 'application/xml', 'yaml': 'text/yaml', 'json': 'application/json', 'jsonp': 'text/javascript', 'html': 'text/html', 'plist': 'application/x-plist'})
self.assertEqual(serializer_2.supported_formats, ['application/json', 'application/xml'])
serializer_3 = Serializer(formats=['json', 'xml'], content_types={'json': 'text/json', 'xml': 'application/xml'})
@@ -48,6 +48,11 @@ def test_init(self):
self.assertEqual(serializer_3.content_types, {'xml': 'application/xml', 'json': 'text/json'})
self.assertEqual(serializer_3.supported_formats, ['text/json', 'application/xml'])
+ serializer_4 = Serializer(formats=['plist', 'json'], content_types={'plist': 'application/x-plist', 'json': 'application/json'})
+ self.assertEqual(serializer_4.formats, ['plist', 'json'])
+ self.assertEqual(serializer_4.content_types, {'plist': 'application/x-plist', 'json': 'application/json'})
+ self.assertEqual(serializer_4.supported_formats, ['application/x-plist', 'application/json'])
+
self.assertRaises(ImproperlyConfigured, Serializer, formats=['json', 'xml'], content_types={'json': 'text/json'})
def get_sample1(self):
@@ -223,7 +228,21 @@ def test_to_jsonp(self):
sample_1 = self.get_sample1()
options = {'callback': 'myCallback'}
- self.assertEqual(serializer.to_jsonp(sample_1, options), 'myCallback({"age": 27, "date_joined": "2010-03-27", "name": "Daniel"})')
+
+ def test_to_plist(self):
+ serializer = Serializer()
+
+ sample_1 = self.get_sample1()
+ self.assertEqual(serializer.to_plist(sample_1), 'bplist00bybiplist1.0\x00\xd3\x01\x02\x03\x04\x05\x06SageTname[date_joined\x10\x1bf\x00D\x00a\x00n\x00i\x00e\x00lZ2010-03-27\x15\x1c %13@\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00K')
+
+ def test_from_plist(self):
+ serializer = Serializer()
+
+ sample_1 = serializer.from_plist('bplist00bybiplist1.0\x00\xd3\x01\x02\x03\x04\x05\x06SageTname[date_joined\x10\x1bf\x00D\x00a\x00n\x00i\x00e\x00lZ2010-03-27\x15\x1c %13@\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00K')
+ self.assertEqual(len(sample_1), 3)
+ self.assertEqual(sample_1['name'], 'Daniel')
+ self.assertEqual(sample_1['age'], 27)
+ self.assertEqual(sample_1['date_joined'], u'2010-03-27')
class ResourceSerializationTestCase(TestCase):
fixtures = ['note_testdata.json']
View
6 tests/core/tests/utils.py
@@ -30,6 +30,9 @@ def test_determine_format(self):
request.GET = {'format': 'yaml'}
self.assertEqual(determine_format(request, serializer), 'text/yaml')
+ request.GET = {'format': 'plist'}
+ self.assertEqual(determine_format(request, serializer), 'application/x-plist')
+
request.GET = {'format': 'foo'}
self.assertEqual(determine_format(request, serializer), 'application/json')
@@ -46,6 +49,9 @@ def test_determine_format(self):
request.META = {'HTTP_ACCEPT': 'text/yaml'}
self.assertEqual(determine_format(request, serializer), 'text/yaml')
+ request.META = {'HTTP_ACCEPT': 'application/x-plist'}
+ self.assertEqual(determine_format(request, serializer), 'application/x-plist')
+
request.META = {'HTTP_ACCEPT': 'text/html'}
self.assertEqual(determine_format(request, serializer), 'text/html')
Please sign in to comment.
Something went wrong with that request. Please try again.