From 9c9effab183be6333fc5f67add4ccc52fd3c16fe Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 13 Oct 2020 19:33:18 +0200 Subject: fixup! WIP: Add Python bindings --- bindings/python/serd.pyx | 84 +++++++++++++++++++++----------------------- bindings/python/test_serd.py | 30 ++++++++-------- 2 files changed, 56 insertions(+), 58 deletions(-) (limited to 'bindings/python') diff --git a/bindings/python/serd.pyx b/bindings/python/serd.pyx index 8c0bfe1b..2363420f 100644 --- a/bindings/python/serd.pyx +++ b/bindings/python/serd.pyx @@ -677,7 +677,12 @@ class EventType(enum.IntEnum): # Private Python Bindings Utilities cdef SerdNode* _unwrap_node(node: Node): - return (node)._ptr if type(node) == Node else NULL + if node is None: + return NULL + elif type(node) == Node: + return (node)._ptr + + raise TypeError("Expected Node, got %s" % type(node)) def _uri_from_param(param) -> Node: @@ -1289,7 +1294,7 @@ cdef class Reader: cdef SerdReader* _ptr cdef __ByteSource _byte_source - cdef SinkBase _sink + cdef _SinkBase _sink cdef object _callback @staticmethod @@ -1307,17 +1312,17 @@ cdef class Reader: flags: ReaderFlags, sink, stack_size: int = 4096): - if isinstance(sink, SinkBase): + if isinstance(sink, _SinkBase): self._sink = sink else: self._callback = sink self._sink = Sink(func=self._callback) - assert isinstance(self._sink, SinkBase) + assert isinstance(self._sink, _SinkBase) assert self._sink._cptr is not NULL self._ptr = serd_reader_new( - world._ptr, syntax, flags, (self._sink)._cptr, stack_size + world._ptr, syntax, flags, (<_SinkBase>self._sink)._cptr, stack_size ) def __dealloc__(self): @@ -1545,15 +1550,15 @@ cdef class Model: def __iter__(self): if self.size() == 0: - return Iter._end() + return _Iter._end() - return Iter._manage(serd_model_begin(self._ptr)) + return _Iter._manage(serd_model_begin(self._ptr)) def __contains__(self, statement): - return self.find(Statement._from_param(statement)) != self.end() + return self._find(Statement._from_param(statement)) != self._end() def __delitem__(self, statement): - i = self.find(statement) + i = self._find(statement) if i is not None: self.erase(i) @@ -1583,11 +1588,13 @@ cdef class Model: return serd_model_empty(self._ptr) def inserter(self, env: Env, default_graph: Node = None) -> Sink: + """Return a sink that will insert into this model when written to.""" return Sink._manage(serd_inserter_new( self._ptr, env._ptr, _unwrap_node(default_graph) )) def insert(self, arg) -> None: + """Insert a Statement or Range into this model.""" if type(arg) == Range: return Status(serd_model_add_range(self._ptr, (arg)._ptr)) @@ -1605,13 +1612,14 @@ cdef class Model: _ensure_success( serd_model_erase_range(self._ptr, (arg)._ptr), "Failed to erase range") - elif type(arg) == Iter: + elif type(arg) == _Iter: + # FIXME: remove? _ensure_success( - serd_model_erase(self._ptr, (arg)._ptr), + serd_model_erase(self._ptr, (<_Iter>arg)._ptr), "Failed to erase iterator") elif type(arg) == Statement: - i = self.find(arg) - if i == self.end(): + i = self._find(arg) + if i == self._end(): raise ValueError("serd.Model.erase(): statement not in model") self.erase(i) @@ -1620,17 +1628,17 @@ cdef class Model: else: raise TypeError("Bad argument type for Model.erase: %s" % type(arg)) - def begin(self) -> Iter: - return Iter._manage(serd_model_begin(self._ptr)) + # def begin(self) -> _Iter: + # return _Iter._manage(serd_model_begin(self._ptr)) - def end(self) -> Iter: - return Iter._wrap(serd_model_end(self._ptr)) + def _end(self) -> _Iter: + return _Iter._wrap(serd_model_end(self._ptr)) def all(self) -> Range: """Return a range that contains all statements in the model.""" return Range._manage(serd_model_all(self._ptr)) - def find(self, statement) -> Iter: + def _find(self, statement) -> _Iter: statement = Statement._from_param(statement) s = statement.subject() p = statement.predicate() @@ -1645,9 +1653,10 @@ cdef class Model: _unwrap_node(g) ) - return Iter._manage(c_iter) if c_iter else self.end() + return _Iter._manage(c_iter) if c_iter else self._end() def range(self, pattern) -> Range: + """Return a range of statements that match a pattern.""" assert type(pattern) == tuple assert len(pattern) == 3 or len(pattern) == 4 @@ -1898,14 +1907,14 @@ cdef class Statement: return Cursor._wrap(serd_statement_cursor(self._ptr)) -cdef class Iter: +cdef class _Iter: """An iterator that points to a statement in a model.""" cdef SerdIter* _ptr cdef bint _is_end @staticmethod cdef _end(): - cdef Iter wrapper = Iter.__new__(Iter) + cdef _Iter wrapper = _Iter.__new__(_Iter) wrapper._ptr = NULL wrapper._is_end = True @@ -1914,7 +1923,7 @@ cdef class Iter: @staticmethod cdef _manage(SerdIter* ptr): - cdef Iter wrapper = Iter.__new__(Iter) + cdef _Iter wrapper = _Iter.__new__(_Iter) if ptr is NULL: wrapper._ptr = NULL @@ -1927,10 +1936,10 @@ cdef class Iter: @staticmethod cdef _wrap(const SerdIter* ptr): - return Iter._manage(serd_iter_copy(ptr)) + return _Iter._manage(serd_iter_copy(ptr)) - def __init__(self, iter: Iter): - assert type(iter) == Iter + def __init__(self, iter: _Iter): + assert type(iter) == _Iter self._is_end = False self._ptr = serd_iter_copy(iter._ptr) @@ -1941,7 +1950,7 @@ cdef class Iter: self._ptr = NULL def __eq__(self, rhs): - return type(rhs) == Iter and serd_iter_equals(self._ptr, (rhs)._ptr) + return type(rhs) == _Iter and serd_iter_equals(self._ptr, (<_Iter>rhs)._ptr) def __next__(self): """Move to and return the next item.""" @@ -1969,9 +1978,6 @@ cdef class Range: print(statement) A range is "truthy" if it is non-empty. - - There are also methods that expose the underlying iterators, as in the C - API, but these are not typically used in Pythonic code. """ cdef SerdRange* _ptr @@ -2004,9 +2010,9 @@ cdef class Range: def __iter__(self): if self.empty(): - return Iter._end() + return _Iter._end() - return Iter._wrap(serd_range_begin(self._ptr)) + return _Iter._wrap(serd_range_begin(self._ptr)) def front(self) -> Statement: """Return the first statement in this range, or None.""" @@ -2016,15 +2022,7 @@ cdef class Range: """Return true iff there are no statements in this range.""" return serd_range_empty(self._ptr) - def begin(self) -> Iter: - """Return an iterator to the start of this range.""" - return Iter._wrap(serd_range_begin(self._ptr)) - - def end(self) -> Iter: - """Return an iterator to the exclusive end of this range.""" - return Iter._wrap(serd_range_end(self._ptr)) - - def serialise(self, sink: SinkBase, flags: SerialisationFlags) -> Status: + def serialise(self, sink: _SinkBase, flags: SerialisationFlags) -> Status: """Write this range to `sink`. The serialisation style can be controlled with `flags`. The default is @@ -2226,11 +2224,11 @@ cdef class Event: return "None" -cdef class SinkBase: +cdef class _SinkBase: cdef const SerdSink* _cptr -cdef class SinkView(SinkBase): +cdef class SinkView(_SinkBase): @staticmethod cdef SinkView _wrap(const SerdSink* cptr): if cptr is NULL: @@ -2241,7 +2239,7 @@ cdef class SinkView(SinkBase): return wrapper -cdef class Sink(SinkBase): +cdef class Sink(_SinkBase): cdef SerdSink* _ptr cdef Env _env cdef object _func diff --git a/bindings/python/test_serd.py b/bindings/python/test_serd.py index 712c21e5..898f4af4 100644 --- a/bindings/python/test_serd.py +++ b/bindings/python/test_serd.py @@ -513,25 +513,25 @@ class ModelTests(unittest.TestCase): self.assertEqual(len(model), 0) self.assertTrue(model.empty()) - def testBeginEnd(self): - s, p, o, g = self.s, self.p, self.o, self.g - model = serd.Model(self.world, serd.ModelFlags.INDEX_SPO) + # def testBeginEnd(self): + # s, p, o, g = self.s, self.p, self.o, self.g + # model = serd.Model(self.world, serd.ModelFlags.INDEX_SPO) - self.assertEqual(model.begin(), model.end()) + # self.assertEqual(model.begin(), model.end()) - model.insert((s, p, o, g)) - self.assertNotEqual(model.begin(), model.end()) + # model.insert((s, p, o, g)) + # self.assertNotEqual(model.begin(), model.end()) - def testFind(self): - s, p, o, g, x = self.s, self.p, self.o, self.g, self.x - flags = serd.ModelFlags.INDEX_SPO | serd.ModelFlags.INDEX_GRAPHS - model = serd.Model(self.world, flags) - in_statement = serd.Statement(s, p, o, g) - out_statement = serd.Statement(x, p, o, g) + # def testFind(self): + # s, p, o, g, x = self.s, self.p, self.o, self.g, self.x + # flags = serd.ModelFlags.INDEX_SPO | serd.ModelFlags.INDEX_GRAPHS + # model = serd.Model(self.world, flags) + # in_statement = serd.Statement(s, p, o, g) + # out_statement = serd.Statement(x, p, o, g) - model += in_statement - self.assertEqual(model.find(out_statement), model.end()) - self.assertNotEqual(model.find(in_statement), model.end()) + # model += in_statement + # self.assertEqual(model.find(out_statement), model.end()) + # self.assertNotEqual(model.find(in_statement), model.end()) def testGet(self): s, p, o, g = self.s, self.p, self.o, self.g -- cgit v1.2.1