source: trunk/lib/syck/dumpers.py @ 25

Revision 25, 11.0 KB checked in by xi, 9 years ago (diff)

Adding some docstrings.

Line 
1"""
2syck.dumpers is a high-level wrapper for the Syck YAML emitter.
3Do not use it directly, use the module 'syck' instead.
4"""
5
6import _syck
7
8try:
9    import cStringIO as StringIO
10except ImportError:
11    import StringIO
12
13__all__ = ['GenericDumper', 'Dumper',
14    'emit', 'dump', 'emit_documents', 'dump_documents']
15
16class GenericDumper(_syck.Emitter):
17    """
18    GenericDumper dumps native Python objects into YAML documents.
19    """
20
21    def dump(self, object):
22        """Dumps the given Python object as a YAML document."""
23        self.emit(self._convert(object, {}))
24
25    def _convert(self, object, object_to_node):
26        if id(object) in object_to_node and self.allow_aliases(object):
27            return object_to_node[id(object)][1]
28        node = self.represent(object)
29        object_to_node[id(object)] = object, node
30        if node.kind == 'seq':
31            for index in range(len(node.value)):
32                item = node.value[index]
33                node.value[index] = self._convert(item, object_to_node)
34        elif node.kind == 'map':
35            if isinstance(node.value, dict):
36                for key in node.value.keys():
37                    value = node.value[key]
38                    del node.value[key]
39                    node.value[self._convert(key, object_to_node)] =    \
40                            self._convert(value, object_to_node)
41            elif isinstance(node.value, list):
42                for index in range(len(node.value)):
43                    key, value = node.value[index]
44                    node.value[index] = (self._convert(key, object_to_node),
45                            self._convert(value, object_to_node))
46#        # Workaround against a Syck bug:
47#        if node.kind == 'scalar' and node.style not in ['1quote', '2quote'] \
48#                and node.value and node.value[-1] in [' ', '\t']:
49#            node.style = '2quote'
50        return node
51
52    def represent(self, object):
53        """Represents the given Python object as a 'Node'."""
54        if isinstance(object, dict):
55            return _syck.Map(object.copy(), tag="tag:yaml.org,2002:map")
56        elif isinstance(object, list):
57            return _syck.Seq(object[:], tag="tag:yaml.org,2002:seq")
58        else:
59            return _syck.Scalar(str(object), tag="tag:yaml.org,2002:str")
60
61    def allow_aliases(self, object):
62        """Checks whether the given object can be aliased."""
63        return True
64
65class Dumper(GenericDumper):
66    """
67    Dumper dumps native Python objects into YAML documents.
68    """
69
70    INF = 1e300000
71    inf_value = repr(INF)
72    neginf_value = repr(-INF)
73    nan_value = repr(INF/INF)
74
75    def find_representer(self, object):
76        """
77        For the given object, find a method that can represent it as a 'Node'
78        object.
79
80        If the type of the object has the form 'package.module.type',
81        find_representer() returns the method 'represent_package_module_type'.
82        If this method does not exist, it checks the base types.
83        """
84        for object_type in type(object).__mro__:
85            if object_type.__module__ == '__builtin__':
86                name = object_type.__name__
87            else:
88                name = '%s.%s' % (object_type.__module__, object_type.__name__)
89            method = 'represent_' + name.replace('.', '_')
90            if hasattr(self, method):
91                return getattr(self, method)
92
93    def represent(self, object):
94        """Represents the given Python object as a 'Node'."""
95        representer = self.find_representer(object)
96        if representer:
97            return representer(object)
98        else:
99            return super(Dumper, self).represent(object)
100
101    def represent_object(self, object):
102        return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:str")
103
104    def represent_NoneType(self, object):
105        return _syck.Scalar('~', tag="tag:yaml.org,2002:null")
106
107    def represent_bool(self, object):
108        return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:bool")
109
110    def represent_str(self, object):
111        return _syck.Scalar(str(object), tag="tag:yaml.org,2002:str")
112
113    def represent_list(self, object):
114        return _syck.Seq(object[:], tag="tag:yaml.org,2002:seq")
115
116    def represent_dict(self, object):
117        return _syck.Map(object.copy(), tag="tag:yaml.org,2002:map")
118
119    def represent_int(self, object):
120        return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:int")
121
122    def represent_float(self, object):
123        value = repr(object)
124        if value == self.inf_value:
125            value = '.inf'
126        elif value == self.neginf_value:
127            value = '-.inf'
128        elif value == self.nan_value:
129            value = '.nan'
130        return _syck.Scalar(value, tag="tag:yaml.org,2002:float")
131
132    def represent_sets_Set(self, object):
133        return _syck.Seq(list(object), tag="tag:yaml.org,2002:set")
134    represent_set = represent_sets_Set
135
136    def represent_datetime_datetime(self, object):
137        return _syck.Scalar(object.isoformat(), tag="tag:yaml.org,2002:timestamp")
138
139    def represent_long(self, object):
140        return _syck.Scalar(repr(object), tag="tag:python.yaml.org,2002:long")
141
142    def represent_unicode(self, object):
143        return _syck.Scalar(object.encode('utf-8'), tag="tag:python.yaml.org,2002:unicode")
144
145    def represent_tuple(self, object):
146        return _syck.Seq(list(object), tag="tag:python.yaml.org,2002:tuple")
147
148    def represent_type(self, object):
149        name = '%s.%s' % (object.__module__, object.__name__)
150        return _syck.Scalar('', tag="tag:python.yaml.org,2002:name:"+name)
151    represent_classobj = represent_type
152    represent_class = represent_type
153    # TODO: Python 2.2 does not provide the module name of a function
154    represent_function = represent_type
155    represent_builtin_function_or_method = represent_type
156
157    def represent_instance(self, object):
158        cls = object.__class__
159        class_name = '%s.%s' % (cls.__module__, cls.__name__)
160        args = ()
161        state = {}
162        if hasattr(object, '__getinitargs__'):
163            args = object.__getinitargs__()
164        if hasattr(object, '__getstate__'):
165            state = object.__getstate__()
166        elif not hasattr(object, '__getinitargs__'):
167            state = object.__dict__.copy()
168        if not args and isinstance(state, dict):
169            return _syck.Map(state.copy(),
170                    tag="tag:python.yaml.org,2002:object:"+class_name)
171        value = {}
172        if args:
173            value['args'] = list(args)
174        if state or not isinstance(state, dict):
175            value['state'] = state
176        return _syck.Map(value,
177                tag="tag:python.yaml.org,2002:new:"+class_name)
178
179    def represent_object(self, object): # Do you understand this? I don't.
180        cls = type(object)
181        class_name = '%s.%s' % (cls.__module__, cls.__name__)
182        args = ()
183        state = {}
184        if cls.__reduce__ is type.__reduce__:
185            if hasattr(object, '__reduce_ex__'):
186                reduce = object.__reduce_ex__(2)
187                args = reduce[1][1:]
188            else:
189                reduce = object.__reduce__()
190            if len(reduce) > 2:
191                state = reduce[2]
192            if state is None:
193                state = {}
194            if not args and isinstance(state, dict):
195                return _syck.Map(state.copy(),
196                        tag="tag:python.yaml.org,2002:object:"+class_name)
197            if not state and isinstance(state, dict):
198                return _syck.Seq(list(args),
199                        tag="tag:python.yaml.org,2002:new:"+class_name)
200            value = {}
201            if args:
202                value['args'] = list(args)
203            if state or not isinstance(state, dict):
204                value['state'] = state
205            return _syck.Map(value,
206                    tag="tag:python.yaml.org,2002:new:"+class_name)
207        else:
208            reduce = object.__reduce__()
209            cls = reduce[0]
210            class_name = '%s.%s' % (cls.__module__, cls.__name__)
211            args = reduce[1]
212            state = None
213            if len(reduce) > 2:
214                state = reduce[2]
215            if state is None:
216                state = {}
217            if not state and isinstance(state, dict):
218                return _syck.Seq(list(args),
219                        tag="tag:python.yaml.org,2002:apply:"+class_name)
220            value = {}
221            if args:
222                value['args'] = list(args)
223            if state or not isinstance(state, dict):
224                value['state'] = state
225            return _syck.Map(value,
226                    tag="tag:python.yaml.org,2002:apply:"+class_name)
227
228    def represent__syck_Node(self, object):
229        object_type = type(object)
230        type_name = '%s.%s' % (object_type.__module__, object_type.__name__)
231        state = []
232        if hasattr(object_type, '__slotnames__'):
233            for name in object_type.__slotnames__:
234                value = getattr(object, name)
235                if value:
236                    state.append((name, value))
237        return _syck.Map(state,
238                tag="tag:python.yaml.org,2002:object:"+type_name)
239
240    def allow_aliases(self, object):
241        """Checks whether the given object can be aliased."""
242        if object is None or type(object) in [int, bool, float]:
243            return False
244        if type(object) is str and (not object or object.isalnum()):
245            return False
246        if type(object) is tuple and not object:
247            return False
248        return True
249
250def emit(node, output=None, Dumper=Dumper, **parameters):
251    """
252    Emits the given node to the output.
253
254    If output is None, returns the produced YAML document.
255    """
256    if output is None:
257        dumper = Dumper(StringIO.StringIO(), **parameters)
258    else:
259        dumper = Dumper(output, **parameters)
260    dumper.emit(node)
261    if output is None:
262        return dumper.output.getvalue()
263
264def dump(object, output=None, Dumper=Dumper, **parameters):
265    """
266    Dumps the given object to the output.
267
268    If output is None, returns the produced YAML document.
269    """
270    if output is None:
271        dumper = Dumper(StringIO.StringIO(), **parameters)
272    else:
273        dumper = Dumper(output, **parameters)
274    dumper.dump(object)
275    if output is None:
276        return dumper.output.getvalue()
277
278def emit_documents(nodes, output=None, Dumper=Dumper, **parameters):
279    """
280    Emits the list of nodes to the output.
281   
282    If output is None, returns the produced YAML document.
283    """
284    if output is None:
285        dumper = Dumper(StringIO.StringIO(), **parameters)
286    else:
287        dumper = Dumper(output, **parameters)
288    for node in nodes:
289        dumper.emit(node)
290    if output is None:
291        return dumper.output.getvalue()
292
293def dump_documents(objects, output=None, Dumper=Dumper, **parameters):
294    """
295    Dumps the list of objects to the output.
296   
297    If output is None, returns the produced YAML document.
298    """
299    if output is None:
300        dumper = Dumper(StringIO.StringIO(), **parameters)
301    else:
302        dumper = Dumper(output, **parameters)
303    for object in objects:
304        dumper.dump(object)
305    if output is None:
306        return dumper.output.getvalue()
307
308
Note: See TracBrowser for help on using the repository browser.