context manager to clean up query instances
@@ -60,6 +60,7 @@ class QueryResult:
# These need to be global for now...
# So that register_python_class works from anywhere
+# @TODO: Fix all examples to call polar.register_python_class and depreciate this.
CLASSES = {}
CLASS_CONSTRUCTORS = {}
@@ -68,6 +69,19 @@ def register_python_class(cls, from_polar=None):
Polar().register_python_class(cls, from_polar)
+class CleanupQuery:
+ """ Context manager for the polar native query object. """
+
+ def __init__(self, query):
+ self.query = query
+
+ def __enter__(self):
+ return self.query
+
+ def __exit__(self, type, value, traceback):
+ lib.query_free(self.query)
+
+
class Polar:
"""Polar API"""
@@ -214,15 +228,13 @@ class Polar:
results = self._do_query(query)
try:
next(results)
+ # Exhaust generator to make sure query object is cleaned up before next load.
+ for _ in results:
+ pass
+
except StopIteration:
# TODO (dhatch): Better error message.
raise PolarRuntimeException("Inline query in file failed.")
-
- # This must be called so there are no open queries on when the next load cycle
- # happens. This sucks, but we only do it when there is not a
- # stop iteration because _do_query does the free otherwise.
- # We need a better api for this.
- lib.query_free(query)
finally:
lib.load_free(load)
@@ -288,12 +300,12 @@ class Polar:
term = {"id": 0, "offset": 0, "value": val}
return term
- def _do_query(self, query):
+ def _do_query(self, q):
"""Method which performs the query loop over an already contructed query"""
+ with CleanupQuery(q) as query:
while True:
event_s = lib.polar_query(self.polar, query)
if event_s == ffi.NULL:
- lib.query_free(query)
self._raise_error()
event = json.loads(ffi.string(event_s).decode())
@@ -422,7 +434,9 @@ class Polar:
try:
left_class = self.classes[left_class_tag]
right_class = self.classes[right_class_tag]
- is_sub_specializer = mro.index(left_class) < mro.index(right_class)
+ is_sub_specializer = mro.index(left_class) < mro.index(
+ right_class
+ )
except (KeyError, ValueError) as e:
is_sub_specializer = False
@@ -452,8 +466,6 @@ class Polar:
if kind == "Result":
yield {k: self.to_python(v) for k, v in data["bindings"].items()}
- lib.query_free(query)
-
def query_str(self, query_str):
# Make sure KB is loaded in
self._kb_load()
