2 __all__
= ['BaseRepresenter', 'SafeRepresenter', 'Representer',
10 datetime_available
= True
12 datetime_available
= False
17 from sets
import Set
as set
21 class RepresenterError(YAMLError
):
24 class BaseRepresenter(object):
26 yaml_representers
= {}
27 yaml_multi_representers
= {}
29 def __init__(self
, default_style
=None, default_flow_style
=None):
30 self
.default_style
= default_style
31 self
.default_flow_style
= default_flow_style
32 self
.represented_objects
= {}
33 self
.object_keeper
= []
36 def represent(self
, data
):
37 node
= self
.represent_data(data
)
39 self
.represented_objects
= {}
40 self
.object_keeper
= []
47 classobj_type
= type(C
)
48 instance_type
= type(c
)
49 function_type
= type(f
)
50 generator_type
= type(g())
51 builtin_function_type
= type(abs)
52 module_type
= type(sys
)
55 def get_classobj_bases(self
, cls
):
57 for base
in cls
.__bases
__:
58 bases
.extend(self
.get_classobj_bases(base
))
61 def represent_data(self
, data
):
62 if self
.ignore_aliases(data
):
65 self
.alias_key
= id(data
)
66 if self
.alias_key
is not None:
67 if self
.alias_key
in self
.represented_objects
:
68 node
= self
.represented_objects
[self
.alias_key
]
70 # raise RepresenterError("recursive objects are not allowed: %r" % data)
72 #self.represented_objects[alias_key] = None
73 self
.object_keeper
.append(data
)
74 data_types
= type(data
).__mro
__
75 if type(data
) is self
.instance_type
:
76 data_types
= self
.get_classobj_bases(data
.__class
__)+list(data_types
)
77 if data_types
[0] in self
.yaml_representers
:
78 node
= self
.yaml_representers
[data_types
[0]](self
, data
)
80 for data_type
in data_types
:
81 if data_type
in self
.yaml_multi_representers
:
82 node
= self
.yaml_multi_representers
[data_type
](self
, data
)
85 if None in self
.yaml_multi_representers
:
86 node
= self
.yaml_multi_representers
[None](self
, data
)
87 elif None in self
.yaml_representers
:
88 node
= self
.yaml_representers
[None](self
, data
)
90 node
= ScalarNode(None, unicode(data
))
91 #if alias_key is not None:
92 # self.represented_objects[alias_key] = node
95 def add_representer(cls
, data_type
, representer
):
96 if not 'yaml_representers' in cls
.__dict
__:
97 cls
.yaml_representers
= cls
.yaml_representers
.copy()
98 cls
.yaml_representers
[data_type
] = representer
99 add_representer
= classmethod(add_representer
)
101 def add_multi_representer(cls
, data_type
, representer
):
102 if not 'yaml_multi_representers' in cls
.__dict
__:
103 cls
.yaml_multi_representers
= cls
.yaml_multi_representers
.copy()
104 cls
.yaml_multi_representers
[data_type
] = representer
105 add_multi_representer
= classmethod(add_multi_representer
)
107 def represent_scalar(self
, tag
, value
, style
=None):
109 style
= self
.default_style
110 node
= ScalarNode(tag
, value
, style
=style
)
111 if self
.alias_key
is not None:
112 self
.represented_objects
[self
.alias_key
] = node
115 def represent_sequence(self
, tag
, sequence
, flow_style
=None):
117 node
= SequenceNode(tag
, value
, flow_style
=flow_style
)
118 if self
.alias_key
is not None:
119 self
.represented_objects
[self
.alias_key
] = node
121 for item
in sequence
:
122 node_item
= self
.represent_data(item
)
123 if not (isinstance(node_item
, ScalarNode
) and not node_item
.style
):
125 value
.append(node_item
)
126 if flow_style
is None:
127 if self
.default_flow_style
is not None:
128 node
.flow_style
= self
.default_flow_style
130 node
.flow_style
= best_style
133 def represent_mapping(self
, tag
, mapping
, flow_style
=None):
135 node
= MappingNode(tag
, value
, flow_style
=flow_style
)
136 if self
.alias_key
is not None:
137 self
.represented_objects
[self
.alias_key
] = node
139 if hasattr(mapping
, 'items'):
140 mapping
= mapping
.items()
142 for item_key
, item_value
in mapping
:
143 node_key
= self
.represent_data(item_key
)
144 node_value
= self
.represent_data(item_value
)
145 if not (isinstance(node_key
, ScalarNode
) and not node_key
.style
):
147 if not (isinstance(node_value
, ScalarNode
) and not node_value
.style
):
149 value
.append((node_key
, node_value
))
150 if flow_style
is None:
151 if self
.default_flow_style
is not None:
152 node
.flow_style
= self
.default_flow_style
154 node
.flow_style
= best_style
157 def ignore_aliases(self
, data
):
160 class SafeRepresenter(BaseRepresenter
):
162 def ignore_aliases(self
, data
):
163 if data
in [None, ()]:
165 if isinstance(data
, (str, unicode, bool, int, float)):
168 def represent_none(self
, data
):
169 return self
.represent_scalar(u
'tag:yaml.org,2002:null',
172 def represent_str(self
, data
):
176 data
= unicode(data
, 'ascii')
177 tag
= u
'tag:yaml.org,2002:str'
178 except UnicodeDecodeError:
180 data
= unicode(data
, 'utf-8')
181 tag
= u
'tag:yaml.org,2002:str'
182 except UnicodeDecodeError:
183 data
= data
.encode('base64')
184 tag
= u
'tag:yaml.org,2002:binary'
186 return self
.represent_scalar(tag
, data
, style
=style
)
188 def represent_unicode(self
, data
):
189 return self
.represent_scalar(u
'tag:yaml.org,2002:str', data
)
191 def represent_bool(self
, data
):
196 return self
.represent_scalar(u
'tag:yaml.org,2002:bool', value
)
198 def represent_int(self
, data
):
199 return self
.represent_scalar(u
'tag:yaml.org,2002:int', unicode(data
))
201 def represent_long(self
, data
):
202 return self
.represent_scalar(u
'tag:yaml.org,2002:int', unicode(data
))
205 while repr(inf_value
) != repr(inf_value
*inf_value
):
206 inf_value
*= inf_value
208 def represent_float(self
, data
):
209 if data
!= data
or (data
== 0.0 and data
== 1.0):
211 elif data
== self
.inf_value
:
213 elif data
== -self
.inf_value
:
216 value
= unicode(repr(data
))
217 return self
.represent_scalar(u
'tag:yaml.org,2002:float', value
)
219 def represent_list(self
, data
):
220 #pairs = (len(data) > 0 and isinstance(data, list))
223 # if not isinstance(item, tuple) or len(item) != 2:
227 return self
.represent_sequence(u
'tag:yaml.org,2002:seq', data
)
229 #for item_key, item_value in data:
230 # value.append(self.represent_mapping(u'tag:yaml.org,2002:map',
231 # [(item_key, item_value)]))
232 #return SequenceNode(u'tag:yaml.org,2002:pairs', value)
234 def represent_dict(self
, data
):
235 return self
.represent_mapping(u
'tag:yaml.org,2002:map', data
)
237 def represent_set(self
, data
):
241 return self
.represent_mapping(u
'tag:yaml.org,2002:set', value
)
243 def represent_date(self
, data
):
244 value
= u
'%04d-%02d-%02d' % (data
.year
, data
.month
, data
.day
)
245 return self
.represent_scalar(u
'tag:yaml.org,2002:timestamp', value
)
247 def represent_datetime(self
, data
):
248 value
= u
'%04d-%02d-%02d %02d:%02d:%02d' \
249 % (data
.year
, data
.month
, data
.day
,
250 data
.hour
, data
.minute
, data
.second
)
252 value
+= u
'.' + unicode(data
.microsecond
/1000000.0).split(u
'.')[1]
254 value
+= unicode(data
.utcoffset())
255 return self
.represent_scalar(u
'tag:yaml.org,2002:timestamp', value
)
257 def represent_yaml_object(self
, tag
, data
, cls
, flow_style
=None):
258 if hasattr(data
, '__getstate__'):
259 state
= data
.__getstate
__()
261 state
= data
.__dict
__.copy()
262 return self
.represent_mapping(tag
, state
, flow_style
=flow_style
)
264 def represent_undefined(self
, data
):
265 raise RepresenterError("cannot represent an object: %s" % data
)
267 SafeRepresenter
.add_representer(type(None),
268 SafeRepresenter
.represent_none
)
270 SafeRepresenter
.add_representer(str,
271 SafeRepresenter
.represent_str
)
273 SafeRepresenter
.add_representer(unicode,
274 SafeRepresenter
.represent_unicode
)
276 SafeRepresenter
.add_representer(bool,
277 SafeRepresenter
.represent_bool
)
279 SafeRepresenter
.add_representer(int,
280 SafeRepresenter
.represent_int
)
282 SafeRepresenter
.add_representer(long,
283 SafeRepresenter
.represent_long
)
285 SafeRepresenter
.add_representer(float,
286 SafeRepresenter
.represent_float
)
288 SafeRepresenter
.add_representer(list,
289 SafeRepresenter
.represent_list
)
291 SafeRepresenter
.add_representer(tuple,
292 SafeRepresenter
.represent_list
)
294 SafeRepresenter
.add_representer(dict,
295 SafeRepresenter
.represent_dict
)
297 SafeRepresenter
.add_representer(set,
298 SafeRepresenter
.represent_set
)
300 if datetime_available
:
301 SafeRepresenter
.add_representer(datetime
.date
,
302 SafeRepresenter
.represent_date
)
303 SafeRepresenter
.add_representer(datetime
.datetime
,
304 SafeRepresenter
.represent_datetime
)
306 SafeRepresenter
.add_representer(None,
307 SafeRepresenter
.represent_undefined
)
309 class Representer(SafeRepresenter
):
311 def represent_str(self
, data
):
315 data
= unicode(data
, 'ascii')
316 tag
= u
'tag:yaml.org,2002:str'
317 except UnicodeDecodeError:
319 data
= unicode(data
, 'utf-8')
320 tag
= u
'tag:yaml.org,2002:python/str'
321 except UnicodeDecodeError:
322 data
= data
.encode('base64')
323 tag
= u
'tag:yaml.org,2002:binary'
325 return self
.represent_scalar(tag
, data
, style
=style
)
327 def represent_unicode(self
, data
):
331 tag
= u
'tag:yaml.org,2002:python/unicode'
332 except UnicodeEncodeError:
333 tag
= u
'tag:yaml.org,2002:str'
334 return self
.represent_scalar(tag
, data
)
336 def represent_long(self
, data
):
337 tag
= u
'tag:yaml.org,2002:int'
338 if int(data
) is not data
:
339 tag
= u
'tag:yaml.org,2002:python/long'
340 return self
.represent_scalar(tag
, unicode(data
))
342 def represent_complex(self
, data
):
344 data
= u
'%r' % data
.real
345 elif data
.real
== 0.0:
346 data
= u
'%rj' % data
.imag
348 data
= u
'%r+%rj' % (data
.real
, data
.imag
)
350 data
= u
'%r%rj' % (data
.real
, data
.imag
)
351 return self
.represent_scalar(u
'tag:yaml.org,2002:python/complex', data
)
353 def represent_tuple(self
, data
):
354 return self
.represent_sequence(u
'tag:yaml.org,2002:python/tuple', data
)
356 def represent_name(self
, data
):
357 name
= u
'%s.%s' % (data
.__module
__, data
.__name
__)
358 return self
.represent_scalar(u
'tag:yaml.org,2002:python/name:'+name
, u
'')
360 def represent_module(self
, data
):
361 return self
.represent_scalar(
362 u
'tag:yaml.org,2002:python/module:'+data
.__name
__, u
'')
364 def represent_instance(self
, data
):
365 # For instances of classic classes, we use __getinitargs__ and
366 # __getstate__ to serialize the data.
368 # If data.__getinitargs__ exists, the object must be reconstructed by
369 # calling cls(**args), where args is a tuple returned by
370 # __getinitargs__. Otherwise, the cls.__init__ method should never be
371 # called and the class instance is created by instantiating a trivial
372 # class and assigning to the instance's __class__ variable.
374 # If data.__getstate__ exists, it returns the state of the object.
375 # Otherwise, the state of the object is data.__dict__.
377 # We produce either a !!python/object or !!python/object/new node.
378 # If data.__getinitargs__ does not exist and state is a dictionary, we
379 # produce a !!python/object node . Otherwise we produce a
380 # !!python/object/new node.
383 class_name
= u
'%s.%s' % (cls
.__module
__, cls
.__name
__)
386 if hasattr(data
, '__getinitargs__'):
387 args
= list(data
.__getinitargs
__())
388 if hasattr(data
, '__getstate__'):
389 state
= data
.__getstate
__()
391 state
= data
.__dict
__
392 if args
is None and isinstance(state
, dict):
393 return self
.represent_mapping(
394 u
'tag:yaml.org,2002:python/object:'+class_name
, state
)
395 if isinstance(state
, dict) and not state
:
396 return self
.represent_sequence(
397 u
'tag:yaml.org,2002:python/object/new:'+class_name
, args
)
401 value
['state'] = state
402 return self
.represent_mapping(
403 u
'tag:yaml.org,2002:python/object/new:'+class_name
, value
)
405 def represent_object(self
, data
):
406 # We use __reduce__ API to save the data. data.__reduce__ returns
407 # a tuple of length 2-5:
408 # (function, args, state, listitems, dictitems)
410 # For reconstructing, we calls function(*args), then set its state,
411 # listitems, and dictitems if they are not None.
413 # A special case is when function.__name__ == '__newobj__'. In this
414 # case we create the object with args[0].__new__(*args).
416 # Another special case is when __reduce__ returns a string - we don't
419 # We produce a !!python/object, !!python/object/new or
420 # !!python/object/apply node.
423 if cls
in copy_reg
.dispatch_table
:
424 reduce = copy_reg
.dispatch_table
[cls
](data
)
425 elif hasattr(data
, '__reduce_ex__'):
426 reduce = data
.__reduce
_ex
__(2)
427 elif hasattr(data
, '__reduce__'):
428 reduce = data
.__reduce
__()
430 raise RepresenterError("cannot represent object: %r" % data
)
431 reduce = (list(reduce)+[None]*5)[:5]
432 function
, args
, state
, listitems
, dictitems
= reduce
436 if listitems
is not None:
437 listitems
= list(listitems
)
438 if dictitems
is not None:
439 dictitems
= dict(dictitems
)
440 if function
.__name
__ == '__newobj__':
443 tag
= u
'tag:yaml.org,2002:python/object/new:'
446 tag
= u
'tag:yaml.org,2002:python/object/apply:'
448 function_name
= u
'%s.%s' % (function
.__module
__, function
.__name
__)
449 if not args
and not listitems
and not dictitems \
450 and isinstance(state
, dict) and newobj
:
451 return self
.represent_mapping(
452 u
'tag:yaml.org,2002:python/object:'+function_name
, state
)
453 if not listitems
and not dictitems \
454 and isinstance(state
, dict) and not state
:
455 return self
.represent_sequence(tag
+function_name
, args
)
459 if state
or not isinstance(state
, dict):
460 value
['state'] = state
462 value
['listitems'] = listitems
464 value
['dictitems'] = dictitems
465 return self
.represent_mapping(tag
+function_name
, value
)
467 Representer
.add_representer(str,
468 Representer
.represent_str
)
470 Representer
.add_representer(unicode,
471 Representer
.represent_unicode
)
473 Representer
.add_representer(long,
474 Representer
.represent_long
)
476 Representer
.add_representer(complex,
477 Representer
.represent_complex
)
479 Representer
.add_representer(tuple,
480 Representer
.represent_tuple
)
482 Representer
.add_representer(type,
483 Representer
.represent_name
)
485 Representer
.add_representer(Representer
.classobj_type
,
486 Representer
.represent_name
)
488 Representer
.add_representer(Representer
.function_type
,
489 Representer
.represent_name
)
491 Representer
.add_representer(Representer
.builtin_function_type
,
492 Representer
.represent_name
)
494 Representer
.add_representer(Representer
.module_type
,
495 Representer
.represent_module
)
497 Representer
.add_multi_representer(Representer
.instance_type
,
498 Representer
.represent_instance
)
500 Representer
.add_multi_representer(object,
501 Representer
.represent_object
)