Files @ 992c91fc90de
Branch filter:

Location: NPO-Accounting/oxrlib/oxrlib/rate.py

Brett Smith
config: Nicer implementation of date parsing.

Keeps less local state through the function, to reduce the risk of that
state getting inconsistent.
import datetime
import decimal
import functools
import json

class Rate:
    FIELDS = [
        'base',
        'disclaimer',
        'license',
        'rates',
        'timestamp',
    ]

    @classmethod
    def walk_fields(cls, get_field, transform_prefix):
        for fieldname in cls.FIELDS:
            value = get_field(fieldname)
            if value is not None:
                try:
                    transformer = getattr(cls, '{}_{}'.format(transform_prefix, fieldname))
                except AttributeError:
                    pass
                else:
                    value = transformer(value)
            yield (fieldname, value)

    def __init__(self, base, rates, **kwargs):
        for key, value in self.walk_fields(kwargs.get, 'deserialize'):
            setattr(self, key, value)
        self.base = base
        self.rates = rates

    @classmethod
    def deserialize_timestamp(cls, value):
        return datetime.datetime.fromtimestamp(value)

    @classmethod
    def serialize_rates(cls, rates):
        return {code: float(rates[code]) for code in rates}

    @classmethod
    def serialize_timestamp(cls, value):
        return int(value.timestamp())

    @classmethod
    def from_json_file(cls, json_file):
        response = json.load(json_file, parse_int=decimal.Decimal, parse_float=decimal.Decimal)
        return cls(**response)

    def convert(self, amount, from_currency, to_currency):
        return amount * self.rates[to_currency] / self.rates[from_currency]

    def serialize(self):
        return dict(self.walk_fields(functools.partial(getattr, self), 'serialize'))