udata 11.1.2.dev9__py3-none-any.whl → 11.1.2.dev10__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/api.py +2 -2
- udata/core/dataset/api_fields.py +3 -4
- udata/core/dataset/apiv2.py +6 -6
- udata/core/dataset/constants.py +124 -38
- udata/core/dataset/factories.py +2 -1
- udata/core/dataset/forms.py +14 -10
- udata/core/dataset/models.py +8 -36
- udata/core/dataset/rdf.py +76 -54
- udata/core/dataset/tasks.py +4 -9
- udata/harvest/backends/ckan/harvesters.py +10 -14
- udata/harvest/backends/maaf.py +15 -14
- udata/harvest/tests/ckan/test_ckan_backend.py +4 -3
- udata/harvest/tests/test_dcat_backend.py +3 -2
- udata/migrations/2025-09-04-update-legacy-frequencies.py +36 -0
- udata/static/chunks/{11.55ab79044cda0271b595.js → 11.51d706fb9521c16976bc.js} +3 -3
- udata/static/chunks/{11.55ab79044cda0271b595.js.map → 11.51d706fb9521c16976bc.js.map} +1 -1
- udata/static/chunks/{13.d9c1735d14038b94c17e.js → 13.f29411b06be1883356a3.js} +2 -2
- udata/static/chunks/{13.d9c1735d14038b94c17e.js.map → 13.f29411b06be1883356a3.js.map} +1 -1
- udata/static/chunks/{17.81c57c0dedf812e43013.js → 17.3bd0340930d4a314ce9c.js} +2 -2
- udata/static/chunks/{17.81c57c0dedf812e43013.js.map → 17.3bd0340930d4a314ce9c.js.map} +1 -1
- udata/static/chunks/{19.3e0e8651d948e04b8cf2.js → 19.ba0bb2baa40e899d440b.js} +3 -3
- udata/static/chunks/{19.3e0e8651d948e04b8cf2.js.map → 19.ba0bb2baa40e899d440b.js.map} +1 -1
- udata/static/chunks/{8.494b003a94383b142c18.js → 8.b966402f5d680d4bdf4a.js} +2 -2
- udata/static/chunks/{8.494b003a94383b142c18.js.map → 8.b966402f5d680d4bdf4a.js.map} +1 -1
- udata/static/common.js +1 -1
- udata/static/common.js.map +1 -1
- udata/tests/api/test_datasets_api.py +41 -12
- udata/tests/dataset/test_dataset_model.py +17 -53
- udata/tests/dataset/test_dataset_rdf.py +27 -28
- udata/translations/udata.pot +226 -150
- {udata-11.1.2.dev9.dist-info → udata-11.1.2.dev10.dist-info}/METADATA +1 -1
- {udata-11.1.2.dev9.dist-info → udata-11.1.2.dev10.dist-info}/RECORD +36 -35
- {udata-11.1.2.dev9.dist-info → udata-11.1.2.dev10.dist-info}/WHEEL +0 -0
- {udata-11.1.2.dev9.dist-info → udata-11.1.2.dev10.dist-info}/entry_points.txt +0 -0
- {udata-11.1.2.dev9.dist-info → udata-11.1.2.dev10.dist-info}/licenses/LICENSE +0 -0
- {udata-11.1.2.dev9.dist-info → udata-11.1.2.dev10.dist-info}/top_level.txt +0 -0
|
@@ -4,19 +4,14 @@ from urllib.parse import urljoin
|
|
|
4
4
|
from uuid import UUID
|
|
5
5
|
|
|
6
6
|
from udata import uris
|
|
7
|
-
from udata.
|
|
8
|
-
from udata.i18n import lazy_gettext as _
|
|
9
|
-
|
|
10
|
-
try:
|
|
11
|
-
from udata.core.dataset.constants import UPDATE_FREQUENCIES
|
|
12
|
-
except ImportError:
|
|
13
|
-
# legacy import of constants in udata
|
|
14
|
-
from udata.models import UPDATE_FREQUENCIES
|
|
7
|
+
from udata.core.dataset.constants import UpdateFrequency
|
|
15
8
|
from udata.core.dataset.models import HarvestDatasetMetadata, HarvestResourceMetadata
|
|
16
9
|
from udata.core.dataset.rdf import frequency_from_rdf
|
|
17
10
|
from udata.frontend.markdown import parse_html
|
|
18
11
|
from udata.harvest.backends.base import BaseBackend, HarvestFilter
|
|
19
12
|
from udata.harvest.exceptions import HarvestException, HarvestSkipException
|
|
13
|
+
from udata.harvest.models import HarvestItem
|
|
14
|
+
from udata.i18n import lazy_gettext as _
|
|
20
15
|
from udata.models import GeoZone, License, Resource, SpatialCoverage, db
|
|
21
16
|
from udata.utils import daterange_end, daterange_start, get_by
|
|
22
17
|
|
|
@@ -193,14 +188,15 @@ class CkanBackend(BaseBackend):
|
|
|
193
188
|
log.debug("spatial-uri value not handled: %s", value)
|
|
194
189
|
elif key == "frequency":
|
|
195
190
|
# Update frequency
|
|
196
|
-
freq
|
|
197
|
-
if freq:
|
|
191
|
+
if freq := frequency_from_rdf(value):
|
|
198
192
|
dataset.frequency = freq
|
|
199
|
-
elif value in UPDATE_FREQUENCIES:
|
|
200
|
-
dataset.frequency = value
|
|
201
193
|
else:
|
|
202
|
-
|
|
203
|
-
|
|
194
|
+
# FIXME(python 3.12+): prefer `if value in UpdateFrequency`
|
|
195
|
+
try:
|
|
196
|
+
dataset.frequency = UpdateFrequency(value)
|
|
197
|
+
except ValueError:
|
|
198
|
+
dataset.extras["ckan:frequency"] = value
|
|
199
|
+
log.debug("frequency value not handled: %s", value)
|
|
204
200
|
# Temporal coverage start
|
|
205
201
|
elif key == "temporal_start":
|
|
206
202
|
temporal_start = daterange_start(value)
|
udata/harvest/backends/maaf.py
CHANGED
|
@@ -7,6 +7,7 @@ from urllib.parse import urljoin
|
|
|
7
7
|
from lxml import etree, html
|
|
8
8
|
from voluptuous import All, Any, In, Length, Lower, Optional, Schema
|
|
9
9
|
|
|
10
|
+
from udata.core.dataset.constants import UpdateFrequency
|
|
10
11
|
from udata.harvest.backends import BaseBackend
|
|
11
12
|
from udata.harvest.filters import (
|
|
12
13
|
boolean,
|
|
@@ -38,19 +39,19 @@ ZONES = {
|
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
FREQUENCIES = {
|
|
41
|
-
"ponctuelle":
|
|
42
|
-
"temps réel":
|
|
43
|
-
"quotidienne":
|
|
44
|
-
"hebdomadaire":
|
|
45
|
-
"bimensuelle":
|
|
46
|
-
"mensuelle":
|
|
47
|
-
"bimestrielle":
|
|
48
|
-
"trimestrielle":
|
|
49
|
-
"semestrielle":
|
|
50
|
-
"annuelle":
|
|
51
|
-
"triennale":
|
|
52
|
-
"quinquennale":
|
|
53
|
-
"aucune":
|
|
42
|
+
"ponctuelle": UpdateFrequency.PUNCTUAL,
|
|
43
|
+
"temps réel": UpdateFrequency.CONTINUOUS,
|
|
44
|
+
"quotidienne": UpdateFrequency.DAILY,
|
|
45
|
+
"hebdomadaire": UpdateFrequency.WEEKLY,
|
|
46
|
+
"bimensuelle": UpdateFrequency.SEMIMONTHLY,
|
|
47
|
+
"mensuelle": UpdateFrequency.MONTHLY,
|
|
48
|
+
"bimestrielle": UpdateFrequency.BIMONTHLY,
|
|
49
|
+
"trimestrielle": UpdateFrequency.QUARTERLY,
|
|
50
|
+
"semestrielle": UpdateFrequency.SEMIANNUAL,
|
|
51
|
+
"annuelle": UpdateFrequency.ANNUAL,
|
|
52
|
+
"triennale": UpdateFrequency.TRIENNIAL,
|
|
53
|
+
"quinquennale": UpdateFrequency.QUINQUENNIAL,
|
|
54
|
+
"aucune": UpdateFrequency.UNKNOWN,
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
XSD_PATH = os.path.join(os.path.dirname(__file__), "maaf.xsd")
|
|
@@ -161,7 +162,7 @@ class MaafBackend(BaseBackend):
|
|
|
161
162
|
dataset = self.get_dataset(item.remote_id)
|
|
162
163
|
|
|
163
164
|
dataset.title = metadata["title"]
|
|
164
|
-
dataset.frequency = FREQUENCIES.get(metadata["frequency"],
|
|
165
|
+
dataset.frequency = FREQUENCIES.get(metadata["frequency"], UpdateFrequency.UNKNOWN)
|
|
165
166
|
dataset.description = metadata["notes"]
|
|
166
167
|
dataset.private = metadata["private"]
|
|
167
168
|
dataset.tags = sorted(set(metadata["tags"]))
|
|
@@ -5,6 +5,7 @@ from datetime import date
|
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
7
7
|
from udata.app import create_app
|
|
8
|
+
from udata.core.dataset.constants import UpdateFrequency
|
|
8
9
|
from udata.core.organization.factories import OrganizationFactory
|
|
9
10
|
from udata.core.spatial.factories import GeoZoneFactory
|
|
10
11
|
from udata.harvest import actions
|
|
@@ -336,7 +337,7 @@ def frequency_as_rdf_uri(resource_data):
|
|
|
336
337
|
"resources": [resource_data],
|
|
337
338
|
"extras": [{"key": "frequency", "value": "http://purl.org/cld/freq/daily"}],
|
|
338
339
|
}
|
|
339
|
-
return data, {"expected":
|
|
340
|
+
return data, {"expected": UpdateFrequency.DAILY}
|
|
340
341
|
|
|
341
342
|
|
|
342
343
|
@pytest.fixture
|
|
@@ -348,7 +349,7 @@ def frequency_as_exact_match(resource_data):
|
|
|
348
349
|
"resources": [resource_data],
|
|
349
350
|
"extras": [{"key": "frequency", "value": "daily"}],
|
|
350
351
|
}
|
|
351
|
-
return data, {"expected":
|
|
352
|
+
return data, {"expected": UpdateFrequency.DAILY}
|
|
352
353
|
|
|
353
354
|
|
|
354
355
|
@pytest.fixture
|
|
@@ -486,7 +487,7 @@ def test_can_parse_frequency_as_exact_match(result, kwargs):
|
|
|
486
487
|
|
|
487
488
|
|
|
488
489
|
@pytest.mark.ckan_data("frequency_as_unknown_value")
|
|
489
|
-
def
|
|
490
|
+
def test_can_parse_frequency_as_unknown_value(result, kwargs):
|
|
490
491
|
dataset = dataset_for(result)
|
|
491
492
|
assert dataset.extras["ckan:frequency"] == kwargs["expected"]
|
|
492
493
|
assert dataset.frequency is None
|
|
@@ -10,6 +10,7 @@ from rdflib import Graph
|
|
|
10
10
|
|
|
11
11
|
from udata.core.dataservices.factories import DataserviceFactory
|
|
12
12
|
from udata.core.dataservices.models import Dataservice
|
|
13
|
+
from udata.core.dataset.constants import UpdateFrequency
|
|
13
14
|
from udata.core.dataset.factories import DatasetFactory, LicenseFactory, ResourceSchemaMockData
|
|
14
15
|
from udata.core.dataset.rdf import dataset_from_rdf
|
|
15
16
|
from udata.core.organization.factories import OrganizationFactory
|
|
@@ -560,7 +561,7 @@ class DcatBackendTest:
|
|
|
560
561
|
assert dataset.harvest.issued_at.date() == date(2016, 12, 14)
|
|
561
562
|
assert dataset.harvest.created_at.date() == date(2016, 12, 12)
|
|
562
563
|
assert dataset.harvest.modified_at.date() == date(2016, 12, 14)
|
|
563
|
-
assert dataset.frequency ==
|
|
564
|
+
assert dataset.frequency == UpdateFrequency.DAILY
|
|
564
565
|
assert dataset.description == "Dataset 3 description"
|
|
565
566
|
|
|
566
567
|
assert dataset.temporal_coverage is not None
|
|
@@ -681,7 +682,7 @@ class DcatBackendTest:
|
|
|
681
682
|
dataset = Dataset.objects.filter(organization=org).first()
|
|
682
683
|
|
|
683
684
|
assert dataset is not None
|
|
684
|
-
assert dataset.frequency ==
|
|
685
|
+
assert dataset.frequency == UpdateFrequency.IRREGULAR
|
|
685
686
|
assert "gravi" in dataset.tags # support dcat:keyword
|
|
686
687
|
assert "geodesy" in dataset.tags # support dcat:theme
|
|
687
688
|
assert dataset.license.id == "fr-lo"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Convert legacy frequencies to latest vocabulary
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
from udata.core.dataset.constants import UpdateFrequency
|
|
8
|
+
from udata.models import Dataset
|
|
9
|
+
|
|
10
|
+
log = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def migrate(db):
|
|
14
|
+
log.info("Updating datasets legacy frequencies:")
|
|
15
|
+
|
|
16
|
+
for legacy_value, frequency in UpdateFrequency._LEGACY_FREQUENCIES.items():
|
|
17
|
+
count = 0
|
|
18
|
+
for dataset in Dataset.objects(frequency=legacy_value).no_cache().timeout(False):
|
|
19
|
+
# Explicitly call update() to force writing the new frequency string to mongo.
|
|
20
|
+
# We can't rely on save() here because:
|
|
21
|
+
# 1. save() only writes modified fields to mongo, basically comparing the Dataset's
|
|
22
|
+
# object state initially returned by the query with its state when save() is called,
|
|
23
|
+
# and only sending the diffset to mongo.
|
|
24
|
+
# 2. At the ODM layer, the Dataset.frequency field has already been instantiated as an
|
|
25
|
+
# UpdateFrequency object, and so legacy frequency strings have already been
|
|
26
|
+
# mapped to their new ids (via UpdateFrequency._missing_).
|
|
27
|
+
# => While the raw frequency string has changed, the save() function sees the same
|
|
28
|
+
# UpdateFrequency and therefore ignores the field in is diffset.
|
|
29
|
+
dataset.update(frequency=frequency.value)
|
|
30
|
+
# Still call save() afterwards so computed fields like quality_cached are updated if
|
|
31
|
+
# necessary, e.g. if moving from a predictable timedelta to an unpredictable one.
|
|
32
|
+
dataset.save()
|
|
33
|
+
count += 1
|
|
34
|
+
log.info(f"- {legacy_value} -> {frequency.value}: {count} updated")
|
|
35
|
+
|
|
36
|
+
log.info("Completed.")
|