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
:
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
= {}
34 def represent(self
, data
):
35 node
= self
.represent_data(data
)
37 self
.represented_objects
= {}
42 classobj_type
= type(C
)
43 instance_type
= type(c
)
44 function_type
= type(f
)
45 builtin_function_type
= type(abs)
46 module_type
= type(sys
)
49 def get_classobj_bases(self
, cls
):
51 for base
in cls
.__bases
__:
52 bases
.extend(self
.get_classobj_bases(base
))
55 def represent_data(self
, data
):
56 if self
.ignore_aliases(data
):
60 if alias_key
is not None:
61 if alias_key
in self
.represented_objects
:
62 node
= self
.represented_objects
[alias_key
]
64 raise RepresenterError("recursive objects are not allowed: %r" % data
)
66 self
.represented_objects
[alias_key
] = None
67 data_types
= type(data
).__mro
__
68 if type(data
) is self
.instance_type
:
69 data_types
= self
.get_classobj_bases(data
.__class
__)+list(data_types
)
70 if data_types
[0] in self
.yaml_representers
:
71 node
= self
.yaml_representers
[data_types
[0]](self
, data
)
73 for data_type
in data_types
:
74 if data_type
in self
.yaml_multi_representers
:
75 node
= self
.yaml_multi_representers
[data_type
](self
, data
)
78 if None in self
.yaml_multi_representers
:
79 node
= self
.yaml_multi_representers
[None](self
, data
)
80 elif None in self
.yaml_representers
:
81 node
= self
.yaml_representers
[None](self
, data
)
83 node
= ScalarNode(None, unicode(data
))
84 if alias_key
is not None:
85 self
.represented_objects
[alias_key
] = node
88 def add_representer(cls
, data_type
, representer
):
89 if not 'yaml_representers' in cls
.__dict
__:
90 cls
.yaml_representers
= cls
.yaml_representers
.copy()
91 cls
.yaml_representers
[data_type
] = representer
92 add_representer
= classmethod(add_representer
)
94 def add_multi_representer(cls
, data_type
, representer
):
95 if not 'yaml_multi_representers' in cls
.__dict
__:
96 cls
.yaml_multi_representers
= cls
.yaml_multi_representers
.copy()
97 cls
.yaml_multi_representers
[data_type
] = representer
98 add_multi_representer
= classmethod(add_multi_representer
)
100 def represent_scalar(self
, tag
, value
, style
=None):
102 style
= self
.default_style
103 return ScalarNode(tag
, value
, style
=style
)
105 def represent_sequence(self
, tag
, sequence
, flow_style
=None):
108 for item
in sequence
:
109 node_item
= self
.represent_data(item
)
110 if not (isinstance(node_item
, ScalarNode
) and not node_item
.style
):
112 value
.append(self
.represent_data(item
))
113 if flow_style
is None:
114 flow_style
= self
.default_flow_style
115 if flow_style
is None:
116 flow_style
= best_style
117 return SequenceNode(tag
, value
, flow_style
=flow_style
)
119 def represent_mapping(self
, tag
, mapping
, flow_style
=None):
121 if hasattr(mapping
, 'keys'):
123 for item_key
in mapping
.keys():
124 item_value
= mapping
[item_key
]
125 node_key
= self
.represent_data(item_key
)
126 node_value
= self
.represent_data(item_value
)
127 if not (isinstance(node_key
, ScalarNode
) and not node_key
.style
):
129 if not (isinstance(node_value
, ScalarNode
) and not node_value
.style
):
131 value
[node_key
] = node_value
134 for item_key
, item_value
in mapping
:
135 node_key
= self
.represent_data(item_key
)
136 node_value
= self
.represent_data(item_value
)
137 if not (isinstance(node_key
, ScalarNode
) and not node_key
.style
):
139 if not (isinstance(node_value
, ScalarNode
) and not node_value
.style
):
141 value
.append((node_key
, node_value
))
142 if flow_style
is None:
143 flow_style
= self
.default_flow_style
144 if flow_style
is None:
145 flow_style
= best_style
146 return MappingNode(tag
, value
, flow_style
=flow_style
)
148 def ignore_aliases(self
, data
):
151 class SafeRepresenter(BaseRepresenter
):
153 def ignore_aliases(self
, data
):
154 if data
in [None, ()]:
156 if isinstance(data
, (str, unicode, bool, int, float)):
159 def represent_none(self
, data
):
160 return self
.represent_scalar(u
'tag:yaml.org,2002:null',
163 def represent_str(self
, data
):
167 data
= unicode(data
, 'ascii')
168 tag
= u
'tag:yaml.org,2002:str'
169 except UnicodeDecodeError:
171 data
= unicode(data
, 'utf-8')
172 tag
= u
'tag:yaml.org,2002:str'
173 except UnicodeDecodeError:
174 data
= data
.encode('base64')
175 tag
= u
'tag:yaml.org,2002:binary'
177 return self
.represent_scalar(tag
, data
, style
=style
)
179 def represent_unicode(self
, data
):
180 return self
.represent_scalar(u
'tag:yaml.org,2002:str', data
)
182 def represent_bool(self
, data
):
187 return self
.represent_scalar(u
'tag:yaml.org,2002:bool', value
)
189 def represent_int(self
, data
):
190 return self
.represent_scalar(u
'tag:yaml.org,2002:int', unicode(data
))
192 def represent_long(self
, data
):
193 return self
.represent_scalar(u
'tag:yaml.org,2002:int', unicode(data
))
196 while repr(inf_value
) != repr(inf_value
*inf_value
):
197 inf_value
*= inf_value
199 def represent_float(self
, data
):
200 if data
!= data
or (data
== 0.0 and data
== 1.0):
202 elif data
== self
.inf_value
:
204 elif data
== -self
.inf_value
:
207 value
= unicode(repr(data
))
208 return self
.represent_scalar(u
'tag:yaml.org,2002:float', value
)
210 def represent_list(self
, data
):
211 pairs
= (len(data
) > 0 and isinstance(data
, list))
214 if not isinstance(item
, tuple) or len(item
) != 2:
218 return self
.represent_sequence(u
'tag:yaml.org,2002:seq', data
)
220 for item_key
, item_value
in data
:
221 value
.append(self
.represent_mapping(u
'tag:yaml.org,2002:map',
222 [(item_key
, item_value
)]))
223 return SequenceNode(u
'tag:yaml.org,2002:pairs', value
)
225 def represent_dict(self
, data
):
226 return self
.represent_mapping(u
'tag:yaml.org,2002:map', data
)
228 def represent_set(self
, data
):
232 return self
.represent_mapping(u
'tag:yaml.org,2002:set', value
)
234 def represent_date(self
, data
):
235 value
= u
'%04d-%02d-%02d' % (data
.year
, data
.month
, data
.day
)
236 return self
.represent_scalar(u
'tag:yaml.org,2002:timestamp', value
)
238 def represent_datetime(self
, data
):
239 value
= u
'%04d-%02d-%02d %02d:%02d:%02d' \
240 % (data
.year
, data
.month
, data
.day
,
241 data
.hour
, data
.minute
, data
.second
)
243 value
+= u
'.' + unicode(data
.microsecond
/1000000.0).split(u
'.')[1]
245 value
+= unicode(data
.utcoffset())
246 return self
.represent_scalar(u
'tag:yaml.org,2002:timestamp', value
)
248 def represent_yaml_object(self
, tag
, data
, cls
, flow_style
=None):
249 if hasattr(data
, '__getstate__'):
250 state
= data
.__getstate
__()
252 state
= data
.__dict
__.copy()
253 if isinstance(state
, dict):
254 state
= state
.items()
256 return self
.represent_mapping(tag
, state
, flow_style
=flow_style
)
258 def represent_undefined(self
, data
):
259 raise RepresenterError("cannot represent an object: %s" % data
)
261 SafeRepresenter
.add_representer(type(None),
262 SafeRepresenter
.represent_none
)
264 SafeRepresenter
.add_representer(str,
265 SafeRepresenter
.represent_str
)
267 SafeRepresenter
.add_representer(unicode,
268 SafeRepresenter
.represent_unicode
)
270 SafeRepresenter
.add_representer(bool,
271 SafeRepresenter
.represent_bool
)
273 SafeRepresenter
.add_representer(int,
274 SafeRepresenter
.represent_int
)
276 SafeRepresenter
.add_representer(long,
277 SafeRepresenter
.represent_long
)
279 SafeRepresenter
.add_representer(float,
280 SafeRepresenter
.represent_float
)
282 SafeRepresenter
.add_representer(list,
283 SafeRepresenter
.represent_list
)
285 SafeRepresenter
.add_representer(tuple,
286 SafeRepresenter
.represent_list
)
288 SafeRepresenter
.add_representer(dict,
289 SafeRepresenter
.represent_dict
)
291 SafeRepresenter
.add_representer(set,
292 SafeRepresenter
.represent_set
)
294 if datetime_available
:
295 SafeRepresenter
.add_representer(datetime
.date
,
296 SafeRepresenter
.represent_date
)
297 SafeRepresenter
.add_representer(datetime
.datetime
,
298 SafeRepresenter
.represent_datetime
)
300 SafeRepresenter
.add_representer(None,
301 SafeRepresenter
.represent_undefined
)
303 class Representer(SafeRepresenter
):
305 def represent_str(self
, data
):
309 data
= unicode(data
, 'ascii')
310 tag
= u
'tag:yaml.org,2002:str'
311 except UnicodeDecodeError:
313 data
= unicode(data
, 'utf-8')
314 tag
= u
'tag:yaml.org,2002:python/str'
315 except UnicodeDecodeError:
316 data
= data
.encode('base64')
317 tag
= u
'tag:yaml.org,2002:binary'
319 return self
.represent_scalar(tag
, data
, style
=style
)
321 def represent_unicode(self
, data
):
325 tag
= u
'tag:yaml.org,2002:python/unicode'
326 except UnicodeEncodeError:
327 tag
= u
'tag:yaml.org,2002:str'
328 return self
.represent_scalar(tag
, data
)
330 def represent_long(self
, data
):
331 tag
= u
'tag:yaml.org,2002:int'
332 if int(data
) is not data
:
333 tag
= u
'tag:yaml.org,2002:python/long'
334 return self
.represent_scalar(tag
, unicode(data
))
336 def represent_complex(self
, data
):
338 data
= u
'%r' % data
.real
339 elif data
.real
== 0.0:
340 data
= u
'%rj' % data
.imag
342 data
= u
'%r+%rj' % (data
.real
, data
.imag
)
344 data
= u
'%r%rj' % (data
.real
, data
.imag
)
345 return self
.represent_scalar(u
'tag:yaml.org,2002:python/complex', data
)
347 def represent_tuple(self
, data
):
348 return self
.represent_sequence(u
'tag:yaml.org,2002:python/tuple', data
)
350 def represent_name(self
, data
):
351 name
= u
'%s.%s' % (data
.__module
__, data
.__name
__)
352 return self
.represent_scalar(u
'tag:yaml.org,2002:python/name:'+name
, u
'')
354 def represent_module(self
, data
):
355 return self
.represent_scalar(
356 u
'tag:yaml.org,2002:python/module:'+data
.__name
__, u
'')
358 def represent_instance(self
, data
):
359 # For instances of classic classes, we use __getinitargs__ and
360 # __getstate__ to serialize the data.
362 # If data.__getinitargs__ exists, the object must be reconstructed by
363 # calling cls(**args), where args is a tuple returned by
364 # __getinitargs__. Otherwise, the cls.__init__ method should never be
365 # called and the class instance is created by instantiating a trivial
366 # class and assigning to the instance's __class__ variable.
368 # If data.__getstate__ exists, it returns the state of the object.
369 # Otherwise, the state of the object is data.__dict__.
371 # We produce either a !!python/object or !!python/object/new node.
372 # If data.__getinitargs__ does not exist and state is a dictionary, we
373 # produce a !!python/object node . Otherwise we produce a
374 # !!python/object/new node.
377 class_name
= u
'%s.%s' % (cls
.__module
__, cls
.__name
__)
380 if hasattr(data
, '__getinitargs__'):
381 args
= list(data
.__getinitargs
__())
382 if hasattr(data
, '__getstate__'):
383 state
= data
.__getstate
__()
385 state
= data
.__dict
__
386 if args
is None and isinstance(state
, dict):
387 state
= state
.items()
389 return self
.represent_mapping(
390 u
'tag:yaml.org,2002:python/object:'+class_name
, state
)
391 if isinstance(state
, dict) and not state
:
392 return self
.represent_sequence(
393 u
'tag:yaml.org,2002:python/object/new:'+class_name
, args
)
397 value
['state'] = state
398 return self
.represent_mapping(
399 u
'tag:yaml.org,2002:python/object/new:'+class_name
, value
)
401 def represent_object(self
, data
):
402 # We use __reduce__ API to save the data. data.__reduce__ returns
403 # a tuple of length 2-5:
404 # (function, args, state, listitems, dictitems)
406 # For reconstructing, we calls function(*args), then set its state,
407 # listitems, and dictitems if they are not None.
409 # A special case is when function.__name__ == '__newobj__'. In this
410 # case we create the object with args[0].__new__(*args).
412 # Another special case is when __reduce__ returns a string - we don't
415 # We produce a !!python/object, !!python/object/new or
416 # !!python/object/apply node.
419 if cls
in copy_reg
.dispatch_table
:
420 reduce = copy_reg
.dispatch_table
[cls
](data
)
421 elif hasattr(data
, '__reduce_ex__'):
422 reduce = data
.__reduce
_ex
__(2)
423 elif hasattr(data
, '__reduce__'):
424 reduce = data
.__reduce
__()
426 raise RepresenterError("cannot represent object: %r" % data
)
427 reduce = (list(reduce)+[None]*5)[:5]
428 function
, args
, state
, listitems
, dictitems
= reduce
432 if listitems
is not None:
433 listitems
= list(listitems
)
434 if dictitems
is not None:
435 dictitems
= dict(dictitems
)
436 if function
.__name
__ == '__newobj__':
439 tag
= u
'tag:yaml.org,2002:python/object/new:'
442 tag
= u
'tag:yaml.org,2002:python/object/apply:'
444 function_name
= u
'%s.%s' % (function
.__module
__, function
.__name
__)
445 if not args
and not listitems
and not dictitems \
446 and isinstance(state
, dict) and newobj
:
447 state
= state
.items()
449 return self
.represent_mapping(
450 u
'tag:yaml.org,2002:python/object:'+function_name
, state
)
451 if not listitems
and not dictitems \
452 and isinstance(state
, dict) and not state
:
453 return self
.represent_sequence(tag
+function_name
, args
)
457 if state
or not isinstance(state
, dict):
458 value
['state'] = state
460 value
['listitems'] = listitems
462 value
['dictitems'] = dictitems
463 return self
.represent_mapping(tag
+function_name
, value
)
465 Representer
.add_representer(str,
466 Representer
.represent_str
)
468 Representer
.add_representer(unicode,
469 Representer
.represent_unicode
)
471 Representer
.add_representer(long,
472 Representer
.represent_long
)
474 Representer
.add_representer(complex,
475 Representer
.represent_complex
)
477 Representer
.add_representer(tuple,
478 Representer
.represent_tuple
)
480 Representer
.add_representer(type,
481 Representer
.represent_name
)
483 Representer
.add_representer(Representer
.classobj_type
,
484 Representer
.represent_name
)
486 Representer
.add_representer(Representer
.function_type
,
487 Representer
.represent_name
)
489 Representer
.add_representer(Representer
.builtin_function_type
,
490 Representer
.represent_name
)
492 Representer
.add_representer(Representer
.module_type
,
493 Representer
.represent_module
)
495 Representer
.add_multi_representer(Representer
.instance_type
,
496 Representer
.represent_instance
)
498 Representer
.add_multi_representer(object,
499 Representer
.represent_object
)