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"]
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
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
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)
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
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
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
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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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"])
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