[ckan-dev] Conditional validation on custom Datasets

Richard Claydon richard at icdw.co.uk
Wed Mar 5 16:52:09 UTC 2014


Hi

before_action and after_action hooks would have been ideal for this
situation, that's a shame it didn't make the release. Do you know when
they are likely to be included?

For what it's worth, I am using v2.2 2014-02-04.

Here is the traceback you requested:

File '/vagrant/src/ckan/ckan/controllers/package.py', line 672 in new_resource
  get_action('resource_create')(context, data)
File '/vagrant/src/ckan/ckan/logic/__init__.py', line 419 in wrapped
  result = _action(context, data_dict, **kw)
File '/vagrant/src/ckanext-feeder/ckanext/feeder/plugin.py', line 44
in feeder_resource_create
  return logic.action.create.resource_create(context, data_dict)
File '/vagrant/src/ckan/ckan/logic/__init__.py', line 456 in warn
  return get_action(action_name)(context, data_dict)
File '/vagrant/src/ckan/ckan/logic/__init__.py', line 419 in wrapped
  result = _action(context, data_dict, **kw)

Then it repeats. The code is as  you suggested:

def feeder_resource_create(context, data_dict):
    import ckan.logic as logic
    context['schema'] = FeederForm().create_package_schema()
    return logic.action.create.resource_create(context, data_dict)

Where FeederForm is defined as

class FeederForm(SingletonPlugin, tk.DefaultDatasetForm):
    implements(IDatasetForm, inherit=False)

Thanks
Richard

On 5 March 2014 11:53, David Raznick <david.raznick at okfn.org> wrote:
> On 5 March 2014 10:46, Richard Claydon <richard at icdw.co.uk> wrote:
>> Hi David
>>
>> Thank you for replying, I understand now why the package is validated
>> as well. I took your example but unfortunately when I call the
>> resource_create in the manner you have, I get a recursion error. CKAN
>> will warn that I am calling the logic action direct...
>
> hmm we do this is may extensions and am confused as to why there is a
> recursion error (I think there would be one if you use get_action to
> call the action function)  Could you give the traceback of the few
> lines where the recursion is.
>
>>
>>             def warn(context, data_dict):
>>                 log.critical('Action `%s` is being called directly '
>>                              'all action calls should be accessed via '
>>                              'logic.get_action' % action_name)
>>
>
> I think this can be safely ignored in this case, not sure why we added
> this warning as your use case is fairly common (tweaking the odd
> action function).
>
>
>
>> ... and then proceed to call my_resource_create anyway.
>>
>> I can put the core CKAN resource_create code in mine, which isn't
>> ideal. Do you know if there's any interface like IAction (or if
>> IAction does it too) that allows me to chain logic calls instead of
>> overriding?
>
> No sadly not as not all action functions are chainable in a sane way.
> The idea was to be able to wrap them like above.  We are planning
> though of having a before_action and after_action hooks so you can
> modify the data_dict or context before or after any logic call but
> sadly that did not make it in the release.
>
>>
>> If I work something out, I'll update here.
>>
>> Thanks
>> Richard
>>
>> On 4 March 2014 14:08, David Raznick <david.raznick at okfn.org> wrote:
>>> Hello
>>>
>>> The reason that it is validated here is that people can write
>>> validators than depend on both resource and dataset data at the same
>>> time.  i.e a validator that states then can be no more than 4
>>> resources in a dataset.
>>> So all the package data has to be validated together or we could break
>>> people code.
>>>
>>>
>>> For this case I think you will have to use an IAction extension point
>>> to override resource_create.  It is recommended you call the original
>>> function from your overriden one like this:
>>>
>>> https://github.com/okfn/ckanext-ecportal/blob/master/ckanext/ecportal/logic.py#L401
>>>
>>> Your case looks difficult though and you may have to override the
>>> whole function.  You "could" just call the original and catch the
>>> KeyError but that is clearly not nice.  Or you can put in the context
>>> a new lenient schema for this case.  A schema in the context. i.e
>>> context['schema'] = {new schema}  will override your defined
>>> package_update one making sure no errors could ever happen in the
>>> package_update.
>>>
>>> So your code would look somehting like
>>>
>>> import ckan.logic as logic
>>>
>>> def my_resource_create(context, data_dict):
>>>     context['schema'] = new_lenient_schema
>>>     return logic.action.create.resource_create(context, data_dict)
>>>
>>> class YourPlugin(p.SingletonPlugin):
>>>     p.implements(p.IActions)
>>>
>>>     def get_actions(self):
>>>         return {
>>>             'resource_create': my_resource_create,
>>>         }
>>>
>>>
>>> Hope that helps
>>>
>>> David
>>>
>>> On 4 March 2014 12:39, Richard Claydon <richard at icdw.co.uk> wrote:
>>>> Hi
>>>>
>>>> I have a requirement to not validate custom data on a package when a
>>>> package is created, only to validate when the package is updated. I
>>>> have achieved this by creating a custom form derived from
>>>> DefaultDatasetForm, adding the relevant rules in
>>>> create_package_schema() and update_package_schema().
>>>>
>>>> So far so good.
>>>>
>>>> The problem I am currently facing is, when I add a resource, the
>>>> package is validated because the package_update action is called
>>>> within the resource_create function inside actions/create.py.
>>>> Unfortunately the exception handler in resource_create assumes the
>>>> problem is with the resources and an unhandled KeyError exception is
>>>> thrown. Here is the code in CKAN.
>>>>
>>>>     try:
>>>>         context['defer_commit'] = True
>>>>         context['use_cache'] = False
>>>>         _get_action('package_update')(context, pkg_dict)
>>>>         context.pop('defer_commit')
>>>>     except ValidationError, e:
>>>>         errors = e.error_dict['resources'][-1] # <--- assumes
>>>> validation error is in the resource.
>>>>         raise ValidationError(errors)
>>>>
>>>> My question is; can anyone suggest how I can suppress package
>>>> validation when a resource is added? Resource validation is fine, but
>>>> the "new_resource" view in CKAN by default does not include the rest
>>>> of the package data, so IMO that shouldn't be validated here.
>>>>
>>>> I would like to try and avoid overriding core code if possible.
>>>>
>>>> Open to suggestions!
>>>>
>>>> Thanks
>>>> Richard
>>>> _______________________________________________
>>>> ckan-dev mailing list
>>>> ckan-dev at lists.okfn.org
>>>> https://lists.okfn.org/mailman/listinfo/ckan-dev
>>>> Unsubscribe: https://lists.okfn.org/mailman/options/ckan-dev
>>> _______________________________________________
>>> ckan-dev mailing list
>>> ckan-dev at lists.okfn.org
>>> https://lists.okfn.org/mailman/listinfo/ckan-dev
>>> Unsubscribe: https://lists.okfn.org/mailman/options/ckan-dev
>> _______________________________________________
>> ckan-dev mailing list
>> ckan-dev at lists.okfn.org
>> https://lists.okfn.org/mailman/listinfo/ckan-dev
>> Unsubscribe: https://lists.okfn.org/mailman/options/ckan-dev
> _______________________________________________
> ckan-dev mailing list
> ckan-dev at lists.okfn.org
> https://lists.okfn.org/mailman/listinfo/ckan-dev
> Unsubscribe: https://lists.okfn.org/mailman/options/ckan-dev



More information about the ckan-dev mailing list