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,6 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
import pytest
|
|
3
2
|
|
|
3
|
+
import pytest
|
|
4
4
|
from voluptuous import Invalid
|
|
5
5
|
|
|
6
6
|
from udata.harvest import filters
|
|
@@ -10,11 +10,23 @@ log = logging.getLogger(__name__)
|
|
|
10
10
|
|
|
11
11
|
class FiltersTest:
|
|
12
12
|
def test_boolean(self):
|
|
13
|
-
true_values = (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
true_values = (
|
|
14
|
+
"1",
|
|
15
|
+
"on",
|
|
16
|
+
"t",
|
|
17
|
+
"TRUE",
|
|
18
|
+
"true",
|
|
19
|
+
"y",
|
|
20
|
+
"yes",
|
|
21
|
+
" 1 ",
|
|
22
|
+
" tRuE ",
|
|
23
|
+
True,
|
|
24
|
+
1,
|
|
25
|
+
2,
|
|
26
|
+
-1,
|
|
27
|
+
)
|
|
28
|
+
false_values = ("0", "f", "FALSE", "false", "n", "no", "off", " 0 ", " f ", False, 0)
|
|
29
|
+
none_values = ("", " ", None)
|
|
18
30
|
|
|
19
31
|
for value in true_values:
|
|
20
32
|
assert filters.boolean(value)
|
|
@@ -26,11 +38,11 @@ class FiltersTest:
|
|
|
26
38
|
assert filters.boolean(value) is None
|
|
27
39
|
|
|
28
40
|
with pytest.raises(Invalid):
|
|
29
|
-
filters.boolean(
|
|
41
|
+
filters.boolean("vrai")
|
|
30
42
|
|
|
31
43
|
def test_empty_none(self):
|
|
32
|
-
empty_values = 0,
|
|
33
|
-
non_empty_values =
|
|
44
|
+
empty_values = 0, "", [], {}
|
|
45
|
+
non_empty_values = "hello", " hello "
|
|
34
46
|
|
|
35
47
|
for value in empty_values:
|
|
36
48
|
assert filters.empty_none(value) is None
|
|
@@ -39,39 +51,38 @@ class FiltersTest:
|
|
|
39
51
|
assert filters.empty_none(value) == value
|
|
40
52
|
|
|
41
53
|
def test_strip(self):
|
|
42
|
-
assert filters.strip(
|
|
43
|
-
assert filters.strip(
|
|
54
|
+
assert filters.strip(" hello ") == "hello"
|
|
55
|
+
assert filters.strip(" ") is None
|
|
44
56
|
|
|
45
57
|
def test_line_endings(self):
|
|
46
|
-
result = filters.line_endings(
|
|
47
|
-
assert result ==
|
|
58
|
+
result = filters.line_endings("hello\r\nworld!\r ")
|
|
59
|
+
assert result == "hello\nworld!\n "
|
|
48
60
|
|
|
49
61
|
def test_hash(self):
|
|
50
62
|
hashes = {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
'faf03a114abf9306591117d781966268f9')
|
|
63
|
+
"md5": "bd8668597bfba2d1843441d7199bea65",
|
|
64
|
+
"sha1": "f2f0249827f501286b4713683e526d541d2cc7e2",
|
|
65
|
+
"sha256": ("c4373e1d81eb44882bf9ff539d0e5f" "faf03a114abf9306591117d781966268f9"),
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
for type, value in hashes.items():
|
|
58
|
-
assert filters.hash(value) == {
|
|
69
|
+
assert filters.hash(value) == {"type": type, "value": value}
|
|
59
70
|
|
|
60
71
|
def test_unknown_hash(self):
|
|
61
|
-
assert filters.hash(
|
|
72
|
+
assert filters.hash("xxxx") is None
|
|
62
73
|
assert filters.hash(None) is None
|
|
63
74
|
|
|
64
75
|
|
|
65
76
|
class IsUrlFilterTest:
|
|
66
77
|
def test_valid_url_with_defaults(self):
|
|
67
78
|
f = filters.is_url()
|
|
68
|
-
assert f(
|
|
79
|
+
assert f("https://somewhere.com/path") == "https://somewhere.com/path"
|
|
69
80
|
|
|
70
81
|
def test_allowed_scheme_not_allowed(self):
|
|
71
82
|
f = filters.is_url()
|
|
72
83
|
with pytest.raises(Invalid):
|
|
73
|
-
f(
|
|
84
|
+
f("not-allowed://somewhere.com")
|
|
74
85
|
|
|
75
86
|
def test_valid_url_with_default_scheme(self):
|
|
76
87
|
f = filters.is_url()
|
|
77
|
-
assert f(
|
|
88
|
+
assert f("somewhere.com/path") == "http://somewhere.com/path"
|
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
|
|
2
3
|
import pytest
|
|
3
4
|
|
|
4
5
|
from udata.utils import faker
|
|
5
6
|
|
|
6
7
|
from ..models import HarvestSource
|
|
7
8
|
|
|
8
|
-
|
|
9
9
|
log = logging.getLogger(__name__)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
@pytest.mark.usefixtures(
|
|
12
|
+
@pytest.mark.usefixtures("clean_db")
|
|
13
13
|
class HarvestSourceTest:
|
|
14
14
|
def test_defaults(self):
|
|
15
|
-
source = HarvestSource.objects.create(name=
|
|
16
|
-
assert source.name ==
|
|
17
|
-
assert source.slug ==
|
|
15
|
+
source = HarvestSource.objects.create(name="Test", url=faker.url(), backend="factory")
|
|
16
|
+
assert source.name == "Test"
|
|
17
|
+
assert source.slug == "test"
|
|
18
18
|
|
|
19
19
|
def test_domain(self):
|
|
20
|
-
source = HarvestSource(name=
|
|
21
|
-
|
|
22
|
-
assert source.domain == 'www.somewhere.com'
|
|
20
|
+
source = HarvestSource(name="Test", url="http://www.somewhere.com/path/")
|
|
21
|
+
assert source.domain == "www.somewhere.com"
|
|
23
22
|
|
|
24
|
-
source = HarvestSource(name=
|
|
25
|
-
|
|
26
|
-
assert source.domain == 'www.somewhere.com'
|
|
23
|
+
source = HarvestSource(name="Test", url="https://www.somewhere.com/path/")
|
|
24
|
+
assert source.domain == "www.somewhere.com"
|
|
27
25
|
|
|
28
|
-
source = HarvestSource(name=
|
|
29
|
-
|
|
30
|
-
assert source.domain == 'www.somewhere.com'
|
|
26
|
+
source = HarvestSource(name="Test", url="http://www.somewhere.com:666/path/")
|
|
27
|
+
assert source.domain == "www.somewhere.com"
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
|
|
3
|
-
from udata.core.user.factories import
|
|
4
|
-
|
|
5
|
-
from .factories import HarvestSourceFactory
|
|
6
|
-
|
|
3
|
+
from udata.core.user.factories import AdminFactory, UserFactory
|
|
7
4
|
from udata.harvest.notifications import validate_harvester_notifications
|
|
8
5
|
from udata.tests.helpers import assert_equal_dates
|
|
9
6
|
|
|
7
|
+
from .factories import HarvestSourceFactory
|
|
8
|
+
|
|
10
9
|
|
|
11
|
-
@pytest.mark.usefixtures(
|
|
10
|
+
@pytest.mark.usefixtures("clean_db")
|
|
12
11
|
class HarvestNotificationsTest:
|
|
13
12
|
def test_pending_harvester_validations(self):
|
|
14
13
|
source = HarvestSourceFactory()
|
|
@@ -22,5 +21,5 @@ class HarvestNotificationsTest:
|
|
|
22
21
|
assert len(notifications) == 1
|
|
23
22
|
dt, details = notifications[0]
|
|
24
23
|
assert_equal_dates(dt, source.created_at)
|
|
25
|
-
assert details[
|
|
26
|
-
assert details[
|
|
24
|
+
assert details["id"] == source.id
|
|
25
|
+
assert details["name"] == source.name
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
|
|
2
3
|
import pytest
|
|
3
4
|
|
|
4
|
-
from ..tasks import
|
|
5
|
+
from ..tasks import purge_harvest_jobs, purge_harvest_sources
|
|
5
6
|
|
|
6
7
|
log = logging.getLogger(__name__)
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
@pytest.mark.usefixtures(
|
|
10
|
+
@pytest.mark.usefixtures("clean_db")
|
|
10
11
|
class HarvestActionsTest:
|
|
11
12
|
def test_purge_sources(self, mocker):
|
|
12
|
-
|
|
13
|
-
mock = mocker.patch(
|
|
13
|
+
"""It should purge from DB sources flagged as deleted"""
|
|
14
|
+
mock = mocker.patch("udata.harvest.actions.purge_sources")
|
|
14
15
|
purge_harvest_sources()
|
|
15
16
|
mock.assert_called_once_with()
|
|
16
17
|
|
|
17
18
|
def test_purge_jobs(self, mocker):
|
|
18
|
-
|
|
19
|
-
mock = mocker.patch(
|
|
19
|
+
"""It should purge from DB jobs older than retention policy"""
|
|
20
|
+
mock = mocker.patch("udata.harvest.actions.purge_jobs")
|
|
20
21
|
purge_harvest_jobs()
|
|
21
22
|
mock.assert_called_once_with()
|
udata/i18n.py
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import importlib.util
|
|
2
|
-
|
|
3
2
|
from contextlib import contextmanager
|
|
4
|
-
from
|
|
3
|
+
from datetime import datetime
|
|
5
4
|
from glob import iglob
|
|
5
|
+
from os.path import basename, dirname, join
|
|
6
6
|
|
|
7
|
+
import flask_babel
|
|
8
|
+
from babel.dates import format_timedelta as babel_format_timedelta
|
|
7
9
|
from flask import ( # noqa
|
|
8
|
-
|
|
10
|
+
abort,
|
|
11
|
+
current_app,
|
|
12
|
+
g,
|
|
13
|
+
has_request_context,
|
|
14
|
+
redirect,
|
|
15
|
+
request,
|
|
16
|
+
url_for,
|
|
9
17
|
)
|
|
10
18
|
from flask.blueprints import BlueprintSetupState, _endpoint_from_view_func
|
|
11
|
-
|
|
12
|
-
from babel.dates import format_timedelta as babel_format_timedelta
|
|
13
|
-
|
|
14
|
-
from datetime import datetime
|
|
15
|
-
|
|
16
|
-
import flask_babel
|
|
17
|
-
from flask_babel import Babel, refresh
|
|
18
|
-
from flask_babel import format_date, format_datetime # noqa
|
|
19
|
+
from flask_babel import Babel, format_date, format_datetime, refresh # noqa
|
|
19
20
|
from flask_babel import get_locale as get_current_locale # noqa
|
|
20
|
-
|
|
21
21
|
from werkzeug.local import LocalProxy
|
|
22
22
|
|
|
23
23
|
from udata import entrypoints
|
|
@@ -36,8 +36,9 @@ def get_translation_directories_and_domains():
|
|
|
36
36
|
spec = importlib.util.find_spec(pkg)
|
|
37
37
|
path = dirname(spec.origin)
|
|
38
38
|
plugin_domains = [
|
|
39
|
-
f.replace(path,
|
|
40
|
-
for f in iglob(join(path,
|
|
39
|
+
f.replace(path, "").replace(".pot", "")[1:]
|
|
40
|
+
for f in iglob(join(path, "**/translations/*.pot"), recursive=True)
|
|
41
|
+
]
|
|
41
42
|
for domain in plugin_domains:
|
|
42
43
|
translations_dir.append(join(path, dirname(domain)))
|
|
43
44
|
domains.append(basename(domain))
|
|
@@ -46,7 +47,7 @@ def get_translation_directories_and_domains():
|
|
|
46
47
|
|
|
47
48
|
|
|
48
49
|
def get_locale():
|
|
49
|
-
if getattr(g,
|
|
50
|
+
if getattr(g, "lang_code", None):
|
|
50
51
|
return g.lang_code
|
|
51
52
|
return str(default_lang)
|
|
52
53
|
|
|
@@ -88,22 +89,25 @@ def lazy_pgettext(*args, **kwargs):
|
|
|
88
89
|
return flask_babel.lazy_pgettext(*args, **kwargs)
|
|
89
90
|
|
|
90
91
|
|
|
91
|
-
def format_timedelta(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
def format_timedelta(
|
|
93
|
+
datetime_or_timedelta, granularity="second", add_direction=False, threshold=0.85
|
|
94
|
+
):
|
|
95
|
+
"""This is format_timedelta from Flask-Babel"""
|
|
96
|
+
"""Flask-BabelEx missed the add_direction parameter"""
|
|
95
97
|
if isinstance(datetime_or_timedelta, datetime):
|
|
96
98
|
datetime_or_timedelta = datetime.utcnow() - datetime_or_timedelta
|
|
97
|
-
return babel_format_timedelta(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
return babel_format_timedelta(
|
|
100
|
+
datetime_or_timedelta,
|
|
101
|
+
granularity,
|
|
102
|
+
threshold=threshold,
|
|
103
|
+
add_direction=add_direction,
|
|
104
|
+
locale=get_current_locale(),
|
|
105
|
+
)
|
|
102
106
|
|
|
103
107
|
|
|
104
108
|
def _default_lang(user=None):
|
|
105
|
-
lang = getattr(user or current_user,
|
|
106
|
-
return lang or current_app.config[
|
|
109
|
+
lang = getattr(user or current_user, "prefered_language", None)
|
|
110
|
+
return lang or current_app.config["DEFAULT_LANGUAGE"]
|
|
107
111
|
|
|
108
112
|
|
|
109
113
|
default_lang = LocalProxy(lambda: _default_lang())
|
|
@@ -111,12 +115,12 @@ default_lang = LocalProxy(lambda: _default_lang())
|
|
|
111
115
|
|
|
112
116
|
@contextmanager
|
|
113
117
|
def language(lang_code):
|
|
114
|
-
|
|
118
|
+
"""Force a given language"""
|
|
115
119
|
ctx = None
|
|
116
120
|
if not request:
|
|
117
121
|
ctx = current_app.test_request_context()
|
|
118
122
|
ctx.push()
|
|
119
|
-
backup = g.get(
|
|
123
|
+
backup = g.get("lang_code")
|
|
120
124
|
g.lang_code = lang_code
|
|
121
125
|
refresh()
|
|
122
126
|
yield
|
|
@@ -127,10 +131,13 @@ def language(lang_code):
|
|
|
127
131
|
|
|
128
132
|
|
|
129
133
|
def check_config(cfg):
|
|
130
|
-
default_language = cfg[
|
|
131
|
-
if default_language not in cfg.get(
|
|
132
|
-
raise ConfigError(
|
|
133
|
-
|
|
134
|
+
default_language = cfg["DEFAULT_LANGUAGE"]
|
|
135
|
+
if default_language not in cfg.get("LANGUAGES", []):
|
|
136
|
+
raise ConfigError(
|
|
137
|
+
"You are using a DEFAULT_LANGUAGE {0} not defined " "into LANGUAGES".format(
|
|
138
|
+
default_language
|
|
139
|
+
)
|
|
140
|
+
)
|
|
134
141
|
|
|
135
142
|
|
|
136
143
|
def init_app(app):
|
|
@@ -138,44 +145,43 @@ def init_app(app):
|
|
|
138
145
|
translations_dir, domains = get_translation_directories_and_domains()
|
|
139
146
|
Babel(
|
|
140
147
|
app,
|
|
141
|
-
default_locale=app.config[
|
|
142
|
-
default_translation_directories=
|
|
143
|
-
default_domain=
|
|
144
|
-
locale_selector=get_locale
|
|
148
|
+
default_locale=app.config["DEFAULT_LANGUAGE"],
|
|
149
|
+
default_translation_directories=";".join(translations_dir),
|
|
150
|
+
default_domain=";".join(domains),
|
|
151
|
+
locale_selector=get_locale,
|
|
145
152
|
)
|
|
146
153
|
|
|
147
154
|
|
|
148
155
|
def _add_language_code(endpoint, values):
|
|
149
156
|
try:
|
|
150
|
-
if current_app.url_map.is_endpoint_expecting(endpoint,
|
|
151
|
-
values.setdefault(
|
|
157
|
+
if current_app.url_map.is_endpoint_expecting(endpoint, "lang_code"):
|
|
158
|
+
values.setdefault("lang_code", g.get("lang_code") or get_locale())
|
|
152
159
|
except KeyError: # Endpoint does not exist
|
|
153
160
|
pass
|
|
154
161
|
|
|
155
162
|
|
|
156
163
|
def _pull_lang_code(endpoint, values):
|
|
157
|
-
lang_code = values.pop(
|
|
158
|
-
if lang_code not in current_app.config[
|
|
159
|
-
abort(redirect(
|
|
160
|
-
url_for(endpoint, lang_code=default_lang, **values)))
|
|
164
|
+
lang_code = values.pop("lang_code", g.get("lang_code") or get_locale())
|
|
165
|
+
if lang_code not in current_app.config["LANGUAGES"]:
|
|
166
|
+
abort(redirect(url_for(endpoint, lang_code=default_lang, **values)))
|
|
161
167
|
g.lang_code = lang_code
|
|
162
168
|
|
|
163
169
|
|
|
164
170
|
def redirect_to_lang(*args, **kwargs):
|
|
165
|
-
|
|
166
|
-
endpoint = request.endpoint.replace(
|
|
171
|
+
"""Redirect non lang-prefixed urls to default language."""
|
|
172
|
+
endpoint = request.endpoint.replace("_redirect", "")
|
|
167
173
|
kwargs = multi_to_dict(request.args)
|
|
168
174
|
kwargs.update(request.view_args)
|
|
169
|
-
kwargs[
|
|
175
|
+
kwargs["lang_code"] = default_lang
|
|
170
176
|
return redirect(url_for(endpoint, **kwargs))
|
|
171
177
|
|
|
172
178
|
|
|
173
179
|
def redirect_to_unlocalized(*args, **kwargs):
|
|
174
|
-
|
|
175
|
-
endpoint = request.endpoint.replace(
|
|
180
|
+
"""Redirect lang-prefixed urls to no prefixed URL."""
|
|
181
|
+
endpoint = request.endpoint.replace("_redirect", "")
|
|
176
182
|
kwargs = multi_to_dict(request.args)
|
|
177
183
|
kwargs.update(request.view_args)
|
|
178
|
-
kwargs.pop(
|
|
184
|
+
kwargs.pop("lang_code", None)
|
|
179
185
|
return redirect(url_for(endpoint, **kwargs))
|
|
180
186
|
|
|
181
187
|
|
|
@@ -187,35 +193,51 @@ class I18nBlueprintSetupState(BlueprintSetupState):
|
|
|
187
193
|
The URL rule is registered twice.
|
|
188
194
|
"""
|
|
189
195
|
# Static assets are not localized
|
|
190
|
-
if endpoint ==
|
|
196
|
+
if endpoint == "static":
|
|
191
197
|
return super(I18nBlueprintSetupState, self).add_url_rule(
|
|
192
|
-
rule, endpoint=endpoint, view_func=view_func, **options
|
|
198
|
+
rule, endpoint=endpoint, view_func=view_func, **options
|
|
199
|
+
)
|
|
193
200
|
if self.url_prefix:
|
|
194
201
|
rule = self.url_prefix + rule
|
|
195
|
-
options.setdefault(
|
|
202
|
+
options.setdefault("subdomain", self.subdomain)
|
|
196
203
|
if endpoint is None:
|
|
197
204
|
endpoint = _endpoint_from_view_func(view_func)
|
|
198
205
|
defaults = self.url_defaults
|
|
199
|
-
if
|
|
200
|
-
defaults = dict(defaults, **options.pop(
|
|
206
|
+
if "defaults" in options:
|
|
207
|
+
defaults = dict(defaults, **options.pop("defaults"))
|
|
201
208
|
|
|
202
|
-
if options.pop(
|
|
203
|
-
self.app.add_url_rule(
|
|
204
|
-
|
|
205
|
-
|
|
209
|
+
if options.pop("localize", True):
|
|
210
|
+
self.app.add_url_rule(
|
|
211
|
+
"/<lang:lang_code>" + rule,
|
|
212
|
+
"%s.%s" % (self.blueprint.name, endpoint),
|
|
213
|
+
view_func,
|
|
214
|
+
defaults=defaults,
|
|
215
|
+
**options,
|
|
216
|
+
)
|
|
206
217
|
|
|
207
218
|
self.app.add_url_rule(
|
|
208
|
-
rule,
|
|
209
|
-
|
|
219
|
+
rule,
|
|
220
|
+
"%s.%s_redirect" % (self.blueprint.name, endpoint),
|
|
221
|
+
redirect_to_lang,
|
|
222
|
+
defaults=defaults,
|
|
223
|
+
**options,
|
|
224
|
+
)
|
|
210
225
|
else:
|
|
211
|
-
self.app.add_url_rule(
|
|
212
|
-
|
|
213
|
-
|
|
226
|
+
self.app.add_url_rule(
|
|
227
|
+
rule,
|
|
228
|
+
"%s.%s" % (self.blueprint.name, endpoint),
|
|
229
|
+
view_func,
|
|
230
|
+
defaults=defaults,
|
|
231
|
+
**options,
|
|
232
|
+
)
|
|
214
233
|
|
|
215
234
|
self.app.add_url_rule(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
redirect_to_unlocalized,
|
|
235
|
+
"/<lang:lang_code>" + rule,
|
|
236
|
+
"%s.%s_redirect" % (self.blueprint.name, endpoint),
|
|
237
|
+
redirect_to_unlocalized,
|
|
238
|
+
defaults=defaults,
|
|
239
|
+
**options,
|
|
240
|
+
)
|
|
219
241
|
|
|
220
242
|
|
|
221
243
|
class I18nBlueprint(Blueprint):
|
|
@@ -229,17 +251,154 @@ class I18nBlueprint(Blueprint):
|
|
|
229
251
|
|
|
230
252
|
|
|
231
253
|
ISO_639_1_CODES = (
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
254
|
+
"aa",
|
|
255
|
+
"ab",
|
|
256
|
+
"af",
|
|
257
|
+
"am",
|
|
258
|
+
"an",
|
|
259
|
+
"ar",
|
|
260
|
+
"as",
|
|
261
|
+
"ay",
|
|
262
|
+
"az",
|
|
263
|
+
"ba",
|
|
264
|
+
"be",
|
|
265
|
+
"bg",
|
|
266
|
+
"bh",
|
|
267
|
+
"bi",
|
|
268
|
+
"bn",
|
|
269
|
+
"bo",
|
|
270
|
+
"br",
|
|
271
|
+
"ca",
|
|
272
|
+
"co",
|
|
273
|
+
"cs",
|
|
274
|
+
"cy",
|
|
275
|
+
"da",
|
|
276
|
+
"de",
|
|
277
|
+
"dz",
|
|
278
|
+
"el",
|
|
279
|
+
"en",
|
|
280
|
+
"eo",
|
|
281
|
+
"es",
|
|
282
|
+
"et",
|
|
283
|
+
"eu",
|
|
284
|
+
"fa",
|
|
285
|
+
"fi",
|
|
286
|
+
"fj",
|
|
287
|
+
"fo",
|
|
288
|
+
"fr",
|
|
289
|
+
"fy",
|
|
290
|
+
"ga",
|
|
291
|
+
"gd",
|
|
292
|
+
"gl",
|
|
293
|
+
"gn",
|
|
294
|
+
"gu",
|
|
295
|
+
"gv",
|
|
296
|
+
"ha",
|
|
297
|
+
"he",
|
|
298
|
+
"hi",
|
|
299
|
+
"hr",
|
|
300
|
+
"ht",
|
|
301
|
+
"hu",
|
|
302
|
+
"hy",
|
|
303
|
+
"ia",
|
|
304
|
+
"id",
|
|
305
|
+
"ie",
|
|
306
|
+
"ii",
|
|
307
|
+
"ik",
|
|
308
|
+
"in",
|
|
309
|
+
"io",
|
|
310
|
+
"is",
|
|
311
|
+
"it",
|
|
312
|
+
"iu",
|
|
313
|
+
"iw",
|
|
314
|
+
"ja",
|
|
315
|
+
"ji",
|
|
316
|
+
"jv",
|
|
317
|
+
"ka",
|
|
318
|
+
"kk",
|
|
319
|
+
"kl",
|
|
320
|
+
"km",
|
|
321
|
+
"kn",
|
|
322
|
+
"ko",
|
|
323
|
+
"ks",
|
|
324
|
+
"ku",
|
|
325
|
+
"ky",
|
|
326
|
+
"la",
|
|
327
|
+
"li",
|
|
328
|
+
"ln",
|
|
329
|
+
"lo",
|
|
330
|
+
"lt",
|
|
331
|
+
"lv",
|
|
332
|
+
"mg",
|
|
333
|
+
"mi",
|
|
334
|
+
"mk",
|
|
335
|
+
"ml",
|
|
336
|
+
"mn",
|
|
337
|
+
"mo",
|
|
338
|
+
"mr",
|
|
339
|
+
"ms",
|
|
340
|
+
"mt",
|
|
341
|
+
"my",
|
|
342
|
+
"na",
|
|
343
|
+
"ne",
|
|
344
|
+
"nl",
|
|
345
|
+
"no",
|
|
346
|
+
"oc",
|
|
347
|
+
"om",
|
|
348
|
+
"or",
|
|
349
|
+
"pa",
|
|
350
|
+
"pl",
|
|
351
|
+
"ps",
|
|
352
|
+
"pt",
|
|
353
|
+
"qu",
|
|
354
|
+
"rm",
|
|
355
|
+
"rn",
|
|
356
|
+
"ro",
|
|
357
|
+
"ru",
|
|
358
|
+
"rw",
|
|
359
|
+
"sa",
|
|
360
|
+
"sd",
|
|
361
|
+
"sg",
|
|
362
|
+
"sh",
|
|
363
|
+
"si",
|
|
364
|
+
"sk",
|
|
365
|
+
"sl",
|
|
366
|
+
"sm",
|
|
367
|
+
"sn",
|
|
368
|
+
"so",
|
|
369
|
+
"sq",
|
|
370
|
+
"sr",
|
|
371
|
+
"ss",
|
|
372
|
+
"st",
|
|
373
|
+
"su",
|
|
374
|
+
"sv",
|
|
375
|
+
"sw",
|
|
376
|
+
"ta",
|
|
377
|
+
"te",
|
|
378
|
+
"tg",
|
|
379
|
+
"th",
|
|
380
|
+
"ti",
|
|
381
|
+
"tk",
|
|
382
|
+
"tl",
|
|
383
|
+
"tn",
|
|
384
|
+
"to",
|
|
385
|
+
"tr",
|
|
386
|
+
"ts",
|
|
387
|
+
"tt",
|
|
388
|
+
"tw",
|
|
389
|
+
"ug",
|
|
390
|
+
"uk",
|
|
391
|
+
"ur",
|
|
392
|
+
"uz",
|
|
393
|
+
"vi",
|
|
394
|
+
"vo",
|
|
395
|
+
"wa",
|
|
396
|
+
"wo",
|
|
397
|
+
"xh",
|
|
398
|
+
"yi",
|
|
399
|
+
"yo",
|
|
400
|
+
"zh",
|
|
401
|
+
"zh-Hans",
|
|
402
|
+
"zh-Hant",
|
|
403
|
+
"zu",
|
|
245
404
|
)
|
udata/linkchecker/backends.py
CHANGED
|
@@ -8,30 +8,24 @@ from udata.entrypoints import get_enabled
|
|
|
8
8
|
log = logging.getLogger(__name__)
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
ENTRYPOINT =
|
|
11
|
+
ENTRYPOINT = "udata.linkcheckers"
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class NoCheckLinkchecker(object):
|
|
15
15
|
"""Dummy linkchecker for resources that need no check"""
|
|
16
16
|
|
|
17
17
|
def check(self, _):
|
|
18
|
-
return {
|
|
19
|
-
'check:status': 204,
|
|
20
|
-
'check:available': True,
|
|
21
|
-
'check:date': datetime.utcnow()
|
|
22
|
-
}
|
|
18
|
+
return {"check:status": 204, "check:available": True, "check:date": datetime.utcnow()}
|
|
23
19
|
|
|
24
20
|
|
|
25
21
|
def get(name):
|
|
26
|
-
|
|
22
|
+
"""Get a linkchecker given its name or fallback on default"""
|
|
27
23
|
linkcheckers = get_enabled(ENTRYPOINT, current_app)
|
|
28
24
|
linkcheckers.update(no_check=NoCheckLinkchecker) # no_check always enabled
|
|
29
25
|
selected_linkchecker = linkcheckers.get(name)
|
|
30
26
|
if not selected_linkchecker:
|
|
31
|
-
default_linkchecker = current_app.config.get(
|
|
32
|
-
'LINKCHECKING_DEFAULT_LINKCHECKER')
|
|
27
|
+
default_linkchecker = current_app.config.get("LINKCHECKING_DEFAULT_LINKCHECKER")
|
|
33
28
|
selected_linkchecker = linkcheckers.get(default_linkchecker)
|
|
34
29
|
if not selected_linkchecker:
|
|
35
|
-
log.error(
|
|
36
|
-
name))
|
|
30
|
+
log.error("No linkchecker found ({} requested and no fallback)".format(name))
|
|
37
31
|
return selected_linkchecker
|