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

Revision 136, 7.9 KB checked in by xi, 8 years ago (diff)

Major refactoring.

RevLine 
[133]1
2__all__ = ['BaseRepresenter', 'SafeRepresenter', 'Representer',
3    'RepresenterError']
4
5from error import *
6from nodes import *
7from detector import *
8
9try:
10    import datetime
11    datetime_available = True
12except ImportError:
13    datetime_available = False
14
15try:
16    set
17except NameError:
18    from sets import Set as set
19
20class RepresenterError(YAMLError):
21    pass
22
[136]23class BaseRepresenter:
[133]24
[136]25    yaml_representers = {}
[133]26
[136]27    def __init__(self):
[133]28        self.represented_objects = {}
29
[136]30    def represent(self, data):
31        node = self.represent_object(data)
32        self.serialize(node)
[133]33        self.represented_objects = {}
34
[136]35    def represent_object(self, data):
36        if self.ignore_aliases(data):
[133]37            alias_key = None
38        else:
[136]39            alias_key = id(data)
[133]40        if alias_key is not None:
41            if alias_key in self.represented_objects:
42                node = self.represented_objects[alias_key]
43                if node is None:
[136]44                    raise RepresenterError("recursive objects are not allowed: %r" % data)
[133]45                return node
46            self.represented_objects[alias_key] = None
[136]47        for data_type in type(data).__mro__:
48            if data_type in self.yaml_representers:
49                node = self.yaml_representers[data_type](self, data)
[133]50                break
51        else:
52            if None in self.yaml_representers:
[136]53                node = self.yaml_representers[None](self, data)
[133]54            else:
[136]55                node = ScalarNode(None, unicode(data))
[133]56        if alias_key is not None:
57            self.represented_objects[alias_key] = node
58        return node
59
[136]60    def add_representer(cls, data_type, representer):
[133]61        if not 'yaml_representers' in cls.__dict__:
62            cls.yaml_representers = cls.yaml_representers.copy()
[136]63        cls.yaml_representers[data_type] = representer
[133]64    add_representer = classmethod(add_representer)
65
66    def represent_scalar(self, tag, value, style=None):
[136]67        return ScalarNode(tag, value, style=style)
[133]68
69    def represent_sequence(self, tag, sequence, flow_style=None):
70        value = []
71        for item in sequence:
72            value.append(self.represent_object(item))
73        return SequenceNode(tag, value, flow_style=flow_style)
74
75    def represent_mapping(self, tag, mapping, flow_style=None):
76        value = {}
77        if hasattr(mapping, 'keys'):
78            for item_key in mapping.keys():
79                item_value = mapping[item_key]
80                value[self.represent_object(item_key)] =    \
81                        self.represent_object(item_value)
82        else:
83            for item_key, item_value in mapping:
84                value[self.represent_object(item_key)] =    \
85                        self.represent_object(item_value)
86        return MappingNode(tag, value, flow_style=flow_style)
87
[136]88    def ignore_aliases(self, data):
[133]89        return False
90
[136]91class SafeRepresenter(BaseRepresenter):
[133]92
[136]93    def ignore_aliases(self, data):
94        if data in [None, ()]:
[133]95            return True
[136]96        if isinstance(data, (str, unicode, bool, int, float)):
[133]97            return True
98
[136]99    def represent_none(self, data):
[133]100        return self.represent_scalar(u'tag:yaml.org,2002:null',
101                u'null')
102
[136]103    def represent_str(self, data):
[135]104        encoding = None
[133]105        try:
[136]106            unicode(data, 'ascii')
[135]107            encoding = 'ascii'
108        except UnicodeDecodeError:
109            try:
[136]110                unicode(data, 'utf-8')
[135]111                encoding = 'utf-8'
112            except UnicodeDecodeError:
113                pass
114        if encoding:
[133]115            return self.represent_scalar(u'tag:yaml.org,2002:str',
[136]116                    unicode(data, encoding))
[133]117        else:
118            return self.represent_scalar(u'tag:yaml.org,2002:binary',
[136]119                    unicode(data.encode('base64')), style='|')
[133]120
[136]121    def represent_unicode(self, data):
122        return self.represent_scalar(u'tag:yaml.org,2002:str', data)
[133]123
[136]124    def represent_bool(self, data):
125        if data:
[133]126            value = u'true'
127        else:
128            value = u'false'
129        return self.represent_scalar(u'tag:yaml.org,2002:bool', value)
130
[136]131    def represent_int(self, data):
132        return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data))
[133]133
[136]134    def represent_long(self, data):
135        return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data))
[133]136
137    inf_value = 1e300000
138    nan_value = inf_value/inf_value
139
[136]140    def represent_float(self, data):
141        if data == self.inf_value:
[133]142            value = u'.inf'
[136]143        elif data == -self.inf_value:
[133]144            value = u'-.inf'
[136]145        elif data == self.nan_value or data != data:
[133]146            value = u'.nan'
147        else:
[136]148            value = unicode(data)
[133]149        return self.represent_scalar(u'tag:yaml.org,2002:float', value)
150
[136]151    def represent_list(self, data):
152        pairs = (len(data) > 0)
153        for item in data:
[133]154            if not isinstance(item, tuple) or len(item) != 2:
155                pairs = False
156                break
157        if not pairs:
[136]158            return self.represent_sequence(u'tag:yaml.org,2002:seq', data)
[133]159        value = []
[136]160        for item_key, item_value in data:
[133]161            value.append(self.represent_mapping(u'tag:yaml.org,2002:map',
162                [(item_key, item_value)]))
163        return SequenceNode(u'tag:yaml.org,2002:pairs', value)
164
[136]165    def represent_dict(self, data):
166        return self.represent_mapping(u'tag:yaml.org,2002:map', data)
[133]167
[136]168    def represent_set(self, data):
[133]169        value = {}
[136]170        for key in data:
[133]171            value[key] = None
172        return self.represent_mapping(u'tag:yaml.org,2002:set', value)
173
[136]174    def represent_date(self, data):
175        value = u'%04d-%02d-%02d' % (data.year, data.month, data.day)
[133]176        return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value)
177
[136]178    def represent_datetime(self, data):
[133]179        value = u'%04d-%02d-%02d %02d:%02d:%02d' \
[136]180                % (data.year, data.month, data.day,
181                    data.hour, data.minute, data.second)
182        if data.microsecond:
183            value += u'.' + unicode(data.microsecond/1000000.0).split(u'.')[1]
184        if data.utcoffset():
185            value += unicode(data.utcoffset())
[133]186        return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value)
187
[136]188    def represent_yaml_object(self, tag, data, cls, flow_style=None):
189        if hasattr(data, '__getstate__'):
190            state = data.__getstate__()
191        else:
192            state = data.__dict__.copy()
193        mapping = state
194        if hasattr(state, 'keys'):
195            mapping = []
196            keys = state.keys()
197            keys.sort()
198            for key in keys:
199                mapping.append((key.replace('_', '-'), state[key]))
200        return self.represent_mapping(tag, mapping, flow_style=flow_style)
[133]201
[136]202    def represent_undefined(self, data):
203        raise RepresenterError("cannot represent an object: %s" % data)
204
[133]205SafeRepresenter.add_representer(type(None),
206        SafeRepresenter.represent_none)
207
208SafeRepresenter.add_representer(str,
209        SafeRepresenter.represent_str)
210
211SafeRepresenter.add_representer(unicode,
212        SafeRepresenter.represent_unicode)
213
214SafeRepresenter.add_representer(bool,
215        SafeRepresenter.represent_bool)
216
217SafeRepresenter.add_representer(int,
218        SafeRepresenter.represent_int)
219
220SafeRepresenter.add_representer(long,
221        SafeRepresenter.represent_long)
222
223SafeRepresenter.add_representer(float,
224        SafeRepresenter.represent_float)
225
226SafeRepresenter.add_representer(list,
227        SafeRepresenter.represent_list)
228
229SafeRepresenter.add_representer(dict,
230        SafeRepresenter.represent_dict)
231
232SafeRepresenter.add_representer(set,
233        SafeRepresenter.represent_set)
234
235if datetime_available:
236    SafeRepresenter.add_representer(datetime.date,
237            SafeRepresenter.represent_date)
238    SafeRepresenter.add_representer(datetime.datetime,
239            SafeRepresenter.represent_datetime)
240
241SafeRepresenter.add_representer(None,
242        SafeRepresenter.represent_undefined)
243
244class Representer(SafeRepresenter):
245    pass
246
Note: See TracBrowser for help on using the repository browser.