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
udata/core/reuse/api_fields.py
CHANGED
|
@@ -1,103 +1,138 @@
|
|
|
1
|
-
from udata.api import api,
|
|
2
|
-
|
|
1
|
+
from udata.api import api, base_reference, fields
|
|
3
2
|
from udata.core.badges.fields import badge_fields
|
|
4
3
|
from udata.core.dataset.api_fields import dataset_fields
|
|
5
4
|
from udata.core.organization.api_fields import org_ref_fields
|
|
6
5
|
from udata.core.user.api_fields import user_ref_fields
|
|
7
6
|
|
|
8
|
-
from .constants import REUSE_TOPICS, REUSE_TYPES
|
|
7
|
+
from .constants import IMAGE_SIZES, REUSE_TOPICS, REUSE_TYPES
|
|
9
8
|
|
|
10
9
|
BIGGEST_IMAGE_SIZE = IMAGE_SIZES[0]
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
reuse_fields = api.model(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
description=
|
|
18
|
-
|
|
19
|
-
description=
|
|
20
|
-
|
|
21
|
-
description
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
fields.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
description=
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
fields.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
12
|
+
reuse_fields = api.model(
|
|
13
|
+
"Reuse",
|
|
14
|
+
{
|
|
15
|
+
"id": fields.String(description="The reuse identifier", readonly=True),
|
|
16
|
+
"title": fields.String(description="The reuse title", required=True),
|
|
17
|
+
"slug": fields.String(description="The reuse permalink string", readonly=True),
|
|
18
|
+
"type": fields.String(description="The reuse type", required=True, enum=list(REUSE_TYPES)),
|
|
19
|
+
"url": fields.String(description="The reuse remote URL (website)", required=True),
|
|
20
|
+
"description": fields.Markdown(
|
|
21
|
+
description="The reuse description in Markdown", required=True
|
|
22
|
+
),
|
|
23
|
+
"tags": fields.List(fields.String, description="Some keywords to help in search"),
|
|
24
|
+
"badges": fields.List(
|
|
25
|
+
fields.Nested(badge_fields), description="The reuse badges", readonly=True
|
|
26
|
+
),
|
|
27
|
+
"topic": fields.String(
|
|
28
|
+
description="The reuse topic", required=True, enum=list(REUSE_TOPICS)
|
|
29
|
+
),
|
|
30
|
+
"featured": fields.Boolean(description="Is the reuse featured", readonly=True),
|
|
31
|
+
"private": fields.Boolean(
|
|
32
|
+
description="Is the reuse private to the owner or the organization"
|
|
33
|
+
),
|
|
34
|
+
"image": fields.ImageField(description="The reuse thumbnail thumbnail (cropped) URL"),
|
|
35
|
+
"image_thumbnail": fields.ImageField(
|
|
36
|
+
attribute="image",
|
|
37
|
+
size=BIGGEST_IMAGE_SIZE,
|
|
38
|
+
description="The reuse thumbnail thumbnail URL. This is the square "
|
|
39
|
+
"({0}x{0}) and cropped version.".format(BIGGEST_IMAGE_SIZE),
|
|
40
|
+
),
|
|
41
|
+
"created_at": fields.ISODateTime(description="The reuse creation date", readonly=True),
|
|
42
|
+
"last_modified": fields.ISODateTime(
|
|
43
|
+
description="The reuse last modification date", readonly=True
|
|
44
|
+
),
|
|
45
|
+
"deleted": fields.ISODateTime(description="The deletion date if deleted", readonly=True),
|
|
46
|
+
"datasets": fields.List(fields.Nested(dataset_fields), description="The reused datasets"),
|
|
47
|
+
"organization": fields.Nested(
|
|
48
|
+
org_ref_fields,
|
|
49
|
+
allow_null=True,
|
|
50
|
+
description="The publishing organization",
|
|
51
|
+
readonly=True,
|
|
52
|
+
),
|
|
53
|
+
"owner": fields.Nested(
|
|
54
|
+
user_ref_fields, description="The owner user", readonly=True, allow_null=True
|
|
55
|
+
),
|
|
56
|
+
"metrics": fields.Raw(
|
|
57
|
+
attribute=lambda o: o.get_metrics(), description="The reuse metrics", readonly=True
|
|
58
|
+
),
|
|
59
|
+
"uri": fields.UrlFor(
|
|
60
|
+
"api.reuse", lambda o: {"reuse": o}, description="The reuse API URI", readonly=True
|
|
61
|
+
),
|
|
62
|
+
"page": fields.UrlFor(
|
|
63
|
+
"reuses.show",
|
|
64
|
+
lambda o: {"reuse": o},
|
|
65
|
+
description="The reuse page URL",
|
|
66
|
+
readonly=True,
|
|
67
|
+
fallback_endpoint="api.reuse",
|
|
68
|
+
),
|
|
69
|
+
"extras": fields.Raw(description="Extras attributes as key-value pairs"),
|
|
70
|
+
},
|
|
71
|
+
mask="*,datasets{title,uri,page}",
|
|
72
|
+
)
|
|
63
73
|
|
|
64
|
-
reuse_page_fields = api.model(
|
|
74
|
+
reuse_page_fields = api.model("ReusePage", fields.pager(reuse_fields))
|
|
65
75
|
|
|
66
76
|
|
|
67
|
-
reuse_ref_fields = api.inherit(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
description=
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
reuse_ref_fields = api.inherit(
|
|
78
|
+
"ReuseReference",
|
|
79
|
+
base_reference,
|
|
80
|
+
{
|
|
81
|
+
"title": fields.String(description="The reuse title", readonly=True),
|
|
82
|
+
"image": fields.ImageField(description="The reuse thumbnail thumbnail (cropped) URL"),
|
|
83
|
+
"image_thumbnail": fields.ImageField(
|
|
84
|
+
attribute="image",
|
|
85
|
+
size=BIGGEST_IMAGE_SIZE,
|
|
86
|
+
description="The reuse thumbnail thumbnail URL. This is the square "
|
|
87
|
+
"({0}x{0}) and cropped version.".format(BIGGEST_IMAGE_SIZE),
|
|
88
|
+
),
|
|
89
|
+
"uri": fields.UrlFor(
|
|
90
|
+
"api.reuse", lambda o: {"reuse": o}, description="The reuse API URI", readonly=True
|
|
91
|
+
),
|
|
92
|
+
"page": fields.UrlFor(
|
|
93
|
+
"reuses.show",
|
|
94
|
+
lambda o: {"reuse": o},
|
|
95
|
+
description="The reuse page URL",
|
|
96
|
+
readonly=True,
|
|
97
|
+
fallback_endpoint="api.reuse",
|
|
98
|
+
),
|
|
99
|
+
},
|
|
100
|
+
)
|
|
80
101
|
|
|
81
102
|
|
|
82
|
-
reuse_type_fields = api.model(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
103
|
+
reuse_type_fields = api.model(
|
|
104
|
+
"ReuseType",
|
|
105
|
+
{
|
|
106
|
+
"id": fields.String(description="The reuse type identifier"),
|
|
107
|
+
"label": fields.String(description="The reuse type display name"),
|
|
108
|
+
},
|
|
109
|
+
)
|
|
86
110
|
|
|
87
111
|
|
|
88
|
-
reuse_suggestion_fields = api.model(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
description=
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
112
|
+
reuse_suggestion_fields = api.model(
|
|
113
|
+
"ReuseSuggestion",
|
|
114
|
+
{
|
|
115
|
+
"id": fields.String(description="The reuse identifier", readonly=True),
|
|
116
|
+
"title": fields.String(description="The reuse title", readonly=True),
|
|
117
|
+
"slug": fields.String(description="The reuse permalink string", readonly=True),
|
|
118
|
+
"image_url": fields.ImageField(
|
|
119
|
+
size=BIGGEST_IMAGE_SIZE, description="The reuse thumbnail URL", readonly=True
|
|
120
|
+
),
|
|
121
|
+
"page": fields.UrlFor(
|
|
122
|
+
"reuses.show_redirect",
|
|
123
|
+
lambda o: {"reuse": o["slug"]},
|
|
124
|
+
description="The reuse page URL",
|
|
125
|
+
readonly=True,
|
|
126
|
+
fallback_endpoint="api.reuse",
|
|
127
|
+
),
|
|
128
|
+
},
|
|
129
|
+
)
|
|
98
130
|
|
|
99
131
|
|
|
100
|
-
reuse_topic_fields = api.model(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
132
|
+
reuse_topic_fields = api.model(
|
|
133
|
+
"ReuseTopic",
|
|
134
|
+
{
|
|
135
|
+
"id": fields.String(description="The reuse topic identifier"),
|
|
136
|
+
"label": fields.String(description="The reuse topic display name"),
|
|
137
|
+
},
|
|
138
|
+
)
|
udata/core/reuse/apiv2.py
CHANGED
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
from flask import request
|
|
2
2
|
|
|
3
3
|
from udata import search
|
|
4
|
-
from udata.api import
|
|
4
|
+
from udata.api import API, apiv2
|
|
5
5
|
from udata.utils import multi_to_dict
|
|
6
6
|
|
|
7
|
-
from .api_fields import
|
|
7
|
+
from .api_fields import reuse_fields, reuse_page_fields
|
|
8
8
|
from .search import ReuseSearch
|
|
9
9
|
|
|
10
|
-
apiv2.inherit(
|
|
11
|
-
apiv2.inherit(
|
|
10
|
+
apiv2.inherit("ReusePage", reuse_page_fields)
|
|
11
|
+
apiv2.inherit("Reuse", reuse_fields)
|
|
12
12
|
|
|
13
|
-
ns = apiv2.namespace(
|
|
13
|
+
ns = apiv2.namespace("reuses", "Reuse related operations")
|
|
14
14
|
|
|
15
15
|
search_parser = ReuseSearch.as_request_parser()
|
|
16
16
|
|
|
17
|
-
DEFAULT_SORTING =
|
|
17
|
+
DEFAULT_SORTING = "-created_at"
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
@ns.route(
|
|
20
|
+
@ns.route("/search/", endpoint="reuse_search")
|
|
21
21
|
class ReuseSearchAPI(API):
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
"""Reuses collection search endpoint"""
|
|
23
|
+
|
|
24
|
+
@apiv2.doc("search_reuses")
|
|
24
25
|
@apiv2.expect(search_parser)
|
|
25
26
|
@apiv2.marshal_with(reuse_page_fields)
|
|
26
27
|
def get(self):
|
|
27
|
-
|
|
28
|
+
"""Search all reuses"""
|
|
28
29
|
search_parser.parse_args()
|
|
29
30
|
return search.query(ReuseSearch, **multi_to_dict(request.args))
|
udata/core/reuse/constants.py
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
from udata.i18n import lazy_gettext as _
|
|
2
2
|
|
|
3
3
|
REUSE_TYPES = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
"api": _("API"),
|
|
5
|
+
"application": _("Application"),
|
|
6
|
+
"idea": _("Idea"),
|
|
7
|
+
"news_article": _("News Article"),
|
|
8
|
+
"paper": _("Paper"),
|
|
9
|
+
"post": _("Post"),
|
|
10
|
+
"visualization": _("Visualization"),
|
|
11
|
+
"hardware": _("Connected device"),
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
REUSE_TOPICS = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
15
|
+
"health": _("Health"),
|
|
16
|
+
"transport_and_mobility": _("Transport and mobility"),
|
|
17
|
+
"housing_and_development": _("Housing and development"),
|
|
18
|
+
"food_and_agriculture": _("Food and agriculture"),
|
|
19
|
+
"culture_and_recreation": _("Culture and recreation"),
|
|
20
|
+
"economy_and_business": _("Economy and business"),
|
|
21
|
+
"environment_and_energy": _("Environment and energy"),
|
|
22
|
+
"work_and_training": _("Work and training"),
|
|
23
|
+
"politics_and_public_life": _("Politics and public life"),
|
|
24
|
+
"safety_and_security": _("Safety and security"),
|
|
25
|
+
"education_and_research": _("Education and research"),
|
|
26
|
+
"society_and_demography": _("Society and demography"),
|
|
27
|
+
"law_and_justice": _("Law and justice"),
|
|
28
|
+
"open_data_tools": _("Open data tools"),
|
|
29
|
+
"others": _("Others"),
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
|
udata/core/reuse/csv.py
CHANGED
|
@@ -6,24 +6,24 @@ from .models import Reuse
|
|
|
6
6
|
@csv.adapter(Reuse)
|
|
7
7
|
class ReuseCsvAdapter(csv.Adapter):
|
|
8
8
|
fields = (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
(
|
|
16
|
-
(
|
|
17
|
-
(
|
|
18
|
-
(
|
|
19
|
-
(
|
|
20
|
-
(
|
|
21
|
-
(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
(
|
|
26
|
-
(
|
|
9
|
+
"id",
|
|
10
|
+
"title",
|
|
11
|
+
"slug",
|
|
12
|
+
("url", "external_url"),
|
|
13
|
+
"type",
|
|
14
|
+
"description",
|
|
15
|
+
("remote_url", "url"),
|
|
16
|
+
("organization", "organization.name"),
|
|
17
|
+
("organization_id", "organization.id"),
|
|
18
|
+
("owner", "owner.slug"), # in case it's owned by a user
|
|
19
|
+
("owner_id", "owner.id"),
|
|
20
|
+
("image", lambda r: r.image(external=True)),
|
|
21
|
+
("featured", lambda r: r.featured or False),
|
|
22
|
+
"created_at",
|
|
23
|
+
"last_modified",
|
|
24
|
+
"topic",
|
|
25
|
+
("tags", lambda r: ",".join(r.tags)),
|
|
26
|
+
("datasets", lambda r: ",".join([str(d.id) for d in r.datasets])),
|
|
27
27
|
)
|
|
28
28
|
|
|
29
29
|
def dynamic_fields(self):
|
udata/core/reuse/factories.py
CHANGED
|
@@ -1,30 +1,26 @@
|
|
|
1
1
|
import factory
|
|
2
|
-
|
|
3
2
|
from factory.fuzzy import FuzzyChoice
|
|
4
3
|
|
|
5
4
|
from udata.core.dataset.factories import DatasetFactory
|
|
6
5
|
from udata.factories import ModelFactory
|
|
7
6
|
from udata.utils import faker
|
|
8
7
|
|
|
8
|
+
from .constants import REUSE_TOPICS, REUSE_TYPES
|
|
9
9
|
from .models import Reuse
|
|
10
|
-
from .constants import REUSE_TYPES, REUSE_TOPICS
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
class ReuseFactory(ModelFactory):
|
|
14
13
|
class Meta:
|
|
15
14
|
model = Reuse
|
|
16
15
|
|
|
17
|
-
title = factory.Faker(
|
|
18
|
-
description = factory.Faker(
|
|
19
|
-
url = factory.LazyAttribute(
|
|
20
|
-
lambda o: '/'.join([faker.url(), faker.unique_string()]))
|
|
16
|
+
title = factory.Faker("sentence")
|
|
17
|
+
description = factory.Faker("text")
|
|
18
|
+
url = factory.LazyAttribute(lambda o: "/".join([faker.url(), faker.unique_string()]))
|
|
21
19
|
type = FuzzyChoice(REUSE_TYPES.keys())
|
|
22
20
|
topic = FuzzyChoice(REUSE_TOPICS.keys())
|
|
23
21
|
|
|
24
22
|
class Params:
|
|
25
|
-
visible = factory.Trait(
|
|
26
|
-
datasets=factory.LazyAttribute(lambda o: [DatasetFactory()])
|
|
27
|
-
)
|
|
23
|
+
visible = factory.Trait(datasets=factory.LazyAttribute(lambda o: [DatasetFactory()]))
|
|
28
24
|
|
|
29
25
|
|
|
30
26
|
class VisibleReuseFactory(ReuseFactory):
|
udata/core/reuse/forms.py
CHANGED
|
@@ -1,41 +1,44 @@
|
|
|
1
|
+
from udata.core.reuse.constants import REUSE_TOPICS, REUSE_TYPES
|
|
1
2
|
from udata.forms import ModelForm, fields, validators
|
|
2
3
|
from udata.i18n import lazy_gettext as _
|
|
3
4
|
from udata.models import Reuse
|
|
4
|
-
from udata.core.reuse.constants import REUSE_TYPES, REUSE_TOPICS
|
|
5
5
|
|
|
6
|
-
from .constants import IMAGE_SIZES, TITLE_SIZE_LIMIT
|
|
6
|
+
from .constants import DESCRIPTION_SIZE_LIMIT, IMAGE_SIZES, TITLE_SIZE_LIMIT
|
|
7
7
|
|
|
8
|
-
__all__ = (
|
|
8
|
+
__all__ = ("ReuseForm",)
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def check_url_does_not_exists(form, field):
|
|
12
|
-
|
|
12
|
+
"""Ensure a reuse URL is not yet registered"""
|
|
13
13
|
if field.data != field.object_data and Reuse.url_exists(field.data):
|
|
14
|
-
raise validators.ValidationError(_(
|
|
14
|
+
raise validators.ValidationError(_("This URL is already registered"))
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class ReuseForm(ModelForm):
|
|
18
18
|
model_class = Reuse
|
|
19
19
|
|
|
20
|
-
title = fields.StringField(
|
|
20
|
+
title = fields.StringField(
|
|
21
|
+
_("Title"), [validators.DataRequired(), validators.Length(max=TITLE_SIZE_LIMIT)]
|
|
22
|
+
)
|
|
21
23
|
description = fields.MarkdownField(
|
|
22
|
-
_(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
_("Description"),
|
|
25
|
+
[validators.DataRequired(), validators.Length(max=DESCRIPTION_SIZE_LIMIT)],
|
|
26
|
+
description=_(
|
|
27
|
+
"The details about the reuse (build process, specifics, " "self-critics...)."
|
|
28
|
+
),
|
|
29
|
+
)
|
|
30
|
+
type = fields.SelectField(_("Type"), choices=list(REUSE_TYPES.items()))
|
|
31
|
+
url = fields.URLField(_("URL"), [validators.DataRequired(), check_url_does_not_exists])
|
|
32
|
+
image = fields.ImageField(_("Image"), sizes=IMAGE_SIZES, placeholder="reuse")
|
|
33
|
+
tags = fields.TagField(_("Tags"), description=_("Some taxonomy keywords"))
|
|
34
|
+
datasets = fields.DatasetListField(_("Used datasets"))
|
|
32
35
|
private = fields.BooleanField(
|
|
33
|
-
_(
|
|
34
|
-
description=_(
|
|
35
|
-
|
|
36
|
-
topic = fields.SelectField(_(
|
|
36
|
+
_("Private"),
|
|
37
|
+
description=_("Restrict the dataset visibility to you or " "your organization only."),
|
|
38
|
+
)
|
|
39
|
+
topic = fields.SelectField(_("Topic"), choices=list(REUSE_TOPICS.items()))
|
|
37
40
|
|
|
38
41
|
owner = fields.CurrentUserField()
|
|
39
|
-
organization = fields.PublishAsField(_(
|
|
42
|
+
organization = fields.PublishAsField(_("Publish as"))
|
|
40
43
|
deleted = fields.DateTimeField()
|
|
41
44
|
extras = fields.ExtrasField()
|