test_samplefile.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. import os
  2. import re
  3. import sys
  4. import unittest
  5. try:
  6. from StringIO import StringIO
  7. except ImportError:
  8. from io import StringIO
  9. import odml
  10. from odml.info import FORMAT_VERSION
  11. from odml.tools import xmlparser
  12. from .util import create_test_dir
  13. try:
  14. unicode = unicode
  15. except NameError:
  16. unicode = str
  17. def dump(doc, filename):
  18. """
  19. Helper function to dump a document for debugging purposes
  20. """
  21. if sys.version_info < (3, 0):
  22. odml_string = unicode(xmlparser.XMLWriter(doc))
  23. else:
  24. odml_string = str(xmlparser.XMLWriter(doc))
  25. open(filename, "w").write(odml_string)
  26. def parse(data):
  27. """
  28. Parses strings to quickly create odml-documents
  29. e.g.:
  30. s1[t1] mapping [T1]
  31. - p1
  32. s2[t1]
  33. - s21[t2] linked to /s1/s2
  34. """
  35. lines = data.strip(" ").strip("\n").split("\n")
  36. offset = len(re.compile(r'(\s*)').match(lines[0]).group())
  37. pat = re.compile(r'(?P<name>\w+)(\[(?P<type>\w+)\])?(\s+mapping \[(?P<dst>'
  38. r'[\w:]+)\])?(\s+linked to (?P<link>[\w/]+))?')
  39. parents = [odml.Document(), None]
  40. for line in lines:
  41. line = line[offset:]
  42. while len(parents) > 1:
  43. parp_ref = (len(parents) - 2) * 2
  44. if line.startswith(" " * parp_ref):
  45. line = line[parp_ref:]
  46. break
  47. parents.pop()
  48. if line.startswith('- '):
  49. line = line[2:]
  50. else:
  51. parents.pop()
  52. try:
  53. match_line = pat.match(line).groupdict()
  54. except:
  55. print("error parsing", repr(line))
  56. raise
  57. if match_line['type'] is None:
  58. obj = odml.Property(name=match_line['name'], value="[val]")
  59. else:
  60. obj = odml.Section(name=match_line['name'], type=match_line['type'])
  61. if match_line['dst'] is not None:
  62. obj.mapping = 'map#%s' % match_line['dst']
  63. if match_line['link'] is not None:
  64. obj._link = match_line['link']
  65. parents[-1].append(obj)
  66. parents.append(obj)
  67. return parents[0]
  68. class SampleFileCreator:
  69. def create_document(self):
  70. doc = odml.Document()
  71. for i in range(3):
  72. doc.append(self.create_section("sec %d" % i))
  73. return doc
  74. def create_section(self, name, depth=0):
  75. sec = odml.Section(name=name, type=name.replace("sec", "type"))
  76. if depth < 1:
  77. for i in range(2):
  78. sec.append(self.create_section("%s,%d" % (name, i), depth=depth + 1))
  79. if name.endswith("1"):
  80. for i in range(3):
  81. sec.append(self.create_property("%s:%d" % (name, i)))
  82. return sec
  83. @staticmethod
  84. def create_property(name):
  85. return odml.Property(name=name.replace("sec", "prop"),
  86. value=name.replace("sec", "val"))
  87. class SampleFileCreatorTest(unittest.TestCase):
  88. @staticmethod
  89. def test_sample_file():
  90. _ = SampleFileCreator().create_document()
  91. class SampleFileOperationTest(unittest.TestCase):
  92. def setUp(self):
  93. doc = SampleFileCreator().create_document()
  94. doc.sections['sec 0'].sections['sec 0,1'].type = "test"
  95. self.doc = doc
  96. def test_find_key(self):
  97. self.assertEqual(self.doc.find(key="sec 1,1"), None)
  98. # find distant child
  99. sec = self.doc.find_related(key="sec 1,1")
  100. self.assertEqual(sec.name, "sec 1,1")
  101. # find sibling
  102. res = sec.find_related(key="sec 0,0")
  103. self.assertEqual(res, None)
  104. sec = sec.find_related(key="sec 1,0")
  105. self.assertEqual(sec.name, "sec 1,0")
  106. # find parent
  107. res = sec.find_related(key="sec 0")
  108. self.assertEqual(res, None)
  109. sec = sec.find_related(key="sec 1")
  110. self.assertEqual(sec.name, "sec 1")
  111. # find section by type
  112. self.assertEqual(self.doc.find_related(type="test").name, "sec 0,1")
  113. def test_xml_writer_version(self):
  114. doc = odml.Document()
  115. if sys.version_info < (3, 0):
  116. val = unicode(xmlparser.XMLWriter(doc))
  117. else:
  118. val = str(xmlparser.XMLWriter(doc))
  119. self.assertIn('version="%s"' % FORMAT_VERSION, val)
  120. doc = xmlparser.XMLReader().from_string(val)
  121. # This test is switched off until the XML versioning support is implemented
  122. # self.assertEqual(doc._xml_version, FORMAT_VERSION)
  123. def test_save(self):
  124. base_path = create_test_dir(__file__)
  125. for module in [xmlparser.XMLWriter]:
  126. path = os.path.join(base_path, "temp.odml")
  127. doc = module(self.doc)
  128. doc.write_file(path)
  129. os.remove(path)
  130. def test_restore(self):
  131. modules = [(xmlparser.XMLWriter, xmlparser.XMLReader)]
  132. for Writer, Reader in modules:
  133. doc = Writer(self.doc)
  134. doc = StringIO(unicode(doc))
  135. doc = Reader().from_file(doc)
  136. self.assertEqual(doc, self.doc)
  137. # for a,b in zip(doc.sections, self.doc.sections):
  138. # print "sec cmp", a, b
  139. # self.assertEqual(a, b)
  140. # print "A ---------------------------------"
  141. # for sec in doc.sections:
  142. # xmlparser.dump_section(sec)
  143. # print "B ---------------------------------"
  144. # for sec in self.doc.sections:
  145. # xmlparser.dump_section(sec)
  146. # print "-----------------------------------"
  147. class AttributeTest(unittest.TestCase):
  148. def test_value_int(self):
  149. prop = odml.Property("test", 1, dtype="int")
  150. self.assertEqual(prop.values[0], 1)
  151. def test_conversion_int_to_float(self):
  152. prop = odml.Property("test", "1", dtype="int")
  153. self.assertEqual(prop.dtype, "int")
  154. self.assertIsInstance(prop.values[0], int)
  155. # change dtype
  156. prop.dtype = "float"
  157. self.assertEqual(prop.dtype, "float")
  158. self.assertEqual(prop.values[0], 1.0)
  159. def test_conversion_float_to_int(self):
  160. prop = odml.Property("test", "1.5", dtype="float")
  161. self.assertEqual(prop.dtype, "float")
  162. prop.dtype = "int"
  163. self.assertEqual(prop.dtype, "int")
  164. self.assertEqual(prop.values[0], 1)
  165. def test_value_float(self):
  166. prop = odml.Property("test", value="1.5", dtype="float")
  167. self.assertEqual(prop.values[0], 1.5)
  168. class CopyTest(unittest.TestCase):
  169. def setUp(self):
  170. self.prop = odml.Property(name="test", value=1)
  171. def test_dependence(self):
  172. prop1 = self.prop
  173. prop2 = self.prop
  174. self.assertEqual(prop1, prop2)
  175. prop1.values = 5
  176. self.assertEqual(prop1, prop2)
  177. self.assertEqual(prop1.values, prop2.values)
  178. def test_independence(self):
  179. prop1 = self.prop.clone()
  180. prop2 = self.prop.clone()
  181. self.assertEqual(prop1, prop2)
  182. prop1.values = 5
  183. self.assertNotEqual(prop1, prop2)
  184. # self.assertUn
  185. class MiscTest(unittest.TestCase):
  186. def setUp(self):
  187. self.doc = SampleFileCreator().create_document()
  188. def test_paths(self):
  189. sec = odml.Section("sec")
  190. self.assertEqual(sec._get_relative_path("/a", "/b"), "/b")
  191. self.assertEqual(sec._get_relative_path("/a", "/a/b"), "b")
  192. self.assertEqual(sec._get_relative_path("/a/b", "/a/c"), "../c")
  193. self.assertEqual(sec._get_relative_path("/a/b/c", "/a"), "../..")
  194. self.assertEqual(sec._get_relative_path("/a/b", "/a"), "..")
  195. def test_section_path(self):
  196. sec1 = self.doc.sections[1]
  197. sec10 = sec1.sections[0]
  198. sec11 = sec1.sections[1]
  199. path = sec10.get_path()
  200. self.assertEqual(path, "/%s/%s" % (sec1.name, sec10.name))
  201. self.assertEqual(self.doc.get_path(), "/")
  202. self.assertEqual(sec10.get_relative_path(sec1), "..")
  203. path_to_sec10 = sec1.get_relative_path(sec10)
  204. self.assertEqual(path_to_sec10, sec10.name)
  205. self.assertIs(sec1.get_section_by_path(path_to_sec10), sec10)
  206. path_to_sec11 = sec10.get_relative_path(sec11)
  207. self.assertEqual(path_to_sec11, "../" + sec11.name)
  208. self.assertIs(sec10.get_section_by_path(path_to_sec11), sec11)
  209. def test_findall_related(self):
  210. doc = parse("""
  211. s1[T1]
  212. - s2[T1]
  213. """)
  214. self.assertEqual(len(doc.find_related(type="T1", findAll=True)), 2)
  215. doc = parse("""
  216. s0[T1]
  217. - s00[T2]
  218. s1[T2]
  219. s2[T1]
  220. """)
  221. self.assertEqual(
  222. len(doc.sections[1].find_related(type="T1", findAll=True)), 2)
  223. def test_reorder_post(self):
  224. old_index = self.doc.sections[0].reorder(2)
  225. self.assertEqual(old_index, 0)
  226. self.assertEqual(self.doc.sections[0].name, "sec 1")
  227. self.assertEqual(self.doc.sections[1].name, "sec 2")
  228. self.assertEqual(self.doc.sections[2].name, "sec 0")
  229. def test_reorder_first(self):
  230. old_index = self.doc.sections[2].reorder(0)
  231. self.assertEqual(old_index, 2)
  232. self.assertEqual(self.doc.sections[0].name, "sec 2")
  233. self.assertEqual(self.doc.sections[1].name, "sec 0")
  234. self.assertEqual(self.doc.sections[2].name, "sec 1")
  235. def test_get_section_by_path(self):
  236. sec1 = self.doc.sections[1]
  237. sec10 = sec1.sections[0]
  238. sec11 = sec1.sections[1]
  239. # test absolute path
  240. current = self.doc.get_section_by_path(sec10.get_path())
  241. self.assertEqual(current, sec10)
  242. # test relative path with ../
  243. current = sec10.get_section_by_path(sec10.get_relative_path(sec11))
  244. self.assertEqual(current, sec11)
  245. # test relative path with ./
  246. current = sec1.get_section_by_path(
  247. "./" + sec1.get_relative_path(sec11))
  248. self.assertEqual(current, sec11)
  249. # test relative path
  250. current = sec1.get_section_by_path(sec1.get_relative_path(sec11))
  251. self.assertEqual(current, sec11)
  252. # test wrong parent
  253. wrong_path = "../" + sec10.get_relative_path(sec11)
  254. self.assertRaises(ValueError, sec10.get_section_by_path, wrong_path)
  255. # test wrong child
  256. wrong_path = sec1.get_relative_path(sec10) + "/sec"
  257. self.assertRaises(ValueError, sec1.get_section_by_path, wrong_path)
  258. # test absolute path with no document
  259. new_sec = SampleFileCreator().create_section("sec", 0)
  260. path = new_sec.sections[0].get_path()
  261. self.assertRaises(ValueError, new_sec.sections[1].get_section_by_path, path)
  262. # test path with property is invalid
  263. path = sec11.properties[0].get_path()
  264. self.assertRaises(ValueError, self.doc.get_section_by_path, path)
  265. def test_get_property_by_path(self):
  266. sec0 = self.doc.sections[0]
  267. sec1 = self.doc.sections[1]
  268. sec00 = self.doc.sections[0].sections[0]
  269. sec11 = self.doc.sections[1].sections[1]
  270. sec10 = self.doc.sections[1].sections[0]
  271. prop = sec11.properties[0]
  272. # test absolute path from document
  273. current = self.doc.get_property_by_path(prop.get_path())
  274. self.assertEqual(current, prop)
  275. # test absolute path from section
  276. current = sec00.get_property_by_path(prop.get_path())
  277. self.assertEqual(current, prop)
  278. # test relative path from section
  279. manual_path = "../%s/%s:%s" % (sec1.name, sec11.name, prop.name)
  280. current = sec0.get_property_by_path(manual_path)
  281. self.assertEqual(current, prop)
  282. # test non-existing property
  283. wrong_path = sec10.get_relative_path(sec11) + ":foo"
  284. self.assertRaises(ValueError, sec1.get_property_by_path, wrong_path)
  285. # test path with section is invalid
  286. wrong_path = sec11.get_path()
  287. self.assertRaises(ValueError, sec1.get_property_by_path, wrong_path)
  288. def test_save_version(self):
  289. tmp_dir = create_test_dir(__file__)
  290. tmp_file = os.path.join(tmp_dir, "example.odml")
  291. self.doc.version = '2.4'
  292. writer = xmlparser.XMLWriter(self.doc)
  293. writer.write_file(tmp_file)
  294. restored = xmlparser.load(tmp_file)
  295. self.assertEqual(self.doc.version, restored.version)