<s> """<STR_LIT>""" <EOL> from django . db import models <EOL> from django . db . models . base import ModelBase <EOL> from django . db . models . signals import post_save , pre_delete <EOL> from django . dispatch import receiver <EOL> from django . utils . six import with_metaclass <EOL> import sys <EOL> def _closure_model_unicode ( self ) : <EOL> """<STR_LIT>""" <EOL> return "<STR_LIT>" % ( self . parent , self . child ) <EOL> def create_closure_model ( cls ) : <EOL> """<STR_LIT>""" <EOL> meta_vals = { <EOL> '<STR_LIT>' : ( ( "<STR_LIT>" , "<STR_LIT>" ) , ) <EOL> } <EOL> if getattr ( cls . _meta , '<STR_LIT>' , None ) : <EOL> meta_vals [ '<STR_LIT>' ] = '<STR_LIT>' % getattr ( cls . _meta , '<STR_LIT>' ) <EOL> model = type ( '<STR_LIT>' % cls . __name__ , ( models . Model , ) , { <EOL> '<STR_LIT>' : models . ForeignKey ( <EOL> cls . __name__ , <EOL> related_name = cls . closure_parentref ( ) <EOL> ) , <EOL> '<STR_LIT>' : models . ForeignKey ( <EOL> cls . __name__ , <EOL> related_name = cls . closure_childref ( ) <EOL> ) , <EOL> '<STR_LIT>' : models . IntegerField ( ) , <EOL> '<STR_LIT>' : cls . __module__ , <EOL> '<STR_LIT>' : _closure_model_unicode , <EOL> '<STR_LIT:Meta>' : type ( '<STR_LIT:Meta>' , ( object , ) , meta_vals ) , <EOL> } ) <EOL> setattr ( cls , "<STR_LIT>" , model ) <EOL> return model <EOL> class ClosureModelBase ( ModelBase ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( cls , name , bases , dct ) : <EOL> """<STR_LIT>""" <EOL> super ( ClosureModelBase , cls ) . __init__ ( name , bases , dct ) <EOL> if not cls . _meta . get_parent_list ( ) and cls . __module__ != __name__ : <EOL> setattr ( <EOL> sys . modules [ cls . __module__ ] , <EOL> '<STR_LIT>' % cls . __name__ , <EOL> create_closure_model ( cls ) <EOL> ) <EOL> class ClosureModel ( with_metaclass ( ClosureModelBase , models . Model ) ) : <EOL> """<STR_LIT>""" <EOL> class Meta : <EOL> """<STR_LIT>""" <EOL> abstract = True <EOL> def __setattr__ ( self , name , value ) : <EOL> if name . endswith ( '<STR_LIT>' ) : <EOL> id_field_name = name <EOL> else : <EOL> id_field_name = "<STR_LIT>" % name <EOL> if ( <EOL> name . startswith ( self . _closure_sentinel_attr ) and <EOL> hasattr ( self , id_field_name ) and <EOL> not self . _closure_change_check ( ) <EOL> ) : <EOL> if name . endswith ( '<STR_LIT>' ) : <EOL> obj_id = value <EOL> elif value : <EOL> obj_id = value . pk <EOL> else : <EOL> obj_id = None <EOL> if getattr ( self , id_field_name ) != obj_id : <EOL> self . _closure_change_init ( ) <EOL> super ( ClosureModel , self ) . __setattr__ ( name , value ) <EOL> @ classmethod <EOL> def _toplevel ( cls ) : <EOL> """<STR_LIT>""" <EOL> superclasses = ( <EOL> list ( set ( ClosureModel . __subclasses__ ( ) ) & <EOL> set ( cls . _meta . get_parent_list ( ) ) ) <EOL> ) <EOL> return next ( iter ( superclasses ) ) if superclasses else cls <EOL> @ classmethod <EOL> def rebuildtable ( cls ) : <EOL> """<STR_LIT>""" <EOL> cls . _closure_model . objects . all ( ) . delete ( ) <EOL> cls . _closure_model . objects . bulk_create ( [ cls . _closure_model ( <EOL> parent_id = x [ '<STR_LIT>' ] , <EOL> child_id = x [ '<STR_LIT>' ] , <EOL> depth = <NUM_LIT:0> <EOL> ) for x in cls . objects . values ( "<STR_LIT>" ) ] ) <EOL> for node in cls . objects . all ( ) : <EOL> node . _closure_createlink ( ) <EOL> @ classmethod <EOL> def closure_parentref ( cls ) : <EOL> """<STR_LIT>""" <EOL> return "<STR_LIT>" % cls . _toplevel ( ) . __name__ . lower ( ) <EOL> _closure_parentref = closure_parentref <EOL> @ classmethod <EOL> def closure_childref ( cls ) : <EOL> """<STR_LIT>""" <EOL> return "<STR_LIT>" % cls . _toplevel ( ) . __name__ . lower ( ) <EOL> _closure_childref = closure_childref <EOL> @ property <EOL> def _closure_sentinel_attr ( self ) : <EOL> """<STR_LIT>""" <EOL> meta = getattr ( self , '<STR_LIT>' , None ) <EOL> return getattr ( meta , '<STR_LIT>' , self . _closure_parent_attr ) <EOL> @ property <EOL> def _closure_parent_attr ( self ) : <EOL> '''<STR_LIT>''' <EOL> meta = getattr ( self , '<STR_LIT>' , None ) <EOL> return getattr ( meta , '<STR_LIT>' , '<STR_LIT>' ) <EOL> @ property <EOL> def _closure_parent_pk ( self ) : <EOL> """<STR_LIT>""" <EOL> if hasattr ( self , "<STR_LIT>" % self . _closure_parent_attr ) : <EOL> return getattr ( self , "<STR_LIT>" % self . _closure_parent_attr ) <EOL> else : <EOL> parent = getattr ( self , self . _closure_parent_attr ) <EOL> return parent . pk if parent else None <EOL> def _closure_deletelink ( self , oldparentpk ) : <EOL> """<STR_LIT>""" <EOL> self . _closure_model . objects . filter ( <EOL> ** { <EOL> "<STR_LIT>" % self . _closure_parentref ( ) : oldparentpk , <EOL> "<STR_LIT>" % self . _closure_childref ( ) : self . pk <EOL> } <EOL> ) . delete ( ) <EOL> def _closure_createlink ( self ) : <EOL> """<STR_LIT>""" <EOL> linkparents = self . _closure_model . objects . filter ( <EOL> child__pk = self . _closure_parent_pk <EOL> ) . values ( "<STR_LIT>" , "<STR_LIT>" ) <EOL> linkchildren = self . _closure_model . objects . filter ( <EOL> parent__pk = self . pk <EOL> ) . values ( "<STR_LIT>" , "<STR_LIT>" ) <EOL> newlinks = [ self . _closure_model ( <EOL> parent_id = p [ '<STR_LIT>' ] , <EOL> child_id = c [ '<STR_LIT>' ] , <EOL> depth = p [ '<STR_LIT>' ] + c [ '<STR_LIT>' ] + <NUM_LIT:1> <EOL> ) for p in linkparents for c in linkchildren ] <EOL> self . _closure_model . objects . bulk_create ( newlinks ) <EOL> def get_ancestors ( self , include_self = False , depth = None ) : <EOL> """<STR_LIT>""" <EOL> if self . is_root_node ( ) : <EOL> if not include_self : <EOL> return self . _toplevel ( ) . objects . none ( ) <EOL> else : <EOL> return self . _toplevel ( ) . objects . filter ( pk = self . pk ) <EOL> params = { "<STR_LIT>" % self . _closure_parentref ( ) : self . pk } <EOL> if depth is not None : <EOL> params [ "<STR_LIT>" % self . _closure_parentref ( ) ] = depth <EOL> ancestors = self . _toplevel ( ) . objects . filter ( ** params ) <EOL> if not include_self : <EOL> ancestors = ancestors . exclude ( pk = self . pk ) <EOL> return ancestors . order_by ( "<STR_LIT>" % self . _closure_parentref ( ) ) <EOL> def get_descendants ( self , include_self = False , depth = None ) : <EOL> """<STR_LIT>""" <EOL> params = { "<STR_LIT>" % self . _closure_childref ( ) : self . pk } <EOL> if depth is not None : <EOL> params [ "<STR_LIT>" % self . _closure_childref ( ) ] = depth <EOL> descendants = self . _toplevel ( ) . objects . filter ( ** params ) <EOL> if not include_self : <EOL> descendants = descendants . exclude ( pk = self . pk ) <EOL> return descendants . order_by ( "<STR_LIT>" % self . _closure_childref ( ) ) <EOL> def prepopulate ( self , queryset ) : <EOL> """<STR_LIT>""" <EOL> objs = list ( queryset ) <EOL> hashobjs = dict ( [ ( x . pk , x ) for x in objs ] + [ ( self . pk , self ) ] ) <EOL> for descendant in hashobjs . values ( ) : <EOL> descendant . _cached_children = [ ] <EOL> for descendant in objs : <EOL> assert descendant . _closure_parent_pk in hashobjs <EOL> parent = hashobjs [ descendant . _closure_parent_pk ] <EOL> parent . _cached_children . append ( descendant ) <EOL> def get_children ( self ) : <EOL> """<STR_LIT>""" <EOL> if hasattr ( self , '<STR_LIT>' ) : <EOL> children = self . _toplevel ( ) . objects . filter ( <EOL> pk__in = [ n . pk for n in self . _cached_children ] <EOL> ) <EOL> children . _result_cache = self . _cached_children <EOL> return children <EOL> else : <EOL> return self . get_descendants ( include_self = False , depth = <NUM_LIT:1> ) <EOL> def get_root ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . is_root_node ( ) : <EOL> return self <EOL> return self . get_ancestors ( ) . order_by ( <EOL> "<STR_LIT>" % self . _closure_parentref ( ) <EOL> ) [ <NUM_LIT:0> ] <EOL> def is_child_node ( self ) : <EOL> """<STR_LIT>""" <EOL> return not self . is_root_node ( ) <EOL> def is_root_node ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _closure_parent_pk is None <EOL> def is_descendant_of ( self , other , include_self = False ) : <EOL> """<STR_LIT>""" <EOL> if other . pk == self . pk : <EOL> return include_self <EOL> return self . _closure_model . objects . filter ( <EOL> parent = other , <EOL> child = self <EOL> ) . exclude ( pk = self . pk ) . exists ( ) <EOL> def is_ancestor_of ( self , other , include_self = False ) : <EOL> """<STR_LIT>""" <EOL> return other . is_descendant_of ( self , include_self = include_self ) <EOL> def _closure_change_init ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _closure_old_parent_pk = self . _closure_parent_pk <EOL> def _closure_change_check ( self ) : <EOL> """<STR_LIT>""" <EOL> return hasattr ( self , "<STR_LIT>" ) <EOL> def _closure_change_oldparent ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _closure_old_parent_pk <EOL> @ receiver ( post_save , dispatch_uid = '<STR_LIT>' ) <EOL> def closure_model_save ( sender , ** kwargs ) : <EOL> if issubclass ( sender , ClosureModel ) : <EOL> instance = kwargs [ '<STR_LIT>' ] <EOL> create = kwargs [ '<STR_LIT>' ] <EOL> if create : <EOL> closure_instance = instance . _closure_model ( <EOL> parent = instance , <EOL> child = instance , <EOL> depth = <NUM_LIT:0> <EOL> ) <EOL> closure_instance . save ( ) <EOL> if instance . _closure_change_check ( ) : <EOL> if instance . _closure_change_oldparent ( ) : <EOL> instance . _closure_deletelink ( instance . _closure_change_oldparent ( ) ) <EOL> instance . _closure_createlink ( ) <EOL> delattr ( instance , "<STR_LIT>" ) <EOL> elif create : <EOL> instance . _closure_createlink ( ) <EOL> @ receiver ( pre_delete , dispatch_uid = '<STR_LIT>' ) <EOL> def closure_model_delete ( sender , ** kwargs ) : <EOL> if issubclass ( sender , ClosureModel ) : <EOL> instance = kwargs [ '<STR_LIT>' ] <EOL> instance . _closure_deletelink ( instance . _closure_parent_pk ) </s>
