samplefile.py 12 KB

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