udata 9.1.2.dev30355__py2.py3-none-any.whl → 9.1.2.dev30454__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.
- tasks/__init__.py +109 -107
- tasks/helpers.py +18 -18
- udata/__init__.py +4 -4
- udata/admin/views.py +5 -5
- udata/api/__init__.py +111 -134
- udata/api/commands.py +45 -37
- udata/api/errors.py +5 -4
- udata/api/fields.py +23 -21
- udata/api/oauth2.py +55 -74
- udata/api/parsers.py +15 -15
- udata/api/signals.py +1 -1
- udata/api_fields.py +137 -89
- udata/app.py +58 -55
- udata/assets.py +5 -5
- udata/auth/__init__.py +37 -26
- udata/auth/forms.py +23 -15
- udata/auth/helpers.py +1 -1
- udata/auth/mails.py +3 -3
- udata/auth/password_validation.py +19 -15
- udata/auth/views.py +94 -68
- udata/commands/__init__.py +71 -69
- udata/commands/cache.py +7 -7
- udata/commands/db.py +201 -140
- udata/commands/dcat.py +36 -30
- udata/commands/fixtures.py +100 -84
- udata/commands/images.py +21 -20
- udata/commands/info.py +17 -20
- udata/commands/init.py +10 -10
- udata/commands/purge.py +12 -13
- udata/commands/serve.py +41 -29
- udata/commands/static.py +16 -18
- udata/commands/test.py +20 -20
- udata/commands/tests/fixtures.py +26 -24
- udata/commands/worker.py +31 -33
- udata/core/__init__.py +12 -12
- udata/core/activity/__init__.py +0 -1
- udata/core/activity/api.py +59 -49
- udata/core/activity/models.py +28 -26
- udata/core/activity/signals.py +1 -1
- udata/core/activity/tasks.py +16 -10
- udata/core/badges/api.py +6 -6
- udata/core/badges/commands.py +14 -13
- udata/core/badges/fields.py +8 -5
- udata/core/badges/forms.py +7 -4
- udata/core/badges/models.py +16 -31
- udata/core/badges/permissions.py +1 -3
- udata/core/badges/signals.py +2 -2
- udata/core/badges/tasks.py +3 -2
- udata/core/badges/tests/test_commands.py +10 -10
- udata/core/badges/tests/test_model.py +24 -31
- udata/core/contact_point/api.py +19 -18
- udata/core/contact_point/api_fields.py +21 -14
- udata/core/contact_point/factories.py +2 -2
- udata/core/contact_point/forms.py +7 -6
- udata/core/contact_point/models.py +3 -5
- udata/core/dataservices/api.py +26 -21
- udata/core/dataservices/factories.py +13 -11
- udata/core/dataservices/models.py +35 -40
- udata/core/dataservices/permissions.py +4 -4
- udata/core/dataservices/rdf.py +40 -17
- udata/core/dataservices/tasks.py +4 -3
- udata/core/dataset/actions.py +10 -10
- udata/core/dataset/activities.py +21 -23
- udata/core/dataset/api.py +321 -298
- udata/core/dataset/api_fields.py +443 -271
- udata/core/dataset/apiv2.py +305 -229
- udata/core/dataset/commands.py +38 -36
- udata/core/dataset/constants.py +61 -54
- udata/core/dataset/csv.py +70 -74
- udata/core/dataset/events.py +39 -32
- udata/core/dataset/exceptions.py +8 -4
- udata/core/dataset/factories.py +57 -65
- udata/core/dataset/forms.py +87 -63
- udata/core/dataset/models.py +336 -280
- udata/core/dataset/permissions.py +9 -6
- udata/core/dataset/preview.py +15 -17
- udata/core/dataset/rdf.py +156 -122
- udata/core/dataset/search.py +92 -77
- udata/core/dataset/signals.py +1 -1
- udata/core/dataset/tasks.py +63 -54
- udata/core/discussions/actions.py +5 -5
- udata/core/discussions/api.py +124 -120
- udata/core/discussions/factories.py +2 -2
- udata/core/discussions/forms.py +9 -7
- udata/core/discussions/metrics.py +1 -3
- udata/core/discussions/models.py +25 -24
- udata/core/discussions/notifications.py +18 -14
- udata/core/discussions/permissions.py +3 -3
- udata/core/discussions/signals.py +4 -4
- udata/core/discussions/tasks.py +24 -28
- udata/core/followers/api.py +32 -33
- udata/core/followers/models.py +9 -9
- udata/core/followers/signals.py +3 -3
- udata/core/jobs/actions.py +7 -7
- udata/core/jobs/api.py +99 -92
- udata/core/jobs/commands.py +48 -49
- udata/core/jobs/forms.py +11 -11
- udata/core/jobs/models.py +6 -6
- udata/core/metrics/__init__.py +2 -2
- udata/core/metrics/commands.py +34 -30
- udata/core/metrics/models.py +2 -4
- udata/core/metrics/signals.py +1 -1
- udata/core/metrics/tasks.py +3 -3
- udata/core/organization/activities.py +12 -15
- udata/core/organization/api.py +167 -174
- udata/core/organization/api_fields.py +183 -124
- udata/core/organization/apiv2.py +32 -32
- udata/core/organization/commands.py +20 -22
- udata/core/organization/constants.py +11 -11
- udata/core/organization/csv.py +17 -15
- udata/core/organization/factories.py +8 -11
- udata/core/organization/forms.py +32 -26
- udata/core/organization/metrics.py +2 -1
- udata/core/organization/models.py +87 -67
- udata/core/organization/notifications.py +18 -14
- udata/core/organization/permissions.py +10 -11
- udata/core/organization/rdf.py +14 -14
- udata/core/organization/search.py +30 -28
- udata/core/organization/signals.py +7 -7
- udata/core/organization/tasks.py +42 -61
- udata/core/owned.py +38 -27
- udata/core/post/api.py +82 -81
- udata/core/post/constants.py +8 -5
- udata/core/post/factories.py +4 -4
- udata/core/post/forms.py +13 -14
- udata/core/post/models.py +20 -22
- udata/core/post/tests/test_api.py +30 -32
- udata/core/reports/api.py +8 -7
- udata/core/reports/constants.py +1 -3
- udata/core/reports/models.py +10 -10
- udata/core/reuse/activities.py +15 -19
- udata/core/reuse/api.py +123 -126
- udata/core/reuse/api_fields.py +120 -85
- udata/core/reuse/apiv2.py +11 -10
- udata/core/reuse/constants.py +23 -23
- udata/core/reuse/csv.py +18 -18
- udata/core/reuse/factories.py +5 -9
- udata/core/reuse/forms.py +24 -21
- udata/core/reuse/models.py +55 -51
- udata/core/reuse/permissions.py +2 -2
- udata/core/reuse/search.py +49 -46
- udata/core/reuse/signals.py +1 -1
- udata/core/reuse/tasks.py +4 -5
- udata/core/site/api.py +47 -50
- udata/core/site/factories.py +2 -2
- udata/core/site/forms.py +4 -5
- udata/core/site/models.py +94 -63
- udata/core/site/rdf.py +14 -14
- udata/core/spam/api.py +16 -9
- udata/core/spam/constants.py +4 -4
- udata/core/spam/fields.py +13 -7
- udata/core/spam/models.py +27 -20
- udata/core/spam/signals.py +1 -1
- udata/core/spam/tests/test_spam.py +6 -5
- udata/core/spatial/api.py +72 -80
- udata/core/spatial/api_fields.py +73 -58
- udata/core/spatial/commands.py +67 -64
- udata/core/spatial/constants.py +3 -3
- udata/core/spatial/factories.py +37 -54
- udata/core/spatial/forms.py +27 -26
- udata/core/spatial/geoids.py +17 -17
- udata/core/spatial/models.py +43 -47
- udata/core/spatial/tasks.py +2 -1
- udata/core/spatial/tests/test_api.py +115 -130
- udata/core/spatial/tests/test_fields.py +74 -77
- udata/core/spatial/tests/test_geoid.py +22 -22
- udata/core/spatial/tests/test_models.py +5 -7
- udata/core/spatial/translations.py +16 -16
- udata/core/storages/__init__.py +16 -18
- udata/core/storages/api.py +66 -64
- udata/core/storages/tasks.py +7 -7
- udata/core/storages/utils.py +15 -15
- udata/core/storages/views.py +5 -6
- udata/core/tags/api.py +17 -14
- udata/core/tags/csv.py +4 -4
- udata/core/tags/models.py +8 -5
- udata/core/tags/tasks.py +11 -13
- udata/core/tags/views.py +4 -4
- udata/core/topic/api.py +84 -73
- udata/core/topic/apiv2.py +157 -127
- udata/core/topic/factories.py +3 -4
- udata/core/topic/forms.py +12 -14
- udata/core/topic/models.py +14 -19
- udata/core/topic/parsers.py +26 -26
- udata/core/user/activities.py +30 -29
- udata/core/user/api.py +151 -152
- udata/core/user/api_fields.py +132 -100
- udata/core/user/apiv2.py +7 -7
- udata/core/user/commands.py +38 -38
- udata/core/user/factories.py +8 -9
- udata/core/user/forms.py +14 -11
- udata/core/user/metrics.py +2 -2
- udata/core/user/models.py +68 -69
- udata/core/user/permissions.py +4 -5
- udata/core/user/rdf.py +7 -8
- udata/core/user/tasks.py +2 -2
- udata/core/user/tests/test_user_model.py +24 -16
- udata/cors.py +99 -0
- udata/db/tasks.py +2 -1
- udata/entrypoints.py +35 -31
- udata/errors.py +2 -1
- udata/event/values.py +6 -6
- udata/factories.py +2 -2
- udata/features/identicon/api.py +5 -6
- udata/features/identicon/backends.py +48 -55
- udata/features/identicon/tests/test_backends.py +4 -5
- udata/features/notifications/__init__.py +0 -1
- udata/features/notifications/actions.py +9 -9
- udata/features/notifications/api.py +17 -13
- udata/features/territories/__init__.py +12 -10
- udata/features/territories/api.py +14 -15
- udata/features/territories/models.py +23 -28
- udata/features/transfer/actions.py +8 -11
- udata/features/transfer/api.py +84 -77
- udata/features/transfer/factories.py +2 -1
- udata/features/transfer/models.py +11 -12
- udata/features/transfer/notifications.py +19 -15
- udata/features/transfer/permissions.py +5 -5
- udata/forms/__init__.py +5 -2
- udata/forms/fields.py +164 -172
- udata/forms/validators.py +19 -22
- udata/forms/widgets.py +9 -13
- udata/frontend/__init__.py +31 -26
- udata/frontend/csv.py +68 -58
- udata/frontend/markdown.py +40 -44
- udata/harvest/actions.py +89 -77
- udata/harvest/api.py +294 -238
- udata/harvest/backends/__init__.py +4 -4
- udata/harvest/backends/base.py +128 -111
- udata/harvest/backends/dcat.py +80 -66
- udata/harvest/commands.py +56 -60
- udata/harvest/csv.py +8 -8
- udata/harvest/exceptions.py +6 -3
- udata/harvest/filters.py +24 -23
- udata/harvest/forms.py +27 -28
- udata/harvest/models.py +88 -80
- udata/harvest/notifications.py +15 -10
- udata/harvest/signals.py +13 -13
- udata/harvest/tasks.py +11 -10
- udata/harvest/tests/factories.py +23 -24
- udata/harvest/tests/test_actions.py +136 -166
- udata/harvest/tests/test_api.py +220 -214
- udata/harvest/tests/test_base_backend.py +117 -112
- udata/harvest/tests/test_dcat_backend.py +380 -308
- udata/harvest/tests/test_filters.py +33 -22
- udata/harvest/tests/test_models.py +11 -14
- udata/harvest/tests/test_notifications.py +6 -7
- udata/harvest/tests/test_tasks.py +7 -6
- udata/i18n.py +237 -78
- udata/linkchecker/backends.py +5 -11
- udata/linkchecker/checker.py +23 -22
- udata/linkchecker/commands.py +4 -6
- udata/linkchecker/models.py +6 -6
- udata/linkchecker/tasks.py +18 -20
- udata/mail.py +21 -21
- udata/migrations/2020-07-24-remove-s-from-scope-oauth.py +9 -8
- udata/migrations/2020-08-24-add-fs-filename.py +9 -8
- udata/migrations/2020-09-28-update-reuses-datasets-metrics.py +5 -4
- udata/migrations/2020-10-16-migrate-ods-resources.py +9 -10
- udata/migrations/2021-04-08-update-schema-with-new-structure.py +8 -7
- udata/migrations/2021-05-27-fix-default-schema-name.py +7 -6
- udata/migrations/2021-07-05-remove-unused-badges.py +17 -15
- udata/migrations/2021-07-07-update-schema-for-community-resources.py +7 -6
- udata/migrations/2021-08-17-follow-integrity.py +5 -4
- udata/migrations/2021-08-17-harvest-integrity.py +13 -12
- udata/migrations/2021-08-17-oauth2client-integrity.py +5 -4
- udata/migrations/2021-08-17-transfer-integrity.py +5 -4
- udata/migrations/2021-08-17-users-integrity.py +9 -8
- udata/migrations/2021-12-14-reuse-topics.py +7 -6
- udata/migrations/2022-04-21-improve-extension-detection.py +8 -7
- udata/migrations/2022-09-22-clean-inactive-harvest-datasets.py +16 -14
- udata/migrations/2022-10-10-add-fs_uniquifier-to-user-model.py +6 -6
- udata/migrations/2022-10-10-migrate-harvest-extras.py +36 -26
- udata/migrations/2023-02-08-rename-internal-dates.py +46 -28
- udata/migrations/2024-01-29-fix-reuse-and-dataset-with-private-None.py +10 -8
- udata/migrations/2024-03-22-migrate-activity-kwargs-to-extras.py +6 -4
- udata/migrations/2024-06-11-fix-reuse-datasets-references.py +7 -6
- udata/migrations/__init__.py +123 -105
- udata/models/__init__.py +4 -4
- udata/mongo/__init__.py +13 -11
- udata/mongo/badges_field.py +3 -2
- udata/mongo/datetime_fields.py +13 -12
- udata/mongo/document.py +17 -16
- udata/mongo/engine.py +15 -16
- udata/mongo/errors.py +2 -1
- udata/mongo/extras_fields.py +30 -20
- udata/mongo/queryset.py +12 -12
- udata/mongo/slug_fields.py +38 -28
- udata/mongo/taglist_field.py +1 -2
- udata/mongo/url_field.py +5 -5
- udata/mongo/uuid_fields.py +4 -3
- udata/notifications/__init__.py +1 -1
- udata/notifications/mattermost.py +10 -9
- udata/rdf.py +167 -188
- udata/routing.py +40 -45
- udata/search/__init__.py +18 -19
- udata/search/adapter.py +17 -16
- udata/search/commands.py +44 -51
- udata/search/fields.py +13 -20
- udata/search/query.py +23 -18
- udata/search/result.py +9 -10
- udata/sentry.py +21 -19
- udata/settings.py +262 -198
- udata/sitemap.py +8 -6
- udata/storage/s3.py +20 -13
- udata/tags.py +4 -5
- udata/tasks.py +43 -42
- udata/tests/__init__.py +9 -6
- udata/tests/api/__init__.py +8 -6
- udata/tests/api/test_auth_api.py +395 -321
- udata/tests/api/test_base_api.py +33 -35
- udata/tests/api/test_contact_points.py +7 -9
- udata/tests/api/test_dataservices_api.py +211 -158
- udata/tests/api/test_datasets_api.py +823 -812
- udata/tests/api/test_follow_api.py +13 -15
- udata/tests/api/test_me_api.py +95 -112
- udata/tests/api/test_organizations_api.py +301 -339
- udata/tests/api/test_reports_api.py +35 -25
- udata/tests/api/test_reuses_api.py +134 -139
- udata/tests/api/test_swagger.py +5 -5
- udata/tests/api/test_tags_api.py +18 -25
- udata/tests/api/test_topics_api.py +94 -94
- udata/tests/api/test_transfer_api.py +53 -48
- udata/tests/api/test_user_api.py +128 -141
- udata/tests/apiv2/test_datasets.py +290 -198
- udata/tests/apiv2/test_me_api.py +10 -11
- udata/tests/apiv2/test_organizations.py +56 -74
- udata/tests/apiv2/test_swagger.py +5 -5
- udata/tests/apiv2/test_topics.py +69 -87
- udata/tests/cli/test_cli_base.py +8 -8
- udata/tests/cli/test_db_cli.py +21 -19
- udata/tests/dataservice/test_dataservice_tasks.py +8 -12
- udata/tests/dataset/test_csv_adapter.py +44 -35
- udata/tests/dataset/test_dataset_actions.py +2 -3
- udata/tests/dataset/test_dataset_commands.py +7 -8
- udata/tests/dataset/test_dataset_events.py +36 -29
- udata/tests/dataset/test_dataset_model.py +224 -217
- udata/tests/dataset/test_dataset_rdf.py +142 -131
- udata/tests/dataset/test_dataset_tasks.py +15 -15
- udata/tests/dataset/test_resource_preview.py +10 -13
- udata/tests/features/territories/__init__.py +9 -13
- udata/tests/features/territories/test_territories_api.py +71 -91
- udata/tests/forms/test_basic_fields.py +7 -7
- udata/tests/forms/test_current_user_field.py +39 -66
- udata/tests/forms/test_daterange_field.py +31 -39
- udata/tests/forms/test_dict_field.py +28 -26
- udata/tests/forms/test_extras_fields.py +102 -76
- udata/tests/forms/test_form_field.py +8 -8
- udata/tests/forms/test_image_field.py +33 -26
- udata/tests/forms/test_model_field.py +134 -123
- udata/tests/forms/test_model_list_field.py +7 -7
- udata/tests/forms/test_nested_model_list_field.py +117 -79
- udata/tests/forms/test_publish_as_field.py +36 -65
- udata/tests/forms/test_reference_field.py +34 -53
- udata/tests/forms/test_user_forms.py +23 -21
- udata/tests/forms/test_uuid_field.py +6 -10
- udata/tests/frontend/__init__.py +9 -6
- udata/tests/frontend/test_auth.py +7 -6
- udata/tests/frontend/test_csv.py +81 -96
- udata/tests/frontend/test_hooks.py +43 -43
- udata/tests/frontend/test_markdown.py +211 -191
- udata/tests/helpers.py +32 -37
- udata/tests/models.py +2 -2
- udata/tests/organization/test_csv_adapter.py +21 -16
- udata/tests/organization/test_notifications.py +11 -18
- udata/tests/organization/test_organization_model.py +13 -13
- udata/tests/organization/test_organization_rdf.py +29 -22
- udata/tests/organization/test_organization_tasks.py +16 -17
- udata/tests/plugin.py +79 -73
- udata/tests/reuse/test_reuse_model.py +21 -21
- udata/tests/reuse/test_reuse_task.py +11 -13
- udata/tests/search/__init__.py +11 -12
- udata/tests/search/test_adapter.py +60 -70
- udata/tests/search/test_query.py +16 -16
- udata/tests/search/test_results.py +10 -7
- udata/tests/site/test_site_api.py +11 -16
- udata/tests/site/test_site_metrics.py +20 -30
- udata/tests/site/test_site_model.py +4 -5
- udata/tests/site/test_site_rdf.py +94 -78
- udata/tests/test_activity.py +17 -17
- udata/tests/test_cors.py +62 -0
- udata/tests/test_discussions.py +292 -299
- udata/tests/test_i18n.py +37 -40
- udata/tests/test_linkchecker.py +91 -85
- udata/tests/test_mail.py +13 -17
- udata/tests/test_migrations.py +219 -180
- udata/tests/test_model.py +164 -157
- udata/tests/test_notifications.py +17 -17
- udata/tests/test_owned.py +14 -14
- udata/tests/test_rdf.py +25 -23
- udata/tests/test_routing.py +89 -93
- udata/tests/test_storages.py +137 -128
- udata/tests/test_tags.py +44 -46
- udata/tests/test_topics.py +7 -7
- udata/tests/test_transfer.py +42 -49
- udata/tests/test_uris.py +160 -161
- udata/tests/test_utils.py +79 -71
- udata/tests/user/test_user_rdf.py +5 -9
- udata/tests/workers/test_jobs_commands.py +57 -58
- udata/tests/workers/test_tasks_routing.py +23 -29
- udata/tests/workers/test_workers_api.py +125 -131
- udata/tests/workers/test_workers_helpers.py +6 -6
- udata/tracking.py +4 -6
- udata/uris.py +45 -46
- udata/utils.py +68 -66
- udata/wsgi.py +1 -1
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/METADATA +7 -3
- udata-9.1.2.dev30454.dist-info/RECORD +706 -0
- udata-9.1.2.dev30355.dist-info/RECORD +0 -704
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/LICENSE +0 -0
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/WHEEL +0 -0
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/entry_points.txt +0 -0
- {udata-9.1.2.dev30355.dist-info → udata-9.1.2.dev30454.dist-info}/top_level.txt +0 -0
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
|
|
3
1
|
from datetime import datetime, timedelta
|
|
4
2
|
from urllib.parse import urlparse
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
5
|
from dateutil.parser import parse
|
|
6
6
|
from voluptuous import Schema
|
|
7
7
|
|
|
8
|
-
from udata.harvest.models import HarvestItem
|
|
9
|
-
from udata.utils import faker
|
|
10
8
|
from udata.core.dataset import tasks
|
|
11
9
|
from udata.core.dataset.factories import DatasetFactory
|
|
10
|
+
from udata.harvest.models import HarvestItem
|
|
12
11
|
from udata.models import Dataset
|
|
13
12
|
from udata.tests.helpers import assert_equal_dates
|
|
13
|
+
from udata.utils import faker
|
|
14
14
|
|
|
15
|
-
from
|
|
16
|
-
|
|
17
|
-
from ..backends import BaseBackend, HarvestFilter, HarvestFeature
|
|
15
|
+
from ..backends import BaseBackend, HarvestFeature, HarvestFilter
|
|
18
16
|
from ..exceptions import HarvestException
|
|
17
|
+
from .factories import HarvestSourceFactory
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
class Unknown:
|
|
@@ -24,17 +23,17 @@ class Unknown:
|
|
|
24
23
|
|
|
25
24
|
class FakeBackend(BaseBackend):
|
|
26
25
|
filters = (
|
|
27
|
-
HarvestFilter(
|
|
28
|
-
HarvestFilter(
|
|
26
|
+
HarvestFilter("First filter", "first", str),
|
|
27
|
+
HarvestFilter("Second filter", "second", str),
|
|
29
28
|
)
|
|
30
29
|
features = (
|
|
31
|
-
HarvestFeature(
|
|
32
|
-
HarvestFeature(
|
|
30
|
+
HarvestFeature("feature", "A test feature"),
|
|
31
|
+
HarvestFeature("enabled", "A test feature enabled by default", default=True),
|
|
33
32
|
)
|
|
34
33
|
|
|
35
34
|
def inner_harvest(self):
|
|
36
|
-
for i in range(self.source.config.get(
|
|
37
|
-
remote_id = f
|
|
35
|
+
for i in range(self.source.config.get("nb_datasets", 3)):
|
|
36
|
+
remote_id = f"fake-{i}"
|
|
38
37
|
self.process_dataset(remote_id)
|
|
39
38
|
if self.is_done():
|
|
40
39
|
return
|
|
@@ -44,37 +43,37 @@ class FakeBackend(BaseBackend):
|
|
|
44
43
|
|
|
45
44
|
for key, value in DatasetFactory.as_dict(visible=True).items():
|
|
46
45
|
setattr(dataset, key, value)
|
|
47
|
-
if self.source.config.get(
|
|
48
|
-
dataset.last_modified_internal = self.source.config[
|
|
46
|
+
if self.source.config.get("last_modified"):
|
|
47
|
+
dataset.last_modified_internal = self.source.config["last_modified"]
|
|
49
48
|
return dataset
|
|
50
49
|
|
|
51
50
|
|
|
52
51
|
class HarvestFilterTest:
|
|
53
|
-
@pytest.mark.parametrize(
|
|
52
|
+
@pytest.mark.parametrize("type,expected", HarvestFilter.TYPES.items())
|
|
54
53
|
def test_type_ok(self, type, expected):
|
|
55
54
|
label = faker.word()
|
|
56
55
|
key = faker.word()
|
|
57
56
|
description = faker.sentence()
|
|
58
57
|
hf = HarvestFilter(label, key, type, description)
|
|
59
58
|
assert hf.as_dict() == {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
"label": label,
|
|
60
|
+
"key": key,
|
|
61
|
+
"type": expected,
|
|
62
|
+
"description": description,
|
|
64
63
|
}
|
|
65
64
|
|
|
66
|
-
@pytest.mark.parametrize(
|
|
65
|
+
@pytest.mark.parametrize("type", [dict, list, tuple, Unknown])
|
|
67
66
|
def test_type_ko(self, type):
|
|
68
67
|
with pytest.raises(TypeError):
|
|
69
68
|
HarvestFilter(faker.word(), faker.word(), type, faker.sentence())
|
|
70
69
|
|
|
71
70
|
|
|
72
|
-
@pytest.mark.usefixtures(
|
|
71
|
+
@pytest.mark.usefixtures("clean_db")
|
|
73
72
|
class BaseBackendTest:
|
|
74
73
|
def test_simple_harvest(self):
|
|
75
74
|
now = datetime.utcnow()
|
|
76
75
|
nb_datasets = 3
|
|
77
|
-
source = HarvestSourceFactory(config={
|
|
76
|
+
source = HarvestSourceFactory(config={"nb_datasets": nb_datasets})
|
|
78
77
|
backend = FakeBackend(source)
|
|
79
78
|
|
|
80
79
|
job = backend.harvest()
|
|
@@ -85,34 +84,36 @@ class BaseBackendTest:
|
|
|
85
84
|
assert_equal_dates(dataset.last_modified, now)
|
|
86
85
|
assert dataset.harvest.source_id == str(source.id)
|
|
87
86
|
assert dataset.harvest.domain == source.domain
|
|
88
|
-
assert dataset.harvest.remote_id.startswith(
|
|
87
|
+
assert dataset.harvest.remote_id.startswith("fake-")
|
|
89
88
|
assert_equal_dates(dataset.harvest.last_update, now)
|
|
90
89
|
|
|
91
90
|
def test_has_feature_defaults(self):
|
|
92
91
|
source = HarvestSourceFactory()
|
|
93
92
|
backend = FakeBackend(source)
|
|
94
93
|
|
|
95
|
-
assert not backend.has_feature(
|
|
96
|
-
assert backend.has_feature(
|
|
94
|
+
assert not backend.has_feature("feature")
|
|
95
|
+
assert backend.has_feature("enabled")
|
|
97
96
|
|
|
98
97
|
def test_has_feature_defined(self):
|
|
99
|
-
source = HarvestSourceFactory(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
98
|
+
source = HarvestSourceFactory(
|
|
99
|
+
config={
|
|
100
|
+
"features": {
|
|
101
|
+
"feature": True,
|
|
102
|
+
"enabled": False,
|
|
103
|
+
}
|
|
103
104
|
}
|
|
104
|
-
|
|
105
|
+
)
|
|
105
106
|
backend = FakeBackend(source)
|
|
106
107
|
|
|
107
|
-
assert backend.has_feature(
|
|
108
|
-
assert not backend.has_feature(
|
|
108
|
+
assert backend.has_feature("feature")
|
|
109
|
+
assert not backend.has_feature("enabled")
|
|
109
110
|
|
|
110
111
|
def test_has_feature_unkown(self):
|
|
111
112
|
source = HarvestSourceFactory()
|
|
112
113
|
backend = FakeBackend(source)
|
|
113
114
|
|
|
114
115
|
with pytest.raises(HarvestException):
|
|
115
|
-
backend.has_feature(
|
|
116
|
+
backend.has_feature("unknown")
|
|
116
117
|
|
|
117
118
|
def test_get_filters_empty(self):
|
|
118
119
|
source = HarvestSourceFactory()
|
|
@@ -121,19 +122,21 @@ class BaseBackendTest:
|
|
|
121
122
|
assert backend.get_filters() == []
|
|
122
123
|
|
|
123
124
|
def test_get_filters(self):
|
|
124
|
-
source = HarvestSourceFactory(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
125
|
+
source = HarvestSourceFactory(
|
|
126
|
+
config={
|
|
127
|
+
"filters": [
|
|
128
|
+
{"key": "second", "value": ""},
|
|
129
|
+
{"key": "first", "value": ""},
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
)
|
|
130
133
|
backend = FakeBackend(source)
|
|
131
134
|
|
|
132
|
-
assert [f[
|
|
135
|
+
assert [f["key"] for f in backend.get_filters()] == ["second", "first"]
|
|
133
136
|
|
|
134
137
|
def test_harvest_source_id(self):
|
|
135
138
|
nb_datasets = 3
|
|
136
|
-
source = HarvestSourceFactory(config={
|
|
139
|
+
source = HarvestSourceFactory(config={"nb_datasets": nb_datasets})
|
|
137
140
|
backend = FakeBackend(source)
|
|
138
141
|
|
|
139
142
|
job = backend.harvest()
|
|
@@ -149,12 +152,12 @@ class BaseBackendTest:
|
|
|
149
152
|
assert len(datasets) == nb_datasets
|
|
150
153
|
for dataset in datasets:
|
|
151
154
|
assert dataset.harvest.source_id == str(source.id)
|
|
152
|
-
parsed = urlparse(source_url).netloc.split(
|
|
155
|
+
parsed = urlparse(source_url).netloc.split(":")[0]
|
|
153
156
|
assert parsed == dataset.harvest.domain
|
|
154
157
|
|
|
155
158
|
def test_dont_overwrite_last_modified(self, mocker):
|
|
156
|
-
last_modified = faker.date_time_between(start_date=
|
|
157
|
-
source = HarvestSourceFactory(config={
|
|
159
|
+
last_modified = faker.date_time_between(start_date="-30y", end_date="-1y")
|
|
160
|
+
source = HarvestSourceFactory(config={"nb_datasets": 1, "last_modified": last_modified})
|
|
158
161
|
backend = FakeBackend(source)
|
|
159
162
|
|
|
160
163
|
backend.harvest()
|
|
@@ -165,8 +168,8 @@ class BaseBackendTest:
|
|
|
165
168
|
assert_equal_dates(dataset.harvest.last_update, datetime.utcnow())
|
|
166
169
|
|
|
167
170
|
def test_dont_overwrite_last_modified_even_if_set_to_same(self, mocker):
|
|
168
|
-
last_modified = faker.date_time_between(start_date=
|
|
169
|
-
source = HarvestSourceFactory(config={
|
|
171
|
+
last_modified = faker.date_time_between(start_date="-30y", end_date="-1y")
|
|
172
|
+
source = HarvestSourceFactory(config={"nb_datasets": 1, "last_modified": last_modified})
|
|
170
173
|
backend = FakeBackend(source)
|
|
171
174
|
|
|
172
175
|
backend.harvest()
|
|
@@ -179,28 +182,32 @@ class BaseBackendTest:
|
|
|
179
182
|
|
|
180
183
|
def test_autoarchive(self, app):
|
|
181
184
|
nb_datasets = 3
|
|
182
|
-
source = HarvestSourceFactory(config={
|
|
185
|
+
source = HarvestSourceFactory(config={"nb_datasets": nb_datasets})
|
|
183
186
|
backend = FakeBackend(source)
|
|
184
187
|
|
|
185
188
|
# create a dangling dataset to be archived
|
|
186
|
-
limit = app.config[
|
|
189
|
+
limit = app.config["HARVEST_AUTOARCHIVE_GRACE_DAYS"]
|
|
187
190
|
last_update = datetime.utcnow() - timedelta(days=limit + 1)
|
|
188
|
-
dataset_arch = DatasetFactory(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
dataset_arch = DatasetFactory(
|
|
192
|
+
harvest={
|
|
193
|
+
"domain": source.domain,
|
|
194
|
+
"source_id": str(source.id),
|
|
195
|
+
"remote_id": "not-on-remote",
|
|
196
|
+
"last_update": last_update,
|
|
197
|
+
}
|
|
198
|
+
)
|
|
194
199
|
|
|
195
200
|
# create a dangling dataset that _won't_ be archived because of grace period
|
|
196
|
-
limit = app.config[
|
|
201
|
+
limit = app.config["HARVEST_AUTOARCHIVE_GRACE_DAYS"]
|
|
197
202
|
last_update = datetime.utcnow() - timedelta(days=limit - 1)
|
|
198
|
-
dataset_no_arch = DatasetFactory(
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
203
|
+
dataset_no_arch = DatasetFactory(
|
|
204
|
+
harvest={
|
|
205
|
+
"domain": source.domain,
|
|
206
|
+
"source_id": str(source.id),
|
|
207
|
+
"remote_id": "not-on-remote-two",
|
|
208
|
+
"last_update": last_update,
|
|
209
|
+
}
|
|
210
|
+
)
|
|
204
211
|
|
|
205
212
|
job = backend.harvest()
|
|
206
213
|
|
|
@@ -209,35 +216,35 @@ class BaseBackendTest:
|
|
|
209
216
|
# all datasets : 3 mocks + 2 manuals (arch and no_arch)
|
|
210
217
|
assert Dataset.objects.count() == nb_datasets + 2
|
|
211
218
|
|
|
212
|
-
archived_items = [i for i in job.items if i.status ==
|
|
219
|
+
archived_items = [i for i in job.items if i.status == "archived"]
|
|
213
220
|
assert len(archived_items) == 1
|
|
214
221
|
assert archived_items[0].dataset == dataset_arch
|
|
215
222
|
|
|
216
223
|
dataset_arch.reload()
|
|
217
224
|
assert dataset_arch.archived is not None
|
|
218
|
-
assert
|
|
219
|
-
assert
|
|
225
|
+
assert "archived" in dataset_arch.harvest
|
|
226
|
+
assert "archived_at" in dataset_arch.harvest
|
|
220
227
|
|
|
221
228
|
dataset_no_arch.reload()
|
|
222
229
|
assert dataset_no_arch.archived is None
|
|
223
|
-
assert
|
|
224
|
-
assert
|
|
230
|
+
assert "archived" not in dataset_no_arch.harvest
|
|
231
|
+
assert "archived_at" not in dataset_no_arch.harvest
|
|
225
232
|
|
|
226
233
|
# test unarchive: archive manually then relaunch harvest
|
|
227
|
-
dataset = Dataset.objects.get(**{
|
|
234
|
+
dataset = Dataset.objects.get(**{"harvest__remote_id": "fake-1"})
|
|
228
235
|
dataset.archived = datetime.utcnow()
|
|
229
|
-
dataset.harvest.archived =
|
|
236
|
+
dataset.harvest.archived = "not-on-remote"
|
|
230
237
|
dataset.harvest.archived_at = datetime.utcnow()
|
|
231
238
|
dataset.save()
|
|
232
239
|
backend.harvest()
|
|
233
240
|
dataset.reload()
|
|
234
241
|
assert dataset.archived is None
|
|
235
|
-
assert
|
|
236
|
-
assert
|
|
242
|
+
assert "archived" not in dataset.harvest
|
|
243
|
+
assert "archived_at" not in dataset.harvest
|
|
237
244
|
|
|
238
245
|
def test_harvest_datasets_get_deleted(self):
|
|
239
246
|
nb_datasets = 3
|
|
240
|
-
source = HarvestSourceFactory(config={
|
|
247
|
+
source = HarvestSourceFactory(config={"nb_datasets": nb_datasets})
|
|
241
248
|
backend = FakeBackend(source)
|
|
242
249
|
|
|
243
250
|
job = backend.harvest()
|
|
@@ -246,7 +253,7 @@ class BaseBackendTest:
|
|
|
246
253
|
assert item.dataset is not None
|
|
247
254
|
|
|
248
255
|
for dataset in Dataset.objects():
|
|
249
|
-
dataset.deleted =
|
|
256
|
+
dataset.deleted = "2016-01-01"
|
|
250
257
|
dataset.save()
|
|
251
258
|
|
|
252
259
|
tasks.purge_datasets()
|
|
@@ -256,81 +263,79 @@ class BaseBackendTest:
|
|
|
256
263
|
assert item.dataset is None
|
|
257
264
|
|
|
258
265
|
|
|
259
|
-
@pytest.mark.usefixtures(
|
|
266
|
+
@pytest.mark.usefixtures("clean_db")
|
|
260
267
|
class BaseBackendValidateTest:
|
|
261
268
|
@pytest.fixture
|
|
262
269
|
def validate(self):
|
|
263
270
|
return FakeBackend(HarvestSourceFactory()).validate
|
|
264
271
|
|
|
265
272
|
def test_valid_data(self, validate):
|
|
266
|
-
schema = Schema({
|
|
267
|
-
data = {
|
|
273
|
+
schema = Schema({"key": str})
|
|
274
|
+
data = {"key": "value"}
|
|
268
275
|
assert validate(data, schema) == data
|
|
269
276
|
|
|
270
277
|
def test_handle_basic_error(self, validate):
|
|
271
|
-
schema = Schema({
|
|
272
|
-
data = {
|
|
278
|
+
schema = Schema({"bad-value": str})
|
|
279
|
+
data = {"bad-value": 42}
|
|
273
280
|
with pytest.raises(HarvestException) as excinfo:
|
|
274
281
|
validate(data, schema)
|
|
275
282
|
msg = str(excinfo.value)
|
|
276
|
-
assert
|
|
283
|
+
assert "[bad-value] expected str: 42" in msg
|
|
277
284
|
|
|
278
285
|
def test_handle_required_values(self, validate):
|
|
279
|
-
schema = Schema({
|
|
286
|
+
schema = Schema({"missing": str}, required=True)
|
|
280
287
|
data = {}
|
|
281
288
|
with pytest.raises(HarvestException) as excinfo:
|
|
282
289
|
validate(data, schema)
|
|
283
290
|
msg = str(excinfo.value)
|
|
284
|
-
assert
|
|
285
|
-
assert
|
|
291
|
+
assert "[missing] required key not provided" in msg
|
|
292
|
+
assert "[missing] required key not provided: None" not in msg
|
|
286
293
|
|
|
287
294
|
def test_handle_multiple_errors_on_object(self, validate):
|
|
288
|
-
schema = Schema({
|
|
289
|
-
data = {
|
|
295
|
+
schema = Schema({"bad-value": str, "other-bad-value": int})
|
|
296
|
+
data = {"bad-value": 42, "other-bad-value": "wrong"}
|
|
290
297
|
with pytest.raises(HarvestException) as excinfo:
|
|
291
298
|
validate(data, schema)
|
|
292
299
|
msg = str(excinfo.value)
|
|
293
|
-
assert
|
|
294
|
-
assert
|
|
300
|
+
assert "[bad-value] expected str: 42" in msg
|
|
301
|
+
assert "[other-bad-value] expected int: wrong" in msg
|
|
295
302
|
|
|
296
303
|
def test_handle_multiple_error_on_nested_object(self, validate):
|
|
297
|
-
schema = Schema({
|
|
298
|
-
|
|
299
|
-
}})
|
|
300
|
-
data = {'nested': {'bad-value': 42, 'other-bad-value': 'wrong'}}
|
|
304
|
+
schema = Schema({"nested": {"bad-value": str, "other-bad-value": int}})
|
|
305
|
+
data = {"nested": {"bad-value": 42, "other-bad-value": "wrong"}}
|
|
301
306
|
with pytest.raises(HarvestException) as excinfo:
|
|
302
307
|
validate(data, schema)
|
|
303
308
|
msg = str(excinfo.value)
|
|
304
|
-
assert
|
|
305
|
-
assert
|
|
309
|
+
assert "[nested.bad-value] expected str: 42" in msg
|
|
310
|
+
assert "[nested.other-bad-value] expected int: wrong" in msg
|
|
306
311
|
|
|
307
312
|
def test_handle_multiple_error_on_nested_list(self, validate):
|
|
308
|
-
schema = Schema({
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
313
|
+
schema = Schema({"nested": [{"bad-value": str, "other-bad-value": int}]})
|
|
314
|
+
data = {
|
|
315
|
+
"nested": [
|
|
316
|
+
{"bad-value": 42, "other-bad-value": "wrong"},
|
|
317
|
+
]
|
|
318
|
+
}
|
|
314
319
|
with pytest.raises(HarvestException) as excinfo:
|
|
315
320
|
validate(data, schema)
|
|
316
321
|
msg = str(excinfo.value)
|
|
317
|
-
assert
|
|
318
|
-
assert
|
|
322
|
+
assert "[nested.0.bad-value] expected str: 42" in msg
|
|
323
|
+
assert "[nested.0.other-bad-value] expected int: wrong" in msg
|
|
319
324
|
|
|
320
325
|
# See: https://github.com/alecthomas/voluptuous/pull/330
|
|
321
|
-
@pytest.mark.skip(reason=
|
|
326
|
+
@pytest.mark.skip(reason="Not yet supported by Voluptuous")
|
|
322
327
|
def test_handle_multiple_error_on_nested_list_items(self, validate):
|
|
323
|
-
schema = Schema({
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
328
|
+
schema = Schema({"nested": [{"bad-value": str, "other-bad-value": int}]})
|
|
329
|
+
data = {
|
|
330
|
+
"nested": [
|
|
331
|
+
{"bad-value": 42, "other-bad-value": "wrong"},
|
|
332
|
+
{"bad-value": 43, "other-bad-value": "bad"},
|
|
333
|
+
]
|
|
334
|
+
}
|
|
330
335
|
with pytest.raises(HarvestException) as excinfo:
|
|
331
336
|
validate(data, schema)
|
|
332
337
|
msg = str(excinfo.value)
|
|
333
|
-
assert
|
|
334
|
-
assert
|
|
335
|
-
assert
|
|
336
|
-
assert
|
|
338
|
+
assert "[nested.0.bad-value] expected str: 42" in msg
|
|
339
|
+
assert "[nested.0.other-bad-value] expected int: wrong" in msg
|
|
340
|
+
assert "[nested.1.bad-value] expected str: 43" in msg
|
|
341
|
+
assert "[nested.1.other-bad-value] expected int: bad" in msg
|