Skip to content

Instantly share code, notes, and snippets.

@kamahen
Created April 12, 2024 14:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kamahen/cc466d546f5cfef9b25f1201810a8b26 to your computer and use it in GitHub Desktop.
Save kamahen/cc466d546f5cfef9b25f1201810a8b26 to your computer and use it in GitHub Desktop.
WIP context manager for swipy
$ git diff stash@{1}
diff --git a/janus.doc b/janus.doc
index fafbae8..dc1836d 100644
--- a/janus.doc
+++ b/janus.doc
@@ -431,7 +431,7 @@ Loading janus into Python is realized using the Python package
\const{janus-swi}, which defines the module \const{janus_swi}. We do
not call this simply \const{janus} to allow coexistence of Janus for
multiple Prolog implementations. Unless you plan to interact with
-multiple Prolog systems in the same session, we advise importing janus
+multiple Prolog systems in the same session, we advice to import janus
for SWI-Prolog as below.
\begin{code}
@@ -564,8 +564,8 @@ though and thus is either \const{True} or an instance of the class
\begin{code}
import janus_swi as janus
-def printRange(fr, to):
- for d in janus.query("between(F,T,X)", {"F":fr, "T":to}):
+def printRange(from, to):
+ for d in janus.query("between(F,T,X)", {"F":from, "T":to})
print(d["X"])
\end{code}
diff --git a/janus/janus.py b/janus/janus.py
index 9eb72d3..a276290 100644
--- a/janus/janus.py
+++ b/janus/janus.py
@@ -202,23 +202,21 @@ class query:
return self
def __next__(self):
"""Implement iter protocol. Returns a dict as janus.query_once()"""
- rc = self.next()
- if rc is None:
+ rc = _swipl.next_solution(self.state)
+ if rc == False or rc["truth"] == False:
raise StopIteration()
- return rc
- def __enter__(self):
- """Implement context manager protocol"""
- return self
- def __exit__(self, type, value, tb):
- """Implement context manager protocol"""
- self.close()
+ else:
+ return rc
def __del__(self):
"""Close the Prolog query"""
- self.close()
+ _swipl.close_query(self.state)
def next(self):
"""Allow for explicit enumeration, Returns None or a dict"""
rc = _swipl.next_solution(self.state)
- return None if rc == False or rc["truth"] == False else rc
+ if rc == False or rc["truth"] == False:
+ return None
+ else:
+ return rc
def close(self):
"""Explicitly close the query."""
_swipl.close_query(self.state)
@@ -466,7 +464,7 @@ class Term:
in Python. Instances are created if data is passed to Python as
`prolog(Term)`. Upon transforming the data back to Prolog, the
interface recovers a copy of the original Prolog terms.
-
+
The user should never create instances of this explicitly.
"""
diff --git a/test_janus.pl b/test_janus.pl
index 4897efe..aa1fd69 100644
--- a/test_janus.pl
+++ b/test_janus.pl
@@ -347,10 +347,8 @@ test(py_double, Tuples == [1-1,2-1,3-1,
1-3,2-3,3-3,
1-4,2-4,3-4]) :-
py_call(demo:double_iter(3,4), Tuples).
-% test(invalid_nesting, X == @true) :-
-% py_call(demo:test_invalid_nesting(), X).
test(invalid_nesting, X == @true) :-
- py_call(demo:test_invalid_nesting2(), X).
+ py_call(demo:test_invalid_nesting(), X).
:- if((py_call(sys:hexversion, V), V >= 0x03080000)).
test(while, X == [1,2,3]) :-
py_call(while:test_while(), X).
diff --git a/tests/demo.py b/tests/demo.py
index 153b07d..587ee04 100644
--- a/tests/demo.py
+++ b/tests/demo.py
@@ -73,48 +73,30 @@ def kwd_all(a=1, b=2, c=3):
def abort_iter(n):
sum=0
- with query("between(1,M,X)", {"M":n}) as q:
- for d in q:
- sum += d["X"]
- if sum > 10000:
- break;
+ for d in query("between(1,M,X)", {"M":n}):
+ sum += d["X"]
+ if sum > 10000:
+ break;
return sum;
def double_iter(w,h):
tuples=[]
- with query("between(1,M,Y)", {"M":h}) as q1:
- for yd in q1:
- with query("between(1,M,X)", {"M":w}) as q2:
- tuples += [(xd['X'],yd['Y']) for xd in q2]
+ for yd in query("between(1,M,Y)", {"M":h}):
+ for xd in query("between(1,M,X)", {"M":w}):
+ tuples.append((xd['X'],yd['Y']))
return tuples
def test_invalid_nesting():
- rc = False
q1 = query("between(1,3,X)")
q2 = query("between(1,3,Y)")
q2.next()
try:
q1.next()
- except PrologError:
+ except:
q2.close()
- rc = True
q1.next()
q1.close()
- return False
-
-def test_invalid_nesting2():
- with (query("between(1,3,X)") as q1,
- query("between(1,3,Y)") as q2):
- q2.next()
- try:
- q1.next()
- except PrologError as exc_p:
- print('*** IN PROLOG_ERROR\n')
- return '***' + str(type(exc_p))
- except Exception as exc:
- print('*** IN EXCEPTION\n')
- return repr(exc)
- return False
+ return True
# Test using generators as custom iterators.
diff --git a/tests/threads.py b/tests/threads.py
index ecee2d3..2eb7bea 100644
--- a/tests/threads.py
+++ b/tests/threads.py
@@ -7,7 +7,7 @@ def one():
print("Starting one")
plone()
-def plone():
+def plone():
x = janus.query_once("""
thread_self(_Me),
thread_property(_Me, id(Me)),
diff --git a/tests/while.py b/tests/while.py
index 930b9b4..870e79c 100644
--- a/tests/while.py
+++ b/tests/while.py
@@ -4,7 +4,8 @@ from janus import *
def test_while():
list=[]
- with query("between(1,3,X)") as q:
- while ( s := q.next() ):
- list.append(s['X'])
+ q = query("between(1,3,X)")
+ while ( s := q.next() ):
+ list.append(s['X'])
+ q.close()
return list
[peter@penguin swipy (context-manager)]$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment