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 store_value(): def values_source(): return ["1st_obj", "2nd_obj"], ["1st_uriref", "2nd_uriref"] store = MockStore() value = LazyResourceLoader(values_source, MockResource(store), "some_name") return store, value
def setUp(self): def values_source(): return ["1st_obj", "2nd_obj"], ["1st_uriref", "2nd_uriref"] self.store = MockStore() self.value = LazyResourceLoader(values_source, MockResource(self.store), "some_name")
def test_get_one_exceptions(self): """ Test RessourceValue.one. """ def values_source(): return ["1st_obj", "2nd_obj"], ["1st_uriref", "2nd_uriref"] instance = LazyResourceLoader(values_source, MockResource(), "some_name") self.assertRaises(surf.exceptions.CardinalityException, instance.get_one)
def test_contains(self): """ Test LazyResourceLoader.__contains__. """ def values_source(): return ["value_as_surf_object"], ["value_as_uriref"] instance = LazyResourceLoader(values_source, MockResource(), "some_name") # Test basic membership check. self.assertTrue("value_as_surf_object" in instance) # Test that "to_rdf" is tried. self.assertTrue("value_as_uriref" in instance)
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)