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,19 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2021-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
|
+
"""Awards vocabulary."""
|
|
10
|
+
|
|
11
|
+
from .resources import AwardsResource, AwardsResourceConfig
|
|
12
|
+
from .services import AwardsService, AwardsServiceConfig
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"AwardsResource",
|
|
16
|
+
"AwardsResourceConfig",
|
|
17
|
+
"AwardsService",
|
|
18
|
+
"AwardsServiceConfig",
|
|
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 awards."""
|
|
10
|
+
|
|
11
|
+
from .awards import record_type
|
|
12
|
+
|
|
13
|
+
Award = record_type.record_cls
|
|
@@ -0,0 +1,96 @@
|
|
|
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 awards."""
|
|
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.dumpers.relations import RelationDumperExt
|
|
21
|
+
from invenio_records.systemfields import MultiRelationsField
|
|
22
|
+
from invenio_records_resources.factories.factory import RecordTypeFactory
|
|
23
|
+
from invenio_records_resources.records.systemfields import (
|
|
24
|
+
ModelPIDField,
|
|
25
|
+
PIDListRelation,
|
|
26
|
+
PIDRelation,
|
|
27
|
+
)
|
|
28
|
+
from invenio_records_resources.resources.records.headers import etag_headers
|
|
29
|
+
|
|
30
|
+
from invenio_vocabularies.services.permissions import PermissionPolicy
|
|
31
|
+
|
|
32
|
+
from ..funders.api import Funder
|
|
33
|
+
from ..subjects.api import Subject
|
|
34
|
+
from .config import AwardsSearchOptions, service_components
|
|
35
|
+
from .schema import AwardSchema
|
|
36
|
+
from .serializer import AwardL10NItemSchema
|
|
37
|
+
|
|
38
|
+
award_relations = MultiRelationsField(
|
|
39
|
+
funders=PIDRelation(
|
|
40
|
+
"funder",
|
|
41
|
+
keys=["name"],
|
|
42
|
+
pid_field=Funder.pid,
|
|
43
|
+
cache_key="funder",
|
|
44
|
+
),
|
|
45
|
+
subjects=PIDListRelation(
|
|
46
|
+
"subjects",
|
|
47
|
+
keys=["subject", "scheme", "identifiers", "props"],
|
|
48
|
+
pid_field=Subject.pid,
|
|
49
|
+
cache_key="subjects",
|
|
50
|
+
),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
record_type = RecordTypeFactory(
|
|
54
|
+
"Award",
|
|
55
|
+
# Data layer
|
|
56
|
+
pid_field_cls=ModelPIDField,
|
|
57
|
+
pid_field_kwargs={
|
|
58
|
+
"model_field_name": "pid",
|
|
59
|
+
},
|
|
60
|
+
model_cls_attrs={
|
|
61
|
+
# cannot set to nullable=False because it would fail at
|
|
62
|
+
# service level when create({}), see records-resources.
|
|
63
|
+
"pid": db.Column(db.String(255), unique=True),
|
|
64
|
+
},
|
|
65
|
+
record_dumper=SearchDumper(
|
|
66
|
+
model_fields={"pid": ("id", str)},
|
|
67
|
+
extensions=[
|
|
68
|
+
RelationDumperExt("relations"),
|
|
69
|
+
IndexedAtDumperExt(),
|
|
70
|
+
],
|
|
71
|
+
),
|
|
72
|
+
schema_version="1.0.0",
|
|
73
|
+
schema_path="local://awards/award-v1.0.0.json",
|
|
74
|
+
record_relations=award_relations,
|
|
75
|
+
# Service layer
|
|
76
|
+
service_id="awards",
|
|
77
|
+
service_schema=AwardSchema,
|
|
78
|
+
search_options=AwardsSearchOptions,
|
|
79
|
+
service_components=service_components,
|
|
80
|
+
permission_policy_cls=PermissionPolicy,
|
|
81
|
+
# Resource layer
|
|
82
|
+
endpoint_route="/awards",
|
|
83
|
+
resource_cls_attrs={
|
|
84
|
+
"response_handlers": {
|
|
85
|
+
"application/json": ResponseHandler(JSONSerializer(), headers=etag_headers),
|
|
86
|
+
"application/vnd.inveniordm.v1+json": ResponseHandler(
|
|
87
|
+
MarshmallowSerializer(
|
|
88
|
+
format_serializer_cls=JSONSerializer,
|
|
89
|
+
object_schema_cls=AwardL10NItemSchema,
|
|
90
|
+
list_schema_cls=BaseListSchema,
|
|
91
|
+
),
|
|
92
|
+
headers=etag_headers,
|
|
93
|
+
),
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
)
|
|
@@ -0,0 +1,59 @@
|
|
|
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 configuration."""
|
|
10
|
+
|
|
11
|
+
from flask import current_app
|
|
12
|
+
from invenio_i18n import lazy_gettext as _
|
|
13
|
+
from invenio_records_resources.services import SearchOptions
|
|
14
|
+
from invenio_records_resources.services.records.components import (
|
|
15
|
+
DataComponent,
|
|
16
|
+
RelationsComponent,
|
|
17
|
+
)
|
|
18
|
+
from invenio_records_resources.services.records.facets import TermsFacet
|
|
19
|
+
from invenio_records_resources.services.records.params import SuggestQueryParser
|
|
20
|
+
from werkzeug.local import LocalProxy
|
|
21
|
+
|
|
22
|
+
from ...services.components import ModelPIDComponent
|
|
23
|
+
from ..funders.facets import FundersLabels
|
|
24
|
+
|
|
25
|
+
award_schemes = LocalProxy(lambda: current_app.config["VOCABULARIES_AWARD_SCHEMES"])
|
|
26
|
+
|
|
27
|
+
awards_openaire_funders_mapping = LocalProxy(
|
|
28
|
+
lambda: current_app.config["VOCABULARIES_AWARDS_OPENAIRE_FUNDERS"]
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
awards_ec_ror_id = LocalProxy(
|
|
32
|
+
lambda: current_app.config["VOCABULARIES_AWARDS_EC_ROR_ID"]
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class AwardsSearchOptions(SearchOptions):
|
|
37
|
+
"""Search options."""
|
|
38
|
+
|
|
39
|
+
suggest_parser_cls = SuggestQueryParser.factory(
|
|
40
|
+
fields=[
|
|
41
|
+
"acronym^100",
|
|
42
|
+
"number^10",
|
|
43
|
+
"identifiers.identifier^10",
|
|
44
|
+
],
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
facets = {
|
|
48
|
+
"funders": TermsFacet(
|
|
49
|
+
field="funder.id", label=_("Funders"), value_labels=FundersLabels("funders")
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
service_components = [
|
|
55
|
+
# Order of components are important!
|
|
56
|
+
DataComponent,
|
|
57
|
+
ModelPIDComponent,
|
|
58
|
+
RelationsComponent,
|
|
59
|
+
]
|
|
@@ -0,0 +1,372 @@
|
|
|
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
|
+
"""Awards datastreams, transformers, writers and readers."""
|
|
10
|
+
|
|
11
|
+
import io
|
|
12
|
+
|
|
13
|
+
import requests
|
|
14
|
+
from flask import current_app
|
|
15
|
+
from invenio_access.permissions import system_identity
|
|
16
|
+
from invenio_i18n import lazy_gettext as _
|
|
17
|
+
|
|
18
|
+
from invenio_vocabularies.datastreams.errors import ReaderError
|
|
19
|
+
|
|
20
|
+
from ...datastreams.errors import TransformerError
|
|
21
|
+
from ...datastreams.readers import BaseReader
|
|
22
|
+
from ...datastreams.transformers import BaseTransformer
|
|
23
|
+
from ...datastreams.writers import ServiceWriter
|
|
24
|
+
from .config import awards_ec_ror_id, awards_openaire_funders_mapping
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class AwardsServiceWriter(ServiceWriter):
|
|
28
|
+
"""Funders service writer."""
|
|
29
|
+
|
|
30
|
+
def __init__(self, *args, **kwargs):
|
|
31
|
+
"""Constructor."""
|
|
32
|
+
service_or_name = kwargs.pop("service_or_name", "awards")
|
|
33
|
+
super().__init__(service_or_name=service_or_name, *args, **kwargs)
|
|
34
|
+
|
|
35
|
+
def _entry_id(self, entry):
|
|
36
|
+
"""Get the id from an entry."""
|
|
37
|
+
return entry["id"]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class OpenAIREProjectTransformer(BaseTransformer):
|
|
41
|
+
"""Transforms an OpenAIRE project record into an award record."""
|
|
42
|
+
|
|
43
|
+
def apply(self, stream_entry, **kwargs):
|
|
44
|
+
"""Applies the transformation to the stream entry."""
|
|
45
|
+
record = stream_entry.entry
|
|
46
|
+
award = {}
|
|
47
|
+
|
|
48
|
+
code = record["code"]
|
|
49
|
+
|
|
50
|
+
# The `id` should follow the format `sourcePrefix::md5(localId)` where `sourcePrefix` is 12 characters long.
|
|
51
|
+
# See: https://graph.openaire.eu/docs/data-model/pids-and-identifiers#identifiers-in-the-graph
|
|
52
|
+
#
|
|
53
|
+
# The format of `id` in the full OpenAIRE Graph Dataset (https://doi.org/10.5281/zenodo.3516917)
|
|
54
|
+
# follows this format (e.g. 'abc_________::0123456789abcdef0123456789abcdef').
|
|
55
|
+
# However, the format of `id` in the new collected projects dataset (https://doi.org/10.5281/zenodo.6419021)
|
|
56
|
+
# does not follow this format, and has a `40|` prefix (e.g. '40|abc_________::0123456789abcdef0123456789abcdef').
|
|
57
|
+
#
|
|
58
|
+
# The number '40' corresponds to the entity types 'Project'.
|
|
59
|
+
# See: https://ec.europa.eu/research/participants/documents/downloadPublic?documentIds=080166e5a3a1a213&appId=PPGMS
|
|
60
|
+
# See: https://graph.openaire.eu/docs/5.0.0/data-model/entities/project#id
|
|
61
|
+
openaire_funder_prefix = record["id"].split("::", 1)[0].split("|", 1)[-1]
|
|
62
|
+
|
|
63
|
+
funder_id = awards_openaire_funders_mapping.get(openaire_funder_prefix)
|
|
64
|
+
if funder_id is None:
|
|
65
|
+
raise TransformerError(
|
|
66
|
+
_(
|
|
67
|
+
"Unknown OpenAIRE funder prefix {openaire_funder_prefix}".format(
|
|
68
|
+
openaire_funder_prefix=openaire_funder_prefix
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
award["id"] = f"{funder_id}::{code}"
|
|
74
|
+
|
|
75
|
+
funding = next(iter(record.get("funding", [])), None)
|
|
76
|
+
if funding:
|
|
77
|
+
funding_stream_id = funding.get("fundingStream", {}).get("id", "")
|
|
78
|
+
# Example funding stream ID: `EC::HE::HORIZON-AG-UN`. We need the `HE`
|
|
79
|
+
# string, i.e. the second "part" of the identifier.
|
|
80
|
+
program = next(iter(funding_stream_id.split("::")[1:2]), "")
|
|
81
|
+
if program:
|
|
82
|
+
award["program"] = program
|
|
83
|
+
|
|
84
|
+
identifiers = []
|
|
85
|
+
if funder_id == awards_ec_ror_id:
|
|
86
|
+
identifiers.append(
|
|
87
|
+
{
|
|
88
|
+
"identifier": f"https://cordis.europa.eu/projects/{code}",
|
|
89
|
+
"scheme": "url",
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
elif record.get("websiteurl"):
|
|
93
|
+
identifiers.append(
|
|
94
|
+
{"identifier": record.get("websiteurl"), "scheme": "url"}
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
if identifiers:
|
|
98
|
+
award["identifiers"] = identifiers
|
|
99
|
+
|
|
100
|
+
award["number"] = code
|
|
101
|
+
|
|
102
|
+
# `title` is a mandatory attribute of the `Project` object in the OpenAIRE Graph Data Model.
|
|
103
|
+
# See: https://graph.openaire.eu/docs/data-model/entities/project#title
|
|
104
|
+
# However, 15'000+ awards for the FCT funder (and 1 record the NIH funder) are missing a title attribute.
|
|
105
|
+
if "title" not in record:
|
|
106
|
+
raise TransformerError(
|
|
107
|
+
_(
|
|
108
|
+
"Missing title attribute for award {award_id}".format(
|
|
109
|
+
award_id=award["id"]
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
award["title"] = {"en": record["title"]}
|
|
114
|
+
|
|
115
|
+
award["funder"] = {"id": funder_id}
|
|
116
|
+
acronym = record.get("acronym")
|
|
117
|
+
if acronym:
|
|
118
|
+
award["acronym"] = acronym
|
|
119
|
+
|
|
120
|
+
if "startDate" in record:
|
|
121
|
+
award["start_date"] = record["startDate"]
|
|
122
|
+
if "endDate" in record:
|
|
123
|
+
award["end_date"] = record["endDate"]
|
|
124
|
+
if "summary" in record:
|
|
125
|
+
award["description"] = {"en": record["summary"]}
|
|
126
|
+
|
|
127
|
+
stream_entry.entry = award
|
|
128
|
+
return stream_entry
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class CORDISProjectHTTPReader(BaseReader):
|
|
132
|
+
"""CORDIS Project HTTP Reader returning an in-memory binary stream of the latest CORDIS Horizon Europe project zip file."""
|
|
133
|
+
|
|
134
|
+
def _iter(self, fp, *args, **kwargs):
|
|
135
|
+
raise NotImplementedError(
|
|
136
|
+
"CORDISProjectHTTPReader downloads one file and therefore does not iterate through items"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
def read(self, item=None, *args, **kwargs):
|
|
140
|
+
"""Reads the latest CORDIS Horizon Europe project zip file and yields an in-memory binary stream of it."""
|
|
141
|
+
if item:
|
|
142
|
+
raise NotImplementedError(
|
|
143
|
+
"CORDISProjectHTTPReader does not support being chained after another reader"
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
if self._origin == "HE":
|
|
147
|
+
file_url = "https://cordis.europa.eu/data/cordis-HORIZONprojects-xml.zip"
|
|
148
|
+
elif self._origin == "H2020":
|
|
149
|
+
file_url = "https://cordis.europa.eu/data/cordis-h2020projects-xml.zip"
|
|
150
|
+
elif self._origin == "FP7":
|
|
151
|
+
file_url = "https://cordis.europa.eu/data/cordis-fp7projects-xml.zip"
|
|
152
|
+
else:
|
|
153
|
+
raise ReaderError(
|
|
154
|
+
"The --origin option should be either 'HE' (for Horizon Europe) or 'H2020' (for Horizon 2020) or 'FP7'"
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Download the ZIP file and fully load the response bytes content in memory.
|
|
158
|
+
# The bytes content are then wrapped by a BytesIO to be file-like object (as required by `zipfile.ZipFile`).
|
|
159
|
+
# Using directly `file_resp.raw` is not possible since `zipfile.ZipFile` requires the file-like object to be seekable.
|
|
160
|
+
file_resp = requests.get(file_url)
|
|
161
|
+
file_resp.raise_for_status()
|
|
162
|
+
yield io.BytesIO(file_resp.content)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class CORDISProjectTransformer(BaseTransformer):
|
|
166
|
+
"""Transforms a CORDIS project record into an award record."""
|
|
167
|
+
|
|
168
|
+
def apply(self, stream_entry, **kwargs):
|
|
169
|
+
"""Applies the transformation to the stream entry."""
|
|
170
|
+
record = stream_entry.entry
|
|
171
|
+
award = {}
|
|
172
|
+
|
|
173
|
+
# Here `id` is the project ID, which will be used to attach the update to the existing project.
|
|
174
|
+
award["id"] = (
|
|
175
|
+
f"{current_app.config['VOCABULARIES_AWARDS_EC_ROR_ID']}::{record['id']}"
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
categories = record.get("relations", {}).get("categories", {}).get("category")
|
|
179
|
+
if categories:
|
|
180
|
+
if isinstance(categories, dict):
|
|
181
|
+
categories = [categories]
|
|
182
|
+
|
|
183
|
+
award["subjects"] = [
|
|
184
|
+
{"id": f"euroscivoc:{vocab_id}"}
|
|
185
|
+
for category in categories
|
|
186
|
+
if category.get("@classification") == "euroSciVoc"
|
|
187
|
+
and (vocab_id := category["code"].split("/")[-1]).isdigit()
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
organizations = (
|
|
191
|
+
record.get("relations", {}).get("associations", {}).get("organization")
|
|
192
|
+
)
|
|
193
|
+
if organizations:
|
|
194
|
+
# Projects with a single organization are not wrapped in a list,
|
|
195
|
+
# so we do this here to be able to iterate over it.
|
|
196
|
+
organizations = (
|
|
197
|
+
organizations if isinstance(organizations, list) else [organizations]
|
|
198
|
+
)
|
|
199
|
+
award["organizations"] = []
|
|
200
|
+
for organization in organizations:
|
|
201
|
+
# Some organizations in FP7 projects do not have a "legalname" key,
|
|
202
|
+
# for instance the 14th participant in "SAGE" https://cordis.europa.eu/project/id/999902.
|
|
203
|
+
# In this case, fully skip the organization entry.
|
|
204
|
+
if "legalname" not in organization:
|
|
205
|
+
continue
|
|
206
|
+
|
|
207
|
+
organization_data = {
|
|
208
|
+
"organization": organization["legalname"],
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
# Some organizations in FP7 projects do not have an "id" key (the PIC identifier),
|
|
212
|
+
# for instance "AIlGreenVehicles" in "MOTORBRAIN" https://cordis.europa.eu/project/id/270693.
|
|
213
|
+
# In this case, still store the name but skip the identifier part.
|
|
214
|
+
if "id" in organization:
|
|
215
|
+
organization_data.update(
|
|
216
|
+
{
|
|
217
|
+
"scheme": "pic",
|
|
218
|
+
"id": organization["id"],
|
|
219
|
+
}
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
award["organizations"].append(organization_data)
|
|
223
|
+
|
|
224
|
+
programmes = (
|
|
225
|
+
record.get("relations", {}).get("associations", {}).get("programme", {})
|
|
226
|
+
)
|
|
227
|
+
if programmes:
|
|
228
|
+
# Projects with a single programme (this is the case of some projects in FP7) are not wrapped in a list,
|
|
229
|
+
# so we do this here to be able to iterate over it.
|
|
230
|
+
programmes = programmes if isinstance(programmes, list) else [programmes]
|
|
231
|
+
|
|
232
|
+
programmes_related_legal_basis = [
|
|
233
|
+
{
|
|
234
|
+
"code": programme["code"],
|
|
235
|
+
"uniqueprogrammepart": programme.get("@uniqueprogrammepart"),
|
|
236
|
+
}
|
|
237
|
+
for programme in programmes
|
|
238
|
+
if programme.get("@type") == "relatedLegalBasis"
|
|
239
|
+
]
|
|
240
|
+
|
|
241
|
+
if len(programmes_related_legal_basis) == 0:
|
|
242
|
+
raise TransformerError(
|
|
243
|
+
_(
|
|
244
|
+
"No related legal basis programme found for project {project_id}".format(
|
|
245
|
+
project_id=record["id"]
|
|
246
|
+
)
|
|
247
|
+
)
|
|
248
|
+
)
|
|
249
|
+
elif len(programmes_related_legal_basis) == 1:
|
|
250
|
+
# FP7 projects have only one related legal basis programme and do not have a 'uniqueprogrammepart' field.
|
|
251
|
+
unique_programme_related_legal_basis = programmes_related_legal_basis[0]
|
|
252
|
+
elif len(programmes_related_legal_basis) >= 1:
|
|
253
|
+
# The entry with the field 'uniqueprogrammepart' == 'true' is the high level programme code,
|
|
254
|
+
# while the other entry is a more specific sub-programme.
|
|
255
|
+
unique_programme_related_legal_basis = [
|
|
256
|
+
programme_related_legal_basis
|
|
257
|
+
# A few H2020 projects have more than one 'uniqueprogrammepart' == 'true',
|
|
258
|
+
# for instance https://cordis.europa.eu/project/id/825673 (showing as "main programme" in the page)
|
|
259
|
+
# which has one entry with the code 'H2020-EU.1.2.',
|
|
260
|
+
# and one with the code 'H2020-EU.1.2.3.'.
|
|
261
|
+
# We sort them from the shortest code to the longest code, and take the first item,
|
|
262
|
+
# so that it conforms more with other projects which all have the shortest code as the main one.
|
|
263
|
+
for programme_related_legal_basis in sorted(
|
|
264
|
+
programmes_related_legal_basis, key=lambda d: len(d["code"])
|
|
265
|
+
)
|
|
266
|
+
if programme_related_legal_basis["uniqueprogrammepart"] == "true"
|
|
267
|
+
][0]
|
|
268
|
+
|
|
269
|
+
# Store the code of the programme.
|
|
270
|
+
# For instance the code "HORIZON.1.2" which means "Marie Skłodowska-Curie Actions (MSCA)"
|
|
271
|
+
# See https://cordis.europa.eu/programme/id/HORIZON.1.2
|
|
272
|
+
award["program"] = unique_programme_related_legal_basis["code"]
|
|
273
|
+
|
|
274
|
+
stream_entry.entry = award
|
|
275
|
+
return stream_entry
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class CORDISAwardsServiceWriter(ServiceWriter):
|
|
279
|
+
"""CORDIS Awards service writer."""
|
|
280
|
+
|
|
281
|
+
def __init__(self, *args, **kwargs):
|
|
282
|
+
"""Constructor."""
|
|
283
|
+
service_or_name = kwargs.pop("service_or_name", "awards")
|
|
284
|
+
# Here we only update and we do not insert, since CORDIS data is used to augment existing awards
|
|
285
|
+
# (with subjects, organizations, and program information) and is not used to create new awards.
|
|
286
|
+
super().__init__(
|
|
287
|
+
service_or_name=service_or_name, insert=False, update=True, *args, **kwargs
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
def _entry_id(self, entry):
|
|
291
|
+
"""Get the id from an entry."""
|
|
292
|
+
return entry["id"]
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
VOCABULARIES_DATASTREAM_READERS = {
|
|
296
|
+
"cordis-project-http": CORDISProjectHTTPReader,
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
VOCABULARIES_DATASTREAM_TRANSFORMERS = {
|
|
300
|
+
"openaire-award": OpenAIREProjectTransformer,
|
|
301
|
+
"cordis-award": CORDISProjectTransformer,
|
|
302
|
+
}
|
|
303
|
+
"""ORCiD Data Streams transformers."""
|
|
304
|
+
|
|
305
|
+
VOCABULARIES_DATASTREAM_WRITERS = {
|
|
306
|
+
"awards-service": AwardsServiceWriter,
|
|
307
|
+
"cordis-awards-service": CORDISAwardsServiceWriter,
|
|
308
|
+
}
|
|
309
|
+
"""ORCiD Data Streams transformers."""
|
|
310
|
+
|
|
311
|
+
DATASTREAM_CONFIG_CORDIS = {
|
|
312
|
+
"readers": [
|
|
313
|
+
{"type": "cordis-project-http"},
|
|
314
|
+
{
|
|
315
|
+
"type": "zip",
|
|
316
|
+
"args": {
|
|
317
|
+
"regex": "\\.xml$",
|
|
318
|
+
"mode": "r",
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
"type": "xml",
|
|
323
|
+
"args": {
|
|
324
|
+
"root_element": "project",
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
],
|
|
328
|
+
"transformers": [
|
|
329
|
+
{"type": "cordis-award"},
|
|
330
|
+
],
|
|
331
|
+
"writers": [
|
|
332
|
+
{
|
|
333
|
+
"type": "cordis-awards-service",
|
|
334
|
+
"args": {
|
|
335
|
+
"identity": system_identity,
|
|
336
|
+
},
|
|
337
|
+
}
|
|
338
|
+
],
|
|
339
|
+
}
|
|
340
|
+
"""Data Stream configuration.
|
|
341
|
+
|
|
342
|
+
An origin is required for the reader.
|
|
343
|
+
"""
|
|
344
|
+
|
|
345
|
+
DATASTREAM_CONFIG = {
|
|
346
|
+
"readers": [
|
|
347
|
+
{
|
|
348
|
+
"type": "tar",
|
|
349
|
+
"args": {
|
|
350
|
+
"regex": "\\.json.gz$",
|
|
351
|
+
"mode": "r",
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
{"type": "gzip"},
|
|
355
|
+
{"type": "jsonl"},
|
|
356
|
+
],
|
|
357
|
+
"transformers": [
|
|
358
|
+
{"type": "openaire-award"},
|
|
359
|
+
],
|
|
360
|
+
"writers": [
|
|
361
|
+
{
|
|
362
|
+
"type": "awards-service",
|
|
363
|
+
"args": {
|
|
364
|
+
"identity": system_identity,
|
|
365
|
+
},
|
|
366
|
+
}
|
|
367
|
+
],
|
|
368
|
+
}
|
|
369
|
+
"""Data Stream configuration.
|
|
370
|
+
|
|
371
|
+
An origin is required for the reader.
|
|
372
|
+
"""
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "local://awards/award-v1.0.0.json",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"additionalProperties": false,
|
|
6
|
+
"properties": {
|
|
7
|
+
"$schema": {
|
|
8
|
+
"$ref": "local://definitions-v1.0.0.json#/$schema"
|
|
9
|
+
},
|
|
10
|
+
"tags": {
|
|
11
|
+
"$ref": "local://vocabularies/definitions-v1.0.0.json#/tags"
|
|
12
|
+
},
|
|
13
|
+
"identifiers": {
|
|
14
|
+
"description": "Alternate identifiers for the award.",
|
|
15
|
+
"type": "array",
|
|
16
|
+
"items": {
|
|
17
|
+
"$ref": "local://definitions-v1.0.0.json#/identifiers_with_scheme"
|
|
18
|
+
},
|
|
19
|
+
"uniqueItems": true
|
|
20
|
+
},
|
|
21
|
+
"number": {
|
|
22
|
+
"type": "string"
|
|
23
|
+
},
|
|
24
|
+
"title": {
|
|
25
|
+
"$ref": "local://vocabularies/definitions-v1.0.0.json#/title"
|
|
26
|
+
},
|
|
27
|
+
"funder": {
|
|
28
|
+
"description": "Award's funder.",
|
|
29
|
+
"type": "object",
|
|
30
|
+
"additionalProperties": false,
|
|
31
|
+
"properties": {
|
|
32
|
+
"id": {
|
|
33
|
+
"$ref": "local://definitions-v1.0.0.json#/identifier"
|
|
34
|
+
},
|
|
35
|
+
"name": {
|
|
36
|
+
"type": "string"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"acronym": {
|
|
41
|
+
"type": "string"
|
|
42
|
+
},
|
|
43
|
+
"program": {
|
|
44
|
+
"type": "string"
|
|
45
|
+
},
|
|
46
|
+
"start_date": {
|
|
47
|
+
"type": "string"
|
|
48
|
+
},
|
|
49
|
+
"end_date": {
|
|
50
|
+
"type": "string"
|
|
51
|
+
},
|
|
52
|
+
"description": {
|
|
53
|
+
"$ref": "local://vocabularies/definitions-v1.0.0.json#/description"
|
|
54
|
+
},
|
|
55
|
+
"subjects": {
|
|
56
|
+
"description": "Award's subjects.",
|
|
57
|
+
"type": "array",
|
|
58
|
+
"properties": {
|
|
59
|
+
"id": {
|
|
60
|
+
"$ref": "local://definitions-v1.0.0.json#/identifier"
|
|
61
|
+
},
|
|
62
|
+
"subject": {
|
|
63
|
+
"description": "Human readable label.",
|
|
64
|
+
"type": "string"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"organizations": {
|
|
69
|
+
"description": "Award's organizations.",
|
|
70
|
+
"type": "array",
|
|
71
|
+
"items": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"additionalProperties": false,
|
|
74
|
+
"properties": {
|
|
75
|
+
"scheme": {
|
|
76
|
+
"description": "Identifier of the organization scheme.",
|
|
77
|
+
"$ref": "local://definitions-v1.0.0.json#/identifier"
|
|
78
|
+
},
|
|
79
|
+
"id": {
|
|
80
|
+
"description": "Identifier of the organization for the given scheme.",
|
|
81
|
+
"$ref": "local://definitions-v1.0.0.json#/identifier"
|
|
82
|
+
},
|
|
83
|
+
"organization": {
|
|
84
|
+
"description": "Human readable label.",
|
|
85
|
+
"type": "string"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
"""Awards OpenSearch v1 mappings."""
|