Procházet zdrojové kódy

Merge pull request #122 from scossu/literals

Literals
Stefano Cossu před 4 roky
rodič
revize
0fe1a09e52

+ 1 - 1
docs/contributing.rst

@@ -33,7 +33,7 @@ Modifying Cython Modules
 Cython files must be recompiled into C files and then into binary files every
 Cython files must be recompiled into C files and then into binary files every
 time they are changed. To recompile Lakesuperior modules, run::
 time they are changed. To recompile Lakesuperior modules, run::
 
 
-    python setup.py --build_ext --inplace
+    python setup.py build_ext --inplace
 
 
 For a faster compilation while testing, the environment variable ``CFLAGS``
 For a faster compilation while testing, the environment variable ``CFLAGS``
 can set to ``-O0`` to turn off compiler optimization. The runtime code may run
 can set to ``-O0`` to turn off compiler optimization. The runtime code may run

+ 6 - 0
lakesuperior/__init__.py

@@ -17,6 +17,12 @@ referenced or copied with a known path relative to the package root.
 """
 """
 
 
 class Env:
 class Env:
+    """
+    Lakesuperior environment.
+
+    Instances of this class contain the environment necessary to run a
+    self-standing instance of Lakesuperior in a Python environment.
+    """
     pass
     pass
 
 
 env = Env()
 env = Env()

+ 0 - 1
lakesuperior/messaging/handlers.py

@@ -24,7 +24,6 @@ class StompHandler(logging.Handler):
             conn_cls = stomp.Connection10
             conn_cls = stomp.Connection10
 
 
         self.conn = conn_cls([(self.conf['host'], self.conf['port'])])
         self.conn = conn_cls([(self.conf['host'], self.conf['port'])])
-        self.conn.start()
         try:
         try:
             self.conn.connect(
             self.conn.connect(
                 username=self.conf['username'],
                 username=self.conf['username'],

+ 1 - 1
lakesuperior/model/rdf/graph.pyx

@@ -520,7 +520,7 @@ cdef class Graph:
         This function converts RDFLib terms into the serialized format stored
         This function converts RDFLib terms into the serialized format stored
         in the graph's internal structure and compares them bytewise.
         in the graph's internal structure and compares them bytewise.
 
 
-        Any and all of the lookup terms msy be ``None``.
+        Any and all of the lookup terms may be ``None``.
 
 
         :rtype: Graph
         :rtype: Graph
         :return: New Graph instance with matching triples.
         :return: New Graph instance with matching triples.

+ 28 - 41
lakesuperior/model/rdf/term.pyx

@@ -8,6 +8,7 @@ from libc.stdlib cimport free
 from libc.string cimport memcpy
 from libc.string cimport memcpy
 
 
 from lakesuperior.cy_include cimport cytpl as tpl
 from lakesuperior.cy_include cimport cytpl as tpl
+from lakesuperior.dictionaries.namespaces import ns_collection as nsc
 from lakesuperior.model.base cimport Buffer, buffer_dump
 from lakesuperior.model.base cimport Buffer, buffer_dump
 
 
 
 
@@ -21,6 +22,7 @@ DEF LSUP_TERM_STRUCT_PK_FMT = b'S(' + LSUP_TERM_PK_FMT + b')'
 #    b'^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?'
 #    b'^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?'
 #)
 #)
 
 
+
 __doc__ = """
 __doc__ = """
 Term model.
 Term model.
 
 
@@ -76,9 +78,9 @@ cdef int deserialize(const Buffer *data, Term *term) except -1:
     """
     """
     #print(f'Deserializing: {buffer_dump(data)}')
     #print(f'Deserializing: {buffer_dump(data)}')
     _pk = tpl.tpl_peek(
     _pk = tpl.tpl_peek(
-            tpl.TPL_MEM | tpl.TPL_DATAPEEK, data[0].addr, data[0].sz,
-            LSUP_TERM_PK_FMT, &(term[0].type), &(term[0].data),
-            &(term[0].datatype), &(term[0].lang))
+            tpl.TPL_MEM | tpl.TPL_DATAPEEK, data.addr, data.sz,
+            LSUP_TERM_PK_FMT, &(term.type), &(term.data),
+            &(term.datatype), &(term.lang))
 
 
     if _pk is NULL:
     if _pk is NULL:
         raise MemoryError('Error deserializing term.')
         raise MemoryError('Error deserializing term.')
@@ -91,21 +93,25 @@ cdef int from_rdflib(term_obj, Term *term) except -1:
     Return a Term struct obtained from a Python/RDFLib term.
     Return a Term struct obtained from a Python/RDFLib term.
     """
     """
     _data = str(term_obj).encode()
     _data = str(term_obj).encode()
-    term[0].data = _data
+    term.data = _data
+    term.datatype = NULL
+    term.lang = NULL
 
 
     if isinstance(term_obj, Literal):
     if isinstance(term_obj, Literal):
-        _datatype = (getattr(term_obj, 'datatype') or '').encode()
-        _lang = (getattr(term_obj, 'language') or '').encode()
-        term[0].type = LSUP_TERM_TYPE_LITERAL
-        term[0].datatype = _datatype
-        term[0].lang = _lang
+        _datatype = getattr(term_obj, 'datatype', None)
+        _lang = getattr(term_obj, 'language', None)
+        term.type = LSUP_TERM_TYPE_LITERAL
+        if _datatype:
+            _datatype = _datatype.encode()
+            term.datatype = _datatype
+        if _lang:
+            _lang = _lang.encode()
+            term.lang = _lang
     else:
     else:
-        term[0].datatype = NULL
-        term[0].lang = NULL
         if isinstance(term_obj, URIRef):
         if isinstance(term_obj, URIRef):
-            term[0].type = LSUP_TERM_TYPE_URIREF
+            term.type = LSUP_TERM_TYPE_URIREF
         elif isinstance(term_obj, BNode):
         elif isinstance(term_obj, BNode):
-            term[0].type = LSUP_TERM_TYPE_BNODE
+            term.type = LSUP_TERM_TYPE_BNODE
         else:
         else:
             raise ValueError(f'Unsupported term type: {type(term_obj)}')
             raise ValueError(f'Unsupported term type: {type(term_obj)}')
 
 
@@ -120,28 +126,7 @@ cdef int serialize_from_rdflib(term_obj, Buffer *data) except -1:
         void *addr
         void *addr
         size_t sz
         size_t sz
 
 
-    # From RDFlib
-    _data = str(term_obj).encode()
-    _term.data = _data
-
-    if isinstance(term_obj, Literal):
-        _datatype = (getattr(term_obj, 'datatype') or '').encode()
-        _lang = (getattr(term_obj, 'language') or '').encode()
-        _term.type = LSUP_TERM_TYPE_LITERAL
-        _term.datatype = _datatype
-        _term.lang = _lang
-    else:
-        _term.datatype = NULL
-        _term.lang = NULL
-        if isinstance(term_obj, URIRef):
-            _term.type = LSUP_TERM_TYPE_URIREF
-        elif isinstance(term_obj, BNode):
-            _term.type = LSUP_TERM_TYPE_BNODE
-        else:
-            raise ValueError(
-                f'Unsupported term type: {term_obj} {type(term_obj)}'
-            )
-
+    from_rdflib(term_obj, &_term)
     serialize(&_term, data)
     serialize(&_term, data)
 
 
 
 
@@ -150,12 +135,14 @@ cdef object to_rdflib(const Term *term):
     Return an RDFLib term.
     Return an RDFLib term.
     """
     """
     cdef str data = (<bytes>term.data).decode()
     cdef str data = (<bytes>term.data).decode()
-    if term[0].type == LSUP_TERM_TYPE_LITERAL:
-        return Literal(
-            data,
-            datatype=term.datatype if not term.lang else None,
-            lang=term.lang or None
-        )
+    if term.type == LSUP_TERM_TYPE_LITERAL:
+        if term.lang:
+            params = {'lang': (<bytes>term.lang).decode()}
+        elif term.datatype:
+            params = {'datatype': (<bytes>term.datatype).decode()}
+        else:
+            params = {}
+        return Literal(data, **params)
     else:
     else:
         if term.type == LSUP_TERM_TYPE_URIREF:
         if term.type == LSUP_TERM_TYPE_URIREF:
             return URIRef(data)
             return URIRef(data)

+ 2 - 2
lakesuperior/store/base_lmdb_store.pyx

@@ -295,9 +295,9 @@ cdef class BaseLmdbStore:
 
 
 
 
     cpdef void close_env(self, bint commit_pending_transaction=False) except *:
     cpdef void close_env(self, bint commit_pending_transaction=False) except *:
-        logger.debug('Cleaning up store env.')
+        #logger.debug('Cleaning up store env.')
         if self.is_open:
         if self.is_open:
-            logger.debug('Closing store env.')
+            #logger.debug('Closing store env.')
             if self.is_txn_open is True:
             if self.is_txn_open is True:
                 if commit_pending_transaction:
                 if commit_pending_transaction:
                     self._txn_commit()
                     self._txn_commit()

+ 2 - 1
requirements_dev.txt

@@ -15,8 +15,9 @@ numpy>=1.15.1
 pytest-flask
 pytest-flask
 pytest>=3.2.2
 pytest>=3.2.2
 rdflib==4.2.2
 rdflib==4.2.2
+rdflib_jsonld==0.4.0
 requests-toolbelt>=0.8.0
 requests-toolbelt>=0.8.0
 requests>=2.18.4
 requests>=2.18.4
 sphinx-rtd-theme>=0.2.4
 sphinx-rtd-theme>=0.2.4
-stomp.py>=4.1.20
+stomp.py>=5.0
 wheel>=0.30.0a0
 wheel>=0.30.0a0

+ 38 - 0
tests/2_api/test_2_0_resource_api.py

@@ -122,6 +122,44 @@ class TestResourceCRUD:
                     rsrc.uri : nsc['rdf'].type : nsc['ldp'].RDFSource]
                     rsrc.uri : nsc['rdf'].type : nsc['ldp'].RDFSource]
 
 
 
 
+    def test_create_ldp_rs_literals(self):
+        """
+        Create an RDF resource (LDP-RS) containing different literal types.
+        """
+        uid = f'/{uuid4()}'
+        uri = nsc['fcres'][uid]
+        with env.app_globals.rdf_store.txn_ctx():
+            gr = from_rdf(
+                data = '''
+                <>
+                  <urn:p:1> 1 ;
+                  <urn:p:2> "Untyped Literal" ;
+                  <urn:p:3> "Typed Literal"^^<http://www.w3.org/2001/XMLSchema#string> ;
+                  <urn:p:4> "2019-09-26"^^<http://www.w3.org/2001/XMLSchema#date> ;
+                  <urn:p:5> "Lang-tagged Literal"@en-US ;
+                  .
+                ''', format='turtle',
+                publicID=uri)
+        evt, _ = rsrc_api.create_or_replace(uid, graph=gr)
+
+        rsrc = rsrc_api.get(uid)
+        with env.app_globals.rdf_store.txn_ctx():
+            assert rsrc.imr[
+                    rsrc.uri : URIRef('urn:p:1') :
+                    Literal('1', datatype=nsc['xsd'].integer)]
+            assert rsrc.imr[
+                    rsrc.uri : URIRef('urn:p:2') : Literal('Untyped Literal')]
+            assert rsrc.imr[
+                    rsrc.uri : URIRef('urn:p:3') :
+                    Literal('Typed Literal', datatype=nsc['xsd'].string)]
+            assert rsrc.imr[
+                    rsrc.uri : URIRef('urn:p:4') :
+                    Literal('2019-09-26', datatype=nsc['xsd'].date)]
+            assert rsrc.imr[
+                    rsrc.uri : URIRef('urn:p:5') :
+                    Literal('Lang-tagged Literal', lang='en-US')]
+
+
     def test_create_ldp_nr(self):
     def test_create_ldp_nr(self):
         """
         """
         Create a non-RDF resource (LDP-NR).
         Create a non-RDF resource (LDP-NR).