test_yaml.py 16 KB

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