Skip to content

Commit

Permalink
feat(dev): logic and schema config option;
Browse files Browse the repository at this point in the history
- Moved logic into util method.
- Renamed config options.
- Added new config option to enforce validation schema existance.
  • Loading branch information
JVickery-TBS committed Feb 2, 2024
1 parent d2720fc commit e888153
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 37 deletions.
19 changes: 16 additions & 3 deletions ckanext/xloader/config_declaration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,25 @@ groups:
to True.
type: bool
required: false
- key: ckanext.xloader.requires_validation
- key: ckanext.xloader.validation.requires_successful_report
default: False
example: True
description: |
Resources are required to pass validation from the ckanext-validation
plugin to be able to get xloadered.
Resources are required to pass Validation from the ckanext-validation
plugin to be able to get XLoadered.
type: bool
required: false
- key: ckanext.xloader.validation.enforce_schema
default: True
example: False
description: |
Resources are expected to have a Validation Schema, or use the default ones if not.
If this option is set to `False`, Resources that do not have
a Validation Schema will be treated like they do not require Validation.
See https://github.com/frictionlessdata/ckanext-validation?tab=readme-ov-file#data-schema
for more details.
type: bool
required: false

Expand Down
21 changes: 16 additions & 5 deletions ckanext/xloader/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def notify(self, entity, operation):
# extension will call resource_patch and this method should
# be called again. However, url_changed will not be in the entity
# once Validation does the patch.
if utils.is_validation_plugin_loaded() and \
if utils.awaiting_validation() and \
toolkit.asbool(toolkit.config.get('ckanext.xloader.requires_validation')):

if entity.__dict__.get('extras', {}).get('validation_status', None) != 'success':
Expand All @@ -136,15 +136,26 @@ def notify(self, entity, operation):
"id": entity.id,
},
)

if utils.awaiting_validation(resource_dict):
# If the resource requires validation, stop here if validation
# has not been performed or did not succeed. The Validation
# extension will call resource_patch and this method should
# be called again. However, url_changed will not be in the entity
# once Validation does the patch.
log.debug("Skipping xloading resource %s because the "
"resource did not pass validation yet.", entity.id)
return
elif not getattr(entity, 'url_changed', False):
# do not submit to xloader if the url has not changed.
return

self._submit_to_xloader(resource_dict)

# IResourceController

def after_resource_create(self, context, resource_dict):
if utils.is_validation_plugin_loaded() and \
toolkit.asbool(toolkit.config.get('ckanext.xloader.requires_validation')) and \
resource_dict.get('validation_status', None) != 'success':

if utils.awaiting_validation(resource_dict):
log.debug("Skipping xloading resource %s because the "
"resource did not pass validation yet.", resource_dict.get('id'))
return
Expand Down
91 changes: 62 additions & 29 deletions ckanext/xloader/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,73 @@
import ckan.plugins as p
from ckan.plugins.toolkit import h, _

from logging import getLogger


log = getLogger(__name__)


def awaiting_validation(res_dict):
"""
Checks the existence of a logic action from the ckanext-validation
plugin, thus supporting any extending of the Validation Plugin class.
Checks ckanext.xloader.validation.requires_successful_report config
option value.
Checks ckanext.xloader.validation.enforce_schema config
option value. Then checks the Resource's validation_status.
"""
if not p.toolkit.asbool(p.toolkit.config.get('ckanext.xloader.validation.requires_successful_report', False)):
# validation.requires_successful_report is turned off, return right away
return False

try:
# check for one of the main actions from ckanext-validation
# in the case that users extend the Validation plugin class
# and rename the plugin entry-point.
p.toolkit.get_action('resource_validation_show')
is_validation_plugin_loaded = True
except KeyError:
is_validation_plugin_loaded = False

if not is_validation_plugin_loaded:
# the validation plugin is not loaded but required, log a warning
log.warning('ckanext.xloader.validation.requires_successful_report requires the ckanext-validation plugin to be activated.')
return False

if p.toolkit.asbool(p.toolkit.config.get('ckanext.xloader.validation.enforce_schema', True)):
# validation.enforce_schema is turned on, so we will always look for `validation_status`
if res_dict.get('validation_status', None) != 'success':
return True

# validation.enforce_schema is turned off, so if the Resource
# does not have a Validation Schema, we will treat it like
# it does not require Validation.
return False


def resource_data(id, resource_id, rows=None):

if p.toolkit.request.method == "POST":
if is_validation_plugin_loaded() and \
p.toolkit.asbool(p.toolkit.config.get('ckanext.xloader.requires_validation')):

context = {
"ignore_auth": True,
}
resource_dict = p.toolkit.get_action("resource_show")(
context,
{
"id": resource_id,
},

context = {
"ignore_auth": True,
}
resource_dict = p.toolkit.get_action("resource_show")(
context,
{
"id": resource_id,
},
)

if awaiting_validation(resource_dict):
h.flash_error(_("Cannot upload resource %s to the DataStore "
"because the resource did not pass validation yet.") % resource_id)
return p.toolkit.redirect_to(
"xloader.resource_data", id=id, resource_id=resource_id
)
if resource_dict.get('validation_status', None) != 'success':
h.flash_error(_("Cannot upload resource %s to the DataStore "
"because the resource did not pass validation yet.") % resource_id)
return p.toolkit.redirect_to(
"xloader.resource_data", id=id, resource_id=resource_id
)

try:
p.toolkit.get_action("xloader_submit")(
None,
Expand Down Expand Up @@ -234,15 +279,3 @@ def type_guess(rows, types=TYPES, strict=False):
guesses_tuples = [(t, guess[t]) for t in types if t in guess]
_columns.append(max(guesses_tuples, key=lambda t_n: t_n[1])[0])
return _columns


def is_validation_plugin_loaded():
"""
Checks the existence of a logic action from the ckanext-validation
plugin, thus supporting any extending of the Validation Plugin class.
"""
try:
p.toolkit.get_action('resource_validation_show')
return True
except KeyError:
return False

0 comments on commit e888153

Please sign in to comment.