Files
mayan-edms/mayan/apps/common/serializers/better_yaml.py
Roberto Rosario 41d0cfb7bf Code cleanups
2014-06-29 20:35:36 -04:00

105 lines
2.9 KiB
Python

# better_yaml.py
"""
Customized YAML serializer, with more condensed and readable output.
Rather than producing a flat list of objects with the same three attributes:
- fields: {...}
model: modelname
pk: 123
This serializer nests the data, grouping by model name, then indexing by
primary key. For example, instead of this output, as produced by the default
YAML serializer:
- fields: {name: blue}
model: app.firstmodel
pk: 3
- fields: {name: red}
model: app.firstmodel
pk: 1
- fields: {name: green}
model: app.firstmodel
pk: 2
- fields: {name: crumbly}
model: app.secondmodel
pk: 2
- fields: {name: squishy}
model: app.secondmodel
pk: 1
You'll get this output:
app.firstmodel:
1: {name: red}
2: {name: green}
3: {name: blue}
app.secondmodel:
1: {name: squishy}
2: {name: crumbly}
To use this customized serializer and deserializer, save this file
somewhere in your Django project, then add this to your settings.py:
SERIALIZATION_MODULES = {
'yaml': 'path.to.better_yaml',
}
Note that this serializer is NOT compatible with the default Django
YAML serializer; this one uses nested dictionaries, while the default
one uses a flat list of object dicts.
Requires PyYaml (http://pyyaml.org/), of course.
"""
from StringIO import StringIO
import yaml
from django.core.serializers.python import Deserializer as PythonDeserializer
from django.core.serializers.pyyaml import Serializer as YamlSerializer
from django.utils.encoding import smart_unicode
class Serializer (YamlSerializer):
"""
Serialize database objects as nested dicts, indexed first by
model name, then by primary key.
"""
def start_serialization(self):
self._current = None
self.objects = {}
def end_object(self, obj):
model = smart_unicode(obj._meta)
pk = obj._get_pk_val()
if model not in self.objects:
self.objects[model] = {}
self.objects[model][pk] = self._current
self._current = None
def Deserializer(stream_or_string, **options):
"""
Deserialize a stream or string of YAML data,
as written by the Serializer above.
"""
if isinstance(stream_or_string, basestring):
stream = StringIO(stream_or_string)
else:
stream = stream_or_string
# Reconstruct the flat object list as PythonDeserializer expects
# NOTE: This could choke on large data sets, since it
# constructs the flattened data list in memory
data = []
for model, objects in yaml.load(stream).iteritems():
# Add the model name back into each object dict
for pk, fields in objects.iteritems():
data.append({'model': model, 'pk': pk, 'fields': fields})
# Deserialize the flattened data
for obj in PythonDeserializer(data, **options):
yield obj