test_property.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. import unittest
  2. from odml import Property, Section, Document, DType
  3. from odml.property import BaseProperty
  4. from odml.section import BaseSection
  5. class TestProperty(unittest.TestCase):
  6. def setUp(self):
  7. pass
  8. def test_simple_attributes(self):
  9. p_name = "propertyName"
  10. p_origin = "from over there"
  11. p_unit = "pears"
  12. p_uncertainty = "12"
  13. p_ref = "4 8 15 16 23"
  14. p_def = "an odml test property"
  15. p_dep = "yes"
  16. p_dep_val = "42"
  17. prop = Property(name=p_name, value_origin=p_origin, unit=p_unit,
  18. uncertainty=p_uncertainty, reference=p_ref, definition=p_def,
  19. dependency=p_dep, dependency_value=p_dep_val)
  20. self.assertEqual(prop.name, p_name)
  21. self.assertEqual(prop.value_origin, p_origin)
  22. self.assertEqual(prop.unit, p_unit)
  23. self.assertEqual(prop.uncertainty, p_uncertainty)
  24. self.assertEqual(prop.reference, p_ref)
  25. self.assertEqual(prop.definition, p_def)
  26. self.assertEqual(prop.dependency, p_dep)
  27. self.assertEqual(prop.dependency_value, p_dep_val)
  28. # Test setting attributes
  29. prop.name = "%s_edit" % p_name
  30. self.assertEqual(prop.name, "%s_edit" % p_name)
  31. prop.value_origin = "%s_edit" % p_origin
  32. self.assertEqual(prop.value_origin, "%s_edit" % p_origin)
  33. prop.unit = "%s_edit" % p_unit
  34. self.assertEqual(prop.unit, "%s_edit" % p_unit)
  35. prop.uncertainty = 13
  36. self.assertEqual(prop.uncertainty, 13.0)
  37. prop.reference = "%s_edit" % p_ref
  38. self.assertEqual(prop.reference, "%s_edit" % p_ref)
  39. prop.definition = "%s_edit" % p_def
  40. self.assertEqual(prop.definition, "%s_edit" % p_def)
  41. prop.dependency = "%s_edit" % p_dep
  42. self.assertEqual(prop.dependency, "%s_edit" % p_dep)
  43. prop.dependency_value = "%s_edit" % p_dep_val
  44. self.assertEqual(prop.dependency_value, "%s_edit" % p_dep_val)
  45. # Test setting attributes to None when '' is passed.
  46. prop.value_origin = ""
  47. self.assertIsNone(prop.value_origin)
  48. prop.unit = ""
  49. self.assertIsNone(prop.unit)
  50. prop.uncertainty = ""
  51. self.assertIsNone(prop.uncertainty)
  52. prop.reference = ""
  53. self.assertIsNone(prop.reference)
  54. prop.definition = ""
  55. self.assertIsNone(prop.definition)
  56. prop.dependency = ""
  57. self.assertIsNone(prop.dependency)
  58. prop.dependency_value = ""
  59. self.assertIsNone(prop.dependency_value)
  60. def test_value(self):
  61. p = Property("property", 100)
  62. self.assertEqual(p.values[0], 100)
  63. self.assertIsInstance(p.values, list)
  64. p.values = None
  65. self.assertEqual(len(p), 0)
  66. p.values = [1, 2, 3]
  67. p.values = ""
  68. self.assertEqual(len(p), 0)
  69. p.values = [1, 2, 3]
  70. p.values = []
  71. self.assertEqual(len(p), 0)
  72. p.values = [1, 2, 3]
  73. p.values = ()
  74. self.assertEqual(len(p), 0)
  75. p.values.append(5)
  76. self.assertEqual(len(p.values), 0)
  77. p2 = Property("test", {"name": "Marie", "name": "Johanna"})
  78. self.assertEqual(len(p2), 1)
  79. # Test tuple dtype value.
  80. t = Property(name="Location", value='(39.12; 67.19)', dtype='2-tuple')
  81. tuple_value = t.values[0] # As the formed tuple is a list of list
  82. self.assertEqual(tuple_value[0], '39.12')
  83. self.assertEqual(tuple_value[1], '67.19')
  84. # Test invalid tuple length
  85. with self.assertRaises(ValueError):
  86. _ = Property(name="Public-Key", value='(5689; 1254; 687)', dtype='2-tuple')
  87. def test_value_append(self):
  88. # Test append w/o Property value or dtype
  89. prop = Property(name="append")
  90. prop.append(1)
  91. self.assertEqual(prop.dtype, DType.int)
  92. self.assertEqual(prop.values, [1])
  93. # Test append with Property dtype.
  94. prop = Property(name="append", dtype="int")
  95. prop.append(3)
  96. self.assertEqual(prop.values, [3])
  97. # Test append with Property value
  98. prop = Property(name="append", value=[1, 2])
  99. prop.append(3)
  100. self.assertEqual(prop.values, [1, 2, 3])
  101. # Test append with Property list value
  102. prop = Property(name="append", value=[1, 2])
  103. prop.append([3])
  104. self.assertEqual(prop.values, [1, 2, 3])
  105. # Test append of empty values, make sure 0 and False are properly handled
  106. prop = Property(name="append")
  107. prop.append(None)
  108. prop.append("")
  109. prop.append([])
  110. prop.append({})
  111. self.assertEqual(prop.values, [])
  112. prop.append(0)
  113. self.assertEqual(prop.values, [0])
  114. prop.values = None
  115. prop.dtype = None
  116. prop.append(False)
  117. self.assertEqual(prop.values, [False])
  118. prop = Property(name="append", value=[1, 2])
  119. prop.append(None)
  120. prop.append("")
  121. prop.append([])
  122. prop.append({})
  123. self.assertEqual(prop.values, [1, 2])
  124. prop.append(0)
  125. self.assertEqual(prop.values, [1, 2, 0])
  126. # Test fail append with multiple values
  127. prop = Property(name="append", value=[1, 2, 3])
  128. with self.assertRaises(ValueError):
  129. prop.append([4, 5])
  130. self.assertEqual(prop.values, [1, 2, 3])
  131. # Test fail append with mismatching dtype
  132. prop = Property(name="append", value=[1, 2], dtype="int")
  133. with self.assertRaises(ValueError):
  134. prop.append([3.14])
  135. with self.assertRaises(ValueError):
  136. prop.append([True])
  137. with self.assertRaises(ValueError):
  138. prop.append(["5.927"])
  139. self.assertEqual(prop.values, [1, 2])
  140. # Test strict flag
  141. prop.append(3.14, strict=False)
  142. prop.append(True, strict=False)
  143. prop.append("5.927", strict=False)
  144. self.assertEqual(prop.values, [1, 2, 3, 1, 5])
  145. # Make sure non-convertible values still raise an error
  146. with self.assertRaises(ValueError):
  147. prop.append("invalid")
  148. self.assertEqual(prop.values, [1, 2, 3, 1, 5])
  149. p5 = Property("test", value="a string")
  150. p5.append("Freude")
  151. self.assertEqual(len(p5), 2)
  152. self.assertRaises(ValueError, p5.append, "[a, b, c]")
  153. def test_value_extend(self):
  154. prop = Property(name="extend")
  155. # Test extend w/o Property value or dtype.
  156. val = [1, 2, 3]
  157. prop.extend(val)
  158. self.assertEqual(prop.dtype, DType.int)
  159. self.assertEqual(prop.values, val)
  160. # Extend with single value.
  161. prop.extend(4)
  162. self.assertEqual(prop.values, [1, 2, 3, 4])
  163. # Extend with list value.
  164. prop.extend([5, 6])
  165. self.assertEqual(prop.values, [1, 2, 3, 4, 5, 6])
  166. # Test extend w/o Property value
  167. prop = Property(name="extend", dtype="float")
  168. prop.extend([1.0, 2.0, 3.0])
  169. self.assertEqual(prop.values, [1.0, 2.0, 3.0])
  170. # Test extend with Property value
  171. prop = Property(name="extend", value=10)
  172. prop.extend([20, 30, '40'])
  173. self.assertEqual(prop.values, [10, 20, 30, 40])
  174. # Test extend fail with mismatching dtype
  175. with self.assertRaises(ValueError):
  176. prop.extend(['5', 6, 7])
  177. with self.assertRaises(ValueError):
  178. prop.extend([5, 6, 'a'])
  179. # Test extend via Property
  180. prop = Property(name="extend", value=["a", "b"])
  181. ext_prop = Property(name="value extend", value="c")
  182. prop.extend(ext_prop)
  183. self.assertEqual(prop.values, ["a", "b", "c"])
  184. ext_prop.values = ["d", "e"]
  185. prop.extend(ext_prop)
  186. self.assertEqual(prop.values, ["a", "b", "c", "d", "e"])
  187. ext_prop = Property(name="value extend", value=[1, 2 ,3])
  188. with self.assertRaises(ValueError):
  189. prop.extend(ext_prop)
  190. self.assertEqual(prop.values, ["a", "b", "c", "d", "e"])
  191. # Test extend via Property unit check
  192. prop = Property(name="extend", value=[1, 2], unit="mV")
  193. ext_prop = Property(name="extend", value=[3, 4], unit="mV")
  194. prop.extend(ext_prop)
  195. self.assertEqual(prop.values, [1, 2, 3, 4])
  196. ext_prop.unit = "kV"
  197. with self.assertRaises(ValueError):
  198. prop.extend(ext_prop)
  199. self.assertEqual(prop.values, [1, 2, 3, 4])
  200. ext_prop.unit = ""
  201. with self.assertRaises(ValueError):
  202. prop.extend(ext_prop)
  203. self.assertEqual(prop.values, [1, 2, 3, 4])
  204. # Test strict flag
  205. prop = Property(name="extend", value=[1, 2], dtype="int")
  206. with self.assertRaises(ValueError):
  207. prop.extend([3.14, True, "5.927"])
  208. self.assertEqual(prop.values, [1, 2])
  209. prop.extend([3.14, True, "5.927"], strict=False)
  210. self.assertEqual(prop.values, [1, 2, 3, 1, 5])
  211. # Make sure non-convertible values still raise an error
  212. with self.assertRaises(ValueError):
  213. prop.extend([6, "some text"])
  214. def test_get_set_value(self):
  215. values = [1, 2, 3, 4, 5]
  216. p = Property("property", value=values)
  217. self.assertEqual(len(p), 5)
  218. for s, d in zip(values, p.values):
  219. self.assertEqual(s, d)
  220. count = 0
  221. for v in p:
  222. count += 1
  223. self.assertEqual(count, len(values))
  224. p[0] = 10
  225. self.assertEqual(p[0], 10)
  226. with self.assertRaises(ValueError):
  227. p[1] = 'stringval'
  228. def test_bool_conversion(self):
  229. # Success tests
  230. p = Property(name='received', value=[1, 0, 1, 0, 1])
  231. assert(p.dtype == 'int')
  232. p.dtype = DType.boolean
  233. assert(p.dtype == 'boolean')
  234. assert(p.values == [True, False, True, False, True])
  235. q = Property(name='sent', value=['False', True, 'TRUE', '0', 't', 'F', '1'])
  236. assert(q.dtype == 'string')
  237. q.dtype = DType.boolean
  238. assert(q.dtype == 'boolean')
  239. assert(q.values == [False, True, True, False, True, False, True])
  240. # Failure tests
  241. curr_val = [3, 0, 1, 0, 8]
  242. curr_type = 'int'
  243. p = Property(name='received', value=curr_val)
  244. assert(p.dtype == curr_type)
  245. with self.assertRaises(ValueError):
  246. p.dtype = DType.boolean
  247. assert(p.dtype == curr_type)
  248. assert(p.values == curr_val)
  249. curr_type = 'string'
  250. q = Property(name='sent', value=['False', True, 'TRUE', '0', 't', '12', 'Ft'])
  251. assert(q.dtype == curr_type)
  252. with self.assertRaises(ValueError):
  253. q.dtype = DType.boolean
  254. assert(q.dtype == curr_type)
  255. def test_str_to_int_convert(self):
  256. # Success Test
  257. p = Property(name='cats_onboard', value=['3', '0', '1', '0', '8'])
  258. assert(p.dtype == 'string')
  259. p.dtype = DType.int
  260. assert(p.dtype == 'int')
  261. assert(p.values == [3, 0, 1, 0, 8])
  262. # Failure Test
  263. p = Property(name='dogs_onboard', value=['7', '20', '1 Dog', 'Seven'])
  264. assert(p.dtype == 'string')
  265. with self.assertRaises(ValueError):
  266. p.dtype = DType.int
  267. assert(p.dtype == 'string')
  268. assert(p.values == ['7', '20', '1 Dog', 'Seven'])
  269. def test_name(self):
  270. # Test id is used when name is not provided
  271. p = Property()
  272. self.assertIsNotNone(p.name)
  273. self.assertEqual(p.name, p.id)
  274. # Test name is properly set on init
  275. name = "rumpelstilzchen"
  276. p = Property(name)
  277. self.assertEqual(p.name, name)
  278. # Test name can be properly set on single and connected Properties
  279. prop = Property()
  280. self.assertNotEqual(prop.name, "prop")
  281. prop.name = "prop"
  282. self.assertEqual(prop.name, "prop")
  283. sec = Section()
  284. prop_a = Property(parent=sec)
  285. self.assertNotEqual(prop_a.name, "prop_a")
  286. prop_a.name = "prop_a"
  287. self.assertEqual(prop_a.name, "prop_a")
  288. # Test property name can be changed with siblings
  289. prop_b = Property(name="prop_b", parent=sec)
  290. self.assertEqual(prop_b.name, "prop_b")
  291. prop_b.name = "prop"
  292. self.assertEqual(prop_b.name, "prop")
  293. # Test property name set will fail on existing sibling with same name
  294. with self.assertRaises(KeyError):
  295. prop_b.name = "prop_a"
  296. self.assertEqual(prop_b.name, "prop")
  297. def test_parent(self):
  298. p = Property("property_section", parent=Section("S"))
  299. self.assertIsInstance(p.parent, BaseSection)
  300. self.assertEqual(len(p.parent._props), 1)
  301. """ Test if child is removed from _props of a parent after assigning
  302. a new parent to the child """
  303. prop_parent = p.parent
  304. p.parent = Section("S1")
  305. self.assertEqual(len(prop_parent._props), 0)
  306. self.assertIsInstance(p.parent, BaseSection)
  307. self.assertIsInstance(p.parent._props[0], BaseProperty)
  308. prop_parent = p.parent
  309. p.parent = None
  310. self.assertIsNone(p.parent)
  311. self.assertEqual(len(prop_parent._props), 0)
  312. with self.assertRaises(ValueError):
  313. Property("property_prop", parent=Property("P"))
  314. with self.assertRaises(ValueError):
  315. Property("property_doc", parent=Document())
  316. def test_dtype(self):
  317. prop = Property(name="prop")
  318. # Test assignment of all supported dtypes.
  319. for curr_type in DType:
  320. prop.dtype = curr_type
  321. self.assertEqual(prop.dtype, curr_type)
  322. # Test assignment of dtype alias.
  323. prop.dtype = "bool"
  324. self.assertEqual(prop.dtype, "bool")
  325. prop.dtype = "str"
  326. self.assertEqual(prop.dtype, "str")
  327. # Test assignment of tuple.
  328. prop.dtype = "2-tuple"
  329. self.assertEqual(prop.dtype, "2-tuple")
  330. # Test set None
  331. prop.dtype = None
  332. self.assertIsNone(prop.dtype)
  333. # Test assignment fails.
  334. with self.assertRaises(AttributeError):
  335. prop.dtype = 1
  336. with self.assertRaises(AttributeError):
  337. prop.dtype = "crash and burn"
  338. with self.assertRaises(AttributeError):
  339. prop.dtype = "x-tuple"
  340. # Test not setting None when a property contains values.
  341. prop.values = [1, 2, 3]
  342. self.assertIsNotNone(prop.dtype)
  343. prop.dtype = None
  344. self.assertIsNotNone(prop.dtype)
  345. def test_get_path(self):
  346. doc = Document()
  347. sec = Section(name="parent", parent=doc)
  348. # Check root path for a detached Property.
  349. prop = Property(name="prop")
  350. self.assertEqual("/", prop.get_path())
  351. # Check absolute path of Property in a Document.
  352. prop.parent = sec
  353. self.assertEqual("/%s:%s" % (sec.name, prop.name), prop.get_path())
  354. def test_id(self):
  355. p = Property(name="P")
  356. self.assertIsNotNone(p.id)
  357. p = Property("P", oid="79b613eb-a256-46bf-84f6-207df465b8f7")
  358. self.assertEqual(p.id, "79b613eb-a256-46bf-84f6-207df465b8f7")
  359. p = Property("P", oid="id")
  360. self.assertNotEqual(p.id, "id")
  361. # Make sure id cannot be reset programmatically.
  362. with self.assertRaises(AttributeError):
  363. p.id = "someId"
  364. def test_new_id(self):
  365. prop = Property(name="prop")
  366. old_id = prop.id
  367. # Test assign new generated id.
  368. prop.new_id()
  369. self.assertNotEqual(old_id, prop.id)
  370. # Test assign new custom id.
  371. old_id = prop.id
  372. prop.new_id("79b613eb-a256-46bf-84f6-207df465b8f7")
  373. self.assertNotEqual(old_id, prop.id)
  374. self.assertEqual("79b613eb-a256-46bf-84f6-207df465b8f7", prop.id)
  375. # Test invalid custom id exception.
  376. with self.assertRaises(ValueError):
  377. prop.new_id("crash and burn")
  378. def test_merge_check(self):
  379. # Test dtype check
  380. source = Property(name="source", dtype="string")
  381. destination = Property(name="destination", dtype="string")
  382. destination.merge_check(source)
  383. source.dtype = "int"
  384. with self.assertRaises(ValueError):
  385. destination.merge_check(source)
  386. destination.merge_check(source, False)
  387. # Test value check
  388. source = Property(name="source", value=[1, 2, 3])
  389. destination = Property(name="destination", value=[4, 5, 6])
  390. destination.merge_check(source)
  391. # Test value convertable
  392. source = Property(name="source", value=["7", "8"])
  393. with self.assertRaises(ValueError):
  394. destination.merge_check(source)
  395. destination.merge_check(source, False)
  396. # Test value not convertable
  397. source = Property(name="source", value=["nine", "ten"])
  398. with self.assertRaises(ValueError):
  399. destination.merge_check(source)
  400. with self.assertRaises(ValueError):
  401. destination.merge_check(source, False)
  402. # Test unit check
  403. source = Property(name="source", unit="Hz")
  404. destination = Property(name="destination", unit="Hz")
  405. destination.merge_check(source)
  406. source.unit = "s"
  407. with self.assertRaises(ValueError):
  408. destination.merge_check(source)
  409. destination.merge_check(source, False)
  410. # Test uncertainty check
  411. source = Property(name="source", uncertainty=0.0)
  412. destination = Property(name="destination", uncertainty=0.0)
  413. destination.merge_check(source)
  414. source.uncertainty = 10.0
  415. with self.assertRaises(ValueError):
  416. destination.merge_check(source)
  417. destination.merge_check(source, False)
  418. # Test definition check
  419. source = Property(name="source", definition="Freude\t schoener\nGoetterfunken\n")
  420. destination = Property(name="destination",
  421. definition="FREUDE schoener GOETTERfunken")
  422. destination.merge_check(source)
  423. source.definition = "Freunde schoender Goetterfunken"
  424. with self.assertRaises(ValueError):
  425. destination.merge_check(source)
  426. destination.merge_check(source, False)
  427. # Test reference check
  428. source = Property(name="source", reference="portal.g-node.org")
  429. destination = Property(name="destination", reference="portal.g-node.org")
  430. destination.merge_check(source)
  431. source.reference = "portal.g-node.org/odml/terminologies/v1.1"
  432. with self.assertRaises(ValueError):
  433. destination.merge_check(source)
  434. destination.merge_check(source, False)
  435. # Test value origin check
  436. source = Property(name="source", value_origin="file")
  437. destination = Property(name="destination", value_origin="file")
  438. destination.merge_check(source)
  439. source.value_origin = "other file"
  440. with self.assertRaises(ValueError):
  441. destination.merge_check(source)
  442. destination.merge_check(source, False)
  443. def test_merge(self):
  444. p_dst = Property("p1", value=[1, 2, 3], unit="Hz", definition="Freude\t schoener\nGoetterfunken\n",
  445. reference="portal.g-node.org", uncertainty=0.0, value_origin="file")
  446. p_src = Property("p2", value=[2, 4, 6], unit="Hz", definition="FREUDE schoener GOETTERfunken")
  447. test_p = p_dst.clone()
  448. test_p.merge(p_src)
  449. self.assertEqual(len(test_p.values), 5)
  450. p_inv_unit = p_src.clone()
  451. p_inv_unit.unit = 's'
  452. p_inv_def = p_src.clone()
  453. p_inv_def.definition = "Freunde schoender Goetterfunken"
  454. p_inv_uncert = p_src.clone()
  455. p_inv_uncert.uncertainty = 10.0
  456. p_inv_ref = p_src.clone()
  457. p_inv_ref.reference = "test"
  458. p_inv_origin = p_src.clone()
  459. p_inv_origin.value_origin = "other file"
  460. test_p = p_dst.clone()
  461. self.assertRaises(ValueError, test_p.merge, p_inv_unit)
  462. self.assertRaises(ValueError, test_p.merge, p_inv_def)
  463. self.assertRaises(ValueError, test_p.merge, p_inv_uncert)
  464. self.assertRaises(ValueError, test_p.merge, p_inv_ref)
  465. self.assertRaises(ValueError, test_p.merge, p_inv_origin)
  466. test_p.reference = None
  467. test_p.merge(p_src)
  468. self.assertEqual(test_p.reference, p_src.reference)
  469. test_p.unit = ""
  470. test_p.merge(p_src)
  471. self.assertEqual(test_p.unit, p_src.unit)
  472. test_p.uncertainty = None
  473. test_p.merge(p_src)
  474. self.assertEqual(test_p.uncertainty, p_src.uncertainty)
  475. test_p.definition = ""
  476. test_p.merge(p_src)
  477. self.assertEqual(test_p.definition, p_src.definition)
  478. test_p.value_origin = ""
  479. test_p.merge(p_src)
  480. self.assertEqual(test_p.value_origin, p_src.value_origin)
  481. double_p = Property("adouble", value=3.14)
  482. int_p = Property("aint", value=3)
  483. self.assertRaises(ValueError, double_p.merge, int_p)
  484. int_p.merge(double_p, strict=False)
  485. self.assertEqual(len(int_p), 2)
  486. def test_clone(self):
  487. sec = Section(name="parent")
  488. # Check different id.
  489. prop = Property(name="original")
  490. clone_prop = prop.clone()
  491. self.assertNotEqual(prop.id, clone_prop.id)
  492. # Check parent removal in clone.
  493. prop.parent = sec
  494. clone_prop = prop.clone()
  495. self.assertIsNotNone(prop.parent)
  496. self.assertIsNone(clone_prop.parent)
  497. # Check keep_id
  498. prop = Property(name="keepid")
  499. clone_prop = prop.clone(True)
  500. self.assertEqual(prop.id, clone_prop.id)
  501. def test_get_merged_equivalent(self):
  502. sec = Section(name="parent")
  503. mersec = Section(name="merged_section")
  504. merprop_other = Property(name="other_prop", value="other")
  505. merprop = Property(name="prop", value=[1, 2, 3])
  506. # Check None on unset parent.
  507. prop = Property(name="prop")
  508. self.assertIsNone(prop.get_merged_equivalent())
  509. # Check None on parent without merged Section.
  510. prop.parent = sec
  511. self.assertIsNone(prop.get_merged_equivalent())
  512. # Check None on parent with merged Section but no attached Property.
  513. sec.merge(mersec)
  514. self.assertIsNone(prop.get_merged_equivalent())
  515. # Check None on parent with merged Section and unequal Property.
  516. merprop_other.parent = mersec
  517. self.assertIsNone(prop.get_merged_equivalent())
  518. # Check receiving merged equivalent Property.
  519. merprop.parent = mersec
  520. self.assertIsNotNone(prop.get_merged_equivalent())
  521. self.assertEqual(prop.get_merged_equivalent(), merprop)
  522. def test_comparison(self):
  523. p_name = "propertyName"
  524. p_origin = "from over there"
  525. p_unit = "pears"
  526. p_uncertainty = "+-12"
  527. p_ref = "4 8 15 16 23"
  528. p_def = "an odml test property"
  529. p_dep = "yes"
  530. p_dep_val = "42"
  531. p_val = ["a", "b"]
  532. prop_a = Property(name=p_name, value_origin=p_origin, unit=p_unit,
  533. uncertainty=p_uncertainty, reference=p_ref, definition=p_def,
  534. dependency=p_dep, dependency_value=p_dep_val, value=p_val)
  535. prop_b = Property(name=p_name, value_origin=p_origin, unit=p_unit,
  536. uncertainty=p_uncertainty, reference=p_ref, definition=p_def,
  537. dependency=p_dep, dependency_value=p_dep_val, value=p_val)
  538. self.assertEqual(prop_a, prop_b)
  539. prop_b.name = 'newPropertyName'
  540. self.assertNotEqual(prop_a, prop_b)
  541. if __name__ == "__main__":
  542. print("TestProperty")
  543. tp = TestProperty()
  544. tp.test_value()
  545. tp.test_merge()