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.

Files changed (36) hide show
  1. udata/core/dataset/api.py +2 -2
  2. udata/core/dataset/api_fields.py +3 -4
  3. udata/core/dataset/apiv2.py +6 -6
  4. udata/core/dataset/constants.py +124 -38
  5. udata/core/dataset/factories.py +2 -1
  6. udata/core/dataset/forms.py +14 -10
  7. udata/core/dataset/models.py +8 -36
  8. udata/core/dataset/rdf.py +76 -54
  9. udata/core/dataset/tasks.py +4 -9
  10. udata/harvest/backends/ckan/harvesters.py +10 -14
  11. udata/harvest/backends/maaf.py +15 -14
  12. udata/harvest/tests/ckan/test_ckan_backend.py +4 -3
  13. udata/harvest/tests/test_dcat_backend.py +3 -2
  14. udata/migrations/2025-09-04-update-legacy-frequencies.py +36 -0
  15. udata/static/chunks/{11.55ab79044cda0271b595.js → 11.51d706fb9521c16976bc.js} +3 -3
  16. udata/static/chunks/{11.55ab79044cda0271b595.js.map → 11.51d706fb9521c16976bc.js.map} +1 -1
  17. udata/static/chunks/{13.d9c1735d14038b94c17e.js → 13.f29411b06be1883356a3.js} +2 -2
  18. udata/static/chunks/{13.d9c1735d14038b94c17e.js.map → 13.f29411b06be1883356a3.js.map} +1 -1
  19. udata/static/chunks/{17.81c57c0dedf812e43013.js → 17.3bd0340930d4a314ce9c.js} +2 -2
  20. udata/static/chunks/{17.81c57c0dedf812e43013.js.map → 17.3bd0340930d4a314ce9c.js.map} +1 -1
  21. udata/static/chunks/{19.3e0e8651d948e04b8cf2.js → 19.ba0bb2baa40e899d440b.js} +3 -3
  22. udata/static/chunks/{19.3e0e8651d948e04b8cf2.js.map → 19.ba0bb2baa40e899d440b.js.map} +1 -1
  23. udata/static/chunks/{8.494b003a94383b142c18.js → 8.b966402f5d680d4bdf4a.js} +2 -2
  24. udata/static/chunks/{8.494b003a94383b142c18.js.map → 8.b966402f5d680d4bdf4a.js.map} +1 -1
  25. udata/static/common.js +1 -1
  26. udata/static/common.js.map +1 -1
  27. udata/tests/api/test_datasets_api.py +41 -12
  28. udata/tests/dataset/test_dataset_model.py +17 -53
  29. udata/tests/dataset/test_dataset_rdf.py +27 -28
  30. udata/translations/udata.pot +226 -150
  31. {udata-11.1.2.dev9.dist-info → udata-11.1.2.dev10.dist-info}/METADATA +1 -1
  32. {udata-11.1.2.dev9.dist-info → udata-11.1.2.dev10.dist-info}/RECORD +36 -35
  33. {udata-11.1.2.dev9.dist-info → udata-11.1.2.dev10.dist-info}/WHEEL +0 -0
  34. {udata-11.1.2.dev9.dist-info → udata-11.1.2.dev10.dist-info}/entry_points.txt +0 -0
  35. {udata-11.1.2.dev9.dist-info → udata-11.1.2.dev10.dist-info}/licenses/LICENSE +0 -0
  36. {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.harvest.models import HarvestItem
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 = frequency_from_rdf(value)
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
- dataset.extras["ckan:frequency"] = value
203
- log.debug("frequency value not handled: %s", value)
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)
@@ -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": "punctual",
42
- "temps réel": "continuous",
43
- "quotidienne": "daily",
44
- "hebdomadaire": "weekly",
45
- "bimensuelle": "semimonthly",
46
- "mensuelle": "monthly",
47
- "bimestrielle": "bimonthly",
48
- "trimestrielle": "quarterly",
49
- "semestrielle": "semiannual",
50
- "annuelle": "annual",
51
- "triennale": "triennial",
52
- "quinquennale": "quinquennial",
53
- "aucune": "unknown",
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"], "unknown")
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": "daily"}
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": "daily"}
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 test_can_parse_frequency_as_unkown_value(result, kwargs):
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 == "daily"
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 == "irregular"
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.")