| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 | # -*- coding: utf-8 -*-import yamlimport yaml.representerimport datetimeyaml.Dumper.add_representer(unicode, yaml.representer.SafeRepresenter.represent_unicode)class Figure(yaml.YAMLObject):    yaml_tag = u"!figure"    def __init__(self, value, unit):        self.value = value        self.unit = unit    def get_value(self):        return self._value    def set_value(self, value):        self._value = value    """ use property() instead of decorator to enable overriding """    value = property(get_value, set_value)    def get_unit(self):        return self._unit    def set_unit(self, unit):        assert type(unit) is unicode        self._unit = unit    """ use property() instead of decorator to enable overriding """    unit = property(get_unit, set_unit)    def __eq__(self, other):        return type(self) == type(other) and self.value == other.value and self.unit == other.unit    def __ne__(self, other):        return not (self == other)    @classmethod    def from_yaml(cls, loader, node):        attr = loader.construct_mapping(node)        print(type(attr['unit']), attr['unit'])        return cls(                value = attr['value'],                unit = unicode(attr['unit']),                )    @classmethod    def to_yaml(cls, dumper, figure):        return dumper.represent_mapping(                cls.yaml_tag,                {'unit': figure.get_unit(), 'value': figure.get_value()},                )class Distance(Figure):    def __init__(self, value, unit):        assert type(value) is float        super(Distance, self).__init__(value, unit)    @property    def metres(self):        if self.unit == 'km':            return self.value * 1000        else:            raise Exception()class Sum(Figure):    def __init__(self, value, currency):        super(Sum, self).__init__(value, currency)    def get_value(self):        return super(Sum, self).get_value()    def set_value(self, value):        assert type(value) is float        super(Sum, self).set_value(value)    """ use property() instead of decorator to enable overriding """    value = property(get_value, set_value)    @property    def currency(self):        return self.unit    def get_unit(self):        return super(Sum, self).get_unit()    def set_unit(self, currency):        if currency == u'€':            currency = u'EUR'        assert type(currency) is unicode        assert currency in [u'EUR']        super(Sum, self).set_unit(currency)    """ use property() instead of decorator to enable overriding """    unit = property(get_unit, set_unit)class Discount(object):    def __init__(            self,            name = None,            amount = None,            ):        assert type(name) is unicode        self.name = name        assert type(amount) is Sum        assert amount.value >= 0        self.amount = amount    def dict_repr(self):        return {            'name': self.name,            'value': self.amount.value,            'value_currency': self.amount.currency,            }    @staticmethod    def from_dict(attr):        return Discount(                name = attr['name'],                amount = Sum(attr['value'], attr['value_currency']),                )    def __eq__(self, other):        return type(self) == type(other) and self.name == other.name and self.amount == other.amount    def __ne__(self, other):        return not (self == other)yaml.SafeDumper.add_representer(Discount, lambda dumper, discount: dumper.represent_dict(discount.dict_repr()))class Order(object):    def __init__(self, platform, order_id, order_date, customer_id = None):        assert type(platform) is unicode        self.platform = platform        assert type(order_id) is unicode        self.order_id = order_id        if type(order_date) is datetime.datetime:            order_date = order_date.date()        assert type(order_date) is datetime.date        self.order_date = order_date        assert customer_id is None or type(customer_id) is unicode        self.customer_id = customer_id        self.items = []        self.discounts = []    def dict_repr(self):        return {k: v for (k, v) in {            'articles': self.items,            'customer_id': self.customer_id,            'discounts': self.discounts,            'order_date': self.order_date.strftime('%Y-%m-%d'),            'order_id': self.order_id,            'platform': self.platform,            }.items() if v is not None}    @staticmethod    def from_dict(attr):        order = Order(                platform = attr['platform'],                order_id = attr['order_id'],                order_date = datetime.datetime.strptime(attr['order_date'], '%Y-%m-%d'),                )        if 'customer_id' in attr:            order.customer_id = attr['customer_id']        for item in attr['articles']:            if type(item) is dict:                item = Item.from_dict(item)            assert isinstance(item, Item)            order.items.append(item)        for discount in attr['discounts']:            if type(discount) is dict:                discount = Discount.from_dict(discount)            assert isinstance(discount, Discount)            order.discounts.append(discount)        return order    def __eq__(self, other):        return (type(self) == type(other)                and vars(self) == vars(other))    def __ne__(self, other):        return not (self == other)yaml.SafeDumper.add_representer(Order, lambda dumper, order: dumper.represent_dict(order.dict_repr()))class Item(object):    def __init__(            self,            name = None,            price_brutto = None,            ):        assert type(name) is unicode        self.name = name        assert type(price_brutto) is Sum        self.price_brutto = price_brutto    def dict_repr(self):        return {            'name': self.name,            'price_brutto': self.price_brutto.value,            'price_brutto_currency': self.price_brutto.currency,            }    @staticmethod    def from_dict(attr):        return Item(                name = attr['name'],                price_brutto = Sum(attr['price_brutto'], attr['price_brutto_currency']),                )    def __eq__(self, other):        return type(self) == type(other) and self.name == other.name and self.price_brutto == other.price_brutto    def __ne__(self, other):        return not (self == other)yaml.SafeDumper.add_representer(Item, lambda dumper, item: dumper.represent_dict(item.dict_repr()))class Article(Item):    def __init__(            self,            quantity = None,            authors = [],            state = None,            reseller = None,            shipper = None,            **kwargs            ):        super(Article, self).__init__(**kwargs)        assert type(quantity) is int        self.quantity = quantity        assert type(authors) is list        self.authors = authors        assert state is None or type(state) is unicode        self.state = state        assert reseller is None or type(reseller) is unicode        self.reseller = reseller        assert shipper is None or type(shipper) is unicode        self.shipper = shipper        self.delivery_date = None    def dict_repr(self):        attr = super(Article, self).dict_repr()        attr.update({            'delivery_date': self.delivery_date,            'quantity': self.quantity,            'reseller': self.reseller,            'shipper': self.shipper,            'state': self.state,            })        if len(self.authors) > 0:            attr['authors'] = self.authors        return attryaml.SafeDumper.add_representer(Article, lambda dumper, article: dumper.represent_dict(article.dict_repr()))class Transportation(Item):    def __init__(            self,            departure_point = None,            destination_point = None,            distance = None,            route_map = None,            **kwargs            ):        super(Transportation, self).__init__(**kwargs)        assert type(departure_point) is unicode        self.departure_point = departure_point        assert type(destination_point) is unicode        self.destination_point = destination_point        assert distance is None or type(distance) is Distance        self.distance = distance        assert route_map is None or type(route_map) is str        self.route_map = route_map    def dict_repr(self):        attr = super(Transportation, self).dict_repr()        attr.update({            'departure_point': self.departure_point,            'destination_point': self.destination_point,            'distance_metres': self.distance.metres if self.distance else None,            'route_map': self.route_map,            })        return attryaml.SafeDumper.add_representer(Transportation, lambda dumper, transportation: dumper.represent_dict(transportation.dict_repr()))class TaxiRide(Transportation):    def __init__(self, name = None, driver = None, arrival_time = None, departure_time = None, **kwargs):        if name is None:            name = u'Taxi Ride'        super(TaxiRide, self).__init__(name = name, **kwargs)        assert type(driver) is unicode        self.driver = driver        assert arrival_time is None or type(arrival_time) is datetime.datetime        self.arrival_time = arrival_time        assert departure_time is None or type(departure_time) is datetime.datetime        self.departure_time = departure_time    def dict_repr(self):        attr = super(TaxiRide, self).dict_repr()        attr.update({            'arrival_time': self.arrival_time.strftime('%Y-%m-%d %H:%M') if self.arrival_time else None,            'departure_time': self.departure_time.strftime('%Y-%m-%d %H:%M') if self.departure_time else None,            'driver': self.driver,            })        return attryaml.SafeDumper.add_representer(TaxiRide, lambda dumper, taxi_ride: dumper.represent_dict(taxi_ride.dict_repr()))
 |