Changeset 21


Ignore:
Timestamp:
08/13/05 17:32:51 (9 years ago)
Author:
xi
Message:

Now it dumps and loads python objects!

Location:
trunk
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/syck/dumpers.py

    r20 r21  
    2222    def _convert(self, object, object_to_node): 
    2323        if id(object) in object_to_node and self.allow_aliases(object): 
    24             return object_to_node[id(object)] 
     24            return object_to_node[id(object)][1] 
    2525        node = self.represent(object) 
    26         object_to_node[id(object)] = node 
     26        object_to_node[id(object)] = object, node 
    2727        if node.kind == 'seq': 
    2828            for index, item in enumerate(node.value): 
     
    5656        super(Dumper, self).__init__(*args, **kwds) 
    5757 
    58     def represent(self, object): 
     58    def find_representer(self, object): 
    5959        for object_type in type(object).__mro__: 
    6060            if object_type.__module__ == '__builtin__': 
     
    6262            else: 
    6363                name = '%s.%s' % (object_type.__module__, object_type.__name__) 
    64             method = 'represent_%s' % name.replace('.', '_') 
     64            method = 'represent_' + name.replace('.', '_') 
    6565            if hasattr(self, method): 
    66                 return getattr(self, method)(object) 
    67         return super(Dumper, self).represent(object) 
     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) 
    6874 
    6975    def represent_object(self, object): 
     
    8490    def represent_dict(self, object): 
    8591        return _syck.Map(object.copy(), tag="tag:yaml.org,2002:map") 
    86  
    87     def represent_int(self, object): 
    88         return _syck.Scalar(repr(object), tag="tag:yaml.org,2002:int") 
    8992 
    9093    def represent_int(self, object): 
     
    107110        return _syck.Scalar(object.isoformat(), tag="tag:yaml.org,2002:timestamp") 
    108111 
     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 
    109198    def allow_aliases(self, object): 
    110199        if object is None or type(object) in [int, bool, float]: 
     
    112201        if type(object) is str and (not object or object.isalnum()): 
    113202            return False 
     203        if type(object) is tuple and not object: 
     204            return False 
    114205        return True 
    115206 
  • trunk/lib/syck/loaders.py

    r18 r21  
    2121import _syck 
    2222 
    23 import re 
     23import sys, re 
    2424 
    2525__all__ = ['GenericLoader', 'Loader', 
     
    8484    nan_value = inf_value/inf_value 
    8585 
    86     ymd_expr = re.compile(r'(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d)') 
    8786    timestamp_expr = re.compile(r'(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d)' 
    8887            r'(?:' 
     
    9594    default_key = Default() 
    9695 
    97     def __init__(self, *args, **kwds): 
    98         super(Loader, self).__init__(*args, **kwds) 
    99         self.tags = {} 
    100         self.add_builtin_types() 
    101  
    102     def add_builtin_types(self): 
    103         self.add_builtin_type('null', lambda node: None) 
    104         self.add_builtin_type('bool#yes', lambda node: True) 
    105         self.add_builtin_type('bool#no', lambda node: False) 
    106         self.add_builtin_type('float#fix', lambda node: float(node.value)) 
    107         self.add_builtin_type('float#exp', lambda node: float(node.value)) 
    108         self.add_builtin_type('float#base60', 'construct_base60_float') 
    109         self.add_builtin_type('float#inf', lambda node: self.inf_value) 
    110         self.add_builtin_type('float#neginf', lambda node: -self.inf_value) 
    111         self.add_builtin_type('float#nan', lambda node: self.nan_value) 
    112         self.add_builtin_type('int', lambda node: int(node.value)) 
    113         self.add_builtin_type('int#hex', lambda node: int(node.value, 16)) 
    114         self.add_builtin_type('int#oct', lambda node: int(node.value, 8)) 
    115         self.add_builtin_type('int#base60', 'construct_base60_int') 
    116         self.add_builtin_type('binary', lambda node: node.value.decode('base64')) 
    117         self.add_builtin_type('timestamp#ymd', 'construct_timestamp') 
    118         self.add_builtin_type('timestamp#iso8601', 'construct_timestamp') 
    119         self.add_builtin_type('timestamp#spaced', 'construct_timestamp') 
    120         self.add_builtin_type('timestamp', 'construct_timestamp') 
    121         self.add_builtin_type('merge', 'construct_merge') 
    122         self.add_builtin_type('default', 'construct_default') 
    123         self.add_builtin_type('omap', 'construct_omap') 
    124         self.add_builtin_type('pairs', 'construct_pairs') 
    125         self.add_builtin_type('set', 'construct_set') 
    126  
    127     def add_type(self, type_tag, constuctor): 
    128         self.tags[type_tag] = constructor 
    129  
    130     def add_domain_type(self, domain, type_tag, constructor): 
    131         self.tags['tag:%s:%s' % (domain, type_tag)] = constructor 
    132  
    133     def add_builtin_type(self, type_tag, constructor): 
    134         self.tags['tag:yaml.org,2002:'+type_tag] = constructor 
    135  
    136     def add_python_type(self, type_tag, constructor): 
    137         self.tags['tag:python.yaml.org,2002:'+type_tag] = constructor 
    138  
    139     def add_private_type(self, type_tag, constructor): 
    140         self.tags['x-private:'+type_tag] = constructor 
     96    non_ascii = [] 
     97    for i in range(256): 
     98        ch = chr(i) 
     99        if ch.isalnum(): 
     100            non_ascii.append(ch) 
     101        else: 
     102            non_ascii.append('_') 
     103    non_ascii = ''.join(non_ascii) 
     104 
     105    python_bools = {'True': True, 'False': False} 
     106 
     107    class python_class: 
     108        pass 
     109 
     110    def find_constructor(self, node): 
     111        parts = [] 
     112        if node.tag: 
     113            parts = node.tag.split(':') 
     114        if parts: 
     115            if parts[0] == 'tag': 
     116                parts.pop(0) 
     117                if parts: 
     118                    if parts[0] == 'yaml.org,2002': 
     119                        parts.pop(0) 
     120                    elif parts[0] == 'python.yaml.org,2002': 
     121                        parts[0] = 'python' 
     122            elif parts[0] == 'x-private': 
     123                parts[0] = 'private' 
     124        parts = [part.translate(self.non_ascii) for part in parts] 
     125        while parts: 
     126            method = 'construct_'+'_'.join(parts) 
     127            if hasattr(self, method): 
     128                return getattr(self, method) 
     129            parts.pop() 
    141130 
    142131    def construct(self, node): 
    143132        if node.kind == 'map' and self.merge_key in node.value: 
    144133            self.merge_maps(node) 
    145         if node.tag in self.tags: 
    146             constructor = self.tags[node.tag] 
    147             if isinstance(constructor, str): 
    148                 constructor = getattr(self, constructor) 
     134        constructor = self.find_constructor(node) 
     135        if constructor: 
    149136            return constructor(node) 
    150137        else: 
    151138            return node.value 
    152139 
    153     def construct_base60_float(self, node): 
    154         return self.construct_base60(float, node) 
    155  
    156     def construct_base60_int(self, node): 
    157         return self.construct_base60(int, node) 
    158  
    159     def construct_base60(self, num_type, node): 
     140    def construct_null(self, node): 
     141        return None 
     142 
     143    def construct_bool_yes(self, node): 
     144        return True 
     145 
     146    def construct_bool_no(self, node): 
     147        return False 
     148 
     149    def construct_numeric_base60(self, num_type, node): 
    160150        digits = [num_type(part) for part in node.value.split(':')] 
    161151        digits.reverse() 
     
    166156            base *= 60 
    167157        return value 
     158 
     159    def construct_int(self, node): 
     160        return int(node.value) 
     161 
     162    def construct_int_hex(self, node): 
     163        return int(node.value, 16) 
     164 
     165    def construct_int_oct(self, node): 
     166        return int(node.value, 8) 
     167 
     168    def construct_int_base60(self, node): 
     169        return self.construct_numeric_base60(int, node) 
     170 
     171    def construct_float(self, node): 
     172        return float(node.value) 
     173    construct_float_fix = construct_float 
     174    construct_float_exp = construct_float 
     175 
     176    def construct_float_base60(self, node): 
     177        return self.construct_numeric_base60(float, node) 
     178 
     179    def construct_float_inf(self, node): 
     180        return self.inf_value 
     181 
     182    def construct_float_neginf(self, node): 
     183        return -self.inf_value 
     184 
     185    def construct_float_nan(self, node): 
     186        return self.nan_value 
     187 
     188    def construct_binary(self, node): 
     189        return node.value.decode('base64') 
    168190 
    169191    def construct_timestamp(self, node): 
     
    183205        diff = datetime.timedelta(hours=values['zhour'], minutes=values['zminute']) 
    184206        return stamp-diff 
     207    construct_timestamp_ymd = construct_timestamp 
     208    construct_timestamp_iso8601 = construct_timestamp 
     209    construct_timestamp_spaced = construct_timestamp 
    185210 
    186211    def construct_merge(self, node): 
     
    217242        return sets.Set(node.value) 
    218243 
     244    def construct_python_none(self, node): 
     245        return None 
     246 
     247    def construct_python_bool(self, node): 
     248        return self.python_bools[node.value] 
     249 
     250    def construct_python_int(self, node): 
     251        return int(node.value) 
     252 
     253    def construct_python_long(self, node): 
     254        return long(node.value) 
     255 
     256    def construct_python_float(self, node): 
     257        return float(node.value) 
     258 
     259    def construct_python_str(self, node): 
     260        return str(node.value) 
     261 
     262    def construct_python_unicode(self, node): 
     263        return unicode(node.value, 'utf-8') 
     264 
     265    def construct_python_list(self, node): 
     266        return node.value 
     267 
     268    def construct_python_tuple(self, node): 
     269        return tuple(node.value) 
     270 
     271    def construct_python_dict(self, node): 
     272        return node.value 
     273 
     274    def find_python_object(self, node): 
     275        full_name = node.tag.split(':')[3] 
     276        parts = full_name.split('.') 
     277        object_name = parts.pop() 
     278        module_name = '.'.join(parts) 
     279        if not module_name: 
     280            module_name = '__builtin__' 
     281        else: 
     282            __import__(module_name) 
     283        return getattr(sys.modules[module_name], object_name) 
     284 
     285    def find_python_state(self, node): 
     286        if node.kind == 'seq': 
     287            args = node.value 
     288            kwds = {} 
     289            state = {} 
     290        else: 
     291            args = node.value.get('args', []) 
     292            kwds = node.value.get('kwds', {}) 
     293            state = node.value.get('state', {}) 
     294        return args, kwds, state 
     295 
     296    def set_python_state(self, object, state): 
     297        if hasattr(object, '__setstate__'): 
     298            object.__setstate__(state) 
     299        else: 
     300            slotstate = {} 
     301            if isinstance(state, tuple) and len(state) == 2: 
     302                state, slotstate = state 
     303            object.__dict__.update(state) 
     304            for key, value in slotstate.items(): 
     305                setattr(object, key, value) 
     306 
     307    def construct_python_name(self, node): 
     308        return self.find_python_object(node) 
     309 
     310    def construct_python_object(self, node): 
     311        cls = self.find_python_object(node) 
     312        if type(cls) is type(self.python_class): 
     313            if hasattr(cls, '__getnewargs__'): 
     314                object = cls() 
     315            else: 
     316                object = self.python_class() 
     317                object.__class__ = cls 
     318        else: 
     319            object = cls.__new__(cls) 
     320        self.set_python_state(object, node.value) 
     321        return object 
     322 
     323    def construct_python_new(self, node): 
     324        cls = self.find_python_object(node) 
     325        args, kwds, state = self.find_python_state(node) 
     326        if type(cls) is type(self.python_class): 
     327            object = cls(*args, **kwds) 
     328        else: 
     329            object = cls.__new__(cls, *args, **kwds) 
     330        self.set_python_state(object, state) 
     331        return object 
     332 
     333    def construct_python_apply(self, node): 
     334        constructor = self.find_python_object(node) 
     335        args, kwds, state = self.find_python_state(node) 
     336        object = constructor(*args, **kwds) 
     337        self.set_python_state(object, state) 
     338        return object 
     339 
    219340def parse(source): 
    220341    """Parses 'source' and returns the root of the 'Node' graph.""" 
  • trunk/tests/test_emitter.py

    r17 r21  
    282282 
    283283 
    284 class TestSyckBugWithTrailingSpace(unittest.TestCase): 
    285  
    286     def testSyckBugWithTrailingSpace(self): 
    287         emitter = _syck.Emitter(StringIO.StringIO()) 
    288         emitter.emit(_syck.Scalar('foo ', tag="tag:yaml.org,2002:str")) 
    289         parser = _syck.Parser(emitter.output.getvalue()) 
    290         self.assertEqual(parser.parse().value, 'foo ') 
    291  
    292  
     284#class TestSyckBugWithTrailingSpace(unittest.TestCase): 
     285# 
     286#    def testSyckBugWithTrailingSpace(self): 
     287#        emitter = _syck.Emitter(StringIO.StringIO()) 
     288#        emitter.emit(_syck.Scalar('foo ', tag="tag:yaml.org,2002:str")) 
     289#        parser = _syck.Parser(emitter.output.getvalue()) 
     290#        self.assertEqual(parser.parse().value, 'foo ') 
     291 
     292 
  • trunk/tests/test_syck.py

    r20 r21  
    22import unittest 
    33 
    4 #from test_node import * 
     4from test_node import * 
    55from test_parser import * 
    66from test_loader import * 
    77from test_emitter import * 
    88from test_dumper import * 
     9from test_pickle import * 
    910 
    1011def main(module='__main__'): 
Note: See TracChangeset for help on using the changeset viewer.