[ckan-changes] commit/ckan: 7 new changesets
Bitbucket
commits-noreply at bitbucket.org
Thu Jul 7 17:32:46 UTC 2011
7 new changesets in ckan:
http://bitbucket.org/okfn/ckan/changeset/7247f216274c/
changeset: 7247f216274c
branch: defect-1214-api-improvements
user: dread
date: 2011-07-07 13:36:35
summary: [tests]: Completed moving of model API tests into tests/funcation/api/model. Minor corrections to API docs, including removing missing rating entity.
affected #: 9 files (20.6 KB)
--- a/ckan/tests/functional/api/base.py Wed Jul 06 20:58:59 2011 +0100
+++ b/ckan/tests/functional/api/base.py Thu Jul 07 12:36:35 2011 +0100
@@ -69,7 +69,7 @@
return '%s%s' % (base, path)
def package_offset(self, package_name=None):
- if package_name == None:
+ if package_name is None:
# Package Register
return self.offset('/rest/package')
else:
@@ -79,14 +79,14 @@
def package_ref_from_name(self, package_name):
package = self.get_package_by_name(unicode(package_name))
- if package == None:
+ if package is None:
return package_name
else:
return self.ref_package(package)
def package_id_from_ref(self, package_name):
package = self.get_package_by_name(unicode(package_name))
- if package == None:
+ if package is None:
return package_name
else:
return self.ref_package(package)
@@ -96,7 +96,7 @@
return getattr(package, self.ref_package_by)
def group_offset(self, group_name=None):
- if group_name == None:
+ if group_name is None:
# Group Register
return self.offset('/rest/group')
else:
@@ -106,7 +106,7 @@
def group_ref_from_name(self, group_name):
group = self.get_group_by_name(unicode(group_name))
- if group == None:
+ if group is None:
return group_name
else:
return self.ref_group(group)
@@ -115,11 +115,52 @@
assert self.ref_group_by in ['id', 'name']
return getattr(group, self.ref_group_by)
+ def revision_offset(self, revision_id=None):
+ if revision_id is None:
+ # Revision Register
+ return self.offset('/rest/revision')
+ else:
+ # Revision Entity
+ return self.offset('/rest/revision/%s' % revision_id)
+
+ def rating_offset(self, package_name=None):
+ if package_name is None:
+ # Revision Register
+ return self.offset('/rest/rating')
+ else:
+ # Revision Entity
+ package_ref = self.package_ref_from_name(package_name)
+ return self.offset('/rest/rating/%s' % package_ref)
+
+ def relationship_offset(self, package_1_name=None,
+ relationship_type=None,
+ package_2_name=None,
+ ):
+ assert package_1_name
+ package_1_ref = self.package_ref_from_name(package_1_name)
+ if package_2_name is None:
+ if not relationship_type:
+ return self.offset('/rest/package/%s/relationships' % \
+ package_1_ref)
+ else:
+ return self.offset('/rest/package/%s/%s' %
+ (package_1_ref, relationship_type))
+ else:
+ package_2_ref = self.package_ref_from_name(package_2_name)
+ if not relationship_type:
+ return self.offset('/rest/package/%s/relationships/%s' % \
+ (package_1_ref, package_2_ref))
+ else:
+ return self.offset('/rest/package/%s/%s/%s' % \
+ (package_1_ref,
+ relationship_type,
+ package_2_ref))
+
def anna_offset(self, postfix=''):
return self.package_offset('annakarenina') + postfix
def tag_offset(self, tag_name=None):
- if tag_name == None:
+ if tag_name is None:
# Tag Register
return self.offset('/rest/tag')
else:
@@ -129,7 +170,7 @@
def tag_ref_from_name(self, tag_name):
tag = self.get_tag_by_name(unicode(tag_name))
- if tag == None:
+ if tag is None:
return tag_name
else:
return self.ref_tag(tag)
@@ -307,8 +348,6 @@
def teardown(self):
model.Session.remove()
model.repo.rebuild_db()
- #self.delete_common_fixtures()
- #self.commit_remove()
super(BaseModelApiTestCase, self).teardown()
def init_extra_environ(self):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ckan/tests/functional/api/model/test_licenses.py Thu Jul 07 12:36:35 2011 +0100
@@ -0,0 +1,32 @@
+from nose.tools import assert_equal
+
+from ckan import model
+
+from ckan.tests.functional.api.base import BaseModelApiTestCase
+from ckan.tests.functional.api.base import Api1TestCase as Version1TestCase
+from ckan.tests.functional.api.base import Api2TestCase as Version2TestCase
+from ckan.tests.functional.api.base import ApiUnversionedTestCase as UnversionedTestCase
+
+class LicensesTestCase(BaseModelApiTestCase):
+
+ commit_changesets = False
+ reuse_common_fixtures = False
+
+ def test_register_get_ok(self):
+ from ckan.model.license import LicenseRegister
+ register = LicenseRegister()
+ assert len(register), "No changesets found in model."
+ offset = self.offset('/rest/licenses')
+ res = self.app.get(offset, status=[200])
+ licenses_data = self.data_from_res(res)
+ assert len(licenses_data) == len(register), (len(licenses_data), len(register))
+ for license_data in licenses_data:
+ id = license_data['id']
+ license = register[id]
+ assert license['title'] == license.title
+ assert license['url'] == license.url
+
+
+class TestLicensesVersion1(Version1TestCase, LicensesTestCase): pass
+class TestLicensesVersion2(Version2TestCase, LicensesTestCase): pass
+class TestLicensesUnversioned(UnversionedTestCase, LicensesTestCase): pass
--- a/ckan/tests/functional/api/model/test_package.py Wed Jul 06 20:58:59 2011 +0100
+++ b/ckan/tests/functional/api/model/test_package.py Thu Jul 07 12:36:35 2011 +0100
@@ -363,7 +363,52 @@
assert len(revisions) == 3, len(revisions)
-class TestPackagesVersion1(Version1TestCase, PackagesTestCase): pass
+class TestPackagesVersion1(Version1TestCase, PackagesTestCase):
+ def test_06_create_pkg_using_download_url(self):
+ test_params = {
+ 'name':u'testpkg06',
+ 'download_url':u'ftp://ftp.monash.edu.au/pub/nihongo/JMdict.gz',
+ }
+ offset = self.package_offset()
+ postparams = '%s=1' % self.dumps(test_params)
+ res = self.app.post(offset, params=postparams,
+ extra_environ=self.extra_environ)
+ model.Session.remove()
+ pkg = self.get_package_by_name(test_params['name'])
+ assert pkg
+ assert pkg.name == test_params['name'], pkg
+ assert len(pkg.resources) == 1, pkg.resources
+ assert pkg.resources[0].url == test_params['download_url'], pkg.resources[0]
+
+ def test_10_edit_pkg_with_download_url(self):
+ test_params = {
+ 'name':u'testpkg10',
+ 'download_url':u'testurl',
+ }
+ rev = model.repo.new_revision()
+ pkg = model.Package()
+ model.Session.add(pkg)
+ pkg.name = test_params['name']
+ pkg.download_url = test_params['download_url']
+ model.Session.commit()
+
+ pkg = self.get_package_by_name(test_params['name'])
+ model.setup_default_user_roles(pkg, [self.user])
+ rev = model.repo.new_revision()
+ model.repo.commit_and_remove()
+ assert self.get_package_by_name(test_params['name'])
+
+ # edit it
+ pkg_vals = {'download_url':u'newurl'}
+ offset = self.package_offset(test_params['name'])
+ postparams = '%s=1' % self.dumps(pkg_vals)
+ res = self.app.post(offset, params=postparams, status=[200],
+ extra_environ=self.extra_environ)
+ model.Session.remove()
+ pkg = model.Session.query(model.Package).filter_by(name=test_params['name']).one()
+ assert len(pkg.resources) == 1, pkg.resources
+ assert pkg.resources[0].url == pkg_vals['download_url']
+
class TestPackagesVersion2(Version2TestCase, PackagesTestCase): pass
class TestPackagesUnversioned(UnversionedTestCase, PackagesTestCase): pass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ckan/tests/functional/api/model/test_ratings.py Thu Jul 07 12:36:35 2011 +0100
@@ -0,0 +1,94 @@
+from nose.tools import assert_equal
+from nose.plugins.skip import SkipTest
+
+from ckan import model
+
+from ckan.tests.functional.api.base import BaseModelApiTestCase
+from ckan.tests.functional.api.base import Api1TestCase as Version1TestCase
+from ckan.tests.functional.api.base import Api2TestCase as Version2TestCase
+from ckan.tests.functional.api.base import ApiUnversionedTestCase as UnversionedTestCase
+
+class RatingsTestCase(BaseModelApiTestCase):
+
+ commit_changesets = False
+ reuse_common_fixtures = True
+
+ def test_register_get(self):
+ raise SkipTest('"Rating register get" functionality is not implemented')
+ rating1 = model.Rating(user_ip_address='1.2.3.4',
+ package=self.anna,
+ rating=4.0)
+ rating2 = model.Rating(user=model.User.by_name(u'annafan'),
+ package=self.anna,
+ rating=2.0)
+ model.Session.add_all((rating1, rating2))
+ model.repo.commit_and_remove()
+
+ offset = self.rating_offset()
+ res = self.app.get(offset, status=[200])
+
+ def test_entity_get(self):
+ raise SkipTest('"Rating entity get" functionality is not implemented')
+ rating = model.Rating(user_ip_address='1.2.3.4',
+ package=self.anna,
+ rating=4.0)
+ model.Session.add(rating)
+ model.repo.commit_and_remove()
+
+ offset = self.rating_offset(self.anna.name)
+ res = self.app.get(offset, status=[200])
+ assert_equal(res, rating_opts['rating'])
+
+ def test_register_post(self):
+ # Test Rating Register Post 200.
+ self.clear_all_tst_ratings()
+ offset = self.rating_offset()
+ rating_opts = {'package':u'warandpeace',
+ 'rating':5}
+ pkg_name = rating_opts['package']
+ postparams = '%s=1' % self.dumps(rating_opts)
+ res = self.app.post(offset, params=postparams, status=[201],
+ extra_environ=self.extra_environ)
+ model.Session.remove()
+ pkg = self.get_package_by_name(pkg_name)
+ assert pkg
+ assert len(pkg.ratings) == 1
+ assert pkg.ratings[0].rating == rating_opts['rating'], pkg.ratings
+
+ # Get package to see rating
+ offset = self.package_offset(pkg_name)
+ res = self.app.get(offset, status=[200])
+ assert pkg_name in res, res
+ assert '"ratings_average": %s.0' % rating_opts['rating'] in res, res
+ assert '"ratings_count": 1' in res, res
+
+ model.Session.remove()
+
+ # Rerate package
+ offset = self.rating_offset()
+ postparams = '%s=1' % self.dumps(rating_opts)
+ res = self.app.post(offset, params=postparams, status=[201],
+ extra_environ=self.extra_environ)
+ model.Session.remove()
+ pkg = self.get_package_by_name(pkg_name)
+ assert pkg
+ assert len(pkg.ratings) == 1
+ assert pkg.ratings[0].rating == rating_opts['rating'], pkg.ratings
+
+ def test_entity_post_invalid(self):
+ self.clear_all_tst_ratings()
+ offset = self.rating_offset()
+ rating_opts = {'package':u'warandpeace',
+ 'rating':0}
+ postparams = '%s=1' % self.dumps(rating_opts)
+ res = self.app.post(offset, params=postparams, status=[409],
+ extra_environ=self.extra_environ)
+ self.assert_json_response(res, 'rating')
+ model.Session.remove()
+ pkg = self.get_package_by_name(rating_opts['package'])
+ assert pkg
+ assert len(pkg.ratings) == 0
+
+class TestRatingsVersion1(Version1TestCase, RatingsTestCase): pass
+class TestRatingsVersion2(Version2TestCase, RatingsTestCase): pass
+class TestRatingsUnversioned(UnversionedTestCase, RatingsTestCase): pass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ckan/tests/functional/api/model/test_relationships.py Thu Jul 07 12:36:35 2011 +0100
@@ -0,0 +1,208 @@
+from nose.tools import assert_equal
+
+from ckan import model
+
+from ckan.tests.functional.api.base import BaseModelApiTestCase
+from ckan.tests.functional.api.base import Api1TestCase as Version1TestCase
+from ckan.tests.functional.api.base import Api2TestCase as Version2TestCase
+from ckan.tests.functional.api.base import ApiUnversionedTestCase as UnversionedTestCase
+
+class RelationshipsTestCase(BaseModelApiTestCase):
+
+ commit_changesets = False
+ reuse_common_fixtures = True
+
+ @classmethod
+ def setup_class(cls):
+# super(RelationshipsTestCase, cls).setup_class()
+ cls.testsysadmin = model.User.by_name(u'testsysadmin')
+ cls.comment = u'Comment umlaut: \xfc.'
+
+ def test_01_create_and_read_relationship(self):
+ # check anna has no existing relationships
+ assert not self.anna.get_relationships()
+ assert self.get_relationships(package1_name='annakarenina') == [], self.get_relationships(package1_name='annakarenina')
+ assert self.get_relationships(package1_name='annakarenina',
+ package2_name='warandpeace') == []
+ assert self.get_relationships(package1_name='annakarenina',
+ type='child_of',
+ package2_name='warandpeace') == 404
+ assert self.get_relationships_via_package('annakarenina') == []
+
+ # Create a relationship.
+ self.create_annakarenina_parent_of_war_and_peace()
+
+ # Check package relationship register.
+ rels = self.get_relationships(package1_name='annakarenina')
+ assert len(rels) == 1
+ self.check_relationship_dict(rels[0],
+ 'annakarenina', 'parent_of', 'warandpeace', self.comment)
+
+ # Todo: Name this?
+ # Check '/api/VER/rest/package/annakarenina/relationships/warandpeace'
+ rels = self.get_relationships(package1_name='annakarenina',
+ package2_name='warandpeace')
+ assert len(rels) == 1
+ self.check_relationship_dict(rels[0],
+ 'annakarenina', 'parent_of', 'warandpeace', self.comment)
+
+ # Todo: Name this?
+ # check '/api/VER/rest/package/annakarenina/parent_of/warandpeace'
+ rels = self.get_relationships(package1_name='annakarenina',
+ type='parent_of',
+ package2_name='warandpeace')
+ assert len(rels) == 1
+ self.check_relationship_dict(rels[0],
+ 'annakarenina', 'parent_of', 'warandpeace', self.comment)
+
+ # same checks in reverse direction
+ rels = self.get_relationships(package1_name='warandpeace')
+ assert len(rels) == 1
+ self.check_relationship_dict(rels[0],
+ 'warandpeace', 'child_of', 'annakarenina', self.comment)
+
+ rels = self.get_relationships(package1_name='warandpeace',
+ package2_name='annakarenina')
+ assert len(rels) == 1
+ self.check_relationship_dict(rels[0],
+ 'warandpeace', 'child_of', 'annakarenina', self.comment)
+
+ rels = self.get_relationships(package1_name='warandpeace',
+ type='child_of',
+ package2_name='annakarenina')
+ assert len(rels) == 1
+ self.check_relationship_dict(rels[0],
+ 'warandpeace', 'child_of', 'annakarenina', self.comment)
+
+ # Check package entity relationships.
+ rels = self.get_relationships_via_package('annakarenina')
+ assert len(rels) == 1
+ self.check_relationship_dict(rels[0],
+ 'annakarenina', 'parent_of', 'warandpeace', self.comment)
+
+ def test_03_update_relationship(self):
+ # Create a relationship.
+ self.create_annakarenina_parent_of_war_and_peace()
+
+ # Check the relationship before update.
+ self.check_relationships_rest('warandpeace', 'annakarenina',
+ [{'type': 'child_of',
+ 'comment': self.comment}])
+
+ # Update the relationship.
+ new_comment = u'New comment.'
+ self.update_annakarenina_parent_of_war_and_peace(comment=new_comment)
+
+ # Check the relationship after update.
+ self.check_relationships_rest('warandpeace', 'annakarenina', [{'type': 'child_of', 'comment': new_comment}])
+
+ # Repeat update with same values, to check it remains the same?
+
+ # Update the relationship.
+ new_comment = u'New comment.'
+ self.update_annakarenina_parent_of_war_and_peace(comment=new_comment)
+
+ # Check the relationship after update.
+ self.check_relationships_rest('warandpeace', 'annakarenina', [{'type': 'child_of', 'comment': new_comment}])
+
+ def test_05_delete_relationship(self):
+ self.create_annakarenina_parent_of_war_and_peace()
+ self.update_annakarenina_parent_of_war_and_peace()
+ expected = [ {'type': 'child_of', 'comment': u'New comment.'} ]
+ self.check_relationships_rest('warandpeace', 'annakarenina', expected)
+
+ self.delete_annakarenina_parent_of_war_and_peace()
+
+ expected = []
+ self.check_relationships_rest('warandpeace', 'annakarenina', expected)
+
+ def create_annakarenina_parent_of_war_and_peace(self):
+ # Create package relationship.
+ # Todo: Redesign this in a RESTful style, so that a relationship is
+ # created by posting a relationship to a relationship **register**.
+ offset = self.relationship_offset('annakarenina', 'parent_of', 'warandpeace')
+ postparams = '%s=1' % self.dumps({'comment':self.comment})
+ res = self.app.post(offset, params=postparams, status=[201],
+ extra_environ=self.extra_environ)
+ # Check the model, directly.
+ rels = self.anna.get_relationships()
+ assert len(rels) == 1, rels
+ assert rels[0].type == 'child_of'
+ assert rels[0].subject.name == 'warandpeace'
+ assert rels[0].object.name == 'annakarenina'
+
+ def update_annakarenina_parent_of_war_and_peace(self, comment=u'New comment.'):
+ offset = self.relationship_offset('annakarenina', 'parent_of', 'warandpeace')
+ postparams = '%s=1' % self.dumps({'comment':comment})
+ res = self.app.post(offset, params=postparams, status=[201], extra_environ=self.extra_environ)
+ return res
+
+ def delete_annakarenina_parent_of_war_and_peace(self):
+ offset = self.relationship_offset('annakarenina', 'parent_of', 'warandpeace')
+ res = self.app.delete(offset, status=[200], extra_environ=self.extra_environ)
+ return res
+
+ def get_relationships(self, package1_name=u'annakarenina', type='relationships', package2_name=None):
+ offset = self.relationship_offset(package1_name, type, package2_name)
+ allowable_statuses = [200]
+ if type:
+ allowable_statuses.append(404)
+ res = self.app.get(offset, status=allowable_statuses)
+ if res.status == 200:
+ res_dict = self.data_from_res(res) if res.body else []
+ return res_dict
+ else:
+ return 404
+
+ def get_relationships_via_package(self, package1_name):
+ offset = self.package_offset(package1_name)
+ res = self.app.get(offset, status=200)
+ res_dict = self.data_from_res(res)
+ return res_dict['relationships']
+
+ def assert_len_relationships(self, relationships, expected_relationships):
+ len_relationships = len(relationships)
+ len_expected_relationships = len(expected_relationships)
+ if len_relationships != len_expected_relationships:
+ msg = 'Found %i relationships, ' % len_relationships
+ msg += 'but expected %i.' % len_expected_relationships
+ if len_relationships:
+ msg += ' Found: '
+ for r in relationships:
+ msg += '%s %s %s; ' % (r['subject'], r['type'], r['object'])
+ msg += '.'
+ raise Exception, msg
+
+ def check_relationships_rest(self, pkg1_name, pkg2_name=None,
+ expected_relationships=[]):
+ rels = self.get_relationships(package1_name=pkg1_name,
+ package2_name=pkg2_name)
+ self.assert_len_relationships(rels, expected_relationships)
+ for rel in rels:
+ the_expected_rel = None
+ for expected_rel in expected_relationships:
+ if expected_rel['type'] == rel['type'] and \
+ (pkg2_name or expected_rel['object'] == pkg2_name):
+ the_expected_rel = expected_rel
+ break
+ if not the_expected_rel:
+ raise Exception('Unexpected relationship: %s %s %s' %
+ (rel['subject'], rel['type'], rel['object']))
+ for field in ('subject', 'object', 'type', 'comment'):
+ if the_expected_rel.has_key(field):
+ value = rel[field]
+ expected = the_expected_rel[field]
+ assert value == expected, (value, expected, field, rel)
+
+ def check_relationship_dict(self, rel_dict, subject_name, type, object_name, comment):
+ subject_ref = self.package_ref_from_name(subject_name)
+ object_ref = self.package_ref_from_name(object_name)
+
+ assert rel_dict['subject'] == subject_ref, (rel_dict, subject_ref)
+ assert rel_dict['object'] == object_ref, (rel_dict, object_ref)
+ assert rel_dict['type'] == type, (rel_dict, type)
+ assert rel_dict['comment'] == comment, (rel_dict, comment)
+
+class TestRelationshipsVersion1(Version1TestCase, RelationshipsTestCase): pass
+class TestRelationshipsVersion2(Version2TestCase, RelationshipsTestCase): pass
+class TestRelationshipsUnversioned(UnversionedTestCase, RelationshipsTestCase): pass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ckan/tests/functional/api/model/test_revisions.py Thu Jul 07 12:36:35 2011 +0100
@@ -0,0 +1,49 @@
+from nose.tools import assert_equal
+
+from ckan import model
+
+from ckan.tests.functional.api.base import BaseModelApiTestCase
+from ckan.tests.functional.api.base import Api1TestCase as Version1TestCase
+from ckan.tests.functional.api.base import Api2TestCase as Version2TestCase
+from ckan.tests.functional.api.base import ApiUnversionedTestCase as UnversionedTestCase
+
+class RevisionsTestCase(BaseModelApiTestCase):
+
+ commit_changesets = False
+ reuse_common_fixtures = True
+
+ def test_register_get_ok(self):
+ # Check mock register behaviour.
+ offset = self.revision_offset()
+ res = self.app.get(offset, status=200)
+ revs = model.Session.query(model.Revision).all()
+ assert revs, 'There are no revisions in the model.'
+ res_dict = self.data_from_res(res)
+ for rev in revs:
+ assert rev.id in res_dict, (rev.id, res_dict)
+
+ def test_entity_get_ok(self):
+ rev = model.repo.history().all()[-2] # 2nd revision is the creation of pkgs
+ assert rev.id
+ assert rev.timestamp.isoformat()
+ offset = self.revision_offset(rev.id)
+ response = self.app.get(offset, status=[200])
+ response_data = self.data_from_res(response)
+ assert_equal(rev.id, response_data['id'])
+ assert_equal(rev.timestamp.isoformat(), response_data['timestamp'])
+ assert 'packages' in response_data
+ packages = response_data['packages']
+ assert isinstance(packages, list)
+ #assert len(packages) != 0, "Revision packages is empty: %s" % packages
+ assert self.ref_package(self.anna) in packages, packages
+ assert self.ref_package(self.war) in packages, packages
+
+ def test_entity_get_404(self):
+ revision_id = "xxxxxxxxxxxxxxxxxxxxxxxxxx"
+ offset = self.revision_offset(revision_id)
+ res = self.app.get(offset, status=404)
+ self.assert_json_response(res, 'Not found')
+
+class TestRevisionsVersion1(Version1TestCase, RevisionsTestCase): pass
+class TestRevisionsVersion2(Version2TestCase, RevisionsTestCase): pass
+class TestRevisionsUnversioned(UnversionedTestCase, RevisionsTestCase): pass
--- a/ckan/tests/functional/api/model/test_tag.py Wed Jul 06 20:58:59 2011 +0100
+++ b/ckan/tests/functional/api/model/test_tag.py Thu Jul 07 12:36:35 2011 +0100
@@ -23,6 +23,10 @@
res = self.app.get(offset, status=self.STATUS_200_OK)
self.assert_msg_represents_russian(msg=res.body)
+ def test_entity_get_not_found(self):
+ offset = self.tag_offset('doesntexist')
+ res = self.app.get(offset, status=404)
+ self.assert_json_response(res, 'Not found')
class TestTagsVersion1(Version1TestCase, TagsTestCase): pass
class TestTagsVersion2(Version2TestCase, TagsTestCase): pass
--- a/ckan/tests/functional/api/test_model.py Wed Jul 06 20:58:59 2011 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,412 +0,0 @@
-from ckan.tests.functional.api.base import *
-from ckan.lib.create_test_data import CreateTestData
-from ckan.tests import TestController as ControllerTestCase
-
-class ModelApiTestCase(BaseModelApiTestCase):
-
- def setup(self):
- self.create_common_fixtures()
- self.init_extra_environ()
- self.source = None
- self.source1 = None
- self.source2 = None
- self.source3 = None
- self.source4 = None
- self.source5 = None
- self.job = None
- self.job1 = None
- self.job2 = None
- self.job3 = None
-
- def teardown(self):
- model.repo.rebuild_db()
-
- def test_02_get_tag_register_ok(self):
- # Test Packages Register Get 200.
- offset = self.offset('/rest/tag')
- res = self.app.get(offset, status=[200])
- assert 'russian' in res, res
- assert 'tolstoy' in res, res
-
- def test_04_get_tag(self):
- offset = self.offset('/rest/tag/tolstoy')
- res = self.app.get(offset, status=[200])
- assert 'annakarenina' in res, res
- assert not 'warandpeace' in res, res
-
- def test_05_get_tag_entity_not_found(self):
- offset = self.offset('/rest/tag/doesntexist')
- res = self.app.get(offset, status=404)
- self.assert_json_response(res, 'Not found')
-
- def test_06_rate_package(self):
- # Test Rating Register Post 200.
- self.clear_all_tst_ratings()
- offset = self.offset('/rest/rating')
- rating_opts = {'package':u'warandpeace',
- 'rating':5}
- postparams = '%s=1' % self.dumps(rating_opts)
- res = self.app.post(offset, params=postparams, status=[201],
- extra_environ=self.extra_environ)
- model.Session.remove()
- pkg = self.get_package_by_name(rating_opts['package'])
- assert pkg
- assert len(pkg.ratings) == 1
- assert pkg.ratings[0].rating == rating_opts['rating'], pkg.ratings
-
- # Get package to see rating
- offset = self.offset('/rest/package/%s' % rating_opts['package'])
- res = self.app.get(offset, status=[200])
- assert rating_opts['package'] in res, res
- assert '"ratings_average": %s.0' % rating_opts['rating'] in res, res
- assert '"ratings_count": 1' in res, res
-
- model.Session.remove()
-
- # Rerate package
- offset = self.offset('/rest/rating')
- postparams = '%s=1' % self.dumps(rating_opts)
- res = self.app.post(offset, params=postparams, status=[201],
- extra_environ=self.extra_environ)
- model.Session.remove()
- pkg = self.get_package_by_name(rating_opts['package'])
- assert pkg
- assert len(pkg.ratings) == 1
- assert pkg.ratings[0].rating == rating_opts['rating'], pkg.ratings
-
- def test_06_rate_package_out_of_range(self):
- self.clear_all_tst_ratings()
- offset = self.offset('/rest/rating')
- rating_opts = {'package':u'warandpeace',
- 'rating':0}
- postparams = '%s=1' % self.dumps(rating_opts)
- res = self.app.post(offset, params=postparams, status=[409],
- extra_environ=self.extra_environ)
- self.assert_json_response(res, 'rating')
- model.Session.remove()
- pkg = self.get_package_by_name(rating_opts['package'])
- assert pkg
- assert len(pkg.ratings) == 0
-
- def test_14_list_revisions(self):
- # Check mock register behaviour.
- offset = self.offset('/rest/revision')
- res = self.app.get(offset, status=200)
- revs = model.Session.query(model.Revision).all()
- assert revs, "There are no revisions in the model."
- res_dict = self.data_from_res(res)
- for rev in revs:
- assert rev.id in res_dict, (rev.id, res_dict)
-
- def test_14_get_revision(self):
- rev = model.repo.history().all()[-2] # 2nd revision is the creation of pkgs
- assert rev.id
- assert rev.timestamp.isoformat()
- offset = self.offset('/rest/revision/%s' % rev.id)
- response = self.app.get(offset, status=[200])
- response_data = self.data_from_res(response)
- assert rev.id == response_data['id']
- assert rev.timestamp.isoformat() == response_data['timestamp'], (rev.timestamp.isoformat(), response_data['timestamp'])
- assert 'packages' in response_data
- packages = response_data['packages']
- assert isinstance(packages, list)
- #assert len(packages) != 0, "Revision packages is empty: %s" % packages
- assert self.ref_package(self.anna) in packages, packages
- assert self.ref_package(self.war) in packages, packages
-
- def test_14_get_revision_404(self):
- revision_id = "xxxxxxxxxxxxxxxxxxxxxxxxxx"
- offset = self.offset('/rest/revision/%s' % revision_id)
- res = self.app.get(offset, status=404)
- self.assert_json_response(res, 'Not found')
- model.Session.remove()
-
- def test_16_list_licenses(self):
- from ckan.model.license import LicenseRegister
- register = LicenseRegister()
- assert len(register), "No changesets found in model."
- offset = self.offset('/rest/licenses')
- res = self.app.get(offset, status=[200])
- licenses_data = self.data_from_res(res)
- assert len(licenses_data) == len(register), (len(licenses_data), len(register))
- for license_data in licenses_data:
- id = license_data['id']
- license = register[id]
- assert license['title'] == license.title
- assert license['url'] == license.url
-
-
-class RelationshipsApiTestCase(ApiTestCase, ControllerTestCase):
-
- @classmethod
- def setup_class(self):
- CreateTestData.create()
- self.user = self.create_user(name=u'barry')
- self.testsysadmin = model.User.by_name(u'testsysadmin')
- self.extra_environ={ 'Authorization' : str(self.user.apikey) }
- self.comment = u'Comment umlaut: \xfc.'
-
- @classmethod
- def teardown_class(self):
- model.Session.remove()
- model.repo.rebuild_db()
- model.Session.remove()
-
- def teardown(self):
- for relationship in self.anna.get_relationships():
- relationship.purge()
- model.Session.commit()
- relationships = self.anna.get_relationships()
- assert relationships == [], "There are still some relationships: %s" % relationships
-
- def test_01_create_and_read_relationship(self):
- # check anna has no existing relationships
- assert not self.anna.get_relationships()
- assert self.get_relationships(package1_name='annakarenina') == [], self.get_relationships(package1_name='annakarenina')
- assert self.get_relationships(package1_name='annakarenina',
- package2_name='warandpeace') == []
- assert self.get_relationships(package1_name='annakarenina',
- type='child_of',
- package2_name='warandpeace') == 404
- assert self.get_relationships_via_package('annakarenina') == []
-
- # Create a relationship.
- self.create_annakarenina_parent_of_war_and_peace()
-
- # Check package relationship register.
- rels = self.get_relationships(package1_name='annakarenina')
- assert len(rels) == 1
- self.check_relationship_dict(rels[0],
- 'annakarenina', 'parent_of', 'warandpeace', self.comment)
-
- # Todo: Name this?
- # Check '/api/VER/rest/package/annakarenina/relationships/warandpeace'
- rels = self.get_relationships(package1_name='annakarenina',
- package2_name='warandpeace')
- assert len(rels) == 1
- self.check_relationship_dict(rels[0],
- 'annakarenina', 'parent_of', 'warandpeace', self.comment)
-
- # Todo: Name this?
- # check '/api/VER/rest/package/annakarenina/parent_of/warandpeace'
- rels = self.get_relationships(package1_name='annakarenina',
- type='parent_of',
- package2_name='warandpeace')
- assert len(rels) == 1
- self.check_relationship_dict(rels[0],
- 'annakarenina', 'parent_of', 'warandpeace', self.comment)
-
- # same checks in reverse direction
- rels = self.get_relationships(package1_name='warandpeace')
- assert len(rels) == 1
- self.check_relationship_dict(rels[0],
- 'warandpeace', 'child_of', 'annakarenina', self.comment)
-
- rels = self.get_relationships(package1_name='warandpeace',
- package2_name='annakarenina')
- assert len(rels) == 1
- self.check_relationship_dict(rels[0],
- 'warandpeace', 'child_of', 'annakarenina', self.comment)
-
- rels = self.get_relationships(package1_name='warandpeace',
- type='child_of',
- package2_name='annakarenina')
- assert len(rels) == 1
- self.check_relationship_dict(rels[0],
- 'warandpeace', 'child_of', 'annakarenina', self.comment)
-
- # Check package entity relationships.
- rels = self.get_relationships_via_package('annakarenina')
- assert len(rels) == 1
- self.check_relationship_dict(rels[0],
- 'annakarenina', 'parent_of', 'warandpeace', self.comment)
-
- def test_03_update_relationship(self):
- # Create a relationship.
- self.create_annakarenina_parent_of_war_and_peace()
-
- # Check the relationship before update.
- self.check_relationships_rest('warandpeace', 'annakarenina',
- [{'type': 'child_of',
- 'comment': self.comment}])
-
- # Update the relationship.
- new_comment = u'New comment.'
- self.update_annakarenina_parent_of_war_and_peace(comment=new_comment)
-
- # Check the relationship after update.
- self.check_relationships_rest('warandpeace', 'annakarenina', [{'type': 'child_of', 'comment': new_comment}])
-
- # Repeat update with same values, to check it remains the same?
-
- # Update the relationship.
- new_comment = u'New comment.'
- self.update_annakarenina_parent_of_war_and_peace(comment=new_comment)
-
- # Check the relationship after update.
- self.check_relationships_rest('warandpeace', 'annakarenina', [{'type': 'child_of', 'comment': new_comment}])
-
- def test_05_delete_relationship(self):
- self.create_annakarenina_parent_of_war_and_peace()
- self.update_annakarenina_parent_of_war_and_peace()
- expected = [ {'type': 'child_of', 'comment': u'New comment.'} ]
- self.check_relationships_rest('warandpeace', 'annakarenina', expected)
-
- self.delete_annakarenina_parent_of_war_and_peace()
-
- expected = []
- self.check_relationships_rest('warandpeace', 'annakarenina', expected)
-
- def create_annakarenina_parent_of_war_and_peace(self):
- # Create package relationship.
- # Todo: Redesign this in a RESTful style, so that a relationship is
- # created by posting a relationship to a relationship **register**.
- offset = self.offset('/rest/package/annakarenina/parent_of/warandpeace')
- postparams = '%s=1' % self.dumps({'comment':self.comment})
- res = self.app.post(offset, params=postparams, status=[201],
- extra_environ=self.extra_environ)
- # Check the model, directly.
- rels = self.anna.get_relationships()
- assert len(rels) == 1, rels
- assert rels[0].type == 'child_of'
- assert rels[0].subject.name == 'warandpeace'
- assert rels[0].object.name == 'annakarenina'
-
- def update_annakarenina_parent_of_war_and_peace(self, comment=u'New comment.'):
- offset = self.offset('/rest/package/annakarenina/parent_of/warandpeace')
- postparams = '%s=1' % self.dumps({'comment':comment})
- res = self.app.post(offset, params=postparams, status=[201], extra_environ=self.extra_environ)
- return res
-
- def delete_annakarenina_parent_of_war_and_peace(self):
- offset = self.offset('/rest/package/annakarenina/parent_of/warandpeace')
- res = self.app.delete(offset, status=[200], extra_environ=self.extra_environ)
- return res
-
- def get_relationships(self, package1_name=u'annakarenina', type='relationships', package2_name=None):
- package1_ref = self.package_ref_from_name(package1_name)
- if not package2_name:
- offset = self.offset('/rest/package/%s/%s' % (package1_ref, type))
- else:
- package2_ref = self.package_ref_from_name(package2_name)
- offset = self.offset('/rest/package/%s/%s/%s' % (
- str(package1_ref), type, str(package2_ref)))
- allowable_statuses = [200]
- if type:
- allowable_statuses.append(404)
- res = self.app.get(offset, status=allowable_statuses)
- if res.status == 200:
- res_dict = self.data_from_res(res) if res.body else []
- return res_dict
- else:
- return 404
-
- def get_relationships_via_package(self, package1_name):
- offset = self.offset('/rest/package/%s' % (str(package1_name)))
- res = self.app.get(offset, status=200)
- res_dict = self.data_from_res(res)
- return res_dict['relationships']
-
- def assert_len_relationships(self, relationships, expected_relationships):
- len_relationships = len(relationships)
- len_expected_relationships = len(expected_relationships)
- if len_relationships != len_expected_relationships:
- msg = 'Found %i relationships, ' % len_relationships
- msg += 'but expected %i.' % len_expected_relationships
- if len_relationships:
- msg += ' Found: '
- for r in relationships:
- msg += '%s %s %s; ' % (r['subject'], r['type'], r['object'])
- msg += '.'
- raise Exception, msg
-
- def check_relationships_rest(self, pkg1_name, pkg2_name=None,
- expected_relationships=[]):
- rels = self.get_relationships(package1_name=pkg1_name,
- package2_name=pkg2_name)
- self.assert_len_relationships(rels, expected_relationships)
- for rel in rels:
- the_expected_rel = None
- for expected_rel in expected_relationships:
- if expected_rel['type'] == rel['type'] and \
- (pkg2_name or expected_rel['object'] == pkg2_name):
- the_expected_rel = expected_rel
- break
- if not the_expected_rel:
- raise Exception('Unexpected relationship: %s %s %s' %
- (rel['subject'], rel['type'], rel['object']))
- for field in ('subject', 'object', 'type', 'comment'):
- if the_expected_rel.has_key(field):
- value = rel[field]
- expected = the_expected_rel[field]
- assert value == expected, (value, expected, field, rel)
-
- def check_relationship_dict(self, rel_dict, subject_name, type, object_name, comment):
- subject_ref = self.package_ref_from_name(subject_name)
- object_ref = self.package_ref_from_name(object_name)
-
- assert rel_dict['subject'] == subject_ref, (rel_dict, subject_ref)
- assert rel_dict['object'] == object_ref, (rel_dict, object_ref)
- assert rel_dict['type'] == type, (rel_dict, type)
- assert rel_dict['comment'] == comment, (rel_dict, comment)
-
-
-# Tests for Version 1 of the API.
-class TestModelApi1(Api1TestCase, ModelApiTestCase):
-
- def test_06_create_pkg_using_download_url(self):
- test_params = {
- 'name':u'testpkg06',
- 'download_url':u'ftp://ftp.monash.edu.au/pub/nihongo/JMdict.gz',
- }
- offset = self.package_offset()
- postparams = '%s=1' % self.dumps(test_params)
- res = self.app.post(offset, params=postparams,
- extra_environ=self.extra_environ)
- model.Session.remove()
- pkg = self.get_package_by_name(test_params['name'])
- assert pkg
- assert pkg.name == test_params['name'], pkg
- assert len(pkg.resources) == 1, pkg.resources
- assert pkg.resources[0].url == test_params['download_url'], pkg.resources[0]
-
- def test_10_edit_pkg_with_download_url(self):
- test_params = {
- 'name':u'testpkg10',
- 'download_url':u'testurl',
- }
- rev = model.repo.new_revision()
- pkg = model.Package()
- model.Session.add(pkg)
- pkg.name = test_params['name']
- pkg.download_url = test_params['download_url']
- model.Session.commit()
-
- pkg = self.get_package_by_name(test_params['name'])
- model.setup_default_user_roles(pkg, [self.user])
- rev = model.repo.new_revision()
- model.repo.commit_and_remove()
- assert self.get_package_by_name(test_params['name'])
-
- # edit it
- pkg_vals = {'download_url':u'newurl'}
- offset = self.package_offset(test_params['name'])
- postparams = '%s=1' % self.dumps(pkg_vals)
- res = self.app.post(offset, params=postparams, status=[200],
- extra_environ=self.extra_environ)
- model.Session.remove()
- pkg = model.Session.query(model.Package).filter_by(name=test_params['name']).one()
- assert len(pkg.resources) == 1, pkg.resources
- assert pkg.resources[0].url == pkg_vals['download_url']
-
-
-class TestRelationshipsApi1(Api1TestCase, RelationshipsApiTestCase): pass
-
-# Tests for Version 2 of the API.
-class TestModelApi2(Api2TestCase, ModelApiTestCase): pass
-class TestRelationshipsApi2(Api2TestCase, RelationshipsApiTestCase): pass
-
-# Tests for unversioned API.
-class TestModelApiUnversioned(ApiUnversionedTestCase, ModelApiTestCase): pass
-class TestRelationshipsApiUnversioned(RelationshipsApiTestCase, ApiUnversionedTestCase): pass
-
--- a/doc/api/model_resources_table.rst.inc Wed Jul 06 20:58:59 2011 +0100
+++ b/doc/api/model_resources_table.rst.inc Thu Jul 07 12:36:35 2011 +0100
@@ -8,7 +8,7 @@
+--------------------------------+-------------------------------------------------------------------+
| Group Register | ``/rest/group`` |
+--------------------------------+-------------------------------------------------------------------+
-| Group Entity | ``/rest/group/GROUP-NAME`` |
+| Group Entity | ``/rest/group/GROUP-REF`` |
+--------------------------------+-------------------------------------------------------------------+
| Tag Register | ``/rest/tag`` |
+--------------------------------+-------------------------------------------------------------------+
@@ -16,9 +16,9 @@
+--------------------------------+-------------------------------------------------------------------+
| Rating Register | ``/rest/rating`` |
+--------------------------------+-------------------------------------------------------------------+
-| Rating Entity | ``/rest/rating/PACKAGE-REF`` |
+| Package Relationships Register | ``/rest/package/PACKAGE-REF/relationships`` |
+--------------------------------+-------------------------------------------------------------------+
-| Package Relationships Register | ``/rest/package/PACKAGE-REF/relationships`` |
+| Package Relationships Register | ``/rest/package/PACKAGE-REF/RELATIONSHIP-TYPE`` |
+--------------------------------+-------------------------------------------------------------------+
| Package Relationships Register | ``/rest/package/PACKAGE-REF/relationships/PACKAGE-REF`` |
+--------------------------------+-------------------------------------------------------------------+
http://bitbucket.org/okfn/ckan/changeset/cd164bfbbce5/
changeset: cd164bfbbce5
branch: defect-1214-api-improvements
user: dread
date: 2011-07-07 14:06:18
summary: [tests]: Working on package delete without specific headers.
affected #: 2 files (1.6 KB)
--- a/ckan/tests/functional/api/base.py Thu Jul 07 12:36:35 2011 +0100
+++ b/ckan/tests/functional/api/base.py Thu Jul 07 13:06:18 2011 +0100
@@ -361,9 +361,37 @@
application/x-www-form-urlencoded)
'''
+ return self.http_request(offset, data, content_type='application/json',
+ request_method='POST',
+ content_length=len(data),
+ status=status, extra_environ=extra_environ)
+
+ def delete_request(self, offset, status=None, extra_environ=None):
+ ''' Sends a delete request. Similar to the paste.delete but it
+ does not send the content type or content length.
+ '''
+ return self.http_request(offset, data='', content_type=None,
+ request_method='DELETE',
+ content_length=None,
+ status=status,
+ extra_environ=extra_environ)
+
+ def http_request(self, offset, data,
+ content_type='application/json',
+ request_method='POST',
+ content_length=None,
+ status=None,
+ extra_environ=None):
+ ''' Posts data in the body in a user-specified format.
+ (rather than Paste Fixture\'s default Content-Type of
+ application/x-www-form-urlencoded)
+
+ '''
environ = self.app._make_environ()
- environ['CONTENT_TYPE'] = 'application/json'
- environ['CONTENT_LENGTH'] = str(len(data))
+ if content_type:
+ environ['CONTENT_TYPE'] = content_type
+ if content_length is not None:
+ environ['CONTENT_LENGTH'] = str(content_length)
environ['REQUEST_METHOD'] = 'POST'
environ['wsgi.input'] = StringIO(data)
if extra_environ:
--- a/ckan/tests/functional/api/model/test_package.py Thu Jul 07 12:36:35 2011 +0100
+++ b/ckan/tests/functional/api/model/test_package.py Thu Jul 07 13:06:18 2011 +0100
@@ -303,15 +303,7 @@
def test_entity_delete_ok(self):
# create a package with package_fixture_data
if not self.get_package_by_name(self.package_fixture_data['name']):
- rev = model.repo.new_revision()
- package = model.Package()
- model.Session.add(package)
- package.name = self.package_fixture_data['name']
- model.repo.commit_and_remove()
- rev = model.repo.new_revision()
- package = self.get_package_by_name(self.package_fixture_data['name'])
- model.setup_default_user_roles(package, [self.user])
- model.repo.commit_and_remove()
+ self.create_package(admins=[self.user], name=self.package_fixture_data['name'])
assert self.get_package_by_name(self.package_fixture_data['name'])
# delete it
offset = self.package_offset(self.package_fixture_data['name'])
@@ -321,6 +313,19 @@
self.assert_equal(package.state, 'deleted')
model.Session.remove()
+ def test_entity_delete_ok_without_request_headers(self):
+ # create a package with package_fixture_data
+ if not self.get_package_by_name(self.package_fixture_data['name']):
+ self.create_package(admins=[self.user], name=self.package_fixture_data['name'])
+ assert self.get_package_by_name(self.package_fixture_data['name'])
+ # delete it
+ offset = self.package_offset(self.package_fixture_data['name'])
+ res = self.delete_request(offset, status=self.STATUS_200_OK,
+ extra_environ=self.extra_environ)
+ package = self.get_package_by_name(self.package_fixture_data['name'])
+ self.assert_equal(package.state, 'deleted')
+ model.Session.remove()
+
def test_entity_delete_not_found(self):
package_name = u'random_one'
assert not model.Session.query(model.Package).filter_by(name=package_name).count()
http://bitbucket.org/okfn/ckan/changeset/50df15bd148a/
changeset: 50df15bd148a
branch: defect-1214-api-improvements
user: dread
date: 2011-07-07 14:09:26
summary: [lib/base]: #1210 Fix application/json errors associated with newer WebOb. (cset:8f6ba8ef63f3 transplanted).
affected #: 1 file (99 bytes)
--- a/ckan/lib/base.py Thu Jul 07 13:06:18 2011 +0100
+++ b/ckan/lib/base.py Thu Jul 07 13:09:26 2011 +0100
@@ -146,22 +146,25 @@
'''
cls.log.debug('Retrieving request params: %r' % request.params)
cls.log.debug('Retrieving request POST: %r' % request.POST)
-
+ request_data = None
if request.POST:
try:
- request_data = request.POST.keys() or request.body
+ request_data = request.POST.keys()
except Exception, inst:
msg = _("Could not find the POST data: %r : %s") % \
(request.POST, inst)
raise ValueError, msg
request_data = request_data[0]
- elif request.body:
- cls.log.debug('Retrieving request POST body: %r' % request.body)
+ else:
try:
request_data = request.body
except Exception, inst:
- msg = _("Could not find the POST data: %r : %s") % \
- (request.POST, inst)
+ msg = _("Could not extract request body data: %s") % \
+ (inst)
+ raise ValueError, msg
+ cls.log.debug('Retrieved request body: %r' % request.body)
+ if not request_data:
+ msg = _("No request body data")
raise ValueError, msg
if request_data:
request_data = json.loads(request_data, encoding='utf8')
http://bitbucket.org/okfn/ckan/changeset/8a84eff41415/
changeset: 8a84eff41415
branch: defect-1214-api-improvements
user: dread
date: 2011-07-07 14:16:46
summary: [tests]: Fixed ability to DELETE package without Content-Length header.
affected #: 1 file (8 bytes)
--- a/ckan/tests/functional/api/base.py Thu Jul 07 13:09:26 2011 +0100
+++ b/ckan/tests/functional/api/base.py Thu Jul 07 13:16:46 2011 +0100
@@ -392,7 +392,7 @@
environ['CONTENT_TYPE'] = content_type
if content_length is not None:
environ['CONTENT_LENGTH'] = str(content_length)
- environ['REQUEST_METHOD'] = 'POST'
+ environ['REQUEST_METHOD'] = request_method
environ['wsgi.input'] = StringIO(data)
if extra_environ:
environ.update(extra_environ)
http://bitbucket.org/okfn/ckan/changeset/557b8ac1688d/
changeset: 557b8ac1688d
branch: defect-1214-api-improvements
user: dread
date: 2011-07-07 14:31:33
summary: [logic]: Fix listing of packages for a tag - used to give package names even for apiv2.
affected #: 3 files (122 bytes)
--- a/ckan/logic/action/get.py Thu Jul 07 13:16:46 2011 +0100
+++ b/ckan/logic/action/get.py Thu Jul 07 13:31:33 2011 +0100
@@ -212,7 +212,7 @@
def tag_show(context):
model = context['model']
- api = context.get('api') or '1'
+ api = context.get('api_version') or '1'
id = context['id']
ref_package_by = 'id' if api == '2' else 'name'
obj = model.Tag.get(id) #TODO tags
--- a/ckan/tests/functional/api/base.py Thu Jul 07 13:16:46 2011 +0100
+++ b/ckan/tests/functional/api/base.py Thu Jul 07 13:31:33 2011 +0100
@@ -240,9 +240,10 @@
def assert_msg_represents_russian(self, msg):
data = self.loads(msg)
pkgs = set(data)
- expected_pkgs = set(['annakarenina', 'warandpeace'])
- missing_pkgs = expected_pkgs - pkgs
- assert not missing_pkgs, missing_pkgs
+ expected_pkgs = set([self.package_ref_from_name('annakarenina'),
+ self.package_ref_from_name('warandpeace')])
+ differences = expected_pkgs ^ pkgs
+ assert not differences, '%r != %r' % (pkgs, expected_pkgs)
def data_from_res(self, res):
return self.loads(res.body)
--- a/ckan/tests/functional/api/model/test_package.py Thu Jul 07 13:16:46 2011 +0100
+++ b/ckan/tests/functional/api/model/test_package.py Thu Jul 07 13:31:33 2011 +0100
@@ -35,6 +35,7 @@
res = self.app.post(offset, params=postparams,
status=self.STATUS_201_CREATED,
extra_environ=self.extra_environ)
+
# Check the value of the Location header.
location = res.header('Location')
assert offset in location
http://bitbucket.org/okfn/ckan/changeset/164d4260f37e/
changeset: 164d4260f37e
branch: defect-1214-api-improvements
user: dread
date: 2011-07-07 18:50:53
summary: [logic]: Fix returned package and group on update. Add test for PUT of a package.
affected #: 3 files (2.7 KB)
--- a/ckan/logic/action/update.py Thu Jul 07 13:31:33 2011 +0100
+++ b/ckan/logic/action/update.py Thu Jul 07 17:50:53 2011 +0100
@@ -6,7 +6,12 @@
from ckan.plugins import PluginImplementations, IGroupController, IPackageController
from ckan.logic import NotFound, check_access, NotAuthorized, ValidationError
from ckan.lib.base import _
-from ckan.lib.dictization.model_dictize import group_dictize, package_dictize
+from ckan.lib.dictization.model_dictize import (package_dictize,
+ package_to_api1,
+ package_to_api2,
+ group_dictize,
+ group_to_api1,
+ group_to_api2)
from ckan.lib.dictization.model_save import (group_api_to_dict,
package_api_to_dict,
group_dict_save,
@@ -274,19 +279,38 @@
model = context['model']
id = context["id"]
+ api = context.get('api_version') or '1'
pkg = model.Package.get(id)
context["package"] = pkg
context["allow_partial_update"] = True
dictized_package = package_api_to_dict(data_dict, context)
- return package_update(dictized_package, context)
+ dictized_after = package_update(dictized_package, context)
+
+ pkg = context['package']
+
+ if api == '1':
+ package_dict = package_to_api1(pkg, context)
+ else:
+ package_dict = package_to_api2(pkg, context)
+
+ return package_dict
def group_update_rest(data_dict, context):
model = context['model']
id = context["id"]
+ api = context.get('api_version') or '1'
group = model.Group.get(id)
context["group"] = group
context["allow_partial_update"] = True
dictized_package = group_api_to_dict(data_dict, context)
- return group_update(dictized_package, context)
+ dictized_after = group_update(dictized_package, context)
+ group = context['group']
+
+ if api == '1':
+ group_dict = group_to_api1(group, context)
+ else:
+ group_dict = group_to_api2(group, context)
+
+ return group_dict
--- a/ckan/tests/functional/api/model/test_package.py Thu Jul 07 13:31:33 2011 +0100
+++ b/ckan/tests/functional/api/model/test_package.py Thu Jul 07 17:50:53 2011 +0100
@@ -1,3 +1,5 @@
+import copy
+
from nose.tools import assert_equal
from ckan.tests.functional.api.base import BaseModelApiTestCase
@@ -36,6 +38,14 @@
status=self.STATUS_201_CREATED,
extra_environ=self.extra_environ)
+ # Check the returned package is as expected
+ pkg = self.loads(res.body)
+ assert_equal(pkg['name'], self.package_fixture_data['name'])
+ assert_equal(pkg['title'], self.package_fixture_data['title'])
+ assert_equal(set(pkg['tags']), set(self.package_fixture_data['tags']))
+ assert_equal(len(pkg['resources']), len(self.package_fixture_data['resources']))
+ assert_equal(pkg['extras'], self.package_fixture_data['extras'])
+
# Check the value of the Location header.
location = res.header('Location')
assert offset in location
@@ -103,8 +113,19 @@
package = self.get_package_by_name(self.package_fixture_data['name'])
assert package
self.assert_equal(package.title, self.package_fixture_data['title'])
+
+ def test_register_post_json(self):
+ assert not self.get_package_by_name(self.package_fixture_data['name'])
+ offset = self.package_offset()
+ data = self.dumps(self.package_fixture_data)
+ res = self.post_json(offset, data, status=self.STATUS_201_CREATED,
+ extra_environ=self.extra_environ)
+ # Check the database record.
+ self.remove()
+ package = self.get_package_by_name(self.package_fixture_data['name'])
+ assert package
+ self.assert_equal(package.title, self.package_fixture_data['title'])
-
def test_register_post_bad_request(self):
test_params = {
'name':u'testpackage06_400',
@@ -201,7 +222,8 @@
def create_package_roles_revision(self, package_data):
self.create_package(admins=[self.user], data=package_data)
- def assert_package_update_ok(self, package_ref_attribute):
+ def assert_package_update_ok(self, package_ref_attribute,
+ method_str):
old_fixture_data = {
'name': self.package_fixture_data['name'],
'url': self.package_fixture_data['url'],
@@ -240,8 +262,20 @@
self.create_package_roles_revision(old_fixture_data)
offset = self.package_offset(old_fixture_data['name'])
params = '%s=1' % self.dumps(new_fixture_data)
- res = self.app.post(offset, params=params, status=self.STATUS_200_OK,
- extra_environ=self.extra_environ)
+ method_func = getattr(self.app, method_str)
+ res = method_func(offset, params=params, status=self.STATUS_200_OK,
+ extra_environ=self.extra_environ)
+
+ # Check the returned package is as expected
+ pkg = self.loads(res.body)
+ assert_equal(pkg['name'], new_fixture_data['name'])
+ assert_equal(pkg['title'], new_fixture_data['title'])
+ assert_equal(set(pkg['tags']), set(new_fixture_data['tags']))
+ assert_equal(len(pkg['resources']), len(new_fixture_data['resources']))
+ expected_extras = copy.deepcopy(new_fixture_data['extras'])
+ del expected_extras['key2']
+ expected_extras['key1'] = old_fixture_data['extras']['key1']
+ assert_equal(pkg['extras'], expected_extras)
# Check submitted field have changed.
self.remove()
@@ -286,10 +320,16 @@
assert not package.extras.has_key('key2')
def test_package_update_ok_by_id(self):
- self.assert_package_update_ok('id')
+ self.assert_package_update_ok('id', 'post')
def test_entity_update_ok_by_name(self):
- self.assert_package_update_ok('name')
+ self.assert_package_update_ok('name', 'post')
+
+ def test_package_update_ok_by_id_by_put(self):
+ self.assert_package_update_ok('id', 'put')
+
+ def test_entity_update_ok_by_name_by_put(self):
+ self.assert_package_update_ok('name', 'put')
def test_entity_update_conflict(self):
package1_name = self.package_fixture_data['name']
--- a/doc/api/model_formats.rst.inc Thu Jul 07 13:31:33 2011 +0100
+++ b/doc/api/model_formats.rst.inc Thu Jul 07 17:50:53 2011 +0100
@@ -26,6 +26,6 @@
* When you update an object, fields that you don't supply will remain as they were before.
- * To delete an 'extra' key-value pair, supply the key with a None value.
+ * To delete an 'extra' key-value pair, supply the key with JSON value: ``null``
* When you read a package then some additional information is supplied that cannot current be adjusted throught the CKAN API. This includes info on Package Relationship ('relationships'), Group membership ('groups'), ratings ('ratings_average' and 'ratings_count'), full URL of the package in CKAN ('ckan_url') and Package ID ('id'). This is purely a convenience for clients, and only forms part of the Package on GET.
http://bitbucket.org/okfn/ckan/changeset/bf7d2162daf2/
changeset: bf7d2162daf2
branch: defect-1214-api-improvements
user: dread
date: 2011-07-07 19:32:12
summary: [tests]: Tracking down problem deleting last package extra. Left a failing test.
affected #: 2 files (3.1 KB)
--- a/ckan/logic/action/update.py Thu Jul 07 17:50:53 2011 +0100
+++ b/ckan/logic/action/update.py Thu Jul 07 18:32:12 2011 +0100
@@ -176,7 +176,7 @@
if 'message' in context:
rev.message = context['message']
else:
- rev.message = _(u'REST API: Create object %s') % data.get("name")
+ rev.message = _(u'REST API: Update object %s') % data.get("name")
pkg = package_dict_save(data, context)
@@ -260,7 +260,7 @@
if 'message' in context:
rev.message = context['message']
else:
- rev.message = _(u'REST API: Create object %s') % data.get("name")
+ rev.message = _(u'REST API: Update object %s') % data.get("name")
group = group_dict_save(data, context)
--- a/ckan/tests/functional/api/model/test_package.py Thu Jul 07 17:50:53 2011 +0100
+++ b/ckan/tests/functional/api/model/test_package.py Thu Jul 07 18:32:12 2011 +0100
@@ -260,7 +260,13 @@
'tags': [u'tag1', u'tag2', u'tag4', u'tag5'],
}
self.create_package_roles_revision(old_fixture_data)
- offset = self.package_offset(old_fixture_data['name'])
+ pkg = self.get_package_by_name(old_fixture_data['name'])
+ # This is the one occasion where we reference package explicitly
+ # by name or ID, rather than use the value from self.ref_package_by
+ # because you should be able to specify the package both ways round
+ # for both versions of the API.
+ package_ref = getattr(pkg, package_ref_attribute)
+ offset = self.offset('/rest/package/%s' % package_ref)
params = '%s=1' % self.dumps(new_fixture_data)
method_func = getattr(self.app, method_str)
res = method_func(offset, params=params, status=self.STATUS_200_OK,
@@ -331,6 +337,68 @@
def test_entity_update_ok_by_name_by_put(self):
self.assert_package_update_ok('name', 'put')
+ def test_package_update_delete_last_extra(self):
+ old_fixture_data = {
+ 'name': self.package_fixture_data['name'],
+ 'extras': {
+ u'key1': u'val1',
+ },
+ }
+ new_fixture_data = {
+ 'name':u'somethingnew',
+ 'extras': {
+ u'key1': None,
+ },
+ }
+ self.create_package_roles_revision(old_fixture_data)
+ offset = self.package_offset(old_fixture_data['name'])
+ params = '%s=1' % self.dumps(new_fixture_data)
+ res = self.app.post(offset, params=params, status=self.STATUS_200_OK,
+ extra_environ=self.extra_environ)
+
+ # Check the returned package is as expected
+ pkg = self.loads(res.body)
+ assert_equal(pkg['name'], new_fixture_data['name'])
+ expected_extras = copy.deepcopy(new_fixture_data['extras'])
+ del expected_extras['key1']
+ assert_equal(pkg['extras'], expected_extras)
+
+ # Check extra was deleted
+ self.remove()
+ package = self.get_package_by_name(new_fixture_data['name'])
+ # - title
+ self.assert_equal(package.extras, [])
+
+ def test_package_update_do_not_delete_last_extra(self):
+ old_fixture_data = {
+ 'name': self.package_fixture_data['name'],
+ 'extras': {
+ u'key1': u'val1',
+ },
+ }
+ new_fixture_data = {
+ 'name':u'somethingnew',
+ 'extras': {}, # no extras specified, but existing
+ # ones should be left alone
+ }
+ self.create_package_roles_revision(old_fixture_data)
+ offset = self.package_offset(old_fixture_data['name'])
+ params = '%s=1' % self.dumps(new_fixture_data)
+ res = self.app.post(offset, params=params, status=self.STATUS_200_OK,
+ extra_environ=self.extra_environ)
+
+ # Check the returned package is as expected
+ pkg = self.loads(res.body)
+ assert_equal(pkg['name'], new_fixture_data['name'])
+ expected_extras = {u'key1': u'val1'} # should not be deleted
+ assert_equal(pkg['extras'], expected_extras)
+
+ # Check extra was not deleted
+ self.remove()
+ package = self.get_package_by_name(new_fixture_data['name'])
+ # - title
+ assert len(package.extras) == 1, package.extras
+
def test_entity_update_conflict(self):
package1_name = self.package_fixture_data['name']
package1_data = {'name': package1_name}
@@ -341,6 +409,15 @@
package1_offset = self.package_offset(package1_name)
self.post(package1_offset, package2_data, self.STATUS_409_CONFLICT)
+ def test_entity_update_empty(self):
+ package1_name = self.package_fixture_data['name']
+ package1_data = {'name': package1_name}
+ package1 = self.create_package_roles_revision(package1_data)
+ package2_data = '' # this is the error
+ package1_offset = self.package_offset(package1_name)
+ self.app.put(package1_offset, package2_data,
+ status=self.STATUS_400_BAD_REQUEST)
+
def test_entity_delete_ok(self):
# create a package with package_fixture_data
if not self.get_package_by_name(self.package_fixture_data['name']):
Repository URL: https://bitbucket.org/okfn/ckan/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
More information about the ckan-changes
mailing list