test_yaml.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. # -*- coding: utf-8 -*-
  2. import pytest
  3. import datetime
  4. import difflib
  5. import finoex
  6. import ioex.calcex
  7. import ioex.datetimeex
  8. import os
  9. import pytz
  10. yaml = pytest.importorskip('yaml')
  11. def get_figure_a():
  12. return ioex.calcex.Figure(12.3, u'km')
  13. def get_figure_b():
  14. return ioex.calcex.Figure(12300, u'米')
  15. def get_sum_a():
  16. return finoex.Sum(1.23, u'EUR')
  17. def get_sum_b():
  18. return finoex.Sum(20.45, u'€')
  19. def get_item_a():
  20. return finoex.Item(
  21. name = u'item a',
  22. price_brutto = get_sum_a(),
  23. )
  24. def get_item_b():
  25. return finoex.Item(
  26. name = u'item β',
  27. price_brutto = get_sum_b(),
  28. )
  29. def get_service_a():
  30. return finoex.Service(
  31. duration = ioex.datetimeex.Duration(years = 2),
  32. location = 'vienna',
  33. name = u'service',
  34. price_brutto = finoex.Sum(1.0, u'EUR'),
  35. state = 'success',
  36. )
  37. def get_hosting_service():
  38. return finoex.HostingService(
  39. duration = ioex.datetimeex.Duration(years = 2),
  40. ip_addresses = ['127.0.0.1', '::1'],
  41. location = 'vienna',
  42. name = u'virtual server',
  43. operating_system = 'debian 8',
  44. price_brutto = finoex.Sum(1.0, u'EUR'),
  45. state = 'running',
  46. )
  47. def get_cloud_mining():
  48. return finoex.CloudMining(
  49. hashrate = ioex.calcex.Figure(8, u'TH/s'),
  50. name = u'sha256 BTC',
  51. price_brutto = finoex.Sum(1.0, u'EUR'),
  52. )
  53. def get_service_b():
  54. return finoex.Service(
  55. name = u'service',
  56. price_brutto = finoex.Sum(1.0, u'EUR'),
  57. period = ioex.datetimeex.Period(
  58. start = datetime.datetime(2017, 4, 2, 10, 23),
  59. end = None,
  60. ),
  61. )
  62. def get_person_a():
  63. return finoex.Person(
  64. first_name = u'Fabian Peter',
  65. last_name = u'Hammerle',
  66. )
  67. def get_person_b():
  68. return finoex.Person(
  69. first_name = u'名字',
  70. last_name = u'贵姓',
  71. )
  72. def get_campaign_a():
  73. return finoex.Campaign(
  74. name = u'campaign a',
  75. founder = u'company',
  76. end = datetime.datetime(2016, 7, 23, 9, 23, 17, tzinfo = pytz.timezone('Europe/Vienna')),
  77. )
  78. def get_campaign_b():
  79. return finoex.Campaign(
  80. founder = u'company',
  81. name = u'campaign without end',
  82. website_url = u'http://campaign.com',
  83. )
  84. def get_pledge():
  85. return finoex.Pledge(
  86. campaign = get_campaign_a(),
  87. price_brutto = finoex.Sum(10.0, u'EUR'),
  88. reward = u'great',
  89. )
  90. def get_contribution():
  91. return finoex.Contribution(
  92. campaign = get_campaign_a(),
  93. price_brutto = finoex.Sum(10.0, u'EUR'),
  94. reward = u'product',
  95. )
  96. def get_article():
  97. return finoex.Article(
  98. authors = ['a', 'b'],
  99. depth = finoex.Distance(12.3, u'dm'),
  100. features = u'supergeil',
  101. height = finoex.Distance(123., u'cm'),
  102. maximum_load = ioex.calcex.Figure(40., u'kg'),
  103. name = u'article name',
  104. price_brutto = get_sum_a(),
  105. product_id = u'0815',
  106. quantity = 1,
  107. reseller = u'seller',
  108. shipper = u'shipper',
  109. state = u'goood',
  110. width = finoex.Distance(1.23, u'm'),
  111. )
  112. def get_transportation():
  113. return finoex.Transportation(
  114. name = u'ticket',
  115. price_brutto = get_sum_a(),
  116. departure_point = u'home',
  117. destination_point = u'city',
  118. distance = finoex.Distance(3.21, u'km'),
  119. passenger = get_person_a(),
  120. valid_from = datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.timezone('Europe/Vienna')),
  121. valid_until = datetime.datetime(2016, 7, 14, 18, 50, 4, 0, tzinfo = pytz.utc),
  122. ticket_url = u'https://www.example.com',
  123. estimated_arrival_time = ioex.datetimeex.Period(
  124. start = pytz.timezone('Europe/Vienna').localize(datetime.datetime(2016, 7, 24, 23, 47, 2)),
  125. end = pytz.utc.localize(datetime.datetime(2016, 7, 24, 23, 48, 5)),
  126. ),
  127. )
  128. def get_shipping():
  129. return finoex.Shipping(
  130. price_brutto = get_sum_a(),
  131. destination_point = u'home',
  132. )
  133. def get_taxi_ride():
  134. return finoex.TaxiRide(
  135. name = u'taxi ride',
  136. price_brutto = get_sum_a(),
  137. departure_point = u'home',
  138. destination_point = u'city',
  139. distance = finoex.Distance(3.21, u'km'),
  140. driver = u'driver',
  141. arrival_time = datetime.datetime(2016, 5, 2, 18, 10, tzinfo = pytz.timezone('Europe/Vienna')),
  142. departure_time = datetime.datetime(2016, 5, 2, 18, 25, tzinfo = pytz.timezone('Europe/Vienna')),
  143. )
  144. def get_discount_a():
  145. return finoex.Discount(
  146. name = u'discount a',
  147. amount = get_sum_a(),
  148. )
  149. def get_discount_b():
  150. return finoex.Discount(
  151. name = u'discount β',
  152. amount = get_sum_b(),
  153. )
  154. def get_discount_c():
  155. return finoex.Discount(
  156. amount = get_sum_b(),
  157. code = 'DISCΓ',
  158. name = u'discount c',
  159. )
  160. def get_order_a(items = True, discounts = True):
  161. order = finoex.Order(
  162. platform = u'platformπ',
  163. order_id = u'id',
  164. order_date = datetime.datetime(2016, 5, 8, 0, 18, 17),
  165. customer_id = u'customer',
  166. )
  167. if items:
  168. order.items.append(get_item_a())
  169. order.items.append(get_item_b())
  170. if discounts:
  171. order.discounts.append(get_discount_a())
  172. order.discounts.append(get_discount_b())
  173. return order
  174. def get_order_b():
  175. order = finoex.Order(
  176. platform = u'platformπ',
  177. order_id = u'order_b',
  178. order_date = datetime.datetime(2015, 5, 8, 0, 18, 17),
  179. )
  180. return order
  181. def get_order_c():
  182. order = finoex.Order(
  183. platform = u'γάμμα',
  184. order_id = u'order_βήτα',
  185. order_date = datetime.datetime(2014, 5, 8, 0, 18, 17),
  186. customer_id = u'ρώ',
  187. )
  188. return order
  189. def get_invoice(items = True, discounts = True):
  190. inv = finoex.Invoice(
  191. creditor = u'platformπ',
  192. invoice_id = u'id',
  193. invoice_date = datetime.datetime(2016, 5, 8, 0, 18, 17),
  194. debitor_id = u'customer',
  195. )
  196. if items:
  197. inv.items.append(get_item_a())
  198. inv.items.append(get_item_b())
  199. if discounts:
  200. inv.discounts.append(get_discount_a())
  201. return inv
  202. def get_distance():
  203. return finoex.Distance(2.4142, u'km')
  204. def to_yaml(data):
  205. class Dumper(yaml.Dumper):
  206. pass
  207. ioex.datetimeex.Duration.register_yaml_representer(yaml.Dumper)
  208. ioex.datetimeex.Period.register_yaml_representer(yaml.Dumper)
  209. ioex.calcex.Figure.register_yaml_representer(yaml.Dumper)
  210. finoex.Sum.register_yaml_representer(yaml.Dumper)
  211. finoex.Distance.register_yaml_representer(yaml.Dumper)
  212. return yaml.dump(
  213. data,
  214. default_flow_style = False,
  215. allow_unicode = True,
  216. Dumper = Dumper,
  217. ) #.decode('utf-8')
  218. def yaml_diff(a, b):
  219. return '\n'.join(difflib.ndiff(
  220. to_yaml(a).split('\n'),
  221. to_yaml(b).split('\n'),
  222. ))
  223. @pytest.mark.parametrize('source_object,expected_yaml', [
  224. [datetime.datetime(2016, 7, 14, 13, 50, 4, 0), '2016-07-14 13:50:04\n...\n'],
  225. [datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.timezone('Europe/Vienna')), '2016-07-14 13:50:04+01:05\n...\n'],
  226. [datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.utc), '2016-07-14 13:50:04+00:00\n...\n'],
  227. [finoex.Distance(1.34, u'km'), u"!distance '1.34 km'\n"],
  228. [finoex.Distance(1.34, u'μm'), u"!distance '1.34 μm'\n"],
  229. [get_discount_a(), u"!discount\namount: !sum '1.23 EUR'\nname: discount a\n"],
  230. [get_discount_b(), u"!discount\namount: !sum '20.45 EUR'\nname: discount β\n"],
  231. [get_discount_c(), u"""!discount
  232. amount: !sum '20.45 EUR'
  233. code: DISCΓ
  234. name: discount c
  235. """],
  236. [get_figure_a(), u"!figure '12.3 km'\n"],
  237. [get_figure_b(), u"!figure '12300 米'\n"],
  238. [get_item_a(), u"!item\nname: item a\nprice_brutto: !sum '1.23 EUR'\n"],
  239. [get_item_b(), u"!item\nname: item β\nprice_brutto: !sum '20.45 EUR'\n"],
  240. [get_person_a(), u'!person\nfirst_name: Fabian Peter\nlast_name: Hammerle\n'],
  241. [get_person_b(), u'!person\nfirst_name: 名字\nlast_name: 贵姓\n'],
  242. [get_campaign_a(), u"""!campaign
  243. end: 2016-07-23 09:23:17+01:05
  244. founder: company
  245. name: campaign a
  246. """],
  247. [get_campaign_b(), u"""!campaign
  248. founder: company
  249. name: campaign without end
  250. website_url: http://campaign.com
  251. """],
  252. [get_service_a(), u"""!service
  253. duration: !duration
  254. years: 2
  255. location: vienna
  256. name: service
  257. price_brutto: !sum '1.0 EUR'
  258. state: success
  259. """],
  260. [get_service_b(), u"""!service
  261. name: service
  262. period: !period
  263. end: null
  264. start: 2017-04-02 10:23:00
  265. price_brutto: !sum '1.0 EUR'
  266. """],
  267. [get_hosting_service(), u"""!hosting-service
  268. duration: !duration
  269. years: 2
  270. ip_addresses:
  271. - 127.0.0.1
  272. - ::1
  273. location: vienna
  274. name: virtual server
  275. operating_system: debian 8
  276. price_brutto: !sum '1.0 EUR'
  277. state: running
  278. """],
  279. [get_cloud_mining(), u"""!cloud-mining
  280. hashrate: !figure '8 TH/s'
  281. name: sha256 BTC
  282. price_brutto: !sum '1.0 EUR'
  283. """],
  284. [get_pledge(), u"""!pledge
  285. campaign: !campaign
  286. end: 2016-07-23 09:23:17+01:05
  287. founder: company
  288. name: campaign a
  289. price_brutto: !sum '10.0 EUR'
  290. reward: great
  291. """],
  292. [get_contribution(), u"""!contribution
  293. campaign: !campaign
  294. end: 2016-07-23 09:23:17+01:05
  295. founder: company
  296. name: campaign a
  297. price_brutto: !sum '10.0 EUR'
  298. reward: product
  299. """],
  300. [get_order_a(), u"""!order
  301. customer_id: customer
  302. discounts:
  303. - !discount
  304. amount: !sum '1.23 EUR'
  305. name: discount a
  306. - !discount
  307. amount: !sum '20.45 EUR'
  308. name: discount β
  309. items:
  310. - !item
  311. name: item a
  312. price_brutto: !sum '1.23 EUR'
  313. - !item
  314. name: item β
  315. price_brutto: !sum '20.45 EUR'
  316. order_date: 2016-05-08 00:18:17
  317. order_id: id
  318. platform: platformπ
  319. """],
  320. [get_order_a(discounts = False), u"""!order
  321. customer_id: customer
  322. items:
  323. - !item
  324. name: item a
  325. price_brutto: !sum '1.23 EUR'
  326. - !item
  327. name: item β
  328. price_brutto: !sum '20.45 EUR'
  329. order_date: 2016-05-08 00:18:17
  330. order_id: id
  331. platform: platformπ
  332. """],
  333. [get_article(), u"""!article
  334. authors:
  335. - a
  336. - b
  337. depth: !distance '12.3 dm'
  338. features: supergeil
  339. height: !distance '123.0 cm'
  340. maximum_load: !figure '40.0 kg'
  341. name: article name
  342. price_brutto: !sum '1.23 EUR'
  343. product_id: 0815
  344. quantity: 1
  345. reseller: seller
  346. shipper: shipper
  347. state: goood
  348. width: !distance '1.23 m'
  349. """],
  350. [get_transportation(), u"""!transportation
  351. departure_point: home
  352. destination_point: city
  353. distance: !distance '3.21 km'
  354. estimated_arrival_time: !period
  355. end: 2016-07-24 23:48:05+00:00
  356. start: 2016-07-24 23:47:02+02:00
  357. name: ticket
  358. passenger: !person
  359. first_name: Fabian Peter
  360. last_name: Hammerle
  361. price_brutto: !sum '1.23 EUR'
  362. ticket_url: https://www.example.com
  363. valid_from: 2016-07-14 13:50:04+01:05
  364. valid_until: 2016-07-14 18:50:04+00:00
  365. """],
  366. [get_shipping(), u"""!shipping
  367. destination_point: home
  368. price_brutto: !sum '1.23 EUR'
  369. """],
  370. [get_taxi_ride(), u"""!taxi-ride
  371. arrival_time: 2016-05-02 18:10:00+01:05
  372. departure_point: home
  373. departure_time: 2016-05-02 18:25:00+01:05
  374. destination_point: city
  375. distance: !distance '3.21 km'
  376. driver: driver
  377. name: taxi ride
  378. price_brutto: !sum '1.23 EUR'
  379. """],
  380. [get_invoice(), u"""!invoice
  381. creditor: platformπ
  382. debitor_id: customer
  383. discounts:
  384. - !discount
  385. amount: !sum '1.23 EUR'
  386. name: discount a
  387. invoice_date: 2016-05-08 00:18:17
  388. invoice_id: id
  389. items:
  390. - !item
  391. name: item a
  392. price_brutto: !sum '1.23 EUR'
  393. - !item
  394. name: item β
  395. price_brutto: !sum '20.45 EUR'
  396. """],
  397. ])
  398. def test_to_yaml(source_object, expected_yaml):
  399. assert expected_yaml == to_yaml(source_object)
  400. @pytest.mark.parametrize('expected_object,source_yaml', [
  401. [datetime.datetime(2016, 7, 14, 13, 50, 4, 0), '2016-07-14 13:50:04'],
  402. [datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.timezone('Europe/Vienna')), '2016-07-14 13:50:04+01:05'],
  403. [datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.utc), '2016-07-14 13:50:04+00:00'],
  404. [finoex.Distance(1.34, u'km'), u"!distance '1.34 km'\n"],
  405. [finoex.Distance(1.34, u'μm'), u"!distance '1.34 μm'"],
  406. [get_discount_a(), u"!discount\nname: discount a\namount: !sum '1.23 EUR'\n"],
  407. [get_discount_b(), u"!discount\nname: discount β\namount: !sum '20.45 EUR'\n"],
  408. [get_discount_c(), u"""!discount
  409. amount: !sum 20.45 EUR
  410. name: discount c
  411. code: DISCΓ
  412. """],
  413. [get_figure_a(), '!figure\nunit: km\nvalue: 12.3\n'],
  414. [get_figure_a(), u'!figure\nunit: km\nvalue: 12.3\n'],
  415. [get_figure_b(), '!figure\nunit: 米\nvalue: 12300\n'],
  416. [get_figure_b(), u'!figure\nunit: 米\nvalue: 12300\n'],
  417. [get_item_a(), u"!item\nname: item a\nprice_brutto: !sum '1.23 EUR'\n"],
  418. [get_item_a(), u"!item\nname: item a\nprice_brutto: !sum 1.23 EUR"],
  419. [get_item_a(), u"!item\nname: item a\nprice_brutto: !sum 1.23 €\n"],
  420. [get_item_b(), u"!item\nname: item β\nprice_brutto: !sum '20.45 EUR'\n"],
  421. [get_person_a(), '!person\nfirst_name: Fabian Peter\nlast_name: Hammerle\n'],
  422. [get_person_a(), u'!person\nfirst_name: Fabian Peter\nlast_name: Hammerle\n'],
  423. [get_person_b(), u'!person\nfirst_name: 名字\nlast_name: 贵姓\n'],
  424. [get_campaign_a(), u"""!campaign
  425. name: campaign a
  426. founder: company
  427. end: 2016-07-23 09:23:17+01:05
  428. """],
  429. [get_campaign_b(), u"""!campaign
  430. founder: company
  431. name: campaign without end
  432. website_url: http://campaign.com
  433. """],
  434. [get_service_a(), u"""!service
  435. duration: !duration
  436. years: 2
  437. location: vienna
  438. name: service
  439. price_brutto: !sum '1.0 EUR'
  440. state: success
  441. """],
  442. [get_service_b(), u"""!service
  443. name: service
  444. period: !period
  445. start: 2017-04-02 10:23:00
  446. price_brutto: !sum '1.0 EUR'
  447. """],
  448. [get_hosting_service(), u"""!hosting-service
  449. duration: !duration
  450. years: 2
  451. ip_addresses:
  452. - 127.0.0.1
  453. - ::1
  454. location: vienna
  455. name: virtual server
  456. operating_system: debian 8
  457. price_brutto: !sum '1.0 EUR'
  458. state: running
  459. """],
  460. [get_cloud_mining(), u"""!cloud-mining
  461. hashrate: !figure 8 TH/s
  462. name: sha256 BTC
  463. price_brutto: !sum 1.0 EUR
  464. """],
  465. [get_pledge(), u"""!pledge
  466. campaign: !campaign
  467. name: campaign a
  468. founder: company
  469. end: 2016-07-23 09:23:17+01:05
  470. price_brutto: !sum '10.0 EUR'
  471. reward: great
  472. """],
  473. [get_contribution(), u"""!contribution
  474. campaign: !campaign
  475. end: 2016-07-23 09:23:17+01:05
  476. founder: company
  477. name: campaign a
  478. price_brutto: !sum '10.0 EUR'
  479. reward: product
  480. """],
  481. [[get_person_a(), get_person_b()], u"""
  482. - !person
  483. first_name: Fabian Peter
  484. last_name: Hammerle
  485. - !person
  486. first_name: 名字
  487. last_name: 贵姓"""],
  488. [get_transportation(), u"""!transportation
  489. departure_point: home
  490. destination_point: city
  491. distance: !distance '3.21 km'
  492. name: ticket
  493. price_brutto: !sum '1.23 EUR'
  494. route_map: null
  495. passenger: !person
  496. first_name: Fabian Peter
  497. last_name: Hammerle
  498. ticket_url: https://www.example.com
  499. valid_from: 2016-07-14 13:50:04+01:05
  500. valid_until: 2016-07-14 18:50:04+00:00
  501. estimated_arrival_time: !period
  502. end: 2016-07-24T23:48:05+00:00
  503. start: 2016-07-24T23:47:02+02:00
  504. """],
  505. [get_shipping(), u"""!shipping
  506. destination_point: home
  507. price_brutto: !sum 1.23 EUR
  508. """],
  509. [get_order_a(), u"""!order
  510. customer_id: customer
  511. discounts:
  512. - !discount
  513. amount: !sum '1.23 EUR'
  514. name: discount a
  515. - !discount
  516. amount: !sum '20.45 EUR'
  517. name: discount β
  518. items:
  519. - !item
  520. name: item a
  521. price_brutto: !sum '1.23 EUR'
  522. - !item
  523. name: item β
  524. price_brutto: !sum '20.45 EUR'
  525. order_date: 2016-05-08 00:18:17
  526. order_id: id
  527. platform: platformπ
  528. """],
  529. [get_article(), u"""!article
  530. authors:
  531. - a
  532. - b
  533. delivery_date: null
  534. features: supergeil
  535. name: article name
  536. price_brutto: !sum '1.23 EUR'
  537. product_id: 0815
  538. quantity: 1
  539. reseller: seller
  540. shipper: shipper
  541. state: goood
  542. depth: !distance 12.3 dm
  543. height: !distance 123.0 cm
  544. maximum_load: !figure 40.0 kg
  545. width: !distance 1.23 m
  546. """],
  547. [get_taxi_ride(), u"""!taxi-ride
  548. arrival_time: 2016-05-02 18:10:00+01:05
  549. departure_point: home
  550. departure_time: 2016-05-02 18:25:00+01:05
  551. destination_point: city
  552. distance: !distance '3.21 km'
  553. driver: driver
  554. name: taxi ride
  555. price_brutto: !sum '1.23 EUR'
  556. route_map: null
  557. """],
  558. [get_invoice(), u"""!invoice
  559. creditor: platformπ
  560. debitor_id: customer
  561. invoice_date: 2016-05-08T00:18:17
  562. invoice_id: id
  563. items:
  564. - !item
  565. name: item a
  566. price_brutto: !sum '1.23 EUR'
  567. - !item
  568. name: item β
  569. price_brutto: !sum '20.45 EUR'
  570. discounts:
  571. - !discount
  572. name: discount a
  573. amount: !sum 1.23 EUR
  574. """],
  575. ])
  576. def test_from_yaml(expected_object, source_yaml):
  577. class Loader(yaml.Loader):
  578. pass
  579. ioex.datetimeex.Duration.register_yaml_constructor(Loader)
  580. ioex.datetimeex.Period.register_yaml_constructor(Loader)
  581. ioex.calcex.Figure.register_yaml_constructor(Loader)
  582. finoex.Sum.register_yaml_constructor(Loader)
  583. finoex.Distance.register_yaml_constructor(Loader)
  584. loaded_object = yaml.load(source_yaml, Loader=Loader)
  585. assert loaded_object == expected_object