<s> import weakref <EOL> import threading <EOL> from base64 import b64encode , b64decode <EOL> from idiokit . xmlcore import Element <EOL> from . import rules <EOL> class NameAlreadyRegistered ( Exception ) : <EOL> pass <EOL> class UnregisteredType ( Exception ) : <EOL> pass <EOL> class UnregisteredName ( Exception ) : <EOL> pass <EOL> class Serializer ( object ) : <EOL> def __init__ ( self , register_common = True ) : <EOL> self . _lock = threading . Lock ( ) <EOL> self . _types = [ ] <EOL> self . _names = dict ( ) <EOL> self . _cache = weakref . WeakKeyDictionary ( ) <EOL> if register_common : <EOL> self . register ( "<STR_LIT:d>" , Dict ( dict ) ) <EOL> self . register ( "<STR_LIT:l>" , List ( list , tuple , set , frozenset ) ) <EOL> self . register ( "<STR_LIT:i>" , Int ( int , long ) ) <EOL> self . register ( "<STR_LIT:f>" , Float ( float ) ) <EOL> self . register ( "<STR_LIT:n>" , Nil ( type ( None ) ) ) <EOL> self . register ( "<STR_LIT:s>" , Str ( unicode ) ) <EOL> self . register ( "<STR_LIT:b>" , Bytes ( str ) ) <EOL> self . register ( "<STR_LIT:t>" , Bool ( bool ) ) <EOL> self . register ( "<STR_LIT>" , Rule ( rules . And ) ) <EOL> self . register ( "<STR_LIT>" , Rule ( rules . Or ) ) <EOL> self . register ( "<STR_LIT>" , Rule ( rules . No ) ) <EOL> self . register ( "<STR_LIT>" , Rule ( rules . Match ) ) <EOL> self . register ( "<STR_LIT>" , Rule ( rules . NonMatch ) ) <EOL> self . register ( "<STR_LIT>" , Rule ( rules . Fuzzy ) ) <EOL> self . register ( "<STR_LIT>" , Rule ( rules . Anything ) ) <EOL> self . register ( "<STR_LIT>" , Rule ( rules . RegExp ) ) <EOL> self . register ( "<STR_LIT>" , Rule ( rules . String ) ) <EOL> self . register ( "<STR_LIT>" , Rule ( rules . IP ) ) <EOL> self . register ( "<STR_LIT>" , Rule ( rules . DomainName ) ) <EOL> def register ( self , name , serializer ) : <EOL> with self . _lock : <EOL> if name in self . _names : <EOL> raise NameAlreadyRegistered ( name ) <EOL> self . _types . append ( ( name , serializer ) ) <EOL> self . _names [ name ] = serializer <EOL> self . _cache . clear ( ) <EOL> def _find_serializer ( self , obj ) : <EOL> obj_type = type ( obj ) <EOL> with self . _lock : <EOL> if obj_type not in self . _cache : <EOL> info = None <EOL> for name , serializer in reversed ( self . _types ) : <EOL> if serializer . isinstance ( obj ) : <EOL> info = name , serializer <EOL> break <EOL> self . _cache [ obj_type ] = info <EOL> info = self . _cache [ obj_type ] <EOL> if info is None : <EOL> raise UnregisteredType ( obj_type ) <EOL> return info <EOL> def dump ( self , obj ) : <EOL> name , serializer = self . _find_serializer ( obj ) <EOL> return serializer . dump ( obj , name , self ) <EOL> def normalize ( self , obj ) : <EOL> _ , serializer = self . _find_serializer ( obj ) <EOL> return serializer . normalize ( obj , self ) <EOL> def load ( self , element ) : <EOL> name = element . name <EOL> with self . _lock : <EOL> if name not in self . _names : <EOL> raise UnregisteredName ( name ) <EOL> serializer = self . _names [ name ] <EOL> return serializer . load ( element , self ) <EOL> class SubSerializer ( object ) : <EOL> def __init__ ( self , * types ) : <EOL> self . _types = types <EOL> def isinstance ( self , obj ) : <EOL> return isinstance ( obj , self . _types ) <EOL> def dump ( self , obj , name , context ) : <EOL> raise NotImplementedError ( ) <EOL> def load ( self , obj , context ) : <EOL> raise NotImplementedError ( ) <EOL> def normalize ( self , obj , context ) : <EOL> return self . load ( self . dump ( obj , context ) , context ) <EOL> class List ( SubSerializer ) : <EOL> def dump ( self , obj , name , context ) : <EOL> element = Element ( name ) <EOL> for item in obj : <EOL> element . add ( context . dump ( item ) ) <EOL> return element <EOL> def load ( self , element , context ) : <EOL> return tuple ( load ( item ) for item in element . children ( ) ) <EOL> def normalize ( self , obj , context ) : <EOL> return tuple ( context . normalize ( x ) for x in obj ) <EOL> class Dict ( SubSerializer ) : <EOL> _list = List ( ) <EOL> def dump ( self , obj , name , context ) : <EOL> return self . _list . dump ( obj . items ( ) , name , context ) <EOL> def load ( self , element , context ) : <EOL> return dict ( self . _list . load ( element , context ) ) <EOL> def normalize ( self , obj , context ) : <EOL> return dict ( self . _list . normalize ( obj . items ( ) , context ) ) <EOL> class Int ( SubSerializer ) : <EOL> def dump ( self , obj , name , context ) : <EOL> return Element ( name , _text = unicode ( obj ) ) <EOL> def load ( self , element , context ) : <EOL> return int ( element . text ) <EOL> def normalize ( self , obj , context ) : <EOL> return obj <EOL> class Float ( SubSerializer ) : <EOL> def dump ( self , obj , name , context ) : <EOL> return Element ( name , _text = repr ( obj ) ) <EOL> def load ( self , element , context ) : <EOL> return float ( element . text ) <EOL> def normalize ( self , obj , context ) : <EOL> return obj <EOL> class Nil ( SubSerializer ) : <EOL> def dump ( self , obj , name , context ) : <EOL> return Element ( name ) <EOL> def load ( self , element , context ) : <EOL> return None <EOL> def normalize ( self , obj , context ) : <EOL> return None <EOL> class Str ( SubSerializer ) : <EOL> def dump ( self , obj , name , context ) : <EOL> return Element ( name , _text = b64encode ( obj . encode ( "<STR_LIT:utf-8>" ) ) ) <EOL> def load ( self , element , context ) : <EOL> return b64decode ( element . text ) . decode ( "<STR_LIT:utf-8>" ) <EOL> def normalize ( self , obj , context ) : <EOL> return obj <EOL> class Bytes ( SubSerializer ) : <EOL> def dump ( self , obj , name , context ) : <EOL> return Element ( name , _text = b64encode ( obj ) ) <EOL> def load ( self , element , context ) : <EOL> return b64decode ( element . text ) <EOL> def normalize ( self , obj , context ) : <EOL> return obj <EOL> class Bool ( SubSerializer ) : <EOL> def dump ( self , obj , name , context ) : <EOL> return Element ( name , _text = unicode ( int ( bool ( obj ) ) ) ) <EOL> def load ( self , element , context ) : <EOL> return bool ( int ( element . text ) ) <EOL> def normalize ( self , obj , context ) : <EOL> return obj <EOL> class Rule ( SubSerializer ) : <EOL> def __init__ ( self , rule_type ) : <EOL> SubSerializer . __init__ ( self , rule_type ) <EOL> self . _rule_type = rule_type <EOL> def dump ( self , obj , name , context ) : <EOL> element = Element ( name ) <EOL> element . add ( context . dump ( obj . dump ( ) ) ) <EOL> return element <EOL> def load ( self , element , context ) : <EOL> for child in element . children ( ) : <EOL> return self . _rule_type . load ( context . load ( child ) ) <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> def normalize ( self , obj , context ) : <EOL> return obj . load ( context . normalize ( obj . dump ( ) ) ) <EOL> global_serializer = Serializer ( ) <EOL> register = global_serializer . register <EOL> dump = global_serializer . dump <EOL> load = global_serializer . load <EOL> normalize = global_serializer . normalize </s>
