udata 10.8.2.dev37001__py2.py3-none-any.whl → 10.8.2.dev37076__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.

@@ -10,7 +10,6 @@ import requests
10
10
  from blinker import signal
11
11
  from dateutil.parser import parse as parse_dt
12
12
  from flask import current_app, url_for
13
- from mongoengine import DynamicEmbeddedDocument
14
13
  from mongoengine import ValidationError as MongoEngineValidationError
15
14
  from mongoengine.fields import DateTimeField
16
15
  from mongoengine.signals import post_save, pre_init, pre_save
@@ -78,7 +77,7 @@ def get_json_ld_extra(key, value):
78
77
  }
79
78
 
80
79
 
81
- class HarvestDatasetMetadata(DynamicEmbeddedDocument):
80
+ class HarvestDatasetMetadata(db.EmbeddedDocument):
82
81
  backend = db.StringField()
83
82
  created_at = db.DateTimeField()
84
83
  modified_at = db.DateTimeField()
@@ -91,12 +90,15 @@ class HarvestDatasetMetadata(DynamicEmbeddedDocument):
91
90
  dct_identifier = db.StringField()
92
91
  archived_at = db.DateTimeField()
93
92
  archived = db.StringField()
93
+ ckan_name = db.StringField()
94
+ ckan_source = db.StringField()
94
95
 
95
96
 
96
- class HarvestResourceMetadata(DynamicEmbeddedDocument):
97
+ class HarvestResourceMetadata(db.EmbeddedDocument):
97
98
  created_at = db.DateTimeField()
98
99
  modified_at = db.DateTimeField()
99
100
  uri = db.StringField()
101
+ dct_identifier = db.StringField()
100
102
 
101
103
 
102
104
  class Schema(db.EmbeddedDocument):
@@ -460,7 +460,7 @@ def test_skip_no_resources(source, result):
460
460
  def test_ckan_url_is_url(data, result):
461
461
  dataset = dataset_for(result)
462
462
  assert dataset.harvest.remote_url == data["url"]
463
- assert not hasattr(dataset.harvest, "ckan_source")
463
+ assert dataset.harvest.ckan_source is None
464
464
 
465
465
 
466
466
  @pytest.mark.ckan_data("ckan_url_is_a_string")
@@ -0,0 +1,29 @@
1
+ """
2
+ This migration removes legacy harvest dynamic fields
3
+ """
4
+
5
+ import logging
6
+
7
+ from mongoengine.connection import get_db
8
+
9
+ log = logging.getLogger(__name__)
10
+
11
+
12
+ def migrate(db):
13
+ # Remove legacy fields (`ods_has_records`, `ods_url`, ...) from old harvested datasets and resources
14
+ dataset_legacy_fields = ["ods_has_records", "ods_url", "ods_geo"]
15
+ for field in dataset_legacy_fields:
16
+ result = get_db().dataset.update_many({}, {"$unset": {f"harvest.{field}": 1}})
17
+ log.info(
18
+ f"Harvest Dataset dynamic legacy fields ({field}) removed from {result.modified_count} objects"
19
+ )
20
+
21
+ resource_legacy_fields = ["ods_type"]
22
+ for field in resource_legacy_fields:
23
+ result = get_db().dataset.update_many(
24
+ {"resources": {"$exists": True, "$type": "array"}},
25
+ {"$unset": {f"resources.$[].harvest.{field}": 1}},
26
+ )
27
+ log.info(
28
+ f"Harvest Resource dynamic legacy fields ({field}) removed from {result.modified_count} objects"
29
+ )
@@ -15,10 +15,6 @@ from udata.api import fields
15
15
  from udata.app import cache
16
16
  from udata.core import storages
17
17
  from udata.core.badges.factories import badge_factory
18
- from udata.core.dataset.api_fields import (
19
- dataset_harvest_fields,
20
- resource_harvest_fields,
21
- )
22
18
  from udata.core.dataset.constants import (
23
19
  DEFAULT_FREQUENCY,
24
20
  DEFAULT_LICENSE,
@@ -2391,10 +2387,6 @@ class DatasetSchemasAPITest:
2391
2387
  class HarvestMetadataAPITest:
2392
2388
  modules = []
2393
2389
 
2394
- # api fields should be updated before app is created
2395
- dataset_harvest_fields["dynamic_field"] = fields.String(description="", allow_null=True)
2396
- resource_harvest_fields["dynamic_field"] = fields.String(description="", allow_null=True)
2397
-
2398
2390
  def test_dataset_with_harvest_metadata(self, api):
2399
2391
  date = datetime(2022, 2, 22, tzinfo=pytz.UTC)
2400
2392
  harvest_metadata = HarvestDatasetMetadata(
@@ -2430,24 +2422,6 @@ class HarvestMetadataAPITest:
2430
2422
  "archived": "not-on-remote",
2431
2423
  }
2432
2424
 
2433
- def test_dataset_dynamic_harvest_metadata_without_api_field(self, api):
2434
- harvest_metadata = HarvestDatasetMetadata(dynamic_field_but_no_api_field_defined="DCAT")
2435
- dataset = DatasetFactory(harvest=harvest_metadata)
2436
-
2437
- response = api.get(url_for("api.dataset", dataset=dataset))
2438
- assert200(response)
2439
- assert response.json["harvest"] == {}
2440
-
2441
- def test_dataset_dynamic_harvest_metadata_with_api_field(self, api):
2442
- harvest_metadata = HarvestDatasetMetadata(dynamic_field="dynamic_value")
2443
- dataset = DatasetFactory(harvest=harvest_metadata)
2444
-
2445
- response = api.get(url_for("api.dataset", dataset=dataset))
2446
- assert200(response)
2447
- assert response.json["harvest"] == {
2448
- "dynamic_field": "dynamic_value",
2449
- }
2450
-
2451
2425
  def test_dataset_with_resource_harvest_metadata(self, api):
2452
2426
  date = datetime(2022, 2, 22, tzinfo=pytz.UTC)
2453
2427
 
@@ -2466,26 +2440,6 @@ class HarvestMetadataAPITest:
2466
2440
  "uri": "http://domain.gouv.fr/dataset/uri",
2467
2441
  }
2468
2442
 
2469
- def test_resource_dynamic_harvest_metadata_without_api_field(self, api):
2470
- harvest_metadata = HarvestResourceMetadata(
2471
- dynamic_field_but_no_api_field_defined="dynamic_value"
2472
- )
2473
- dataset = DatasetFactory(resources=[ResourceFactory(harvest=harvest_metadata)])
2474
-
2475
- response = api.get(url_for("api.dataset", dataset=dataset))
2476
- assert200(response)
2477
- assert response.json["resources"][0]["harvest"] == {}
2478
-
2479
- def test_resource_dynamic_harvest_metadata_with_api_field(self, api):
2480
- harvest_metadata = HarvestResourceMetadata(dynamic_field="dynamic_value")
2481
- dataset = DatasetFactory(resources=[ResourceFactory(harvest=harvest_metadata)])
2482
-
2483
- response = api.get(url_for("api.dataset", dataset=dataset))
2484
- assert200(response)
2485
- assert response.json["resources"][0]["harvest"] == {
2486
- "dynamic_field": "dynamic_value",
2487
- }
2488
-
2489
2443
  def test_dataset_with_harvest_computed_dates(self, api):
2490
2444
  creation_date = datetime(2022, 2, 22, tzinfo=pytz.UTC)
2491
2445
  modification_date = datetime(2022, 3, 19, tzinfo=pytz.UTC)
@@ -789,14 +789,6 @@ class HarvestMetadataTest:
789
789
  with pytest.raises(db.ValidationError):
790
790
  dataset.save()
791
791
 
792
- def test_harvest_dataset_metadata_no_validation_dynamic(self):
793
- # Adding a dynamic field (not defined in HarvestDatasetMetadata) does not raise error
794
- # at validation time
795
- harvest_metadata = HarvestDatasetMetadata(dynamic_created_at="maintenant")
796
- dataset = DatasetFactory()
797
- dataset.harvest = harvest_metadata
798
- dataset.save()
799
-
800
792
  def test_harvest_dataset_metadata_past_modifed_at(self):
801
793
  dataset = DatasetFactory()
802
794
 
@@ -826,14 +818,6 @@ class HarvestMetadataTest:
826
818
  with pytest.raises(db.ValidationError):
827
819
  resource.validate()
828
820
 
829
- def test_harvest_resource_metadata_no_validation_dynamic(self):
830
- # Adding a dynamic field (not defined in HarvestResourceMetadata) does not raise error
831
- # at validation time
832
- harvest_metadata = HarvestResourceMetadata(dynamic_created_at="maintenant")
833
- resource = ResourceFactory()
834
- resource.harvest = harvest_metadata
835
- resource.validate()
836
-
837
821
  def test_harvest_resource_metadata_future_modifed_at(self):
838
822
  resource = ResourceFactory()
839
823
  harvest_metadata = HarvestResourceMetadata(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: udata
3
- Version: 10.8.2.dev37001
3
+ Version: 10.8.2.dev37076
4
4
  Summary: Open data portal
5
5
  Home-page: https://github.com/opendatateam/udata
6
6
  Author: Opendata Team
@@ -151,6 +151,7 @@ It is collectively taken care of by members of the
151
151
  - Fix not returning 404 for harvest sources [#3382](https://github.com/opendatateam/udata/pull/3382/)
152
152
  - Add missing trailing slashes on some endpoints [#3392](https://github.com/opendatateam/udata/pull/3392/)
153
153
  - Make organization name filter case insensitive [#3392](https://github.com/opendatateam/udata/pull/3395)
154
+ - Harvest metadata documents are no longer dynamic [#3396](https://github.com/opendatateam/udata/pull/3396)
154
155
 
155
156
  ## 10.8.1 (2025-07-25)
156
157
 
@@ -106,7 +106,7 @@ udata/core/dataset/events.py,sha256=bSM0nFEX14r4JHc-bAM-7OOuD3JAxUIpw9GgXbOsUyw,
106
106
  udata/core/dataset/exceptions.py,sha256=uKiayLSpSzsnLvClObS6hOO0qXEqvURKN7_w8eimQNU,498
107
107
  udata/core/dataset/factories.py,sha256=fRDWDlybR_ud4pDs1-ntWuYHKtV9LMHeBOBp2SmTT6M,9006
108
108
  udata/core/dataset/forms.py,sha256=7KUxuFcEGT0MUe0cZCiZtsnZhvGgvEd68pe13NgeSMI,6292
109
- udata/core/dataset/models.py,sha256=kkzcuQAFZYT8MHFAGPsDm8atJIDJUaoYuP5_Ed_i5EM,43527
109
+ udata/core/dataset/models.py,sha256=JBIORJcJf1UamIBCpBplKU2L_QjvzmG0FZ3XuhuI3Xw,43577
110
110
  udata/core/dataset/permissions.py,sha256=zXQ6kU-Ni3Pl5tDtat-ZPupug9InsNeCN7xRLc2Vcrc,1097
111
111
  udata/core/dataset/preview.py,sha256=qXmd4-nKvIPtcKLrMqC-aJne4-vMIiq_NubpX39D6I0,855
112
112
  udata/core/dataset/rdf.py,sha256=PFSzkpTFRdpa4cF-mxYU7IV1cJ73m80MmX-GZfWk3hg,30845
@@ -304,7 +304,6 @@ udata/harvest/backends/maaf.py,sha256=N7ty8ZWO9pfKPtZRk1wTaJ5pY6qi-0-GtF1p8jiYiY
304
304
  udata/harvest/backends/maaf.xsd,sha256=vEyG8Vqw7Yn_acjRdXjqUJgxOj4pv8bibep-FX-f3BQ,18322
305
305
  udata/harvest/backends/ckan/__init__.py,sha256=JE7Qa7kX7Yd8OvmJnAO_NupZe0tqYyhhkgJ-iGNxX64,35
306
306
  udata/harvest/backends/ckan/harvesters.py,sha256=WCnO80FJQqve3AaJgRs1tXrlcqmQwZBkTJy3P5xNkjo,10681
307
- udata/harvest/backends/ckan/models.py,sha256=r2cZKMXOkSfq0s0aHOrpB6EuHO0_7uQLYMj773RVxyA,432
308
307
  udata/harvest/backends/ckan/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
309
308
  udata/harvest/backends/ckan/schemas/ckan.py,sha256=59VQoIxPBb5vOHFzzMtdnPcxHL4qNOTkPYa4cqn-7xQ,2353
310
309
  udata/harvest/backends/ckan/schemas/dkan.py,sha256=RyQGPEaKqnunIrr9yApcz7WEfgye0IT1bV85wa2E8Lc,2774
@@ -320,7 +319,7 @@ udata/harvest/tests/test_models.py,sha256=f9NRR2_S4oZFgF8qOumg0vv-lpnEBJbI5vNtcw
320
319
  udata/harvest/tests/test_notifications.py,sha256=MMzTzkv-GXMNFeOwAi31rdTsAXyLCLOSna41zOtaJG0,816
321
320
  udata/harvest/tests/test_tasks.py,sha256=7wQGhaX7xJEPKGAF7dprIDj2_7Z2tTInzvAd5GiqaN8,681
322
321
  udata/harvest/tests/ckan/conftest.py,sha256=SNIRJ7uh6ssIB56mwIdDgteHKUY040yX4gzaGMREjJw,1893
323
- udata/harvest/tests/ckan/test_ckan_backend.py,sha256=1SNuIgzgLljirEc9TB-5jYxq52GHQy77EsQEkF2t5LE,21447
322
+ udata/harvest/tests/ckan/test_ckan_backend.py,sha256=SiuUTquQ-MFYjGIJTJgry88-QIxQIb68sUvoox7l7VY,21439
324
323
  udata/harvest/tests/ckan/test_ckan_backend_errors.py,sha256=LbT-jFz9Fs_WECcQxpuOEEBm2FZ9PdqSbGYxMb1X32c,3847
325
324
  udata/harvest/tests/ckan/test_ckan_backend_filters.py,sha256=_cBXkHihCTvL1jsrH6ppfU6KmyfErXVqGplHVgIHMnU,3698
326
325
  udata/harvest/tests/ckan/test_dkan_backend.py,sha256=9Ym7bFLMj6bqbtdGCpDYm7nSwswbYQM3ksljfpi8z_g,2178
@@ -387,6 +386,7 @@ udata/migrations/2025-06-18-clean-spatial-coverages.py,sha256=aKg9HQwCmHDJSXAGD0
387
386
  udata/migrations/2025-07-18-compute-last-update.py,sha256=K3wSSl9oC8TRbHlvgKeekgPB9fMMVgll1NXtxGUiNyI,680
388
387
  udata/migrations/2025-07-18-redo-count-discussion.py,sha256=BOFTjf0zq_ahnVlYQC-d8fuoLixxyk2vP6JYJXhmvbs,941
389
388
  udata/migrations/2025-07-22-fix-duplicate-contact-points.py,sha256=ZEw2PX1E3jJiDNWLj6Y52zBAIHS-kZSLjBP6gUmA_ho,1789
389
+ udata/migrations/2025-07-30-purge-old-harvest-dynamic-fields.py,sha256=ijeu6WvX6etOJrv0cEMCRJzj1pSetBguF-aUB1-2y_0,1017
390
390
  udata/migrations/__init__.py,sha256=RBCBDaTlLjuMs_Qzwji6Z6T4r7FCGXhESKoxQbT5qAA,11221
391
391
  udata/models/__init__.py,sha256=txbZwa-lRG3mq99eQ9E5YcFWiNUdjDVSyJJvlqUMFfs,1413
392
392
  udata/mongo/__init__.py,sha256=y4Rv-kq3o_kcEulcNpePLzocXPBNpx3Jd82G-VZPaMc,1421
@@ -650,7 +650,7 @@ udata/tests/api/test_auth_api.py,sha256=OMRlY0OQt60j5N4A-N3HdWTuffOjRlFHkz5a3jJF
650
650
  udata/tests/api/test_base_api.py,sha256=2w_vz0eEuq3P3aN-ByvxGc3VZAo7XtgatFfcrzf2uEU,2244
651
651
  udata/tests/api/test_contact_points.py,sha256=Sbb486RTN7HVycna_XB60OnURPSNc7xUity26XsYA4k,8766
652
652
  udata/tests/api/test_dataservices_api.py,sha256=PGl-817qFAHXmIjb3qzpFzp7sVXSq8gwEzG-g01Qnn8,31025
653
- udata/tests/api/test_datasets_api.py,sha256=R15D11LSNPZJx97UhYiGpSkgIUCz_zpSP9dhcgZW3zI,103167
653
+ udata/tests/api/test_datasets_api.py,sha256=R4xX1wNTCwA97XUrVHgPwdPPRXICVCrzSknW9PU1V68,101118
654
654
  udata/tests/api/test_fields.py,sha256=OW85Z5MES5HeWOpapeem8OvR1cIcrqW-xMWpdZO4LZ8,1033
655
655
  udata/tests/api/test_follow_api.py,sha256=4nFXG5pZ_Hf2PJ4KEdHJX_uggjc9RpB8v0fidkAcw9I,5792
656
656
  udata/tests/api/test_me_api.py,sha256=YPd8zmR3zwJKtpSqz8nY1nOOMyXs66INeBwyhg5D0Us,13846
@@ -681,7 +681,7 @@ udata/tests/dataset/test_csv_adapter.py,sha256=7U83RiuSKNVgX-mV45Txp9a828mnWE4eK
681
681
  udata/tests/dataset/test_dataset_actions.py,sha256=bgDjVYjOvu3sX_FCTCzf2snZYSprsqor2nAhIVuokSs,722
682
682
  udata/tests/dataset/test_dataset_commands.py,sha256=zMPJG2wYwKBee2zI65kmboxf59Zqa84DDjT8V5wj9uo,801
683
683
  udata/tests/dataset/test_dataset_events.py,sha256=hlrpoOiBbnX_COUI9Pzdqlp45GZZDqu5piwupbnPiTI,3601
684
- udata/tests/dataset/test_dataset_model.py,sha256=av4RhOnT-52qs-WL1NCn6R2SMa_fzDcoV-06vjccsdw,33891
684
+ udata/tests/dataset/test_dataset_model.py,sha256=5NYgIcl_7w4KJqWMwtNDb4OTXsjIA_gzECXmEoxXj84,33130
685
685
  udata/tests/dataset/test_dataset_rdf.py,sha256=j919psNAH0scn0DIwHNlqiZGFKd_lKOlyTisICNGeOE,44327
686
686
  udata/tests/dataset/test_dataset_recommendations.py,sha256=K52HXGXi9DuUSiSRQWpqTrsFCkYbv7K3upNp0fFp5v8,7068
687
687
  udata/tests/dataset/test_dataset_tasks.py,sha256=n1W2Pg0ez02d66zQG3N93kh7dpR2yLMRDqUI6PnPaI0,3088
@@ -757,9 +757,9 @@ udata/translations/pt/LC_MESSAGES/udata.mo,sha256=ogtEGsjwIkOEtzrI49e57izi-NUim5
757
757
  udata/translations/pt/LC_MESSAGES/udata.po,sha256=1omSlqdMEdwYtzHGalXrtptVk14mlb6JS_8xR8BsznU,48428
758
758
  udata/translations/sr/LC_MESSAGES/udata.mo,sha256=V7unDjO31PNLiRhfEkYU3pU47wWWct-otdL0GDma0S4,28692
759
759
  udata/translations/sr/LC_MESSAGES/udata.po,sha256=wVBipfpPl-DmYeVm5wrlzWWM3oEvuruDVbJHx4I1p8s,55170
760
- udata-10.8.2.dev37001.dist-info/LICENSE,sha256=V8j_M8nAz8PvAOZQocyRDX7keai8UJ9skgmnwqETmdY,34520
761
- udata-10.8.2.dev37001.dist-info/METADATA,sha256=kFNi1RaBP0RrU3VtSjl25Gee1M5-8Hz8Vkd1wrtad3k,152929
762
- udata-10.8.2.dev37001.dist-info/WHEEL,sha256=Kh9pAotZVRFj97E15yTA4iADqXdQfIVTHcNaZTjxeGM,110
763
- udata-10.8.2.dev37001.dist-info/entry_points.txt,sha256=v2u12qO11i2lyLNIp136WmLJ-NHT-Kew3Duu8J-AXPM,614
764
- udata-10.8.2.dev37001.dist-info/top_level.txt,sha256=39OCg-VWFWOq4gCKnjKNu-s3OwFlZIu_dVH8Gl6ndHw,12
765
- udata-10.8.2.dev37001.dist-info/RECORD,,
760
+ udata-10.8.2.dev37076.dist-info/LICENSE,sha256=V8j_M8nAz8PvAOZQocyRDX7keai8UJ9skgmnwqETmdY,34520
761
+ udata-10.8.2.dev37076.dist-info/METADATA,sha256=cDKSCXXtTtNalqZpf-abrvdlCtpSnkSp647y2x3dO3I,153037
762
+ udata-10.8.2.dev37076.dist-info/WHEEL,sha256=Kh9pAotZVRFj97E15yTA4iADqXdQfIVTHcNaZTjxeGM,110
763
+ udata-10.8.2.dev37076.dist-info/entry_points.txt,sha256=v2u12qO11i2lyLNIp136WmLJ-NHT-Kew3Duu8J-AXPM,614
764
+ udata-10.8.2.dev37076.dist-info/top_level.txt,sha256=39OCg-VWFWOq4gCKnjKNu-s3OwFlZIu_dVH8Gl6ndHw,12
765
+ udata-10.8.2.dev37076.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- from udata.api import fields
2
- from udata.core.dataset.api_fields import dataset_harvest_fields
3
-
4
- # Register additional harvest fields to serve by api
5
- dataset_harvest_fields["ckan_name"] = fields.String(
6
- description="The ckan name property for ckan harvested dataset", allow_null=True
7
- )
8
- dataset_harvest_fields["ckan_source"] = fields.String(
9
- description="The ckan source property for ckan harvested dataset", allow_null=True
10
- )