def test_create_finds_existing_entity_in_db(self): Entity.c.save({'name': 'existing', 'company_id': 1000}) existing = Entity.find_one({'company_id': 1000}) loader = self._make_loader() loader.create_entity(name=u'Test', company_id=1000, match_keys=('company_id',)) cached = loader.entity_cache[('company_id',)][(1000,)] h.assert_equal(existing['_id'], cached['_id']) h.assert_equal(Entity.find({'company_id': 1000}).count(), 1)
def test_loader_checks_duplicate_entities(self): entity = Entity(name=u'Test Entity') entity.save() duplicate = Entity(name=u'Test Entity') duplicate.save() h.assert_raises(ValueError, self._make_loader, unique_keys=['name'])
def _make_one(self, name, **kwargs): from openspending.model import Entity entity = kwargs entity['name'] = name new_id = Entity.c.save(entity, manipulate=True) return Entity.find_one({'_id': new_id})
def test_create_entry_with_different_match_keys(self): loader = self._make_loader() loader.create_entity(name=u'Test', company_id=1000, match_keys=('company_id',)) h.assert_equal(len(loader.entity_cache[('company_id',)]), 1) h.assert_true(Entity.find_one({'company_id': 1000}) is not None)
def create_entity(self, name=None, label=u'', description=u'', _cache=None, match_keys=('name', ), **entity): '''\ Create or update an :class:`openspending.model.Entity` object in the database when this is called for the entity the first time. An existing entity is looked up with the entitie's data for *match_keys*. By default we look up by name, but other data like company or tax ids may be more appropriate. The entry will only be created/updated if it is not in the ``_cache``. ``name`` Name of the entity. ``label, description`` label an description of the entity (unicodes) ``match_keys`` The keys with which we try to find an existing entity in the database. default: ('name',). type: ``list`` or ``tuple``. ``**entity`` Keyword arguments that are saved in the entity. ``_cache`` Use the given ``dict`` like object for caching. Normally not used by callers. It can be used to force an update of an entity that was created/updated by an earlier call. With ``None`` (default), the ``Loader`` uses internal caching. Returns: The created ``Entity`` object. Raises: :exc:`AssertionError` If the name ends with a suffix used for REST, e.g. .json. If match_keys is not list or tuple. :exc:`KeyError` If a given match_key is not present in the entity. ''' # assertions check_rest_suffix(name) if not isinstance(match_keys, (list, tuple)): raise AssertionError('match_keys has to be list or tuple') entity.update({'name': name, 'label': label, 'description': description}) # prepare a cache for the match_keys combination if _cache is None: _cache = self.entity_cache cache = _cache.setdefault(match_keys, {}) cache_key = tuple([entity[key] for key in match_keys]) if not cache_key in cache: query = {} for key in match_keys: query[key] = entity[key] entity_obj = Entity.find_one(query) if entity_obj is None: operation = CREATE else: operation = UPDATE Entity.c.update(query, {"$set": entity}, upsert=True) new_entity = Entity.find_one(query) self._add_changeobj(Entity.c.name, new_entity['_id'], new_entity, operation) cache[cache_key] = new_entity return cache[cache_key]