udata 12.0.2.dev15__py3-none-any.whl → 13.0.1.dev21__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/api/__init__.py +1 -0
- udata/api_fields.py +10 -4
- udata/app.py +11 -10
- udata/auth/__init__.py +9 -10
- udata/auth/mails.py +137 -45
- udata/auth/views.py +5 -12
- udata/commands/__init__.py +2 -3
- udata/commands/info.py +1 -3
- udata/commands/tests/test_fixtures.py +6 -3
- udata/core/access_type/api.py +18 -0
- udata/core/access_type/constants.py +98 -0
- udata/core/access_type/models.py +44 -0
- udata/core/activity/models.py +1 -1
- udata/core/badges/models.py +1 -1
- udata/core/badges/tasks.py +35 -1
- udata/core/badges/tests/test_commands.py +2 -4
- udata/core/badges/tests/test_model.py +2 -2
- udata/core/badges/tests/test_tasks.py +55 -0
- udata/core/constants.py +1 -0
- udata/core/contact_point/models.py +8 -0
- udata/core/dataservices/api.py +3 -3
- udata/core/dataservices/apiv2.py +3 -1
- udata/core/dataservices/constants.py +0 -29
- udata/core/dataservices/models.py +44 -44
- udata/core/dataservices/rdf.py +2 -1
- udata/core/dataservices/search.py +5 -9
- udata/core/dataservices/tasks.py +33 -0
- udata/core/dataset/api_fields.py +11 -0
- udata/core/dataset/apiv2.py +11 -0
- udata/core/dataset/constants.py +0 -1
- udata/core/dataset/forms.py +29 -0
- udata/core/dataset/models.py +16 -4
- udata/core/dataset/rdf.py +2 -1
- udata/core/dataset/search.py +2 -2
- udata/core/dataset/tasks.py +86 -8
- udata/core/discussions/mails.py +63 -0
- udata/core/discussions/tasks.py +4 -18
- udata/core/metrics/__init__.py +0 -6
- udata/core/organization/api.py +3 -1
- udata/core/organization/mails.py +144 -0
- udata/core/organization/models.py +2 -1
- udata/core/organization/search.py +1 -1
- udata/core/organization/tasks.py +21 -49
- udata/core/pages/tests/test_api.py +0 -2
- udata/core/reuse/api.py +27 -1
- udata/core/reuse/mails.py +21 -0
- udata/core/reuse/models.py +10 -1
- udata/core/reuse/search.py +1 -1
- udata/core/reuse/tasks.py +2 -3
- udata/core/site/models.py +2 -6
- udata/core/spatial/tests/test_api.py +17 -20
- udata/core/spatial/tests/test_models.py +3 -3
- udata/core/user/mails.py +54 -0
- udata/core/user/models.py +2 -3
- udata/core/user/tasks.py +8 -23
- udata/core/user/tests/test_user_model.py +2 -6
- udata/entrypoints.py +0 -5
- udata/features/identicon/tests/test_backends.py +3 -13
- udata/forms/fields.py +3 -3
- udata/forms/widgets.py +2 -2
- udata/frontend/__init__.py +3 -32
- udata/harvest/actions.py +4 -9
- udata/harvest/api.py +5 -14
- udata/harvest/backends/__init__.py +20 -11
- udata/harvest/backends/base.py +2 -2
- udata/harvest/backends/ckan/harvesters.py +2 -1
- udata/harvest/backends/dcat.py +3 -0
- udata/harvest/backends/maaf.py +1 -0
- udata/harvest/commands.py +6 -4
- udata/harvest/forms.py +9 -6
- udata/harvest/tasks.py +3 -5
- udata/harvest/tests/ckan/test_ckan_backend.py +300 -337
- udata/harvest/tests/ckan/test_ckan_backend_errors.py +94 -99
- udata/harvest/tests/ckan/test_ckan_backend_filters.py +128 -122
- udata/harvest/tests/ckan/test_dkan_backend.py +39 -51
- udata/harvest/tests/dcat/datara--5a26b0f6-0ccf-46ad-ac58-734054b91977.rdf.xml +255 -0
- udata/harvest/tests/dcat/datara--f40c3860-7236-4b30-a141-23b8ae33f7b2.rdf.xml +289 -0
- udata/harvest/tests/factories.py +1 -1
- udata/harvest/tests/test_actions.py +11 -9
- udata/harvest/tests/test_api.py +4 -5
- udata/harvest/tests/test_base_backend.py +5 -4
- udata/harvest/tests/test_dcat_backend.py +50 -19
- udata/harvest/tests/test_models.py +2 -4
- udata/harvest/tests/test_notifications.py +2 -4
- udata/harvest/tests/test_tasks.py +2 -3
- udata/mail.py +90 -53
- udata/migrations/2025-01-05-dataservices-fields-changes.py +8 -14
- udata/migrations/2025-10-21-remove-ckan-harvest-modified-at.py +28 -0
- udata/migrations/2025-10-29-harvesters-sources-integrity.py +27 -0
- udata/mongo/taglist_field.py +3 -3
- udata/rdf.py +32 -15
- udata/sentry.py +3 -4
- udata/settings.py +7 -2
- udata/tags.py +5 -5
- udata/tasks.py +3 -3
- udata/templates/mail/message.html +65 -0
- udata/templates/mail/message.txt +16 -0
- udata/tests/__init__.py +40 -58
- udata/tests/api/__init__.py +87 -2
- udata/tests/api/test_activities_api.py +17 -23
- udata/tests/api/test_auth_api.py +2 -4
- udata/tests/api/test_contact_points.py +48 -54
- udata/tests/api/test_dataservices_api.py +57 -37
- udata/tests/api/test_datasets_api.py +146 -49
- udata/tests/api/test_me_api.py +4 -6
- udata/tests/api/test_organizations_api.py +19 -38
- udata/tests/api/test_reports_api.py +0 -4
- udata/tests/api/test_reuses_api.py +92 -19
- udata/tests/api/test_security_api.py +124 -0
- udata/tests/api/test_swagger.py +2 -3
- udata/tests/api/test_tags_api.py +6 -7
- udata/tests/api/test_transfer_api.py +0 -2
- udata/tests/api/test_user_api.py +8 -10
- udata/tests/apiv2/test_datasets.py +0 -4
- udata/tests/apiv2/test_me_api.py +0 -2
- udata/tests/apiv2/test_organizations.py +0 -2
- udata/tests/apiv2/test_swagger.py +2 -3
- udata/tests/apiv2/test_topics.py +0 -2
- udata/tests/cli/test_cli_base.py +14 -12
- udata/tests/cli/test_db_cli.py +51 -54
- udata/tests/contact_point/test_contact_point_models.py +2 -2
- udata/tests/dataservice/test_csv_adapter.py +2 -5
- udata/tests/dataservice/test_dataservice_rdf.py +8 -6
- udata/tests/dataservice/test_dataservice_tasks.py +36 -38
- udata/tests/dataset/test_csv_adapter.py +2 -5
- udata/tests/dataset/test_dataset_actions.py +2 -4
- udata/tests/dataset/test_dataset_commands.py +2 -4
- udata/tests/dataset/test_dataset_events.py +3 -3
- udata/tests/dataset/test_dataset_model.py +6 -7
- udata/tests/dataset/test_dataset_rdf.py +201 -12
- udata/tests/dataset/test_dataset_recommendations.py +2 -2
- udata/tests/dataset/test_dataset_tasks.py +66 -68
- udata/tests/dataset/test_resource_preview.py +39 -48
- udata/tests/dataset/test_transport_tasks.py +2 -2
- udata/tests/features/territories/__init__.py +0 -6
- udata/tests/features/territories/test_territories_api.py +25 -24
- udata/tests/forms/test_current_user_field.py +2 -2
- udata/tests/forms/test_dict_field.py +2 -4
- udata/tests/forms/test_extras_fields.py +2 -3
- udata/tests/forms/test_image_field.py +2 -2
- udata/tests/forms/test_model_field.py +2 -4
- udata/tests/forms/test_publish_as_field.py +2 -4
- udata/tests/forms/test_user_forms.py +26 -29
- udata/tests/frontend/test_auth.py +2 -3
- udata/tests/frontend/test_csv.py +5 -6
- udata/tests/frontend/test_error_handlers.py +2 -3
- udata/tests/frontend/test_hooks.py +5 -7
- udata/tests/frontend/test_markdown.py +3 -4
- udata/tests/helpers.py +2 -7
- udata/tests/metrics/test_metrics.py +52 -48
- udata/tests/metrics/test_tasks.py +154 -150
- udata/tests/organization/test_csv_adapter.py +2 -5
- udata/tests/organization/test_notifications.py +2 -4
- udata/tests/organization/test_organization_model.py +3 -4
- udata/tests/organization/test_organization_rdf.py +2 -8
- udata/tests/plugin.py +6 -110
- udata/tests/reuse/test_reuse_model.py +3 -4
- udata/tests/site/test_site_api.py +0 -2
- udata/tests/site/test_site_csv_exports.py +0 -2
- udata/tests/site/test_site_metrics.py +2 -4
- udata/tests/site/test_site_model.py +2 -2
- udata/tests/site/test_site_rdf.py +4 -7
- udata/tests/test_activity.py +3 -3
- udata/tests/test_api_fields.py +6 -9
- udata/tests/test_cors.py +0 -2
- udata/tests/test_dcat_commands.py +2 -3
- udata/tests/test_discussions.py +2 -7
- udata/tests/test_mail.py +150 -114
- udata/tests/test_migrations.py +413 -419
- udata/tests/test_model.py +10 -11
- udata/tests/test_notifications.py +2 -3
- udata/tests/test_owned.py +3 -3
- udata/tests/test_rdf.py +19 -15
- udata/tests/test_routing.py +5 -5
- udata/tests/test_storages.py +6 -5
- udata/tests/test_tags.py +2 -4
- udata/tests/test_topics.py +2 -4
- udata/tests/test_transfer.py +4 -5
- udata/tests/topic/test_topic_tasks.py +25 -27
- udata/tests/user/test_user_rdf.py +2 -8
- udata/tests/user/test_user_tasks.py +3 -5
- udata/tests/workers/test_jobs_commands.py +2 -2
- udata/tests/workers/test_tasks_routing.py +27 -27
- udata/translations/ar/LC_MESSAGES/udata.mo +0 -0
- udata/translations/ar/LC_MESSAGES/udata.po +369 -435
- udata/translations/de/LC_MESSAGES/udata.mo +0 -0
- udata/translations/de/LC_MESSAGES/udata.po +371 -437
- udata/translations/es/LC_MESSAGES/udata.mo +0 -0
- udata/translations/es/LC_MESSAGES/udata.po +369 -435
- udata/translations/fr/LC_MESSAGES/udata.mo +0 -0
- udata/translations/fr/LC_MESSAGES/udata.po +381 -447
- udata/translations/it/LC_MESSAGES/udata.mo +0 -0
- udata/translations/it/LC_MESSAGES/udata.po +371 -437
- udata/translations/pt/LC_MESSAGES/udata.mo +0 -0
- udata/translations/pt/LC_MESSAGES/udata.po +371 -437
- udata/translations/sr/LC_MESSAGES/udata.mo +0 -0
- udata/translations/sr/LC_MESSAGES/udata.po +372 -438
- udata/translations/udata.pot +379 -440
- udata/utils.py +14 -2
- {udata-12.0.2.dev15.dist-info → udata-13.0.1.dev21.dist-info}/METADATA +1 -2
- {udata-12.0.2.dev15.dist-info → udata-13.0.1.dev21.dist-info}/RECORD +205 -242
- udata/templates/mail/account_deleted.html +0 -5
- udata/templates/mail/account_deleted.txt +0 -6
- udata/templates/mail/account_inactivity.html +0 -40
- udata/templates/mail/account_inactivity.txt +0 -31
- udata/templates/mail/badge_added_association.html +0 -33
- udata/templates/mail/badge_added_association.txt +0 -11
- udata/templates/mail/badge_added_certified.html +0 -33
- udata/templates/mail/badge_added_certified.txt +0 -11
- udata/templates/mail/badge_added_company.html +0 -33
- udata/templates/mail/badge_added_company.txt +0 -11
- udata/templates/mail/badge_added_local_authority.html +0 -33
- udata/templates/mail/badge_added_local_authority.txt +0 -11
- udata/templates/mail/badge_added_public_service.html +0 -33
- udata/templates/mail/badge_added_public_service.txt +0 -11
- udata/templates/mail/discussion_closed.html +0 -47
- udata/templates/mail/discussion_closed.txt +0 -16
- udata/templates/mail/inactive_account_deleted.html +0 -5
- udata/templates/mail/inactive_account_deleted.txt +0 -6
- udata/templates/mail/membership_refused.html +0 -20
- udata/templates/mail/membership_refused.txt +0 -11
- udata/templates/mail/membership_request.html +0 -46
- udata/templates/mail/membership_request.txt +0 -12
- udata/templates/mail/new_discussion.html +0 -44
- udata/templates/mail/new_discussion.txt +0 -15
- udata/templates/mail/new_discussion_comment.html +0 -45
- udata/templates/mail/new_discussion_comment.txt +0 -16
- udata/templates/mail/new_member.html +0 -27
- udata/templates/mail/new_member.txt +0 -11
- udata/templates/mail/new_reuse.html +0 -37
- udata/templates/mail/new_reuse.txt +0 -9
- udata/templates/mail/test.html +0 -6
- udata/templates/mail/test.txt +0 -6
- udata/templates/mail/user_mail_card.html +0 -26
- udata/templates/security/email/base.html +0 -105
- udata/templates/security/email/base.txt +0 -6
- udata/templates/security/email/button.html +0 -3
- udata/templates/security/email/change_notice.html +0 -22
- udata/templates/security/email/change_notice.txt +0 -8
- udata/templates/security/email/confirmation_instructions.html +0 -20
- udata/templates/security/email/confirmation_instructions.txt +0 -7
- udata/templates/security/email/login_instructions.html +0 -19
- udata/templates/security/email/login_instructions.txt +0 -7
- udata/templates/security/email/reset_instructions.html +0 -24
- udata/templates/security/email/reset_instructions.txt +0 -9
- udata/templates/security/email/reset_notice.html +0 -11
- udata/templates/security/email/reset_notice.txt +0 -4
- udata/templates/security/email/welcome.html +0 -24
- udata/templates/security/email/welcome.txt +0 -9
- udata/templates/security/email/welcome_existing.html +0 -32
- udata/templates/security/email/welcome_existing.txt +0 -14
- udata/terms.md +0 -6
- udata/tests/frontend/__init__.py +0 -23
- udata/tests/metrics/conftest.py +0 -15
- {udata-12.0.2.dev15.dist-info → udata-13.0.1.dev21.dist-info}/WHEEL +0 -0
- {udata-12.0.2.dev15.dist-info → udata-13.0.1.dev21.dist-info}/entry_points.txt +0 -0
- {udata-12.0.2.dev15.dist-info → udata-13.0.1.dev21.dist-info}/licenses/LICENSE +0 -0
- {udata-12.0.2.dev15.dist-info → udata-13.0.1.dev21.dist-info}/top_level.txt +0 -0
|
@@ -4,7 +4,6 @@ from datetime import date
|
|
|
4
4
|
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
7
|
-
from udata.app import create_app
|
|
8
7
|
from udata.core.dataset.constants import UpdateFrequency
|
|
9
8
|
from udata.core.organization.factories import OrganizationFactory
|
|
10
9
|
from udata.core.spatial.factories import GeoZoneFactory
|
|
@@ -13,34 +12,14 @@ from udata.harvest.backends.ckan.harvesters import ALLOWED_RESOURCE_TYPES
|
|
|
13
12
|
from udata.harvest.backends.ckan.schemas.ckan import RESOURCE_TYPES
|
|
14
13
|
from udata.harvest.tests.factories import HarvestSourceFactory
|
|
15
14
|
from udata.models import Dataset
|
|
16
|
-
from udata.
|
|
17
|
-
from udata.tests.plugin import drop_db
|
|
15
|
+
from udata.tests.api import PytestOnlyDBTestCase
|
|
18
16
|
from udata.utils import faker
|
|
19
17
|
|
|
20
18
|
|
|
21
|
-
class CkanSettings(Testing):
|
|
22
|
-
PLUGINS = ["ckan"]
|
|
23
|
-
|
|
24
|
-
|
|
25
19
|
@pytest.fixture
|
|
26
|
-
def
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
with app.app_context():
|
|
30
|
-
drop_db(app)
|
|
31
|
-
yield app
|
|
32
|
-
with app.app_context():
|
|
33
|
-
drop_db(app)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
@pytest.fixture
|
|
37
|
-
def source(app, ckan):
|
|
38
|
-
"""
|
|
39
|
-
Create an harvest source for an organization.
|
|
40
|
-
"""
|
|
41
|
-
with app.app_context():
|
|
42
|
-
org = OrganizationFactory()
|
|
43
|
-
return HarvestSourceFactory(backend="ckan", url=ckan.BASE_URL, organization=org)
|
|
20
|
+
def source(ckan):
|
|
21
|
+
org = OrganizationFactory()
|
|
22
|
+
return HarvestSourceFactory(backend="ckan", url=ckan.BASE_URL, organization=org)
|
|
44
23
|
|
|
45
24
|
|
|
46
25
|
def ckan_package(data):
|
|
@@ -72,7 +51,7 @@ def ckan_package(data):
|
|
|
72
51
|
|
|
73
52
|
|
|
74
53
|
@pytest.fixture
|
|
75
|
-
def harvest_ckan(request, source, ckan,
|
|
54
|
+
def harvest_ckan(request, source, ckan, rmock):
|
|
76
55
|
"""
|
|
77
56
|
This fixture performs the harvesting and return the data, result
|
|
78
57
|
and kwargs for this test case
|
|
@@ -96,11 +75,10 @@ def harvest_ckan(request, source, ckan, app, rmock):
|
|
|
96
75
|
headers={"Content-Type": "application/json"},
|
|
97
76
|
)
|
|
98
77
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
assert len(job.items) == 1
|
|
78
|
+
actions.run(source)
|
|
79
|
+
source.reload()
|
|
80
|
+
job = source.get_last_job()
|
|
81
|
+
assert len(job.items) == 1
|
|
104
82
|
|
|
105
83
|
return data, result, kwargs
|
|
106
84
|
|
|
@@ -223,9 +201,8 @@ def spatial_geom_multipolygon(resource_data):
|
|
|
223
201
|
|
|
224
202
|
|
|
225
203
|
@pytest.fixture
|
|
226
|
-
def known_spatial_text_name(
|
|
227
|
-
|
|
228
|
-
zone = GeoZoneFactory()
|
|
204
|
+
def known_spatial_text_name(resource_data):
|
|
205
|
+
zone = GeoZoneFactory()
|
|
229
206
|
data = {
|
|
230
207
|
"name": faker.unique_string(),
|
|
231
208
|
"title": faker.sentence(),
|
|
@@ -237,9 +214,8 @@ def known_spatial_text_name(app, resource_data):
|
|
|
237
214
|
|
|
238
215
|
|
|
239
216
|
@pytest.fixture
|
|
240
|
-
def known_spatial_text_slug(
|
|
241
|
-
|
|
242
|
-
zone = GeoZoneFactory()
|
|
217
|
+
def known_spatial_text_slug(resource_data):
|
|
218
|
+
zone = GeoZoneFactory()
|
|
243
219
|
data = {
|
|
244
220
|
"name": faker.unique_string(),
|
|
245
221
|
"title": faker.sentence(),
|
|
@@ -251,10 +227,9 @@ def known_spatial_text_slug(app, resource_data):
|
|
|
251
227
|
|
|
252
228
|
|
|
253
229
|
@pytest.fixture
|
|
254
|
-
def multiple_known_spatial_text(
|
|
230
|
+
def multiple_known_spatial_text(resource_data):
|
|
255
231
|
name = faker.word()
|
|
256
|
-
|
|
257
|
-
GeoZoneFactory.create_batch(2, name=name)
|
|
232
|
+
GeoZoneFactory.create_batch(2, name=name)
|
|
258
233
|
data = {
|
|
259
234
|
"name": faker.unique_string(),
|
|
260
235
|
"title": faker.sentence(),
|
|
@@ -389,310 +364,298 @@ def empty_extras(resource_data):
|
|
|
389
364
|
##############################################################################
|
|
390
365
|
|
|
391
366
|
|
|
392
|
-
@pytest.mark.
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
@pytest.mark.ckan_data("spatial_geom_polygon")
|
|
434
|
-
def test_geospatial_geom_polygon(result, kwargs):
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
@pytest.mark.ckan_data("spatial_geom_multipolygon")
|
|
445
|
-
def test_geospatial_geom_multipolygon(result, kwargs):
|
|
446
|
-
multipolygon = kwargs["multipolygon"]
|
|
447
|
-
|
|
448
|
-
dataset = dataset_for(result)
|
|
449
|
-
assert dataset.spatial.geom == multipolygon
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
@pytest.mark.ckan_data("skipped_no_resources")
|
|
453
|
-
def test_skip_no_resources(source, result):
|
|
454
|
-
job = source.get_last_job()
|
|
455
|
-
item = job_item_for(job, result)
|
|
456
|
-
assert item.status == "skipped"
|
|
457
|
-
assert dataset_for(result) is None
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
@pytest.mark.ckan_data("ckan_url_is_url")
|
|
461
|
-
def test_ckan_url_is_url(data, result):
|
|
462
|
-
dataset = dataset_for(result)
|
|
463
|
-
assert dataset.harvest.remote_url == data["url"]
|
|
464
|
-
assert dataset.harvest.ckan_source is None
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
@pytest.mark.ckan_data("ckan_url_is_a_string")
|
|
468
|
-
def test_ckan_url_is_string(ckan, data, result):
|
|
469
|
-
dataset = dataset_for(result)
|
|
470
|
-
expected_url = "{0}/dataset/{1}".format(ckan.BASE_URL, data["name"])
|
|
471
|
-
assert dataset.harvest.remote_url == expected_url
|
|
472
|
-
assert dataset.harvest.ckan_source == data["url"]
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
@pytest.mark.ckan_data("frequency_as_rdf_uri")
|
|
476
|
-
def test_can_parse_frequency_as_uri(result, kwargs):
|
|
477
|
-
dataset = dataset_for(result)
|
|
478
|
-
assert dataset.frequency == kwargs["expected"]
|
|
479
|
-
assert "ckan:frequency" not in dataset.extras
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
@pytest.mark.ckan_data("frequency_as_exact_match")
|
|
483
|
-
def test_can_parse_frequency_as_exact_match(result, kwargs):
|
|
484
|
-
dataset = dataset_for(result)
|
|
485
|
-
assert dataset.frequency == kwargs["expected"]
|
|
486
|
-
assert "ckan:frequency" not in dataset.extras
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
@pytest.mark.ckan_data("frequency_as_unknown_value")
|
|
490
|
-
def test_can_parse_frequency_as_unknown_value(result, kwargs):
|
|
491
|
-
dataset = dataset_for(result)
|
|
492
|
-
assert dataset.extras["ckan:frequency"] == kwargs["expected"]
|
|
493
|
-
assert dataset.frequency is None
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
@pytest.mark.ckan_data("empty_extras")
|
|
497
|
-
def test_skip_empty_extras(result):
|
|
498
|
-
dataset = dataset_for(result)
|
|
499
|
-
assert "none" not in dataset.extras
|
|
500
|
-
assert "blank" not in dataset.extras
|
|
501
|
-
assert "spaces" not in dataset.extras
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
@pytest.mark.ckan_data("known_spatial_text_name")
|
|
505
|
-
def test_known_spatial_text_name(result, kwargs):
|
|
506
|
-
zone = kwargs["zone"]
|
|
507
|
-
dataset = dataset_for(result)
|
|
508
|
-
assert zone in dataset.spatial.zones
|
|
509
|
-
assert "ckan:spatial-text" not in dataset.extras
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
@pytest.mark.ckan_data("known_spatial_text_slug")
|
|
513
|
-
def test_known_spatial_text_slug(result, kwargs):
|
|
514
|
-
zone = kwargs["zone"]
|
|
515
|
-
dataset = dataset_for(result)
|
|
516
|
-
assert zone in dataset.spatial.zones
|
|
517
|
-
assert "ckan:spatial-text" not in dataset.extras
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
@pytest.mark.ckan_data("multiple_known_spatial_text")
|
|
521
|
-
def test_store_unsure_spatial_text_as_extra(result, kwargs):
|
|
522
|
-
dataset = dataset_for(result)
|
|
523
|
-
assert dataset.extras["ckan:spatial-text"] == kwargs["name"]
|
|
524
|
-
assert dataset.spatial is None
|
|
525
|
-
|
|
367
|
+
@pytest.mark.options(HARVESTER_BACKENDS=["ckan"])
|
|
368
|
+
class CkanBackendTest(PytestOnlyDBTestCase):
|
|
369
|
+
@pytest.mark.ckan_data("minimal")
|
|
370
|
+
def test_minimal_metadata(self, data, result, kwargs):
|
|
371
|
+
resource_url = kwargs["resource_url"]
|
|
372
|
+
|
|
373
|
+
dataset = dataset_for(result)
|
|
374
|
+
assert dataset.title == data["title"]
|
|
375
|
+
assert dataset.description == data["notes"]
|
|
376
|
+
assert dataset.harvest.remote_id == result["result"]["id"]
|
|
377
|
+
assert dataset.harvest.domain == "localhost"
|
|
378
|
+
assert dataset.harvest.ckan_name == data["name"]
|
|
379
|
+
assert len(dataset.resources) == 1
|
|
380
|
+
|
|
381
|
+
resource = dataset.resources[0]
|
|
382
|
+
assert resource.url == resource_url
|
|
383
|
+
|
|
384
|
+
@pytest.mark.ckan_data("all_metadata")
|
|
385
|
+
def test_all_metadata(self, data, result):
|
|
386
|
+
resource_data = data["resources"][0]
|
|
387
|
+
resource_result = result["result"]["resources"][0]
|
|
388
|
+
|
|
389
|
+
dataset = dataset_for(result)
|
|
390
|
+
assert dataset.title == data["title"]
|
|
391
|
+
assert dataset.description == data["notes"]
|
|
392
|
+
assert set(dataset.tags) == set([t["name"] for t in data["tags"]])
|
|
393
|
+
assert dataset.harvest.remote_id == result["result"]["id"]
|
|
394
|
+
assert dataset.harvest.domain == "localhost"
|
|
395
|
+
assert dataset.harvest.ckan_name == data["name"]
|
|
396
|
+
assert len(dataset.resources) == 1
|
|
397
|
+
|
|
398
|
+
resource = dataset.resources[0]
|
|
399
|
+
assert resource.title == resource_data["name"]
|
|
400
|
+
assert resource.description == resource_data["description"]
|
|
401
|
+
assert resource.url == resource_data["url"]
|
|
402
|
+
# Use result because format is normalized by CKAN
|
|
403
|
+
assert resource.format == resource_result["format"].lower()
|
|
404
|
+
assert resource.mime == resource_data["mimetype"].lower()
|
|
405
|
+
assert resource.harvest.issued_at.date() == date(2022, 9, 29)
|
|
406
|
+
assert resource.harvest.modified_at.date() == date(2022, 9, 30)
|
|
407
|
+
|
|
408
|
+
@pytest.mark.ckan_data("spatial_geom_polygon")
|
|
409
|
+
def test_geospatial_geom_polygon(self, result, kwargs):
|
|
410
|
+
polygon = kwargs["polygon"]
|
|
411
|
+
dataset = dataset_for(result)
|
|
412
|
+
|
|
413
|
+
assert dataset.spatial.geom == {
|
|
414
|
+
"type": "MultiPolygon",
|
|
415
|
+
"coordinates": [polygon["coordinates"]],
|
|
416
|
+
}
|
|
526
417
|
|
|
527
|
-
@pytest.mark.ckan_data("
|
|
528
|
-
def
|
|
529
|
-
|
|
530
|
-
assert dataset.extras["ckan:spatial-text"] == kwargs["spatial"]
|
|
531
|
-
assert dataset.spatial is None
|
|
418
|
+
@pytest.mark.ckan_data("spatial_geom_multipolygon")
|
|
419
|
+
def test_geospatial_geom_multipolygon(self, result, kwargs):
|
|
420
|
+
multipolygon = kwargs["multipolygon"]
|
|
532
421
|
|
|
422
|
+
dataset = dataset_for(result)
|
|
423
|
+
assert dataset.spatial.geom == multipolygon
|
|
533
424
|
|
|
534
|
-
@pytest.mark.ckan_data("
|
|
535
|
-
def
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
425
|
+
@pytest.mark.ckan_data("skipped_no_resources")
|
|
426
|
+
def test_skip_no_resources(self, source, result):
|
|
427
|
+
job = source.get_last_job()
|
|
428
|
+
item = job_item_for(job, result)
|
|
429
|
+
assert item.status == "skipped"
|
|
430
|
+
assert dataset_for(result) is None
|
|
431
|
+
|
|
432
|
+
@pytest.mark.ckan_data("ckan_url_is_url")
|
|
433
|
+
def test_ckan_url_is_url(self, data, result):
|
|
434
|
+
dataset = dataset_for(result)
|
|
435
|
+
assert dataset.harvest.remote_url == data["url"]
|
|
436
|
+
assert dataset.harvest.ckan_source is None
|
|
437
|
+
|
|
438
|
+
@pytest.mark.ckan_data("ckan_url_is_a_string")
|
|
439
|
+
def test_ckan_url_is_string(self, ckan, data, result):
|
|
440
|
+
dataset = dataset_for(result)
|
|
441
|
+
expected_url = "{0}/dataset/{1}".format(ckan.BASE_URL, data["name"])
|
|
442
|
+
assert dataset.harvest.remote_url == expected_url
|
|
443
|
+
assert dataset.harvest.ckan_source == data["url"]
|
|
444
|
+
|
|
445
|
+
@pytest.mark.ckan_data("frequency_as_rdf_uri")
|
|
446
|
+
def test_can_parse_frequency_as_uri(self, result, kwargs):
|
|
447
|
+
dataset = dataset_for(result)
|
|
448
|
+
assert dataset.frequency == kwargs["expected"]
|
|
449
|
+
assert "ckan:frequency" not in dataset.extras
|
|
450
|
+
|
|
451
|
+
@pytest.mark.ckan_data("frequency_as_exact_match")
|
|
452
|
+
def test_can_parse_frequency_as_exact_match(self, result, kwargs):
|
|
453
|
+
dataset = dataset_for(result)
|
|
454
|
+
assert dataset.frequency == kwargs["expected"]
|
|
455
|
+
assert "ckan:frequency" not in dataset.extras
|
|
456
|
+
|
|
457
|
+
@pytest.mark.ckan_data("frequency_as_unknown_value")
|
|
458
|
+
def test_can_parse_frequency_as_unknown_value(self, result, kwargs):
|
|
459
|
+
dataset = dataset_for(result)
|
|
460
|
+
assert dataset.extras["ckan:frequency"] == kwargs["expected"]
|
|
461
|
+
assert dataset.frequency is None
|
|
462
|
+
|
|
463
|
+
@pytest.mark.ckan_data("empty_extras")
|
|
464
|
+
def test_skip_empty_extras(self, result):
|
|
465
|
+
dataset = dataset_for(result)
|
|
466
|
+
assert "none" not in dataset.extras
|
|
467
|
+
assert "blank" not in dataset.extras
|
|
468
|
+
assert "spaces" not in dataset.extras
|
|
469
|
+
|
|
470
|
+
@pytest.mark.ckan_data("known_spatial_text_name")
|
|
471
|
+
def test_known_spatial_text_name(self, result, kwargs):
|
|
472
|
+
zone = kwargs["zone"]
|
|
473
|
+
dataset = dataset_for(result)
|
|
474
|
+
assert zone in dataset.spatial.zones
|
|
475
|
+
assert "ckan:spatial-text" not in dataset.extras
|
|
476
|
+
|
|
477
|
+
@pytest.mark.ckan_data("known_spatial_text_slug")
|
|
478
|
+
def test_known_spatial_text_slug(self, result, kwargs):
|
|
479
|
+
zone = kwargs["zone"]
|
|
480
|
+
dataset = dataset_for(result)
|
|
481
|
+
assert zone in dataset.spatial.zones
|
|
482
|
+
assert "ckan:spatial-text" not in dataset.extras
|
|
483
|
+
|
|
484
|
+
@pytest.mark.ckan_data("multiple_known_spatial_text")
|
|
485
|
+
def test_store_unsure_spatial_text_as_extra(self, result, kwargs):
|
|
486
|
+
dataset = dataset_for(result)
|
|
487
|
+
assert dataset.extras["ckan:spatial-text"] == kwargs["name"]
|
|
488
|
+
assert dataset.spatial is None
|
|
489
|
+
|
|
490
|
+
@pytest.mark.ckan_data("unknown_spatial_text")
|
|
491
|
+
def test_keep_unknown_spatial_text_as_extra(self, result, kwargs):
|
|
492
|
+
dataset = dataset_for(result)
|
|
493
|
+
assert dataset.extras["ckan:spatial-text"] == kwargs["spatial"]
|
|
494
|
+
assert dataset.spatial is None
|
|
495
|
+
|
|
496
|
+
@pytest.mark.ckan_data("spatial_uri")
|
|
497
|
+
def test_keep_unknown_spatial_uri_as_extra(self, result, kwargs):
|
|
498
|
+
dataset = dataset_for(result)
|
|
499
|
+
assert dataset.extras["ckan:spatial-uri"] == kwargs["spatial"]
|
|
500
|
+
assert dataset.spatial is None
|
|
539
501
|
|
|
540
502
|
|
|
541
503
|
##############################################################################
|
|
542
504
|
# Edge cases manually written #
|
|
543
505
|
##############################################################################
|
|
544
|
-
def test_minimal_ckan_response(app, rmock):
|
|
545
|
-
"""CKAN Harvester should accept the minimum dataset payload"""
|
|
546
|
-
CKAN_URL = "https://harvest.me/"
|
|
547
|
-
API_URL = "{}api/3/action/".format(CKAN_URL)
|
|
548
|
-
PACKAGE_LIST_URL = "{}package_list".format(API_URL)
|
|
549
|
-
PACKAGE_SHOW_URL = "{}package_show".format(API_URL)
|
|
550
|
-
|
|
551
|
-
name = faker.unique_string()
|
|
552
|
-
json = {
|
|
553
|
-
"success": True,
|
|
554
|
-
"result": minimal_data(name=name),
|
|
555
|
-
}
|
|
556
|
-
source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
|
|
557
|
-
rmock.get(
|
|
558
|
-
PACKAGE_LIST_URL,
|
|
559
|
-
json={"success": True, "result": [name]},
|
|
560
|
-
status_code=200,
|
|
561
|
-
headers={"Content-Type": "application/json"},
|
|
562
|
-
)
|
|
563
|
-
rmock.get(
|
|
564
|
-
PACKAGE_SHOW_URL,
|
|
565
|
-
json=json,
|
|
566
|
-
status_code=200,
|
|
567
|
-
headers={"Content-Type": "application/json"},
|
|
568
|
-
)
|
|
569
|
-
actions.run(source)
|
|
570
|
-
source.reload()
|
|
571
|
-
assert source.get_last_job().status == "done"
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
def test_flawed_ckan_response(app, rmock):
|
|
575
|
-
"""CKAN Harvester should report item error with id == remote_id in item"""
|
|
576
|
-
CKAN_URL = "https://harvest.me/"
|
|
577
|
-
API_URL = "{}api/3/action/".format(CKAN_URL)
|
|
578
|
-
PACKAGE_LIST_URL = "{}package_list".format(API_URL)
|
|
579
|
-
PACKAGE_SHOW_URL = "{}package_show".format(API_URL)
|
|
580
|
-
|
|
581
|
-
name = faker.unique_string()
|
|
582
|
-
_id = faker.uuid4()
|
|
583
|
-
# flawed response, missing way too much required attrs
|
|
584
|
-
json = {
|
|
585
|
-
"success": True,
|
|
586
|
-
"result": {
|
|
587
|
-
"id": _id,
|
|
588
|
-
"name": name,
|
|
589
|
-
},
|
|
590
|
-
}
|
|
591
|
-
source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
|
|
592
|
-
rmock.get(
|
|
593
|
-
PACKAGE_LIST_URL,
|
|
594
|
-
json={"success": True, "result": [name]},
|
|
595
|
-
status_code=200,
|
|
596
|
-
headers={"Content-Type": "application/json"},
|
|
597
|
-
)
|
|
598
|
-
rmock.get(
|
|
599
|
-
PACKAGE_SHOW_URL,
|
|
600
|
-
json=json,
|
|
601
|
-
status_code=200,
|
|
602
|
-
headers={"Content-Type": "application/json"},
|
|
603
|
-
)
|
|
604
|
-
actions.run(source)
|
|
605
|
-
source.reload()
|
|
606
|
-
assert source.get_last_job().status == "done-errors"
|
|
607
|
-
assert source.get_last_job().items[0].remote_id == _id
|
|
608
|
-
# flawed response, without an id, we should fallback on the name
|
|
609
|
-
json = {
|
|
610
|
-
"success": True,
|
|
611
|
-
"result": {
|
|
612
|
-
"name": name,
|
|
613
|
-
},
|
|
614
|
-
}
|
|
615
|
-
rmock.get(
|
|
616
|
-
PACKAGE_SHOW_URL,
|
|
617
|
-
json=json,
|
|
618
|
-
status_code=200,
|
|
619
|
-
headers={"Content-Type": "application/json"},
|
|
620
|
-
)
|
|
621
|
-
actions.run(source)
|
|
622
|
-
source.reload()
|
|
623
|
-
assert source.get_last_job().status == "done-errors"
|
|
624
|
-
assert source.get_last_job().items[0].remote_id == name
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
@pytest.mark.options(HARVEST_MAX_ITEMS=1)
|
|
628
|
-
def test_max_items(app, rmock):
|
|
629
|
-
"""CKAN Harvester should report item error with id == remote_id in item"""
|
|
630
|
-
CKAN_URL = "https://harvest.me/"
|
|
631
|
-
API_URL = "{}api/3/action/".format(CKAN_URL)
|
|
632
|
-
PACKAGE_LIST_URL = "{}package_list".format(API_URL)
|
|
633
|
-
PACKAGE_SHOW_URL = "{}package_show".format(API_URL)
|
|
634
|
-
|
|
635
|
-
name_a = faker.unique_string()
|
|
636
|
-
name_b = faker.unique_string()
|
|
637
|
-
id_a = faker.uuid4()
|
|
638
|
-
json_a = {
|
|
639
|
-
"success": True,
|
|
640
|
-
"result": minimal_data(id=id_a, name=name_a),
|
|
641
|
-
}
|
|
642
|
-
id_b = faker.uuid4()
|
|
643
|
-
json_b = {
|
|
644
|
-
"success": True,
|
|
645
|
-
"result": minimal_data(id=id_b, name=name_b),
|
|
646
|
-
}
|
|
647
|
-
source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
|
|
648
|
-
rmock.get(
|
|
649
|
-
PACKAGE_LIST_URL,
|
|
650
|
-
json={"success": True, "result": [name_a, name_b]},
|
|
651
|
-
status_code=200,
|
|
652
|
-
headers={"Content-Type": "application/json"},
|
|
653
|
-
)
|
|
654
|
-
rmock.get(
|
|
655
|
-
f"{PACKAGE_SHOW_URL}?id={name_a}",
|
|
656
|
-
json=json_a,
|
|
657
|
-
status_code=200,
|
|
658
|
-
headers={"Content-Type": "application/json"},
|
|
659
|
-
)
|
|
660
|
-
rmock.get(
|
|
661
|
-
f"{PACKAGE_SHOW_URL}?id={name_b}",
|
|
662
|
-
json=json_b,
|
|
663
|
-
status_code=200,
|
|
664
|
-
headers={"Content-Type": "application/json"},
|
|
665
|
-
)
|
|
666
|
-
actions.run(source)
|
|
667
|
-
source.reload()
|
|
668
|
-
assert source.get_last_job().status == "done"
|
|
669
|
-
assert len(source.get_last_job().items) == 1
|
|
670
|
-
assert source.get_last_job().items[0].remote_id == id_a
|
|
671
506
|
|
|
672
507
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
"
|
|
685
|
-
"
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
"
|
|
691
|
-
|
|
692
|
-
"
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
508
|
+
@pytest.mark.options(HARVESTER_BACKENDS=["ckan"])
|
|
509
|
+
class CkanBackendEdgeCasesTest(PytestOnlyDBTestCase):
|
|
510
|
+
def test_minimal_ckan_response(self, rmock):
|
|
511
|
+
"""CKAN Harvester should accept the minimum dataset payload"""
|
|
512
|
+
CKAN_URL = "https://harvest.me/"
|
|
513
|
+
API_URL = "{}api/3/action/".format(CKAN_URL)
|
|
514
|
+
PACKAGE_LIST_URL = "{}package_list".format(API_URL)
|
|
515
|
+
PACKAGE_SHOW_URL = "{}package_show".format(API_URL)
|
|
516
|
+
|
|
517
|
+
name = faker.unique_string()
|
|
518
|
+
json = {
|
|
519
|
+
"success": True,
|
|
520
|
+
"result": self.minimal_data(name=name),
|
|
521
|
+
}
|
|
522
|
+
source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
|
|
523
|
+
rmock.get(
|
|
524
|
+
PACKAGE_LIST_URL,
|
|
525
|
+
json={"success": True, "result": [name]},
|
|
526
|
+
status_code=200,
|
|
527
|
+
headers={"Content-Type": "application/json"},
|
|
528
|
+
)
|
|
529
|
+
rmock.get(
|
|
530
|
+
PACKAGE_SHOW_URL,
|
|
531
|
+
json=json,
|
|
532
|
+
status_code=200,
|
|
533
|
+
headers={"Content-Type": "application/json"},
|
|
534
|
+
)
|
|
535
|
+
actions.run(source)
|
|
536
|
+
source.reload()
|
|
537
|
+
assert source.get_last_job().status == "done"
|
|
538
|
+
|
|
539
|
+
def test_flawed_ckan_response(self, rmock):
|
|
540
|
+
"""CKAN Harvester should report item error with id == remote_id in item"""
|
|
541
|
+
CKAN_URL = "https://harvest.me/"
|
|
542
|
+
API_URL = "{}api/3/action/".format(CKAN_URL)
|
|
543
|
+
PACKAGE_LIST_URL = "{}package_list".format(API_URL)
|
|
544
|
+
PACKAGE_SHOW_URL = "{}package_show".format(API_URL)
|
|
545
|
+
|
|
546
|
+
name = faker.unique_string()
|
|
547
|
+
_id = faker.uuid4()
|
|
548
|
+
# flawed response, missing way too much required attrs
|
|
549
|
+
json = {
|
|
550
|
+
"success": True,
|
|
551
|
+
"result": {
|
|
552
|
+
"id": _id,
|
|
553
|
+
"name": name,
|
|
554
|
+
},
|
|
555
|
+
}
|
|
556
|
+
source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
|
|
557
|
+
rmock.get(
|
|
558
|
+
PACKAGE_LIST_URL,
|
|
559
|
+
json={"success": True, "result": [name]},
|
|
560
|
+
status_code=200,
|
|
561
|
+
headers={"Content-Type": "application/json"},
|
|
562
|
+
)
|
|
563
|
+
rmock.get(
|
|
564
|
+
PACKAGE_SHOW_URL,
|
|
565
|
+
json=json,
|
|
566
|
+
status_code=200,
|
|
567
|
+
headers={"Content-Type": "application/json"},
|
|
568
|
+
)
|
|
569
|
+
actions.run(source)
|
|
570
|
+
source.reload()
|
|
571
|
+
assert source.get_last_job().status == "done-errors"
|
|
572
|
+
assert source.get_last_job().items[0].remote_id == _id
|
|
573
|
+
# flawed response, without an id, we should fallback on the name
|
|
574
|
+
json = {
|
|
575
|
+
"success": True,
|
|
576
|
+
"result": {
|
|
577
|
+
"name": name,
|
|
578
|
+
},
|
|
579
|
+
}
|
|
580
|
+
rmock.get(
|
|
581
|
+
PACKAGE_SHOW_URL,
|
|
582
|
+
json=json,
|
|
583
|
+
status_code=200,
|
|
584
|
+
headers={"Content-Type": "application/json"},
|
|
585
|
+
)
|
|
586
|
+
actions.run(source)
|
|
587
|
+
source.reload()
|
|
588
|
+
assert source.get_last_job().status == "done-errors"
|
|
589
|
+
assert source.get_last_job().items[0].remote_id == name
|
|
590
|
+
|
|
591
|
+
@pytest.mark.options(HARVEST_MAX_ITEMS=1)
|
|
592
|
+
def test_max_items(self, app, rmock):
|
|
593
|
+
"""CKAN Harvester should report item error with id == remote_id in item"""
|
|
594
|
+
CKAN_URL = "https://harvest.me/"
|
|
595
|
+
API_URL = "{}api/3/action/".format(CKAN_URL)
|
|
596
|
+
PACKAGE_LIST_URL = "{}package_list".format(API_URL)
|
|
597
|
+
PACKAGE_SHOW_URL = "{}package_show".format(API_URL)
|
|
598
|
+
|
|
599
|
+
name_a = faker.unique_string()
|
|
600
|
+
name_b = faker.unique_string()
|
|
601
|
+
id_a = faker.uuid4()
|
|
602
|
+
json_a = {
|
|
603
|
+
"success": True,
|
|
604
|
+
"result": self.minimal_data(id=id_a, name=name_a),
|
|
605
|
+
}
|
|
606
|
+
id_b = faker.uuid4()
|
|
607
|
+
json_b = {
|
|
608
|
+
"success": True,
|
|
609
|
+
"result": self.minimal_data(id=id_b, name=name_b),
|
|
610
|
+
}
|
|
611
|
+
source = HarvestSourceFactory(backend="ckan", url=CKAN_URL)
|
|
612
|
+
rmock.get(
|
|
613
|
+
PACKAGE_LIST_URL,
|
|
614
|
+
json={"success": True, "result": [name_a, name_b]},
|
|
615
|
+
status_code=200,
|
|
616
|
+
headers={"Content-Type": "application/json"},
|
|
617
|
+
)
|
|
618
|
+
rmock.get(
|
|
619
|
+
f"{PACKAGE_SHOW_URL}?id={name_a}",
|
|
620
|
+
json=json_a,
|
|
621
|
+
status_code=200,
|
|
622
|
+
headers={"Content-Type": "application/json"},
|
|
623
|
+
)
|
|
624
|
+
rmock.get(
|
|
625
|
+
f"{PACKAGE_SHOW_URL}?id={name_b}",
|
|
626
|
+
json=json_b,
|
|
627
|
+
status_code=200,
|
|
628
|
+
headers={"Content-Type": "application/json"},
|
|
629
|
+
)
|
|
630
|
+
actions.run(source)
|
|
631
|
+
source.reload()
|
|
632
|
+
assert source.get_last_job().status == "done"
|
|
633
|
+
assert len(source.get_last_job().items) == 1
|
|
634
|
+
assert source.get_last_job().items[0].remote_id == id_a
|
|
635
|
+
|
|
636
|
+
def minimal_data(self, **kwargs):
|
|
637
|
+
# extras and revision_id are not always present so we exclude them
|
|
638
|
+
# from the minimal payload
|
|
639
|
+
return {
|
|
640
|
+
**{
|
|
641
|
+
"id": faker.uuid4(),
|
|
642
|
+
"name": faker.uuid4(),
|
|
643
|
+
"title": faker.sentence(),
|
|
644
|
+
"maintainer": faker.name(),
|
|
645
|
+
"tags": [],
|
|
646
|
+
"private": False,
|
|
647
|
+
"maintainer_email": faker.email(),
|
|
648
|
+
"license_id": None,
|
|
649
|
+
"metadata_created": faker.iso8601(),
|
|
650
|
+
"organization": None,
|
|
651
|
+
"metadata_modified": faker.iso8601(),
|
|
652
|
+
"author": None,
|
|
653
|
+
"author_email": None,
|
|
654
|
+
"notes": faker.paragraph(),
|
|
655
|
+
"license_title": None,
|
|
656
|
+
"state": None,
|
|
657
|
+
"type": "dataset",
|
|
658
|
+
"resources": [],
|
|
659
|
+
},
|
|
660
|
+
**kwargs,
|
|
661
|
+
}
|