# -*- coding: utf-8 -*- import pytest import datetime import difflib import finoex import ioex.calcex import ioex.datetimeex import os import pytz yaml = pytest.importorskip('yaml') def get_figure_a(): return ioex.calcex.Figure(12.3, u'km') def get_figure_b(): return ioex.calcex.Figure(12300, u'米') def get_sum_a(): return finoex.Sum(1.23, u'EUR') def get_sum_b(): return finoex.Sum(20.45, u'€') def get_item_a(sub_items = False): item = finoex.Item( name = u'item a', price_brutto = get_sum_a(), ) if sub_items: item.sub_items.append(get_item_b()) return item def get_item_b(): return finoex.Item( name = u'item β', price_brutto = get_sum_b(), ) def get_service_a(): return finoex.Service( duration = ioex.datetimeex.Duration(years = 2), ip_addresses = ['::1'], location = 'vienna', name = u'service', price_brutto = finoex.Sum(1.0, u'EUR'), state = 'success', ) def get_hosting_service(): return finoex.HostingService( duration = ioex.datetimeex.Duration(years = 2), ip_addresses = ['127.0.0.1', '::1'], location = 'vienna', name = u'virtual server', operating_system = 'debian 8', price_brutto = finoex.Sum(1.0, u'EUR'), state = 'running', ) def get_cloud_mining(): return finoex.CloudMining( hashrate = ioex.calcex.Figure(8, u'TH/s'), name = u'sha256 BTC', price_brutto = finoex.Sum(1.0, u'EUR'), ) def get_service_b(): return finoex.Service( name = u'service', price_brutto = finoex.Sum(1.0, u'EUR'), period = ioex.datetimeex.Period( start = datetime.datetime(2017, 4, 2, 10, 23), end = None, ), ) def get_person_a(): return finoex.Person( first_name = u'Fabian Peter', last_name = u'Hammerle', ) def get_person_b(): return finoex.Person( first_name = u'名字', last_name = u'贵姓', ) def get_campaign_a(): return finoex.Campaign( name = u'campaign a', founder = u'company', end = datetime.datetime(2016, 7, 23, 9, 23, 17, tzinfo = pytz.timezone('Europe/Vienna')), ) def get_campaign_b(): return finoex.Campaign( founder = u'company', name = u'campaign without end', website_url = u'http://campaign.com', ) def get_pledge(): return finoex.Pledge( campaign = get_campaign_a(), price_brutto = finoex.Sum(10.0, u'EUR'), reward = u'great', ) def get_contribution(): return finoex.Contribution( campaign = get_campaign_a(), price_brutto = finoex.Sum(10.0, u'EUR'), reward = u'product', ) def get_article(): return finoex.Article( access_option = 'download', authors = ['a', 'b'], depth = finoex.Distance(12.3, u'dm'), features = u'supergeil', height = finoex.Distance(123., u'cm'), maximum_load = ioex.calcex.Figure(40., u'kg'), name = u'article name', price_brutto = get_sum_a(), product_id = u'0815', quantity = 1, release_date = datetime.date(2017, 10, 24), reseller = u'seller', shipper = u'shipper', state = u'goood', width = finoex.Distance(1.23, u'm'), ) def get_transportation(period=False): arrival_time = pytz.timezone('Europe/Vienna').localize( datetime.datetime(2016, 7, 24, 23, 47, 35) ) if period: arrival_time = ioex.datetimeex.Period( start=arrival_time, end=arrival_time + datetime.timedelta(days=2), ) return finoex.Transportation( name = u'ticket', price_brutto = get_sum_a(), departure_point = u'home', destination_point = u'city', distance = finoex.Distance(3.21, u'km'), passenger = get_person_a(), valid_from = datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.timezone('Europe/Vienna')), valid_until = datetime.datetime(2016, 7, 14, 18, 50, 4, 0, tzinfo = pytz.utc), ticket_url = u'https://www.example.com', estimated_arrival_time = ioex.datetimeex.Period( start = pytz.timezone('Europe/Vienna').localize(datetime.datetime(2016, 7, 24, 23, 47, 2)), end = pytz.utc.localize(datetime.datetime(2016, 7, 24, 23, 48, 5)), ), arrival_time=arrival_time, ) def get_shipping(): return finoex.Shipping( price_brutto = get_sum_a(), destination_point = u'home', tracking_number = 'LX123456789CN', ) def get_taxi_ride(): return finoex.TaxiRide( name = u'taxi ride', price_brutto = get_sum_a(), departure_point = u'home', destination_point = u'city', distance = finoex.Distance(3.21, u'km'), driver = u'driver', arrival_time = datetime.datetime(2016, 5, 2, 18, 10, tzinfo = pytz.timezone('Europe/Vienna')), departure_time = datetime.datetime(2016, 5, 2, 18, 25, tzinfo = pytz.timezone('Europe/Vienna')), ) def get_discount_a(): return finoex.Discount( name = u'discount a', amount = get_sum_a(), ) def get_discount_b(): return finoex.Discount( name = u'discount β', amount = get_sum_b(), ) def get_discount_c(): return finoex.Discount( amount = get_sum_b(), code = 'DISCΓ', name = u'discount c', ) def get_order_a(items = True, discounts = True): order = finoex.Order( customer_id = u'customer', debitor_address='@home', debitor_comment='important note', order_date = datetime.datetime(2016, 5, 8, 0, 18, 17), order_id = u'id', platform = u'platformπ', platform_view_url = 'http://i.dont.know', ) if items: order.items.append(get_item_a()) order.items.append(get_item_b()) if discounts: order.discounts.append(get_discount_a()) order.discounts.append(get_discount_b()) return order def get_order_b(): order = finoex.Order( platform = u'platformπ', order_id = u'order_b', order_date = datetime.datetime(2015, 5, 8, 0, 18, 17), ) return order def get_order_c(): order = finoex.Order( platform = u'γάμμα', order_id = u'order_βήτα', order_date = datetime.datetime(2014, 5, 8, 0, 18, 17), customer_id = u'ρώ', ) return order def get_invoice(items = True, discounts = True): inv = finoex.Invoice( creditor = u'platformπ', debitor_id = u'customer', debitor_address='@home', debitor_comment='important note', invoice_date = datetime.datetime(2016, 5, 8, 0, 18, 17), invoice_id = u'id', invoice_url = 'http://example.com/invoice.pdf', ) if items: inv.items.append(get_item_a()) inv.items.append(get_item_b()) if discounts: inv.discounts.append(get_discount_a()) return inv def get_distance(): return finoex.Distance(2.4142, u'km') def to_yaml(data): class Dumper(yaml.Dumper): pass ioex.datetimeex.Duration.register_yaml_representer(yaml.Dumper) ioex.datetimeex.Period.register_yaml_representer(yaml.Dumper) ioex.calcex.Figure.register_yaml_representer(yaml.Dumper) finoex.Sum.register_yaml_representer(yaml.Dumper) finoex.Distance.register_yaml_representer(yaml.Dumper) return yaml.dump( data, default_flow_style = False, allow_unicode = True, Dumper = Dumper, ) #.decode('utf-8') def yaml_diff(a, b): return '\n'.join(difflib.ndiff( to_yaml(a).split('\n'), to_yaml(b).split('\n'), )) @pytest.mark.parametrize('source_object,expected_yaml', [ [datetime.datetime(2016, 7, 14, 13, 50, 4, 0), '2016-07-14 13:50:04\n...\n'], [datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.timezone('Europe/Vienna')), '2016-07-14 13:50:04+01:05\n...\n'], [datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.utc), '2016-07-14 13:50:04+00:00\n...\n'], [finoex.Distance(1.34, u'km'), u"!distance '1.34 km'\n"], [finoex.Distance(1.34, u'μm'), u"!distance '1.34 μm'\n"], [get_discount_a(), u"!discount\namount: !sum '1.23 EUR'\nname: discount a\n"], [get_discount_b(), u"!discount\namount: !sum '20.45 EUR'\nname: discount β\n"], [get_discount_c(), u"""!discount amount: !sum '20.45 EUR' code: DISCΓ name: discount c """], [get_figure_a(), u"!figure '12.3 km'\n"], [get_figure_b(), u"!figure '12300 米'\n"], [get_item_a(), u"!item\nname: item a\nprice_brutto: !sum '1.23 EUR'\n"], [get_item_a(sub_items=True), u"""!item name: item a price_brutto: !sum '1.23 EUR' sub_items: - !item name: item β price_brutto: !sum '20.45 EUR' """], [get_item_b(), u"!item\nname: item β\nprice_brutto: !sum '20.45 EUR'\n"], [get_person_a(), u'!person\nfirst_name: Fabian Peter\nlast_name: Hammerle\n'], [get_person_b(), u'!person\nfirst_name: 名字\nlast_name: 贵姓\n'], [get_campaign_a(), u"""!campaign end: 2016-07-23 09:23:17+01:05 founder: company name: campaign a """], [get_campaign_b(), u"""!campaign founder: company name: campaign without end website_url: http://campaign.com """], [get_service_a(), u"""!service duration: !duration years: 2 ip_addresses: - ::1 location: vienna name: service price_brutto: !sum '1.0 EUR' state: success """], [get_service_b(), u"""!service name: service period: !period end: null start: 2017-04-02 10:23:00 price_brutto: !sum '1.0 EUR' """], [get_hosting_service(), u"""!hosting-service duration: !duration years: 2 ip_addresses: - 127.0.0.1 - ::1 location: vienna name: virtual server operating_system: debian 8 price_brutto: !sum '1.0 EUR' state: running """], [get_cloud_mining(), u"""!cloud-mining hashrate: !figure '8 TH/s' name: sha256 BTC price_brutto: !sum '1.0 EUR' """], [get_pledge(), u"""!pledge campaign: !campaign end: 2016-07-23 09:23:17+01:05 founder: company name: campaign a price_brutto: !sum '10.0 EUR' reward: great """], [get_contribution(), u"""!contribution campaign: !campaign end: 2016-07-23 09:23:17+01:05 founder: company name: campaign a price_brutto: !sum '10.0 EUR' reward: product """], [get_order_a(), u"""!order customer_id: customer debitor_address: '@home' debitor_comment: important note discounts: - !discount amount: !sum '1.23 EUR' name: discount a - !discount amount: !sum '20.45 EUR' name: discount β items: - !item name: item a price_brutto: !sum '1.23 EUR' - !item name: item β price_brutto: !sum '20.45 EUR' order_date: 2016-05-08 00:18:17 order_id: id platform: platformπ platform_view_url: http://i.dont.know """], [get_order_a(discounts = False), u"""!order customer_id: customer debitor_address: '@home' debitor_comment: important note items: - !item name: item a price_brutto: !sum '1.23 EUR' - !item name: item β price_brutto: !sum '20.45 EUR' order_date: 2016-05-08 00:18:17 order_id: id platform: platformπ platform_view_url: http://i.dont.know """], [get_article(), u"""!article access_option: download authors: - a - b depth: !distance '12.3 dm' features: supergeil height: !distance '123.0 cm' maximum_load: !figure '40.0 kg' name: article name price_brutto: !sum '1.23 EUR' product_id: 0815 quantity: 1 release_date: 2017-10-24 reseller: seller shipper: shipper state: goood width: !distance '1.23 m' """], [get_transportation(period=False), u"""!transportation arrival_time: 2016-07-24 23:47:35+02:00 departure_point: home destination_point: city distance: !distance '3.21 km' estimated_arrival_time: !period end: 2016-07-24 23:48:05+00:00 start: 2016-07-24 23:47:02+02:00 name: ticket passenger: !person first_name: Fabian Peter last_name: Hammerle price_brutto: !sum '1.23 EUR' ticket_url: https://www.example.com valid_from: 2016-07-14 13:50:04+01:05 valid_until: 2016-07-14 18:50:04+00:00 """], [get_transportation(period=True), u"""!transportation arrival_time: !period end: 2016-07-26 23:47:35+02:00 start: 2016-07-24 23:47:35+02:00 departure_point: home destination_point: city distance: !distance '3.21 km' estimated_arrival_time: !period end: 2016-07-24 23:48:05+00:00 start: 2016-07-24 23:47:02+02:00 name: ticket passenger: !person first_name: Fabian Peter last_name: Hammerle price_brutto: !sum '1.23 EUR' ticket_url: https://www.example.com valid_from: 2016-07-14 13:50:04+01:05 valid_until: 2016-07-14 18:50:04+00:00 """], [get_shipping(), u"""!shipping destination_point: home price_brutto: !sum '1.23 EUR' tracking_number: LX123456789CN """], [get_taxi_ride(), u"""!taxi-ride arrival_time: 2016-05-02 18:10:00+01:05 departure_point: home departure_time: 2016-05-02 18:25:00+01:05 destination_point: city distance: !distance '3.21 km' driver: driver name: taxi ride price_brutto: !sum '1.23 EUR' """], [get_invoice(), u"""!invoice creditor: platformπ debitor_address: '@home' debitor_comment: important note debitor_id: customer discounts: - !discount amount: !sum '1.23 EUR' name: discount a invoice_date: 2016-05-08 00:18:17 invoice_id: id invoice_url: http://example.com/invoice.pdf items: - !item name: item a price_brutto: !sum '1.23 EUR' - !item name: item β price_brutto: !sum '20.45 EUR' """], ]) def test_to_yaml(source_object, expected_yaml): assert expected_yaml == to_yaml(source_object) @pytest.mark.parametrize('expected_object,source_yaml', [ [datetime.datetime(2016, 7, 14, 13, 50, 4, 0), '2016-07-14 13:50:04'], [datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.timezone('Europe/Vienna')), '2016-07-14 13:50:04+01:05'], [datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.utc), '2016-07-14 13:50:04+00:00'], [finoex.Distance(1.34, u'km'), u"!distance '1.34 km'\n"], [finoex.Distance(1.34, u'μm'), u"!distance '1.34 μm'"], [get_discount_a(), u"!discount\nname: discount a\namount: !sum '1.23 EUR'\n"], [get_discount_b(), u"!discount\nname: discount β\namount: !sum '20.45 EUR'\n"], [get_discount_c(), u"""!discount amount: !sum 20.45 EUR name: discount c code: DISCΓ """], [get_figure_a(), '!figure\nunit: km\nvalue: 12.3\n'], [get_figure_a(), u'!figure\nunit: km\nvalue: 12.3\n'], [get_figure_b(), '!figure\nunit: 米\nvalue: 12300\n'], [get_figure_b(), u'!figure\nunit: 米\nvalue: 12300\n'], [get_item_a(), u"!item\nname: item a\nprice_brutto: !sum '1.23 EUR'\n"], [get_item_a(), u"!item\nname: item a\nprice_brutto: !sum 1.23 EUR"], [get_item_a(sub_items=True), u"""!item name: item a price_brutto: !sum '1.23 EUR' sub_items: - !item name: item β price_brutto: !sum '20.45 EUR' """], [get_item_a(), u"!item\nname: item a\nprice_brutto: !sum 1.23 €\n"], [get_item_b(), u"!item\nname: item β\nprice_brutto: !sum '20.45 EUR'\n"], [get_person_a(), '!person\nfirst_name: Fabian Peter\nlast_name: Hammerle\n'], [get_person_a(), u'!person\nfirst_name: Fabian Peter\nlast_name: Hammerle\n'], [get_person_b(), u'!person\nfirst_name: 名字\nlast_name: 贵姓\n'], [get_campaign_a(), u"""!campaign name: campaign a founder: company end: 2016-07-23 09:23:17+01:05 """], [get_campaign_b(), u"""!campaign founder: company name: campaign without end website_url: http://campaign.com """], [get_service_a(), u"""!service duration: !duration years: 2 ip_addresses: - ::1 location: vienna name: service price_brutto: !sum '1.0 EUR' state: success """], [get_service_b(), u"""!service name: service period: !period start: 2017-04-02 10:23:00 price_brutto: !sum '1.0 EUR' """], [get_hosting_service(), u"""!hosting-service duration: !duration years: 2 ip_addresses: - 127.0.0.1 - ::1 location: vienna name: virtual server operating_system: debian 8 price_brutto: !sum '1.0 EUR' state: running """], [get_cloud_mining(), u"""!cloud-mining hashrate: !figure 8 TH/s name: sha256 BTC price_brutto: !sum 1.0 EUR """], [get_pledge(), u"""!pledge campaign: !campaign name: campaign a founder: company end: 2016-07-23 09:23:17+01:05 price_brutto: !sum '10.0 EUR' reward: great """], [get_contribution(), u"""!contribution campaign: !campaign end: 2016-07-23 09:23:17+01:05 founder: company name: campaign a price_brutto: !sum '10.0 EUR' reward: product """], [[get_person_a(), get_person_b()], u""" - !person first_name: Fabian Peter last_name: Hammerle - !person first_name: 名字 last_name: 贵姓"""], [get_transportation(period=False), u"""!transportation arrival_time: 2016-07-24 23:47:35+02:00 departure_point: home destination_point: city distance: !distance '3.21 km' name: ticket price_brutto: !sum '1.23 EUR' route_map: null passenger: !person first_name: Fabian Peter last_name: Hammerle ticket_url: https://www.example.com valid_from: 2016-07-14 13:50:04+01:05 valid_until: 2016-07-14 18:50:04+00:00 estimated_arrival_time: !period end: 2016-07-24T23:48:05+00:00 start: 2016-07-24T23:47:02+02:00 """], [get_transportation(period=True), u"""!transportation arrival_time: !period end: 2016-07-26 23:47:35+02:00 start: 2016-07-24 23:47:35+02:00 departure_point: home destination_point: city distance: !distance '3.21 km' estimated_arrival_time: !period end: 2016-07-24 23:48:05+00:00 start: 2016-07-24 23:47:02+02:00 name: ticket passenger: !person first_name: Fabian Peter last_name: Hammerle price_brutto: !sum '1.23 EUR' ticket_url: https://www.example.com valid_from: 2016-07-14 13:50:04+01:05 valid_until: 2016-07-14 18:50:04+00:00 """], [get_shipping(), u"""!shipping destination_point: home price_brutto: !sum 1.23 EUR tracking_number: LX123456789CN """], [get_order_a(), u"""!order customer_id: customer debitor_address: '@home' debitor_comment: important note discounts: - !discount amount: !sum '1.23 EUR' name: discount a - !discount amount: !sum '20.45 EUR' name: discount β items: - !item name: item a price_brutto: !sum '1.23 EUR' - !item name: item β price_brutto: !sum '20.45 EUR' order_date: 2016-05-08 00:18:17 order_id: id platform: platformπ platform_view_url: http://i.dont.know """], [get_article(), u"""!article access_option: download authors: - a - b delivery_date: null features: supergeil name: article name price_brutto: !sum '1.23 EUR' product_id: 0815 quantity: 1 release_date: 2017-10-24 reseller: seller shipper: shipper state: goood depth: !distance 12.3 dm height: !distance 123.0 cm maximum_load: !figure 40.0 kg width: !distance 1.23 m """], [get_taxi_ride(), u"""!taxi-ride arrival_time: 2016-05-02 18:10:00+01:05 departure_point: home departure_time: 2016-05-02 18:25:00+01:05 destination_point: city distance: !distance '3.21 km' driver: driver name: taxi ride price_brutto: !sum '1.23 EUR' route_map: null """], [get_invoice(), u"""!invoice creditor: platformπ debitor_address: '@home' debitor_comment: important note debitor_id: customer invoice_date: 2016-05-08T00:18:17 invoice_id: id invoice_url: http://example.com/invoice.pdf items: - !item name: item a price_brutto: !sum '1.23 EUR' - !item name: item β price_brutto: !sum '20.45 EUR' discounts: - !discount name: discount a amount: !sum 1.23 EUR """], ]) def test_from_yaml(expected_object, source_yaml): class Loader(yaml.Loader): pass ioex.datetimeex.Duration.register_yaml_constructor(Loader) ioex.datetimeex.Period.register_yaml_constructor(Loader) ioex.calcex.Figure.register_yaml_constructor(Loader) finoex.Sum.register_yaml_constructor(Loader) finoex.Distance.register_yaml_constructor(Loader) loaded_object = yaml.load(source_yaml, Loader=Loader) assert loaded_object == expected_object