Skip to content

Commit 7dde867

Browse files
authored
Merge pull request #375 from fschrader1992/rdf
Terminology Cache
2 parents 01fb08a + 8056005 commit 7dde867

File tree

3 files changed

+93
-4
lines changed

3 files changed

+93
-4
lines changed

odml/terminology.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@
2424
CACHE_AGE = datetime.timedelta(days=1)
2525

2626

27-
def cache_load(url):
27+
def cache_load(url, replace_file=False):
2828
"""
2929
Loads the url and store it in a temporary cache directory
3030
subsequent requests for this url will use the cached version.
3131
3232
:param url: URL from where to load an odML terminology file from.
33+
:param replace_file: True, if file should be reloaded
3334
"""
3435
filename = '.'.join([md5(url.encode()).hexdigest(), os.path.basename(url)])
3536
cache_dir = os.path.join(tempfile.gettempdir(), "odml.cache")
@@ -41,8 +42,9 @@ def cache_load(url):
4142
raise
4243
cache_file = os.path.join(cache_dir, filename)
4344
if not os.path.exists(cache_file) \
44-
or datetime.datetime.fromtimestamp(os.path.getmtime(cache_file)) < \
45-
datetime.datetime.now() - CACHE_AGE:
45+
or replace_file \
46+
or datetime.datetime.fromtimestamp(os.path.getmtime(cache_file)) < \
47+
datetime.datetime.now() - CACHE_AGE:
4648
try:
4749
data = urllib2.urlopen(url).read()
4850
if sys.version_info.major > 2:
@@ -64,6 +66,7 @@ class Terminologies(dict):
6466
browsing and importing of full or partial odML terminologies.
6567
"""
6668
loading = {}
69+
reload_cache = False
6770

6871
def load(self, url):
6972
"""
@@ -92,7 +95,7 @@ def _load(self, url):
9295
It will silently return None, if any exceptions
9396
occur to enable loading of nested odML files.
9497
"""
95-
file_obj = cache_load(url)
98+
file_obj = cache_load(url, self.reload_cache)
9699
if file_obj is None:
97100
print("did not successfully load '%s'" % url)
98101
return
@@ -117,10 +120,23 @@ def deferred_load(self, url):
117120
self.loading[url] = threading.Thread(target=self._load, args=(url,))
118121
self.loading[url].start()
119122

123+
def refresh(self, url):
124+
"""
125+
Deletes and reloads all cached odML XML files given in the
126+
terminology file from a URL.
127+
128+
:param url: location of an odML XML file.
129+
"""
130+
self.reload_cache = True
131+
self.clear()
132+
self.load(url)
133+
self.reload_cache = False
134+
120135

121136
terminologies = Terminologies()
122137
load = terminologies.load
123138
deferred_load = terminologies.deferred_load
139+
refresh = terminologies.refresh
124140

125141

126142
if __name__ == "__main__":

test/test_doc.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import datetime
22
import os
33
import unittest
4+
import tempfile
5+
import odml.terminology
6+
from hashlib import md5
47
try:
58
from urllib.request import pathname2url
69
except ImportError:
@@ -109,6 +112,32 @@ def test_get_terminology_equivalent(self):
109112
doc.repository = None
110113
self.assertIsNone(doc.get_terminology_equivalent())
111114

115+
def test_terminology_refresh(self):
116+
117+
cache_dir = os.path.join(tempfile.gettempdir(), "odml.cache")
118+
url = "https://terminologies.g-node.org/v1.1/terminologies.xml"
119+
term_doc = odml.terminology.load(url)
120+
121+
terms = []
122+
for sec in term_doc.sections:
123+
terms += ['.'.join([md5(sec.include.encode()).hexdigest(), os.path.basename(sec.include)])]
124+
125+
before = datetime.datetime.now()
126+
127+
for loaded_file in os.listdir(cache_dir):
128+
for term in terms:
129+
if term in loaded_file:
130+
assert datetime.datetime.fromtimestamp(
131+
os.path.getmtime(os.path.join(cache_dir, loaded_file))) < before
132+
133+
odml.terminology.refresh(url)
134+
135+
for replaced_file in os.listdir(cache_dir):
136+
for term in terms:
137+
if term in replaced_file:
138+
assert datetime.datetime.fromtimestamp(
139+
os.path.getmtime(os.path.join(cache_dir, replaced_file))) > before
140+
112141
def test_append(self):
113142
doc = Document()
114143
self.assertListEqual(doc.sections, [])

test/test_parser_odml.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import tempfile
99
import unittest
1010

11+
from odml import Document, Section, Property
1112
from odml.tools import odmlparser
1213

1314

@@ -82,6 +83,10 @@ def test_json_file(self):
8283
self.assertEqual(json_doc, self.odml_doc)
8384

8485
def test_rdf_file(self):
86+
"""
87+
Test comparison of document before and after rdf-conversion
88+
"""
89+
8590
self.rdf_writer.write_file(self.odml_doc, self.rdf_file)
8691
rdf_doc = self.rdf_reader.from_file(self.rdf_file, "xml")
8792

@@ -101,6 +106,45 @@ def test_rdf_file(self):
101106
with self.assertRaises(ValueError):
102107
self.rdf_reader.from_file(self.rdf_file)
103108

109+
doc = Document()
110+
sec1 = Section(name="sec1", type="int", parent=doc)
111+
Property(name="prop11", values=[1, 2, 3], dtype="int", parent=sec1)
112+
Property(name="prop12", values=[1.1, 2.2, 3.3], dtype="float", parent=sec1)
113+
Property(name="prop13", values=["a", "b", "c"], dtype="string", parent=sec1)
114+
sec2 = Section(name="sec2", type="int", parent=doc)
115+
Property(name="prop21", values=[1, 2, 3], dtype="int", parent=sec2)
116+
Property(name="prop22", values=[1.1, 2.2, 3.3], dtype="float", parent=sec2)
117+
Property(name="prop23", values=["a", "b", "c"], dtype="string", parent=sec2)
118+
sec3 = Section(name="sec3", type="int", parent=doc)
119+
Property(name="prop31", values=[1, 2, 3], dtype="int", parent=sec3)
120+
Property(name="prop32", values=[1.1, 2.2, 3.3], dtype="float", parent=sec3)
121+
Property(name="prop33", values=["a", "b", "c"], dtype="string", parent=sec3)
122+
self.rdf_writer.write_file(doc, self.rdf_file)
123+
rdf_doc = self.rdf_reader.from_file(self.rdf_file, "xml")
124+
125+
self.assertEqual(doc, rdf_doc[0])
126+
self.assertEqual(len(rdf_doc), 1)
127+
self.assertEqual(len(rdf_doc[0].sections), 3)
128+
129+
self.assertIn(doc.sections[0].name, rdf_doc[0].sections)
130+
self.assertIn(doc.sections[1].name, rdf_doc[0].sections)
131+
self.assertIn(doc.sections[2].name, rdf_doc[0].sections)
132+
rdf_sec1 = rdf_doc[0].sections[doc.sections[0].name]
133+
self.assertEqual(len(rdf_sec1.properties), 3)
134+
self.assertIn(doc.sections[0].properties[0].name, rdf_sec1.properties)
135+
self.assertIn(doc.sections[0].properties[1].name, rdf_sec1.properties)
136+
self.assertIn(doc.sections[0].properties[1].name, rdf_sec1.properties)
137+
rdf_sec2 = rdf_doc[0].sections[doc.sections[1].name]
138+
self.assertEqual(len(rdf_sec2.properties), 3)
139+
self.assertIn(doc.sections[1].properties[0].name, rdf_sec2.properties)
140+
self.assertIn(doc.sections[1].properties[1].name, rdf_sec2.properties)
141+
self.assertIn(doc.sections[1].properties[1].name, rdf_sec2.properties)
142+
rdf_sec3 = rdf_doc[0].sections[doc.sections[2].name]
143+
self.assertEqual(len(rdf_sec3.properties), 3)
144+
self.assertIn(doc.sections[2].properties[0].name, rdf_sec3.properties)
145+
self.assertIn(doc.sections[2].properties[1].name, rdf_sec3.properties)
146+
self.assertIn(doc.sections[2].properties[1].name, rdf_sec3.properties)
147+
104148
def test_xml_string(self):
105149
# Read from string
106150
author = "HPL"

0 commit comments

Comments
 (0)