source: pyyaml/trunk/lib/yaml/representer.py @ 139

Revision 139, 10.8 KB checked in by xi, 8 years ago (diff)

Add constructors for some simple python types.

RevLine 
[133]1
2__all__ = ['BaseRepresenter', 'SafeRepresenter', 'Representer',
3    'RepresenterError']
4
5from error import *
6from nodes import *
7
8try:
9    import datetime
10    datetime_available = True
11except ImportError:
12    datetime_available = False
13
14try:
15    set
16except NameError:
17    from sets import Set as set
18
[139]19import sys
20
[133]21class RepresenterError(YAMLError):
22    pass
23
[136]24class BaseRepresenter:
[133]25
[136]26    yaml_representers = {}
[133]27
[136]28    def __init__(self):
[133]29        self.represented_objects = {}
30
[136]31    def represent(self, data):
32        node = self.represent_object(data)
33        self.serialize(node)
[133]34        self.represented_objects = {}
35
[139]36    class C: pass
37    c = C()
38    def f(): pass
39    classobj_type = type(C)
40    instance_type = type(c)
41    function_type = type(f)
42    builtin_function_type = type(abs)
43    module_type = type(sys)
44    del C, c, f
45
46    def get_classobj_bases(self, cls):
47        bases = [cls]
48        for base in cls.__bases__:
49            bases.extend(self.get_classobj_bases(base))
50        return bases
51
[136]52    def represent_object(self, data):
53        if self.ignore_aliases(data):
[133]54            alias_key = None
55        else:
[136]56            alias_key = id(data)
[133]57        if alias_key is not None:
58            if alias_key in self.represented_objects:
59                node = self.represented_objects[alias_key]
60                if node is None:
[136]61                    raise RepresenterError("recursive objects are not allowed: %r" % data)
[133]62                return node
63            self.represented_objects[alias_key] = None
[139]64        data_types = type(data).__mro__
65        if type(data) is self.instance_type:
66            data_types = self.get_classobj_bases(data.__class__)+data_types
67        for data_type in data_types:
[136]68            if data_type in self.yaml_representers:
69                node = self.yaml_representers[data_type](self, data)
[133]70                break
71        else:
72            if None in self.yaml_representers:
[136]73                node = self.yaml_representers[None](self, data)
[133]74            else:
[136]75                node = ScalarNode(None, unicode(data))
[133]76        if alias_key is not None:
77            self.represented_objects[alias_key] = node
78        return node
79
[136]80    def add_representer(cls, data_type, representer):
[133]81        if not 'yaml_representers' in cls.__dict__:
82            cls.yaml_representers = cls.yaml_representers.copy()
[136]83        cls.yaml_representers[data_type] = representer
[133]84    add_representer = classmethod(add_representer)
85
86    def represent_scalar(self, tag, value, style=None):
[136]87        return ScalarNode(tag, value, style=style)
[133]88
89    def represent_sequence(self, tag, sequence, flow_style=None):
90        value = []
91        for item in sequence:
92            value.append(self.represent_object(item))
93        return SequenceNode(tag, value, flow_style=flow_style)
94
95    def represent_mapping(self, tag, mapping, flow_style=None):
96        if hasattr(mapping, 'keys'):
[139]97            value = {}
[133]98            for item_key in mapping.keys():
99                item_value = mapping[item_key]
100                value[self.represent_object(item_key)] =    \
101                        self.represent_object(item_value)
102        else:
[139]103            value = []
[133]104            for item_key, item_value in mapping:
[139]105                value.append((self.represent_object(item_key),
106                        self.represent_object(item_value)))
[133]107        return MappingNode(tag, value, flow_style=flow_style)
108
[136]109    def ignore_aliases(self, data):
[133]110        return False
111
[136]112class SafeRepresenter(BaseRepresenter):
[133]113
[136]114    def ignore_aliases(self, data):
115        if data in [None, ()]:
[133]116            return True
[136]117        if isinstance(data, (str, unicode, bool, int, float)):
[133]118            return True
119
[136]120    def represent_none(self, data):
[133]121        return self.represent_scalar(u'tag:yaml.org,2002:null',
122                u'null')
123
[136]124    def represent_str(self, data):
[139]125        tag = None
126        style = None
[133]127        try:
[139]128            data = unicode(data, 'ascii')
129            tag = u'tag:yaml.org,2002:str'
[135]130        except UnicodeDecodeError:
131            try:
[139]132                data = unicode(data, 'utf-8')
133                tag = u'tag:yaml.org,2002:str'
[135]134            except UnicodeDecodeError:
[139]135                data = data.encode('base64')
136                tag = u'tag:yaml.org,2002:binary'
137                style = '|'
138        return self.represent_scalar(tag, data, style=style)
[133]139
[136]140    def represent_unicode(self, data):
141        return self.represent_scalar(u'tag:yaml.org,2002:str', data)
[133]142
[136]143    def represent_bool(self, data):
144        if data:
[133]145            value = u'true'
146        else:
147            value = u'false'
148        return self.represent_scalar(u'tag:yaml.org,2002:bool', value)
149
[136]150    def represent_int(self, data):
151        return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data))
[133]152
[136]153    def represent_long(self, data):
154        return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data))
[133]155
156    inf_value = 1e300000
157    nan_value = inf_value/inf_value
158
[136]159    def represent_float(self, data):
160        if data == self.inf_value:
[133]161            value = u'.inf'
[136]162        elif data == -self.inf_value:
[133]163            value = u'-.inf'
[136]164        elif data == self.nan_value or data != data:
[133]165            value = u'.nan'
166        else:
[139]167            value = unicode(repr(data))
[133]168        return self.represent_scalar(u'tag:yaml.org,2002:float', value)
169
[136]170    def represent_list(self, data):
[139]171        pairs = (len(data) > 0 and isinstance(data, list))
172        if pairs:
173            for item in data:
174                if not isinstance(item, tuple) or len(item) != 2:
175                    pairs = False
176                    break
[133]177        if not pairs:
[136]178            return self.represent_sequence(u'tag:yaml.org,2002:seq', data)
[133]179        value = []
[136]180        for item_key, item_value in data:
[133]181            value.append(self.represent_mapping(u'tag:yaml.org,2002:map',
182                [(item_key, item_value)]))
183        return SequenceNode(u'tag:yaml.org,2002:pairs', value)
184
[136]185    def represent_dict(self, data):
186        return self.represent_mapping(u'tag:yaml.org,2002:map', data)
[133]187
[136]188    def represent_set(self, data):
[133]189        value = {}
[136]190        for key in data:
[133]191            value[key] = None
192        return self.represent_mapping(u'tag:yaml.org,2002:set', value)
193
[136]194    def represent_date(self, data):
195        value = u'%04d-%02d-%02d' % (data.year, data.month, data.day)
[133]196        return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value)
197
[136]198    def represent_datetime(self, data):
[133]199        value = u'%04d-%02d-%02d %02d:%02d:%02d' \
[136]200                % (data.year, data.month, data.day,
201                    data.hour, data.minute, data.second)
202        if data.microsecond:
203            value += u'.' + unicode(data.microsecond/1000000.0).split(u'.')[1]
204        if data.utcoffset():
205            value += unicode(data.utcoffset())
[133]206        return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value)
207
[136]208    def represent_yaml_object(self, tag, data, cls, flow_style=None):
209        if hasattr(data, '__getstate__'):
210            state = data.__getstate__()
211        else:
212            state = data.__dict__.copy()
[139]213        return self.represent_mapping(tag, state, flow_style=flow_style)
[133]214
[136]215    def represent_undefined(self, data):
216        raise RepresenterError("cannot represent an object: %s" % data)
217
[133]218SafeRepresenter.add_representer(type(None),
219        SafeRepresenter.represent_none)
220
221SafeRepresenter.add_representer(str,
222        SafeRepresenter.represent_str)
223
224SafeRepresenter.add_representer(unicode,
225        SafeRepresenter.represent_unicode)
226
227SafeRepresenter.add_representer(bool,
228        SafeRepresenter.represent_bool)
229
230SafeRepresenter.add_representer(int,
231        SafeRepresenter.represent_int)
232
233SafeRepresenter.add_representer(long,
234        SafeRepresenter.represent_long)
235
236SafeRepresenter.add_representer(float,
237        SafeRepresenter.represent_float)
238
239SafeRepresenter.add_representer(list,
240        SafeRepresenter.represent_list)
241
[139]242SafeRepresenter.add_representer(tuple,
243        SafeRepresenter.represent_list)
244
[133]245SafeRepresenter.add_representer(dict,
246        SafeRepresenter.represent_dict)
247
248SafeRepresenter.add_representer(set,
249        SafeRepresenter.represent_set)
250
251if datetime_available:
252    SafeRepresenter.add_representer(datetime.date,
253            SafeRepresenter.represent_date)
254    SafeRepresenter.add_representer(datetime.datetime,
255            SafeRepresenter.represent_datetime)
256
257SafeRepresenter.add_representer(None,
258        SafeRepresenter.represent_undefined)
259
260class Representer(SafeRepresenter):
[139]261   
262    def represent_str(self, data):
263        tag = None
264        style = None
265        try:
266            data = unicode(data, 'ascii')
267            tag = u'tag:yaml.org,2002:str'
268        except UnicodeDecodeError:
269            try:
270                data = unicode(data, 'utf-8')
271                tag = u'tag:yaml.org,2002:python/str'
272            except UnicodeDecodeError:
273                data = data.encode('base64')
274                tag = u'tag:yaml.org,2002:binary'
275                style = '|'
276        return self.represent_scalar(tag, data, style=style)
[133]277
[139]278    def represent_unicode(self, data):
279        tag = None
280        try:
281            data.encode('ascii')
282            tag = u'tag:yaml.org,2002:python/unicode'
283        except UnicodeEncodeError:
284            tag = u'tag:yaml.org,2002:str'
285        return self.represent_scalar(tag, data)
286
287    def represent_long(self, data):
288        tag = u'tag:yaml.org,2002:int'
289        if int(data) is not data:
290            tag = u'tag:yaml.org,2002:python/long'
291        return self.represent_scalar(tag, unicode(data))
292
293    def represent_complex(self, data):
294        if data.real != 0.0:
295            data = u'%r+%rj' % (data.real, data.imag)
296        else:
297            data = u'%rj' % data.imag
298        return self.represent_scalar(u'tag:yaml.org,2002:python/complex', data)
299
300    def represent_tuple(self, data):
301        return self.represent_sequence(u'tag:yaml.org,2002:python/tuple', data)
302
303    def represent_name(self, data):
304        name = u'%s.%s' % (data.__module__, data.__name__)
305        return self.represent_scalar(u'tag:yaml.org,2002:python/name:'+name, u'')
306
307    def represent_module(self, data):
308        return self.represent_scalar(
309                u'tag:yaml.org,2002:python/module:'+data.__name__, u'')
310
311Representer.add_representer(str,
312        Representer.represent_str)
313
314Representer.add_representer(unicode,
315        Representer.represent_unicode)
316
317Representer.add_representer(long,
318        Representer.represent_long)
319
320Representer.add_representer(complex,
321        Representer.represent_complex)
322
323Representer.add_representer(tuple,
324        Representer.represent_tuple)
325
326Representer.add_representer(type,
327        Representer.represent_name)
328
329Representer.add_representer(Representer.classobj_type,
330        Representer.represent_name)
331
332Representer.add_representer(Representer.function_type,
333        Representer.represent_name)
334
335Representer.add_representer(Representer.builtin_function_type,
336        Representer.represent_name)
337
338Representer.add_representer(Representer.module_type,
339        Representer.represent_module)
340
Note: See TracBrowser for help on using the repository browser.