udata 6.2.1.dev26916__py2.py3-none-any.whl → 6.2.1.dev26928__py2.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/dataset/apiv2.py +4 -4
- udata/core/dataset/rdf.py +13 -4
- udata/harvest/tests/dcat/catalog.xml +5 -0
- udata/harvest/tests/test_dcat_backend.py +12 -3
- udata/static/chunks/{11.c0ccea08914b6b41568e.js → 11.a23c110811a9ac943478.js} +3 -3
- udata/static/chunks/{11.c0ccea08914b6b41568e.js.map → 11.a23c110811a9ac943478.js.map} +1 -1
- udata/static/chunks/{13.526a25163ababaa44409.js → 13.0889e093f8664e38568c.js} +2 -2
- udata/static/chunks/{13.526a25163ababaa44409.js.map → 13.0889e093f8664e38568c.js.map} +1 -1
- udata/static/chunks/{16.7901839b4227881947f6.js → 16.f41599478d3e97ad9a30.js} +2 -2
- udata/static/chunks/{16.7901839b4227881947f6.js.map → 16.f41599478d3e97ad9a30.js.map} +1 -1
- udata/static/chunks/{19.471d5a2a08eef6e5338a.js → 19.2b534a26af8b17e9170b.js} +3 -3
- udata/static/chunks/{19.471d5a2a08eef6e5338a.js.map → 19.2b534a26af8b17e9170b.js.map} +1 -1
- udata/static/chunks/{5.6b73b3d83a8ff187132d.js → 5.da4db938a6ecf99fccbc.js} +3 -3
- udata/static/chunks/{5.6b73b3d83a8ff187132d.js.map → 5.da4db938a6ecf99fccbc.js.map} +1 -1
- udata/static/chunks/{6.e56975229e6065f68d2a.js → 6.16bb24fb8240f2746488.js} +3 -3
- udata/static/chunks/{6.e56975229e6065f68d2a.js.map → 6.16bb24fb8240f2746488.js.map} +1 -1
- udata/static/chunks/{9.534426728626f11f4571.js → 9.3e752966ff14e47e11f2.js} +2 -2
- udata/static/chunks/{9.534426728626f11f4571.js.map → 9.3e752966ff14e47e11f2.js.map} +1 -1
- udata/static/common.js +1 -1
- udata/static/common.js.map +1 -1
- udata/tests/apiv2/test_datasets.py +22 -7
- {udata-6.2.1.dev26916.dist-info → udata-6.2.1.dev26928.dist-info}/METADATA +3 -1
- {udata-6.2.1.dev26916.dist-info → udata-6.2.1.dev26928.dist-info}/RECORD +27 -27
- {udata-6.2.1.dev26916.dist-info → udata-6.2.1.dev26928.dist-info}/LICENSE +0 -0
- {udata-6.2.1.dev26916.dist-info → udata-6.2.1.dev26928.dist-info}/WHEEL +0 -0
- {udata-6.2.1.dev26916.dist-info → udata-6.2.1.dev26928.dist-info}/entry_points.txt +0 -0
- {udata-6.2.1.dev26916.dist-info → udata-6.2.1.dev26928.dist-info}/top_level.txt +0 -0
udata/core/dataset/apiv2.py
CHANGED
|
@@ -232,7 +232,7 @@ class DatasetExtrasAPI(API):
|
|
|
232
232
|
data.pop(key)
|
|
233
233
|
# then update the extras with the remaining payload
|
|
234
234
|
dataset.extras.update(data)
|
|
235
|
-
dataset.save()
|
|
235
|
+
dataset.save(signal_kwargs={'ignores': ['post_save']})
|
|
236
236
|
return dataset.extras
|
|
237
237
|
|
|
238
238
|
@apiv2.secure
|
|
@@ -250,7 +250,7 @@ class DatasetExtrasAPI(API):
|
|
|
250
250
|
del dataset.extras[key]
|
|
251
251
|
except KeyError:
|
|
252
252
|
apiv2.abort(404, 'Key not found in existing extras')
|
|
253
|
-
dataset.save()
|
|
253
|
+
dataset.save(signal_kwargs={'ignores': ['post_save']})
|
|
254
254
|
return dataset.extras, 204
|
|
255
255
|
|
|
256
256
|
|
|
@@ -348,7 +348,7 @@ class ResourceExtrasAPI(ResourceMixin, API):
|
|
|
348
348
|
data.pop(key)
|
|
349
349
|
# then update the extras with the remaining payload
|
|
350
350
|
resource.extras.update(data)
|
|
351
|
-
resource.save()
|
|
351
|
+
resource.save(signal_kwargs={'ignores': ['post_save']})
|
|
352
352
|
return resource.extras
|
|
353
353
|
|
|
354
354
|
@apiv2.secure
|
|
@@ -367,5 +367,5 @@ class ResourceExtrasAPI(ResourceMixin, API):
|
|
|
367
367
|
del resource.extras[key]
|
|
368
368
|
except KeyError:
|
|
369
369
|
apiv2.abort(404, 'Key not found in existing extras')
|
|
370
|
-
resource.save()
|
|
370
|
+
resource.save(signal_kwargs={'ignores': ['post_save']})
|
|
371
371
|
return resource.extras, 204
|
udata/core/dataset/rdf.py
CHANGED
|
@@ -389,6 +389,7 @@ def remote_url_from_rdf(rdf):
|
|
|
389
389
|
except uris.ValidationError:
|
|
390
390
|
pass
|
|
391
391
|
|
|
392
|
+
|
|
392
393
|
def theme_labels_from_rdf(rdf):
|
|
393
394
|
for theme in rdf.objects(DCAT.theme):
|
|
394
395
|
if isinstance(theme, RdfResource):
|
|
@@ -399,7 +400,7 @@ def theme_labels_from_rdf(rdf):
|
|
|
399
400
|
yield label
|
|
400
401
|
|
|
401
402
|
|
|
402
|
-
def resource_from_rdf(graph_or_distrib, dataset=None):
|
|
403
|
+
def resource_from_rdf(graph_or_distrib, dataset=None, is_additionnal=False):
|
|
403
404
|
'''
|
|
404
405
|
Map a Resource domain model to a DCAT/RDF graph
|
|
405
406
|
'''
|
|
@@ -410,9 +411,12 @@ def resource_from_rdf(graph_or_distrib, dataset=None):
|
|
|
410
411
|
object=DCAT.Distribution)
|
|
411
412
|
distrib = graph_or_distrib.resource(node)
|
|
412
413
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
414
|
+
if not is_additionnal:
|
|
415
|
+
download_url = url_from_rdf(distrib, DCAT.downloadURL)
|
|
416
|
+
access_url = url_from_rdf(distrib, DCAT.accessURL)
|
|
417
|
+
url = safe_unicode(download_url or access_url)
|
|
418
|
+
else:
|
|
419
|
+
url = distrib.identifier.toPython() if isinstance(distrib.identifier, URIRef) else None
|
|
416
420
|
# we shouldn't create resources without URLs
|
|
417
421
|
if not url:
|
|
418
422
|
log.warning(f'Resource without url: {distrib}')
|
|
@@ -439,6 +443,8 @@ def resource_from_rdf(graph_or_distrib, dataset=None):
|
|
|
439
443
|
resource.checksum = Checksum()
|
|
440
444
|
resource.checksum.value = rdf_value(checksum, SPDX.checksumValue)
|
|
441
445
|
resource.checksum.type = algorithm
|
|
446
|
+
if is_additionnal:
|
|
447
|
+
resource.type = 'other'
|
|
442
448
|
|
|
443
449
|
identifier = rdf_value(distrib, DCT.identifier)
|
|
444
450
|
uri = distrib.identifier.toPython() if isinstance(distrib.identifier, URIRef) else None
|
|
@@ -494,6 +500,9 @@ def dataset_from_rdf(graph, dataset=None, node=None):
|
|
|
494
500
|
elif isinstance(value, RdfResource):
|
|
495
501
|
licenses.add(value.identifier.toPython())
|
|
496
502
|
|
|
503
|
+
for additionnal in d.objects(DCT.hasPart):
|
|
504
|
+
resource_from_rdf(additionnal, dataset, is_additionnal=True)
|
|
505
|
+
|
|
497
506
|
default_license = dataset.license or License.default()
|
|
498
507
|
dataset_license = rdf_value(d, DCT.license)
|
|
499
508
|
dataset.license = License.guess(dataset_license, *licenses, default=default_license)
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
<dcat:distribution rdf:resource="http://data.test.org/datasets/1/resources/1"/>
|
|
62
62
|
<dcterms:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2016-12-14T18:59:02.737480</dcterms:issued>
|
|
63
63
|
<dcterms:identifier>1</dcterms:identifier>
|
|
64
|
+
<dcterms:hasPart rdf:resource="http://data.test.org/datasets/1/resources/3"/>
|
|
64
65
|
</dcat:Dataset>
|
|
65
66
|
</dcat:dataset>
|
|
66
67
|
<dcat:dataset>
|
|
@@ -134,6 +135,10 @@
|
|
|
134
135
|
<dcterms:description>A JSON resource</dcterms:description>
|
|
135
136
|
<dcat:accessURL>http://data.test.org/datasets/3/resources/1/file.json</dcat:accessURL>
|
|
136
137
|
</dcat:Distribution>
|
|
138
|
+
<foaf:Document rdf:about="http://data.test.org/datasets/1/resources/3">
|
|
139
|
+
<dcterms:title>Resource 1-3</dcterms:title>
|
|
140
|
+
<dcterms:format>JSON</dcterms:format>
|
|
141
|
+
</foaf:Document>
|
|
137
142
|
<dcterms:Location rdf:about="http://wuEurope.com/"/>
|
|
138
143
|
<foaf:Organization rdf:about="http://data.test.org/organizations/1">
|
|
139
144
|
<foaf:name>An Organization</foaf:name>
|
|
@@ -297,7 +297,7 @@ class DcatBackendTest:
|
|
|
297
297
|
assert dataset.temporal_coverage.start == date(2016, 1, 1)
|
|
298
298
|
assert dataset.temporal_coverage.end == date(2016, 12, 5)
|
|
299
299
|
|
|
300
|
-
assert len(dataset.resources) ==
|
|
300
|
+
assert len(dataset.resources) == 3
|
|
301
301
|
|
|
302
302
|
resource_1 = next(res for res in dataset.resources if res.title == 'Resource 1-1')
|
|
303
303
|
assert resource_1.filetype == 'remote'
|
|
@@ -307,11 +307,20 @@ class DcatBackendTest:
|
|
|
307
307
|
assert resource_1.filesize == 12323
|
|
308
308
|
assert resource_1.description == 'A JSON resource'
|
|
309
309
|
assert resource_1.url == 'http://data.test.org/datasets/1/resources/1/file.json'
|
|
310
|
+
assert resource_1.type == 'main'
|
|
310
311
|
|
|
311
312
|
resource_2 = next(res for res in dataset.resources if res.title == 'Resource 1-2')
|
|
312
313
|
assert resource_2.format == 'json'
|
|
313
314
|
assert resource_2.description == 'A JSON resource'
|
|
314
315
|
assert resource_2.url == 'http://data.test.org/datasets/1/resources/2/file.json'
|
|
316
|
+
assert resource_2.type == 'main'
|
|
317
|
+
|
|
318
|
+
# Make sure additionnal resource is correctly harvested
|
|
319
|
+
resource_3 = next(res for res in dataset.resources if res.title == 'Resource 1-3')
|
|
320
|
+
assert resource_3.format == 'json'
|
|
321
|
+
assert resource_3.description == ''
|
|
322
|
+
assert resource_3.url == 'http://data.test.org/datasets/1/resources/3'
|
|
323
|
+
assert resource_3.type == 'other'
|
|
315
324
|
|
|
316
325
|
def test_geonetwork_xml_catalog(self, rmock):
|
|
317
326
|
url = mock_dcat(rmock, 'geonetwork.xml', path='catalog.xml')
|
|
@@ -413,7 +422,7 @@ class DcatBackendTest:
|
|
|
413
422
|
error = job.errors[0]
|
|
414
423
|
expected = 'Unable to detect format from extension or mime type'
|
|
415
424
|
assert error.message == expected
|
|
416
|
-
|
|
425
|
+
|
|
417
426
|
def test_use_replaced_uris(self, rmock, mocker):
|
|
418
427
|
mocker.patch.dict(
|
|
419
428
|
URIS_TO_REPLACE,
|
|
@@ -465,7 +474,7 @@ class DcatBackendTest:
|
|
|
465
474
|
assert len(job.errors) == 1
|
|
466
475
|
assert "404 Client Error" in job.errors[0].message
|
|
467
476
|
|
|
468
|
-
|
|
477
|
+
|
|
469
478
|
@pytest.mark.usefixtures('clean_db')
|
|
470
479
|
@pytest.mark.options(PLUGINS=['csw-dcat'])
|
|
471
480
|
class CswDcatBackendTest:
|