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

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

Major refactoring.

Line 
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
23class BaseRepresenter:
24
25    yaml_representers = {}
26
27    def __init__(self):
28        self.represented_objects = {}
29
30    def represent(self, data):
31        node = self.represent_object(data)
32        self.serialize(node)
33        self.represented_objects = {}
34
35    def represent_object(self, data):
36        if self.ignore_aliases(data):
37            alias_key = None
38        else:
39            alias_key = id(data)
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:
44                    raise RepresenterError("recursive objects are not allowed: %r" % data)
45                return node
46            self.represented_objects[alias_key] = None
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)
50                break
51        else:
52            if None in self.yaml_representers:
53                node = self.yaml_representers[None](self, data)
54            else:
55                node = ScalarNode(None, unicode(data))
56        if alias_key is not None:
57            self.represented_objects[alias_key] = node
58        return node
59
60    def add_representer(cls, data_type, representer):
61        if not 'yaml_representers' in cls.__dict__:
62            cls.yaml_representers = cls.yaml_representers.copy()
63        cls.yaml_representers[data_type] = representer
64    add_representer = classmethod(add_representer)
65
66    def represent_scalar(self, tag, value, style=None):
67        return ScalarNode(tag, value, style=style)
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
88    def ignore_aliases(self, data):
89        return False
90
91class SafeRepresenter(BaseRepresenter):
92
93    def ignore_aliases(self, data):
94        if data in [None, ()]:
95            return True
96        if isinstance(data, (str, unicode, bool, int, float)):
97            return True
98
99    def represent_none(self, data):
100        return self.represent_scalar(u'tag:yaml.org,2002:null',
101                u'null')
102
103    def represent_str(self, data):
104        encoding = None
105        try:
106            unicode(data, 'ascii')
107            encoding = 'ascii'
108        except UnicodeDecodeError:
109            try:
110                unicode(data, 'utf-8')
111                encoding = 'utf-8'
112            except UnicodeDecodeError:
113                pass
114        if encoding:
115            return self.represent_scalar(u'tag:yaml.org,2002:str',
116                    unicode(data, encoding))
117        else:
118            return self.represent_scalar(u'tag:yaml.org,2002:binary',
119                    unicode(data.encode('base64')), style='|')
120
121    def represent_unicode(self, data):
122        return self.represent_scalar(u'tag:yaml.org,2002:str', data)
123
124    def represent_bool(self, data):
125        if data:
126            value = u'true'
127        else:
128            value = u'false'
129        return self.represent_scalar(u'tag:yaml.org,2002:bool', value)
130
131    def represent_int(self, data):
132        return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data))
133
134    def represent_long(self, data):
135        return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data))
136
137    inf_value = 1e300000
138    nan_value = inf_value/inf_value
139
140    def represent_float(self, data):
141        if data == self.inf_value:
142            value = u'.inf'
143        elif data == -self.inf_value:
144            value = u'-.inf'
145        elif data == self.nan_value or data != data:
146            value = u'.nan'
147        else:
148            value = unicode(data)
149        return self.represent_scalar(u'tag:yaml.org,2002:float', value)
150
151    def represent_list(self, data):
152        pairs = (len(data) > 0)
153        for item in data:
154            if not isinstance(item, tuple) or len(item) != 2:
155                pairs = False
156                break
157        if not pairs:
158            return self.represent_sequence(u'tag:yaml.org,2002:seq', data)
159        value = []
160        for item_key, item_value in data:
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
165    def represent_dict(self, data):
166        return self.represent_mapping(u'tag:yaml.org,2002:map', data)
167
168    def represent_set(self, data):
169        value = {}
170        for key in data:
171            value[key] = None
172        return self.represent_mapping(u'tag:yaml.org,2002:set', value)
173
174    def represent_date(self, data):
175        value = u'%04d-%02d-%02d' % (data.year, data.month, data.day)
176        return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value)
177
178    def represent_datetime(self, data):
179        value = u'%04d-%02d-%02d %02d:%02d:%02d' \
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())
186        return self.represent_scalar(u'tag:yaml.org,2002:timestamp', value)
187
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)
201
202    def represent_undefined(self, data):
203        raise RepresenterError("cannot represent an object: %s" % data)
204
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.