def test_attr2rdf_period():
    """
    Check that attr2rdf handles minus symbol in predicate names.
    """

    uriref, _ = attr2rdf("surf_predicate-with-minus")
    assert uriref == surf.ns.SURF["predicate-with-minus"]
Example #2
0
def test_attr2rdf_period():
    """
    Check that attr2rdf handles minus symbol in predicate names.
    """

    uriref, _ = attr2rdf("surf_predicate-with-minus")
    assert uriref == surf.ns.SURF["predicate-with-minus"]
Example #3
0
    def __getattr__(self, attr_name):
        """ Retrieve and cache attribute values.

        If attribute name is not in the "ns_predicate" form, an
        `AttributeError` will be raised.


        This method has no impact on the *dirty* state of the object.

        """

        predicate, direct = attr2rdf(attr_name)

        if not predicate:
            raise AttributeError('Not a predicate: %s' % attr_name)

        # Prepare closure for lazy execution.
        def prepare_getvalues_callable(resource, predicate, direct, retrieve):
            """ Return callable that loads and returns values. """
            def getvalues_callable():
                """ Load and return values for this attribute. """
                # Select triple dictionary for synchronization
                rdf_dict = resource.__rdf_direct if direct else resource.__rdf_inverse

                # Initial synchronization
                if retrieve:
                    store = resource.session[resource.store_key]
                    # send request to triple store
                    values = store.get(resource, predicate, direct)
                    if not values:
                        predicate_values = rdf_dict.get(predicate, [])
                        values.update([(pred_val, [])
                                       for pred_val in predicate_values])
                    # instantiate SuRF objects
                    surf_values = resource._lazy(values)
                else:
                    surf_values = []

                rdf_dict[predicate] = [
                    resource.to_rdf(value) for value in surf_values
                ]
                return surf_values, rdf_dict[predicate]

            return getvalues_callable

        # If resource is fully loaded and we're still here (__getattr__), this must be an empty
        # attribute, therefore there is no point in querying the triple store !
        retrieve_values = (not self.__full_direct) if direct else (
            not self.__full_inverse)
        getvalues_callable = prepare_getvalues_callable(
            self, predicate, direct, retrieve_values)

        attr_value = LazyResourceLoader(getvalues_callable, self, attr_name)

        # Not using self.__setattr__, that would trigger loading of attributes
        #        object.__setattr__(self, attr_name, attr_value)
        super(Resource, self).__setattr__(attr_name, attr_value)
        self.dirty = False

        return attr_value
Example #4
0
    def get_by_attribute(cls, attributes, context = None):
        """
        Retrieve all `instances` from the data store that have the specified `attributes`
        and are of `rdf:type` of the resource class

        """

        direct_attributes = []
        inverse_attributes = []
        attribute_uris = [inverse_attributes, direct_attributes]
        for attribute_name in attributes:
            attribute_uri, direct = attr2rdf(attribute_name)
            # Using boolean as array index.
            attribute_uris[direct].append(attribute_uri)

        subjects = {}
        if direct_attributes:
            subjects.update(cls.session[cls.store_key].instances_by_attribute(cls, direct_attributes, True, context))
        if inverse_attributes:
            subjects.update(cls.session[cls.store_key].instances_by_attribute(cls, inverse_attributes, False, context))
        
        instances = []
        for s, types in subjects.items():
            if not isinstance(s, URIRef):
                continue

            if cls.uri:
                concepts = [cls.uri]
            else:
                concepts = types

            instances.append(cls._instance(s, concepts))
        
        return instances
Example #5
0
    def get_by(self, **kwargs):
        """ Add filter conditions.

        Arguments are expected in form::

            foaf_name = "John"

        Multiple arguments are supported.
        An example that retrieves all persons named "John Smith"::

            FoafPerson = session.get_class(surf.ns.FOAF.Person)
            for person in FoafPerson.get_by(foaf_name = "John", foaf_surname = "Smith"):
                print person.subject

        """

        params = self.__params.copy()
        # Don't overwrite existing get_by parameters, just append new ones.
        # Overwriting get_by params would cause resource.some_attr.get_by()
        # to work incorrectly.
        params.setdefault("get_by", [])
        for name, value in kwargs.items():
            attr, direct = attr2rdf(name)
            # Assume by plain strings user means literals
            if type(value) in [str, unicode]:
                value = Literal(value)
            
            # If value has subject attribute, this must be Resource, 
            # take its subject.
            if hasattr(value, "subject"):
                value = value.subject
             
            params["get_by"].append((attr, value, direct))
        return ResultProxy(params)
Example #6
0
    def __getattr__(self, attr_name):
        """ Retrieve and cache attribute values.

        If attribute name is not in the "ns_predicate" form, an
        `AttributeError` will be raised.


        This method has no impact on the *dirty* state of the object.

        """

        predicate, direct = attr2rdf(attr_name)
            
        if not predicate:
            raise AttributeError('Not a predicate: %s' % attr_name)

        # Closure for lazy execution.
        def make_values_source(resource, predicate, direct, do_query):
            """ Return callable that loads and returns values. """

            def getattr_values_source():
                """ Load and return values for this attribute. """
                
                if do_query:
                    store = resource.session[resource.store_key]
                    # Request to triple store
                    values = store.get(resource, predicate, direct)
                    # Instantiate SuRF objects
                    surf_values = resource._lazy(values)
                else:
                    surf_values = []


                # Select triple dictionary for synchronization
                if direct:
                    rdf_dict = resource.__rdf_direct
                else:
                    rdf_dict = resource.__rdf_inverse

                # Initial synchronization
                rdf_dict[predicate] = [resource.to_rdf(value) for value in surf_values]

                return surf_values, rdf_dict[predicate]

            return getattr_values_source

        # If resource is fully loaded and still we're here
        # at __getattr__, this must be an empty attribute, so
        # no point querying triple store.
        do_query = not self.__full
        values_source = make_values_source(self, predicate, direct, do_query)

        attr_value = ResourceValue(values_source, self, attr_name)

        # Not using self.__setattr__, that would trigger loading of attributes
        object.__setattr__(self, attr_name, attr_value)
        self.dirty = False

        return attr_value
Example #7
0
    def __getattr__(self, attr_name):
        """ Retrieve and cache attribute values.

        If attribute name is not in the "ns_predicate" form, an
        `AttributeError` will be raised.


        This method has no impact on the *dirty* state of the object.

        """

        predicate, direct = attr2rdf(attr_name)
            
        if not predicate:
            raise AttributeError('Not a predicate: %s' % attr_name)

        # Prepare closure for lazy execution.
        def prepare_getvalues_callable(resource, predicate, direct, retrieve):
            """ Return callable that loads and returns values. """

            def getvalues_callable():
                """ Load and return values for this attribute. """
                # Select triple dictionary for synchronization
                rdf_dict = resource.__rdf_direct if direct else resource.__rdf_inverse

                # Initial synchronization
                if retrieve:
                    store = resource.session[resource.store_key]
                    # send request to triple store
                    values = store.get(resource, predicate, direct)
                    if not values:
                        predicate_values = rdf_dict.get(predicate,[])
                        values.update([(pred_val, []) for pred_val in predicate_values])
                    # instantiate SuRF objects
                    surf_values = resource._lazy(values)
                else:
                    surf_values = []

                rdf_dict[predicate] = [resource.to_rdf(value) for value in surf_values]
                return surf_values, rdf_dict[predicate]

            return getvalues_callable

        # If resource is fully loaded and we're still here (__getattr__), this must be an empty
        # attribute, therefore there is no point in querying the triple store !
        retrieve_values     = (not self.__full_direct) if direct else (not self.__full_inverse)
        getvalues_callable  = prepare_getvalues_callable(self, predicate, direct, retrieve_values)

        attr_value          = LazyResourceLoader(getvalues_callable, self, attr_name)

        # Not using self.__setattr__, that would trigger loading of attributes
#        object.__setattr__(self, attr_name, attr_value)
        super(Resource, self).__setattr__(attr_name, attr_value)
        self.dirty = False

        return attr_value
Example #8
0
def split_attribute_edges(name):
    """ Allow specifying indirect attributes by giving a path of properties
    from the object up to the requested attribute """
    edges = []
    for edge in name.split('__'):
        attr, direct = attr2rdf(edge)
        if attr is None:
            raise ValueError("Not an attribute %r" % edge)
        edges.append((attr, direct))

    return edges
Example #9
0
def split_attribute_edges(name):
    """ Allow specifying indirect attributes by giving a path of properties
    from the object up to the requested attribute """
    edges = []
    for edge in name.split("__"):
        attr, direct = attr2rdf(edge)
        if attr is None:
            raise ValueError("Not an attribute %r" % edge)
        edges.append((attr, direct))

    return edges
Example #10
0
    def __uri(self, uri):
        """ For **internal** use only, convert the `uri` to a `URIRef`. """

        if not uri:
            return None

        if type(uri) is URIRef:
            return uri
        else:
            if not is_uri(uri):
                attrname = de_camel_case(uri, '_', DE_CAMEL_CASE_DEFAULT)
                uri, _ = attr2rdf(attrname)
            return URIRef(uri)
Example #11
0
    def __uri(self, uri):
        """ For **internal** use only, convert the `uri` to a `URIRef`. """

        if not uri:
            return None

        if type(uri) is URIRef:
            return uri
        else:
            if not is_uri(uri):
                attrname = de_camel_case(uri, '_', DE_CAMEL_CASE_DEFAULT)
                uri, _ = attr2rdf(attrname)
            return URIRef(uri)
Example #12
0
    def query_attribute(self, attribute_name):
        """ Return ResultProxy for querying attribute values. """

        # If we want to get john.foaf_knows values, we have to formulate
        # query like friends = get_by(is_foaf_knows_of = john), thus the
        # attribute name inversion
        uri, direct = attr2rdf(attribute_name)
        inverse_attribute_name = unicode(rdf2attr(uri, not direct))

        store = self.session[self.store_key]
        proxy = ResultProxy(store = store,
                            instancemaker = self.__instancemaker)

        kwargs = {inverse_attribute_name : self.subject}
        return proxy.get_by(**kwargs)
Example #13
0
    def __delattr__(self, attr_name):
        """
        The `del` method - responsible for deleting the attribute of the object given
        by `attr_name`

        .. note:: This method sets the state of the resource to *dirty*
                  (the `resource` will be persisted if the `commit` `session`
                  method is called)

        """

        predicate, direct = attr2rdf(attr_name)
        if predicate:
            #value = self.__getattr__(attr_name)
            rdf_dict = direct and self.__rdf_direct or self.__rdf_inverse
            rdf_dict[predicate] = []
            self.dirty = True
        object.__delattr__(self, attr_name)
Example #14
0
    def __delattr__(self, attr_name):
        """
        The `del` method - responsible for deleting the attribute of the object given
        by `attr_name`

        .. note:: This method sets the state of the resource to *dirty*
                  (the `resource` will be persisted if the `commit` `session`
                  method is called)

        """

        predicate, direct = attr2rdf(attr_name)
        if predicate:
            #value = self.__getattr__(attr_name)
            rdf_dict = direct and self.__rdf_direct or self.__rdf_inverse
            rdf_dict[predicate] = []
            self.dirty = True
        object.__delattr__(self, attr_name)
Example #15
0
    def query_attribute(self, attribute_name):
        """ Return ResultProxy for querying attribute values. """

        # If we want to get john.foaf_knows values, we have to formulate
        # query like friends = get_by(is_foaf_knows_of = john), thus the
        # attribute name inversion
        uri, direct = attr2rdf(attribute_name)

        # We'll be using inverse_attribute_name as keyword argument.
        # Python 2.6.2 and older don't allow unicode keyword arguments,
        # so we revert back to str().
        inverse_attribute_name = str(rdf2attr(uri, not direct))

        store = self.session[self.store_key]
        proxy = ResultProxy(store=store,
                            instance_factory=self.__instance_factory)

        kwargs = {inverse_attribute_name: self.subject}
        return proxy.get_by(**kwargs)
Example #16
0
    def query_attribute(self, attribute_name):
        """ Return ResultProxy for querying attribute values. """

        # If we want to get john.foaf_knows values, we have to formulate
        # query like friends = get_by(is_foaf_knows_of = john), thus the
        # attribute name inversion
        uri, direct = attr2rdf(attribute_name)
        
        # We'll be using inverse_attribute_name as keyword argument.
        # Python 2.6.2 and older doesn't allow unicode keyword arguments, 
        # so we do str().
        inverse_attribute_name = str(rdf2attr(uri, not direct))

        store = self.session[self.store_key]
        proxy = ResultProxy(store = store,
                            instancemaker = self.__instancemaker)

        kwargs = {inverse_attribute_name : self.subject}
        return proxy.get_by(**kwargs)
Example #17
0
    def __setattr__(self, name, value):
        """
        The `set` method - responsible for *caching* the `value` to the
        corresponding object attribute given by `name`.

        .. note: This method sets the state of the resource to *dirty*
        (the `resource` will be persisted if the `commit` `session` method
        is called).

        """

        def make_values_source(values, rdf_values):
            """ Return callable that returns stored values for this attr. """
            
            def setattr_values_source():
                """ Return stored values for this attribute. """

                return values, rdf_values

            return setattr_values_source

        predicate, direct = attr2rdf(name)
        if predicate:
            rdf_dict = direct and self.__rdf_direct or self.__rdf_inverse
            if not isinstance(value, list):
                value = [value]
            rdf_dict[predicate] = []
            rdf_dict[predicate].extend([self.to_rdf(val) for val in value])
            self.dirty = True

            if type(value) is ResourceValue:
                pass
            else:
                if type(value) not in [list, tuple]: 
                    value = [value]
                    
                value = map(value_to_rdf, value)
                values_source = make_values_source(value, rdf_dict[predicate])
                value = ResourceValue(values_source, self, name)

        object.__setattr__(self, name, value)
Example #18
0
    def get_by(self, **kwargs):
        """ Add filter conditions.

        Arguments are expected in form::

            foaf_name = "John"

        Multiple arguments are supported.
        An example that retrieves all persons named "John Smith"::

            FoafPerson = session.get_class(surf.ns.FOAF.Person)
            for person in FoafPerson.get_by(foaf_name = "John", foaf_surname = "Smith"):
                print person.subject

        """

        params = self._params.copy()
        # Don't overwrite existing get_by parameters, just append new ones.
        # Overwriting get_by params would cause resource.some_attr.get_by()
        # to work incorrectly.
        params.setdefault("get_by", [])
        for name, value in kwargs.items():
            attr, direct = attr2rdf(name)

            if hasattr(value, "subject"):
                # If value has a subject attribute, this must be a Resource,
                # take its subject.
                value = value.subject
            elif not isinstance(value, basestring) and hasattr(
                    value, "__iter__"):
                # Map alternatives
                value = [
                    hasattr(val, "subject") and val.subject
                    or value_to_rdf(val) for val in value
                ]
            else:
                value = value_to_rdf(value)

            params["get_by"].append((attr, value, direct))
        return ResultProxy(params)
Example #19
0
    def get_by(self, **kwargs):
        """ Add filter conditions.

        Arguments are expected in form::

            foaf_name = "John"

        Multiple arguments are supported.
        An example that retrieves all persons named "John Smith"::

            FoafPerson = session.get_class(surf.ns.FOAF.Person)
            for person in FoafPerson.get_by(foaf_name = "John", foaf_surname = "Smith"):
                print person.subject

        """

        params = self.__params.copy()
        # Don't overwrite existing get_by parameters, just append new ones.
        # Overwriting get_by params would cause resource.some_attr.get_by()
        # to work incorrectly.
        params.setdefault("get_by", [])
        for name, value in kwargs.items():
            attr, direct = attr2rdf(name)

            if hasattr(value, "subject"):
                # If value has a subject attribute, this must be a Resource, 
                # take its subject.
                value = value.subject
            elif hasattr(value, "__iter__"):
                # Map alternatives
                value = map(lambda val: hasattr(val, "subject")
                                        and val.subject
                                        or value_to_rdf(val),
                            value)
            else:
                value = value_to_rdf(value)

            params["get_by"].append((attr, value, direct))
        return ResultProxy(params)
Example #20
0
    def __setattr__(self, name, value):
        """
        The `set` method - responsible for *caching* the `value` to the
        corresponding object attribute given by `name`.

        .. note: This method sets the state of the resource to *dirty*
        (the `resource` will be persisted if the `commit` `session` method
        is called).

        """
        def prepare_getvalues_callable(values, rdf_values):
            """ Return callable that returns stored values for this attr. """
            def getvalues_callable():
                """ Return stored values for this attribute. """

                return values, rdf_values

            return getvalues_callable

        predicate, direct = attr2rdf(name)
        if predicate:
            rdf_dict = direct and self.__rdf_direct or self.__rdf_inverse
            if not isinstance(value, list):
                value = [value]
            rdf_dict[predicate] = []
            rdf_dict[predicate].extend([self.to_rdf(val) for val in value])
            self.dirty = True

            if type(value) is LazyResourceLoader:
                pass
            else:
                if type(value) not in [list, tuple]:
                    value = [value]
                value = list(map(value_to_rdf, value))
                getvalues_callable = prepare_getvalues_callable(
                    value, rdf_dict[predicate])
                value = LazyResourceLoader(getvalues_callable, self, name)

        object.__setattr__(self, name, value)
Example #21
0
    def filter(self, **kwargs):
        """ Add filter conditions.

        Expects arguments in form::

            ns_predicate = "(%s > 15)"

        ``ns_predicate`` specifies which predicate will be used for
        filtering, a query variable will be bound to it. `%s` is a placeholder
        for this variable.

        Filter expression (in example: "(%s > 15)") must follow SPARQL
        specification, on execution "%s" will be substituted with variable
        and the resulting string will be placed in query as-is. Because of
        string substitution percent signs need to be escaped. For example::

            Person.all().filter(foaf_name = "(%s LIKE 'J%%')")

        This Virtuoso-specific filter is intended to select persons with names starting with
        "J". In generated query it will look like this::

            ...
            ?s <http://xmlns.com/foaf/0.1/name> ?f1 .
            FILTER (?f1 LIKE 'J%')
            ...

        """

        params = self.__params.copy()
        params.setdefault("filter", [])
        for name, value in kwargs.items():
            attr, direct = attr2rdf(name)
            assert direct, "Only direct attributes can be used for filters"
            # Assume by plain strings user means literals
            if type(value) in [str, unicode]:
                value = Literal(value)
            params["filter"].append((attr, value, direct))
        return ResultProxy(params)
Example #22
0
    def filter(self, **kwargs):
        """ Add filter conditions.

        Expects arguments in form::

            ns_predicate = "(%s > 15)"

        ``ns_predicate`` specifies which predicate will be used for
        filtering, a query variable will be bound to it. `%s` is a placeholder
        for this variable.

        Filter expression (in example: "(%s > 15)") must follow SPARQL
        specification, on execution "%s" will be substituted with variable
        and the resulting string will be placed in query as-is. Because of
        string substitution percent signs need to be escaped. For example::

            Person.all().filter(foaf_name = "(%s LIKE 'J%%')")

        This Virtuoso-specific filter is intended to select persons with names starting with
        "J". In generated query it will look like this::

            ...
            ?s <http://xmlns.com/foaf/0.1/name> ?f1 .
            FILTER (?f1 LIKE 'J%')
            ...

        """

        params = self.__params.copy()
        params.setdefault("filter", [])
        for name, value in kwargs.items():
            attr, direct = attr2rdf(name)
            assert direct, "Only direct attributes can be used for filters"
            # Assume by plain strings user means literals
            if type(value) in [str, unicode]:
                value = Literal(value)
            params["filter"].append((attr, value, direct))
        return ResultProxy(params)
Example #23
0
    def get_by_attribute(cls, attributes, context=None):
        """
        Retrieve all `instances` from the data store that have the specified `attributes`
        and are of `rdf:type` of the resource class

        """

        direct_attributes = []
        inverse_attributes = []
        attribute_uris = [inverse_attributes, direct_attributes]
        for attribute_name in attributes:
            attribute_uri, direct = attr2rdf(attribute_name)
            # Using boolean as array index.
            attribute_uris[direct].append(attribute_uri)

        subjects = {}
        if direct_attributes:
            subjects.update(cls.session[cls.store_key].instances_by_attribute(
                cls, direct_attributes, True, context))
        if inverse_attributes:
            subjects.update(cls.session[cls.store_key].instances_by_attribute(
                cls, inverse_attributes, False, context))

        instances = []
        for s, types in list(subjects.items()):
            if not isinstance(s, URIRef):
                continue

            if cls.uri:
                concepts = [cls.uri]
            else:
                concepts = types

            instances.append(cls._instance(s, concepts))

        return instances
Example #24
0
    def test_attr2rdf_period(self):
        """ Check that attr2rdf handles minus symbol in predicate names. """

        uriref, _ = attr2rdf("surf_predicate-with-minus")
        self.assertEquals(uriref, surf.ns.SURF["predicate-with-minus"])
Example #25
0
    def test_attr2rdf_period(self):
        """ Check that attr2rdf handles minus symbol in predicate names. """

        uriref, _ = attr2rdf("surf_predicate-with-minus")
        self.assertEquals(uriref, surf.ns.SURF["predicate-with-minus"])
Example #26
0
    def __getattr__(self, attr_name):
        """ Retrieve and cache attribute values.

        If attribute name is not in the "ns_predicate" form, an
        `AttributeError` will be raised.


        This method has no impact on the *dirty* state of the object.

        """

        predicate, direct = attr2rdf(attr_name)

        if not predicate:
            raise AttributeError('Not a predicate: %s' % attr_name)

        # Closure for lazy execution.
        def make_values_source(resource, predicate, direct, do_query):
            """ Return callable that loads and returns values. """
            def getattr_values_source():
                """ Load and return values for this attribute. """

                if do_query:
                    store = resource.session[resource.store_key]
                    # Request to triple store
                    values = store.get(resource, predicate, direct)
                    # Instantiate SuRF objects
                    surf_values = resource._lazy(values)
                else:
                    surf_values = []

                # Select triple dictionary for synchronization
                if direct:
                    rdf_dict = resource.__rdf_direct
                else:
                    rdf_dict = resource.__rdf_inverse

                # Save query_contexts
                for i in range(len(surf_values)):
                    if isinstance(surf_values[i], Resource):
                        surf_values[i].query_contexts = self.query_contexts

                # Initial synchronization
                rdf_dict[predicate] = [
                    resource.to_rdf(value) for value in surf_values
                ]

                return surf_values, rdf_dict[predicate]

            return getattr_values_source

        # If resource is fully loaded and still we're here
        # at __getattr__, this must be an empty attribute, so
        # no point querying triple store.
        do_query = not self.__full
        values_source = make_values_source(self, predicate, direct, do_query)

        attr_value = ResourceValue(values_source, self, attr_name)

        # Not using self.__setattr__, that would trigger loading of attributes
        object.__setattr__(self, attr_name, attr_value)
        self.dirty = False

        return attr_value