Merge branch 'harvest-object-create'

This commit is contained in:
amercader 2013-10-04 17:22:58 +01:00
commit c5f4d6889b
7 changed files with 158 additions and 4 deletions

View File

@ -1,18 +1,27 @@
import logging import logging
import ckan
from ckan import logic from ckan import logic
from ckan.logic import NotFound, check_access from ckan.logic import NotFound, check_access
from ckanext.harvest.logic import HarvestJobExists from ckanext.harvest.logic import HarvestJobExists
from ckanext.harvest.plugin import DATASET_TYPE_NAME from ckanext.harvest.plugin import DATASET_TYPE_NAME
from ckanext.harvest.model import (HarvestSource, HarvestJob) from ckanext.harvest.model import (HarvestSource, HarvestJob, HarvestObject,
from ckanext.harvest.logic.dictization import harvest_job_dictize HarvestObjectExtra)
from ckanext.harvest.logic.schema import harvest_source_show_package_schema from ckanext.harvest.logic.dictization import (harvest_job_dictize,
harvest_object_dictize)
from ckanext.harvest.logic.schema import (harvest_source_show_package_schema,
harvest_object_create_schema)
from ckanext.harvest.logic.action.get import harvest_source_list,harvest_job_list from ckanext.harvest.logic.action.get import harvest_source_list,harvest_job_list
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
_validate = ckan.lib.navl.dictization_functions.validate
class InactiveSource(Exception):
pass
def harvest_source_create(context,data_dict): def harvest_source_create(context,data_dict):
''' '''
Creates a new harvest source Creates a new harvest source
@ -136,3 +145,32 @@ def _check_for_existing_jobs(context, source_id):
exist = len(exist_new + exist_running) > 0 exist = len(exist_new + exist_running) > 0
return exist return exist
def harvest_object_create(context, data_dict):
""" Create a new harvest object
:type guid: string (optional)
:type content: string (optional)
:type job_id: string
:type source_id: string (optional)
:type package_id: string (optional)
:type extras: dict (optional)
"""
check_access('harvest_object_create', context, data_dict)
data, errors = _validate(data_dict, harvest_object_create_schema(), context)
if errors:
raise logic.ValidationError(errors)
obj = HarvestObject(
guid=data.get('guid'),
content=data.get('content'),
job=data['job_id'],
harvest_source_id=data.get('source_id'),
package_id=data.get('package_id'),
extras=[ HarvestObjectExtra(key=k, value=v)
for k, v in data.get('extras', {}).items() ]
)
obj.save()
return harvest_object_dictize(obj, context)

View File

@ -52,3 +52,13 @@ def harvest_job_create_all(context, data_dict):
return {'success': False, 'msg': pt._('Only sysadmins can create harvest jobs for all sources')} return {'success': False, 'msg': pt._('Only sysadmins can create harvest jobs for all sources')}
else: else:
return {'success': True} return {'success': True}
def harvest_object_create(context, data_dict):
"""
Auth check for creating a harvest object
only the sysadmins can create harvest objects
"""
# sysadmins can run all actions if we've got to this point we're not a sysadmin
return {'success': False, 'msg': pt._('Only the sysadmins can create harvest objects')}

View File

@ -20,6 +20,9 @@ from ckanext.harvest.logic.validators import (harvest_source_url_validator,
harvest_source_frequency_exists, harvest_source_frequency_exists,
dataset_type_exists, dataset_type_exists,
harvest_source_convert_from_config, harvest_source_convert_from_config,
harvest_source_id_exists,
harvest_job_exists,
harvest_object_extras_validator,
) )
def harvest_source_schema(): def harvest_source_schema():
@ -74,3 +77,16 @@ def harvest_source_show_package_schema():
}) })
return schema return schema
def harvest_object_create_schema():
schema = {
'guid': [ignore_missing, unicode],
'content': [ignore_missing, unicode],
'state': [ignore_missing, unicode],
'job_id': [harvest_job_exists],
'source_id': [ignore_missing, harvest_source_id_exists],
'package_id': [ignore_missing, package_id_exists],
'extras': [ignore_missing, harvest_object_extras_validator],
}
return schema

View File

@ -7,7 +7,7 @@ from ckan import model
from ckan.plugins import PluginImplementations from ckan.plugins import PluginImplementations
from ckanext.harvest.plugin import DATASET_TYPE_NAME from ckanext.harvest.plugin import DATASET_TYPE_NAME
from ckanext.harvest.model import HarvestSource, UPDATE_FREQUENCIES from ckanext.harvest.model import HarvestSource, UPDATE_FREQUENCIES, HarvestJob
from ckanext.harvest.interfaces import IHarvester from ckanext.harvest.interfaces import IHarvester
from ckan.lib.navl.validators import keep_extras from ckan.lib.navl.validators import keep_extras
@ -22,6 +22,14 @@ def harvest_source_id_exists(value, context):
raise Invalid('Harvest Source with id %r does not exist.' % str(value)) raise Invalid('Harvest Source with id %r does not exist.' % str(value))
return value return value
def harvest_job_exists(value, context):
"""Check if a harvest job exists and returns the model if it does"""
result = HarvestJob.get(value, None)
if not result:
raise Invalid('Harvest Job with id %r does not exist.' % str(value))
return result
def _normalize_url(url): def _normalize_url(url):
o = urlparse.urlparse(url) o = urlparse.urlparse(url)
@ -196,3 +204,11 @@ def dataset_type_exists(value):
if value != DATASET_TYPE_NAME: if value != DATASET_TYPE_NAME:
value = DATASET_TYPE_NAME value = DATASET_TYPE_NAME
return value return value
def harvest_object_extras_validator(value, context):
if not isinstance(value, dict):
raise Invalid('extras must be a dict')
for v in value.values():
if not isinstance(v, basestring):
raise Invalid('extras must be a dict of strings')
return value

View File

@ -0,0 +1,14 @@
import factory
from ckanext.harvest.model import HarvestSource, HarvestJob
class HarvestSourceFactory(factory.Factory):
FACTORY_FOR = HarvestSource
url = "http://harvest.test.com"
type = "test-harvest-source"
class HarvestJobFactory(factory.Factory):
FACTORY_FOR = HarvestJob
status = "New"
source = factory.SubFactory(HarvestSourceFactory)

View File

@ -3,12 +3,16 @@ import copy
import ckan import ckan
import paste import paste
import pylons.test import pylons.test
import factories
import unittest
from ckan import tests from ckan import tests
from ckan import plugins as p from ckan import plugins as p
from ckan.plugins import toolkit
from ckanext.harvest.interfaces import IHarvester from ckanext.harvest.interfaces import IHarvester
import ckanext.harvest.model as harvest_model import ckanext.harvest.model as harvest_model
class MockHarvesterForActionTests(p.SingletonPlugin): class MockHarvesterForActionTests(p.SingletonPlugin):
p.implements(IHarvester) p.implements(IHarvester)
def info(self): def info(self):
@ -203,3 +207,58 @@ class TestHarvestSourceActionUpdate(HarvestSourceActionBase):
assert source.url == source_dict['url'] assert source.url == source_dict['url']
assert source.type == source_dict['source_type'] assert source.type == source_dict['source_type']
class TestHarvestObject(unittest.TestCase):
@classmethod
def setup_class(cls):
harvest_model.setup()
@classmethod
def teardown_class(cls):
ckan.model.repo.rebuild_db()
def test_create(self):
job = factories.HarvestJobFactory()
job.save()
context = {
'model' : ckan.model,
'session': ckan.model.Session,
'ignore_auth': True,
}
data_dict = {
'guid' : 'guid',
'content' : 'content',
'job_id' : job.id,
'extras' : { 'a key' : 'a value' },
}
harvest_object = toolkit.get_action('harvest_object_create')(
context, data_dict)
# fetch the object from database to check it was created
created_object = harvest_model.HarvestObject.get(harvest_object['id'])
assert created_object.guid == harvest_object['guid'] == data_dict['guid']
def test_create_bad_parameters(self):
source_a = factories.HarvestSourceFactory()
source_a.save()
job = factories.HarvestJobFactory()
job.save()
context = {
'model' : ckan.model,
'session': ckan.model.Session,
'ignore_auth': True,
}
data_dict = {
'job_id' : job.id,
'source_id' : source_a.id,
'extras' : 1
}
harvest_object_create = toolkit.get_action('harvest_object_create')
self.assertRaises(ckan.logic.ValidationError, harvest_object_create,
context, data_dict)
data_dict['extras'] = {'test': 1 }
self.assertRaises(ckan.logic.ValidationError, harvest_object_create,
context, data_dict)

View File

@ -1 +1,2 @@
pika==0.9.8 pika==0.9.8
factory-boy>=2