invenio-vocabularies 9.1.2__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.
- invenio_vocabularies/__init__.py +16 -0
- invenio_vocabularies/administration/__init__.py +10 -0
- invenio_vocabularies/administration/views/__init__.py +10 -0
- invenio_vocabularies/administration/views/vocabularies.py +43 -0
- invenio_vocabularies/alembic/17c703ce1eb7_create_names_table.py +54 -0
- invenio_vocabularies/alembic/3ba812d80559_add_internal_name_id.py +36 -0
- invenio_vocabularies/alembic/4a9a4fd235f8_create_vocabulary_schemes.py +37 -0
- invenio_vocabularies/alembic/4f365fced43f_create_vocabularies_tables.py +92 -0
- invenio_vocabularies/alembic/55a700f897b6_add_names_and_afiliations_pid_column.py +96 -0
- invenio_vocabularies/alembic/6312f33645c1_create_affiliations_table.py +54 -0
- invenio_vocabularies/alembic/676dd587542d_create_funders_vocabulary_table.py +58 -0
- invenio_vocabularies/alembic/8ff82dfb0be8_create_vocabularies_branch.py +28 -0
- invenio_vocabularies/alembic/__init__.py +9 -0
- invenio_vocabularies/alembic/af2457652217_drop_unique_constraint_from_internal_id.py +37 -0
- invenio_vocabularies/alembic/e1146238edd3_create_awards_table.py +56 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/.eslintrc.yml +11 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/.prettierrc +1 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/index.js +7 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/package.json +25 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/AwardResults.js +95 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/CustomAwardForm.js +139 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/FunderDropdown.js +87 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/FundingField.js +244 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/FundingField.test.js +1 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/FundingFieldItem.js +152 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/FundingModal.js +246 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/NoAwardResults.js +37 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/index.js +8 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/index.js +7 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/index.js +7 -0
- invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/index.js +7 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/i18next.js +36 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/_generatedTranslations.js +66 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ar/messages.po +96 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ar/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/bg/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/bg/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ca/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ca/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/cs/messages.po +97 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/cs/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/da/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/da/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/de/messages.po +98 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/de/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/el/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/el/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/en/messages.po +88 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/en/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/es/messages.po +96 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/es/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/et/messages.po +95 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/et/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/fa/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/fa/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/fr/messages.po +96 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/fr/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/hr/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/hr/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/hu/messages.po +96 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/hu/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/index.js +24 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/it/messages.po +96 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/it/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ja/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ja/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ka/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ka/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ko/messages.po +90 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ko/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/lt/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/lt/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/no/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/no/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/pl/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/pl/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/pt/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/pt/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ro/messages.po +95 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ro/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ru/messages.po +95 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ru/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/sk/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/sk/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/sv/messages.po +98 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/sv/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/tr/messages.po +96 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/tr/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/uk/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/uk/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/zh_CN/messages.po +96 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/zh_CN/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/zh_TW/messages.po +94 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/zh_TW/translations.json +28 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/package.json +19 -0
- invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/translations.pot +88 -0
- invenio_vocabularies/cli.py +175 -0
- invenio_vocabularies/config.py +231 -0
- invenio_vocabularies/contrib/__init__.py +9 -0
- invenio_vocabularies/contrib/affiliations/__init__.py +20 -0
- invenio_vocabularies/contrib/affiliations/affiliations.py +61 -0
- invenio_vocabularies/contrib/affiliations/api.py +13 -0
- invenio_vocabularies/contrib/affiliations/config.py +79 -0
- invenio_vocabularies/contrib/affiliations/datastreams.py +301 -0
- invenio_vocabularies/contrib/affiliations/facets.py +36 -0
- invenio_vocabularies/contrib/affiliations/jsonschemas/__init__.py +9 -0
- invenio_vocabularies/contrib/affiliations/jsonschemas/affiliations/affiliation-v1.0.0.json +63 -0
- invenio_vocabularies/contrib/affiliations/mappings/__init__.py +10 -0
- invenio_vocabularies/contrib/affiliations/mappings/os-v1/__init__.py +9 -0
- invenio_vocabularies/contrib/affiliations/mappings/os-v1/affiliations/affiliation-v1.0.0.json +112 -0
- invenio_vocabularies/contrib/affiliations/mappings/os-v1/affiliations/affiliation-v2.0.0.json +171 -0
- invenio_vocabularies/contrib/affiliations/mappings/os-v2/__init__.py +9 -0
- invenio_vocabularies/contrib/affiliations/mappings/os-v2/affiliations/affiliation-v1.0.0.json +112 -0
- invenio_vocabularies/contrib/affiliations/mappings/os-v2/affiliations/affiliation-v2.0.0.json +171 -0
- invenio_vocabularies/contrib/affiliations/mappings/v7/__init__.py +9 -0
- invenio_vocabularies/contrib/affiliations/mappings/v7/affiliations/affiliation-v1.0.0.json +112 -0
- invenio_vocabularies/contrib/affiliations/models.py +13 -0
- invenio_vocabularies/contrib/affiliations/resources.py +16 -0
- invenio_vocabularies/contrib/affiliations/schema.py +71 -0
- invenio_vocabularies/contrib/affiliations/services.py +15 -0
- invenio_vocabularies/contrib/awards/__init__.py +19 -0
- invenio_vocabularies/contrib/awards/api.py +13 -0
- invenio_vocabularies/contrib/awards/awards.py +96 -0
- invenio_vocabularies/contrib/awards/config.py +59 -0
- invenio_vocabularies/contrib/awards/datastreams.py +372 -0
- invenio_vocabularies/contrib/awards/jsonschemas/__init__.py +9 -0
- invenio_vocabularies/contrib/awards/jsonschemas/awards/award-v1.0.0.json +91 -0
- invenio_vocabularies/contrib/awards/mappings/__init__.py +9 -0
- invenio_vocabularies/contrib/awards/mappings/os-v1/__init__.py +9 -0
- invenio_vocabularies/contrib/awards/mappings/os-v1/awards/award-v1.0.0.json +147 -0
- invenio_vocabularies/contrib/awards/mappings/os-v2/__init__.py +9 -0
- invenio_vocabularies/contrib/awards/mappings/os-v2/awards/award-v1.0.0.json +147 -0
- invenio_vocabularies/contrib/awards/mappings/v7/__init__.py +9 -0
- invenio_vocabularies/contrib/awards/mappings/v7/awards/award-v1.0.0.json +147 -0
- invenio_vocabularies/contrib/awards/models.py +13 -0
- invenio_vocabularies/contrib/awards/resources.py +16 -0
- invenio_vocabularies/contrib/awards/schema.py +119 -0
- invenio_vocabularies/contrib/awards/serializer.py +47 -0
- invenio_vocabularies/contrib/awards/services.py +15 -0
- invenio_vocabularies/contrib/common/__init__.py +9 -0
- invenio_vocabularies/contrib/common/openaire/__init__.py +9 -0
- invenio_vocabularies/contrib/common/openaire/datastreams.py +84 -0
- invenio_vocabularies/contrib/common/ror/__init__.py +9 -0
- invenio_vocabularies/contrib/common/ror/datastreams.py +230 -0
- invenio_vocabularies/contrib/funders/__init__.py +19 -0
- invenio_vocabularies/contrib/funders/api.py +13 -0
- invenio_vocabularies/contrib/funders/config.py +78 -0
- invenio_vocabularies/contrib/funders/datastreams.py +97 -0
- invenio_vocabularies/contrib/funders/facets.py +36 -0
- invenio_vocabularies/contrib/funders/funders.py +72 -0
- invenio_vocabularies/contrib/funders/jsonschemas/__init__.py +9 -0
- invenio_vocabularies/contrib/funders/jsonschemas/funders/funder-v1.0.0.json +65 -0
- invenio_vocabularies/contrib/funders/mappings/__init__.py +9 -0
- invenio_vocabularies/contrib/funders/mappings/os-v1/__init__.py +9 -0
- invenio_vocabularies/contrib/funders/mappings/os-v1/funders/funder-v1.0.0.json +90 -0
- invenio_vocabularies/contrib/funders/mappings/os-v1/funders/funder-v2.0.0.json +156 -0
- invenio_vocabularies/contrib/funders/mappings/os-v2/__init__.py +9 -0
- invenio_vocabularies/contrib/funders/mappings/os-v2/funders/funder-v1.0.0.json +90 -0
- invenio_vocabularies/contrib/funders/mappings/os-v2/funders/funder-v2.0.0.json +156 -0
- invenio_vocabularies/contrib/funders/mappings/v7/__init__.py +9 -0
- invenio_vocabularies/contrib/funders/mappings/v7/funders/funder-v1.0.0.json +90 -0
- invenio_vocabularies/contrib/funders/models.py +13 -0
- invenio_vocabularies/contrib/funders/resources.py +16 -0
- invenio_vocabularies/contrib/funders/schema.py +88 -0
- invenio_vocabularies/contrib/funders/serializer.py +33 -0
- invenio_vocabularies/contrib/funders/services.py +15 -0
- invenio_vocabularies/contrib/names/__init__.py +19 -0
- invenio_vocabularies/contrib/names/api.py +13 -0
- invenio_vocabularies/contrib/names/components.py +24 -0
- invenio_vocabularies/contrib/names/config.py +75 -0
- invenio_vocabularies/contrib/names/datastreams.py +483 -0
- invenio_vocabularies/contrib/names/jsonschemas/__init__.py +9 -0
- invenio_vocabularies/contrib/names/jsonschemas/names/name-v1.0.0.json +68 -0
- invenio_vocabularies/contrib/names/mappings/__init__.py +9 -0
- invenio_vocabularies/contrib/names/mappings/os-v1/__init__.py +9 -0
- invenio_vocabularies/contrib/names/mappings/os-v1/names/name-v1.0.0.json +101 -0
- invenio_vocabularies/contrib/names/mappings/os-v1/names/name-v2.0.0.json +165 -0
- invenio_vocabularies/contrib/names/mappings/os-v2/__init__.py +9 -0
- invenio_vocabularies/contrib/names/mappings/os-v2/names/name-v1.0.0.json +101 -0
- invenio_vocabularies/contrib/names/mappings/os-v2/names/name-v2.0.0.json +165 -0
- invenio_vocabularies/contrib/names/mappings/v7/__init__.py +9 -0
- invenio_vocabularies/contrib/names/mappings/v7/names/name-v1.0.0.json +101 -0
- invenio_vocabularies/contrib/names/models.py +13 -0
- invenio_vocabularies/contrib/names/names.py +80 -0
- invenio_vocabularies/contrib/names/permissions.py +30 -0
- invenio_vocabularies/contrib/names/resources.py +54 -0
- invenio_vocabularies/contrib/names/s3client.py +50 -0
- invenio_vocabularies/contrib/names/schema.py +121 -0
- invenio_vocabularies/contrib/names/services.py +64 -0
- invenio_vocabularies/contrib/subjects/__init__.py +22 -0
- invenio_vocabularies/contrib/subjects/api.py +14 -0
- invenio_vocabularies/contrib/subjects/config.py +90 -0
- invenio_vocabularies/contrib/subjects/datastreams.py +63 -0
- invenio_vocabularies/contrib/subjects/euroscivoc/__init__.py +9 -0
- invenio_vocabularies/contrib/subjects/euroscivoc/datastreams.py +101 -0
- invenio_vocabularies/contrib/subjects/facets.py +23 -0
- invenio_vocabularies/contrib/subjects/gemet/__init__.py +9 -0
- invenio_vocabularies/contrib/subjects/gemet/datastreams.py +140 -0
- invenio_vocabularies/contrib/subjects/jsonschemas/__init__.py +10 -0
- invenio_vocabularies/contrib/subjects/jsonschemas/subjects/subject-v1.0.0.json +69 -0
- invenio_vocabularies/contrib/subjects/mappings/__init__.py +9 -0
- invenio_vocabularies/contrib/subjects/mappings/os-v1/__init__.py +9 -0
- invenio_vocabularies/contrib/subjects/mappings/os-v1/subjects/subject-v1.0.0.json +96 -0
- invenio_vocabularies/contrib/subjects/mappings/os-v2/__init__.py +9 -0
- invenio_vocabularies/contrib/subjects/mappings/os-v2/subjects/subject-v1.0.0.json +96 -0
- invenio_vocabularies/contrib/subjects/mappings/v7/__init__.py +9 -0
- invenio_vocabularies/contrib/subjects/mappings/v7/subjects/subject-v1.0.0.json +96 -0
- invenio_vocabularies/contrib/subjects/mesh/__init__.py +9 -0
- invenio_vocabularies/contrib/subjects/mesh/datastreams.py +48 -0
- invenio_vocabularies/contrib/subjects/models.py +14 -0
- invenio_vocabularies/contrib/subjects/nvs/__init__.py +9 -0
- invenio_vocabularies/contrib/subjects/nvs/datastreams.py +114 -0
- invenio_vocabularies/contrib/subjects/resources.py +17 -0
- invenio_vocabularies/contrib/subjects/schema.py +101 -0
- invenio_vocabularies/contrib/subjects/services.py +30 -0
- invenio_vocabularies/contrib/subjects/subjects.py +55 -0
- invenio_vocabularies/datastreams/__init__.py +18 -0
- invenio_vocabularies/datastreams/datastreams.py +239 -0
- invenio_vocabularies/datastreams/errors.py +29 -0
- invenio_vocabularies/datastreams/factories.py +86 -0
- invenio_vocabularies/datastreams/readers.py +448 -0
- invenio_vocabularies/datastreams/tasks.py +115 -0
- invenio_vocabularies/datastreams/transformers.py +130 -0
- invenio_vocabularies/datastreams/writers.py +222 -0
- invenio_vocabularies/datastreams/xml.py +34 -0
- invenio_vocabularies/ext.py +179 -0
- invenio_vocabularies/factories.py +193 -0
- invenio_vocabularies/fixtures.py +52 -0
- invenio_vocabularies/jobs.py +207 -0
- invenio_vocabularies/proxies.py +27 -0
- invenio_vocabularies/records/__init__.py +9 -0
- invenio_vocabularies/records/api.py +53 -0
- invenio_vocabularies/records/jsonschemas/__init__.py +9 -0
- invenio_vocabularies/records/jsonschemas/vocabularies/definitions-v1.0.0.json +30 -0
- invenio_vocabularies/records/jsonschemas/vocabularies/vocabulary-v1.0.0.json +55 -0
- invenio_vocabularies/records/mappings/__init__.py +9 -0
- invenio_vocabularies/records/mappings/os-v1/__init__.py +9 -0
- invenio_vocabularies/records/mappings/os-v1/vocabularies/vocabulary-v1.0.0.json +109 -0
- invenio_vocabularies/records/mappings/os-v2/__init__.py +9 -0
- invenio_vocabularies/records/mappings/os-v2/vocabularies/vocabulary-v1.0.0.json +109 -0
- invenio_vocabularies/records/mappings/v7/__init__.py +9 -0
- invenio_vocabularies/records/mappings/v7/vocabularies/vocabulary-v1.0.0.json +109 -0
- invenio_vocabularies/records/models.py +90 -0
- invenio_vocabularies/records/pidprovider.py +118 -0
- invenio_vocabularies/records/systemfields/__init__.py +16 -0
- invenio_vocabularies/records/systemfields/pid.py +125 -0
- invenio_vocabularies/records/systemfields/relations.py +51 -0
- invenio_vocabularies/resources/__init__.py +23 -0
- invenio_vocabularies/resources/config.py +105 -0
- invenio_vocabularies/resources/resource.py +156 -0
- invenio_vocabularies/resources/schema.py +21 -0
- invenio_vocabularies/resources/serializer.py +39 -0
- invenio_vocabularies/services/__init__.py +19 -0
- invenio_vocabularies/services/components.py +58 -0
- invenio_vocabularies/services/config.py +173 -0
- invenio_vocabularies/services/custom_fields/__init__.py +17 -0
- invenio_vocabularies/services/custom_fields/subject.py +82 -0
- invenio_vocabularies/services/custom_fields/vocabulary.py +96 -0
- invenio_vocabularies/services/facets.py +114 -0
- invenio_vocabularies/services/generators.py +38 -0
- invenio_vocabularies/services/permissions.py +30 -0
- invenio_vocabularies/services/querystr.py +57 -0
- invenio_vocabularies/services/results.py +110 -0
- invenio_vocabularies/services/schema.py +163 -0
- invenio_vocabularies/services/service.py +189 -0
- invenio_vocabularies/services/tasks.py +38 -0
- invenio_vocabularies/templates/semantic-ui/invenio_vocabularies/subjects.html +23 -0
- invenio_vocabularies/templates/semantic-ui/invenio_vocabularies/vocabularies-list.html +12 -0
- invenio_vocabularies/templates/semantic-ui/invenio_vocabularies/vocabulary-details.html +71 -0
- invenio_vocabularies/translations/ar/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/ar/LC_MESSAGES/messages.po +277 -0
- invenio_vocabularies/translations/bg/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/bg/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/translations/ca/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/ca/LC_MESSAGES/messages.po +276 -0
- invenio_vocabularies/translations/cs/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/cs/LC_MESSAGES/messages.po +281 -0
- invenio_vocabularies/translations/da/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/da/LC_MESSAGES/messages.po +271 -0
- invenio_vocabularies/translations/de/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/de/LC_MESSAGES/messages.po +293 -0
- invenio_vocabularies/translations/el/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/el/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/translations/es/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/es/LC_MESSAGES/messages.po +281 -0
- invenio_vocabularies/translations/et/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/et/LC_MESSAGES/messages.po +276 -0
- invenio_vocabularies/translations/fa/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/fa/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/translations/fr/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/fr/LC_MESSAGES/messages.po +279 -0
- invenio_vocabularies/translations/hr/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/hr/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/translations/hu/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/hu/LC_MESSAGES/messages.po +280 -0
- invenio_vocabularies/translations/it/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/it/LC_MESSAGES/messages.po +277 -0
- invenio_vocabularies/translations/ja/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/ja/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/translations/ka/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/ka/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/translations/ko/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/ko/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/translations/lt/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/lt/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/translations/messages.pot +270 -0
- invenio_vocabularies/translations/no/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/no/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/translations/pl/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/pl/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/translations/pt/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/pt/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/translations/ro/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/ro/LC_MESSAGES/messages.po +280 -0
- invenio_vocabularies/translations/ru/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/ru/LC_MESSAGES/messages.po +276 -0
- invenio_vocabularies/translations/sk/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/sk/LC_MESSAGES/messages.po +276 -0
- invenio_vocabularies/translations/sv/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/sv/LC_MESSAGES/messages.po +280 -0
- invenio_vocabularies/translations/tr/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/tr/LC_MESSAGES/messages.po +277 -0
- invenio_vocabularies/translations/uk/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/uk/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/translations/zh_CN/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/zh_CN/LC_MESSAGES/messages.po +276 -0
- invenio_vocabularies/translations/zh_TW/LC_MESSAGES/messages.mo +0 -0
- invenio_vocabularies/translations/zh_TW/LC_MESSAGES/messages.po +275 -0
- invenio_vocabularies/views.py +53 -0
- invenio_vocabularies/webpack.py +51 -0
- invenio_vocabularies-9.1.2.dist-info/METADATA +517 -0
- invenio_vocabularies-9.1.2.dist-info/RECORD +337 -0
- invenio_vocabularies-9.1.2.dist-info/WHEEL +6 -0
- invenio_vocabularies-9.1.2.dist-info/entry_points.txt +73 -0
- invenio_vocabularies-9.1.2.dist-info/licenses/AUTHORS.rst +13 -0
- invenio_vocabularies-9.1.2.dist-info/licenses/LICENSE +21 -0
- invenio_vocabularies-9.1.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2024 CERN.
|
|
4
|
+
#
|
|
5
|
+
# Invenio-Vocabularies is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
7
|
+
# details.
|
|
8
|
+
|
|
9
|
+
"""OpenAIRE-related Datastreams Readers/Writers/Transformers module."""
|
|
10
|
+
|
|
11
|
+
import io
|
|
12
|
+
|
|
13
|
+
import requests
|
|
14
|
+
|
|
15
|
+
from invenio_vocabularies.datastreams.errors import ReaderError
|
|
16
|
+
from invenio_vocabularies.datastreams.readers import BaseReader
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class OpenAIREHTTPReader(BaseReader):
|
|
20
|
+
"""OpenAIRE HTTP Reader returning an in-memory binary stream of the latest OpenAIRE Graph Dataset tar file of a given type."""
|
|
21
|
+
|
|
22
|
+
def __init__(self, origin=None, mode="r", tar_href=None, *args, **kwargs):
|
|
23
|
+
"""Constructor."""
|
|
24
|
+
self.tar_href = tar_href
|
|
25
|
+
super().__init__(origin, mode, *args, **kwargs)
|
|
26
|
+
|
|
27
|
+
def _iter(self, fp, *args, **kwargs):
|
|
28
|
+
raise NotImplementedError(
|
|
29
|
+
"OpenAIREHTTPReader downloads one file and therefore does not iterate through items"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
def read(self, item=None, *args, **kwargs):
|
|
33
|
+
"""Reads the latest OpenAIRE Graph Dataset tar file of a given type from Zenodo and yields an in-memory binary stream of it."""
|
|
34
|
+
if item:
|
|
35
|
+
raise NotImplementedError(
|
|
36
|
+
"OpenAIREHTTPReader does not support being chained after another reader"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
if self._origin == "full":
|
|
40
|
+
# OpenAIRE Graph Dataset
|
|
41
|
+
api_url = "https://zenodo.org/api/records/3516917"
|
|
42
|
+
elif self._origin == "diff":
|
|
43
|
+
# OpenAIRE Graph dataset: new collected projects
|
|
44
|
+
api_url = "https://zenodo.org/api/records/6419021"
|
|
45
|
+
else:
|
|
46
|
+
raise ReaderError("The --origin option should be either 'full' or 'diff'")
|
|
47
|
+
|
|
48
|
+
# Call the signposting `linkset+json` endpoint for the Concept DOI (i.e. latest version) of the OpenAIRE Graph Dataset.
|
|
49
|
+
# See: https://github.com/inveniosoftware/rfcs/blob/master/rfcs/rdm-0071-signposting.md#provide-an-applicationlinksetjson-endpoint
|
|
50
|
+
headers = {"Accept": "application/linkset+json"}
|
|
51
|
+
api_resp = requests.get(api_url, headers=headers)
|
|
52
|
+
api_resp.raise_for_status()
|
|
53
|
+
|
|
54
|
+
# Extract the Landing page Link Set Object located as the first (index 0) item.
|
|
55
|
+
landing_page_linkset = api_resp.json()["linkset"][0]
|
|
56
|
+
|
|
57
|
+
# Extract the URL of the only tar file matching `tar_href` linked to the record.
|
|
58
|
+
landing_page_matching_tar_items = [
|
|
59
|
+
item
|
|
60
|
+
for item in landing_page_linkset["item"]
|
|
61
|
+
if item["type"] == "application/x-tar"
|
|
62
|
+
and item["href"].endswith(self.tar_href)
|
|
63
|
+
]
|
|
64
|
+
if len(landing_page_matching_tar_items) != 1:
|
|
65
|
+
raise ReaderError(
|
|
66
|
+
f"Expected 1 tar item matching {self.tar_href} but got {len(landing_page_matching_tar_items)}"
|
|
67
|
+
)
|
|
68
|
+
file_url = landing_page_matching_tar_items[0]["href"]
|
|
69
|
+
|
|
70
|
+
# Download the matching tar file and fully load the response bytes content in memory.
|
|
71
|
+
# The bytes content are then wrapped by a BytesIO to be file-like object (as required by `tarfile.open`).
|
|
72
|
+
# Using directly `file_resp.raw` is not possible since `tarfile.open` requires the file-like object to be seekable.
|
|
73
|
+
file_resp = requests.get(file_url)
|
|
74
|
+
file_resp.raise_for_status()
|
|
75
|
+
yield io.BytesIO(file_resp.content)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
VOCABULARIES_DATASTREAM_READERS = {
|
|
79
|
+
"openaire-http": OpenAIREHTTPReader,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
VOCABULARIES_DATASTREAM_TRANSFORMERS = {}
|
|
83
|
+
|
|
84
|
+
VOCABULARIES_DATASTREAM_WRITERS = {}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2024-2025 CERN.
|
|
4
|
+
# Copyright (C) 2024 California Institute of Technology.
|
|
5
|
+
#
|
|
6
|
+
# Invenio-Vocabularies is free software; you can redistribute it and/or
|
|
7
|
+
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
8
|
+
# details.
|
|
9
|
+
|
|
10
|
+
"""ROR-related Datastreams Readers/Writers/Transformers module."""
|
|
11
|
+
|
|
12
|
+
import io
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
|
|
15
|
+
import requests
|
|
16
|
+
from flask import current_app
|
|
17
|
+
from idutils import normalize_ror
|
|
18
|
+
|
|
19
|
+
from invenio_vocabularies.datastreams.errors import ReaderError, TransformerError
|
|
20
|
+
from invenio_vocabularies.datastreams.readers import BaseReader
|
|
21
|
+
from invenio_vocabularies.datastreams.transformers import BaseTransformer
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class RORHTTPReader(BaseReader):
|
|
25
|
+
"""ROR HTTP Reader.
|
|
26
|
+
|
|
27
|
+
Returning an in-memory
|
|
28
|
+
binary stream of the latest ROR data dump ZIP file.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(self, origin=None, mode="r", since=None, *args, **kwargs):
|
|
32
|
+
"""Constructor."""
|
|
33
|
+
self._since = since
|
|
34
|
+
super().__init__(origin, mode, *args, **kwargs)
|
|
35
|
+
|
|
36
|
+
def _iter(self, fp, *args, **kwargs):
|
|
37
|
+
raise NotImplementedError(
|
|
38
|
+
"RORHTTPReader downloads one file "
|
|
39
|
+
"and therefore does not iterate through items"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def _get_last_dump_date(self, linksets):
|
|
43
|
+
"""Get the last dump date."""
|
|
44
|
+
for linkset in linksets:
|
|
45
|
+
metadata_formats = linkset.get("describedby", [])
|
|
46
|
+
for format_link in metadata_formats:
|
|
47
|
+
if format_link.get("type") == "application/ld+json":
|
|
48
|
+
json_ld_reponse = requests.get(
|
|
49
|
+
format_link["href"],
|
|
50
|
+
headers={"Accept": format_link["type"]},
|
|
51
|
+
)
|
|
52
|
+
json_ld_reponse.raise_for_status()
|
|
53
|
+
json_ld_data = json_ld_reponse.json()
|
|
54
|
+
|
|
55
|
+
last_dump_date = json_ld_data.get(
|
|
56
|
+
"dateCreated"
|
|
57
|
+
) or json_ld_data.get("datePublished")
|
|
58
|
+
last_dump_date = datetime.fromisoformat(
|
|
59
|
+
last_dump_date.replace("Z", "+00:00")
|
|
60
|
+
)
|
|
61
|
+
return last_dump_date
|
|
62
|
+
else:
|
|
63
|
+
raise ReaderError(
|
|
64
|
+
"Couldn't find JSON-LD in publisher's linkset "
|
|
65
|
+
"to determine last dump date."
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
def read(self, item=None, *args, **kwargs):
|
|
69
|
+
"""Reads the latest ROR data dump.
|
|
70
|
+
|
|
71
|
+
Read from ZIP file from
|
|
72
|
+
Zenodo and yields an in-memory binary stream of it.
|
|
73
|
+
"""
|
|
74
|
+
if item:
|
|
75
|
+
raise NotImplementedError(
|
|
76
|
+
"RORHTTPReader does not support being chained after another reader"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Follow the DOI to get the link of the linkset
|
|
80
|
+
dataset_doi_link = "https://doi.org/10.5281/zenodo.6347574"
|
|
81
|
+
landing_page = requests.get(dataset_doi_link, allow_redirects=True)
|
|
82
|
+
landing_page.raise_for_status()
|
|
83
|
+
|
|
84
|
+
# Call the signposting `linkset+json` endpoint for
|
|
85
|
+
# the Concept DOI (i.e. latest version) of the ROR data dump.
|
|
86
|
+
# See: https://github.com/inveniosoftware/rfcs/blob/master/rfcs/rdm-0071-signposting.md#provide-an-applicationlinksetjson-endpoint
|
|
87
|
+
if "linkset" not in landing_page.links:
|
|
88
|
+
raise ReaderError("Linkset not found in the ROR dataset record.")
|
|
89
|
+
linkset_response = requests.get(
|
|
90
|
+
landing_page.links["linkset"]["url"],
|
|
91
|
+
headers={"Accept": "application/linkset+json"},
|
|
92
|
+
)
|
|
93
|
+
linkset_response.raise_for_status()
|
|
94
|
+
linksets = linkset_response.json()["linkset"]
|
|
95
|
+
|
|
96
|
+
if self._since and self._since != "None":
|
|
97
|
+
last_dump_date = self._get_last_dump_date(linksets)
|
|
98
|
+
since = datetime.fromisoformat(self._since)
|
|
99
|
+
|
|
100
|
+
if last_dump_date < since:
|
|
101
|
+
current_app.logger.info(
|
|
102
|
+
f"Skipping ROR data dump (last dump: {last_dump_date}, since: {self._since})"
|
|
103
|
+
)
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
for linkset in linksets:
|
|
107
|
+
items = linkset.get("item", [])
|
|
108
|
+
zip_files = [item for item in items if item["type"] == "application/zip"]
|
|
109
|
+
if len(zip_files) == 1:
|
|
110
|
+
file_url = zip_files[0]["href"]
|
|
111
|
+
break
|
|
112
|
+
if len(zip_files) > 1:
|
|
113
|
+
raise ReaderError(f"Expected 1 ZIP item but got {len(zip_files)}")
|
|
114
|
+
|
|
115
|
+
current_app.logger.info(f"Reading ROR data dump (URL: {file_url})")
|
|
116
|
+
|
|
117
|
+
# Download the ZIP file and fully load the response bytes content in memory.
|
|
118
|
+
# The bytes content are then wrapped by a BytesIO to be
|
|
119
|
+
# file-like object (as required by `zipfile.ZipFile`).
|
|
120
|
+
# Using directly `file_resp.raw` is not possible since
|
|
121
|
+
# `zipfile.ZipFile` requires the file-like object to be seekable.
|
|
122
|
+
file_resp = requests.get(file_url)
|
|
123
|
+
file_resp.raise_for_status()
|
|
124
|
+
yield io.BytesIO(file_resp.content)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
VOCABULARIES_DATASTREAM_READERS = {
|
|
128
|
+
"ror-http": RORHTTPReader,
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class RORTransformer(BaseTransformer):
|
|
133
|
+
"""Transforms a JSON ROR record into a funders record."""
|
|
134
|
+
|
|
135
|
+
def __init__(
|
|
136
|
+
self, *args, vocab_schemes=None, funder_fundref_doi_prefix=None, **kwargs
|
|
137
|
+
):
|
|
138
|
+
"""Initializes the transformer."""
|
|
139
|
+
self.vocab_schemes = vocab_schemes
|
|
140
|
+
self.funder_fundref_doi_prefix = funder_fundref_doi_prefix
|
|
141
|
+
super().__init__(*args, **kwargs)
|
|
142
|
+
|
|
143
|
+
def apply(self, stream_entry, **kwargs):
|
|
144
|
+
"""Applies the transformation to the stream entry."""
|
|
145
|
+
record = stream_entry.entry
|
|
146
|
+
ror = {}
|
|
147
|
+
ror["title"] = {}
|
|
148
|
+
|
|
149
|
+
ror["id"] = normalize_ror(record.get("id"))
|
|
150
|
+
if not ror["id"]:
|
|
151
|
+
raise TransformerError(_("Id not found in ROR entry."))
|
|
152
|
+
|
|
153
|
+
# Using set so aliases are unique
|
|
154
|
+
aliases = set()
|
|
155
|
+
acronym = None
|
|
156
|
+
for name in record.get("names"):
|
|
157
|
+
lang = name.get("lang", "en")
|
|
158
|
+
if lang == None:
|
|
159
|
+
lang = "en"
|
|
160
|
+
if "ror_display" in name["types"]:
|
|
161
|
+
ror["name"] = name["value"]
|
|
162
|
+
if "label" in name["types"]:
|
|
163
|
+
ror["title"][lang] = name["value"]
|
|
164
|
+
if "alias" in name["types"]:
|
|
165
|
+
aliases.add(name["value"])
|
|
166
|
+
if "acronym" in name["types"]:
|
|
167
|
+
# The first acronyn goes in acronym field to maintain
|
|
168
|
+
# compatability with existing data structure
|
|
169
|
+
if not acronym:
|
|
170
|
+
acronym = name["value"]
|
|
171
|
+
else:
|
|
172
|
+
aliases.add(name["value"])
|
|
173
|
+
if "en" not in ror["title"]:
|
|
174
|
+
ror["title"]["en"] = ror["name"]
|
|
175
|
+
if acronym:
|
|
176
|
+
ror["acronym"] = acronym
|
|
177
|
+
if aliases:
|
|
178
|
+
ror["aliases"] = list(aliases)
|
|
179
|
+
|
|
180
|
+
# ror_display is required and should be in every entry
|
|
181
|
+
if not ror["name"]:
|
|
182
|
+
raise TransformerError(
|
|
183
|
+
_("Name with type ror_display not found in ROR entry.")
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# This only gets the first location, to maintain compatability
|
|
187
|
+
# with existing data structure
|
|
188
|
+
location = record.get("locations", [{}])[0].get("geonames_details", {})
|
|
189
|
+
ror["country"] = location.get("country_code")
|
|
190
|
+
ror["country_name"] = location.get("country_name")
|
|
191
|
+
ror["location_name"] = location.get("name")
|
|
192
|
+
|
|
193
|
+
ror["types"] = record.get("types")
|
|
194
|
+
|
|
195
|
+
status = record.get("status")
|
|
196
|
+
ror["status"] = status
|
|
197
|
+
|
|
198
|
+
# The ROR is always listed in identifiers, expected by serialization
|
|
199
|
+
ror["identifiers"] = [{"identifier": ror["id"], "scheme": "ror"}]
|
|
200
|
+
if self.vocab_schemes:
|
|
201
|
+
valid_schemes = set(self.vocab_schemes.keys())
|
|
202
|
+
else:
|
|
203
|
+
valid_schemes = set()
|
|
204
|
+
fund_ref = "fundref"
|
|
205
|
+
if self.funder_fundref_doi_prefix:
|
|
206
|
+
valid_schemes.add(fund_ref)
|
|
207
|
+
for identifier in record.get("external_ids"):
|
|
208
|
+
scheme = identifier["type"]
|
|
209
|
+
if scheme in valid_schemes:
|
|
210
|
+
value = identifier.get("preferred") or identifier.get("all")[0]
|
|
211
|
+
if scheme == fund_ref:
|
|
212
|
+
if self.funder_fundref_doi_prefix:
|
|
213
|
+
value = f"{self.funder_fundref_doi_prefix}/{value}"
|
|
214
|
+
scheme = "doi"
|
|
215
|
+
ror["identifiers"].append(
|
|
216
|
+
{
|
|
217
|
+
"identifier": value,
|
|
218
|
+
"scheme": scheme,
|
|
219
|
+
}
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
stream_entry.entry = ror
|
|
223
|
+
return stream_entry
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
VOCABULARIES_DATASTREAM_TRANSFORMERS = {
|
|
227
|
+
"ror": RORTransformer,
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
VOCABULARIES_DATASTREAM_WRITERS = {}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2022 CERN.
|
|
4
|
+
#
|
|
5
|
+
# Invenio-Vocabularies is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
7
|
+
# details.
|
|
8
|
+
|
|
9
|
+
"""Funders vocabulary."""
|
|
10
|
+
|
|
11
|
+
from .resources import FundersResource, FundersResourceConfig
|
|
12
|
+
from .services import FundersService, FundersServiceConfig
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"FundersResource",
|
|
16
|
+
"FundersResourceConfig",
|
|
17
|
+
"FundersService",
|
|
18
|
+
"FundersServiceConfig",
|
|
19
|
+
]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2022 CERN.
|
|
4
|
+
#
|
|
5
|
+
# Invenio-Vocabularies is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
7
|
+
# details.
|
|
8
|
+
|
|
9
|
+
"""Vocabulary funders."""
|
|
10
|
+
|
|
11
|
+
from .funders import record_type
|
|
12
|
+
|
|
13
|
+
Funder = record_type.record_cls
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2022-2024 CERN.
|
|
4
|
+
#
|
|
5
|
+
# Invenio-Vocabularies is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
7
|
+
# details.
|
|
8
|
+
|
|
9
|
+
"""Vocabulary funders configuration."""
|
|
10
|
+
|
|
11
|
+
from flask import current_app
|
|
12
|
+
from invenio_i18n import get_locale
|
|
13
|
+
from invenio_i18n import lazy_gettext as _
|
|
14
|
+
from invenio_records_resources.services import SearchOptions
|
|
15
|
+
from invenio_records_resources.services.records.components import DataComponent
|
|
16
|
+
from invenio_records_resources.services.records.queryparser import (
|
|
17
|
+
CompositeSuggestQueryParser,
|
|
18
|
+
)
|
|
19
|
+
from werkzeug.local import LocalProxy
|
|
20
|
+
|
|
21
|
+
from ...services.components import ModelPIDComponent
|
|
22
|
+
|
|
23
|
+
funder_schemes = LocalProxy(lambda: current_app.config["VOCABULARIES_FUNDER_SCHEMES"])
|
|
24
|
+
|
|
25
|
+
funder_fundref_doi_prefix = LocalProxy(
|
|
26
|
+
lambda: current_app.config["VOCABULARIES_FUNDER_DOI_PREFIX"]
|
|
27
|
+
)
|
|
28
|
+
localized_title = LocalProxy(lambda: f"title.{get_locale()}^2")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class FundersSearchOptions(SearchOptions):
|
|
32
|
+
"""Search options."""
|
|
33
|
+
|
|
34
|
+
suggest_parser_cls = CompositeSuggestQueryParser.factory(
|
|
35
|
+
fields=[
|
|
36
|
+
# We boost the acronym fields, since they're smaller words and are more
|
|
37
|
+
# likely to be used in a query.
|
|
38
|
+
"acronym.keyword^50",
|
|
39
|
+
"acronym^10",
|
|
40
|
+
"name^10",
|
|
41
|
+
# Aliases can sometimes be shorter, so we boost them a bit.
|
|
42
|
+
"aliases^5",
|
|
43
|
+
localized_title,
|
|
44
|
+
# Allow to search identifiers directly (e.g. ROR)
|
|
45
|
+
"identifiers.identifier",
|
|
46
|
+
"country_name",
|
|
47
|
+
],
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
sort_default = "bestmatch"
|
|
51
|
+
|
|
52
|
+
sort_default_no_query = "name"
|
|
53
|
+
|
|
54
|
+
sort_options = {
|
|
55
|
+
"bestmatch": dict(
|
|
56
|
+
title=_("Best match"),
|
|
57
|
+
fields=["_score"], # ES defaults to desc on `_score` field
|
|
58
|
+
),
|
|
59
|
+
"name": dict(
|
|
60
|
+
title=_("Name"),
|
|
61
|
+
fields=["name_sort"],
|
|
62
|
+
),
|
|
63
|
+
"newest": dict(
|
|
64
|
+
title=_("Newest"),
|
|
65
|
+
fields=["-created"],
|
|
66
|
+
),
|
|
67
|
+
"oldest": dict(
|
|
68
|
+
title=_("Oldest"),
|
|
69
|
+
fields=["created"],
|
|
70
|
+
),
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
service_components = [
|
|
75
|
+
# Order of components are important!
|
|
76
|
+
DataComponent,
|
|
77
|
+
ModelPIDComponent,
|
|
78
|
+
]
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2022-2024 CERN.
|
|
4
|
+
# Copyright (C) 2024 California Institute of Technology.
|
|
5
|
+
#
|
|
6
|
+
# Invenio-Vocabularies is free software; you can redistribute it and/or
|
|
7
|
+
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
8
|
+
# details.
|
|
9
|
+
|
|
10
|
+
"""Funders datastreams, transformers, writers and readers."""
|
|
11
|
+
|
|
12
|
+
from flask import current_app
|
|
13
|
+
|
|
14
|
+
from ...datastreams.writers import ServiceWriter
|
|
15
|
+
from ..common.ror.datastreams import RORTransformer
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class FundersServiceWriter(ServiceWriter):
|
|
19
|
+
"""Funders service writer."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, *args, **kwargs):
|
|
22
|
+
"""Constructor."""
|
|
23
|
+
service_or_name = kwargs.pop("service_or_name", "funders")
|
|
24
|
+
super().__init__(service_or_name=service_or_name, *args, **kwargs)
|
|
25
|
+
|
|
26
|
+
def _entry_id(self, entry):
|
|
27
|
+
"""Get the id from an entry."""
|
|
28
|
+
return entry["id"]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class FundersRORTransformer(RORTransformer):
|
|
32
|
+
"""Funders ROR Transformer."""
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self, *args, vocab_schemes=None, funder_fundref_doi_prefix=None, **kwargs
|
|
36
|
+
):
|
|
37
|
+
"""Constructor."""
|
|
38
|
+
if vocab_schemes is None:
|
|
39
|
+
vocab_schemes = current_app.config.get("VOCABULARIES_FUNDER_SCHEMES")
|
|
40
|
+
if funder_fundref_doi_prefix is None:
|
|
41
|
+
funder_fundref_doi_prefix = current_app.config.get(
|
|
42
|
+
"VOCABULARIES_FUNDER_DOI_PREFIX"
|
|
43
|
+
)
|
|
44
|
+
super().__init__(
|
|
45
|
+
*args,
|
|
46
|
+
vocab_schemes=vocab_schemes,
|
|
47
|
+
funder_fundref_doi_prefix=funder_fundref_doi_prefix,
|
|
48
|
+
**kwargs,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
VOCABULARIES_DATASTREAM_READERS = {}
|
|
53
|
+
"""Funders datastreams writers."""
|
|
54
|
+
|
|
55
|
+
VOCABULARIES_DATASTREAM_WRITERS = {
|
|
56
|
+
"funders-service": FundersServiceWriter,
|
|
57
|
+
}
|
|
58
|
+
"""Funders datastreams writers."""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
VOCABULARIES_DATASTREAM_TRANSFORMERS = {
|
|
62
|
+
"ror-funders": FundersRORTransformer,
|
|
63
|
+
}
|
|
64
|
+
"""Funders datastreams transformers."""
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
DATASTREAM_CONFIG = {
|
|
68
|
+
"readers": [
|
|
69
|
+
{"type": "ror-http"},
|
|
70
|
+
{
|
|
71
|
+
"type": "zip",
|
|
72
|
+
"args": {
|
|
73
|
+
"regex": "-ror-data\\.json$",
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
{"type": "json"},
|
|
77
|
+
],
|
|
78
|
+
"transformers": [
|
|
79
|
+
{
|
|
80
|
+
"type": "ror-funders",
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
"writers": [
|
|
84
|
+
{
|
|
85
|
+
"type": "async",
|
|
86
|
+
"args": {
|
|
87
|
+
"writer": {
|
|
88
|
+
"type": "funders-service",
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
}
|
|
94
|
+
"""Data Stream configuration.
|
|
95
|
+
|
|
96
|
+
An origin is required for the reader.
|
|
97
|
+
"""
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2022 CERN.
|
|
4
|
+
#
|
|
5
|
+
# Invenio-Vocabularies is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
7
|
+
# details.
|
|
8
|
+
|
|
9
|
+
"""Vocabulary awards facets and labels."""
|
|
10
|
+
|
|
11
|
+
from ...services.facets import VocabularyLabels, lazy_get_label
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class FundersLabels(VocabularyLabels):
|
|
15
|
+
"""Fetching of vocabulary labels for facets."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, vocabulary, cache=True, cache_ttl=3600, service_id=None):
|
|
18
|
+
"""Initialize the labels.
|
|
19
|
+
|
|
20
|
+
:param vocabulary: the name of the vocabulary type.
|
|
21
|
+
:param cache: use simple process in-memory cache when True.
|
|
22
|
+
:param cache_ttl: cache expiration in seconds.
|
|
23
|
+
:param service_id: the id of the registered service to be used
|
|
24
|
+
when fetching values for the vocabulary.
|
|
25
|
+
"""
|
|
26
|
+
super().__init__(
|
|
27
|
+
vocabulary,
|
|
28
|
+
cache=cache,
|
|
29
|
+
cache_ttl=cache_ttl,
|
|
30
|
+
service_id="funders",
|
|
31
|
+
)
|
|
32
|
+
self.fields = ("id", "title", "country") # not configurable
|
|
33
|
+
|
|
34
|
+
def _vocab_to_label(self, vocab):
|
|
35
|
+
"""Returns the label string for a vocabulary entry."""
|
|
36
|
+
return f"{lazy_get_label(vocab['title'])} ({vocab['country']})"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2022-2024 CERN.
|
|
4
|
+
#
|
|
5
|
+
# Invenio-Vocabularies is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
7
|
+
# details.
|
|
8
|
+
|
|
9
|
+
"""Vocabulary funders."""
|
|
10
|
+
|
|
11
|
+
from flask_resources import (
|
|
12
|
+
BaseListSchema,
|
|
13
|
+
JSONSerializer,
|
|
14
|
+
MarshmallowSerializer,
|
|
15
|
+
ResponseHandler,
|
|
16
|
+
)
|
|
17
|
+
from invenio_db import db
|
|
18
|
+
from invenio_records.dumpers import SearchDumper
|
|
19
|
+
from invenio_records.dumpers.indexedat import IndexedAtDumperExt
|
|
20
|
+
from invenio_records_resources.factories.factory import RecordTypeFactory
|
|
21
|
+
from invenio_records_resources.records.systemfields import ModelPIDField
|
|
22
|
+
from invenio_records_resources.resources.records.headers import etag_headers
|
|
23
|
+
|
|
24
|
+
from invenio_vocabularies.services.permissions import PermissionPolicy
|
|
25
|
+
|
|
26
|
+
from .config import FundersSearchOptions, service_components
|
|
27
|
+
from .schema import FunderSchema
|
|
28
|
+
from .serializer import FunderL10NItemSchema
|
|
29
|
+
|
|
30
|
+
record_type = RecordTypeFactory(
|
|
31
|
+
"Funder",
|
|
32
|
+
# Data layer
|
|
33
|
+
pid_field_cls=ModelPIDField,
|
|
34
|
+
pid_field_kwargs={
|
|
35
|
+
"model_field_name": "pid",
|
|
36
|
+
},
|
|
37
|
+
model_cls_attrs={
|
|
38
|
+
# cannot set to nullable=False because it would fail at
|
|
39
|
+
# service level when create({}), see records-resources.
|
|
40
|
+
"pid": db.Column(db.String(255), unique=True),
|
|
41
|
+
},
|
|
42
|
+
record_dumper=SearchDumper(
|
|
43
|
+
model_fields={"pid": ("id", str)},
|
|
44
|
+
extensions=[
|
|
45
|
+
IndexedAtDumperExt(),
|
|
46
|
+
],
|
|
47
|
+
),
|
|
48
|
+
schema_version="1.0.0",
|
|
49
|
+
schema_path="local://funders/funder-v1.0.0.json",
|
|
50
|
+
index_name="funders-funder-v2.0.0",
|
|
51
|
+
# Service layer
|
|
52
|
+
service_id="funders",
|
|
53
|
+
service_schema=FunderSchema,
|
|
54
|
+
search_options=FundersSearchOptions,
|
|
55
|
+
service_components=service_components,
|
|
56
|
+
permission_policy_cls=PermissionPolicy,
|
|
57
|
+
# Resource layer
|
|
58
|
+
endpoint_route="/funders",
|
|
59
|
+
resource_cls_attrs={
|
|
60
|
+
"response_handlers": {
|
|
61
|
+
"application/json": ResponseHandler(JSONSerializer(), headers=etag_headers),
|
|
62
|
+
"application/vnd.inveniordm.v1+json": ResponseHandler(
|
|
63
|
+
MarshmallowSerializer(
|
|
64
|
+
format_serializer_cls=JSONSerializer,
|
|
65
|
+
object_schema_cls=FunderL10NItemSchema,
|
|
66
|
+
list_schema_cls=BaseListSchema,
|
|
67
|
+
),
|
|
68
|
+
headers=etag_headers,
|
|
69
|
+
),
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
)
|