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

Revision 21, 8.6 KB checked in by xi, 9 years ago (diff)

Now it dumps and loads python objects!

Line 
1
2import _syck
3
4try:
5    import cStringIO as StringIO
6except ImportError:
7    import StringIO
8
9__all__ = ['GenericDumper', 'Dumper',
10    'emit', 'dump', 'emit_documents', 'dump_documents']
11
12INF = 1e300000
13NEGINF = -INF
14NAN = INF/INF
15
16
17class GenericDumper(_syck.Emitter):
18
19    def dump(self, object):
20        self.emit(self._convert(object, {}))
21
22    def _convert(self, object, object_to_node):
23        if id(object) in object_to_node and self.allow_aliases(object):
24            return object_to_node[id(object)][1]
25        node = self.represent(object)
26        object_to_node[id(object)] = object, node
27        if node.kind == 'seq':
28            for index, item in enumerate(node.value):
29                node.value[index] = self._convert(item, object_to_node)
30        elif node.kind == 'map':
31            for key in node.value.keys():
32                value = node.value[key]
33                del node.value[key]
34                node.value[self._convert(key, object_to_node)] =    \
35                        self._convert(value, object_to_node)
36#        # Workaround against a Syck bug:
37#        if node.kind == 'scalar' and node.style not in ['1quote', '2quote'] \
38#                and node.value and node.value[-1] in [' ', '\t']:
39#            node.style = '2quote'
40        return node
41
42    def represent(self, object):
43        if isinstance(object, dict):
44            return _syck.Map(object.copy(), tag="tag:yaml.org,2002:map")
45        elif isinstance(object, list):
46            return _syck.Seq(object[:], tag="tag:yaml.org,2002:seq")
47        else:
48            return _syck.Scalar(str(object), tag="tag:yaml.org,2002:str")
49
50    def allow_aliases(self, object):
51        return True
52
53class Dumper(GenericDumper):
54
55    def __init__(self, *args, **kwds):
56        super(Dumper, self).__init__(*args, **kwds)
57
58    def find_representer(self, object):
59        for object_type in type(object).__mro__:
60            if object_type.__module__ == '__builtin__':
61                name = object_type.__name__
62            else:
63                name = '%s.%s' % (object_type.__module__, object_type.__name__)
64            method = 'represent_' + name.replace('.', '_')
65            if hasattr(self, method):
66                return getattr(self, method)
67
68    def represent(self, object):
69        representer = self.find_representer(object)
70        if representer:
71            return representer(object)
72        else:
73            return super(Dumper, self).represent(object)
74
75    def represent_object(self, object):
76        return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:str")
77
78    def represent_NoneType(self, object):
79        return _syck.Scalar('~', tag="tag:yaml.org,2002:null")
80
81    def represent_bool(self, object):
82        return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:bool")
83
84    def represent_str(self, object):
85        return _syck.Scalar(str(object), tag="tag:yaml.org,2002:str")
86
87    def represent_list(self, object):
88        return _syck.Seq(object[:], tag="tag:yaml.org,2002:seq")
89
90    def represent_dict(self, object):
91        return _syck.Map(object.copy(), tag="tag:yaml.org,2002:map")
92
93    def represent_int(self, object):
94        return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:int")
95
96    def represent_float(self, object):
97        value = repr(object)
98        if value == repr(INF):
99            value = '.inf'
100        elif value == repr(NEGINF):
101            value = '-.inf'
102        elif value == repr(NAN):
103            value = '.nan'
104        return _syck.Scalar(value, tag="tag:yaml.org,2002:float")
105
106    def represent_sets_Set(self, object):
107        return _syck.Seq(list(object), tag="tag:yaml.org,2002:set")
108
109    def represent_datetime_datetime(self, object):
110        return _syck.Scalar(object.isoformat(), tag="tag:yaml.org,2002:timestamp")
111
112    def represent_long(self, object):
113        return _syck.Scalar(repr(object), tag="tag:python.yaml.org,2002:long")
114
115    def represent_unicode(self, object):
116        return _syck.Scalar(object.encode('utf-8'), tag="tag:python.yaml.org,2002:unicode")
117
118    def represent_tuple(self, object):
119        return _syck.Seq(list(object), tag="tag:python.yaml.org,2002:tuple")
120
121    def represent_type(self, object):
122        name = '%s.%s' % (object.__module__, object.__name__)
123        return _syck.Scalar('', tag="tag:python.yaml.org,2002:name:"+name)
124    represent_classobj = represent_type
125    represent_function = represent_type
126    represent_builtin_function_or_method = represent_type
127
128    def represent_instance(self, object):
129        cls = object.__class__
130        class_name = '%s.%s' % (cls.__module__, cls.__name__)
131        args = ()
132        state = {}
133        if hasattr(object, '__getinitargs__'):
134            args = object.__getinitargs__()
135        if hasattr(object, '__getstate__'):
136            state = object.__getstate__()
137        elif not hasattr(object, '__getinitargs__'):
138            state = object.__dict__.copy()
139        if not args and isinstance(state, dict):
140            return _syck.Map(state.copy(),
141                    tag="tag:python.yaml.org,2002:object:"+class_name)
142        value = {}
143        if args:
144            value['args'] = list(args)
145        if state or not isinstance(state, dict):
146            value['state'] = state
147        return _syck.Map(value,
148                tag="tag:python.yaml.org,2002:new:"+class_name)
149
150    def represent_object(self, object): # Do you understand this? I don't.
151        cls = type(object)
152        class_name = '%s.%s' % (cls.__module__, cls.__name__)
153        args = ()
154        if cls.__reduce__ is type.__reduce__:
155            if hasattr(object, '__reduce_ex__'):
156                reduce = object.__reduce_ex__(2)
157                args = reduce[1][1:]
158            else:
159                reduce = object.__reduce__()
160            if len(reduce) > 2:
161                state = reduce[2]
162            if state is None:
163                state = {}
164            if not args and isinstance(state, dict):
165                return _syck.Map(state.copy(),
166                        tag="tag:python.yaml.org,2002:object:"+class_name)
167            if not state and isinstance(state, dict):
168                return _syck.Seq(list(args),
169                        tag="tag:python.yaml.org,2002:new:"+class_name)
170            value = {}
171            if args:
172                value['args'] = list(args)
173            if state or not isinstance(state, dict):
174                value['state'] = state
175            return _syck.Map(value,
176                    tag="tag:python.yaml.org,2002:new:"+class_name)
177        else:
178            reduce = object.__reduce__()
179            cls = reduce[0]
180            class_name = '%s.%s' % (cls.__module__, cls.__name__)
181            args = reduce[1]
182            state = None
183            if len(reduce) > 2:
184                state = reduce[2]
185            if state is None:
186                state = {}
187            if not state and isinstance(state, dict):
188                return _syck.Seq(list(args),
189                        tag="tag:python.yaml.org,2002:apply:"+class_name)
190            value = {}
191            if args:
192                value['args'] = list(args)
193            if state or not isinstance(state, dict):
194                value['state'] = state
195            return _syck.Map(value,
196                    tag="tag:python.yaml.org,2002:apply:"+class_name)
197
198    def allow_aliases(self, object):
199        if object is None or type(object) in [int, bool, float]:
200            return False
201        if type(object) is str and (not object or object.isalnum()):
202            return False
203        if type(object) is tuple and not object:
204            return False
205        return True
206
207def emit(node, output=None, **parameters):
208    if output is None:
209        dumper = Dumper(StringIO.StringIO(), **parameters)
210    else:
211        dumper = Dumper(output, **parameters)
212    dumper.emit(node)
213    if output is None:
214        return dumper.output.getvalue()
215
216def dump(object, output=None, **parameters):
217    if output is None:
218        dumper = Dumper(StringIO.StringIO(), **parameters)
219    else:
220        dumper = Dumper(output, **parameters)
221    dumper.dump(object)
222    if output is None:
223        return dumper.output.getvalue()
224
225def emit_documents(nodes, output=None, **parameters):
226    if output is None:
227        dumper = Dumper(StringIO.StringIO(), **parameters)
228    else:
229        dumper = Dumper(output, **parameters)
230    for node in nodes:
231        dumper.emit(node)
232    if output is None:
233        return dumper.output.getvalue()
234
235def dump_documents(objects, output=None, **parameters):
236    if output is None:
237        dumper = Dumper(StringIO.StringIO(), **parameters)
238    else:
239        dumper = Dumper(output, **parameters)
240    for object in objects:
241        dumper.dump(object)
242    if output is None:
243        return dumper.output.getvalue()
244
245
Note: See TracBrowser for help on using the repository browser.