<s> from __future__ import division , absolute_import , print_function , unicode_literals <EOL> from collections import Mapping <EOL> from copy import copy , deepcopy <EOL> from datetime import date , time , datetime , timedelta , tzinfo <EOL> from decimal import Decimal <EOL> from uuid import UUID <EOL> from django . conf import settings <EOL> from django . core . exceptions import FieldDoesNotExist <EOL> from django . db import models <EOL> from django . db . models import ManyToManyField , ManyToOneRel <EOL> from django . utils import six <EOL> __all__ = ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> IMMUTABLE_TYPES = set ( getattr ( settings , '<STR_LIT>' , ( <EOL> type ( None ) , bool , float , complex , Decimal , <EOL> six . text_type , six . binary_type , tuple , frozenset , <EOL> date , time , datetime , timedelta , tzinfo , <EOL> UUID <EOL> ) + six . integer_types + six . string_types ) ) <EOL> INFINITELY_ITERABLE_IMMUTABLE_TYPES = set ( getattr ( settings , '<STR_LIT>' , ( six . text_type , six . binary_type ) + six . string_types ) ) <EOL> class DoesNotExist : <EOL> """<STR_LIT>""" <EOL> pass <EOL> def is_mutable ( obj ) : <EOL> if type ( obj ) not in IMMUTABLE_TYPES : <EOL> return True <EOL> elif type ( obj ) not in INFINITELY_ITERABLE_IMMUTABLE_TYPES : <EOL> try : <EOL> for sub_obj in iter ( obj ) : <EOL> if is_mutable ( sub_obj ) : <EOL> return True <EOL> except TypeError : <EOL> pass <EOL> return False <EOL> class BaseChangeTracker ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( BaseChangeTracker , self ) . __init__ ( * args , ** kwargs ) <EOL> self . _mutable_fields = { } <EOL> self . _changed_fields = { } <EOL> def __getattribute__ ( self , name ) : <EOL> """<STR_LIT>""" <EOL> value = super ( BaseChangeTracker , self ) . __getattribute__ ( name ) <EOL> if ( <EOL> not hasattr ( value , '<STR_LIT>' ) and <EOL> '<STR_LIT>' in super ( BaseChangeTracker , self ) . __getattribute__ ( '<STR_LIT>' ) <EOL> and name in ( field . attname for field in super ( BaseChangeTracker , self ) . __getattribute__ ( '<STR_LIT>' ) . concrete_fields ) <EOL> ) : <EOL> if is_mutable ( value ) : <EOL> super ( BaseChangeTracker , self ) . __getattribute__ ( '<STR_LIT>' ) [ name ] = deepcopy ( value ) <EOL> return value <EOL> def __setattr__ ( self , name , value ) : <EOL> """<STR_LIT>""" <EOL> if hasattr ( self , '<STR_LIT>' ) and name in super ( BaseChangeTracker , self ) . __getattribute__ ( '<STR_LIT>' ) . _forward_fields_map : <EOL> try : <EOL> field = self . _meta . get_field ( name ) <EOL> except FieldDoesNotExist : <EOL> field = None <EOL> if field and not field . hidden and field . __class__ not in ( ManyToManyField , ManyToOneRel ) : <EOL> old = self . __dict__ . get ( field . attname , DoesNotExist ) <EOL> if old is not DoesNotExist and field . is_relation : <EOL> try : <EOL> hydrated_old = getattr ( self , getattr ( self . __class__ , field . name ) . cache_name ) <EOL> if hydrated_old . pk != old : <EOL> hydrated_old = DoesNotExist <EOL> except AttributeError : <EOL> hydrated_old = DoesNotExist <EOL> else : <EOL> hydrated_old = DoesNotExist <EOL> super ( BaseChangeTracker , self ) . __setattr__ ( name , value ) <EOL> new = self . __dict__ . get ( field . attname , DoesNotExist ) <EOL> try : <EOL> changed = ( old != new ) <EOL> except Exception : <EOL> changed = True <EOL> if changed : <EOL> if field . attname in self . _changed_fields : <EOL> if self . _changed_fields [ field . attname ] == new : <EOL> self . _changed_fields . pop ( field . attname , None ) <EOL> if field . attname != field . name : <EOL> self . _changed_fields . pop ( field . name , None ) <EOL> else : <EOL> self . _changed_fields [ field . attname ] = copy ( old ) <EOL> if field . attname != field . name and hydrated_old is not DoesNotExist : <EOL> self . _changed_fields [ field . name ] = copy ( hydrated_old ) <EOL> else : <EOL> super ( BaseChangeTracker , self ) . __setattr__ ( name , value ) <EOL> else : <EOL> super ( BaseChangeTracker , self ) . __setattr__ ( name , value ) <EOL> def save ( self , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> super ( BaseChangeTracker , self ) . save ( * args , ** kwargs ) <EOL> self . _mutable_fields = { } <EOL> self . _changed_fields = { } <EOL> class SaveTheChange ( BaseChangeTracker ) : <EOL> """<STR_LIT>""" <EOL> def save ( self , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> if self . pk and hasattr ( self , '<STR_LIT>' ) and hasattr ( self , '<STR_LIT>' ) and '<STR_LIT>' not in kwargs and not kwargs . get ( '<STR_LIT>' , False ) : <EOL> kwargs [ '<STR_LIT>' ] = ( <EOL> [ key for key , value in six . iteritems ( self . _changed_fields ) ] + <EOL> [ key for key , value in six . iteritems ( self . _mutable_fields ) if hasattr ( self , key ) and getattr ( self , key ) != value ] <EOL> ) <EOL> super ( SaveTheChange , self ) . save ( * args , ** kwargs ) <EOL> class OldValues ( Mapping ) : <EOL> def __init__ ( self , instance ) : <EOL> self . instance = instance <EOL> def __getitem__ ( self , field_name ) : <EOL> field = self . instance . _meta . _forward_fields_map [ field_name ] <EOL> try : <EOL> if field . attname not in self . instance . _changed_fields : <EOL> return getattr ( self . instance , field . name ) <EOL> elif field . name in self . instance . _changed_fields : <EOL> return self . instance . _changed_fields [ field . name ] <EOL> elif field . is_relation and self . instance . _changed_fields [ field . attname ] is not None : <EOL> try : <EOL> self . instance . _changed_fields [ field . name ] = getattr ( <EOL> self . instance . __class__ , <EOL> field . name <EOL> ) . get_queryset ( ) . get ( pk = self . instance . _changed_fields [ field . attname ] ) <EOL> except self . instance . DoesNotExist : <EOL> self . instance . _changed_fields [ field . name ] = DoesNotExist <EOL> else : <EOL> return self . instance . _changed_fields [ field . attname ] <EOL> except ( AttributeError , KeyError ) : <EOL> raise KeyError ( field_name ) <EOL> def __iter__ ( self ) : <EOL> for field in self . instance . _meta . get_fields ( ) : <EOL> yield field . name <EOL> def __len__ ( self ) : <EOL> return len ( self . instance . _meta . get_fields ( ) ) <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % repr ( self . instance ) <EOL> class TrackChanges ( BaseChangeTracker ) : <EOL> """<STR_LIT>""" <EOL> @ property <EOL> def has_changed ( self ) : <EOL> """<STR_LIT>""" <EOL> return bool ( self . _changed_fields ) <EOL> @ property <EOL> def changed_fields ( self ) : <EOL> """<STR_LIT>""" <EOL> return set ( self . _meta . _forward_fields_map [ name ] . name for name in self . _changed_fields . keys ( ) ) <EOL> @ property <EOL> def old_values ( self ) : <EOL> """<STR_LIT>""" <EOL> return OldValues ( self ) <EOL> def revert_fields ( self , field_names = None ) : <EOL> """<STR_LIT>""" <EOL> if not field_names : <EOL> for field_name in self . changed_fields : <EOL> self . revert_field ( field_name ) <EOL> else : <EOL> for field_name in field_names : <EOL> self . revert_field ( field_name ) <EOL> def revert_field ( self , field_name ) : <EOL> if field_name in self . _meta . _forward_fields_map : <EOL> field = self . _meta . _forward_fields_map [ field_name ] <EOL> if field . name in self . _changed_fields : <EOL> super ( BaseChangeTracker , self ) . __setattr__ ( field . name , self . _changed_fields [ field . name ] ) <EOL> self . _changed_fields . pop ( field . name ) <EOL> if field . attname in self . _changed_fields : <EOL> super ( BaseChangeTracker , self ) . __setattr__ ( field . attname , self . _changed_fields [ field . attname ] ) <EOL> if field . is_relation : <EOL> hydrated_old = getattr ( self , getattr ( self . __class__ , field . name ) . cache_name , DoesNotExist ) <EOL> if hydrated_old is not DoesNotExist and ( hydrated_old is None or hydrated_old . pk != self . _changed_fields [ field . attname ] ) : <EOL> delattr ( self , getattr ( self . __class__ , field . name ) . cache_name ) <EOL> self . _changed_fields . pop ( field . attname ) <EOL> class HideMetaOpts ( models . base . ModelBase ) : <EOL> """<STR_LIT>""" <EOL> default_meta_opts = { <EOL> '<STR_LIT>' : ( ) , <EOL> } <EOL> hide_unknown_opts = False <EOL> def __new__ ( cls , name , bases , attrs ) : <EOL> if not [ b for b in bases if isinstance ( b , HideMetaOpts ) ] : <EOL> return super ( HideMetaOpts , cls ) . __new__ ( cls , name , bases , attrs ) <EOL> else : <EOL> meta_opts = deepcopy ( cls . default_meta_opts ) <EOL> if '<STR_LIT:Meta>' in attrs and attrs [ '<STR_LIT:Meta>' ] . __module__ != '<STR_LIT>' : <EOL> meta = attrs . get ( '<STR_LIT:Meta>' ) <EOL> else : <EOL> for base in bases : <EOL> meta = getattr ( base , '<STR_LIT>' , None ) <EOL> if meta : <EOL> break <EOL> if meta : <EOL> for opt , value in vars ( meta ) . items ( ) : <EOL> if opt not in models . options . DEFAULT_NAMES and ( cls . hide_unknown_opts or opt in meta_opts ) : <EOL> meta_opts [ opt ] = value <EOL> delattr ( meta , opt ) <EOL> new_class = super ( HideMetaOpts , cls ) . __new__ ( cls , name , bases , attrs ) <EOL> if meta : <EOL> for opt in meta_opts : <EOL> setattr ( meta , opt , meta_opts [ opt ] ) <EOL> for opt in meta_opts : <EOL> setattr ( new_class . _meta , opt , meta_opts [ opt ] ) <EOL> return new_class </s>
