Skip to content

Commit

Permalink
Merge pull request #2066 from ckan/2063-reimpl-rdf-template
Browse files Browse the repository at this point in the history
Reimplement the read.rdf template lost in genshi purge
  • Loading branch information
David Read committed Nov 21, 2014
2 parents c76a487 + 133219b commit 36718f2
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 33 deletions.
19 changes: 9 additions & 10 deletions ckan/controllers/package.py
Expand Up @@ -311,10 +311,10 @@ def pager_url(q=None, page=None):
extra_vars={'dataset_type': package_type})

def _content_type_from_extension(self, ext):
ct, mu, ext = accept.parse_extension(ext)
ct, ext = accept.parse_extension(ext)
if not ct:
return None, None, None,
return ct, ext, (NewTextTemplate, MarkupTemplate)[mu]
return None, None
return ct, ext

def _content_type_from_accept(self):
"""
Expand All @@ -323,8 +323,8 @@ def _content_type_from_accept(self):
it accurately. TextTemplate must be used for non-xml templates
whilst all that are some sort of XML should use MarkupTemplate.
"""
ct, mu, ext = accept.parse_header(request.headers.get('Accept', ''))
return ct, ext, (NewTextTemplate, MarkupTemplate)[mu]
ct, ext = accept.parse_header(request.headers.get('Accept', ''))
return ct, ext

def resources(self, id):
package_type = self._get_package_type(id.split('@')[0])
Expand Down Expand Up @@ -356,16 +356,15 @@ def resources(self, id):

def read(self, id, format='html'):
if not format == 'html':
ctype, extension, loader = \
ctype, extension = \
self._content_type_from_extension(format)
if not ctype:
# An unknown format, we'll carry on in case it is a
# revision specifier and re-constitute the original id
id = "%s.%s" % (id, format)
ctype, format, loader = "text/html; charset=utf-8", "html", \
MarkupTemplate
ctype, format = "text/html; charset=utf-8", "html"
else:
ctype, format, loader = self._content_type_from_accept()
ctype, format = self._content_type_from_accept()

response.headers['Content-Type'] = ctype

Expand Down Expand Up @@ -423,7 +422,7 @@ def read(self, id, format='html'):
template = template[:template.index('.') + 1] + format

try:
return render(template, loader_class=loader,
return render(template,
extra_vars={'dataset_type': package_type})
except ckan.lib.render.TemplateNotFound:
msg = _("Viewing {package_type} datasets in {format} format is "
Expand Down
10 changes: 5 additions & 5 deletions ckan/lib/accept.py
Expand Up @@ -9,10 +9,10 @@
accept_re = re.compile("^(?P<ct>[^;]+)[ \t]*(;[ \t]*q=(?P<q>[0-9.]+)){0,1}$")

accept_types = {
# Name : ContentType, Is Markup?, Extension
"text/html": ("text/html; charset=utf-8", True, 'html'),
"text/n3": ("text/n3; charset=utf-8", False, 'n3'),
"application/rdf+xml": ("application/rdf+xml; charset=utf-8", True, 'rdf'),
# Name : ContentType, Extension
"text/html": ("text/html; charset=utf-8", 'html'),
"text/n3": ("text/n3; charset=utf-8", 'n3'),
"application/rdf+xml": ("application/rdf+xml; charset=utf-8", 'rdf'),
}
accept_by_extension = {
"rdf": "application/rdf+xml",
Expand All @@ -28,7 +28,7 @@ def parse_extension(file_ext):
ext = accept_by_extension.get(file_ext, None)
if ext:
return accept_types[ext]
return (None, None, None,)
return (None, None)


def parse_header(accept_header=''):
Expand Down
32 changes: 32 additions & 0 deletions ckan/new_tests/controllers/test_package.py
Expand Up @@ -178,3 +178,35 @@ def test_inexistent_resource_view_page_returns_not_found_code(self):

app = self._get_test_app()
app.get(url, status=404)


class TestPackageRead(helpers.FunctionalTestBase):
@classmethod
def setup_class(cls):
super(cls, cls).setup_class()
helpers.reset_db()

def setup(self):
model.repo.rebuild_db()

def test_read_rdf(self):
dataset1 = factories.Dataset()

offset = url_for(controller='package', action='read',
id=dataset1['name']) + ".rdf"
app = self._get_test_app()
res = app.get(offset, status=200)

assert 'dcat' in res, res
assert '{{' not in res, res

def test_read_n3(self):
dataset1 = factories.Dataset()

offset = url_for(controller='package', action='read',
id=dataset1['name']) + ".n3"
app = self._get_test_app()
res = app.get(offset, status=200)

assert 'dcat' in res, res
assert '{{' not in res, res
4 changes: 2 additions & 2 deletions ckan/plugins/interfaces.py
Expand Up @@ -963,8 +963,8 @@ def read_template(self):
``'package/read.html'``.
If the user requests the dataset in a format other than HTML
(CKAN supports returning datasets in RDF or N3 format by appending .rdf
or .n3 to the dataset read URL, see
(CKAN supports returning datasets in RDF/XML or N3 format by appending
.rdf or .n3 to the dataset read URL, see
:doc:`/maintaining/linked-data-and-rdf`) then CKAN will try to render a
template file with the same path as returned by this function, but a
different filename extension, e.g. ``'package/read.rdf'``. If your
Expand Down
45 changes: 45 additions & 0 deletions ckan/templates/package/read.n3
@@ -0,0 +1,45 @@
@prefix : <http://www.w3.org/2000/01/rdf-schema#> .
@prefix dcat: <http://www.w3.org/ns/dcat#> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

<{{ h.url_for(controller='package',action='read',id=c.pkg_dict['name'], qualified=True)}}>
a dcat:Dataset;
dct:description "{{c.pkg_dict['notes']}}";
dct:identifier "{{c.pkg_dict['name']}}";
dct:relation [
rdf:value "";
:label "change_note" ],
[
rdf:value "";
:label "definition_note" ],
[
rdf:value "";
:label "editorial_note" ],
[
rdf:value "";
:label "example_note" ],
[
rdf:value "";
:label "history_note" ],
[
rdf:value "";
:label "scope_note" ],
[
rdf:value "";
:label "skos_note" ],
[
rdf:value "";
:label "temporal_granularity" ],
[
rdf:value "";
:label "type_of_dataset" ],
[
rdf:value "";
:label "update_frequency" ];
dct:title "{{c.pkg_dict['title']}}";
:label "{{c.pkg_dict['name']}}";
= <urn:uuid:{{c.pkg_dict['id']}}>;
foaf:homepage <{{ h.url_for(controller='package',action='read',id=c.pkg_dict['name'], qualified=True)}}> .
71 changes: 71 additions & 0 deletions ckan/templates/package/read.rdf
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dcat="http://www.w3.org/ns/dcat#"
xmlns:dct="http://purl.org/dc/terms/"
>
<dcat:Dataset rdf:about="{{ h.url_for(controller='package',action='read',id=c.pkg_dict['name'], qualified=True) }}">
<owl:sameAs rdf:resource="urn:uuid:{{c.pkg_dict['id']}}"/>
<dct:description>{{c.pkg_dict['notes']}}</dct:description>
{% for tag_dict in c.pkg_dict['tags'] %}
<dcat:keyword>{{ tag_dict["name"] }}</dcat:keyword>
{% endfor %}
<foaf:homepage rdf:resource="{{ h.url_for(controller='package',action='read',id=c.pkg_dict['name'], qualified=True)}}"/>
<rdfs:label>{{c.pkg_dict['name']}}</rdfs:label>

<dct:identifier>{{c.pkg_dict['name']}}</dct:identifier>
<dct:title>{{c.pkg_dict['title']}}</dct:title>
{% for rsc_dict in c.pkg_dict['resources'] %}
<dcat:distribution>
<dcat:Distribution>
<dcat:accessURL rdf:resource="{{ rsc_dict['url'] }}"/>
{% if rsc_dict.get('format')%}
<dct:format>
<dct:IMT>
<rdf:value>{{rsc_dict.get('format')}}</rdf:value>
<rdfs:label>{{rsc_dict.get('format')}}</rdfs:label>
</dct:IMT>
</dct:format>
{% endif %}
{% if rsc_dict.get('name')%}<dct:title>{{rsc_dict.get('name')}}</dct:title>{% endif %}
</dcat:Distribution>
</dcat:distribution>
{% endfor %}
{% if c.pkg_dict.get('author', None) %}
<dct:creator>
<rdf:Description>
<foaf:name>{{ c.pkg_dict['author'] }}</foaf:name>
{% if c.pkg_dict.get('maintainer_email', None)%}
<foaf:mbox rdf:resource="mailto:{{c.pkg_dict['author_email']}}"/>
{% endif %}
</rdf:Description>
</dct:creator>
{% endif %}
{% if c.pkg_dict.get('maintainer', None)%}
<dct:contributor>
<rdf:Description>
<foaf:name>{{ c.pkg_dict['maintainer'] }}</foaf:name>
{% if c.pkg_dict.get('maintainer_email', None) %}
<foaf:mbox rdf:resource="mailto:{{c.pkg_dict['maintainer_email']}}"/>
{% endif %}
</rdf:Description>
</dct:contributor>
{% endif %}

{% if c.pkg_dict.get('license_url', None) %}
<dct:rights rdf:resource="{{c.pkg_dict['license_url']}}"/>
{% endif %}

{% for extra_dict in c.pkg_dict.get('extras',None) %}
<dct:relation>
<rdf:Description>
<rdfs:label>{{extra_dict.get('key','')}}</rdfs:label>
<rdf:value>{{extra_dict.get('value','')}}</rdf:value>
</rdf:Description>
</dct:relation>
{% endfor %}
</dcat:Dataset>
</rdf:RDF>
24 changes: 8 additions & 16 deletions ckan/tests/lib/test_accept.py
Expand Up @@ -4,55 +4,47 @@

class TestAccept:
def test_accept_invalid(self):
ct, markup, ext = accept.parse_header(None)
ct, ext = accept.parse_header(None)
assert_equal( ct, "text/html; charset=utf-8")
assert_equal( markup, True)
assert_equal( ext, "html")

def test_accept_invalid2(self):
ct, markup, ext = accept.parse_header("")
ct, ext = accept.parse_header("")
assert_equal( ct, "text/html; charset=utf-8")
assert_equal( markup, True)
assert_equal( ext, "html")

def test_accept_invalid3(self):
ct, markup, ext = accept.parse_header("wombles")
ct, ext = accept.parse_header("wombles")
assert_equal( ct, "text/html; charset=utf-8")
assert_equal( markup, True)
assert_equal( ext, "html")


def test_accept_valid(self):
a = "text/turtle,application/turtle,application/rdf+xml,text/plain;q=0.8,*/*;q=.5"
ct, markup, ext = accept.parse_header(a)
ct, ext = accept.parse_header(a)
assert_equal( ct, "application/rdf+xml; charset=utf-8")
assert_equal( markup, True)
assert_equal( ext, "rdf")

def test_accept_valid2(self):
a = "text/turtle,application/turtle,application/rdf+xml;q=0.9,text/plain;q=0.8,*/*;q=.5"
ct, markup, ext = accept.parse_header(a)
ct, ext = accept.parse_header(a)
assert_equal( ct, "application/rdf+xml; charset=utf-8")
assert_equal( markup, True)
assert_equal( ext, "rdf")

def test_accept_valid4(self):
a = "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
ct, markup, ext = accept.parse_header(a)
ct, ext = accept.parse_header(a)
assert_equal( ct, "text/html; charset=utf-8")
assert_equal( markup, True)
assert_equal( ext, "html")

def test_accept_valid5(self):
a = "application/rdf+xml;q=0.5,application/xhtml+xml,text/html;q=0.9"
ct, markup, ext = accept.parse_header(a)
ct, ext = accept.parse_header(a)
assert_equal( ct, "text/html; charset=utf-8")
assert_equal( markup, True)
assert_equal( ext, "html")

def test_accept_valid6(self):
a = "application/rdf+xml;q=0.9,application/xhtml+xml,text/html;q=0.5"
ct, markup, ext = accept.parse_header(a)
ct, ext = accept.parse_header(a)
assert_equal( ct, "application/rdf+xml; charset=utf-8")
assert_equal( markup, True)
assert_equal( ext, "rdf")

0 comments on commit 36718f2

Please sign in to comment.