udata 12.0.2.dev11__py3-none-any.whl → 12.0.2.dev13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of udata might be problematic. Click here for more details.
- udata/core/dataservices/api.py +5 -5
- udata/core/dataset/api.py +11 -5
- udata/core/organization/api.py +17 -13
- udata/core/organization/rdf.py +3 -3
- udata/core/site/api.py +27 -19
- udata/core/site/rdf.py +2 -2
- udata/rdf.py +4 -3
- udata/tests/api/test_dataservices_api.py +1 -57
- udata/tests/dataservice/test_dataservice_rdf.py +58 -0
- udata/tests/dataset/test_dataset_rdf.py +4 -4
- udata/tests/organization/test_organization_rdf.py +4 -4
- udata/tests/site/test_site_rdf.py +82 -23
- {udata-12.0.2.dev11.dist-info → udata-12.0.2.dev13.dist-info}/METADATA +1 -3
- {udata-12.0.2.dev11.dist-info → udata-12.0.2.dev13.dist-info}/RECORD +18 -18
- {udata-12.0.2.dev11.dist-info → udata-12.0.2.dev13.dist-info}/WHEEL +0 -0
- {udata-12.0.2.dev11.dist-info → udata-12.0.2.dev13.dist-info}/entry_points.txt +0 -0
- {udata-12.0.2.dev11.dist-info → udata-12.0.2.dev13.dist-info}/licenses/LICENSE +0 -0
- {udata-12.0.2.dev11.dist-info → udata-12.0.2.dev13.dist-info}/top_level.txt +0 -0
udata/core/dataservices/api.py
CHANGED
|
@@ -238,19 +238,19 @@ class DataserviceDatasetAPI(API):
|
|
|
238
238
|
class DataserviceRdfAPI(API):
|
|
239
239
|
@api.doc("rdf_dataservice")
|
|
240
240
|
def get(self, dataservice):
|
|
241
|
-
|
|
242
|
-
url = url_for("api.dataservice_rdf_format", dataservice=dataservice.id,
|
|
241
|
+
_format = RDF_EXTENSIONS[negociate_content()]
|
|
242
|
+
url = url_for("api.dataservice_rdf_format", dataservice=dataservice.id, _format=_format)
|
|
243
243
|
return redirect(url)
|
|
244
244
|
|
|
245
245
|
|
|
246
246
|
@ns.route(
|
|
247
|
-
"/<dataservice:dataservice>/rdf.<
|
|
247
|
+
"/<dataservice:dataservice>/rdf.<_format>", endpoint="dataservice_rdf_format", doc=common_doc
|
|
248
248
|
)
|
|
249
249
|
@api.response(404, "Dataservice not found")
|
|
250
250
|
@api.response(410, "Dataservice has been deleted")
|
|
251
251
|
class DataserviceRdfFormatAPI(API):
|
|
252
252
|
@api.doc("rdf_dataservice_format")
|
|
253
|
-
def get(self, dataservice: Dataservice,
|
|
253
|
+
def get(self, dataservice: Dataservice, _format):
|
|
254
254
|
if not dataservice.permissions["edit"].can():
|
|
255
255
|
if dataservice.private:
|
|
256
256
|
api.abort(404)
|
|
@@ -260,7 +260,7 @@ class DataserviceRdfFormatAPI(API):
|
|
|
260
260
|
resource = dataservice_to_rdf(dataservice)
|
|
261
261
|
# bypass flask-restplus make_response, since graph_response
|
|
262
262
|
# is handling the content negociation directly
|
|
263
|
-
return make_response(*graph_response(resource,
|
|
263
|
+
return make_response(*graph_response(resource, _format))
|
|
264
264
|
|
|
265
265
|
|
|
266
266
|
@ns.route("/<id>/followers/", endpoint="dataservice_followers")
|
udata/core/dataset/api.py
CHANGED
|
@@ -290,6 +290,12 @@ community_parser.add_argument(
|
|
|
290
290
|
|
|
291
291
|
common_doc = {"params": {"dataset": "The dataset ID or slug"}}
|
|
292
292
|
|
|
293
|
+
# Build catalog_parser from DatasetApiParser parser with a default page_size of 100
|
|
294
|
+
catalog_parser = DatasetApiParser().parser
|
|
295
|
+
catalog_parser.replace_argument(
|
|
296
|
+
"page_size", type=int, location="args", default=100, help="The page size"
|
|
297
|
+
)
|
|
298
|
+
|
|
293
299
|
|
|
294
300
|
@ns.route("/", endpoint="datasets")
|
|
295
301
|
class DatasetListAPI(API):
|
|
@@ -431,17 +437,17 @@ class DatasetFeaturedAPI(API):
|
|
|
431
437
|
class DatasetRdfAPI(API):
|
|
432
438
|
@api.doc("rdf_dataset")
|
|
433
439
|
def get(self, dataset):
|
|
434
|
-
|
|
435
|
-
url = url_for("api.dataset_rdf_format", dataset=dataset.id,
|
|
440
|
+
_format = RDF_EXTENSIONS[negociate_content()]
|
|
441
|
+
url = url_for("api.dataset_rdf_format", dataset=dataset.id, _format=_format)
|
|
436
442
|
return redirect(url)
|
|
437
443
|
|
|
438
444
|
|
|
439
|
-
@ns.route("/<dataset:dataset>/rdf.<
|
|
445
|
+
@ns.route("/<dataset:dataset>/rdf.<_format>", endpoint="dataset_rdf_format", doc=common_doc)
|
|
440
446
|
@api.response(404, "Dataset not found")
|
|
441
447
|
@api.response(410, "Dataset has been deleted")
|
|
442
448
|
class DatasetRdfFormatAPI(API):
|
|
443
449
|
@api.doc("rdf_dataset_format")
|
|
444
|
-
def get(self, dataset,
|
|
450
|
+
def get(self, dataset, _format):
|
|
445
451
|
if not dataset.permissions["edit"].can():
|
|
446
452
|
if dataset.private:
|
|
447
453
|
api.abort(404)
|
|
@@ -451,7 +457,7 @@ class DatasetRdfFormatAPI(API):
|
|
|
451
457
|
resource = dataset_to_rdf(dataset)
|
|
452
458
|
# bypass flask-restplus make_response, since graph_response
|
|
453
459
|
# is handling the content negociation directly
|
|
454
|
-
return make_response(*graph_response(resource,
|
|
460
|
+
return make_response(*graph_response(resource, _format))
|
|
455
461
|
|
|
456
462
|
|
|
457
463
|
@ns.route("/badges/", endpoint="available_dataset_badges")
|
udata/core/organization/api.py
CHANGED
|
@@ -13,7 +13,7 @@ from udata.core.contact_point.api import ContactPointApiParser
|
|
|
13
13
|
from udata.core.contact_point.api_fields import contact_point_fields, contact_point_page_fields
|
|
14
14
|
from udata.core.dataservices.csv import DataserviceCsvAdapter
|
|
15
15
|
from udata.core.dataservices.models import Dataservice
|
|
16
|
-
from udata.core.dataset.api import DatasetApiParser
|
|
16
|
+
from udata.core.dataset.api import DatasetApiParser, catalog_parser
|
|
17
17
|
from udata.core.dataset.api_fields import dataset_page_fields
|
|
18
18
|
from udata.core.dataset.csv import DatasetCsvAdapter, ResourcesCsvAdapter
|
|
19
19
|
from udata.core.dataset.models import Dataset
|
|
@@ -29,7 +29,6 @@ from udata.core.storages.api import (
|
|
|
29
29
|
)
|
|
30
30
|
from udata.models import ContactPoint
|
|
31
31
|
from udata.rdf import RDF_EXTENSIONS, graph_response, negociate_content
|
|
32
|
-
from udata.utils import multi_to_dict
|
|
33
32
|
|
|
34
33
|
from .api_fields import (
|
|
35
34
|
member_fields,
|
|
@@ -234,32 +233,37 @@ class DatasetsResourcesCsvAPI(API):
|
|
|
234
233
|
class OrganizationRdfAPI(API):
|
|
235
234
|
@api.doc("rdf_organization")
|
|
236
235
|
def get(self, org):
|
|
237
|
-
|
|
238
|
-
|
|
236
|
+
_format = RDF_EXTENSIONS[negociate_content()]
|
|
237
|
+
# We sanitize the args used as kwargs in url_for
|
|
238
|
+
params = catalog_parser.parse_args()
|
|
239
|
+
url = url_for("api.organization_rdf_format", org=org.id, _format=_format, **params)
|
|
239
240
|
return redirect(url)
|
|
240
241
|
|
|
241
242
|
|
|
242
|
-
@ns.route("/<org:org>/catalog.<
|
|
243
|
+
@ns.route("/<org:org>/catalog.<_format>", endpoint="organization_rdf_format", doc=common_doc)
|
|
243
244
|
@api.response(404, "Organization not found")
|
|
244
245
|
@api.response(410, "Organization has been deleted")
|
|
245
246
|
class OrganizationRdfFormatAPI(API):
|
|
246
247
|
@api.doc("rdf_organization_format")
|
|
247
|
-
|
|
248
|
+
@api.expect(catalog_parser)
|
|
249
|
+
def get(self, org, _format):
|
|
248
250
|
if org.deleted:
|
|
249
251
|
api.abort(410)
|
|
250
|
-
params =
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
252
|
+
params = catalog_parser.parse_args()
|
|
253
|
+
datasets = DatasetApiParser.parse_filters(
|
|
254
|
+
Dataset.objects(organization=org).visible(), params
|
|
255
|
+
)
|
|
256
|
+
datasets = datasets.paginate(params["page"], params["page_size"])
|
|
257
|
+
|
|
254
258
|
dataservices = (
|
|
255
259
|
Dataservice.objects(organization=org)
|
|
256
260
|
.visible()
|
|
257
|
-
.filter_by_dataset_pagination(datasets, page)
|
|
261
|
+
.filter_by_dataset_pagination(datasets, params["page"])
|
|
258
262
|
)
|
|
259
|
-
catalog = build_org_catalog(org, datasets, dataservices,
|
|
263
|
+
catalog = build_org_catalog(org, datasets, dataservices, _format=_format, **params)
|
|
260
264
|
# bypass flask-restplus make_response, since graph_response
|
|
261
265
|
# is handling the content negociation directly
|
|
262
|
-
return make_response(*graph_response(catalog,
|
|
266
|
+
return make_response(*graph_response(catalog, _format))
|
|
263
267
|
|
|
264
268
|
|
|
265
269
|
@ns.route("/badges/", endpoint="available_organization_badges")
|
udata/core/organization/rdf.py
CHANGED
|
@@ -32,7 +32,7 @@ def organization_to_rdf(org, graph=None):
|
|
|
32
32
|
return o
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def build_org_catalog(org, datasets, dataservices,
|
|
35
|
+
def build_org_catalog(org, datasets, dataservices, _format=None, **kwargs):
|
|
36
36
|
graph = Graph(namespace_manager=namespace_manager)
|
|
37
37
|
org_catalog_url = url_for("api.organization_rdf", org=org.id, _external=True)
|
|
38
38
|
|
|
@@ -47,9 +47,9 @@ def build_org_catalog(org, datasets, dataservices, format=None):
|
|
|
47
47
|
for dataservice in dataservices:
|
|
48
48
|
catalog.add(DCAT.service, dataservice_to_rdf(dataservice, graph))
|
|
49
49
|
|
|
50
|
-
values = {"org": org.id}
|
|
50
|
+
values = {**kwargs, "org": org.id}
|
|
51
51
|
|
|
52
52
|
if isinstance(datasets, Paginable):
|
|
53
|
-
paginate_catalog(catalog, graph, datasets,
|
|
53
|
+
paginate_catalog(catalog, graph, datasets, _format, "api.organization_rdf_format", **values)
|
|
54
54
|
|
|
55
55
|
return catalog
|
udata/core/site/api.py
CHANGED
|
@@ -6,7 +6,7 @@ from udata.auth import admin_permission
|
|
|
6
6
|
from udata.core import csv
|
|
7
7
|
from udata.core.dataservices.csv import DataserviceCsvAdapter
|
|
8
8
|
from udata.core.dataservices.models import Dataservice
|
|
9
|
-
from udata.core.dataset.api import DatasetApiParser
|
|
9
|
+
from udata.core.dataset.api import DatasetApiParser, catalog_parser
|
|
10
10
|
from udata.core.dataset.csv import ResourcesCsvAdapter
|
|
11
11
|
from udata.core.dataset.search import DatasetSearch
|
|
12
12
|
from udata.core.dataset.tasks import get_queryset as get_csv_queryset
|
|
@@ -47,39 +47,47 @@ class SiteAPI(API):
|
|
|
47
47
|
return current_site
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
@api.route("/site/data.<
|
|
50
|
+
@api.route("/site/data.<_format>", endpoint="site_dataportal")
|
|
51
51
|
class SiteDataPortal(API):
|
|
52
|
-
def get(self,
|
|
52
|
+
def get(self, _format):
|
|
53
53
|
"""Root RDF endpoint with content negociation handling"""
|
|
54
|
-
url = url_for("api.site_rdf_catalog_format",
|
|
54
|
+
url = url_for("api.site_rdf_catalog_format", _format=_format)
|
|
55
55
|
return redirect(url)
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
@api.route("/site/catalog", endpoint="site_rdf_catalog")
|
|
59
59
|
class SiteRdfCatalog(API):
|
|
60
|
+
@api.expect(catalog_parser)
|
|
60
61
|
def get(self):
|
|
61
62
|
"""Root RDF endpoint with content negociation handling"""
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
_format = RDF_EXTENSIONS[negociate_content()]
|
|
64
|
+
# We sanitize the args used as kwargs in url_for
|
|
65
|
+
params = catalog_parser.parse_args()
|
|
66
|
+
url = url_for("api.site_rdf_catalog_format", _format=_format, **params)
|
|
64
67
|
return redirect(url)
|
|
65
68
|
|
|
66
69
|
|
|
67
|
-
@api.route("/site/catalog.<
|
|
70
|
+
@api.route("/site/catalog.<_format>", endpoint="site_rdf_catalog_format")
|
|
68
71
|
class SiteRdfCatalogFormat(API):
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
datasets
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
datasets =
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
@api.expect(catalog_parser)
|
|
73
|
+
def get(self, _format):
|
|
74
|
+
"""
|
|
75
|
+
Return the RDF catalog in the requested format.
|
|
76
|
+
Filtering, sorting and paginating abilities apply to the datasets elements.
|
|
77
|
+
"""
|
|
78
|
+
params = catalog_parser.parse_args()
|
|
79
|
+
datasets = DatasetApiParser.parse_filters(Dataset.objects.visible(), params)
|
|
80
|
+
datasets = datasets.paginate(params["page"], params["page_size"])
|
|
81
|
+
dataservices = Dataservice.objects.visible().filter_by_dataset_pagination(
|
|
82
|
+
datasets, params["page"]
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
catalog = build_catalog(
|
|
86
|
+
current_site, datasets, dataservices=dataservices, _format=_format, **params
|
|
87
|
+
)
|
|
80
88
|
# bypass flask-restplus make_response, since graph_response
|
|
81
89
|
# is handling the content negociation directly
|
|
82
|
-
return make_response(*graph_response(catalog,
|
|
90
|
+
return make_response(*graph_response(catalog, _format))
|
|
83
91
|
|
|
84
92
|
|
|
85
93
|
@api.route("/site/datasets.csv", endpoint="site_datasets_csv")
|
udata/core/site/rdf.py
CHANGED
|
@@ -15,7 +15,7 @@ from udata.uris import homepage_url
|
|
|
15
15
|
from udata.utils import Paginable
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def build_catalog(site, datasets, dataservices=[],
|
|
18
|
+
def build_catalog(site, datasets, dataservices=[], _format=None, **kwargs):
|
|
19
19
|
"""Build the DCAT catalog for this site"""
|
|
20
20
|
catalog_url = url_for("api.site_rdf_catalog", _external=True)
|
|
21
21
|
graph = Graph(namespace_manager=namespace_manager)
|
|
@@ -45,6 +45,6 @@ def build_catalog(site, datasets, dataservices=[], format=None):
|
|
|
45
45
|
catalog.add(DCAT.service, rdf_dataservice)
|
|
46
46
|
|
|
47
47
|
if isinstance(datasets, Paginable):
|
|
48
|
-
paginate_catalog(catalog, graph, datasets,
|
|
48
|
+
paginate_catalog(catalog, graph, datasets, _format, "api.site_rdf_catalog_format", **kwargs)
|
|
49
49
|
|
|
50
50
|
return catalog
|
udata/rdf.py
CHANGED
|
@@ -490,17 +490,18 @@ def escape_xml_illegal_chars(val, replacement="?"):
|
|
|
490
490
|
return illegal_xml_chars_RE.sub(replacement, val)
|
|
491
491
|
|
|
492
492
|
|
|
493
|
-
def paginate_catalog(catalog, graph, datasets,
|
|
493
|
+
def paginate_catalog(catalog, graph, datasets, _format, rdf_catalog_endpoint, **values):
|
|
494
494
|
if not format:
|
|
495
495
|
raise ValueError("Pagination requires format")
|
|
496
496
|
catalog.add(RDF.type, HYDRA.Collection)
|
|
497
497
|
catalog.set(HYDRA.totalItems, Literal(datasets.total))
|
|
498
498
|
kwargs = {
|
|
499
|
-
"
|
|
499
|
+
"_format": _format,
|
|
500
500
|
"page_size": datasets.page_size,
|
|
501
501
|
"_external": True,
|
|
502
502
|
}
|
|
503
|
-
|
|
503
|
+
values.pop("page", None)
|
|
504
|
+
values.pop("page_size", None)
|
|
504
505
|
kwargs.update(values)
|
|
505
506
|
|
|
506
507
|
first_url = url_for(rdf_catalog_endpoint, page=1, **kwargs)
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
from datetime import datetime, timedelta
|
|
2
|
-
from xml.etree.ElementTree import XML
|
|
3
2
|
|
|
4
3
|
import feedparser
|
|
5
|
-
import pytest
|
|
6
4
|
from flask import url_for
|
|
7
5
|
from werkzeug.test import TestResponse
|
|
8
6
|
|
|
@@ -24,7 +22,7 @@ from udata.core.organization.models import Member
|
|
|
24
22
|
from udata.core.topic.factories import TopicElementFactory, TopicFactory
|
|
25
23
|
from udata.core.user.factories import AdminFactory, UserFactory
|
|
26
24
|
from udata.i18n import gettext as _
|
|
27
|
-
from udata.tests.helpers import assert200, assert400, assert410
|
|
25
|
+
from udata.tests.helpers import assert200, assert400, assert410
|
|
28
26
|
|
|
29
27
|
from . import APITestCase
|
|
30
28
|
|
|
@@ -664,60 +662,6 @@ class DataserviceAPITest(APITestCase):
|
|
|
664
662
|
self.assertEqual(Dataservice.objects.first().organization.id, new_org.id)
|
|
665
663
|
|
|
666
664
|
|
|
667
|
-
@pytest.mark.frontend
|
|
668
|
-
class DataserviceRdfViewsTest:
|
|
669
|
-
def test_rdf_default_to_jsonld(self, client):
|
|
670
|
-
dataservice = DataserviceFactory()
|
|
671
|
-
expected = url_for("api.dataservice_rdf_format", dataservice=dataservice.id, format="json")
|
|
672
|
-
response = client.get(url_for("api.dataservice_rdf", dataservice=dataservice))
|
|
673
|
-
assert_redirects(response, expected)
|
|
674
|
-
|
|
675
|
-
def test_rdf_perform_content_negociation(self, client):
|
|
676
|
-
dataservice = DataserviceFactory()
|
|
677
|
-
expected = url_for("api.dataservice_rdf_format", dataservice=dataservice.id, format="xml")
|
|
678
|
-
url = url_for("api.dataservice_rdf", dataservice=dataservice)
|
|
679
|
-
headers = {"accept": "application/xml"}
|
|
680
|
-
response = client.get(url, headers=headers)
|
|
681
|
-
assert_redirects(response, expected)
|
|
682
|
-
|
|
683
|
-
def test_rdf_perform_content_negociation_response(self, client):
|
|
684
|
-
"""Check we have valid XML as output"""
|
|
685
|
-
dataservice = DataserviceFactory()
|
|
686
|
-
url = url_for("api.dataservice_rdf", dataservice=dataservice)
|
|
687
|
-
headers = {"accept": "application/xml"}
|
|
688
|
-
response = client.get(url, headers=headers, follow_redirects=True)
|
|
689
|
-
element = XML(response.data)
|
|
690
|
-
assert element.tag == "{http://www.w3.org/1999/02/22-rdf-syntax-ns#}RDF"
|
|
691
|
-
|
|
692
|
-
def test_dataservice_rdf_json_ld(self, client):
|
|
693
|
-
dataservice = DataserviceFactory()
|
|
694
|
-
for fmt in "json", "jsonld":
|
|
695
|
-
url = url_for("api.dataservice_rdf_format", dataservice=dataservice, format=fmt)
|
|
696
|
-
response = client.get(url, headers={"Accept": "application/ld+json"})
|
|
697
|
-
assert200(response)
|
|
698
|
-
assert response.content_type == "application/ld+json"
|
|
699
|
-
assert response.json["@context"]["@vocab"] == "http://www.w3.org/ns/dcat#"
|
|
700
|
-
|
|
701
|
-
@pytest.mark.parametrize(
|
|
702
|
-
"fmt,mime",
|
|
703
|
-
[
|
|
704
|
-
("n3", "text/n3"),
|
|
705
|
-
("nt", "application/n-triples"),
|
|
706
|
-
("ttl", "application/x-turtle"),
|
|
707
|
-
("xml", "application/rdf+xml"),
|
|
708
|
-
("rdf", "application/rdf+xml"),
|
|
709
|
-
("owl", "application/rdf+xml"),
|
|
710
|
-
("trig", "application/trig"),
|
|
711
|
-
],
|
|
712
|
-
)
|
|
713
|
-
def test_dataservice_rdf_formats(self, client, fmt, mime):
|
|
714
|
-
dataservice = DataserviceFactory()
|
|
715
|
-
url = url_for("api.dataservice_rdf_format", dataservice=dataservice, format=fmt)
|
|
716
|
-
response = client.get(url, headers={"Accept": mime})
|
|
717
|
-
assert200(response)
|
|
718
|
-
assert response.content_type == mime
|
|
719
|
-
|
|
720
|
-
|
|
721
665
|
class DataservicesFeedAPItest(APITestCase):
|
|
722
666
|
def test_recent_feed(self):
|
|
723
667
|
DataserviceFactory(title="A", created_at=datetime.utcnow())
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
from xml.etree.ElementTree import XML
|
|
2
|
+
|
|
1
3
|
import pytest
|
|
4
|
+
from flask import url_for
|
|
2
5
|
from rdflib import BNode, Literal, URIRef
|
|
3
6
|
from rdflib.namespace import RDF
|
|
4
7
|
from rdflib.resource import Resource as RdfResource
|
|
@@ -13,6 +16,7 @@ from udata.rdf import (
|
|
|
13
16
|
HVD_LEGISLATION,
|
|
14
17
|
TAG_TO_EU_HVD_CATEGORIES,
|
|
15
18
|
)
|
|
19
|
+
from udata.tests.helpers import assert200, assert_redirects
|
|
16
20
|
|
|
17
21
|
pytestmark = pytest.mark.usefixtures("app")
|
|
18
22
|
|
|
@@ -77,3 +81,57 @@ class DataserviceToRdfTest:
|
|
|
77
81
|
assert URIRef(TAG_TO_EU_HVD_CATEGORIES["meteorologiques"]) not in hvd_categories
|
|
78
82
|
for distrib in d.objects(DCAT.distribution):
|
|
79
83
|
assert distrib.value(DCATAP.applicableLegislation).identifier == URIRef(HVD_LEGISLATION)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@pytest.mark.frontend
|
|
87
|
+
class DataserviceRdfViewsTest:
|
|
88
|
+
def test_rdf_default_to_jsonld(self, client):
|
|
89
|
+
dataservice = DataserviceFactory()
|
|
90
|
+
expected = url_for("api.dataservice_rdf_format", dataservice=dataservice.id, _format="json")
|
|
91
|
+
response = client.get(url_for("api.dataservice_rdf", dataservice=dataservice))
|
|
92
|
+
assert_redirects(response, expected)
|
|
93
|
+
|
|
94
|
+
def test_rdf_perform_content_negociation(self, client):
|
|
95
|
+
dataservice = DataserviceFactory()
|
|
96
|
+
expected = url_for("api.dataservice_rdf_format", dataservice=dataservice.id, _format="xml")
|
|
97
|
+
url = url_for("api.dataservice_rdf", dataservice=dataservice)
|
|
98
|
+
headers = {"accept": "application/xml"}
|
|
99
|
+
response = client.get(url, headers=headers)
|
|
100
|
+
assert_redirects(response, expected)
|
|
101
|
+
|
|
102
|
+
def test_rdf_perform_content_negociation_response(self, client):
|
|
103
|
+
"""Check we have valid XML as output"""
|
|
104
|
+
dataservice = DataserviceFactory()
|
|
105
|
+
url = url_for("api.dataservice_rdf", dataservice=dataservice)
|
|
106
|
+
headers = {"accept": "application/xml"}
|
|
107
|
+
response = client.get(url, headers=headers, follow_redirects=True)
|
|
108
|
+
element = XML(response.data)
|
|
109
|
+
assert element.tag == "{http://www.w3.org/1999/02/22-rdf-syntax-ns#}RDF"
|
|
110
|
+
|
|
111
|
+
def test_dataservice_rdf_json_ld(self, client):
|
|
112
|
+
dataservice = DataserviceFactory()
|
|
113
|
+
for fmt in "json", "jsonld":
|
|
114
|
+
url = url_for("api.dataservice_rdf_format", dataservice=dataservice, _format=fmt)
|
|
115
|
+
response = client.get(url, headers={"Accept": "application/ld+json"})
|
|
116
|
+
assert200(response)
|
|
117
|
+
assert response.content_type == "application/ld+json"
|
|
118
|
+
assert response.json["@context"]["@vocab"] == "http://www.w3.org/ns/dcat#"
|
|
119
|
+
|
|
120
|
+
@pytest.mark.parametrize(
|
|
121
|
+
"fmt,mime",
|
|
122
|
+
[
|
|
123
|
+
("n3", "text/n3"),
|
|
124
|
+
("nt", "application/n-triples"),
|
|
125
|
+
("ttl", "application/x-turtle"),
|
|
126
|
+
("xml", "application/rdf+xml"),
|
|
127
|
+
("rdf", "application/rdf+xml"),
|
|
128
|
+
("owl", "application/rdf+xml"),
|
|
129
|
+
("trig", "application/trig"),
|
|
130
|
+
],
|
|
131
|
+
)
|
|
132
|
+
def test_dataservice_rdf_formats(self, client, fmt, mime):
|
|
133
|
+
dataservice = DataserviceFactory()
|
|
134
|
+
url = url_for("api.dataservice_rdf_format", dataservice=dataservice, _format=fmt)
|
|
135
|
+
response = client.get(url, headers={"Accept": mime})
|
|
136
|
+
assert200(response)
|
|
137
|
+
assert response.content_type == mime
|
|
@@ -1126,13 +1126,13 @@ class RdfToDatasetTest:
|
|
|
1126
1126
|
class DatasetRdfViewsTest:
|
|
1127
1127
|
def test_rdf_default_to_jsonld(self, client):
|
|
1128
1128
|
dataset = DatasetFactory()
|
|
1129
|
-
expected = url_for("api.dataset_rdf_format", dataset=dataset.id,
|
|
1129
|
+
expected = url_for("api.dataset_rdf_format", dataset=dataset.id, _format="json")
|
|
1130
1130
|
response = client.get(url_for("api.dataset_rdf", dataset=dataset))
|
|
1131
1131
|
assert_redirects(response, expected)
|
|
1132
1132
|
|
|
1133
1133
|
def test_rdf_perform_content_negociation(self, client):
|
|
1134
1134
|
dataset = DatasetFactory()
|
|
1135
|
-
expected = url_for("api.dataset_rdf_format", dataset=dataset.id,
|
|
1135
|
+
expected = url_for("api.dataset_rdf_format", dataset=dataset.id, _format="xml")
|
|
1136
1136
|
url = url_for("api.dataset_rdf", dataset=dataset)
|
|
1137
1137
|
headers = {"accept": "application/xml"}
|
|
1138
1138
|
response = client.get(url, headers=headers)
|
|
@@ -1150,7 +1150,7 @@ class DatasetRdfViewsTest:
|
|
|
1150
1150
|
def test_dataset_rdf_json_ld(self, client):
|
|
1151
1151
|
dataset = DatasetFactory()
|
|
1152
1152
|
for fmt in "json", "jsonld":
|
|
1153
|
-
url = url_for("api.dataset_rdf_format", dataset=dataset,
|
|
1153
|
+
url = url_for("api.dataset_rdf_format", dataset=dataset, _format=fmt)
|
|
1154
1154
|
response = client.get(url, headers={"Accept": "application/ld+json"})
|
|
1155
1155
|
assert200(response)
|
|
1156
1156
|
assert response.content_type == "application/ld+json"
|
|
@@ -1170,7 +1170,7 @@ class DatasetRdfViewsTest:
|
|
|
1170
1170
|
)
|
|
1171
1171
|
def test_dataset_rdf_formats(self, client, fmt, mime):
|
|
1172
1172
|
dataset = DatasetFactory()
|
|
1173
|
-
url = url_for("api.dataset_rdf_format", dataset=dataset,
|
|
1173
|
+
url = url_for("api.dataset_rdf_format", dataset=dataset, _format=fmt)
|
|
1174
1174
|
response = client.get(url, headers={"Accept": mime})
|
|
1175
1175
|
assert200(response)
|
|
1176
1176
|
assert response.content_type == mime
|
|
@@ -95,7 +95,7 @@ class OrganizationToRdfTest(DBTestMixin, TestCase):
|
|
|
95
95
|
uri_first = url_for(
|
|
96
96
|
"api.organization_rdf_format",
|
|
97
97
|
org=origin_org.id,
|
|
98
|
-
|
|
98
|
+
_format="json",
|
|
99
99
|
page=1,
|
|
100
100
|
page_size=page_size,
|
|
101
101
|
_external=True,
|
|
@@ -103,7 +103,7 @@ class OrganizationToRdfTest(DBTestMixin, TestCase):
|
|
|
103
103
|
uri_last = url_for(
|
|
104
104
|
"api.organization_rdf_format",
|
|
105
105
|
org=origin_org.id,
|
|
106
|
-
|
|
106
|
+
_format="json",
|
|
107
107
|
page=2,
|
|
108
108
|
page_size=page_size,
|
|
109
109
|
_external=True,
|
|
@@ -124,7 +124,7 @@ class OrganizationToRdfTest(DBTestMixin, TestCase):
|
|
|
124
124
|
# First page
|
|
125
125
|
datasets = Dataset.objects.paginate(1, page_size)
|
|
126
126
|
dataservices = Dataservice.objects.filter_by_dataset_pagination(datasets, 1)
|
|
127
|
-
catalog = build_org_catalog(origin_org, datasets, dataservices,
|
|
127
|
+
catalog = build_org_catalog(origin_org, datasets, dataservices, _format="json")
|
|
128
128
|
graph = catalog.graph
|
|
129
129
|
|
|
130
130
|
self.assertIsInstance(catalog, RdfResource)
|
|
@@ -152,7 +152,7 @@ class OrganizationToRdfTest(DBTestMixin, TestCase):
|
|
|
152
152
|
# Second page
|
|
153
153
|
datasets = Dataset.objects.paginate(2, page_size)
|
|
154
154
|
dataservices = Dataservice.objects.filter_by_dataset_pagination(datasets, 2)
|
|
155
|
-
catalog = build_org_catalog(origin_org, datasets, dataservices,
|
|
155
|
+
catalog = build_org_catalog(origin_org, datasets, dataservices, _format="json")
|
|
156
156
|
graph = catalog.graph
|
|
157
157
|
|
|
158
158
|
self.assertIsInstance(catalog, RdfResource)
|
|
@@ -3,8 +3,10 @@ from flask import url_for
|
|
|
3
3
|
from rdflib import Graph, Literal, URIRef
|
|
4
4
|
from rdflib.namespace import FOAF, RDF
|
|
5
5
|
from rdflib.resource import Resource
|
|
6
|
+
from werkzeug.datastructures import ImmutableMultiDict
|
|
6
7
|
|
|
7
8
|
from udata.core.dataservices.factories import DataserviceFactory, HarvestMetadataFactory
|
|
9
|
+
from udata.core.dataset.constants import HVD
|
|
8
10
|
from udata.core.dataset.factories import DatasetFactory
|
|
9
11
|
from udata.core.dataset.models import Dataset
|
|
10
12
|
from udata.core.organization.factories import OrganizationFactory
|
|
@@ -77,14 +79,14 @@ class CatalogTest:
|
|
|
77
79
|
uri = url_for("api.site_rdf_catalog", _external=True)
|
|
78
80
|
uri_first = url_for(
|
|
79
81
|
"api.site_rdf_catalog_format",
|
|
80
|
-
|
|
82
|
+
_format="json",
|
|
81
83
|
page=1,
|
|
82
84
|
page_size=page_size,
|
|
83
85
|
_external=True,
|
|
84
86
|
)
|
|
85
87
|
uri_last = url_for(
|
|
86
88
|
"api.site_rdf_catalog_format",
|
|
87
|
-
|
|
89
|
+
_format="json",
|
|
88
90
|
page=2,
|
|
89
91
|
page_size=page_size,
|
|
90
92
|
_external=True,
|
|
@@ -93,7 +95,7 @@ class CatalogTest:
|
|
|
93
95
|
|
|
94
96
|
# First page
|
|
95
97
|
datasets = Dataset.objects.paginate(1, page_size)
|
|
96
|
-
catalog = build_catalog(site, datasets,
|
|
98
|
+
catalog = build_catalog(site, datasets, _format="json")
|
|
97
99
|
graph = catalog.graph
|
|
98
100
|
|
|
99
101
|
assert isinstance(catalog, Resource)
|
|
@@ -117,7 +119,7 @@ class CatalogTest:
|
|
|
117
119
|
|
|
118
120
|
# Second page
|
|
119
121
|
datasets = Dataset.objects.paginate(2, page_size)
|
|
120
|
-
catalog = build_catalog(site, datasets,
|
|
122
|
+
catalog = build_catalog(site, datasets, _format="json")
|
|
121
123
|
graph = catalog.graph
|
|
122
124
|
|
|
123
125
|
assert isinstance(catalog, Resource)
|
|
@@ -152,12 +154,39 @@ class SiteRdfViewsTest:
|
|
|
152
154
|
assert response.json == CONTEXT
|
|
153
155
|
|
|
154
156
|
def test_catalog_default_to_jsonld(self, client):
|
|
155
|
-
expected = url_for("api.site_rdf_catalog_format",
|
|
157
|
+
expected = url_for("api.site_rdf_catalog_format", _format="json", page=1, page_size=100)
|
|
156
158
|
response = client.get(url_for("api.site_rdf_catalog"))
|
|
157
159
|
assert_redirects(response, expected)
|
|
158
160
|
|
|
161
|
+
def test_catalog_redirect_with_filters_sanitizing(self, client):
|
|
162
|
+
"""
|
|
163
|
+
It should filter out unknown params (including url_for keywords).
|
|
164
|
+
Repeated keywords should be kept as expected.
|
|
165
|
+
"""
|
|
166
|
+
expected_params = ImmutableMultiDict(
|
|
167
|
+
[("page", 3), ("tag", "hvd"), ("tag", "other"), ("page_size", 100)]
|
|
168
|
+
)
|
|
169
|
+
expected = url_for(
|
|
170
|
+
"api.site_rdf_catalog_format", _format="xml", **expected_params.to_dict(flat=False)
|
|
171
|
+
)
|
|
172
|
+
params = [
|
|
173
|
+
("page", 3),
|
|
174
|
+
("tag", "hvd"),
|
|
175
|
+
("tag", "other"),
|
|
176
|
+
("unknown_param", 5),
|
|
177
|
+
("_external", True),
|
|
178
|
+
]
|
|
179
|
+
url = (
|
|
180
|
+
url_for("api.site_rdf_catalog")
|
|
181
|
+
+ "?"
|
|
182
|
+
+ "&".join(f"{arg}={value}" for arg, value in params)
|
|
183
|
+
)
|
|
184
|
+
headers = {"accept": "application/xml"}
|
|
185
|
+
response = client.get(url, headers=headers)
|
|
186
|
+
assert_redirects(response, expected)
|
|
187
|
+
|
|
159
188
|
def test_rdf_perform_content_negociation(self, client):
|
|
160
|
-
expected = url_for("api.site_rdf_catalog_format",
|
|
189
|
+
expected = url_for("api.site_rdf_catalog_format", _format="xml", page=1, page_size=100)
|
|
161
190
|
url = url_for("api.site_rdf_catalog")
|
|
162
191
|
headers = {"accept": "application/xml"}
|
|
163
192
|
response = client.get(url, headers=headers)
|
|
@@ -165,57 +194,65 @@ class SiteRdfViewsTest:
|
|
|
165
194
|
|
|
166
195
|
@pytest.mark.parametrize("fmt", ("json", "jsonld"))
|
|
167
196
|
def test_catalog_rdf_json_ld(self, fmt, client):
|
|
168
|
-
url = url_for("api.site_rdf_catalog_format",
|
|
197
|
+
url = url_for("api.site_rdf_catalog_format", _format=fmt)
|
|
169
198
|
response = client.get(url, headers={"Accept": "application/ld+json"})
|
|
170
199
|
assert200(response)
|
|
171
200
|
assert response.content_type == "application/ld+json"
|
|
172
201
|
assert response.json["@context"]["@vocab"] == "http://www.w3.org/ns/dcat#"
|
|
173
202
|
|
|
174
203
|
def test_catalog_rdf_n3(self, client):
|
|
175
|
-
url = url_for("api.site_rdf_catalog_format",
|
|
204
|
+
url = url_for("api.site_rdf_catalog_format", _format="n3")
|
|
176
205
|
response = client.get(url, headers={"Accept": "text/n3"})
|
|
177
206
|
assert200(response)
|
|
178
207
|
assert response.content_type == "text/n3"
|
|
179
208
|
|
|
180
209
|
def test_catalog_rdf_turtle(self, client):
|
|
181
|
-
url = url_for("api.site_rdf_catalog_format",
|
|
210
|
+
url = url_for("api.site_rdf_catalog_format", _format="ttl")
|
|
182
211
|
response = client.get(url, headers={"Accept": "application/x-turtle"})
|
|
183
212
|
assert200(response)
|
|
184
213
|
assert response.content_type == "application/x-turtle"
|
|
185
214
|
|
|
186
215
|
@pytest.mark.parametrize("fmt", ("xml", "rdf", "owl"))
|
|
187
216
|
def test_catalog_rdf_rdfxml(self, fmt, client):
|
|
188
|
-
url = url_for("api.site_rdf_catalog_format",
|
|
217
|
+
url = url_for("api.site_rdf_catalog_format", _format=fmt)
|
|
189
218
|
response = client.get(url, headers={"Accept": "application/rdf+xml"})
|
|
190
219
|
assert200(response)
|
|
191
220
|
assert response.content_type == "application/rdf+xml"
|
|
192
221
|
|
|
193
222
|
def test_catalog_rdf_n_triples(self, client):
|
|
194
|
-
url = url_for("api.site_rdf_catalog_format",
|
|
223
|
+
url = url_for("api.site_rdf_catalog_format", _format="nt")
|
|
195
224
|
response = client.get(url, headers={"Accept": "application/n-triples"})
|
|
196
225
|
assert200(response)
|
|
197
226
|
assert response.content_type == "application/n-triples"
|
|
198
227
|
|
|
199
228
|
def test_catalog_rdf_trig(self, client):
|
|
200
|
-
url = url_for("api.site_rdf_catalog_format",
|
|
229
|
+
url = url_for("api.site_rdf_catalog_format", _format="trig")
|
|
201
230
|
response = client.get(url, headers={"Accept": "application/trig"})
|
|
202
231
|
assert200(response)
|
|
203
232
|
assert response.content_type == "application/trig"
|
|
204
233
|
|
|
205
234
|
@pytest.mark.parametrize("fmt", ("json", "xml", "ttl"))
|
|
206
235
|
def test_dataportal_compliance(self, fmt, client):
|
|
207
|
-
url = url_for("api.site_dataportal",
|
|
236
|
+
url = url_for("api.site_dataportal", _format=fmt)
|
|
208
237
|
assert url == "/api/1/site/data.{0}".format(fmt)
|
|
209
|
-
expected_url = url_for("api.site_rdf_catalog_format",
|
|
238
|
+
expected_url = url_for("api.site_rdf_catalog_format", _format=fmt)
|
|
210
239
|
|
|
211
240
|
response = client.get(url)
|
|
212
241
|
assert_redirects(response, expected_url)
|
|
213
242
|
|
|
214
243
|
def test_catalog_rdf_paginate(self, client):
|
|
215
|
-
DatasetFactory.create_batch(4)
|
|
216
|
-
|
|
244
|
+
DatasetFactory.create_batch(4, tags=["my-tag"])
|
|
245
|
+
DatasetFactory.create_batch(
|
|
246
|
+
3, tags=["other-tag"]
|
|
247
|
+
) # Shouldn't be returned because of the filter on tag="my-tag"
|
|
248
|
+
url = url_for("api.site_rdf_catalog_format", _format="n3", page_size=3, tag="my-tag")
|
|
217
249
|
next_url = url_for(
|
|
218
|
-
"api.site_rdf_catalog_format",
|
|
250
|
+
"api.site_rdf_catalog_format",
|
|
251
|
+
_format="n3",
|
|
252
|
+
page=2,
|
|
253
|
+
page_size=3,
|
|
254
|
+
_external=True,
|
|
255
|
+
tag="my-tag",
|
|
219
256
|
)
|
|
220
257
|
|
|
221
258
|
response = client.get(url, headers={"Accept": "text/n3"})
|
|
@@ -227,16 +264,27 @@ class SiteRdfViewsTest:
|
|
|
227
264
|
pagination = graph.resource(pagination)
|
|
228
265
|
assert not pagination.value(HYDRA.previous)
|
|
229
266
|
assert pagination.value(HYDRA.next).identifier == URIRef(next_url)
|
|
267
|
+
assert pagination.value(HYDRA.last).identifier == URIRef(next_url)
|
|
268
|
+
catalog = graph.value(predicate=RDF.type, object=HYDRA.Collection)
|
|
269
|
+
assert catalog is not None
|
|
270
|
+
catalog = graph.resource(catalog)
|
|
271
|
+
assert catalog.value(HYDRA.totalItems) == Literal(4)
|
|
230
272
|
|
|
231
273
|
def test_catalog_format_unknown(self, client):
|
|
232
|
-
url = url_for("api.site_rdf_catalog_format",
|
|
274
|
+
url = url_for("api.site_rdf_catalog_format", _format="unknown")
|
|
233
275
|
response = client.get(url)
|
|
234
276
|
assert404(response)
|
|
235
277
|
|
|
236
|
-
def
|
|
278
|
+
def test_catalog_rdf_filter(self, client):
|
|
279
|
+
"""
|
|
280
|
+
Test catalog RDF filter on tags and badges
|
|
281
|
+
"""
|
|
237
282
|
DatasetFactory.create_batch(4, tags=["my-tag"])
|
|
283
|
+
[dat.add_badge(HVD) for dat in DatasetFactory.create_batch(5)]
|
|
238
284
|
DatasetFactory.create_batch(3)
|
|
239
|
-
|
|
285
|
+
|
|
286
|
+
# Filter on tags
|
|
287
|
+
url = url_for("api.site_rdf_catalog_format", _format="xml", tag="my-tag")
|
|
240
288
|
|
|
241
289
|
response = client.get(url, headers={"Accept": "application/xml"})
|
|
242
290
|
assert200(response)
|
|
@@ -249,6 +297,17 @@ class SiteRdfViewsTest:
|
|
|
249
297
|
for dat in datasets:
|
|
250
298
|
assert graph.value(dat, DCAT.keyword) == Literal("my-tag")
|
|
251
299
|
|
|
300
|
+
# Filter on badge
|
|
301
|
+
url = url_for("api.site_rdf_catalog_format", _format="xml", badge=HVD)
|
|
302
|
+
|
|
303
|
+
response = client.get(url, headers={"Accept": "application/xml"})
|
|
304
|
+
assert200(response)
|
|
305
|
+
|
|
306
|
+
graph = Graph().parse(data=response.data, format="xml")
|
|
307
|
+
|
|
308
|
+
datasets = list(graph.subjects(RDF.type, DCAT.Dataset))
|
|
309
|
+
assert len(datasets) == 5
|
|
310
|
+
|
|
252
311
|
def test_catalog_rdf_dataservices(self, client):
|
|
253
312
|
dataset_a = DatasetFactory.create()
|
|
254
313
|
dataset_b = DatasetFactory.create()
|
|
@@ -260,7 +319,7 @@ class SiteRdfViewsTest:
|
|
|
260
319
|
dataservice_y = DataserviceFactory.create(datasets=[])
|
|
261
320
|
|
|
262
321
|
response = client.get(
|
|
263
|
-
url_for("api.site_rdf_catalog_format",
|
|
322
|
+
url_for("api.site_rdf_catalog_format", _format="xml"),
|
|
264
323
|
headers={"Accept": "application/xml"},
|
|
265
324
|
)
|
|
266
325
|
assert200(response)
|
|
@@ -280,7 +339,7 @@ class SiteRdfViewsTest:
|
|
|
280
339
|
|
|
281
340
|
# Test first page contains the dataservice without dataset
|
|
282
341
|
response = client.get(
|
|
283
|
-
url_for("api.site_rdf_catalog_format",
|
|
342
|
+
url_for("api.site_rdf_catalog_format", _format="xml", page_size=1),
|
|
284
343
|
headers={"Accept": "application/xml"},
|
|
285
344
|
)
|
|
286
345
|
assert200(response)
|
|
@@ -299,7 +358,7 @@ class SiteRdfViewsTest:
|
|
|
299
358
|
|
|
300
359
|
# Test second page doesn't contains the dataservice without dataset
|
|
301
360
|
response = client.get(
|
|
302
|
-
url_for("api.site_rdf_catalog_format",
|
|
361
|
+
url_for("api.site_rdf_catalog_format", _format="xml", page_size=1, page=2),
|
|
303
362
|
headers={"Accept": "application/xml"},
|
|
304
363
|
)
|
|
305
364
|
assert200(response)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: udata
|
|
3
|
-
Version: 12.0.2.
|
|
3
|
+
Version: 12.0.2.dev13
|
|
4
4
|
Summary: Open data portal
|
|
5
5
|
Author-email: Opendata Team <opendatateam@data.gouv.fr>
|
|
6
6
|
Maintainer-email: Opendata Team <opendatateam@data.gouv.fr>
|
|
@@ -96,8 +96,6 @@ Requires-Dist: invoke<3.0,>=2.2.0; extra == "dev"
|
|
|
96
96
|
Requires-Dist: pip-tools<8.0,>=7.4.1; extra == "dev"
|
|
97
97
|
Requires-Dist: pre-commit<5.0,>=4.2.0; extra == "dev"
|
|
98
98
|
Requires-Dist: ruff<1.0,>=0.11.0; extra == "dev"
|
|
99
|
-
Requires-Dist: twine<7.0,>=6.1.0; extra == "dev"
|
|
100
|
-
Requires-Dist: wheel<1.0,>=0.45.1; extra == "dev"
|
|
101
99
|
Provides-Extra: test
|
|
102
100
|
Requires-Dist: faker<38.0,>=37.0.2; extra == "test"
|
|
103
101
|
Requires-Dist: feedparser<7.0,>=6.0.11; extra == "test"
|
|
@@ -7,7 +7,7 @@ udata/errors.py,sha256=E8W7b4PH7c5B85g_nsUMt8fHqMVpDFOZFkO6wMPl6bA,117
|
|
|
7
7
|
udata/factories.py,sha256=MoklZnU8iwNL25dm3JsoXhoQs1PQWSVYL1WvcUBtJqM,492
|
|
8
8
|
udata/i18n.py,sha256=bC9ajf66YgcYoJffvresLZLa32rb6NsY-JGMtFiVsG4,8163
|
|
9
9
|
udata/mail.py,sha256=Huhx_1QthJkLvuRUuP6jqb5Qq5R4iSmqeEpLVO9ZkQ4,2671
|
|
10
|
-
udata/rdf.py,sha256=
|
|
10
|
+
udata/rdf.py,sha256=4SruNYSJzqwureb8no6ghh0ZXypG7wCahqSpSrBo8K0,19435
|
|
11
11
|
udata/routing.py,sha256=Hnc1ktmKVS-RUHNKw2zYTft2HJ903FhjtlcenQ9igwI,8044
|
|
12
12
|
udata/sentry.py,sha256=ekcxqUSqxfM98TtvCsPaOoX5i2l6PEcYt7kb4l3od-Q,3223
|
|
13
13
|
udata/settings.py,sha256=1gDu1fnorsgzRzkMIEzFjWiVZ_7UPe1kRW-GQulb7O0,21686
|
|
@@ -79,7 +79,7 @@ udata/core/contact_point/forms.py,sha256=oBe1agSJFyx2QRgYzPRg2A7qVscaBTaKG4V-AyI
|
|
|
79
79
|
udata/core/contact_point/models.py,sha256=Xqmqg7S13gcaKxiQT52WHeQEHTaUDDGIXInXyqNh4Po,854
|
|
80
80
|
udata/core/dataservices/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
81
81
|
udata/core/dataservices/activities.py,sha256=wcYQCyYpKciCz99VqQqKti72a5Fyhc-AvDZBWdF0KUc,1763
|
|
82
|
-
udata/core/dataservices/api.py,sha256=
|
|
82
|
+
udata/core/dataservices/api.py,sha256=_-ShQz9ijnFwy5xM7nJffA0YpHyXyXknFnsEuV1YvRY,10058
|
|
83
83
|
udata/core/dataservices/apiv2.py,sha256=pd4UWF6m7pQ5nmBRFmeiDyedhZSngz211to6qTscVsA,1205
|
|
84
84
|
udata/core/dataservices/constants.py,sha256=SxetyqvbWQlb-T9Bqn7mdfzV3vS-is7s56rzmGzTXY0,1029
|
|
85
85
|
udata/core/dataservices/csv.py,sha256=HWI2JrN_Vuw0te9FHlJ6eyqcRcKHOKXuzg45D4Ti6F0,1106
|
|
@@ -92,7 +92,7 @@ udata/core/dataservices/tasks.py,sha256=fHG1r5ymfJRXJ_Lug6je3VKZoK30XKXE2rQ8x0R-
|
|
|
92
92
|
udata/core/dataset/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
93
93
|
udata/core/dataset/actions.py,sha256=mX6xox0PiMrbcAPZ3VZsI26rfM-ciYfEXxN6sqqImKA,1222
|
|
94
94
|
udata/core/dataset/activities.py,sha256=eGxMUnC47YHxTgcls6igQ3qP7cYgwFtPfj0asCylGsI,3315
|
|
95
|
-
udata/core/dataset/api.py,sha256=
|
|
95
|
+
udata/core/dataset/api.py,sha256=ct3GNQjoAxZSYqb98rQkx85o-pj2qO5E5DMzCDGauN8,35585
|
|
96
96
|
udata/core/dataset/api_fields.py,sha256=p7ZnmGNImZ4sgZTpoyHpI0CgOukpEIx8QdGnxlmgl2I,18032
|
|
97
97
|
udata/core/dataset/apiv2.py,sha256=1H4557ZMi6rwEyrwB1Ha20m0bf3Avhg_vDLiDQt5Fi0,21030
|
|
98
98
|
udata/core/dataset/commands.py,sha256=3mKSdJ-M7ggdG29AVn77C4ouZanbYoqkTaGQoBKOp3s,3471
|
|
@@ -145,7 +145,7 @@ udata/core/metrics/signals.py,sha256=9mdJW__gR2GJT3huBr6HN2SDhKYJRgNbW9dnh48cAnU
|
|
|
145
145
|
udata/core/metrics/tasks.py,sha256=5hVSvBFF2-k_MZGn1XrzEWLgRp3TlrZJtPjX1Y_niS4,4963
|
|
146
146
|
udata/core/organization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
147
147
|
udata/core/organization/activities.py,sha256=Mw4-R8Q6G745IZnCDgrj7h2ax2crGYRhZtcewSK6_Ok,1213
|
|
148
|
-
udata/core/organization/api.py,sha256=
|
|
148
|
+
udata/core/organization/api.py,sha256=mjfo19OeLijo_0HyPElyYcxIiz_OqNYzjcREsUgheg4,22304
|
|
149
149
|
udata/core/organization/api_fields.py,sha256=UlDYS62Wt1capSO0rYf6-m_rza3lCmpTuA93R-sV9w8,7776
|
|
150
150
|
udata/core/organization/apiv2.py,sha256=fLMN5T7s8yF4u7c1WWHXMqQAlyH2OCSyAfmleiFlf7M,3037
|
|
151
151
|
udata/core/organization/commands.py,sha256=DsRAtFDZvTciYNsUWumQWdn0jnNmKW-PwfIHUUZoBb8,1591
|
|
@@ -157,7 +157,7 @@ udata/core/organization/metrics.py,sha256=CEhkZLUufDyWi2XyizMoXkuddz7xDJvmdkPTwe
|
|
|
157
157
|
udata/core/organization/models.py,sha256=QYneMUDA99NsMHn4_pGn1dnnDK4dESVUy5ogo8Tm7ZI,10962
|
|
158
158
|
udata/core/organization/notifications.py,sha256=i_36-l2y7fOGmnBmr5NDWmGGmrGRaCWbU-6XS4c2wQs,917
|
|
159
159
|
udata/core/organization/permissions.py,sha256=GD-9TMtRppVCPaC1ysXYrONvGJV-ArzAOXm2XMKf9yo,1256
|
|
160
|
-
udata/core/organization/rdf.py,sha256=
|
|
160
|
+
udata/core/organization/rdf.py,sha256=KYJXTE5Yxhp3Cb7GZsRT1BY3Bd7rcRfwFSK9dWG2xQ4,1807
|
|
161
161
|
udata/core/organization/search.py,sha256=5XMZn7xehkTV4X9NvGys_1WyHDGlUVpCQ_uJ3oyWdsE,2227
|
|
162
162
|
udata/core/organization/signals.py,sha256=Ft1MBU9S41uxFN-rUrKHhiwedR1OYGv-ncuroKg8orY,488
|
|
163
163
|
udata/core/organization/tasks.py,sha256=2Pd9ixeKNd7BGxBHrHYbR9AelhqkflX3ocnGgtoa8Uc,5641
|
|
@@ -194,11 +194,11 @@ udata/core/reuse/search.py,sha256=y1DwXYkBMBwuhn62CULkU1NNo89IYp0Ae7U01jcnjBY,31
|
|
|
194
194
|
udata/core/reuse/signals.py,sha256=nDrEUpYKN0AdYiEbrR0z3nzXzjaRcD8SAMutwIDsQPM,155
|
|
195
195
|
udata/core/reuse/tasks.py,sha256=cc6f06HMFCDHRsdgsG09FBYsITNQ8xzdZjE-pMY61a0,1688
|
|
196
196
|
udata/core/site/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
197
|
-
udata/core/site/api.py,sha256=
|
|
197
|
+
udata/core/site/api.py,sha256=GhSZfdv0rQgtmqG3h0uGcXrzbX9Zx3GuypgaxcAClsg,8139
|
|
198
198
|
udata/core/site/factories.py,sha256=O0nLFmjrFyemzcs-YwNukq5nqd383KBGrgL5bOQsGbA,378
|
|
199
199
|
udata/core/site/forms.py,sha256=avEZ4rJhibF7sKexqMlKt1qMFiUHNrmJGKjZqcAyjrc,459
|
|
200
200
|
udata/core/site/models.py,sha256=mlSsnXUoMmIZ26-mvotWpICaoL1ScbYMsc85Dt-28cI,8322
|
|
201
|
-
udata/core/site/rdf.py,sha256=
|
|
201
|
+
udata/core/site/rdf.py,sha256=CT4TIu9DMiYHaNugW873UAJsQLBtzqQIr_a24CMyEJ8,2037
|
|
202
202
|
udata/core/spam/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
203
203
|
udata/core/spam/api.py,sha256=eqmDB4_VF5EM92675FqFmk4Be5TAnu87dmSVtgXKF4A,1740
|
|
204
204
|
udata/core/spam/constants.py,sha256=dTj0GyPH2zdxhurxva2CGnL-3WwqZETyt5vYQhmVpow,144
|
|
@@ -516,7 +516,7 @@ udata/tests/api/test_activities_api.py,sha256=GzyznB1rHrWfPH-te5RKmA3Ezlo5jlP3z7
|
|
|
516
516
|
udata/tests/api/test_auth_api.py,sha256=Mue5EneRp3MbD-ahcXI3YaRNYPcxzHMw-hYpY0RtGVU,25569
|
|
517
517
|
udata/tests/api/test_base_api.py,sha256=2w_vz0eEuq3P3aN-ByvxGc3VZAo7XtgatFfcrzf2uEU,2244
|
|
518
518
|
udata/tests/api/test_contact_points.py,sha256=Sbb486RTN7HVycna_XB60OnURPSNc7xUity26XsYA4k,8766
|
|
519
|
-
udata/tests/api/test_dataservices_api.py,sha256=
|
|
519
|
+
udata/tests/api/test_dataservices_api.py,sha256=scju3nQVO51NyNxeCagi0znjMQozPBbp5BQKP-BuhyY,28961
|
|
520
520
|
udata/tests/api/test_datasets_api.py,sha256=EkMJndRMNHpVVC7ar-F8i_PXdGyvd-bCoVbnsaatH3s,104911
|
|
521
521
|
udata/tests/api/test_fields.py,sha256=OW85Z5MES5HeWOpapeem8OvR1cIcrqW-xMWpdZO4LZ8,1033
|
|
522
522
|
udata/tests/api/test_follow_api.py,sha256=4nFXG5pZ_Hf2PJ4KEdHJX_uggjc9RpB8v0fidkAcw9I,5792
|
|
@@ -540,7 +540,7 @@ udata/tests/contact_point/test_contact_point_models.py,sha256=b8vraZPPrs9LeQMWLn
|
|
|
540
540
|
udata/tests/data/image.jpg,sha256=hdmpaCjOhmAAfNGuTqWKEjv7IC4GXJx-nP_rT274hc8,337049
|
|
541
541
|
udata/tests/data/image.png,sha256=GAqXz7w_u7CapODIUF45UpVddmqelnGQkcrwKZq3448,266488
|
|
542
542
|
udata/tests/dataservice/test_csv_adapter.py,sha256=UyDPiqKIDwe0AdXLKLpSsBqe4ZJsfkzcZ6SxMns2WnY,1984
|
|
543
|
-
udata/tests/dataservice/test_dataservice_rdf.py,sha256=
|
|
543
|
+
udata/tests/dataservice/test_dataservice_rdf.py,sha256=a2ptzGaNUYOYCwC-uUAmg6bdYJeGeI7zPohJY0QEHl0,6217
|
|
544
544
|
udata/tests/dataservice/test_dataservice_tasks.py,sha256=9XUoYLb_p3dzmgLfswaXjMG2civP0i1kzzP4VdJWE0k,1614
|
|
545
545
|
udata/tests/dataset/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
546
546
|
udata/tests/dataset/test_csv_adapter.py,sha256=Qy3dKg7OVz7paEOrRzHe-plBGsZgkalfW30SJK1JB0g,3905
|
|
@@ -548,7 +548,7 @@ udata/tests/dataset/test_dataset_actions.py,sha256=bgDjVYjOvu3sX_FCTCzf2snZYSprs
|
|
|
548
548
|
udata/tests/dataset/test_dataset_commands.py,sha256=zMPJG2wYwKBee2zI65kmboxf59Zqa84DDjT8V5wj9uo,801
|
|
549
549
|
udata/tests/dataset/test_dataset_events.py,sha256=hlrpoOiBbnX_COUI9Pzdqlp45GZZDqu5piwupbnPiTI,3601
|
|
550
550
|
udata/tests/dataset/test_dataset_model.py,sha256=plzvIaEqvxQpcYS8YlDBltjuTgtT7xgNVEzkmlPZBC0,33766
|
|
551
|
-
udata/tests/dataset/test_dataset_rdf.py,sha256=
|
|
551
|
+
udata/tests/dataset/test_dataset_rdf.py,sha256=aug8GJLvIjiutVVklQY8Oej6le5o_n8r6GVV05pLWv8,45949
|
|
552
552
|
udata/tests/dataset/test_dataset_recommendations.py,sha256=K52HXGXi9DuUSiSRQWpqTrsFCkYbv7K3upNp0fFp5v8,7068
|
|
553
553
|
udata/tests/dataset/test_dataset_tasks.py,sha256=SwSv-hDSXgs1xXtvtaePQ6fa6_d4ZpHo-oahDRinvPg,3271
|
|
554
554
|
udata/tests/dataset/test_resource_preview.py,sha256=AxSF8cnG6bhy2pz9Fi3PfEzdLlNhZ0xrp9dr6yrt31A,2051
|
|
@@ -586,7 +586,7 @@ udata/tests/organization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
586
586
|
udata/tests/organization/test_csv_adapter.py,sha256=61XIVDYdZxnWUyysN_wApWwghM7nT_Id-74IMtFd3Zg,1263
|
|
587
587
|
udata/tests/organization/test_notifications.py,sha256=PGmME5BbYVtcPffeSE1sx47J6iAfm4RDAZIRv_MXDFE,1366
|
|
588
588
|
udata/tests/organization/test_organization_model.py,sha256=ZEUHX7lvGMYMlHDpPiVUPeZeJeDDTp5owLEpFDSihjc,4311
|
|
589
|
-
udata/tests/organization/test_organization_rdf.py,sha256=
|
|
589
|
+
udata/tests/organization/test_organization_rdf.py,sha256=mAaMQHofgJ_sCPuE2v_3qDc3IO2EPiYSVu8HrP6E1Zk,8078
|
|
590
590
|
udata/tests/organization/test_organization_tasks.py,sha256=9Ta-f4R3RoKdARYUFWHO4pE1nijceTHzyEvI34lYBJo,2876
|
|
591
591
|
udata/tests/reuse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
592
592
|
udata/tests/reuse/test_reuse_model.py,sha256=PtdC39JrDCtF9iSfYSH98115309Q-E8aKn4s6rZCqCY,4662
|
|
@@ -600,7 +600,7 @@ udata/tests/site/test_site_api.py,sha256=pGisx3jtxTWNL9-R-tcCPBPYoQZM8oz8BJ4-seK
|
|
|
600
600
|
udata/tests/site/test_site_csv_exports.py,sha256=hrUthkJw8yoSpEZNDHfzZIMEoXSBFosjhNVd5OxQDOE,17487
|
|
601
601
|
udata/tests/site/test_site_metrics.py,sha256=KxlilOUeAbBta7HwD4mB4ybDWBmRB-3UVrLunvRGoGg,2362
|
|
602
602
|
udata/tests/site/test_site_model.py,sha256=CNE-jP48guJpRlh4D3rQGruu2hSRliQaLOnBmzkHMnI,2181
|
|
603
|
-
udata/tests/site/test_site_rdf.py,sha256=
|
|
603
|
+
udata/tests/site/test_site_rdf.py,sha256=8xGGd68WgjNj9mw52E8XTx1Byh3zDq2OgM2xg9RyMAU,15308
|
|
604
604
|
udata/tests/topic/test_topic_tasks.py,sha256=6rotG7ZtRffpfaO-KFu4i5MRqHitbwvMwqXg1jFT6XU,1199
|
|
605
605
|
udata/tests/user/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
606
606
|
udata/tests/user/test_user_rdf.py,sha256=BRdv9ivLLUQoImFOuIohDoZAQXMXCruaNJ37siKul5o,1771
|
|
@@ -625,9 +625,9 @@ udata/translations/pt/LC_MESSAGES/udata.mo,sha256=nv80xZLfIfUsSOMBcr29L268FDc_Gt
|
|
|
625
625
|
udata/translations/pt/LC_MESSAGES/udata.po,sha256=bUp-7Ray8t8ALgJk3Icw1jmiGIc9_pEJQHiGw_2EU2o,50989
|
|
626
626
|
udata/translations/sr/LC_MESSAGES/udata.mo,sha256=Y_XpUxD074wXc63oJTnoVOyOQ2lmBxl-MrgluZ0Qdw4,27961
|
|
627
627
|
udata/translations/sr/LC_MESSAGES/udata.po,sha256=qh8mrz9AFuVQtXYSSP4QWsXLM_Lv3EHVifHT1NflWXY,57529
|
|
628
|
-
udata-12.0.2.
|
|
629
|
-
udata-12.0.2.
|
|
630
|
-
udata-12.0.2.
|
|
631
|
-
udata-12.0.2.
|
|
632
|
-
udata-12.0.2.
|
|
633
|
-
udata-12.0.2.
|
|
628
|
+
udata-12.0.2.dev13.dist-info/licenses/LICENSE,sha256=V8j_M8nAz8PvAOZQocyRDX7keai8UJ9skgmnwqETmdY,34520
|
|
629
|
+
udata-12.0.2.dev13.dist-info/METADATA,sha256=0p4YaygMwNbbY_fnRD4PmOzXTqOb40rc6-mwEAzrgls,5174
|
|
630
|
+
udata-12.0.2.dev13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
631
|
+
udata-12.0.2.dev13.dist-info/entry_points.txt,sha256=v2u12qO11i2lyLNIp136WmLJ-NHT-Kew3Duu8J-AXPM,614
|
|
632
|
+
udata-12.0.2.dev13.dist-info/top_level.txt,sha256=EF6CE6YSHd_og-8LCEA4q25ALUpWVe8D0okOLdMAE3A,6
|
|
633
|
+
udata-12.0.2.dev13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|