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

Revision 137, 7.9 KB checked in by xi, 9 years ago (diff)

Refactor resolver.

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