<s> """<STR_LIT>""" <EOL> from past . builtins import basestring <EOL> from builtins import object <EOL> import logging <EOL> logger = logging . getLogger ( __name__ ) <EOL> import datetime <EOL> from django . conf import settings <EOL> from django . db import models <EOL> from django . utils . translation import ugettext_lazy as _ <EOL> from django . utils import timezone <EOL> from lino . api import dd <EOL> from lino . core import fields <EOL> from lino . core . roles import SiteStaff <EOL> from lino . core . signals import pre_ui_delete , on_ui_created , on_ui_updated <EOL> from lino . core . signals import pre_merge <EOL> from lino . core . signals import pre_add_child , pre_remove_child <EOL> from lino . core . signals import receiver <EOL> from lino . modlib . gfks . fields import GenericForeignKey , GenericForeignKeyIdField <EOL> class ChangeTypes ( dd . ChoiceList ) : <EOL> """<STR_LIT>""" <EOL> verbose_name = _ ( "<STR_LIT>" ) <EOL> verbose_name_plural = _ ( "<STR_LIT>" ) <EOL> add = ChangeTypes . add_item <EOL> add ( '<STR_LIT:C>' , _ ( "<STR_LIT>" ) , '<STR_LIT>' ) <EOL> add ( '<STR_LIT>' , _ ( "<STR_LIT>" ) , '<STR_LIT>' ) <EOL> add ( '<STR_LIT:D>' , _ ( "<STR_LIT>" ) , '<STR_LIT>' ) <EOL> add ( '<STR_LIT:R>' , _ ( "<STR_LIT>" ) , '<STR_LIT>' ) <EOL> add ( '<STR_LIT:A>' , _ ( "<STR_LIT>" ) , '<STR_LIT>' ) <EOL> add ( '<STR_LIT:M>' , _ ( "<STR_LIT>" ) , '<STR_LIT>' ) <EOL> @ dd . python_2_unicode_compatible <EOL> class Change ( dd . Model ) : <EOL> """<STR_LIT>""" <EOL> class Meta ( object ) : <EOL> verbose_name = _ ( "<STR_LIT>" ) <EOL> verbose_name_plural = _ ( "<STR_LIT>" ) <EOL> time = models . DateTimeField ( ) <EOL> type = ChangeTypes . field ( ) <EOL> if settings . SITE . user_model : <EOL> user = dd . ForeignKey ( settings . SITE . user_model ) <EOL> else : <EOL> user = dd . DummyField ( ) <EOL> object_type = models . ForeignKey ( <EOL> '<STR_LIT>' , blank = True , null = True , <EOL> verbose_name = _ ( "<STR_LIT>" ) , <EOL> related_name = '<STR_LIT>' ) <EOL> object_id = GenericForeignKeyIdField ( <EOL> object_type , blank = True , null = True ) <EOL> object = GenericForeignKey ( '<STR_LIT>' , '<STR_LIT>' , _ ( "<STR_LIT>" ) ) <EOL> master_type = models . ForeignKey ( <EOL> '<STR_LIT>' , blank = True , null = True , <EOL> verbose_name = _ ( "<STR_LIT>" ) , related_name = '<STR_LIT>' ) <EOL> master_id = GenericForeignKeyIdField ( <EOL> master_type , blank = True , null = True ) <EOL> master = GenericForeignKey ( '<STR_LIT>' , '<STR_LIT>' , _ ( "<STR_LIT>" ) ) <EOL> diff = dd . RichTextField ( _ ( "<STR_LIT>" ) , format = '<STR_LIT>' , blank = True ) <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % self . id <EOL> class Changes ( dd . Table ) : <EOL> """<STR_LIT>""" <EOL> param_object_type = models . ForeignKey ( <EOL> '<STR_LIT>' , <EOL> verbose_name = _ ( "<STR_LIT>" ) , blank = True ) <EOL> parameters = { <EOL> '<STR_LIT>' : ChangeTypes . field ( force_selection = False , blank = True ) , <EOL> '<STR_LIT:date>' : models . DateField ( _ ( "<STR_LIT>" ) , blank = True ) , <EOL> '<STR_LIT>' : param_object_type , <EOL> '<STR_LIT>' : models . PositiveIntegerField ( "<STR_LIT>" , blank = True ) , <EOL> } <EOL> if settings . SITE . user_model : <EOL> parameters [ '<STR_LIT:user>' ] = dd . ForeignKey ( <EOL> settings . SITE . user_model , <EOL> blank = True ) <EOL> required_roles = dd . required ( SiteStaff ) <EOL> editable = False <EOL> model = '<STR_LIT>' <EOL> order_by = [ '<STR_LIT>' ] <EOL> detail_layout = """<STR_LIT>""" <EOL> params_layout = """<STR_LIT>""" <EOL> @ classmethod <EOL> def get_request_queryset ( cls , ar ) : <EOL> qs = super ( Changes , cls ) . get_request_queryset ( ar ) <EOL> if not isinstance ( qs , list ) : <EOL> if ar . param_values . change_type : <EOL> qs = qs . filter ( type = ar . param_values . change_type ) <EOL> if ar . param_values . date : <EOL> qs = qs . filter ( time__range = ( <EOL> ar . param_values . date , <EOL> ar . param_values . date + datetime . timedelta ( <NUM_LIT:1> ) ) ) <EOL> if settings . SITE . user_model and ar . param_values . user : <EOL> qs = qs . filter ( user = ar . param_values . user ) <EOL> if ar . param_values . object_type : <EOL> qs = qs . filter ( object_type = ar . param_values . object_type ) <EOL> if ar . param_values . object_id : <EOL> qs = qs . filter ( object_id = ar . param_values . object_id ) <EOL> return qs <EOL> class ChangesByObject ( Changes ) : <EOL> """<STR_LIT>""" <EOL> required_roles = dd . required ( SiteStaff ) <EOL> master_key = '<STR_LIT:object>' <EOL> column_names = '<STR_LIT>' <EOL> class ChangesByMaster ( Changes ) : <EOL> """<STR_LIT>""" <EOL> required_roles = dd . required ( ) <EOL> master_key = '<STR_LIT>' <EOL> column_names = '<STR_LIT>' <EOL> class WatcherSpec ( object ) : <EOL> def __init__ ( self , ignored_fields , get_master ) : <EOL> self . ignored_fields = ignored_fields <EOL> self . get_master = get_master <EOL> def watch_all_changes ( ignore = [ ] ) : <EOL> """<STR_LIT>""" <EOL> watch_all_changes . allow = True <EOL> watch_all_changes . ignore . extend ( ignore ) <EOL> watch_all_changes . allow = False <EOL> watch_all_changes . ignore = [ ] <EOL> def return_self ( obj ) : <EOL> return obj <EOL> def watch_changes ( model , ignore = [ ] , master_key = None , ** options ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( ignore , basestring ) : <EOL> ignore = fields . fields_list ( model , ignore ) <EOL> if isinstance ( master_key , basestring ) : <EOL> fld = model . get_data_elem ( master_key ) <EOL> if fld is None : <EOL> raise Exception ( "<STR_LIT>" % ( master_key , model ) ) <EOL> master_key = fld <EOL> if isinstance ( master_key , fields . RemoteField ) : <EOL> get_master = master_key . func <EOL> elif master_key is None : <EOL> get_master = return_self <EOL> else : <EOL> def get_master ( obj ) : <EOL> return getattr ( obj , master_key . name ) <EOL> ignore = set ( ignore ) <EOL> cs = model . change_watcher_spec <EOL> if cs is not None : <EOL> ignore |= cs . ignored_fields <EOL> for f in model . _meta . fields : <EOL> if not f . editable : <EOL> ignore . add ( f . name ) <EOL> model . change_watcher_spec = WatcherSpec ( ignore , get_master ) <EOL> def get_change_watcher_spec ( obj ) : <EOL> cs = obj . change_watcher_spec <EOL> if cs is None : <EOL> if not watch_all_changes . allow or obj . __class__ . __name__ in watch_all_changes . ignore : <EOL> return None <EOL> cs = WatcherSpec ( [ ] , return_self ) <EOL> obj . change_watcher_spec = cs <EOL> return cs <EOL> def get_master ( obj ) : <EOL> cs = get_change_watcher_spec ( obj ) <EOL> if cs : <EOL> return cs . get_master ( obj ) <EOL> def log_change ( type , request , master , obj , msg = '<STR_LIT>' ) : <EOL> Change ( <EOL> type = type , <EOL> time = timezone . now ( ) , <EOL> user = request . user , <EOL> master = master , <EOL> object = obj , <EOL> diff = msg ) . save ( ) <EOL> @ receiver ( on_ui_updated ) <EOL> def on_update ( sender = None , watcher = None , request = None , ** kw ) : <EOL> """<STR_LIT>""" <EOL> master = get_master ( watcher . watched ) <EOL> if master is None : <EOL> return <EOL> cs = watcher . watched . change_watcher_spec <EOL> changes = [ ] <EOL> for k , old , new in watcher . get_updates ( cs . ignored_fields ) : <EOL> changes . append ( "<STR_LIT>" % <EOL> ( k , dd . obj2str ( old ) , dd . obj2str ( new ) ) ) <EOL> if len ( changes ) == <NUM_LIT:0> : <EOL> msg = '<STR_LIT>' <EOL> elif len ( changes ) == <NUM_LIT:1> : <EOL> msg = changes [ <NUM_LIT:0> ] <EOL> else : <EOL> msg = '<STR_LIT>' + ( '<STR_LIT>' . join ( changes ) ) <EOL> log_change ( ChangeTypes . update , request , master , watcher . watched , msg ) <EOL> @ receiver ( pre_ui_delete ) <EOL> def on_delete ( sender = None , request = None , ** kw ) : <EOL> """<STR_LIT>""" <EOL> master = get_master ( sender ) <EOL> if master is None : <EOL> return <EOL> log_change ( ChangeTypes . delete , request , master , <EOL> sender , dd . obj2str ( sender , True ) ) <EOL> @ receiver ( on_ui_created ) <EOL> def on_create ( sender = None , request = None , ** kw ) : <EOL> """<STR_LIT>""" <EOL> master = get_master ( sender ) <EOL> if master is None : <EOL> return <EOL> log_change ( ChangeTypes . create , request , master , <EOL> sender , dd . obj2str ( sender , True ) ) <EOL> @ receiver ( pre_add_child ) <EOL> def on_add_child ( sender = None , request = None , child = None , ** kw ) : <EOL> master = get_master ( sender ) <EOL> if master is None : <EOL> return <EOL> log_change ( ChangeTypes . add_child , request , master , <EOL> sender , dd . full_model_name ( child ) ) <EOL> @ receiver ( pre_remove_child ) <EOL> def on_remove_child ( sender = None , request = None , child = None , ** kw ) : <EOL> master = get_master ( sender ) <EOL> if master is None : <EOL> return <EOL> log_change ( ChangeTypes . remove_child , request , <EOL> master , sender , dd . full_model_name ( child ) ) <EOL> @ receiver ( pre_merge ) <EOL> def on_merge ( sender = None , request = None , ** kw ) : <EOL> """<STR_LIT:U+0020>""" <EOL> master = get_master ( sender . obj ) <EOL> if master is None : <EOL> return <EOL> log_change ( ChangeTypes . merge , request , <EOL> master , sender . obj , sender . logmsg ( ) ) </s>
