def test_10_package_alter_pending(self): context = {'model': model, 'session': model.Session, "user": '******', 'pending': True} anna1 = model.Session.query(model.Package).filter_by(name='annakarenina_changed').one() anna_dictized = package_dictize(anna1, context) anna_dictized['name'] = u'annakarenina_changed2' anna_dictized['resources'][0]['url'] = u'http://new_url2' anna_dictized['tags'][0]['name'] = u'new_tag' anna_dictized['tags'][0].pop('id') #test if anna_dictized['extras'][0]['value'] = u'new_value' model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() pkgrevisions = model.Session.query(model.PackageRevision).filter_by(id=anna1.id).all() sorted_packages = sorted(pkgrevisions, key=lambda x:x.revision_timestamp)[::-1] assert len(sorted_packages) == 3 assert sorted_packages[0].state == 'pending' assert sorted_packages[1].state == 'active' assert sorted_packages[1].current assert sorted_packages[2].state == 'active' assert str(sorted_packages[0].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_packages[1].expired_timestamp) != '9999-12-31 00:00:00' assert str(sorted_packages[2].expired_timestamp) != '9999-12-31 00:00:00' resources_revisions = model.Session.query(model.ResourceRevision).filter_by(package_id=anna1.id).all() sorted_resources = sorted(resources_revisions, key=lambda x: (x.revision_timestamp, x.url))[::-1] for pkg in sorted_resources: print pkg.url, pkg.id, pkg.revision_timestamp, pkg.expired_timestamp, pkg.state, pkg.current assert len(sorted_resources) == 4 assert sorted_resources[0].state == 'pending' assert sorted_resources[1].state == 'active' assert sorted_resources[1].current assert sorted_resources[2].state == 'active' assert sorted_resources[2].current assert sorted_resources[3].state == 'active' assert str(sorted_resources[0].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_resources[1].expired_timestamp) != '9999-12-31 00:00:00' assert str(sorted_resources[2].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_resources[3].expired_timestamp) != '9999-12-31 00:00:00' tag_revisions = model.Session.query(model.PackageTagRevision).filter_by(package_id=anna1.id).all() sorted_tags = sorted(tag_revisions, key=lambda x: (x.revision_timestamp, x.tag.name))[::-1] print [(tag.state, tag.tag.name) for tag in sorted_tags]
def test_08_package_save(self): context = {"model": model, "user": '******', "session": model.Session} anna1 = model.Session.query(model.Package).filter_by(name='annakarenina').one() anna_dictized = self.remove_changable_columns(package_dictize(anna1, context)) anna_dictized["name"] = u'annakarenina3' model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() # Re-clean anna_dictized anna_dictized = self.remove_changable_columns(anna_dictized) pkg = model.Session.query(model.Package).filter_by(name='annakarenina3').one() package_dictized = self.remove_changable_columns(package_dictize(pkg, context)) anna_original = pformat(anna_dictized) anna_after_save = pformat(package_dictized) assert package_dictized == anna_dictized,\ "\n".join(unified_diff(anna_original.split("\n"), anna_after_save.split("\n")))
def test_10_package_alter_pending(self): context = {"model": model, "session": model.Session, "pending": True} anna1 = model.Session.query(model.Package).filter_by(name="annakarenina_changed").one() anna_dictized = package_dictize(anna1, context) anna_dictized["name"] = u"annakarenina_changed2" anna_dictized["resources"][0]["url"] = u"new_url2" anna_dictized["tags"][0]["name"] = u"new_tag" anna_dictized["tags"][0].pop("id") # test if anna_dictized["extras"][0]["value"] = u'"new_value"' model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() pkgrevisions = model.Session.query(model.PackageRevision).filter_by(id=anna1.id).all() sorted_packages = sorted(pkgrevisions, key=lambda x: x.revision_timestamp)[::-1] assert len(sorted_packages) == 3 assert sorted_packages[0].state == "pending" assert sorted_packages[1].state == "active" assert sorted_packages[1].current assert sorted_packages[2].state == "active" assert str(sorted_packages[0].expired_timestamp) == "9999-12-31 00:00:00" assert str(sorted_packages[1].expired_timestamp) != "9999-12-31 00:00:00" assert str(sorted_packages[2].expired_timestamp) != "9999-12-31 00:00:00" resources_revisions = ( model.Session.query(model.ResourceRevision).filter_by(resource_group_id=anna1.resource_groups[0].id).all() ) sorted_resources = sorted(resources_revisions, key=lambda x: (x.revision_timestamp, x.url))[::-1] for pkg in sorted_resources: print pkg.url, pkg.id, pkg.revision_timestamp, pkg.expired_timestamp, pkg.state, pkg.current assert len(sorted_resources) == 4 assert sorted_resources[0].state == "pending" assert sorted_resources[1].state == "active" assert sorted_resources[1].current assert sorted_resources[2].state == "active" assert sorted_resources[2].current assert sorted_resources[3].state == "active" assert str(sorted_resources[0].expired_timestamp) == "9999-12-31 00:00:00" assert str(sorted_resources[1].expired_timestamp) != "9999-12-31 00:00:00" assert str(sorted_resources[2].expired_timestamp) == "9999-12-31 00:00:00" assert str(sorted_resources[3].expired_timestamp) != "9999-12-31 00:00:00" tag_revisions = model.Session.query(model.PackageTagRevision).filter_by(package_id=anna1.id).all() sorted_tags = sorted(tag_revisions, key=lambda x: (x.revision_timestamp, x.tag.name))[::-1] print [(tag.state, tag.tag.name) for tag in sorted_tags]
def modified_save(context, pkg, data): groups_key = 'groups' if groups_key in data: temp_groups = data[groups_key] data[groups_key] = None pkg = model_save.package_dict_save(data, context) data[groups_key] = temp_groups else: pkg = model_save.package_dict_save(data, context) package_membership_list_save(data.get("groups"), pkg, context) return pkg
def test_11_add_pending(self): context = {'model': model, 'session': model.Session, "user": '******', 'pending': True} anna1 = model.Session.query(model.Package).filter_by(name='annakarenina_changed2').one() anna_dictized = package_dictize(anna1, context) anna_dictized['notes'] = 'wee' anna_dictized['resources'].append({ 'format': u'plain text', 'url': u'http://newurl'} ) anna_dictized['tags'].append({'name': u'newnew_tag'}) anna_dictized['extras'].append({'key': 'david', 'value': u'new_value'}) model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() resources_revisions = model.Session.query(model.ResourceRevision).filter_by(package_id=anna1.id).all() sorted_resources = sorted(resources_revisions, key=lambda x: (x.revision_timestamp, x.url))[::-1] pprint(anna_dictized['resources']) for pkg in sorted_resources: print pkg.url, pkg.id, pkg.revision_timestamp, pkg.expired_timestamp, pkg.state, pkg.current assert len(sorted_resources) == 5, len(sorted_resources) assert sorted_resources[0].state == 'pending' assert sorted_resources[1].state == 'pending' assert sorted_resources[2].current assert sorted_resources[2].state == 'active' assert sorted_resources[3].current assert sorted_resources[3].state == 'active' assert sorted_resources[4].state == 'active' assert str(sorted_resources[0].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_resources[1].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_resources[2].expired_timestamp) != '9999-12-31 00:00:00' assert str(sorted_resources[3].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_resources[4].expired_timestamp) != '9999-12-31 00:00:00' tag_revisions = model.Session.query(model.PackageTagRevision).filter_by(package_id=anna1.id).all() sorted_tags = sorted(tag_revisions, key=lambda x: (x.revision_timestamp, x.tag.name))[::-1] print [(tag.state, tag.tag.name) for tag in sorted_tags]
def test_11_add_pending(self): context = {"model": model, "session": model.Session, "user": "******", "pending": True} anna1 = model.Session.query(model.Package).filter_by(name="annakarenina_changed2").one() anna_dictized = package_dictize(anna1, context) anna_dictized["notes"] = "wee" anna_dictized["resources"].append({"format": u"plain text", "url": u"http://newurl"}) anna_dictized["tags"].append({"name": u"newnew_tag"}) anna_dictized["extras"].append({"key": "david", "value": u"new_value"}) model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() resources_revisions = ( model.Session.query(model.ResourceRevision) .filter_by(resource_group_id=anna1.resource_groups_all[0].id) .all() ) sorted_resources = sorted(resources_revisions, key=lambda x: (x.revision_timestamp, x.url))[::-1] pprint(anna_dictized["resources"]) for pkg in sorted_resources: print pkg.url, pkg.id, pkg.revision_timestamp, pkg.expired_timestamp, pkg.state, pkg.current assert len(sorted_resources) == 5, len(sorted_resources) assert sorted_resources[0].state == "pending" assert sorted_resources[1].state == "pending" assert sorted_resources[2].current assert sorted_resources[2].state == "active" assert sorted_resources[3].current assert sorted_resources[3].state == "active" assert sorted_resources[4].state == "active" assert str(sorted_resources[0].expired_timestamp) == "9999-12-31 00:00:00" assert str(sorted_resources[1].expired_timestamp) == "9999-12-31 00:00:00" assert str(sorted_resources[2].expired_timestamp) != "9999-12-31 00:00:00" assert str(sorted_resources[3].expired_timestamp) == "9999-12-31 00:00:00" assert str(sorted_resources[4].expired_timestamp) != "9999-12-31 00:00:00" tag_revisions = model.Session.query(model.PackageTagRevision).filter_by(package_id=anna1.id).all() sorted_tags = sorted(tag_revisions, key=lambda x: (x.revision_timestamp, x.tag.name))[::-1] print [(tag.state, tag.tag.name) for tag in sorted_tags]
def package_create(context, data_dict): model = context["model"] user = context["user"] model.Session.remove() model.Session()._context = context package_type = data_dict.get("type") package_plugin = lib_plugins.lookup_package_plugin(package_type) try: schema = package_plugin.form_to_db_schema_options( {"type": "create", "api": "api_version" in context, "context": context} ) except AttributeError: schema = package_plugin.form_to_db_schema() check_access("package_create", context, data_dict) if "api_version" not in context: # old plugins do not support passing the schema so we need # to ensure they still work try: package_plugin.check_data_dict(data_dict, schema) except TypeError: package_plugin.check_data_dict(data_dict) data, errors = validate(data_dict, schema, context) if errors: model.Session.rollback() raise ValidationError(errors, error_summary(errors)) rev = model.repo.new_revision() rev.author = user if "message" in context: rev.message = context["message"] else: rev.message = _(u"REST API: Create object %s") % data.get("name") pkg = model_save.package_dict_save(data, context) admins = [] if user: admins = [model.User.by_name(user.decode("utf8"))] model.setup_default_user_roles(pkg, admins) # Needed to let extensions know the package id model.Session.flush() for item in plugins.PluginImplementations(plugins.IPackageController): item.create(pkg) if not context.get("defer_commit"): model.repo.commit() ## need to let rest api create context["package"] = pkg ## this is added so that the rest controller can make a new location context["id"] = pkg.id log.debug("Created object %s" % str(pkg.name)) return get_action("package_show")(context, {"id": context["id"]})
def package_update(context, data_dict): model = context['model'] user = context['user'] name_or_id = data_dict.get("id") or data_dict['name'] model.Session.remove() model.Session()._context = context pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg data_dict["id"] = pkg.id check_access('package_update', context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) try: schema = package_plugin.form_to_db_schema_options({'type':'update', 'api':'api_version' in context, 'context': context}) except AttributeError: schema = package_plugin.form_to_db_schema() if 'api_version' not in context: # old plugins do not support passing the schema so we need # to ensure they still work try: package_plugin.check_data_dict(data_dict, schema) except TypeError: package_plugin.check_data_dict(data_dict) data, errors = validate(data_dict, schema, context) if errors: model.Session.rollback() raise ValidationError(errors, error_summary(errors)) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") pkg = model_save.package_dict_save(data, context) for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) if not context.get('defer_commit'): model.repo.commit() return get_action('package_show')(context, data_dict)
def test_09_package_alter(self): context = {"model": model, "session": model.Session, "user": '******' } anna1 = model.Session.query(model.Package).filter_by(name='annakarenina').one() anna_dictized = package_dictize(anna1, context) anna_dictized["name"] = u'annakarenina_changed' anna_dictized["resources"][0]["url"] = u'http://new_url' model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() pkg = model.Session.query(model.Package).filter_by(name='annakarenina_changed').one() package_dictized = package_dictize(pkg, context) resources_revisions = model.Session.query(model.ResourceRevision).filter_by(package_id=anna1.id).all() sorted_resources = sorted(resources_revisions, key=lambda x: (x.revision_timestamp, x.url))[::-1] for res in sorted_resources: print res.id, res.revision_timestamp, res.expired_timestamp, res.state, res.current assert len(sorted_resources) == 3 # Make sure we remove changeable fields BEFORE we store the pretty-printed version # for comparison clean_package_dictized = self.remove_changable_columns(package_dictized) anna_original = pformat(anna_dictized) anna_after_save = pformat(clean_package_dictized) assert self.remove_changable_columns(anna_dictized) == clean_package_dictized, \ "\n".join(unified_diff(anna_original.split("\n"), anna_after_save.split("\n")))
def test_09_package_alter(self): context = {"model": model, "session": model.Session, "user": "******"} anna1 = model.Session.query(model.Package).filter_by(name="annakarenina").one() anna_dictized = package_dictize(anna1, context) anna_dictized["name"] = u"annakarenina_changed" anna_dictized["resources"][0]["url"] = u"http://new_url" model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() pkg = model.Session.query(model.Package).filter_by(name="annakarenina_changed").one() package_dictized = package_dictize(pkg, context) resources_revisions = ( model.Session.query(model.ResourceRevision) .filter_by(resource_group_id=anna1.resource_groups_all[0].id) .all() ) sorted_resources = sorted(resources_revisions, key=lambda x: (x.revision_timestamp, x.url))[::-1] for res in sorted_resources: print res.id, res.revision_timestamp, res.expired_timestamp, res.state, res.current assert len(sorted_resources) == 3 anna_original = pformat(anna_dictized) anna_after_save = pformat(package_dictized) print anna_original print anna_after_save assert self.remove_changable_columns(anna_dictized) == self.remove_changable_columns(package_dictized) assert "\n".join(unified_diff(anna_original.split("\n"), anna_after_save.split("\n")))
def package_create(context, data_dict): model = context['model'] user = context['user'] preview = context.get('preview', False) schema = context.get('schema') or default_create_package_schema() model.Session.remove() model.Session()._context = context check_access(model.System(), model.Action.PACKAGE_CREATE, context) check_group_auth(context, data_dict) data, errors = validate(data_dict, schema, context) if errors: model.Session.rollback() raise ValidationError(errors, package_error_summary(errors)) if not preview: rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Create object %s') % data.get("name") pkg = package_dict_save(data, context) admins = [] if user: admins = [model.User.by_name(user.decode('utf8'))] if not preview: model.setup_default_user_roles(pkg, admins) for item in PluginImplementations(IPackageController): item.create(pkg) model.repo.commit() ## need to let rest api create and preview context["package"] = pkg ## this is added so that the rest controller can make a new location context["id"] = pkg.id log.debug('Created object %s' % str(pkg.name)) if not preview: return package_dictize(pkg, context) else: return data
def package_update(context, data_dict): model = context['model'] user = context['user'] id = data_dict["id"] preview = context.get('preview', False) schema = context.get('schema') or default_update_package_schema() model.Session.remove() model.Session()._context = context pkg = model.Package.get(id) context["package"] = pkg if pkg is None: raise NotFound(_('Package was not found.')) data_dict["id"] = pkg.id check_access(pkg, model.Action.EDIT, context) data, errors = validate(data_dict, schema, context) check_group_auth(context, data) if errors: model.Session.rollback() raise ValidationError(errors, package_error_summary(errors)) if not preview: rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") pkg = package_dict_save(data, context) if not preview: for item in PluginImplementations(IPackageController): item.edit(pkg) model.repo.commit() return package_dictize(pkg, context) return data
def package_update(context, data_dict): model = context["model"] user = context["user"] id = data_dict["id"] schema = context.get("schema") or default_update_package_schema() model.Session.remove() model.Session()._context = context pkg = model.Package.get(id) context["package"] = pkg if pkg is None: raise NotFound(_("Package was not found.")) data_dict["id"] = pkg.id check_access("package_update", context, data_dict) data, errors = validate(data_dict, schema, context) if errors: model.Session.rollback() raise ValidationError(errors, package_error_summary(errors)) rev = model.repo.new_revision() rev.author = user if "message" in context: rev.message = context["message"] else: rev.message = _(u"REST API: Update object %s") % data.get("name") pkg = package_dict_save(data, context) for item in PluginImplementations(IPackageController): item.edit(pkg) if not context.get("defer_commit"): model.repo.commit() return package_dictize(pkg, context)
def package_update(context, data_dict): '''Update a dataset (package). You must be authorized to edit the dataset and the groups that it belongs to. Plugins may change the parameters of this function depending on the value of the dataset's ``type`` attribute, see the ``IDatasetForm`` plugin interface. For further parameters see ``package_create()``. :param id: the name or id of the dataset to update :type id: string :returns: the updated dataset (if 'return_package_dict' is True in the context, which is the default. Otherwise returns just the dataset id) :rtype: dictionary ''' model = context['model'] user = context['user'] name_or_id = data_dict.get("id") or data_dict['name'] pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg data_dict["id"] = pkg.id _check_access('package_update', context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) try: schema = package_plugin.form_to_db_schema_options({ 'type': 'update', 'api': 'api_version' in context, 'context': context }) except AttributeError: schema = package_plugin.form_to_db_schema() if 'api_version' not in context: # old plugins do not support passing the schema so we need # to ensure they still work try: package_plugin.check_data_dict(data_dict, schema) except TypeError: package_plugin.check_data_dict(data_dict) data, errors = _validate(data_dict, schema, context) log.debug('package_update validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), context.get('package').name if context.get('package') else '', data) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") pkg = model_save.package_dict_save(data, context) context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True _get_action('package_owner_org_update')(context_org_update, { 'id': pkg.id, 'organization_id': pkg.owner_org }) for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) item.after_update(context, data) if not context.get('defer_commit'): model.repo.commit() log.debug('Updated object %s' % str(pkg.name)) return_id_only = context.get('return_id_only', False) output = data_dict['id'] if return_id_only \ else _get_action('package_show')(context, {'id': data_dict['id']}) return output
def test_10_package_alter_pending(self): context = {'model': model, 'session': model.Session, 'pending': True} anna1 = model.Session.query(model.Package).filter_by(name='annakarenina_changed').one() anna_dictized = package_dictize(anna1, context) anna_dictized['name'] = u'annakarenina_changed2' anna_dictized['resources'][0]['url'] = u'new_url2' anna_dictized['tags'][0]['name'] = u'new_tag' anna_dictized['tags'][0].pop('id') #test if anna_dictized['extras'][0]['value'] = u'"new_value"' model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() pkgrevisions = model.Session.query(model.PackageRevision).filter_by(id=anna1.id).all() sorted_packages = sorted(pkgrevisions, key=lambda x:x.revision_timestamp)[::-1] assert len(sorted_packages) == 3 assert sorted_packages[0].state == 'pending' assert sorted_packages[1].state == 'active' assert sorted_packages[1].current assert sorted_packages[2].state == 'active' assert str(sorted_packages[0].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_packages[1].expired_timestamp) != '9999-12-31 00:00:00' assert str(sorted_packages[2].expired_timestamp) != '9999-12-31 00:00:00' resources_revisions = model.Session.query(model.ResourceRevision).filter_by(resource_group_id=anna1.resource_groups[0].id).all() sorted_resources = sorted(resources_revisions, key=lambda x: (x.revision_timestamp, x.url))[::-1] for pkg in sorted_resources: print pkg.url, pkg.id, pkg.revision_timestamp, pkg.expired_timestamp, pkg.state, pkg.current assert len(sorted_resources) == 4 assert sorted_resources[0].state == 'pending' assert sorted_resources[1].state == 'active' assert sorted_resources[1].current assert sorted_resources[2].state == 'active' assert sorted_resources[2].current assert sorted_resources[3].state == 'active' assert str(sorted_resources[0].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_resources[1].expired_timestamp) != '9999-12-31 00:00:00' assert str(sorted_resources[2].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_resources[3].expired_timestamp) != '9999-12-31 00:00:00' tag_revisions = model.Session.query(model.PackageTagRevision).filter_by(package_id=anna1.id).all() sorted_tags = sorted(tag_revisions, key=lambda x: (x.revision_timestamp, x.tag.name))[::-1] print [(tag.state, tag.tag.name) for tag in sorted_tags] assert len(sorted_tags) == 5, len(sorted_tags) assert sorted_tags[0].state == 'pending' # new_tag assert sorted_tags[1].state == 'pending-deleted' # Flexible assert sorted_tags[2].state == 'active' # tolstoy assert sorted_tags[3].state == 'active' # russian assert sorted_tags[4].state == 'active' # Flexible assert sorted_tags[2].current assert sorted_tags[3].current assert sorted_tags[4].current assert str(sorted_tags[0].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_tags[1].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_tags[2].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_tags[3].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_tags[4].expired_timestamp) != '9999-12-31 00:00:00' extras_revisions = model.Session.query(model.PackageExtraRevision).filter_by(package_id=anna1.id).all() sorted_extras = sorted(extras_revisions, key=lambda x: (x.revision_timestamp, x.key))[::-1] assert sorted_extras[0].state == 'pending' assert sorted_resources[1].current assert sorted_extras[1].state == 'active' assert sorted_resources[1].current assert sorted_extras[2].state == 'active' assert str(sorted_extras[0].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_extras[1].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_extras[2].expired_timestamp) != '9999-12-31 00:00:00'
def package_update(context, data_dict): '''Update a dataset (package). You must be authorized to edit the dataset and the groups that it belongs to. It is recommended to call :py:func:`ckan.logic.action.get.package_show`, make the desired changes to the result, and then call ``package_update()`` with it. Plugins may change the parameters of this function depending on the value of the dataset's ``type`` attribute, see the :py:class:`~ckan.plugins.interfaces.IDatasetForm` plugin interface. For further parameters see :py:func:`~ckan.logic.action.create.package_create`. :param id: the name or id of the dataset to update :type id: string :returns: the updated dataset (if ``'return_package_dict'`` is ``True`` in the context, which is the default. Otherwise returns just the dataset id) :rtype: dictionary ''' model = context['model'] user = context['user'] name_or_id = data_dict.get('id') or data_dict.get('name') if name_or_id is None: raise ValidationError({'id': _('Missing value')}) pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg data_dict["id"] = pkg.id data_dict['type'] = pkg.type _check_access('package_update', context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.update_package_schema() if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: package_plugin.check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work. package_plugin.check_data_dict(data_dict) data, errors = lib_plugins.plugin_validate(package_plugin, context, data_dict, schema, 'package_update') log.debug('package_update validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), context.get('package').name if context.get('package') else '', data) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") #avoid revisioning by updating directly model.Session.query(model.Package).filter_by(id=pkg.id).update( {"metadata_modified": datetime.datetime.utcnow()}) model.Session.refresh(pkg) pkg = model_save.package_dict_save(data, context) context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True context_org_update['add_revision'] = False _get_action('package_owner_org_update')(context_org_update, { 'id': pkg.id, 'organization_id': pkg.owner_org }) # Needed to let extensions know the new resources ids model.Session.flush() if data.get('resources'): for index, resource in enumerate(data['resources']): resource['id'] = pkg.resources[index].id for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) item.after_update(context, data) if not context.get('defer_commit'): model.repo.commit() log.debug('Updated object %s' % pkg.name) return_id_only = context.get('return_id_only', False) # Make sure that a user provided schema is not used on package_show context.pop('schema', None) # we could update the dataset so we should still be able to read it. context['ignore_auth'] = True output = data_dict['id'] if return_id_only \ else _get_action('package_show')(context, {'id': data_dict['id']}) return output
def package_update(context, data_dict): model = context['model'] user = context['user'] name_or_id = data_dict.get("id") or data_dict['name'] pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg data_dict["id"] = pkg.id check_access('package_update', context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.update_package_schema() # We modify the schema here to replace owner_org_validator by our own if 'owner_org' in schema: schema['owner_org'] = [uds_oov if f is default_oov else f for f in schema['owner_org']] if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: package_plugin.check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work. package_plugin.check_data_dict(data_dict) data, errors = lib_plugins.plugin_validate( package_plugin, context, data_dict, schema, 'package_update') log.debug('package_update validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), context.get('package').name if context.get('package') else '', data) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") #avoid revisioning by updating directly model.Session.query(model.Package).filter_by(id=pkg.id).update( {"metadata_modified": datetime.datetime.utcnow()}) model.Session.refresh(pkg) pkg = model_save.package_dict_save(data, context) context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True get_action('package_owner_org_update')(context_org_update, {'id': pkg.id, 'organization_id': pkg.owner_org}) for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) item.after_update(context, data) if not context.get('defer_commit'): model.repo.commit() log.debug('Updated object %s' % pkg.name) return_id_only = context.get('return_id_only', False) # Make sure that a user provided schema is not used on package_show context.pop('schema', None) # we could update the dataset so we should still be able to read it. context['ignore_auth'] = True output = data_dict['id'] if return_id_only \ else get_action('package_show')(context, {'id': data_dict['id']}) return output
def test_15_api_to_dictize(self): context = {"model": model, "api_version": 1, "session": model.Session} api_data = { "name": u"testpkg", "title": u"Some Title", "url": u"http://blahblahblah.mydomain", "resources": [ { u"url": u"http://blah.com/file2.xml", u"format": u"xml", u"description": u"Second file", u"hash": u"def123", u"alt_url": u"alt_url", u"size": u"200", }, { u"url": u"http://blah.com/file.xml", u"format": u"xml", u"description": u"Main file", u"hash": u"abc123", u"alt_url": u"alt_url", u"size": u"200", }, ], "tags": u"russion novel", "license_id": u"gpl-3.0", "extras": { "genre": u"horror", "media": u"dvd" }, } dictized = package_api_to_dict(api_data, context) assert dictized == { "extras": [ { "key": "genre", "value": u"horror" }, { "key": "media", "value": u"dvd" }, ], "license_id": u"gpl-3.0", "name": u"testpkg", "resources": [ { u"alt_url": u"alt_url", u"description": u"Second file", u"size": u"200", u"format": u"xml", u"hash": u"def123", u"url": u"http://blah.com/file2.xml", }, { u"alt_url": u"alt_url", u"description": u"Main file", u"size": u"200", u"format": u"xml", u"hash": u"abc123", u"url": u"http://blah.com/file.xml", }, ], "tags": [{ "name": u"russion" }, { "name": u"novel" }], "title": u"Some Title", "url": u"http://blahblahblah.mydomain", } package_dict_save(dictized, context) model.Session.commit() model.Session.remove() pkg = model.Package.get("testpkg") self.remove_changable_columns(package_dictize(pkg, context))
def test_09_package_alter(self): context = { "model": model, "session": model.Session, "user": '******' } anna1 = model.Session.query( model.Package).filter_by(name='annakarenina').one() anna_dictized = package_dictize(anna1, context) anna_dictized["name"] = u'annakarenina_changed' anna_dictized["resources"][0]["url"] = u'http://new_url' package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() make_package_revision(model.Package.by_name('annakarenina_changed')) pkg = model.Session.query( model.Package).filter_by(name='annakarenina_changed').one() package_dictized = package_dictize(pkg, context) resources_revisions = model.Session.query( RevisionTableMappings.instance().ResourceRevision).filter_by( package_id=anna1.id).all() sorted_resource_revisions = sorted(resources_revisions, key=lambda x: (x.revision_timestamp, x.url))[::-1] for res in sorted_resource_revisions: print(res.id, res.revision_timestamp, res.state) assert len( sorted_resource_revisions ) == 4 # 2 resources originally, then make_package_revision saves them both again # Make sure we remove changeable fields BEFORE we store the pretty-printed version # for comparison clean_package_dictized = self.remove_changable_columns( package_dictized) anna_original = pformat(anna_dictized) anna_after_save = pformat(clean_package_dictized) assert self.remove_changable_columns(anna_dictized) == clean_package_dictized, \ "\n".join(unified_diff(anna_original.split("\n"), anna_after_save.split("\n"))) # changes to the package, relied upon by later tests anna1 = model.Session.query( model.Package).filter_by(name='annakarenina_changed').one() anna_dictized = package_dictize(anna1, context) anna_dictized['name'] = u'annakarenina_changed2' anna_dictized['resources'][0]['url'] = u'http://new_url2' anna_dictized['tags'][0]['name'] = u'new_tag' anna_dictized['tags'][0].pop('id') # test if anna_dictized['extras'][0]['value'] = u'new_value' package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() make_package_revision(model.Package.by_name('annakarenina_changed2')) anna1 = model.Session.query( model.Package).filter_by(name='annakarenina_changed2').one() anna_dictized = package_dictize(anna1, context) anna_dictized['notes'] = 'wee' anna_dictized['resources'].append({ 'format': u'plain text', 'url': u'http://newurl' }) anna_dictized['tags'].append({'name': u'newnew_tag'}) anna_dictized['extras'].append({'key': 'david', 'value': u'new_value'}) package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() make_package_revision(model.Package.by_name('annakarenina_changed2')) context = {'model': model, 'session': model.Session} anna1 = model.Session.query( model.Package).filter_by(name='annakarenina_changed2').one() pkgrevisions = model.Session.query( RevisionTableMappings.instance().PackageRevision).filter_by( id=anna1.id).all() sorted_packages = sorted(pkgrevisions, key=lambda x: x.revision_timestamp) context['revision_id'] = sorted_packages[ 0].revision_id # original state with PackageDictizeMonkeyPatch(): first_dictized = self.remove_changable_columns( package_dictize(anna1, context)) assert self.remove_changable_columns( self.package_expected) == first_dictized context['revision_id'] = sorted_packages[1].revision_id second_dictized = self.remove_changable_columns( package_dictize(anna1, context)) first_dictized["name"] = u'annakarenina_changed' first_dictized["resources"][0]["url"] = u'http://new_url' assert second_dictized == first_dictized context['revision_id'] = sorted_packages[2].revision_id third_dictized = self.remove_changable_columns( package_dictize(anna1, context)) second_dictized['name'] = u'annakarenina_changed2' second_dictized['resources'][0]['url'] = u'http://new_url2' second_dictized['tags'][0]['name'] = u'new_tag' second_dictized['tags'][0]['display_name'] = u'new_tag' second_dictized['state'] = 'active' print('\n'.join( unified_diff( pformat(second_dictized).split('\n'), pformat(third_dictized).split('\n')))) assert second_dictized == third_dictized context['revision_id'] = sorted_packages[ 3].revision_id # original state forth_dictized = self.remove_changable_columns( package_dictize(anna1, context)) third_dictized['notes'] = 'wee' third_dictized['resources'].insert( 2, { u'cache_last_updated': None, u'cache_url': None, u'description': u'', u'format': u'plain text', u'hash': u'', u'last_modified': None, u'mimetype': None, u'mimetype_inner': None, u'name': None, u'position': 2, u'resource_type': None, u'url_type': None, u'size': None, u'state': u'active', u'url': u'http://newurl' }) third_dictized['num_resources'] = third_dictized['num_resources'] + 1 third_dictized['tags'].insert( 1, { 'name': u'newnew_tag', 'display_name': u'newnew_tag', 'state': 'active' }) third_dictized['num_tags'] = third_dictized['num_tags'] + 1 third_dictized['state'] = 'active' third_dictized['state'] = 'active' pprint(third_dictized) pprint(forth_dictized) assert third_dictized == forth_dictized
def package_update(context, data_dict): '''Update a dataset (package). You must be authorized to edit the dataset and the groups that it belongs to. Plugins may change the parameters of this function depending on the value of the dataset's ``type`` attribute, see the ``IDatasetForm`` plugin interface. For further parameters see ``package_create()``. :param id: the name or id of the dataset to update :type id: string :returns: the updated dataset :rtype: dictionary ''' model = context['model'] user = context['user'] name_or_id = data_dict.get("id") or data_dict['name'] model.Session.remove() model.Session()._context = context pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg data_dict["id"] = pkg.id _check_access('package_update', context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) try: schema = package_plugin.form_to_db_schema_options({ 'type': 'update', 'api': 'api_version' in context, 'context': context }) except AttributeError: schema = package_plugin.form_to_db_schema() if 'api_version' not in context: # old plugins do not support passing the schema so we need # to ensure they still work try: package_plugin.check_data_dict(data_dict, schema) except TypeError: package_plugin.check_data_dict(data_dict) data, errors = _validate(data_dict, schema, context) if errors: model.Session.rollback() raise ValidationError(errors, _error_summary(errors)) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") pkg = model_save.package_dict_save(data, context) for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) if not context.get('defer_commit'): model.repo.commit() return _get_action('package_show')(context, data_dict)
def test_09_package_alter(self): context = {"model": model, "session": model.Session, "user": "******"} anna1 = model.Session.query(model.Package).filter_by(name="annakarenina").one() anna_dictized = package_dictize(anna1, context) anna_dictized["name"] = u"annakarenina_changed" anna_dictized["resources"][0]["url"] = u"http://new_url" model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() pkg = model.Session.query(model.Package).filter_by(name="annakarenina_changed").one() package_dictized = package_dictize(pkg, context) resources_revisions = model.Session.query(model.ResourceRevision).filter_by(package_id=anna1.id).all() sorted_resource_revisions = sorted(resources_revisions, key=lambda x: (x.revision_timestamp, x.url))[::-1] for res in sorted_resource_revisions: print res.id, res.revision_timestamp, res.state assert len(sorted_resource_revisions) == 3 # Make sure we remove changeable fields BEFORE we store the pretty-printed version # for comparison clean_package_dictized = self.remove_changable_columns(package_dictized) anna_original = pformat(anna_dictized) anna_after_save = pformat(clean_package_dictized) assert self.remove_changable_columns(anna_dictized) == clean_package_dictized, "\n".join( unified_diff(anna_original.split("\n"), anna_after_save.split("\n")) ) # changes to the package, relied upon by later tests anna1 = model.Session.query(model.Package).filter_by(name="annakarenina_changed").one() anna_dictized = package_dictize(anna1, context) anna_dictized["name"] = u"annakarenina_changed2" anna_dictized["resources"][0]["url"] = u"http://new_url2" anna_dictized["tags"][0]["name"] = u"new_tag" anna_dictized["tags"][0].pop("id") # test if anna_dictized["extras"][0]["value"] = u"new_value" model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() anna1 = model.Session.query(model.Package).filter_by(name="annakarenina_changed2").one() anna_dictized = package_dictize(anna1, context) anna_dictized["notes"] = "wee" anna_dictized["resources"].append({"format": u"plain text", "url": u"http://newurl"}) anna_dictized["tags"].append({"name": u"newnew_tag"}) anna_dictized["extras"].append({"key": "david", "value": u"new_value"}) model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove()
def package_create(context, data_dict): '''Create a new dataset (package). You must be authorized to create new datasets. If you specify any groups for the new dataset, you must also be authorized to edit these groups. Plugins may change the parameters of this function depending on the value of the ``type`` parameter, see the ``IDatasetForm`` plugin interface. :param name: the name of the new dataset, must be between 2 and 100 characters long and contain only lowercase alphanumeric characters, ``-`` and ``_``, e.g. ``'warandpeace'`` :type name: string :param title: the title of the dataset (optional, default: same as ``name``) :type title: string :param author: the name of the dataset's author (optional) :type author: string :param author_email: the email address of the dataset's author (optional) :type author_email: string :param maintainer: the name of the dataset's maintainer (optional) :type maintainer: string :param maintainer_email: the email address of the dataset's maintainer (optional) :type maintainer_email: string :param license_id: the id of the dataset's license, see ``license_list()`` for available values (optional) :type license_id: license id string :param notes: a description of the dataset (optional) :type notes: string :param url: a URL for the dataset's source (optional) :type url: string :param version: (optional) :type version: string, no longer than 100 characters :param state: the current state of the dataset, e.g. ``'active'`` or ``'deleted'``, only active datasets show up in search results and other lists of datasets, this parameter will be ignored if you are not authorized to change the state of the dataset (optional, default: ``'active'``) :type state: string :param type: the type of the dataset (optional), ``IDatasetForm`` plugins associate themselves with different dataset types and provide custom dataset handling behaviour for these types :type type: string :param resources: the dataset's resources, see ``resource_create()`` for the format of resource dictionaries (optional) :type resources: list of resource dictionaries :param tags: the dataset's tags, see ``tag_create()`` for the format of tag dictionaries (optional) :type tags: list of tag dictionaries :param extras: the dataset's extras (optional), extras are arbitrary (key: value) metadata items that can be added to datasets, each extra dictionary should have keys ``'key'`` (a string), ``'value'`` (a string), and optionally ``'deleted'`` :type extras: list of dataset extra dictionaries :param relationships_as_object: see ``package_relationship_create()`` for the format of relationship dictionaries (optional) :type relationships_as_object: list of relationship dictionaries :param relationships_as_subject: see ``package_relationship_create()`` for the format of relationship dictionaries (optional) :type relationships_as_subject: list of relationship dictionaries :param groups: the groups to which the dataset belongs (optional), each group dictionary should have one or more of the following keys which identify an existing group: ``'id'`` (the id of the group, string), ``'name'`` (the name of the group, string), ``'title'`` (the title of the group, string), to see which groups exist call ``group_list()`` :type groups: list of dictionaries :returns: the newly created dataset :rtype: dictionary ''' model = context['model'] user = context['user'] model.Session.remove() model.Session()._context = context package_type = data_dict.get('type') package_plugin = lib_plugins.lookup_package_plugin(package_type) try: schema = package_plugin.form_to_db_schema_options({'type':'create', 'api':'api_version' in context, 'context': context}) except AttributeError: schema = package_plugin.form_to_db_schema() _check_access('package_create', context, data_dict) if 'api_version' not in context: # old plugins do not support passing the schema so we need # to ensure they still work try: package_plugin.check_data_dict(data_dict, schema) except TypeError: package_plugin.check_data_dict(data_dict) data, errors = _validate(data_dict, schema, context) if errors: model.Session.rollback() raise ValidationError(errors, _error_summary(errors)) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Create object %s') % data.get("name") pkg = model_save.package_dict_save(data, context) admins = [] if user: admins = [model.User.by_name(user.decode('utf8'))] model.setup_default_user_roles(pkg, admins) # Needed to let extensions know the package id model.Session.flush() for item in plugins.PluginImplementations(plugins.IPackageController): item.create(pkg) if not context.get('defer_commit'): model.repo.commit() ## need to let rest api create context["package"] = pkg ## this is added so that the rest controller can make a new location context["id"] = pkg.id log.debug('Created object %s' % str(pkg.name)) return _get_action('package_show')(context, {'id':context['id']})
def package_create(fb, context, data_dict): model = context['model'] user = context['user'] package_type = data_dict.get('type') package_plugin = lib_plugins.lookup_package_plugin(package_type) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.create_package_schema() # We modify the schema here to replace owner_org_validator by our own if 'owner_org' in schema: schema['owner_org'] = [uds_oov if f is default_oov else f for f in schema['owner_org']] check_access('package_create', context, data_dict) if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work package_plugin.check_data_dict(data_dict) data, errors = lib_plugins.plugin_validate( package_plugin, context, data_dict, schema, 'package_create') log.debug('package_create validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), data.get('name'), data_dict) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Create object %s') % data.get("name") admins = [] if user: user_obj = model.User.by_name(user.decode('utf8')) if user_obj: admins = [user_obj] data['creator_user_id'] = user_obj.id pkg = model_save.package_dict_save(data, context) model.setup_default_user_roles(pkg, admins) # Needed to let extensions know the package id model.Session.flush() data['id'] = pkg.id context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True get_action('package_owner_org_update')(context_org_update, {'id': pkg.id, 'organization_id': pkg.owner_org}) for item in plugins.PluginImplementations(plugins.IPackageController): item.create(pkg) item.after_create(context, data) if not context.get('defer_commit'): model.repo.commit() ## need to let rest api create context["package"] = pkg ## this is added so that the rest controller can make a new location context["id"] = pkg.id log.debug('Created object %s' % pkg.name) # Make sure that a user provided schema is not used on package_show context.pop('schema', None) return_id_only = context.get('return_id_only', False) output = context['id'] if return_id_only \ else get_action('package_show')(context, {'id': context['id']}) return output
def package_create(context, data_dict): model = context['model'] user = context['user'] model.Session.remove() model.Session()._context = context package_type = data_dict.get('type') package_plugin = lib_plugins.lookup_package_plugin(package_type) try: schema = package_plugin.form_to_db_schema_options({ 'type': 'create', 'api': 'api_version' in context }) except AttributeError: schema = package_plugin.form_to_db_schema() check_access('package_create', context, data_dict) if 'api_version' not in context: # old plugins do not support passing the schema so we need # to ensure they still work try: package_plugin.check_data_dict(data_dict, schema) except TypeError: package_plugin.check_data_dict(data_dict) data, errors = validate(data_dict, schema, context) if errors: model.Session.rollback() raise ValidationError(errors, error_summary(errors)) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Create object %s') % data.get("name") pkg = model_save.package_dict_save(data, context) admins = [] if user: admins = [model.User.by_name(user.decode('utf8'))] model.setup_default_user_roles(pkg, admins) # Needed to let extensions know the package id model.Session.flush() for item in plugins.PluginImplementations(plugins.IPackageController): item.create(pkg) if not context.get('defer_commit'): model.repo.commit() ## need to let rest api create context["package"] = pkg ## this is added so that the rest controller can make a new location context["id"] = pkg.id log.debug('Created object %s' % str(pkg.name)) return get_action('package_show')(context, {'id': context['id']})
def package_create(fb, context, data_dict): model = context['model'] user = context['user'] package_type = data_dict.get('type') package_plugin = lib_plugins.lookup_package_plugin(package_type) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.create_package_schema() # We modify the schema here to replace owner_org_validator by our own if 'owner_org' in schema: schema['owner_org'] = [ uds_oov if f is default_oov else f for f in schema['owner_org'] ] check_access('package_create', context, data_dict) if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work package_plugin.check_data_dict(data_dict) data, errors = lib_plugins.plugin_validate(package_plugin, context, data_dict, schema, 'package_create') log.debug('package_create validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), data.get('name'), data_dict) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Create object %s') % data.get("name") admins = [] if user: user_obj = model.User.by_name(user.decode('utf8')) if user_obj: admins = [user_obj] data['creator_user_id'] = user_obj.id pkg = model_save.package_dict_save(data, context) model.setup_default_user_roles(pkg, admins) # Needed to let extensions know the package id model.Session.flush() data['id'] = pkg.id context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True get_action('package_owner_org_update')(context_org_update, { 'id': pkg.id, 'organization_id': pkg.owner_org }) for item in plugins.PluginImplementations(plugins.IPackageController): item.create(pkg) item.after_create(context, data) if not context.get('defer_commit'): model.repo.commit() ## need to let rest api create context["package"] = pkg ## this is added so that the rest controller can make a new location context["id"] = pkg.id log.debug('Created object %s' % pkg.name) # Make sure that a user provided schema is not used on package_show context.pop('schema', None) return_id_only = context.get('return_id_only', False) output = context['id'] if return_id_only \ else get_action('package_show')(context, {'id': context['id']}) return output
def package_update(context, data_dict): '''Update a dataset (package). You must be authorized to edit the dataset and the groups that it belongs to. Plugins may change the parameters of this function depending on the value of the dataset's ``type`` attribute, see the ``IDatasetForm`` plugin interface. For further parameters see ``package_create()``. :param id: the name or id of the dataset to update :type id: string :returns: the updated dataset (if 'return_package_dict' is True in the context, which is the default. Otherwise returns just the dataset id) :rtype: dictionary ''' model = context['model'] user = context['user'] name_or_id = data_dict.get("id") or data_dict['name'] pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg data_dict["id"] = pkg.id _check_access('package_update', context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) try: schema = package_plugin.form_to_db_schema_options({'type':'update', 'api':'api_version' in context, 'context': context}) except AttributeError: schema = package_plugin.form_to_db_schema() if 'api_version' not in context: # old plugins do not support passing the schema so we need # to ensure they still work try: package_plugin.check_data_dict(data_dict, schema) except TypeError: package_plugin.check_data_dict(data_dict) data, errors = _validate(data_dict, schema, context) log.debug('package_update validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), context.get('package').name if context.get('package') else '', data) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") pkg = model_save.package_dict_save(data, context) context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True _get_action('package_owner_org_update')(context_org_update, {'id': pkg.id, 'organization_id': pkg.owner_org}) for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) item.after_update(context, data) if not context.get('defer_commit'): model.repo.commit() log.debug('Updated object %s' % str(pkg.name)) return_id_only = context.get('return_id_only', False) # we could update the dataset so we should still be able to read it. context['ignore_auth'] = True output = data_dict['id'] if return_id_only \ else _get_action('package_show')(context, {'id': data_dict['id']}) return output
def test_11_add_pending(self): context = {'model': model, 'session': model.Session, 'pending': True} anna1 = model.Session.query(model.Package).filter_by(name='annakarenina_changed2').one() anna_dictized = package_dictize(anna1, context) anna_dictized['notes'] = 'wee' anna_dictized['resources'].append({ 'format': u'plain text', 'url': u'newurl'} ) anna_dictized['tags'].append({'name': u'newnew_tag'}) anna_dictized['extras'].append({'key': 'david', 'value': u'"new_value"'}) model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() resources_revisions = model.Session.query(model.ResourceRevision).filter_by(resource_group_id=anna1.resource_groups[0].id).all() sorted_resources = sorted(resources_revisions, key=lambda x: (x.revision_timestamp, x.url))[::-1] pprint(anna_dictized['resources']) for pkg in sorted_resources: print pkg.url, pkg.id, pkg.revision_timestamp, pkg.expired_timestamp, pkg.state, pkg.current assert len(sorted_resources) == 5, len(sorted_resources) assert sorted_resources[0].state == 'pending' assert sorted_resources[1].state == 'pending' assert sorted_resources[2].current assert sorted_resources[2].state == 'active' assert sorted_resources[3].current assert sorted_resources[3].state == 'active' assert sorted_resources[4].state == 'active' assert str(sorted_resources[0].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_resources[1].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_resources[2].expired_timestamp) != '9999-12-31 00:00:00' assert str(sorted_resources[3].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_resources[4].expired_timestamp) != '9999-12-31 00:00:00' tag_revisions = model.Session.query(model.PackageTagRevision).filter_by(package_id=anna1.id).all() sorted_tags = sorted(tag_revisions, key=lambda x: (x.revision_timestamp, x.tag.name))[::-1] print [(tag.state, tag.tag.name) for tag in sorted_tags] assert len(sorted_tags) == 6, len(sorted_tags) assert sorted_tags[0].state == 'pending' # newnew_tag assert sorted_tags[1].state == 'pending' # new_tag assert sorted_tags[2].state == 'pending-deleted' # Flexible assert sorted_tags[3].state == 'active' # tolstoy assert sorted_tags[4].state == 'active' # russian assert sorted_tags[5].state == 'active' # Flexible assert sorted_tags[3].current assert sorted_tags[4].current assert sorted_tags[5].current assert str(sorted_tags[0].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_tags[1].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_tags[2].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_tags[3].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_tags[4].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_tags[5].expired_timestamp) != '9999-12-31 00:00:00' extras_revisions = model.Session.query(model.PackageExtraRevision).filter_by(package_id=anna1.id).all() sorted_extras = sorted(extras_revisions, key=lambda x: (x.revision_timestamp, x.key))[::-1] print [(extra.state, extra.key, extra.value) for extra in sorted_extras] assert sorted_extras[0].state == 'pending' assert sorted_extras[1].state == 'pending' assert sorted_extras[2].state == 'active' assert sorted_extras[3].state == 'active' assert str(sorted_extras[0].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_extras[1].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_extras[2].expired_timestamp) == '9999-12-31 00:00:00' assert str(sorted_extras[3].expired_timestamp) != '9999-12-31 00:00:00'
def test_09_package_alter(self): context = { "model": model, "session": model.Session, "user": '******' } anna1 = model.Session.query( model.Package).filter_by(name='annakarenina').one() anna_dictized = package_dictize(anna1, context) anna_dictized["name"] = u'annakarenina_changed' anna_dictized["resources"][0]["url"] = u'http://new_url' model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() pkg = model.Session.query( model.Package).filter_by(name='annakarenina_changed').one() package_dictized = package_dictize(pkg, context) resources_revisions = model.Session.query( model.ResourceRevision).filter_by(package_id=anna1.id).all() sorted_resource_revisions = sorted(resources_revisions, key=lambda x: (x.revision_timestamp, x.url))[::-1] for res in sorted_resource_revisions: print res.id, res.revision_timestamp, res.state assert len(sorted_resource_revisions) == 3 # Make sure we remove changeable fields BEFORE we store the pretty-printed version # for comparison clean_package_dictized = self.remove_changable_columns( package_dictized) anna_original = pformat(anna_dictized) anna_after_save = pformat(clean_package_dictized) assert self.remove_changable_columns(anna_dictized) == clean_package_dictized, \ "\n".join(unified_diff(anna_original.split("\n"), anna_after_save.split("\n"))) # changes to the package, relied upon by later tests anna1 = model.Session.query( model.Package).filter_by(name='annakarenina_changed').one() anna_dictized = package_dictize(anna1, context) anna_dictized['name'] = u'annakarenina_changed2' anna_dictized['resources'][0]['url'] = u'http://new_url2' anna_dictized['tags'][0]['name'] = u'new_tag' anna_dictized['tags'][0].pop('id') #test if anna_dictized['extras'][0]['value'] = u'new_value' model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() anna1 = model.Session.query( model.Package).filter_by(name='annakarenina_changed2').one() anna_dictized = package_dictize(anna1, context) anna_dictized['notes'] = 'wee' anna_dictized['resources'].append({ 'format': u'plain text', 'url': u'http://newurl' }) anna_dictized['tags'].append({'name': u'newnew_tag'}) anna_dictized['extras'].append({'key': 'david', 'value': u'new_value'}) model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove()
def test_15_api_to_dictize(self): context = {"model": model, 'api_version': 1, "session": model.Session} api_data = { 'name' : u'testpkg', 'title': u'Some Title', 'url': u'http://blahblahblah.mydomain', 'resources': [ { u'url':u'http://blah.com/file2.xml', u'format':u'xml', u'description':u'Second file', u'hash':u'def123', u'alt_url':u'alt_url', u'size':u'200', }, { u'url':u'http://blah.com/file.xml', u'format':u'xml', u'description':u'Main file', u'hash':u'abc123', u'alt_url':u'alt_url', u'size':u'200', }, ], 'tags': u'russion novel', 'license_id': u'gpl-3.0', 'extras': { 'genre' : u'horror', 'media' : u'dvd', }, } dictized = package_api_to_dict(api_data, context) assert dictized == {'extras': [{'key': 'genre', 'value': u'"horror"'}, {'key': 'media', 'value': u'"dvd"'}], 'license_id': u'gpl-3.0', 'name': u'testpkg', 'resources': [{u'alt_url': u'alt_url', u'description': u'Second file', u'size': u'200', u'format': u'xml', u'hash': u'def123', u'url': u'http://blah.com/file2.xml'}, {u'alt_url': u'alt_url', u'description': u'Main file', u'size': u'200', u'format': u'xml', u'hash': u'abc123', u'url': u'http://blah.com/file.xml'}], 'tags': [{'name': u'russion'}, {'name': u'novel'}], 'title': u'Some Title', 'url': u'http://blahblahblah.mydomain'} model.repo.new_revision() package_dict_save(dictized, context) model.Session.commit() model.Session.remove() pkg = model.Session.query(model.Package).filter_by(name=u'testpkg').one() package_dictized = self.remove_changable_columns(package_dictize(pkg, context))
def test_15_api_to_dictize(self): context = {"model": model, 'api_version': 1, "session": model.Session} api_data = { 'name' : u'testpkg', 'title': u'Some Title', 'url': u'http://blahblahblah.mydomain', 'resources': [ { u'url':u'http://blah.com/file2.xml', u'format':u'xml', u'description':u'Second file', u'hash':u'def123', u'alt_url':u'alt_url', u'size':u'200', }, { u'url':u'http://blah.com/file.xml', u'format':u'xml', u'description':u'Main file', u'hash':u'abc123', u'alt_url':u'alt_url', u'size':u'200', }, ], 'tags': u'russion novel', 'license_id': u'gpl-3.0', 'extras': { 'genre' : u'horror', 'media' : u'dvd', }, } dictized = package_api_to_dict(api_data, context) assert dictized == {'extras': [{'key': 'genre', 'value': u'horror'}, {'key': 'media', 'value': u'dvd'}], 'license_id': u'gpl-3.0', 'name': u'testpkg', 'resources': [{u'alt_url': u'alt_url', u'description': u'Second file', u'size': u'200', u'format': u'xml', u'hash': u'def123', u'url': u'http://blah.com/file2.xml'}, {u'alt_url': u'alt_url', u'description': u'Main file', u'size': u'200', u'format': u'xml', u'hash': u'abc123', u'url': u'http://blah.com/file.xml'}], 'tags': [{'name': u'russion'}, {'name': u'novel'}], 'title': u'Some Title', 'url': u'http://blahblahblah.mydomain'} model.repo.new_revision() package_dict_save(dictized, context) model.Session.commit() model.Session.remove() pkg = model.Session.query(model.Package).filter_by(name=u'testpkg').one() package_dictized = self.remove_changable_columns(package_dictize(pkg, context))
def test_15_api_to_dictize(self): context = {"model": model, "api_version": 1, "session": model.Session} api_data = { "name": u"testpkg", "title": u"Some Title", "url": u"http://blahblahblah.mydomain", "resources": [ { u"url": u"http://blah.com/file2.xml", u"format": u"xml", u"description": u"Second file", u"hash": u"def123", u"alt_url": u"alt_url", u"size": u"200", }, { u"url": u"http://blah.com/file.xml", u"format": u"xml", u"description": u"Main file", u"hash": u"abc123", u"alt_url": u"alt_url", u"size": u"200", }, ], "tags": u"russion novel", "license_id": u"gpl-3.0", "extras": {"genre": u"horror", "media": u"dvd"}, } dictized = package_api_to_dict(api_data, context) assert dictized == { "extras": [{"key": "genre", "value": u"horror"}, {"key": "media", "value": u"dvd"}], "license_id": u"gpl-3.0", "name": u"testpkg", "resources": [ { u"alt_url": u"alt_url", u"description": u"Second file", u"size": u"200", u"format": u"xml", u"hash": u"def123", u"url": u"http://blah.com/file2.xml", }, { u"alt_url": u"alt_url", u"description": u"Main file", u"size": u"200", u"format": u"xml", u"hash": u"abc123", u"url": u"http://blah.com/file.xml", }, ], "tags": [{"name": u"russion"}, {"name": u"novel"}], "title": u"Some Title", "url": u"http://blahblahblah.mydomain", } model.repo.new_revision() package_dict_save(dictized, context) model.Session.commit() model.Session.remove() pkg = model.Session.query(model.Package).filter_by(name=u"testpkg").one() package_dictized = self.remove_changable_columns(package_dictize(pkg, context))
def package_update(context, data_dict): '''Update a dataset (package). You must be authorized to edit the dataset and the groups that it belongs to. Plugins may change the parameters of this function depending on the value of the dataset's ``type`` attribute, see the ``IDatasetForm`` plugin interface. For further parameters see ``package_create()``. :param id: the name or id of the dataset to update :type id: string :returns: the updated dataset (if 'return_package_dict' is True in the context, which is the default. Otherwise returns just the dataset id) :rtype: dictionary ''' log.info('context: %s', context) model = context['model'] user = context['user'] name_or_id = data_dict.get("id") or data_dict['name'] log.info('package update: %s', data_dict) pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg data_dict["id"] = pkg.id pkg_dict = _get_action("package_show")(context, {'id': pkg.id}) pkg_dict.update(data_dict) _check_access('package_update', context, data_dict) _get_action('notify_package_update')(context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.update_package_schema() if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: package_plugin.check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work. package_plugin.check_data_dict(data_dict) #we cannot modify model but we can ensure no modification via GUI/API delete_keys = ['author_email', 'maintainer', 'maintainer_email'] for key in delete_keys: if key in pkg_dict: del pkg_dict[key] data, errors = _validate(pkg_dict, schema, context) log.debug('package_update validate_errs=%r user=%s package=%s', errors, context.get('user'), context.get('package').name if context.get('package') else '') if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") #avoid revisioning by updating directly model.Session.query(model.Package).filter_by(id=pkg.id).update( {"metadata_modified": datetime.datetime.utcnow()}) model.Session.refresh(pkg) pkg = model_save.package_dict_save(data, context) context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True _get_action('package_owner_org_update')(context_org_update, { 'id': pkg.id, 'organization_id': pkg.owner_org }) for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) item.after_update(context, data) if not context.get('defer_commit'): model.repo.commit() log.debug('Updated object %s' % pkg.name) return_id_only = context.get('return_id_only', False) # Make sure that a user provided schema is not used on package_show context.pop('schema', None) # we could update the dataset so we should still be able to read it. context['ignore_auth'] = True output = data_dict['id'] if return_id_only \ else _get_action('package_show')(context, {'id': data_dict['id']}) #action will be audited in resource_create or resource_update action if not context.get('defer_audit', None): audit_helper(data_dict, output, 'package_update') _get_action('package_unlock')(context, {'id': pkg.id}) return output
def package_update(context, data_dict): '''Update a dataset (package). You must be authorized to edit the dataset and the groups that it belongs to. Plugins may change the parameters of this function depending on the value of the dataset's ``type`` attribute, see the ``IDatasetForm`` plugin interface. For further parameters see ``package_create()``. :param id: the name or id of the dataset to update :type id: string :returns: the updated dataset :rtype: dictionary ''' model = context['model'] user = context['user'] name_or_id = data_dict.get("id") or data_dict['name'] model.Session.remove() model.Session()._context = context pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg data_dict["id"] = pkg.id _check_access('package_update', context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) try: schema = package_plugin.form_to_db_schema_options({'type':'update', 'api':'api_version' in context, 'context': context}) except AttributeError: schema = package_plugin.form_to_db_schema() if 'api_version' not in context: # old plugins do not support passing the schema so we need # to ensure they still work try: package_plugin.check_data_dict(data_dict, schema) except TypeError: package_plugin.check_data_dict(data_dict) data, errors = _validate(data_dict, schema, context) if errors: model.Session.rollback() raise ValidationError(errors, _error_summary(errors)) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") pkg = model_save.package_dict_save(data, context) for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) if not context.get('defer_commit'): model.repo.commit() return _get_action('package_show')(context, data_dict)
def package_create(context, data_dict): '''Create a new dataset (package). You must be authorized to create new datasets. If you specify any groups for the new dataset, you must also be authorized to edit these groups. Plugins may change the parameters of this function depending on the value of the ``type`` parameter, see the ``IDatasetForm`` plugin interface. :param name: the name of the new dataset, must be between 2 and 100 characters long and contain only lowercase alphanumeric characters, ``-`` and ``_``, e.g. ``'warandpeace'`` :type name: string :param title: the title of the dataset (optional, default: same as ``name``) :type title: string :param author: the name of the dataset's author (optional) :type author: string :param author_email: the email address of the dataset's author (optional) :type author_email: string :param maintainer: the name of the dataset's maintainer (optional) :type maintainer: string :param maintainer_email: the email address of the dataset's maintainer (optional) :type maintainer_email: string :param license_id: the id of the dataset's license, see ``license_list()`` for available values (optional) :type license_id: license id string :param notes: a description of the dataset (optional) :type notes: string :param url: a URL for the dataset's source (optional) :type url: string :param version: (optional) :type version: string, no longer than 100 characters :param state: the current state of the dataset, e.g. ``'active'`` or ``'deleted'``, only active datasets show up in search results and other lists of datasets, this parameter will be ignored if you are not authorized to change the state of the dataset (optional, default: ``'active'``) :type state: string :param type: the type of the dataset (optional), ``IDatasetForm`` plugins associate themselves with different dataset types and provide custom dataset handling behaviour for these types :type type: string :param resources: the dataset's resources, see ``resource_create()`` for the format of resource dictionaries (optional) :type resources: list of resource dictionaries :param tags: the dataset's tags, see ``tag_create()`` for the format of tag dictionaries (optional) :type tags: list of tag dictionaries :param extras: the dataset's extras (optional), extras are arbitrary (key: value) metadata items that can be added to datasets, each extra dictionary should have keys ``'key'`` (a string), ``'value'`` (a string), and optionally ``'deleted'`` :type extras: list of dataset extra dictionaries :param relationships_as_object: see ``package_relationship_create()`` for the format of relationship dictionaries (optional) :type relationships_as_object: list of relationship dictionaries :param relationships_as_subject: see ``package_relationship_create()`` for the format of relationship dictionaries (optional) :type relationships_as_subject: list of relationship dictionaries :param groups: the groups to which the dataset belongs (optional), each group dictionary should have one or more of the following keys which identify an existing group: ``'id'`` (the id of the group, string), ``'name'`` (the name of the group, string), ``'title'`` (the title of the group, string), to see which groups exist call ``group_list()`` :type groups: list of dictionaries :returns: the newly created dataset (unless 'return_id_only' is set to True in the context, in which case just the dataset id will be returned) :rtype: dictionary ''' model = context['model'] user = context['user'] package_type = data_dict.get('type') package_plugin = lib_plugins.lookup_package_plugin(package_type) try: schema = package_plugin.form_to_db_schema_options({'type':'create', 'api':'api_version' in context, 'context': context}) except AttributeError: schema = package_plugin.form_to_db_schema() _check_access('package_create', context, data_dict) if 'api_version' not in context: # old plugins do not support passing the schema so we need # to ensure they still work try: package_plugin.check_data_dict(data_dict, schema) except TypeError: package_plugin.check_data_dict(data_dict) data, errors = _validate(data_dict, schema, context) log.debug('package_create validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), data.get('name'), data_dict) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Create object %s') % data.get("name") pkg = model_save.package_dict_save(data, context) admins = [] if user: admins = [model.User.by_name(user.decode('utf8'))] model.setup_default_user_roles(pkg, admins) # Needed to let extensions know the package id model.Session.flush() data['id'] = pkg.id context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True _get_action('package_owner_org_update')(context_org_update, {'id': pkg.id, 'organization_id': pkg.owner_org}) for item in plugins.PluginImplementations(plugins.IPackageController): item.create(pkg) item.after_create(context, data) if not context.get('defer_commit'): model.repo.commit() ## need to let rest api create context["package"] = pkg ## this is added so that the rest controller can make a new location context["id"] = pkg.id log.debug('Created object %s' % str(pkg.name)) return_id_only = context.get('return_id_only', False) output = context['id'] if return_id_only \ else _get_action('package_show')(context, {'id':context['id']}) return output
def package_create(context, data_dict): """Create a new dataset (package). You must be authorized to create new datasets. If you specify any groups for the new dataset, you must also be authorized to edit these groups. Plugins may change the parameters of this function depending on the value of the ``type`` parameter, see the ``IDatasetForm`` plugin interface. :param name: the name of the new dataset, must be between 2 and 100 characters long and contain only lowercase alphanumeric characters, ``-`` and ``_``, e.g. ``'warandpeace'`` :type name: string :param title: the title of the dataset (optional, default: same as ``name``) :type title: string :param author: the name of the dataset's author (optional) :type author: string :param author_email: the email address of the dataset's author (optional) :type author_email: string :param maintainer: the name of the dataset's maintainer (optional) :type maintainer: string :param maintainer_email: the email address of the dataset's maintainer (optional) :type maintainer_email: string :param license_id: the id of the dataset's license, see ``license_list()`` for available values (optional) :type license_id: license id string :param notes: a description of the dataset (optional) :type notes: string :param url: a URL for the dataset's source (optional) :type url: string :param version: (optional) :type version: string, no longer than 100 characters :param state: the current state of the dataset, e.g. ``'active'`` or ``'deleted'``, only active datasets show up in search results and other lists of datasets, this parameter will be ignored if you are not authorized to change the state of the dataset (optional, default: ``'active'``) :type state: string :param type: the type of the dataset (optional), ``IDatasetForm`` plugins associate themselves with different dataset types and provide custom dataset handling behaviour for these types :type type: string :param resources: the dataset's resources, see ``resource_create()`` for the format of resource dictionaries (optional) :type resources: list of resource dictionaries :param tags: the dataset's tags, see ``tag_create()`` for the format of tag dictionaries (optional) :type tags: list of tag dictionaries :param extras: the dataset's extras (optional), extras are arbitrary (key: value) metadata items that can be added to datasets, each extra dictionary should have keys ``'key'`` (a string), ``'value'`` (a string) :type extras: list of dataset extra dictionaries :param relationships_as_object: see ``package_relationship_create()`` for the format of relationship dictionaries (optional) :type relationships_as_object: list of relationship dictionaries :param relationships_as_subject: see ``package_relationship_create()`` for the format of relationship dictionaries (optional) :type relationships_as_subject: list of relationship dictionaries :param groups: the groups to which the dataset belongs (optional), each group dictionary should have one or more of the following keys which identify an existing group: ``'id'`` (the id of the group, string), ``'name'`` (the name of the group, string), ``'title'`` (the title of the group, string), to see which groups exist call ``group_list()`` :type groups: list of dictionaries :param owner_org: the id of the dataset's owning organization, see ``organization_list()`` or ``organization_list_for_user`` for available values (optional) :type owner_org: string :returns: the newly created dataset (unless 'return_id_only' is set to True in the context, in which case just the dataset id will be returned) :rtype: dictionary """ model = context["model"] user = context["user"] package_type = data_dict.get("type") package_plugin = lib_plugins.lookup_package_plugin(package_type) if "schema" in context: schema = context["schema"] else: schema = package_plugin.create_package_schema() _check_access("package_create", context, data_dict) if "api_version" not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, "check_data_dict", None) if check_data_dict: try: check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work package_plugin.check_data_dict(data_dict) data, errors = _validate(data_dict, schema, context) if "tags" in data: data["tags"] = get_tag_vocabulary(data["tags"]) if "groups" in data: data["extras"].append({"key": "solr_additions", "value": build_additions(data["groups"])}) log.debug( "package_create validate_errs=%r user=%s package=%s data=%r", errors, context.get("user"), data.get("name"), data_dict, ) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if "message" in context: rev.message = context["message"] else: rev.message = _(u"REST API: Create object %s") % data.get("name") admins = [] if user: user_obj = model.User.by_name(user.decode("utf8")) if user_obj: admins = [user_obj] data["creator_user_id"] = user_obj.id pkg = model_save.package_dict_save(data, context) model.setup_default_user_roles(pkg, admins) # Needed to let extensions know the package id model.Session.flush() data["id"] = pkg.id context_org_update = context.copy() context_org_update["ignore_auth"] = True context_org_update["defer_commit"] = True _get_action("package_owner_org_update")(context_org_update, {"id": pkg.id, "organization_id": pkg.owner_org}) for item in plugins.PluginImplementations(plugins.IPackageController): item.create(pkg) item.after_create(context, data) if not context.get("defer_commit"): model.repo.commit() # need to let rest api create context["package"] = pkg # this is added so that the rest controller can make a new location context["id"] = pkg.id log.debug("Created object %s" % pkg.name) # Make sure that a user provided schema is not used on package_show context.pop("schema", None) return_id_only = context.get("return_id_only", False) output = context["id"] if return_id_only else _get_action("package_show")(context, {"id": context["id"]}) return output
def package_update(context, data_dict): """Update a dataset (package). You must be authorized to edit the dataset and the groups that it belongs to. Plugins may change the parameters of this function depending on the value of the dataset's ``type`` attribute, see the ``IDatasetForm`` plugin interface. For further parameters see ``package_create()``. :param id: the name or id of the dataset to update :type id: string :returns: the updated dataset (if 'return_package_dict' is True in the context, which is the default. Otherwise returns just the dataset id) :rtype: dictionary """ model = context["model"] user = context["user"] name_or_id = data_dict.get("id") or data_dict["name"] pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_("Package was not found.")) context["package"] = pkg data_dict["id"] = pkg.id _check_access("package_update", context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) try: schema = package_plugin.form_to_db_schema_options( {"type": "update", "api": "api_version" in context, "context": context} ) except AttributeError: schema = package_plugin.form_to_db_schema() if "api_version" not in context: # old plugins do not support passing the schema so we need # to ensure they still work try: package_plugin.check_data_dict(data_dict, schema) except TypeError: package_plugin.check_data_dict(data_dict) data, errors = _validate(data_dict, schema, context) log.debug( "package_update validate_errs=%r user=%s package=%s data=%r", errors, context.get("user"), context.get("package").name if context.get("package") else "", data, ) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if "message" in context: rev.message = context["message"] else: rev.message = _(u"REST API: Update object %s") % data.get("name") pkg = model_save.package_dict_save(data, context) context_no_auth = context.copy() context_no_auth["ignore_auth"] = True _get_action("package_owner_org_update")(context_no_auth, {"id": pkg.id, "organization_id": pkg.owner_org}) for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) if not context.get("defer_commit"): model.repo.commit() log.debug("Updated object %s" % str(pkg.name)) return_id_only = context.get("return_id_only", False) output = data_dict["id"] if return_id_only else _get_action("package_show")(context, {"id": data_dict["id"]}) return output
def package_create(context, data_dict): '''Create a new dataset (package). You must be authorized to create new datasets. If you specify any groups for the new dataset, you must also be authorized to edit these groups. Plugins may change the parameters of this function depending on the value of the ``type`` parameter, see the ``IDatasetForm`` plugin interface. :param name: the name of the new dataset, must be between 2 and 100 characters long and contain only lowercase alphanumeric characters, ``-`` and ``_``, e.g. ``'warandpeace'`` :type name: string :param title: the title of the dataset (optional, default: same as ``name``) :type title: string :param author: the name of the dataset's author (optional) :type author: string :param author_email: the email address of the dataset's author (optional) :type author_email: string :param maintainer: the name of the dataset's maintainer (optional) :type maintainer: string :param maintainer_email: the email address of the dataset's maintainer (optional) :type maintainer_email: string :param license_id: the id of the dataset's license, see ``license_list()`` for available values (optional) :type license_id: license id string :param notes: a description of the dataset (optional) :type notes: string :param url: a URL for the dataset's source (optional) :type url: string :param version: (optional) :type version: string, no longer than 100 characters :param state: the current state of the dataset, e.g. ``'active'`` or ``'deleted'``, only active datasets show up in search results and other lists of datasets, this parameter will be ignored if you are not authorized to change the state of the dataset (optional, default: ``'active'``) :type state: string :param type: the type of the dataset (optional), ``IDatasetForm`` plugins associate themselves with different dataset types and provide custom dataset handling behaviour for these types :type type: string :param resources: the dataset's resources, see ``resource_create()`` for the format of resource dictionaries (optional) :type resources: list of resource dictionaries :param tags: the dataset's tags, see ``tag_create()`` for the format of tag dictionaries (optional) :type tags: list of tag dictionaries :param extras: the dataset's extras (optional), extras are arbitrary (key: value) metadata items that can be added to datasets, each extra dictionary should have keys ``'key'`` (a string), ``'value'`` (a string) :type extras: list of dataset extra dictionaries :param relationships_as_object: see ``package_relationship_create()`` for the format of relationship dictionaries (optional) :type relationships_as_object: list of relationship dictionaries :param relationships_as_subject: see ``package_relationship_create()`` for the format of relationship dictionaries (optional) :type relationships_as_subject: list of relationship dictionaries :param groups: the groups to which the dataset belongs (optional), each group dictionary should have one or more of the following keys which identify an existing group: ``'id'`` (the id of the group, string), ``'name'`` (the name of the group, string), ``'title'`` (the title of the group, string), to see which groups exist call ``group_list()`` :type groups: list of dictionaries :param owner_org: the id of the dataset's owning organization, see ``organization_list()`` or ``organization_list_for_user`` for available values (optional) :type owner_org: string :returns: the newly created dataset (unless 'return_id_only' is set to True in the context, in which case just the dataset id will be returned) :rtype: dictionary ''' model = context['model'] user = context['user'] log.info('context: %s', context) package_type = data_dict.get('type') package_plugin = lib_plugins.lookup_package_plugin(package_type) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.create_package_schema() _check_access('package_create', context, data_dict) if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work package_plugin.check_data_dict(data_dict) #we cannot modify model but we can ensure no modification via GUI/API delete_keys = ['author_email', 'maintainer', 'maintainer_email'] for key in delete_keys: if key in data_dict: del data_dict[key] data, errors = _validate(data_dict, schema, context) log.debug('package_create validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), data.get('name'), data_dict) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Create object %s') % data.get("name") admins = [] if user: user_obj = model.User.by_name(user.decode('utf8')) if user_obj: admins = [user_obj] data['creator_user_id'] = user_obj.id pkg = model_save.package_dict_save(data, context) model.setup_default_user_roles(pkg, admins) # Needed to let extensions know the package id model.Session.flush() data['id'] = pkg.id context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True _get_action('package_owner_org_update')(context_org_update, { 'id': pkg.id, 'organization_id': pkg.owner_org }) for item in plugins.PluginImplementations(plugins.IPackageController): item.create(pkg) item.after_create(context, data) if not context.get('defer_commit'): model.repo.commit() ## need to let rest api create context["package"] = pkg ## this is added so that the rest controller can make a new location context["id"] = pkg.id log.debug('Created object %s' % pkg.name) # Make sure that a user provided schema is not used on package_show context.pop('schema', None) return_id_only = context.get('return_id_only', False) output = context['id'] if return_id_only \ else _get_action('package_show')(context, {'id':context['id']}) _get_action('notify_package_create')(context, data_dict) audit_helper(data_dict, output, 'package_create') return output
def package_create(context, data_dict): '''Create a new dataset (package). You must be authorized to create new datasets. If you specify any groups for the new dataset, you must also be authorized to edit these groups. Plugins may change the parameters of this function depending on the value of the ``type`` parameter, see the :py:class:`~ckan.plugins.interfaces.IDatasetForm` plugin interface. :param name: the name of the new dataset, must be between 2 and 100 characters long and contain only lowercase alphanumeric characters, ``-`` and ``_``, e.g. ``'warandpeace'`` :type name: string :param title: the title of the dataset (optional, default: same as ``name``) :type title: string :param author: the name of the dataset's author (optional) :type author: string :param author_email: the email address of the dataset's author (optional) :type author_email: string :param maintainer: the name of the dataset's maintainer (optional) :type maintainer: string :param maintainer_email: the email address of the dataset's maintainer (optional) :type maintainer_email: string :param license_id: the id of the dataset's license, see :py:func:`~ckan.logic.action.get.license_list` for available values (optional) :type license_id: license id string :param notes: a description of the dataset (optional) :type notes: string :param url: a URL for the dataset's source (optional) :type url: string :param version: (optional) :type version: string, no longer than 100 characters :param state: the current state of the dataset, e.g. ``'active'`` or ``'deleted'``, only active datasets show up in search results and other lists of datasets, this parameter will be ignored if you are not authorized to change the state of the dataset (optional, default: ``'active'``) :type state: string :param type: the type of the dataset (optional), :py:class:`~ckan.plugins.interfaces.IDatasetForm` plugins associate themselves with different dataset types and provide custom dataset handling behaviour for these types :type type: string :param resources: the dataset's resources, see :py:func:`resource_create` for the format of resource dictionaries (optional) :type resources: list of resource dictionaries :param tags: the dataset's tags, see :py:func:`tag_create` for the format of tag dictionaries (optional) :type tags: list of tag dictionaries :param extras: the dataset's extras (optional), extras are arbitrary (key: value) metadata items that can be added to datasets, each extra dictionary should have keys ``'key'`` (a string), ``'value'`` (a string) :type extras: list of dataset extra dictionaries :param relationships_as_object: see :py:func:`package_relationship_create` for the format of relationship dictionaries (optional) :type relationships_as_object: list of relationship dictionaries :param relationships_as_subject: see :py:func:`package_relationship_create` for the format of relationship dictionaries (optional) :type relationships_as_subject: list of relationship dictionaries :param groups: the groups to which the dataset belongs (optional), each group dictionary should have one or more of the following keys which identify an existing group: ``'id'`` (the id of the group, string), or ``'name'`` (the name of the group, string), to see which groups exist call :py:func:`~ckan.logic.action.get.group_list` :type groups: list of dictionaries :param owner_org: the id of the dataset's owning organization, see :py:func:`~ckan.logic.action.get.organization_list` or :py:func:`~ckan.logic.action.get.organization_list_for_user` for available values (optional) :type owner_org: string :returns: the newly created dataset (unless 'return_id_only' is set to True in the context, in which case just the dataset id will be returned) :rtype: dictionary ''' model = context['model'] user = context['user'] if 'type' not in data_dict: package_plugin = lib_plugins.lookup_package_plugin() try: # use first type as default if user didn't provide type package_type = package_plugin.package_types()[0] except (AttributeError, IndexError): package_type = 'dataset' # in case a 'dataset' plugin was registered w/o fallback package_plugin = lib_plugins.lookup_package_plugin(package_type) data_dict['type'] = package_type else: package_plugin = lib_plugins.lookup_package_plugin(data_dict['type']) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.create_package_schema() _check_access('package_create', context, data_dict) if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work package_plugin.check_data_dict(data_dict) data, errors = lib_plugins.plugin_validate( package_plugin, context, data_dict, schema, 'package_create') log.debug('package_create validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), data.get('name'), data_dict) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Create object %s') % data.get("name") admins = [] if user: user_obj = model.User.by_name(user.decode('utf8')) if user_obj: admins = [user_obj] data['creator_user_id'] = user_obj.id pkg = model_save.package_dict_save(data, context) model.setup_default_user_roles(pkg, admins) # Needed to let extensions know the package and resources ids model.Session.flush() data['id'] = pkg.id if data.get('resources'): for index, resource in enumerate(data['resources']): resource['id'] = pkg.resources[index].id context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True _get_action('package_owner_org_update')(context_org_update, {'id': pkg.id, 'organization_id': pkg.owner_org}) for item in plugins.PluginImplementations(plugins.IPackageController): item.create(pkg) item.after_create(context, data) # Create default views for resources if necessary if data.get('resources'): ckan.lib.datapreview.add_default_views_to_dataset_resources(context, data) if not context.get('defer_commit'): model.repo.commit() ## need to let rest api create context["package"] = pkg ## this is added so that the rest controller can make a new location context["id"] = pkg.id log.debug('Created object %s' % pkg.name) # Make sure that a user provided schema is not used on package_show context.pop('schema', None) return_id_only = context.get('return_id_only', False) output = context['id'] if return_id_only \ else _get_action('package_show')(context, {'id': context['id']}) return output
def rdf_package_update(context, data_dict): model = context['model'] user = context['user'] name_or_id = data_dict.get("id") or data_dict['name'] pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg data_dict["id"] = pkg.id data_dict['type'] = pkg.type # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.update_package_schema() schema.update({ 'load_rdf_job_identifier': [toolkit.get_validator('ignore_missing'), toolkit.get_converter('convert_to_extras')] }) schema.update({ 'load_rdf_job_start': [toolkit.get_validator('ignore_missing'), toolkit.get_converter('convert_to_extras')] }) if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: package_plugin.check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work. package_plugin.check_data_dict(data_dict) data, errors = lib_plugins.plugin_validate( package_plugin, context, data_dict, schema, 'package_update') rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") #avoid revisioning by updating directly model.Session.query(model.Package).filter_by(id=pkg.id).update( {"metadata_modified": datetime.datetime.utcnow()}) model.Session.refresh(pkg) pkg = model_save.package_dict_save(data, context) context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True get_action('package_owner_org_update')(context_org_update, {'id': pkg.id, 'organization_id': pkg.owner_org}) # Needed to let extensions know the new resources ids model.Session.flush() if data.get('resources'): for index, resource in enumerate(data['resources']): resource['id'] = pkg.resources[index].id for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) item.after_update(context, data) # Create default views for resources if necessary if data.get('resources'): logic.get_action('package_create_default_resource_views')( {'model': context['model'], 'user': context['user'], 'ignore_auth': True}, {'package': data}) if not context.get('defer_commit'): model.repo.commit() return_id_only = context.get('return_id_only', False) # Make sure that a user provided schema is not used on package_show context.pop('schema', None) # we could update the dataset so we should still be able to read it. context['ignore_auth'] = True output = data_dict['id'] if return_id_only \ else get_action('package_show')(context, {'id': data_dict['id']}) return output
def package_update(context, data_dict): '''Update a dataset (package). You must be authorized to edit the dataset and the groups that it belongs to. Plugins may change the parameters of this function depending on the value of the dataset's ``type`` attribute, see the ``IDatasetForm`` plugin interface. For further parameters see ``package_create()``. :param id: the name or id of the dataset to update :type id: string :returns: the updated dataset (if 'return_package_dict' is True in the context, which is the default. Otherwise returns just the dataset id) :rtype: dictionary ''' model = context['model'] user = context['user'] name_or_id = data_dict.get("id") or data_dict['name'] pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg data_dict["id"] = pkg.id # FIXME: first modifications to package_updade begin here: # tag strings are reconstructed because validators are stripping # tags passed and only taking taks as tag_string values # image upload support has also been added here old_data = get_action('package_show')(context, {'id': pkg.id}) ''' Constructing the tag_string from the given tags. There must be at least one tag, otherwise the tag_string will be empty and a validation error will be raised. ''' if not data_dict.get('tag_string'): data_dict['tag_string'] = ', '.join( h.dict_list_reduce(data_dict.get('tags', {}), 'name')) for key, value in old_data.iteritems() : if key not in data_dict : data_dict[key] = value #data_dict['resources'] = data_dict.get('resources', old_data.get('resources')) # iso_topic_cat = data_dict.get('iso_topic_string', []) # if isinstance(iso_topic_cat, basestring): # iso_topic_cat = [iso_topic_cat] # # data_dict['iso_topic_string'] = ','.join(iso_topic_cat) #Set the package last modified date data_dict['record_last_modified'] = str(datetime.date.today()) # If the Created Date has not yet been set, then set it if data_dict['edc_state'] == 'DRAFT' and not data_dict.get('record_create_date'): data_dict['record_create_date'] = str(datetime.date.today()) # If the Publish Date has not yet been set, then set it if data_dict['edc_state'] == 'PUBLISHED' and not data_dict.get('record_publish_date'): data_dict['record_publish_date'] = str(datetime.date.today()) # If the Archive Date has not yet been set, then set it if data_dict['edc_state'] == 'ARCHIVED' and not data_dict.get('record_archive_date'): data_dict['record_archive_date'] = str(datetime.date.today()) _check_access('package_update', context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.update_package_schema() image_url = old_data.get('image_url', None) upload = uploader.Upload('edc', image_url) upload.update_data_dict(data_dict, 'image_url', 'image_upload', 'clear_upload') #Adding image display url for the uploaded image image_url = data_dict.get('image_url') data_dict['image_display_url'] = image_url if image_url and not image_url.startswith('http'): image_url = munge.munge_filename(image_url) data_dict['image_display_url'] = h.url_for_static('uploads/edc/%s' % data_dict.get('image_url'), qualified=True) if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: package_plugin.check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work. package_plugin.check_data_dict(data_dict) # FIXME: modifications to package_update end here^ data, errors = _validate(data_dict, schema, context) # log.debug('package_update validate_errs=%r user=%s package=%s data=%r', # errors, context.get('user'), # context.get('package').name if context.get('package') else '', # data) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") #avoid revisioning by updating directly model.Session.query(model.Package).filter_by(id=pkg.id).update( {"metadata_modified": datetime.datetime.utcnow()}) model.Session.refresh(pkg) pkg = model_save.package_dict_save(data, context) context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True _get_action('package_owner_org_update')(context_org_update, {'id': pkg.id, 'organization_id': pkg.owner_org}) for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) item.after_update(context, data) upload.upload(uploader.get_max_image_size()) #TODO the next two blocks are copied from ckan/ckan/logic/action/update.py # This codebase is currently hard to maintain because large chunks of the # CKAN action API and the CKAN controllers are simply overriden. This is # probably worse than just forking CKAN would have been, because in that # case at least we could track changes. - @deniszgonjanin # Needed to let extensions know the new resources ids model.Session.flush() if data.get('resources'): for index, resource in enumerate(data['resources']): resource['id'] = pkg.resources[index].id # Create default views for resources if necessary if data.get('resources'): logic.get_action('package_create_default_resource_views')( {'model': context['model'], 'user': context['user'], 'ignore_auth': True}, {'package': data}) if not context.get('defer_commit'): model.repo.commit() log.debug('Updated object %s' % pkg.name) return_id_only = context.get('return_id_only', False) # Make sure that a user provided schema is not used on package_show context.pop('schema', None) # we could update the dataset so we should still be able to read it. context['ignore_auth'] = True output = data_dict['id'] if return_id_only \ else _get_action('package_show')(context, {'id': data_dict['id']}) ''' Send state change notifications if required; Added by Khalegh Mamakani Using a thread to run the job in the background so that package_update will not wait for notifications sending. ''' old_state = old_data.get('edc_state') context = {'model': model, 'session': model.Session, 'user': c.user or c.author, 'auth_user_obj': c.userobj} dataset_url = config.get('ckan.site_url') + h.url_for(controller='package', action="read", id = data_dict['name']) import threading notify_thread = threading.Thread(target=check_record_state, args=(context, old_state, data_dict, g.site_title, g.site_url, dataset_url) ) notify_thread.start() return output
def package_update(context, data_dict): '''Update a dataset (package). You must be authorized to edit the dataset and the groups that it belongs to. Plugins may change the parameters of this function depending on the value of the dataset's ``type`` attribute, see the ``IDatasetForm`` plugin interface. For further parameters see ``package_create()``. :param id: the name or id of the dataset to update :type id: string :returns: the updated dataset (if 'return_package_dict' is True in the context, which is the default. Otherwise returns just the dataset id) :rtype: dictionary ''' model = context['model'] user = context['user'] name_or_id = data_dict.get("id") or data_dict['name'] pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg data_dict["id"] = pkg.id _check_access('package_update', context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.update_package_schema() if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: package_plugin.check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work. package_plugin.check_data_dict(data_dict) data, errors = lib_plugins.plugin_validate( package_plugin, context, data_dict, schema, 'package_update') log.debug('package_update validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), context.get('package').name if context.get('package') else '', data) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") #avoid revisioning by updating directly model.Session.query(model.Package).filter_by(id=pkg.id).update( {"metadata_modified": datetime.datetime.utcnow()}) model.Session.refresh(pkg) pkg = model_save.package_dict_save(data, context) context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True _get_action('package_owner_org_update')(context_org_update, {'id': pkg.id, 'organization_id': pkg.owner_org}) for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) item.after_update(context, data) if not context.get('defer_commit'): model.repo.commit() log.debug('Updated object %s' % pkg.name) return_id_only = context.get('return_id_only', False) # Make sure that a user provided schema is not used on package_show context.pop('schema', None) # we could update the dataset so we should still be able to read it. context['ignore_auth'] = True output = data_dict['id'] if return_id_only \ else _get_action('package_show')(context, {'id': data_dict['id']}) return output
def package_update(context, data_dict): '''Update a dataset (package). You must be authorized to edit the dataset and the groups that it belongs to. .. note:: Update methods may delete parameters not explicitly provided in the data_dict. If you want to edit only a specific attribute use `package_patch` instead. It is recommended to call :py:func:`ckan.logic.action.get.package_show`, make the desired changes to the result, and then call ``package_update()`` with it. Plugins may change the parameters of this function depending on the value of the dataset's ``type`` attribute, see the :py:class:`~ckan.plugins.interfaces.IDatasetForm` plugin interface. For further parameters see :py:func:`~ckan.logic.action.create.package_create`. :param id: the name or id of the dataset to update :type id: string :returns: the updated dataset (if ``'return_package_dict'`` is ``True`` in the context, which is the default. Otherwise returns just the dataset id) :rtype: dictionary ''' model = context['model'] session = context['session'] name_or_id = data_dict.get('id') or data_dict.get('name') if name_or_id is None: raise ValidationError({'id': _('Missing value')}) pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg # immutable fields data_dict["id"] = pkg.id data_dict['type'] = pkg.type _check_access('package_update', context, data_dict) user = context['user'] # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.update_package_schema() if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: package_plugin.check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work. package_plugin.check_data_dict(data_dict) resource_uploads = [] for resource in data_dict.get('resources', []): # file uploads/clearing upload = uploader.get_resource_uploader(resource) if 'mimetype' not in resource: if hasattr(upload, 'mimetype'): resource['mimetype'] = upload.mimetype if 'size' not in resource and 'url_type' in resource: if hasattr(upload, 'filesize'): resource['size'] = upload.filesize resource_uploads.append(upload) data, errors = lib_plugins.plugin_validate( package_plugin, context, data_dict, schema, 'package_update') log.debug('package_update validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), context.get('package').name if context.get('package') else '', data) if errors: model.Session.rollback() raise ValidationError(errors) #avoid revisioning by updating directly model.Session.query(model.Package).filter_by(id=pkg.id).update( {"metadata_modified": datetime.datetime.utcnow()}) model.Session.refresh(pkg) pkg = model_save.package_dict_save(data, context) context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True _get_action('package_owner_org_update')(context_org_update, {'id': pkg.id, 'organization_id': pkg.owner_org}) # Needed to let extensions know the new resources ids model.Session.flush() for index, (resource, upload) in enumerate( zip(data.get('resources', []), resource_uploads)): resource['id'] = pkg.resources[index].id upload.upload(resource['id'], uploader.get_max_resource_size()) for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) item.after_dataset_update(context, data) # Create activity if not pkg.private: user_obj = model.User.by_name(user) if user_obj: user_id = user_obj.id else: user_id = 'not logged in' activity = pkg.activity_stream_item('changed', user_id) session.add(activity) if not context.get('defer_commit'): model.repo.commit() log.debug('Updated object %s' % pkg.name) return_id_only = context.get('return_id_only', False) # Make sure that a user provided schema is not used on package_show context.pop('schema', None) # we could update the dataset so we should still be able to read it. context['ignore_auth'] = True output = data_dict['id'] if return_id_only \ else _get_action('package_show')(context, {'id': data_dict['id']}) return output
def test_09_package_alter(self): context = {"model": model, "session": model.Session, "user": '******' } anna1 = model.Session.query(model.Package).filter_by(name='annakarenina').one() anna_dictized = package_dictize(anna1, context) anna_dictized["name"] = u'annakarenina_changed' anna_dictized["resources"][0]["url"] = u'http://new_url' model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() pkg = model.Session.query(model.Package).filter_by(name='annakarenina_changed').one() package_dictized = package_dictize(pkg, context) resources_revisions = model.Session.query(model.ResourceRevision).filter_by(package_id=anna1.id).all() sorted_resource_revisions = sorted(resources_revisions, key=lambda x: (x.revision_timestamp, x.url))[::-1] for res in sorted_resource_revisions: print res.id, res.revision_timestamp, res.state assert len(sorted_resource_revisions) == 3 # Make sure we remove changeable fields BEFORE we store the pretty-printed version # for comparison clean_package_dictized = self.remove_changable_columns(package_dictized) anna_original = pformat(anna_dictized) anna_after_save = pformat(clean_package_dictized) assert self.remove_changable_columns(anna_dictized) == clean_package_dictized, \ "\n".join(unified_diff(anna_original.split("\n"), anna_after_save.split("\n"))) # changes to the package, relied upon by later tests anna1 = model.Session.query(model.Package).filter_by(name='annakarenina_changed').one() anna_dictized = package_dictize(anna1, context) anna_dictized['name'] = u'annakarenina_changed2' anna_dictized['resources'][0]['url'] = u'http://new_url2' anna_dictized['tags'][0]['name'] = u'new_tag' anna_dictized['tags'][0].pop('id') #test if anna_dictized['extras'][0]['value'] = u'new_value' model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove() anna1 = model.Session.query(model.Package).filter_by(name='annakarenina_changed2').one() anna_dictized = package_dictize(anna1, context) anna_dictized['notes'] = 'wee' anna_dictized['resources'].append({ 'format': u'plain text', 'url': u'http://newurl'} ) anna_dictized['tags'].append({'name': u'newnew_tag'}) anna_dictized['extras'].append({'key': 'david', 'value': u'new_value'}) model.repo.new_revision() package_dict_save(anna_dictized, context) model.Session.commit() model.Session.remove()
def logic_action_create_package_create(context, data_dict): '''Create a new dataset (package). You must be authorized to create new datasets. If you specify any groups for the new dataset, you must also be authorized to edit these groups. Plugins may change the parameters of this function depending on the value of the ``type`` parameter, see the :py:class:`~ckan.plugins.interfaces.IDatasetForm` plugin interface. :param name: the name of the new dataset, must be between 2 and 100 characters long and contain only lowercase alphanumeric characters, ``-`` and ``_``, e.g. ``'warandpeace'`` :type name: string :param title: the title of the dataset (optional, default: same as ``name``) :type title: string :param author: the name of the dataset's author (optional) :type author: string :param author_email: the email address of the dataset's author (optional) :type author_email: string :param maintainer: the name of the dataset's maintainer (optional) :type maintainer: string :param maintainer_email: the email address of the dataset's maintainer (optional) :type maintainer_email: string :param license_id: the id of the dataset's license, see :py:func:`~ckan.logic.action.get.license_list` for available values (optional) :type license_id: license id string :param notes: a description of the dataset (optional) :type notes: string :param url: a URL for the dataset's source (optional) :type url: string :param version: (optional) :type version: string, no longer than 100 characters :param state: the current state of the dataset, e.g. ``'active'`` or ``'deleted'``, only active datasets show up in search results and other lists of datasets, this parameter will be ignored if you are not authorized to change the state of the dataset (optional, default: ``'active'``) :type state: string :param type: the type of the dataset (optional), :py:class:`~ckan.plugins.interfaces.IDatasetForm` plugins associate themselves with different dataset types and provide custom dataset handling behaviour for these types :type type: string :param resources: the dataset's resources, see :py:func:`resource_create` for the format of resource dictionaries (optional) :type resources: list of resource dictionaries :param tags: the dataset's tags, see :py:func:`tag_create` for the format of tag dictionaries (optional) :type tags: list of tag dictionaries :param extras: the dataset's extras (optional), extras are arbitrary (key: value) metadata items that can be added to datasets, each extra dictionary should have keys ``'key'`` (a string), ``'value'`` (a string) :type extras: list of dataset extra dictionaries :param relationships_as_object: see :py:func:`package_relationship_create` for the format of relationship dictionaries (optional) :type relationships_as_object: list of relationship dictionaries :param relationships_as_subject: see :py:func:`package_relationship_create` for the format of relationship dictionaries (optional) :type relationships_as_subject: list of relationship dictionaries :param groups: the groups to which the dataset belongs (optional), each group dictionary should have one or more of the following keys which identify an existing group: ``'id'`` (the id of the group, string), or ``'name'`` (the name of the group, string), to see which groups exist call :py:func:`~ckan.logic.action.get.group_list` :type groups: list of dictionaries :param owner_org: the id of the dataset's owning organization, see :py:func:`~ckan.logic.action.get.organization_list` or :py:func:`~ckan.logic.action.get.organization_list_for_user` for available values (optional) :type owner_org: string :returns: the newly created dataset (unless 'return_id_only' is set to True in the context, in which case just the dataset id will be returned) :rtype: dictionary ''' import ckan.lib.plugins as lib_plugins import datetime import ckan.lib.dictization.model_save as model_save import ckan.plugins as plugins import ckan.lib.uploader as uploader _check_access = ckan.logic.check_access model = context['model'] user = context['user'] if 'type' not in data_dict: package_plugin = lib_plugins.lookup_package_plugin() try: # use first type as default if user didn't provide type package_type = package_plugin.package_types()[0] except (AttributeError, IndexError): package_type = 'dataset' # in case a 'dataset' plugin was registered w/o fallback package_plugin = lib_plugins.lookup_package_plugin(package_type) data_dict['type'] = package_type else: package_plugin = lib_plugins.lookup_package_plugin(data_dict['type']) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.create_package_schema() upload = uploader.Upload('package', '') upload.update_data_dict(data_dict, 'image_url', 'image_upload', 'clear_upload') _check_access('package_create', context, data_dict) if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work package_plugin.check_data_dict(data_dict) data, errors = lib_plugins.plugin_validate(package_plugin, context, data_dict, schema, 'package_create') log.debug('package_create validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), data.get('name'), data_dict) if errors: model.Session.rollback() raise ckan.logic.ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Create object %s') % data.get("name") admins = [] if user: user_obj = model.User.by_name(user.decode('utf8')) if user_obj: admins = [user_obj] data['creator_user_id'] = user_obj.id upload.upload(uploader.get_max_image_size()) generateThumbs(upload.filepath) if 'raw_image_url' in data_dict: data['extras'].append({ 'key': 'image_url', 'value': data_dict['raw_image_url'] }) generateThumbs( config.get('ckan.storage_path') + '/storage/uploads/package/' + data_dict['raw_image_url']) pkg = model_save.package_dict_save(data, context) model.setup_default_user_roles(pkg, admins) # Needed to let extensions know the package and resources ids model.Session.flush() data['id'] = pkg.id if data.get('resources'): for index, resource in enumerate(data['resources']): resource['id'] = pkg.resources[index].id context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True ckan.logic.get_action('package_owner_org_update')( context_org_update, { 'id': pkg.id, 'organization_id': pkg.owner_org }) for item in plugins.PluginImplementations(plugins.IPackageController): item.create(pkg) item.after_create(context, data) # Make sure that a user provided schema is not used in create_views # and on package_show context.pop('schema', None) # Create default views for resources if necessary if data.get('resources'): ckan.logic.get_action('package_create_default_resource_views')( { 'model': context['model'], 'user': context['user'], 'ignore_auth': True }, { 'package': data }) if not context.get('defer_commit'): model.repo.commit() ## need to let rest api create context["package"] = pkg ## this is added so that the rest controller can make a new location context["id"] = pkg.id log.debug('Created object %s' % pkg.name) return_id_only = context.get('return_id_only', False) output = context['id'] if return_id_only \ else ckan.logic.get_action('package_show')(context, {'id': context['id']}) return output
def package_update(context, data_dict): '''Update a dataset (package). You must be authorized to edit the dataset and the groups that it belongs to. Plugins may change the parameters of this function depending on the value of the dataset's ``type`` attribute, see the ``IDatasetForm`` plugin interface. For further parameters see ``package_create()``. :param id: the name or id of the dataset to update :type id: string :returns: the updated dataset (if 'return_package_dict' is True in the context, which is the default. Otherwise returns just the dataset id) :rtype: dictionary ''' model = context['model'] user = context['user'] name_or_id = data_dict.get("id") or data_dict['name'] pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_('Package was not found.')) context["package"] = pkg data_dict["id"] = pkg.id # FIXME: first modifications to package_updade begin here: # tag strings are reconstructed because validators are stripping # tags passed and only taking taks as tag_string values # image upload support has also been added here old_data = get_action('package_show')(context, {'id': pkg.id}) ''' Constructing the tag_string from the given tags. There must be at least one tag, otherwise the tag_string will be empty and a validation error will be raised. ''' if not data_dict.get('tag_string'): data_dict['tag_string'] = ', '.join( h.dict_list_reduce(data_dict.get('tags', {}), 'name')) for key, value in old_data.iteritems(): if key not in data_dict: data_dict[key] = value # data_dict['resources'] = data_dict.get('resources', old_data.get('resources')) # iso_topic_cat = data_dict.get('iso_topic_string', []) # if isinstance(iso_topic_cat, basestring): # iso_topic_cat = [iso_topic_cat] # # data_dict['iso_topic_string'] = ','.join(iso_topic_cat) # Set the package last modified date data_dict['record_last_modified'] = str(datetime.date.today()) # If the Created Date has not yet been set, then set it if data_dict['edc_state'] == 'DRAFT' and not data_dict.get( 'record_create_date'): data_dict['record_create_date'] = str(datetime.date.today()) # If the Publish Date has not yet been set, then set it if data_dict['edc_state'] == 'PUBLISHED' and not data_dict.get( 'record_publish_date'): data_dict['record_publish_date'] = str(datetime.date.today()) # If the Archive Date has not yet been set, then set it if data_dict['edc_state'] == 'ARCHIVED' and not data_dict.get( 'record_archive_date'): data_dict['record_archive_date'] = str(datetime.date.today()) _check_access('package_update', context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) if 'schema' in context: schema = context['schema'] else: schema = package_plugin.update_package_schema() image_url = old_data.get('image_url', None) upload = uploader.Upload('edc', image_url) upload.update_data_dict(data_dict, 'image_url', 'image_upload', 'clear_upload') # Adding image display url for the uploaded image image_url = data_dict.get('image_url') data_dict['image_display_url'] = image_url if image_url and not image_url.startswith('http'): image_url = munge.munge_filename(image_url) data_dict['image_display_url'] = h.url_for_static( 'uploads/edc/%s' % data_dict.get('image_url'), qualified=True) if 'api_version' not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, 'check_data_dict', None) if check_data_dict: try: package_plugin.check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work. package_plugin.check_data_dict(data_dict) # FIXME: modifications to package_update end here^ data, errors = lib_plugins.plugin_validate(package_plugin, context, data_dict, schema, 'package_update') log.debug('package_update validate_errs=%r user=%s package=%s data=%r', errors, context.get('user'), context.get('package').name if context.get('package') else '', data) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if 'message' in context: rev.message = context['message'] else: rev.message = _(u'REST API: Update object %s') % data.get("name") # avoid revisioning by updating directly model.Session.query(model.Package).filter_by(id=pkg.id).update( {"metadata_modified": datetime.datetime.utcnow()}) model.Session.refresh(pkg) pkg = model_save.package_dict_save(data, context) context_org_update = context.copy() context_org_update['ignore_auth'] = True context_org_update['defer_commit'] = True _get_action('package_owner_org_update')(context_org_update, { 'id': pkg.id, 'organization_id': pkg.owner_org }) for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) item.after_update(context, data) upload.upload(uploader.get_max_image_size()) # TODO the next two blocks are copied from ckan/ckan/logic/action/update.py # This codebase is currently hard to maintain because large chunks of the # CKAN action API and the CKAN controllers are simply overriden. This is # probably worse than just forking CKAN would have been, because in that # case at least we could track changes. - @deniszgonjanin # Needed to let extensions know the new resources ids model.Session.flush() if data.get('resources'): for index, resource in enumerate(data['resources']): resource['id'] = pkg.resources[index].id # Create default views for resources if necessary if data.get('resources'): logic.get_action('package_create_default_resource_views')( { 'model': context['model'], 'user': context['user'], 'ignore_auth': True }, { 'package': data }) if not context.get('defer_commit'): model.repo.commit() log.debug('Updated object %s' % pkg.name) return_id_only = context.get('return_id_only', False) # Make sure that a user provided schema is not used on package_show context.pop('schema', None) # we could update the dataset so we should still be able to read it. context['ignore_auth'] = True output = data_dict['id'] if return_id_only \ else _get_action('package_show')(context, {'id': data_dict['id']}) ''' Send state change notifications if required; Added by Khalegh Mamakani Using a thread to run the job in the background so that package_update will not wait for notifications sending. ''' old_state = old_data.get('edc_state') context = { 'model': model, 'session': model.Session, 'user': c.user or c.author, 'auth_user_obj': c.userobj } dataset_url = config.get('ckan.site_url') + h.url_for( controller='package', action="read", id=data_dict['name']) import threading notify_thread = threading.Thread(target=check_record_state, args=(context, old_state, data_dict, g.site_title, g.site_url, dataset_url)) notify_thread.start() return output
def package_update(context, data_dict): """Update a dataset (package). You must be authorized to edit the dataset and the groups that it belongs to. It is recommended to call :py:func:`ckan.logic.action.get.package_show`, make the desired changes to the result, and then call ``package_update()`` with it. Plugins may change the parameters of this function depending on the value of the dataset's ``type`` attribute, see the :py:class:`~ckan.plugins.interfaces.IDatasetForm` plugin interface. For further parameters see :py:func:`~ckan.logic.action.create.package_create`. :param id: the name or id of the dataset to update :type id: string :returns: the updated dataset (if ``'return_package_dict'`` is ``True`` in the context, which is the default. Otherwise returns just the dataset id) :rtype: dictionary """ model = context["model"] user = context["user"] name_or_id = data_dict.get("id") or data_dict["name"] pkg = model.Package.get(name_or_id) if pkg is None: raise NotFound(_("Package was not found.")) context["package"] = pkg data_dict["id"] = pkg.id data_dict["type"] = pkg.type _check_access("package_update", context, data_dict) # get the schema package_plugin = lib_plugins.lookup_package_plugin(pkg.type) if "schema" in context: schema = context["schema"] else: schema = package_plugin.update_package_schema() if "api_version" not in context: # check_data_dict() is deprecated. If the package_plugin has a # check_data_dict() we'll call it, if it doesn't have the method we'll # do nothing. check_data_dict = getattr(package_plugin, "check_data_dict", None) if check_data_dict: try: package_plugin.check_data_dict(data_dict, schema) except TypeError: # Old plugins do not support passing the schema so we need # to ensure they still work. package_plugin.check_data_dict(data_dict) data, errors = lib_plugins.plugin_validate(package_plugin, context, data_dict, schema, "package_update") log.debug( "package_update validate_errs=%r user=%s package=%s data=%r", errors, context.get("user"), context.get("package").name if context.get("package") else "", data, ) if errors: model.Session.rollback() raise ValidationError(errors) rev = model.repo.new_revision() rev.author = user if "message" in context: rev.message = context["message"] else: rev.message = _(u"REST API: Update object %s") % data.get("name") # avoid revisioning by updating directly model.Session.query(model.Package).filter_by(id=pkg.id).update({"metadata_modified": datetime.datetime.utcnow()}) model.Session.refresh(pkg) pkg = model_save.package_dict_save(data, context) context_org_update = context.copy() context_org_update["ignore_auth"] = True context_org_update["defer_commit"] = True context_org_update["add_revision"] = False _get_action("package_owner_org_update")(context_org_update, {"id": pkg.id, "organization_id": pkg.owner_org}) # Needed to let extensions know the new resources ids model.Session.flush() if data.get("resources"): for index, resource in enumerate(data["resources"]): resource["id"] = pkg.resources[index].id for item in plugins.PluginImplementations(plugins.IPackageController): item.edit(pkg) item.after_update(context, data) if not context.get("defer_commit"): model.repo.commit() log.debug("Updated object %s" % pkg.name) return_id_only = context.get("return_id_only", False) # Make sure that a user provided schema is not used on package_show context.pop("schema", None) # we could update the dataset so we should still be able to read it. context["ignore_auth"] = True output = data_dict["id"] if return_id_only else _get_action("package_show")(context, {"id": data_dict["id"]}) return output