<s> from bson import DBRef , SON <EOL> from mongoengine . python_support import txt_type <EOL> from base import ( <EOL> BaseDict , BaseList , EmbeddedDocumentList , <EOL> TopLevelDocumentMetaclass , get_document <EOL> ) <EOL> from fields import ( ReferenceField , ListField , DictField , MapField ) <EOL> from connection import get_db <EOL> from queryset import QuerySet <EOL> from document import Document , EmbeddedDocument <EOL> class DeReference ( object ) : <EOL> def __call__ ( self , items , max_depth = <NUM_LIT:1> , instance = None , name = None ) : <EOL> """<STR_LIT>""" <EOL> if items is None or isinstance ( items , basestring ) : <EOL> return items <EOL> if isinstance ( items , QuerySet ) : <EOL> items = [ i for i in items ] <EOL> self . max_depth = max_depth <EOL> doc_type = None <EOL> if instance and isinstance ( instance , ( Document , EmbeddedDocument , <EOL> TopLevelDocumentMetaclass ) ) : <EOL> doc_type = instance . _fields . get ( name ) <EOL> while hasattr ( doc_type , '<STR_LIT>' ) : <EOL> doc_type = doc_type . field <EOL> if isinstance ( doc_type , ReferenceField ) : <EOL> field = doc_type <EOL> doc_type = doc_type . document_type <EOL> is_list = not hasattr ( items , '<STR_LIT>' ) <EOL> if is_list and all ( [ i . __class__ == doc_type for i in items ] ) : <EOL> return items <EOL> elif not is_list and all ( <EOL> [ i . __class__ == doc_type for i in items . values ( ) ] ) : <EOL> return items <EOL> elif not field . dbref : <EOL> if not hasattr ( items , '<STR_LIT>' ) : <EOL> def _get_items ( items ) : <EOL> new_items = [ ] <EOL> for v in items : <EOL> if isinstance ( v , list ) : <EOL> new_items . append ( _get_items ( v ) ) <EOL> elif not isinstance ( v , ( DBRef , Document ) ) : <EOL> new_items . append ( field . to_python ( v ) ) <EOL> else : <EOL> new_items . append ( v ) <EOL> return new_items <EOL> items = _get_items ( items ) <EOL> else : <EOL> items = dict ( [ <EOL> ( k , field . to_python ( v ) ) <EOL> if not isinstance ( v , ( DBRef , Document ) ) else ( k , v ) <EOL> for k , v in items . iteritems ( ) ] <EOL> ) <EOL> self . reference_map = self . _find_references ( items ) <EOL> self . object_map = self . _fetch_objects ( doc_type = doc_type ) <EOL> return self . _attach_objects ( items , <NUM_LIT:0> , instance , name ) <EOL> def _find_references ( self , items , depth = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> reference_map = { } <EOL> if not items or depth >= self . max_depth : <EOL> return reference_map <EOL> if not hasattr ( items , '<STR_LIT>' ) : <EOL> iterator = enumerate ( items ) <EOL> else : <EOL> iterator = items . iteritems ( ) <EOL> depth += <NUM_LIT:1> <EOL> for k , item in iterator : <EOL> if isinstance ( item , ( Document , EmbeddedDocument ) ) : <EOL> for field_name , field in item . _fields . iteritems ( ) : <EOL> v = item . _data . get ( field_name , None ) <EOL> if isinstance ( v , DBRef ) : <EOL> reference_map . setdefault ( field . document_type , set ( ) ) . add ( v . id ) <EOL> elif isinstance ( v , ( dict , SON ) ) and '<STR_LIT>' in v : <EOL> reference_map . setdefault ( get_document ( v [ '<STR_LIT>' ] ) , set ( ) ) . add ( v [ '<STR_LIT>' ] . id ) <EOL> elif isinstance ( v , ( dict , list , tuple ) ) and depth <= self . max_depth : <EOL> field_cls = getattr ( getattr ( field , '<STR_LIT>' , None ) , '<STR_LIT>' , None ) <EOL> references = self . _find_references ( v , depth ) <EOL> for key , refs in references . iteritems ( ) : <EOL> if isinstance ( field_cls , ( Document , TopLevelDocumentMetaclass ) ) : <EOL> key = field_cls <EOL> reference_map . setdefault ( key , set ( ) ) . update ( refs ) <EOL> elif isinstance ( item , DBRef ) : <EOL> reference_map . setdefault ( item . collection , set ( ) ) . add ( item . id ) <EOL> elif isinstance ( item , ( dict , SON ) ) and '<STR_LIT>' in item : <EOL> reference_map . setdefault ( get_document ( item [ '<STR_LIT>' ] ) , set ( ) ) . add ( item [ '<STR_LIT>' ] . id ) <EOL> elif isinstance ( item , ( dict , list , tuple ) ) and depth - <NUM_LIT:1> <= self . max_depth : <EOL> references = self . _find_references ( item , depth - <NUM_LIT:1> ) <EOL> for key , refs in references . iteritems ( ) : <EOL> reference_map . setdefault ( key , set ( ) ) . update ( refs ) <EOL> return reference_map <EOL> def _fetch_objects ( self , doc_type = None ) : <EOL> """<STR_LIT>""" <EOL> object_map = { } <EOL> for collection , dbrefs in self . reference_map . iteritems ( ) : <EOL> if hasattr ( collection , '<STR_LIT>' ) : <EOL> col_name = collection . _get_collection_name ( ) <EOL> refs = [ dbref for dbref in dbrefs <EOL> if ( col_name , dbref ) not in object_map ] <EOL> references = collection . objects . in_bulk ( refs ) <EOL> for key , doc in references . iteritems ( ) : <EOL> object_map [ ( col_name , key ) ] = doc <EOL> else : <EOL> if isinstance ( doc_type , ( ListField , DictField , MapField , ) ) : <EOL> continue <EOL> refs = [ dbref for dbref in dbrefs <EOL> if ( collection , dbref ) not in object_map ] <EOL> if doc_type : <EOL> references = doc_type . _get_db ( ) [ collection ] . find ( { '<STR_LIT>' : { '<STR_LIT>' : refs } } ) <EOL> for ref in references : <EOL> doc = doc_type . _from_son ( ref ) <EOL> object_map [ ( collection , doc . id ) ] = doc <EOL> else : <EOL> references = get_db ( ) [ collection ] . find ( { '<STR_LIT>' : { '<STR_LIT>' : refs } } ) <EOL> for ref in references : <EOL> if '<STR_LIT>' in ref : <EOL> doc = get_document ( ref [ "<STR_LIT>" ] ) . _from_son ( ref ) <EOL> elif doc_type is None : <EOL> doc = get_document ( <EOL> '<STR_LIT>' . join ( x . capitalize ( ) <EOL> for x in collection . split ( '<STR_LIT:_>' ) ) ) . _from_son ( ref ) <EOL> else : <EOL> doc = doc_type . _from_son ( ref ) <EOL> object_map [ ( collection , doc . id ) ] = doc <EOL> return object_map <EOL> def _attach_objects ( self , items , depth = <NUM_LIT:0> , instance = None , name = None ) : <EOL> """<STR_LIT>""" <EOL> if not items : <EOL> if isinstance ( items , ( BaseDict , BaseList ) ) : <EOL> return items <EOL> if instance : <EOL> if isinstance ( items , dict ) : <EOL> return BaseDict ( items , instance , name ) <EOL> else : <EOL> return BaseList ( items , instance , name ) <EOL> if isinstance ( items , ( dict , SON ) ) : <EOL> if '<STR_LIT>' in items : <EOL> return self . object_map . get ( <EOL> ( items [ '<STR_LIT>' ] . collection , items [ '<STR_LIT>' ] . id ) , items ) <EOL> elif '<STR_LIT>' in items : <EOL> doc = get_document ( items [ '<STR_LIT>' ] ) . _from_son ( items ) <EOL> _cls = doc . _data . pop ( '<STR_LIT>' , None ) <EOL> del items [ '<STR_LIT>' ] <EOL> doc . _data = self . _attach_objects ( doc . _data , depth , doc , None ) <EOL> if _cls is not None : <EOL> doc . _data [ '<STR_LIT>' ] = _cls <EOL> return doc <EOL> if not hasattr ( items , '<STR_LIT>' ) : <EOL> is_list = True <EOL> list_type = BaseList <EOL> if isinstance ( items , EmbeddedDocumentList ) : <EOL> list_type = EmbeddedDocumentList <EOL> as_tuple = isinstance ( items , tuple ) <EOL> iterator = enumerate ( items ) <EOL> data = [ ] <EOL> else : <EOL> is_list = False <EOL> iterator = items . iteritems ( ) <EOL> data = { } <EOL> depth += <NUM_LIT:1> <EOL> for k , v in iterator : <EOL> if is_list : <EOL> data . append ( v ) <EOL> else : <EOL> data [ k ] = v <EOL> if k in self . object_map and not is_list : <EOL> data [ k ] = self . object_map [ k ] <EOL> elif isinstance ( v , ( Document , EmbeddedDocument ) ) : <EOL> for field_name , field in v . _fields . iteritems ( ) : <EOL> v = data [ k ] . _data . get ( field_name , None ) <EOL> if isinstance ( v , DBRef ) : <EOL> data [ k ] . _data [ field_name ] = self . object_map . get ( <EOL> ( v . collection , v . id ) , v ) <EOL> elif isinstance ( v , ( dict , SON ) ) and '<STR_LIT>' in v : <EOL> data [ k ] . _data [ field_name ] = self . object_map . get ( <EOL> ( v [ '<STR_LIT>' ] . collection , v [ '<STR_LIT>' ] . id ) , v ) <EOL> elif isinstance ( v , ( dict , list , tuple ) ) and depth <= self . max_depth : <EOL> item_name = txt_type ( "<STR_LIT>" ) . format ( name , k , field_name ) <EOL> data [ k ] . _data [ field_name ] = self . _attach_objects ( v , depth , instance = instance , name = item_name ) <EOL> elif isinstance ( v , ( dict , list , tuple ) ) and depth <= self . max_depth : <EOL> item_name = '<STR_LIT>' % ( name , k ) if name else name <EOL> data [ k ] = self . _attach_objects ( v , depth - <NUM_LIT:1> , instance = instance , name = item_name ) <EOL> elif hasattr ( v , '<STR_LIT:id>' ) : <EOL> data [ k ] = self . object_map . get ( ( v . collection , v . id ) , v ) <EOL> if instance and name : <EOL> if is_list : <EOL> return tuple ( data ) if as_tuple else list_type ( data , instance , name ) <EOL> return BaseDict ( data , instance , name ) <EOL> depth += <NUM_LIT:1> <EOL> return data </s>
