diff --git a/MANIFEST.in b/MANIFEST.in index cbb4ca17..1e3a411a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include README.rst +include README.md include LICENSE include requirements.txt -recursive-include ckanext/validation *.html *.json *.js *.less *.css *.mo \ No newline at end of file +recursive-include ckanext/validation *.html *.json *.js *.less *.css *.mo *.config *.yml \ No newline at end of file diff --git a/ckanext/validation/blueprints.py b/ckanext/validation/blueprints.py deleted file mode 100644 index 3ec0dc34..00000000 --- a/ckanext/validation/blueprints.py +++ /dev/null @@ -1,46 +0,0 @@ -# encoding: utf-8 - -from flask import Blueprint - -from ckantoolkit import c, NotAuthorized, ObjectNotFound, abort, _, render, get_action - -validation = Blueprint("validation", __name__) - - -def read(id, resource_id): - - try: - validation = get_action(u"resource_validation_show")( - {u"user": c.user}, {u"resource_id": resource_id} - ) - - resource = get_action(u"resource_show")({u"user": c.user}, {u"id": resource_id}) - - dataset = get_action(u"package_show")( - {u"user": c.user}, {u"id": resource[u"package_id"]} - ) - - # Needed for core resource templates - c.package = c.pkg_dict = dataset - c.resource = resource - - return render( - u"validation/validation_read.html", - extra_vars={ - u"validation": validation, - u"resource": resource, - u"dataset": dataset, - u"pkg_dict": dataset, - }, - ) - - except NotAuthorized: - abort(403, _(u"Unauthorized to read this validation report")) - except ObjectNotFound: - - abort(404, _(u"No validation report exists for this resource")) - - -validation.add_url_rule( - "/dataset//resource//validation", view_func=read -) diff --git a/ckanext/validation/common.py b/ckanext/validation/common.py new file mode 100644 index 00000000..cd4a284e --- /dev/null +++ b/ckanext/validation/common.py @@ -0,0 +1,56 @@ +# encoding: utf-8 + +import csv +import logging +import six +import sys + +from ckantoolkit import (c, NotAuthorized, + ObjectNotFound, abort, _, + render, get_action, config) + +from ckanext.validation import settings +from ckanext.validation.logic.action import _search_datasets +from ckanext.validation.model import create_tables, tables_exist + + +log = logging.getLogger(__name__) + +############################################################################### +# Controller # +############################################################################### + + +def validation(resource_id, id=None): + try: + validation = get_action(u'resource_validation_show')( + {u'user': c.user}, + {u'resource_id': resource_id}) + + resource = get_action(u'resource_show')( + {u'user': c.user}, + {u'id': resource_id}) + + package_id = resource[u'package_id'] + if id and id != package_id: + raise ObjectNotFound("Resource {} not found in package {}".format(resource_id, id)) + + dataset = get_action(u'package_show')( + {u'user': c.user}, + {u'id': id or resource[u'package_id']}) + + # Needed for core resource templates + c.package = c.pkg_dict = dataset + c.resource = resource + + return render(u'validation/validation_read.html', extra_vars={ + u'validation': validation, + u'resource': resource, + u'pkg_dict': dataset, + u'dataset': dataset, + }) + + except NotAuthorized: + return abort(403, _(u'Unauthorized to read this validation report')) + except ObjectNotFound: + return abort(404, _(u'No validation report exists for this resource')) \ No newline at end of file diff --git a/ckanext/validation/helpers.py b/ckanext/validation/helpers.py index b6c856df..aa36572b 100644 --- a/ckanext/validation/helpers.py +++ b/ckanext/validation/helpers.py @@ -4,6 +4,18 @@ from ckan.lib.helpers import url_for_static from ckantoolkit import url_for, _, config, asbool, literal, h +def _get_helpers(): + validators = ( + get_validation_badge, + validation_extract_report_from_errors, + dump_json_value, + bootstrap_version, + validation_dict, + use_webassets + ) + + return {"{}".format(func.__name__): func for func in validators} + def get_validation_badge(resource, in_listing=False): diff --git a/ckanext/validation/plugin.py b/ckanext/validation/plugin.py index ddda1ab4..40da56a0 100644 --- a/ckanext/validation/plugin.py +++ b/ckanext/validation/plugin.py @@ -1,14 +1,16 @@ # encoding: utf-8 +import json import logging import cgi -import json + from werkzeug.datastructures import FileStorage as FlaskFileStorage import ckan.plugins as p import ckantoolkit as t -from ckanext.validation import settings +from . import settings, validators +from .helpers import _get_helpers from ckanext.validation.model import tables_exist from .logic import action, auth from ckanext.validation.helpers import ( @@ -28,8 +30,7 @@ get_update_mode_from_config, ) from ckanext.validation.interfaces import IDataValidation -from ckanext.validation import blueprints, cli - +from ckanext.validation import views, cli ALLOWED_UPLOAD_TYPES = (cgi.FieldStorage, FlaskFileStorage) log = logging.getLogger(__name__) @@ -49,22 +50,23 @@ class ValidationPlugin(p.SingletonPlugin): # IBlueprint def get_blueprint(self): - return [blueprints.validation] + return views.get_blueprints() # IClick def get_commands(self): - return [cli.validation] + return cli.get_commands() # IConfigurer def update_config(self, config_): if not tables_exist(): + init_command = 'ckan validation init-db' log.critical(u''' -The validation extension requires a database setup. Please run the following -to create the database tables: - paster --plugin=ckanext-validation validation init-db -''') +The validation extension requires a database setup. +Validation pages will not be enabled. +Please run the following to create the database tables: + %s''', init_command) else: log.debug(u'Validation tables exist') @@ -85,14 +87,12 @@ def get_auth_functions(self): # ITemplateHelpers def get_helpers(self): - return { - u'get_validation_badge': get_validation_badge, - u'validation_extract_report_from_errors': validation_extract_report_from_errors, - u'dump_json_value': dump_json_value, - u'bootstrap_version': bootstrap_version, - u'validation_dict': validation_dict, - u'use_webassets': use_webassets, - } + return _get_helpers() + + # IValidators + + def get_validators(self): + return validators.get_validators() # IResourceController @@ -132,14 +132,27 @@ def _process_schema_fields(self, data_dict): return data_dict + # CKAN < 2.10 def before_create(self, context, data_dict): + return self.before_resource_create(context, data_dict) + + # CKAN >= 2.10 + def before_resource_create(self, context, data_dict): is_dataset = self._data_dict_is_dataset(data_dict) if not is_dataset: context["_resource_create_call"] = True return self._process_schema_fields(data_dict) + # CKAN < 2.10 def after_create(self, context, data_dict): + if (self._data_dict_is_dataset(data_dict)): + return self.after_dataset_create(context, data_dict) + else: + return self.after_resource_create(context, data_dict) + + # CKAN >= 2.10 + def after_resource_create(self, context, data_dict): is_dataset = self._data_dict_is_dataset(data_dict) @@ -185,7 +198,12 @@ def _handle_validation_for_resource(self, context, resource): _run_async_validation(resource[u'id']) + # CKAN < 2.10 def before_update(self, context, current_resource, updated_resource): + return self.before_resource_update(context, current_resource, updated_resource) + + # CKAN >= 2.10 + def before_resource_update(self, context, current_resource, updated_resource): updated_resource = self._process_schema_fields(updated_resource) @@ -225,7 +243,15 @@ def before_update(self, context, current_resource, updated_resource): return updated_resource + # CKAN < 2.10 def after_update(self, context, data_dict): + if (self._data_dict_is_dataset(data_dict)): + return self.after_dataset_update(context, data_dict) + else: + return self.after_resource_update(context, data_dict) + + # CKAN >= 2.10 + def after_resource_update(self, context, data_dict): is_dataset = self._data_dict_is_dataset(data_dict) @@ -287,7 +313,13 @@ def after_update(self, context, data_dict): # IPackageController + # CKAN < 2.10 def before_index(self, index_dict): + if (self._data_dict_is_dataset(index_dict)): + return self.before_dataset_index(index_dict) + + # CKAN >= 2.10 + def before_dataset_index(self, index_dict): res_status = [] dataset_dict = json.loads(index_dict['validated_data_dict']) @@ -300,14 +332,6 @@ def before_index(self, index_dict): return index_dict - # IValidators - - def get_validators(self): - return { - 'resource_schema_validator': resource_schema_validator, - 'validation_options_validator': validation_options_validator, - } - def _run_async_validation(resource_id): diff --git a/ckanext/validation/validators.py b/ckanext/validation/validators.py index 9e1962a8..da7c081a 100644 --- a/ckanext/validation/validators.py +++ b/ckanext/validation/validators.py @@ -6,6 +6,15 @@ from ckantoolkit import Invalid, config +def get_validators(): + validators = ( + resource_schema_validator, + validation_options_validator, + ) + + return {"{}".format(func.__name__): func for func in validators} + + # Input validators def resource_schema_validator(value, context): diff --git a/ckanext/validation/views.py b/ckanext/validation/views.py index c17f44ee..8e91962a 100644 --- a/ckanext/validation/views.py +++ b/ckanext/validation/views.py @@ -2,46 +2,16 @@ from flask import Blueprint -from ckantoolkit import ( - c, NotAuthorized, ObjectNotFound, - abort, _, render, get_action) +from ckanext.validation import common -validation = Blueprint("service_proxy", __name__) +validation = Blueprint(u'validation', __name__) -def validation_read(self, id, resource_id): - - try: - validation = get_action(u'resource_validation_show')( - {u'user': c.user}, - {u'resource_id': resource_id}) - - resource = get_action(u'resource_show')( - {u'user': c.user}, - {u'id': resource_id}) - - dataset = get_action(u'package_show')( - {u'user': c.user}, - {u'id': resource[u'package_id']}) - - # Needed for core resource templates - c.package = c.pkg_dict = dataset - c.resource = resource - - return render(u'validation/validation_read.html', extra_vars={ - u'validation': validation, - u'resource': resource, - u'dataset': dataset, - }) - - except NotAuthorized: - abort(403, _(u'Unauthorized to read this validation report')) - except ObjectNotFound: - - abort(404, _(u'No validation report exists for this resource')) - validation.add_url_rule( - '/dataset/{id}/resource/{resource_id}/validation', - view_func=validation_read + u'/dataset//resource//validation', 'read', methods=('GET',), view_func=common.validation ) + + +def get_blueprints(): + return [validation]