Skip to content

Commit

Permalink
Merge branch 'release-v1.5.1c' of ssh://github.com/okfn/ckan into rel…
Browse files Browse the repository at this point in the history
…ease-v1.5.1c
  • Loading branch information
David Read committed Dec 21, 2011
2 parents 0226b33 + 9abdd09 commit 885e209
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 41 deletions.
2 changes: 2 additions & 0 deletions ckan/controllers/group.py
Expand Up @@ -62,6 +62,7 @@ def index(self):
c.page = Page(
collection=results,
page=request.params.get('page', 1),
url=h.pager_url,
items_per_page=20
)
return render('group/index.html')
Expand Down Expand Up @@ -99,6 +100,7 @@ def read(self, id):
c.page = Page(
collection=results,
page=request.params.get('page', 1),
url=h.pager_url,
items_per_page=50
)

Expand Down
1 change: 1 addition & 0 deletions ckan/controllers/revision.py
Expand Up @@ -116,6 +116,7 @@ def list(self):
c.page = Page(
collection=query,
page=request.params.get('page', 1),
url=h.pager_url,
items_per_page=20
)
return render('revision/list.html')
Expand Down
3 changes: 2 additions & 1 deletion ckan/controllers/user.py
Expand Up @@ -76,9 +76,10 @@ def index(self):
c.page = h.Page(
collection=users_list,
page=page,
url=h.pager_url,
item_count=users_list.count(),
items_per_page=LIMIT
)
)
return render('user/list.html')

def read(self, id=None):
Expand Down
10 changes: 6 additions & 4 deletions ckan/lib/dictization/model_dictize.py
Expand Up @@ -263,10 +263,12 @@ def package_to_api1(pkg, context):
site_url = config.get('ckan.site_url', None)
if site_url:
dictized['ckan_url'] = '%s/dataset/%s' % (site_url, pkg.name)
dictized['metadata_modified'] = pkg.metadata_modified.isoformat() \
if pkg.metadata_modified else None
dictized['metadata_created'] = pkg.metadata_created.isoformat() \
if pkg.metadata_created else None
metadata_modified = pkg.metadata_modified
dictized['metadata_modified'] = metadata_modified.isoformat() \
if metadata_modified else None
metadata_created = pkg.metadata_created
dictized['metadata_created'] = metadata_created.isoformat() \
if metadata_created else None

subjects = dictized.pop("relationships_as_subject")
objects = dictized.pop("relationships_as_object")
Expand Down
20 changes: 8 additions & 12 deletions ckan/lib/helpers.py
Expand Up @@ -236,29 +236,25 @@ def linked_gravatar(email_hash, size=100, default="mm"):
def gravatar(email_hash, size=100, default="mm"):
return literal('<img src="http://gravatar.com/avatar/%s?s=%d&amp;d=%s" />' % (email_hash, size, default))

def pager_url(page, partial=None, **kwargs):
routes_dict = url.environ['pylons.routes_dict']
kwargs['controller'] = routes_dict['controller']
kwargs['action'] = routes_dict['action']
if routes_dict.get('id'):
kwargs['id'] = routes_dict['id']
kwargs['page'] = page
return url(**kwargs)

class Page(paginate.Page):

def _page_url(self, page, partial=None, **kwargs):
routes_dict = url.environ['pylons.routes_dict']
kwargs['controller'] = routes_dict['controller']
kwargs['action'] = routes_dict['action']
if routes_dict.get('id'):
kwargs['id'] = routes_dict['id']
kwargs['page'] = page
return url(**kwargs)

# Curry the pager method of the webhelpers.paginate.Page class, so we have
# our custom layout set as default.
def pager(self, *args, **kwargs):
self._url_generator = self._page_url
kwargs.update(
format=u"<div class='pager'>$link_previous ~2~ $link_next</div>",
symbol_previous=u'« Prev', symbol_next=u'Next »'
)
return super(Page, self).pager(*args, **kwargs)


def render_datetime(datetime_):
'''Render a datetime object or timestamp string as a pretty string
(Y-m-d H:m).
Expand Down
2 changes: 1 addition & 1 deletion ckan/model/group.py
Expand Up @@ -12,7 +12,7 @@

__all__ = ['group_table', 'Group', 'package_revision_table',
'PackageGroup', 'GroupRevision', 'PackageGroupRevision',
'package_group_revision_table']
'package_group_table', 'package_group_revision_table']

package_group_table = Table('package_group', metadata,
Column('id', UnicodeText, primary_key=True, default=make_uuid),
Expand Down
28 changes: 9 additions & 19 deletions ckan/model/package.py
Expand Up @@ -454,17 +454,14 @@ def diff(self, to_revision=None, from_revision=None):
results[key] = value_diff
return results

@staticmethod
def last_modified(*av):
@property
def metadata_modified(self):
"""
Return most recent timestamp for a package revision, with optionally
extra where clause.
Return most recent timestamp for revisions related to this package.
NB Excludes changes to the package's groups
"""
from ckan import model
where = []
for arg in av:
if isinstance(arg, expression.ClauseElement) or isinstance(arg, basestring):
where.append(arg)
where = [model.package_table.c.id == self.id]
where_clauses = [
and_(model.package_table.c.revision_id == model.revision_table.c.id, *where),
and_(model.package_extra_table.c.package_id == model.package_table.c.id,
Expand All @@ -490,19 +487,12 @@ def last_modified(*av):
result = conn.execute(query).fetchone()
if result:
result_datetime = iso_date_to_datetime_for_sqlite(result[0])
timestamp = result_datetime.utctimetuple()
timestamp_without_usecs = result_datetime.utctimetuple()
usecs = float(result_datetime.microsecond) / 1e6
else:
timestamp, usecs = gmtime(), 0
# use timegm instead of mktime, because we don't want it localised
return timegm(timestamp) + usecs
# use timegm instead of mktime, because we don't want it localised
timestamp_float = timegm(timestamp_without_usecs) + usecs
return datetime.datetime.utcfromtimestamp(timestamp_float)

@property
def metadata_modified(self):
import ckan.model as model
epochtime = self.last_modified(model.package_table.c.id==self.id)
return datetime.datetime.utcfromtimestamp(epochtime)

@property
def metadata_created(self):
import ckan.model as model
Expand Down
2 changes: 1 addition & 1 deletion ckan/templates/package/read_core.html
Expand Up @@ -23,7 +23,7 @@ <h3>Resources</h3>
<tr rel="dcat:distribution" resource="_:res${res.id}"
typeof="dcat:Distribution">
<td>
<a href="${res.get('url', '')}" rel="dcat:accessURL" target="_blank">
<a class="resource-url-analytics" href="${res.get('url', '')}" rel="dcat:accessURL" target="_blank">
<py:if test="res.get('name') or res.get('description')">
<span property="rdfs:label">${res.get('description') or res.get('name')}</span>
</py:if>
Expand Down
45 changes: 45 additions & 0 deletions ckan/tests/functional/api/test_action.py
Expand Up @@ -934,3 +934,48 @@ def test_3_bad_param(self):
status=400)
assert '"message": "Search Query is invalid:' in res.body, res.body
assert '"Invalid search parameters: [u\'weird_param\']' in res.body, res.body

def test_4_sort_by_metadata_modified(self):
search_params = '%s=1' % json.dumps({
'q': '*:*',
'fl': 'name, metadata_modified',
'sort': u'metadata_modified desc'
})

# modify warandpeace, check that it is the first search result
rev = model.repo.new_revision()
pkg = model.Package.get('warandpeace')
pkg.title = "War and Peace [UPDATED]"
model.repo.commit_and_remove()

res = self.app.post('/api/action/package_search', params=search_params)
result = json.loads(res.body)['result']
result_names = [r['name'] for r in result['results']]
assert result_names == ['warandpeace', 'annakarenina'], result_names

# modify annakarenina, check that it is the first search result
rev = model.repo.new_revision()
pkg = model.Package.get('annakarenina')
pkg.title = "A Novel By Tolstoy [UPDATED]"
model.repo.commit_and_remove()

res = self.app.post('/api/action/package_search', params=search_params)
result = json.loads(res.body)['result']
result_names = [r['name'] for r in result['results']]
assert result_names == ['annakarenina', 'warandpeace'], result_names

# add a tag to warandpeace, check that it is the first result
pkg = model.Package.get('warandpeace')
pkg_params = '%s=1' % json.dumps({'id': pkg.id})
res = self.app.post('/api/action/package_show', params=pkg_params)
pkg_dict = json.loads(res.body)['result']
pkg_dict['tags'].append({'name': 'new-tag'})
pkg_params = '%s=1' % json.dumps(pkg_dict)
res = self.app.post('/api/action/package_update', params=pkg_params,
extra_environ={'Authorization': 'tester'})

res = self.app.post('/api/action/package_search', params=search_params)
result = json.loads(res.body)['result']
result_names = [r['name'] for r in result['results']]
assert result_names == ['warandpeace', 'annakarenina'], result_names

12 changes: 11 additions & 1 deletion ckan/tests/functional/test_pagination.py
@@ -1,10 +1,11 @@
from ckan.lib.create_test_data import CreateTestData
import ckan.model as model
from ckan.tests import TestController, url_for
from ckan.tests import TestController, url_for, setup_test_search_index

class TestPagination(TestController):
@classmethod
def setup_class(cls):
setup_test_search_index()
model.repo.init_db()

# no. entities per page is hardcoded into the controllers, so
Expand All @@ -30,6 +31,15 @@ def setup_class(cls):
def teardown_class(self):
model.repo.rebuild_db()

def test_search(self):
res = self.app.get(url_for(controller='package', action='search', q='groups:group_00'))
assert 'href="/dataset?q=groups%3Agroup_00&amp;page=2"' in res
assert 'href="/dataset/package_19"' in res

res = self.app.get(url_for(controller='package', action='search', q='groups:group_00', page=2))
assert 'href="/dataset?q=groups%3Agroup_00&amp;page=1"' in res
assert 'href="/dataset/package_20"' in res

def test_group_index(self):
res = self.app.get(url_for(controller='group', action='index'))
assert 'href="/group?page=2"' in res
Expand Down
55 changes: 54 additions & 1 deletion ckan/tests/models/test_package.py
Expand Up @@ -128,7 +128,7 @@ def test_metadata_created_and_modified(self):
assert package.metadata_modified == created_timestamp,\
(package.metadata_modified, created_timestamp)

# update the package it
# update the package
rev = model.repo.new_revision()
package = model.Package.by_name(name)
package.title = "test_metadata_new_title"
Expand All @@ -138,6 +138,59 @@ def test_metadata_created_and_modified(self):
package = model.Package.by_name(name)
assert package.metadata_created == created_timestamp
assert package.metadata_modified == modified_timestamp
last_modified_timestamp = modified_timestamp

# update a package's tag
rev = model.repo.new_revision()
package = model.Package.by_name(name)
package.add_tag_by_name('new-tag')
modified_timestamp = model.Session().revision.timestamp
assert modified_timestamp != last_modified_timestamp
model.repo.commit_and_remove()

package = model.Package.by_name(name)
assert package.metadata_created == created_timestamp
assert package.metadata_modified == modified_timestamp
last_modified_timestamp = modified_timestamp

# update a package's extra
rev = model.repo.new_revision()
package = model.Package.by_name(name)
package.extras['new-key'] = 'value'
modified_timestamp = model.Session().revision.timestamp
assert modified_timestamp != last_modified_timestamp
model.repo.commit_and_remove()

package = model.Package.by_name(name)
assert package.metadata_created == created_timestamp
assert package.metadata_modified == modified_timestamp
last_modified_timestamp = modified_timestamp

# update a package's relationship
rev = model.repo.new_revision()
package = model.Package.by_name(name)
anna = model.Package.by_name(u'annakarenina')
package.add_relationship(u'child_of', anna)
modified_timestamp = model.Session().revision.timestamp
assert modified_timestamp != last_modified_timestamp
model.repo.commit_and_remove()

package = model.Package.by_name(name)
assert package.metadata_created == created_timestamp
assert package.metadata_modified == modified_timestamp
last_modified_timestamp = modified_timestamp

# update a package's group - NB no change this time
rev = model.repo.new_revision()
group = model.Group.by_name('roger')
group.add_package_by_name(name)
modified_timestamp = model.Session().revision.timestamp
assert modified_timestamp != last_modified_timestamp
model.repo.commit_and_remove()

package = model.Package.by_name(name)
assert package.metadata_created == created_timestamp
assert package.metadata_modified == last_modified_timestamp # no change


class TestPackageWithTags:
Expand Down
2 changes: 1 addition & 1 deletion doc/apiv3.rst
Expand Up @@ -369,7 +369,7 @@ These parameters are all the standard SOLR syntax (in contrast to the syntax use
| | || fl=* | |
+-----------------------+---------------+----------------------------------+----------------------------------+
| sort | field name, || sort=name asc | Changes the sort order according |
| | asc / dec | | to the field and direction given.|
| | asc / dec || sort=metadata_modified asc | to the field and direction given.|
| | | | default: score desc, name asc |
+-----------------------+---------------+----------------------------------+----------------------------------+
| start, rows | result-int | start=40&amp;rows=20 | Pagination options. Start is the |
Expand Down

0 comments on commit 885e209

Please sign in to comment.