<s> from __future__ import division <EOL> import inspect <EOL> from decimal import ROUND_DOWN , Decimal <EOL> from django . conf import settings <EOL> from django . core . exceptions import ValidationError <EOL> from django . db import models <EOL> from django . db . models import F <EOL> from django . db . models . signals import class_prepared <EOL> from django . utils import translation <EOL> from moneyed import Currency , Money <EOL> from moneyed . localization import _FORMATTER , format_money <EOL> from djmoney import forms <EOL> from . . _compat import ( <EOL> BaseExpression , <EOL> Expression , <EOL> deconstructible , <EOL> smart_unicode , <EOL> split_expression , <EOL> string_types , <EOL> ) <EOL> from . . settings import CURRENCY_CHOICES , DEFAULT_CURRENCY <EOL> from . . utils import get_currency_field_name , prepare_expression <EOL> if '<STR_LIT>' in settings . INSTALLED_APPS : <EOL> try : <EOL> from djmoney_rates . utils import convert_money <EOL> AUTO_CONVERT_MONEY = True <EOL> except ImportError : <EOL> AUTO_CONVERT_MONEY = False <EOL> else : <EOL> AUTO_CONVERT_MONEY = False <EOL> __all__ = ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> SUPPORTED_LOOKUPS = ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) <EOL> class NotSupportedLookup ( Exception ) : <EOL> def __init__ ( self , lookup ) : <EOL> self . lookup = lookup <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % self . lookup <EOL> @ deconstructible <EOL> class MoneyPatched ( Money ) : <EOL> use_l10n = None <EOL> def __float__ ( self ) : <EOL> return float ( self . amount ) <EOL> def _convert_to_local_currency ( self , other ) : <EOL> """<STR_LIT>""" <EOL> if AUTO_CONVERT_MONEY : <EOL> return convert_money ( other . amount , other . currency , self . currency ) <EOL> else : <EOL> return other <EOL> @ classmethod <EOL> def _patch_to_current_class ( cls , money ) : <EOL> """<STR_LIT>""" <EOL> return cls ( money . amount , money . currency ) <EOL> def __pos__ ( self ) : <EOL> return MoneyPatched . _patch_to_current_class ( <EOL> super ( MoneyPatched , self ) . __pos__ ( ) ) <EOL> def __neg__ ( self ) : <EOL> return MoneyPatched . _patch_to_current_class ( <EOL> super ( MoneyPatched , self ) . __neg__ ( ) ) <EOL> def __add__ ( self , other ) : <EOL> other = self . _convert_to_local_currency ( other ) <EOL> return MoneyPatched . _patch_to_current_class ( <EOL> super ( MoneyPatched , self ) . __add__ ( other ) ) <EOL> def __sub__ ( self , other ) : <EOL> other = self . _convert_to_local_currency ( other ) <EOL> return MoneyPatched . _patch_to_current_class ( <EOL> super ( MoneyPatched , self ) . __sub__ ( other ) ) <EOL> def __mul__ ( self , other ) : <EOL> return MoneyPatched . _patch_to_current_class ( <EOL> super ( MoneyPatched , self ) . __mul__ ( other ) ) <EOL> def __eq__ ( self , other ) : <EOL> if hasattr ( other , '<STR_LIT>' ) : <EOL> if self . currency == other . currency : <EOL> return self . amount == other . amount <EOL> raise TypeError ( '<STR_LIT>' + <EOL> '<STR_LIT>' ) <EOL> return False <EOL> def __truediv__ ( self , other ) : <EOL> if isinstance ( other , Money ) : <EOL> return super ( MoneyPatched , self ) . __truediv__ ( other ) <EOL> else : <EOL> return self . _patch_to_current_class ( <EOL> super ( MoneyPatched , self ) . __truediv__ ( other ) ) <EOL> def __rmod__ ( self , other ) : <EOL> return MoneyPatched . _patch_to_current_class ( <EOL> super ( MoneyPatched , self ) . __rmod__ ( other ) ) <EOL> def __get_current_locale ( self ) : <EOL> language = translation . get_language ( ) or settings . LANGUAGE_CODE <EOL> locale = translation . to_locale ( language ) <EOL> if _FORMATTER . get_formatting_definition ( locale ) : <EOL> return locale <EOL> if _FORMATTER . get_formatting_definition ( '<STR_LIT>' % ( locale , locale ) ) : <EOL> return '<STR_LIT>' % ( locale , locale ) <EOL> return '<STR_LIT>' <EOL> def __use_l10n ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . use_l10n is None : <EOL> return settings . USE_L10N <EOL> return self . use_l10n <EOL> def __unicode__ ( self ) : <EOL> if self . __use_l10n ( ) : <EOL> locale = self . __get_current_locale ( ) <EOL> if locale : <EOL> return format_money ( self , locale = locale ) <EOL> return format_money ( self ) <EOL> __str__ = __unicode__ <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . amount . to_integral_value ( ROUND_DOWN ) , self . currency ) <EOL> def get_value ( obj , expr ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( expr , F ) : <EOL> expr = getattr ( obj , expr . name ) <EOL> elif hasattr ( expr , '<STR_LIT:value>' ) : <EOL> expr = expr . value <EOL> return expr <EOL> def validate_money_expression ( obj , expr ) : <EOL> """<STR_LIT>""" <EOL> lhs , rhs = split_expression ( expr ) <EOL> connector = expr . connector <EOL> lhs = get_value ( obj , lhs ) <EOL> rhs = get_value ( obj , rhs ) <EOL> if ( not isinstance ( rhs , Money ) and connector in ( '<STR_LIT:+>' , '<STR_LIT:->' ) ) or connector == '<STR_LIT>' : <EOL> raise ValidationError ( '<STR_LIT>' , code = '<STR_LIT>' ) <EOL> if isinstance ( lhs , Money ) and isinstance ( rhs , Money ) : <EOL> if connector in ( '<STR_LIT:*>' , '<STR_LIT:/>' , '<STR_LIT>' , '<STR_LIT>' ) : <EOL> raise ValidationError ( '<STR_LIT>' , code = '<STR_LIT>' ) <EOL> if lhs . currency != rhs . currency : <EOL> raise ValidationError ( '<STR_LIT>' , code = '<STR_LIT>' ) <EOL> def validate_money_value ( value ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( value , ( list , tuple ) ) and ( len ( value ) != <NUM_LIT:2> or value [ <NUM_LIT:1> ] is None ) : <EOL> raise ValidationError ( <EOL> '<STR_LIT>' , <EOL> code = '<STR_LIT>' , <EOL> params = { '<STR_LIT:value>' : value } , <EOL> ) <EOL> def get_currency ( value ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( value , Money ) : <EOL> return smart_unicode ( value . currency ) <EOL> elif isinstance ( value , ( list , tuple ) ) : <EOL> return value [ <NUM_LIT:1> ] <EOL> class MoneyFieldProxy ( object ) : <EOL> def __init__ ( self , field ) : <EOL> self . field = field <EOL> self . currency_field_name = get_currency_field_name ( self . field . name ) <EOL> def _money_from_obj ( self , obj ) : <EOL> amount = obj . __dict__ [ self . field . name ] <EOL> currency = obj . __dict__ [ self . currency_field_name ] <EOL> if amount is None : <EOL> return None <EOL> return MoneyPatched ( amount = amount , currency = currency ) <EOL> def __get__ ( self , obj , type = None ) : <EOL> if obj is None : <EOL> raise AttributeError ( '<STR_LIT>' ) <EOL> if isinstance ( obj . __dict__ [ self . field . name ] , BaseExpression ) : <EOL> return obj . __dict__ [ self . field . name ] <EOL> if not isinstance ( obj . __dict__ [ self . field . name ] , Money ) : <EOL> obj . __dict__ [ self . field . name ] = self . _money_from_obj ( obj ) <EOL> return obj . __dict__ [ self . field . name ] <EOL> def __set__ ( self , obj , value ) : <EOL> if isinstance ( value , BaseExpression ) : <EOL> validate_money_expression ( obj , value ) <EOL> prepare_expression ( value ) <EOL> else : <EOL> validate_money_value ( value ) <EOL> currency = get_currency ( value ) <EOL> if currency : <EOL> self . set_currency ( obj , currency ) <EOL> value = self . field . to_python ( value ) <EOL> obj . __dict__ [ self . field . name ] = value <EOL> def set_currency ( self , obj , value ) : <EOL> object_currency = obj . __dict__ [ self . currency_field_name ] <EOL> default_currency = str ( self . field . default_currency ) <EOL> if object_currency != value and ( object_currency == default_currency or value != default_currency ) : <EOL> setattr ( obj , self . currency_field_name , value ) <EOL> class CurrencyField ( models . CharField ) : <EOL> description = '<STR_LIT>' <EOL> def __init__ ( self , price_field = None , verbose_name = None , name = None , <EOL> default = DEFAULT_CURRENCY , ** kwargs ) : <EOL> if isinstance ( default , Currency ) : <EOL> default = default . code <EOL> kwargs [ '<STR_LIT:max_length>' ] = <NUM_LIT:3> <EOL> self . price_field = price_field <EOL> self . frozen_by_south = kwargs . pop ( '<STR_LIT>' , False ) <EOL> super ( CurrencyField , self ) . __init__ ( verbose_name , name , default = default , <EOL> ** kwargs ) <EOL> def contribute_to_class ( self , cls , name ) : <EOL> if not self . frozen_by_south and name not in [ f . name for f in cls . _meta . fields ] : <EOL> super ( CurrencyField , self ) . contribute_to_class ( cls , name ) <EOL> class MoneyField ( models . DecimalField ) : <EOL> description = '<STR_LIT>' <EOL> def __init__ ( self , verbose_name = None , name = None , <EOL> max_digits = None , decimal_places = None , <EOL> default = None , <EOL> default_currency = DEFAULT_CURRENCY , <EOL> currency_choices = CURRENCY_CHOICES , ** kwargs ) : <EOL> nullable = kwargs . get ( '<STR_LIT:null>' , False ) <EOL> if default is None and not nullable : <EOL> default = <NUM_LIT:0.0> <EOL> if isinstance ( default , string_types ) : <EOL> try : <EOL> amount , currency = default . split ( '<STR_LIT:U+0020>' ) <EOL> except ValueError : <EOL> amount = default <EOL> currency = default_currency <EOL> default = Money ( Decimal ( amount ) , Currency ( code = currency ) ) <EOL> elif isinstance ( default , ( float , Decimal , int ) ) : <EOL> default = Money ( default , default_currency ) <EOL> if not ( nullable and default is None ) and not isinstance ( default , Money ) : <EOL> raise Exception ( <EOL> '<STR_LIT>' % str ( default ) ) <EOL> if max_digits is None : <EOL> raise Exception ( <EOL> '<STR_LIT>' ) <EOL> if decimal_places is None : <EOL> raise Exception ( <EOL> '<STR_LIT>' ) <EOL> if not default_currency : <EOL> default_currency = default . currency <EOL> self . default_currency = default_currency <EOL> self . currency_choices = currency_choices <EOL> self . frozen_by_south = kwargs . pop ( '<STR_LIT>' , False ) <EOL> super ( MoneyField , self ) . __init__ ( verbose_name , name , max_digits , <EOL> decimal_places , default = default , <EOL> ** kwargs ) <EOL> def to_python ( self , value ) : <EOL> if isinstance ( value , Expression ) : <EOL> return value <EOL> if isinstance ( value , Money ) : <EOL> value = value . amount <EOL> if isinstance ( value , tuple ) : <EOL> value = value [ <NUM_LIT:0> ] <EOL> if isinstance ( value , float ) : <EOL> value = str ( value ) <EOL> return super ( MoneyField , self ) . to_python ( value ) <EOL> def contribute_to_class ( self , cls , name ) : <EOL> cls . _meta . has_money_field = True <EOL> if not self . frozen_by_south : <EOL> self . add_currency_field ( cls , name ) <EOL> super ( MoneyField , self ) . contribute_to_class ( cls , name ) <EOL> setattr ( cls , self . name , MoneyFieldProxy ( self ) ) <EOL> def add_currency_field ( self , cls , name ) : <EOL> """<STR_LIT>""" <EOL> currency_field = CurrencyField ( <EOL> max_length = <NUM_LIT:3> , price_field = self , <EOL> default = self . default_currency , editable = False , <EOL> choices = self . currency_choices <EOL> ) <EOL> currency_field . creation_counter = self . creation_counter <EOL> self . creation_counter += <NUM_LIT:1> <EOL> currency_field_name = get_currency_field_name ( name ) <EOL> cls . add_to_class ( currency_field_name , currency_field ) <EOL> def get_db_prep_save ( self , value , connection ) : <EOL> if isinstance ( value , Expression ) : <EOL> return value <EOL> if isinstance ( value , Money ) : <EOL> value = value . amount <EOL> return super ( MoneyField , self ) . get_db_prep_save ( value , connection ) <EOL> def get_db_prep_lookup ( self , lookup_type , value , connection , prepared = False ) : <EOL> if lookup_type not in SUPPORTED_LOOKUPS : <EOL> raise NotSupportedLookup ( lookup_type ) <EOL> value = self . get_db_prep_save ( value , connection ) <EOL> return super ( MoneyField , self ) . get_db_prep_lookup ( lookup_type , value , connection , prepared ) <EOL> def get_default ( self ) : <EOL> if isinstance ( self . default , Money ) : <EOL> frm = inspect . stack ( ) [ <NUM_LIT:1> ] <EOL> mod = inspect . getmodule ( frm [ <NUM_LIT:0> ] ) <EOL> if mod . __name__ == '<STR_LIT>' : <EOL> return float ( self . default . amount ) <EOL> return self . default <EOL> else : <EOL> return super ( MoneyField , self ) . get_default ( ) <EOL> def formfield ( self , ** kwargs ) : <EOL> defaults = { '<STR_LIT>' : forms . MoneyField } <EOL> defaults . update ( kwargs ) <EOL> defaults [ '<STR_LIT>' ] = self . currency_choices <EOL> return super ( MoneyField , self ) . formfield ( ** defaults ) <EOL> def get_south_default ( self ) : <EOL> return '<STR_LIT:%s>' % str ( self . default ) <EOL> def get_south_default_currency ( self ) : <EOL> return '<STR_LIT>' % str ( self . default_currency . code ) <EOL> def value_to_string ( self , obj ) : <EOL> value = self . _get_val_from_obj ( obj ) <EOL> return self . get_prep_value ( value ) <EOL> def south_field_triple ( self ) : <EOL> """<STR_LIT>""" <EOL> from south . modelsinspector import introspector <EOL> field_class = self . __class__ . __module__ + '<STR_LIT:.>' + self . __class__ . __name__ <EOL> args , kwargs = introspector ( self ) <EOL> kwargs . pop ( '<STR_LIT:default>' ) <EOL> kwargs [ '<STR_LIT>' ] = "<STR_LIT>" % self . default_currency <EOL> return field_class , args , kwargs <EOL> def deconstruct ( self ) : <EOL> name , path , args , kwargs = super ( MoneyField , self ) . deconstruct ( ) <EOL> if self . default is not None : <EOL> kwargs [ '<STR_LIT:default>' ] = self . default . amount <EOL> if self . default_currency != DEFAULT_CURRENCY : <EOL> kwargs [ '<STR_LIT>' ] = str ( self . default_currency ) <EOL> if self . currency_choices != CURRENCY_CHOICES : <EOL> kwargs [ '<STR_LIT>' ] = self . currency_choices <EOL> return name , path , args , kwargs <EOL> try : <EOL> from south . modelsinspector import add_introspection_rules <EOL> rules = [ <EOL> ( ( CurrencyField , ) , <EOL> [ ] , <EOL> { '<STR_LIT:default>' : ( '<STR_LIT:default>' , { '<STR_LIT:default>' : DEFAULT_CURRENCY . code } ) , <EOL> '<STR_LIT:max_length>' : ( '<STR_LIT:max_length>' , { '<STR_LIT:default>' : <NUM_LIT:3> } ) } ) , <EOL> ] <EOL> add_introspection_rules ( rules , [ '<STR_LIT>' ] ) <EOL> except ImportError : <EOL> pass <EOL> def patch_managers ( sender , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> from . managers import money_manager <EOL> if hasattr ( sender . _meta , '<STR_LIT>' ) : <EOL> sender . copy_managers ( [ <EOL> ( _id , name , money_manager ( manager ) ) <EOL> for _id , name , manager in sender . _meta . concrete_managers <EOL> ] ) <EOL> class_prepared . connect ( patch_managers ) </s>
