udata 10.0.9.dev33787__py2.py3-none-any.whl → 10.0.9.dev33847__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/commands/fixtures.py +42 -8
- udata/commands/tests/test_fixtures.py +12 -2
- udata/core/contact_point/api.py +13 -1
- udata/core/contact_point/api_fields.py +10 -1
- udata/core/contact_point/factories.py +3 -1
- udata/core/contact_point/forms.py +1 -0
- udata/core/contact_point/models.py +9 -1
- udata/core/dataservices/models.py +11 -4
- udata/core/dataservices/rdf.py +12 -6
- udata/core/dataset/api.py +1 -0
- udata/core/dataset/api_fields.py +3 -3
- udata/core/dataset/apiv2.py +5 -3
- udata/core/dataset/forms.py +4 -4
- udata/core/dataset/models.py +1 -1
- udata/core/dataset/rdf.py +23 -13
- udata/forms/fields.py +1 -4
- udata/harvest/api.py +5 -1
- udata/harvest/tests/dcat/evian.json +1 -1
- udata/harvest/tests/test_dcat_backend.py +5 -5
- udata/migrations/2024-12-05-contact-point-is-now-a-list.py +33 -0
- udata/rdf.py +75 -44
- udata/static/chunks/{10.471164b2a9fe15614797.js → 10.8ca60413647062717b1e.js} +3 -3
- udata/static/chunks/{10.471164b2a9fe15614797.js.map → 10.8ca60413647062717b1e.js.map} +1 -1
- udata/static/chunks/{11.51d706fb9521c16976bc.js → 11.0f04e49a40a0a381bcce.js} +3 -3
- udata/static/chunks/{11.51d706fb9521c16976bc.js.map → 11.0f04e49a40a0a381bcce.js.map} +1 -1
- udata/static/chunks/{13.f29411b06be1883356a3.js → 13.d9c1735d14038b94c17e.js} +2 -2
- udata/static/chunks/{13.f29411b06be1883356a3.js.map → 13.d9c1735d14038b94c17e.js.map} +1 -1
- udata/static/chunks/{17.3bd0340930d4a314ce9c.js → 17.81c57c0dedf812e43013.js} +2 -2
- udata/static/chunks/{17.3bd0340930d4a314ce9c.js.map → 17.81c57c0dedf812e43013.js.map} +1 -1
- udata/static/chunks/{8.54e44b102164ae5e7a67.js → 8.494b003a94383b142c18.js} +2 -2
- udata/static/chunks/{8.54e44b102164ae5e7a67.js.map → 8.494b003a94383b142c18.js.map} +1 -1
- udata/static/chunks/{9.07515e5187f475bce828.js → 9.033d7e190ca9e226a5d0.js} +3 -3
- udata/static/chunks/{9.07515e5187f475bce828.js.map → 9.033d7e190ca9e226a5d0.js.map} +1 -1
- udata/static/common.js +1 -1
- udata/static/common.js.map +1 -1
- udata/tests/api/test_contact_points.py +36 -5
- udata/tests/api/test_dataservices_api.py +2 -2
- udata/tests/api/test_datasets_api.py +8 -6
- udata/tests/api/test_organizations_api.py +1 -0
- udata/tests/api/test_user_api.py +1 -0
- udata/tests/contact_point/test_contact_point_models.py +19 -0
- udata/tests/dataset/test_dataset_rdf.py +30 -3
- udata/tests/organization/test_organization_tasks.py +1 -0
- udata/tests/test_rdf.py +41 -7
- udata/translations/udata.pot +23 -7
- {udata-10.0.9.dev33787.dist-info → udata-10.0.9.dev33847.dist-info}/METADATA +3 -1
- {udata-10.0.9.dev33787.dist-info → udata-10.0.9.dev33847.dist-info}/RECORD +51 -49
- {udata-10.0.9.dev33787.dist-info → udata-10.0.9.dev33847.dist-info}/LICENSE +0 -0
- {udata-10.0.9.dev33787.dist-info → udata-10.0.9.dev33847.dist-info}/WHEEL +0 -0
- {udata-10.0.9.dev33787.dist-info → udata-10.0.9.dev33847.dist-info}/entry_points.txt +0 -0
- {udata-10.0.9.dev33787.dist-info → udata-10.0.9.dev33847.dist-info}/top_level.txt +0 -0
udata/rdf.py
CHANGED
|
@@ -6,6 +6,7 @@ import logging
|
|
|
6
6
|
import re
|
|
7
7
|
from html.parser import HTMLParser
|
|
8
8
|
|
|
9
|
+
import mongoengine
|
|
9
10
|
from flask import abort, current_app, request, url_for
|
|
10
11
|
from rdflib import BNode, Graph, Literal, URIRef
|
|
11
12
|
from rdflib.namespace import (
|
|
@@ -47,6 +48,7 @@ EUFORMAT = Namespace("http://publications.europa.eu/resource/authority/file-type
|
|
|
47
48
|
IANAFORMAT = Namespace("https://www.iana.org/assignments/media-types/")
|
|
48
49
|
DCT = DCTERMS # More common usage
|
|
49
50
|
VCARD = Namespace("http://www.w3.org/2006/vcard/ns#")
|
|
51
|
+
GEODCAT = Namespace("http://data.europa.eu/930/")
|
|
50
52
|
|
|
51
53
|
namespace_manager = NamespaceManager(Graph())
|
|
52
54
|
namespace_manager.bind("adms", ADMS)
|
|
@@ -127,6 +129,19 @@ EU_HVD_CATEGORIES = {
|
|
|
127
129
|
HVD_LEGISLATION = "http://data.europa.eu/eli/reg_impl/2023/138/oj"
|
|
128
130
|
TAG_TO_EU_HVD_CATEGORIES = {slugify_tag(EU_HVD_CATEGORIES[uri]): uri for uri in EU_HVD_CATEGORIES}
|
|
129
131
|
|
|
132
|
+
AGENT_ROLE_TO_RDF_PREDICATE = {
|
|
133
|
+
"contact": DCAT.contactPoint,
|
|
134
|
+
"publisher": DCT.publisher,
|
|
135
|
+
"creator": DCT.creator,
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
# Map rdf contact point entity to role
|
|
139
|
+
CONTACT_POINT_ENTITY_TO_ROLE = {
|
|
140
|
+
DCAT.contactPoint: "contact",
|
|
141
|
+
DCT.publisher: "publisher",
|
|
142
|
+
DCT.creator: "creator",
|
|
143
|
+
}
|
|
144
|
+
|
|
130
145
|
|
|
131
146
|
def guess_format(string):
|
|
132
147
|
"""Guess format given an extension or a mime-type"""
|
|
@@ -294,61 +309,77 @@ def themes_from_rdf(rdf):
|
|
|
294
309
|
return list(set(tags))
|
|
295
310
|
|
|
296
311
|
|
|
297
|
-
def
|
|
298
|
-
contact_point
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
email = email.replace("mailto:", "").strip() if email else None
|
|
307
|
-
contact_form = rdf_value(contact_point, VCARD.hasUrl)
|
|
308
|
-
if not email and not contact_form:
|
|
309
|
-
return
|
|
310
|
-
if dataset.organization:
|
|
311
|
-
contact, _ = ContactPoint.objects.get_or_create(
|
|
312
|
-
name=name, email=email, contact_form=contact_form, organization=dataset.organization
|
|
312
|
+
def contact_points_from_rdf(rdf, prop, role, dataset):
|
|
313
|
+
for contact_point in rdf.objects(prop):
|
|
314
|
+
# Read contact point information
|
|
315
|
+
if prop == DCAT.contactPoint: # Could be split on the type of contact_point instead
|
|
316
|
+
name = rdf_value(contact_point, VCARD.fn) or ""
|
|
317
|
+
email = (
|
|
318
|
+
rdf_value(contact_point, VCARD.hasEmail)
|
|
319
|
+
or rdf_value(contact_point, VCARD.email)
|
|
320
|
+
or rdf_value(contact_point, DCAT.email)
|
|
313
321
|
)
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
322
|
+
email = email.replace("mailto:", "").strip() if email else None
|
|
323
|
+
contact_form = rdf_value(contact_point, VCARD.hasUrl)
|
|
324
|
+
else:
|
|
325
|
+
name = (
|
|
326
|
+
rdf_value(contact_point, FOAF.name)
|
|
327
|
+
or rdf_value(contact_point, SKOS.prefLabel)
|
|
328
|
+
or ""
|
|
317
329
|
)
|
|
330
|
+
email = rdf_value(contact_point, FOAF.mbox)
|
|
331
|
+
email = email.replace("mailto:", "").strip() if email else None
|
|
332
|
+
contact_form = None
|
|
333
|
+
|
|
334
|
+
# Tested at validation time, because it depends on the role
|
|
335
|
+
# if not email and not contact_form:
|
|
336
|
+
# continue
|
|
337
|
+
|
|
338
|
+
# Create of get contact point object
|
|
339
|
+
if not dataset.organization and not dataset.owner:
|
|
340
|
+
continue
|
|
341
|
+
org_or_owner = {}
|
|
342
|
+
if dataset.organization:
|
|
343
|
+
org_or_owner = {"organization": dataset.organization}
|
|
318
344
|
else:
|
|
319
|
-
|
|
320
|
-
|
|
345
|
+
org_or_owner = {"owner": dataset.owner}
|
|
346
|
+
try:
|
|
347
|
+
contact, _ = ContactPoint.objects.get_or_create(
|
|
348
|
+
name=name, email=email, contact_form=contact_form, role=role, **org_or_owner
|
|
349
|
+
)
|
|
350
|
+
except mongoengine.errors.ValidationError as validation_error:
|
|
351
|
+
log.warning(f"Unable to validate contact point: {validation_error}", exc_info=True)
|
|
352
|
+
continue
|
|
353
|
+
yield contact
|
|
321
354
|
|
|
322
355
|
|
|
323
|
-
def
|
|
356
|
+
def contact_points_to_rdf(contacts, graph=None):
|
|
324
357
|
"""
|
|
325
358
|
Map a contact point to a DCAT/RDF graph
|
|
326
359
|
"""
|
|
327
|
-
if not contact:
|
|
328
|
-
return None
|
|
329
|
-
|
|
330
360
|
graph = graph or Graph(namespace_manager=namespace_manager)
|
|
331
361
|
|
|
332
|
-
|
|
333
|
-
id
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
362
|
+
for contact in contacts:
|
|
363
|
+
if contact.id:
|
|
364
|
+
id = URIRef(
|
|
365
|
+
endpoint_for(
|
|
366
|
+
"api.contact_point",
|
|
367
|
+
contact_point=contact.id,
|
|
368
|
+
_external=True,
|
|
369
|
+
)
|
|
338
370
|
)
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
node.
|
|
351
|
-
return node
|
|
371
|
+
else:
|
|
372
|
+
id = BNode()
|
|
373
|
+
|
|
374
|
+
node = graph.resource(id)
|
|
375
|
+
node.set(RDF.type, VCARD.Kind)
|
|
376
|
+
if contact.name:
|
|
377
|
+
node.set(VCARD.fn, Literal(contact.name))
|
|
378
|
+
if contact.email:
|
|
379
|
+
node.set(VCARD.hasEmail, URIRef(f"mailto:{contact.email}"))
|
|
380
|
+
if contact.contact_form:
|
|
381
|
+
node.set(VCARD.hasUrl, URIRef(contact.contact_form))
|
|
382
|
+
yield node, AGENT_ROLE_TO_RDF_PREDICATE.get(contact.role, DCAT.contactPoint)
|
|
352
383
|
|
|
353
384
|
|
|
354
385
|
def primary_topic_identifier_from_rdf(graph: Graph, resource: RdfResource):
|