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.
Files changed (337) hide show
  1. invenio_vocabularies/__init__.py +16 -0
  2. invenio_vocabularies/administration/__init__.py +10 -0
  3. invenio_vocabularies/administration/views/__init__.py +10 -0
  4. invenio_vocabularies/administration/views/vocabularies.py +43 -0
  5. invenio_vocabularies/alembic/17c703ce1eb7_create_names_table.py +54 -0
  6. invenio_vocabularies/alembic/3ba812d80559_add_internal_name_id.py +36 -0
  7. invenio_vocabularies/alembic/4a9a4fd235f8_create_vocabulary_schemes.py +37 -0
  8. invenio_vocabularies/alembic/4f365fced43f_create_vocabularies_tables.py +92 -0
  9. invenio_vocabularies/alembic/55a700f897b6_add_names_and_afiliations_pid_column.py +96 -0
  10. invenio_vocabularies/alembic/6312f33645c1_create_affiliations_table.py +54 -0
  11. invenio_vocabularies/alembic/676dd587542d_create_funders_vocabulary_table.py +58 -0
  12. invenio_vocabularies/alembic/8ff82dfb0be8_create_vocabularies_branch.py +28 -0
  13. invenio_vocabularies/alembic/__init__.py +9 -0
  14. invenio_vocabularies/alembic/af2457652217_drop_unique_constraint_from_internal_id.py +37 -0
  15. invenio_vocabularies/alembic/e1146238edd3_create_awards_table.py +56 -0
  16. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/.eslintrc.yml +11 -0
  17. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/.prettierrc +1 -0
  18. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/index.js +7 -0
  19. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/package.json +25 -0
  20. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/AwardResults.js +95 -0
  21. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/CustomAwardForm.js +139 -0
  22. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/FunderDropdown.js +87 -0
  23. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/FundingField.js +244 -0
  24. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/FundingField.test.js +1 -0
  25. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/FundingFieldItem.js +152 -0
  26. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/FundingModal.js +246 -0
  27. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/NoAwardResults.js +37 -0
  28. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/Funding/index.js +8 -0
  29. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/forms/index.js +7 -0
  30. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/contrib/index.js +7 -0
  31. invenio_vocabularies/assets/semantic-ui/js/invenio_vocabularies/src/index.js +7 -0
  32. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/i18next.js +36 -0
  33. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/_generatedTranslations.js +66 -0
  34. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ar/messages.po +96 -0
  35. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ar/translations.json +28 -0
  36. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/bg/messages.po +94 -0
  37. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/bg/translations.json +28 -0
  38. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ca/messages.po +94 -0
  39. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ca/translations.json +28 -0
  40. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/cs/messages.po +97 -0
  41. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/cs/translations.json +28 -0
  42. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/da/messages.po +94 -0
  43. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/da/translations.json +28 -0
  44. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/de/messages.po +98 -0
  45. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/de/translations.json +28 -0
  46. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/el/messages.po +94 -0
  47. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/el/translations.json +28 -0
  48. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/en/messages.po +88 -0
  49. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/en/translations.json +28 -0
  50. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/es/messages.po +96 -0
  51. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/es/translations.json +28 -0
  52. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/et/messages.po +95 -0
  53. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/et/translations.json +28 -0
  54. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/fa/messages.po +94 -0
  55. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/fa/translations.json +28 -0
  56. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/fr/messages.po +96 -0
  57. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/fr/translations.json +28 -0
  58. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/hr/messages.po +94 -0
  59. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/hr/translations.json +28 -0
  60. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/hu/messages.po +96 -0
  61. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/hu/translations.json +28 -0
  62. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/index.js +24 -0
  63. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/it/messages.po +96 -0
  64. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/it/translations.json +28 -0
  65. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ja/messages.po +94 -0
  66. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ja/translations.json +28 -0
  67. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ka/messages.po +94 -0
  68. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ka/translations.json +28 -0
  69. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ko/messages.po +90 -0
  70. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ko/translations.json +28 -0
  71. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/lt/messages.po +94 -0
  72. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/lt/translations.json +28 -0
  73. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/no/messages.po +94 -0
  74. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/no/translations.json +28 -0
  75. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/pl/messages.po +94 -0
  76. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/pl/translations.json +28 -0
  77. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/pt/messages.po +94 -0
  78. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/pt/translations.json +28 -0
  79. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ro/messages.po +95 -0
  80. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ro/translations.json +28 -0
  81. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ru/messages.po +95 -0
  82. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/ru/translations.json +28 -0
  83. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/sk/messages.po +94 -0
  84. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/sk/translations.json +28 -0
  85. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/sv/messages.po +98 -0
  86. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/sv/translations.json +28 -0
  87. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/tr/messages.po +96 -0
  88. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/tr/translations.json +28 -0
  89. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/uk/messages.po +94 -0
  90. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/uk/translations.json +28 -0
  91. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/zh_CN/messages.po +96 -0
  92. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/zh_CN/translations.json +28 -0
  93. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/zh_TW/messages.po +94 -0
  94. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/messages/zh_TW/translations.json +28 -0
  95. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/package.json +19 -0
  96. invenio_vocabularies/assets/semantic-ui/translations/invenio_vocabularies/translations.pot +88 -0
  97. invenio_vocabularies/cli.py +175 -0
  98. invenio_vocabularies/config.py +231 -0
  99. invenio_vocabularies/contrib/__init__.py +9 -0
  100. invenio_vocabularies/contrib/affiliations/__init__.py +20 -0
  101. invenio_vocabularies/contrib/affiliations/affiliations.py +61 -0
  102. invenio_vocabularies/contrib/affiliations/api.py +13 -0
  103. invenio_vocabularies/contrib/affiliations/config.py +79 -0
  104. invenio_vocabularies/contrib/affiliations/datastreams.py +301 -0
  105. invenio_vocabularies/contrib/affiliations/facets.py +36 -0
  106. invenio_vocabularies/contrib/affiliations/jsonschemas/__init__.py +9 -0
  107. invenio_vocabularies/contrib/affiliations/jsonschemas/affiliations/affiliation-v1.0.0.json +63 -0
  108. invenio_vocabularies/contrib/affiliations/mappings/__init__.py +10 -0
  109. invenio_vocabularies/contrib/affiliations/mappings/os-v1/__init__.py +9 -0
  110. invenio_vocabularies/contrib/affiliations/mappings/os-v1/affiliations/affiliation-v1.0.0.json +112 -0
  111. invenio_vocabularies/contrib/affiliations/mappings/os-v1/affiliations/affiliation-v2.0.0.json +171 -0
  112. invenio_vocabularies/contrib/affiliations/mappings/os-v2/__init__.py +9 -0
  113. invenio_vocabularies/contrib/affiliations/mappings/os-v2/affiliations/affiliation-v1.0.0.json +112 -0
  114. invenio_vocabularies/contrib/affiliations/mappings/os-v2/affiliations/affiliation-v2.0.0.json +171 -0
  115. invenio_vocabularies/contrib/affiliations/mappings/v7/__init__.py +9 -0
  116. invenio_vocabularies/contrib/affiliations/mappings/v7/affiliations/affiliation-v1.0.0.json +112 -0
  117. invenio_vocabularies/contrib/affiliations/models.py +13 -0
  118. invenio_vocabularies/contrib/affiliations/resources.py +16 -0
  119. invenio_vocabularies/contrib/affiliations/schema.py +71 -0
  120. invenio_vocabularies/contrib/affiliations/services.py +15 -0
  121. invenio_vocabularies/contrib/awards/__init__.py +19 -0
  122. invenio_vocabularies/contrib/awards/api.py +13 -0
  123. invenio_vocabularies/contrib/awards/awards.py +96 -0
  124. invenio_vocabularies/contrib/awards/config.py +59 -0
  125. invenio_vocabularies/contrib/awards/datastreams.py +372 -0
  126. invenio_vocabularies/contrib/awards/jsonschemas/__init__.py +9 -0
  127. invenio_vocabularies/contrib/awards/jsonschemas/awards/award-v1.0.0.json +91 -0
  128. invenio_vocabularies/contrib/awards/mappings/__init__.py +9 -0
  129. invenio_vocabularies/contrib/awards/mappings/os-v1/__init__.py +9 -0
  130. invenio_vocabularies/contrib/awards/mappings/os-v1/awards/award-v1.0.0.json +147 -0
  131. invenio_vocabularies/contrib/awards/mappings/os-v2/__init__.py +9 -0
  132. invenio_vocabularies/contrib/awards/mappings/os-v2/awards/award-v1.0.0.json +147 -0
  133. invenio_vocabularies/contrib/awards/mappings/v7/__init__.py +9 -0
  134. invenio_vocabularies/contrib/awards/mappings/v7/awards/award-v1.0.0.json +147 -0
  135. invenio_vocabularies/contrib/awards/models.py +13 -0
  136. invenio_vocabularies/contrib/awards/resources.py +16 -0
  137. invenio_vocabularies/contrib/awards/schema.py +119 -0
  138. invenio_vocabularies/contrib/awards/serializer.py +47 -0
  139. invenio_vocabularies/contrib/awards/services.py +15 -0
  140. invenio_vocabularies/contrib/common/__init__.py +9 -0
  141. invenio_vocabularies/contrib/common/openaire/__init__.py +9 -0
  142. invenio_vocabularies/contrib/common/openaire/datastreams.py +84 -0
  143. invenio_vocabularies/contrib/common/ror/__init__.py +9 -0
  144. invenio_vocabularies/contrib/common/ror/datastreams.py +230 -0
  145. invenio_vocabularies/contrib/funders/__init__.py +19 -0
  146. invenio_vocabularies/contrib/funders/api.py +13 -0
  147. invenio_vocabularies/contrib/funders/config.py +78 -0
  148. invenio_vocabularies/contrib/funders/datastreams.py +97 -0
  149. invenio_vocabularies/contrib/funders/facets.py +36 -0
  150. invenio_vocabularies/contrib/funders/funders.py +72 -0
  151. invenio_vocabularies/contrib/funders/jsonschemas/__init__.py +9 -0
  152. invenio_vocabularies/contrib/funders/jsonschemas/funders/funder-v1.0.0.json +65 -0
  153. invenio_vocabularies/contrib/funders/mappings/__init__.py +9 -0
  154. invenio_vocabularies/contrib/funders/mappings/os-v1/__init__.py +9 -0
  155. invenio_vocabularies/contrib/funders/mappings/os-v1/funders/funder-v1.0.0.json +90 -0
  156. invenio_vocabularies/contrib/funders/mappings/os-v1/funders/funder-v2.0.0.json +156 -0
  157. invenio_vocabularies/contrib/funders/mappings/os-v2/__init__.py +9 -0
  158. invenio_vocabularies/contrib/funders/mappings/os-v2/funders/funder-v1.0.0.json +90 -0
  159. invenio_vocabularies/contrib/funders/mappings/os-v2/funders/funder-v2.0.0.json +156 -0
  160. invenio_vocabularies/contrib/funders/mappings/v7/__init__.py +9 -0
  161. invenio_vocabularies/contrib/funders/mappings/v7/funders/funder-v1.0.0.json +90 -0
  162. invenio_vocabularies/contrib/funders/models.py +13 -0
  163. invenio_vocabularies/contrib/funders/resources.py +16 -0
  164. invenio_vocabularies/contrib/funders/schema.py +88 -0
  165. invenio_vocabularies/contrib/funders/serializer.py +33 -0
  166. invenio_vocabularies/contrib/funders/services.py +15 -0
  167. invenio_vocabularies/contrib/names/__init__.py +19 -0
  168. invenio_vocabularies/contrib/names/api.py +13 -0
  169. invenio_vocabularies/contrib/names/components.py +24 -0
  170. invenio_vocabularies/contrib/names/config.py +75 -0
  171. invenio_vocabularies/contrib/names/datastreams.py +483 -0
  172. invenio_vocabularies/contrib/names/jsonschemas/__init__.py +9 -0
  173. invenio_vocabularies/contrib/names/jsonschemas/names/name-v1.0.0.json +68 -0
  174. invenio_vocabularies/contrib/names/mappings/__init__.py +9 -0
  175. invenio_vocabularies/contrib/names/mappings/os-v1/__init__.py +9 -0
  176. invenio_vocabularies/contrib/names/mappings/os-v1/names/name-v1.0.0.json +101 -0
  177. invenio_vocabularies/contrib/names/mappings/os-v1/names/name-v2.0.0.json +165 -0
  178. invenio_vocabularies/contrib/names/mappings/os-v2/__init__.py +9 -0
  179. invenio_vocabularies/contrib/names/mappings/os-v2/names/name-v1.0.0.json +101 -0
  180. invenio_vocabularies/contrib/names/mappings/os-v2/names/name-v2.0.0.json +165 -0
  181. invenio_vocabularies/contrib/names/mappings/v7/__init__.py +9 -0
  182. invenio_vocabularies/contrib/names/mappings/v7/names/name-v1.0.0.json +101 -0
  183. invenio_vocabularies/contrib/names/models.py +13 -0
  184. invenio_vocabularies/contrib/names/names.py +80 -0
  185. invenio_vocabularies/contrib/names/permissions.py +30 -0
  186. invenio_vocabularies/contrib/names/resources.py +54 -0
  187. invenio_vocabularies/contrib/names/s3client.py +50 -0
  188. invenio_vocabularies/contrib/names/schema.py +121 -0
  189. invenio_vocabularies/contrib/names/services.py +64 -0
  190. invenio_vocabularies/contrib/subjects/__init__.py +22 -0
  191. invenio_vocabularies/contrib/subjects/api.py +14 -0
  192. invenio_vocabularies/contrib/subjects/config.py +90 -0
  193. invenio_vocabularies/contrib/subjects/datastreams.py +63 -0
  194. invenio_vocabularies/contrib/subjects/euroscivoc/__init__.py +9 -0
  195. invenio_vocabularies/contrib/subjects/euroscivoc/datastreams.py +101 -0
  196. invenio_vocabularies/contrib/subjects/facets.py +23 -0
  197. invenio_vocabularies/contrib/subjects/gemet/__init__.py +9 -0
  198. invenio_vocabularies/contrib/subjects/gemet/datastreams.py +140 -0
  199. invenio_vocabularies/contrib/subjects/jsonschemas/__init__.py +10 -0
  200. invenio_vocabularies/contrib/subjects/jsonschemas/subjects/subject-v1.0.0.json +69 -0
  201. invenio_vocabularies/contrib/subjects/mappings/__init__.py +9 -0
  202. invenio_vocabularies/contrib/subjects/mappings/os-v1/__init__.py +9 -0
  203. invenio_vocabularies/contrib/subjects/mappings/os-v1/subjects/subject-v1.0.0.json +96 -0
  204. invenio_vocabularies/contrib/subjects/mappings/os-v2/__init__.py +9 -0
  205. invenio_vocabularies/contrib/subjects/mappings/os-v2/subjects/subject-v1.0.0.json +96 -0
  206. invenio_vocabularies/contrib/subjects/mappings/v7/__init__.py +9 -0
  207. invenio_vocabularies/contrib/subjects/mappings/v7/subjects/subject-v1.0.0.json +96 -0
  208. invenio_vocabularies/contrib/subjects/mesh/__init__.py +9 -0
  209. invenio_vocabularies/contrib/subjects/mesh/datastreams.py +48 -0
  210. invenio_vocabularies/contrib/subjects/models.py +14 -0
  211. invenio_vocabularies/contrib/subjects/nvs/__init__.py +9 -0
  212. invenio_vocabularies/contrib/subjects/nvs/datastreams.py +114 -0
  213. invenio_vocabularies/contrib/subjects/resources.py +17 -0
  214. invenio_vocabularies/contrib/subjects/schema.py +101 -0
  215. invenio_vocabularies/contrib/subjects/services.py +30 -0
  216. invenio_vocabularies/contrib/subjects/subjects.py +55 -0
  217. invenio_vocabularies/datastreams/__init__.py +18 -0
  218. invenio_vocabularies/datastreams/datastreams.py +239 -0
  219. invenio_vocabularies/datastreams/errors.py +29 -0
  220. invenio_vocabularies/datastreams/factories.py +86 -0
  221. invenio_vocabularies/datastreams/readers.py +448 -0
  222. invenio_vocabularies/datastreams/tasks.py +115 -0
  223. invenio_vocabularies/datastreams/transformers.py +130 -0
  224. invenio_vocabularies/datastreams/writers.py +222 -0
  225. invenio_vocabularies/datastreams/xml.py +34 -0
  226. invenio_vocabularies/ext.py +179 -0
  227. invenio_vocabularies/factories.py +193 -0
  228. invenio_vocabularies/fixtures.py +52 -0
  229. invenio_vocabularies/jobs.py +207 -0
  230. invenio_vocabularies/proxies.py +27 -0
  231. invenio_vocabularies/records/__init__.py +9 -0
  232. invenio_vocabularies/records/api.py +53 -0
  233. invenio_vocabularies/records/jsonschemas/__init__.py +9 -0
  234. invenio_vocabularies/records/jsonschemas/vocabularies/definitions-v1.0.0.json +30 -0
  235. invenio_vocabularies/records/jsonschemas/vocabularies/vocabulary-v1.0.0.json +55 -0
  236. invenio_vocabularies/records/mappings/__init__.py +9 -0
  237. invenio_vocabularies/records/mappings/os-v1/__init__.py +9 -0
  238. invenio_vocabularies/records/mappings/os-v1/vocabularies/vocabulary-v1.0.0.json +109 -0
  239. invenio_vocabularies/records/mappings/os-v2/__init__.py +9 -0
  240. invenio_vocabularies/records/mappings/os-v2/vocabularies/vocabulary-v1.0.0.json +109 -0
  241. invenio_vocabularies/records/mappings/v7/__init__.py +9 -0
  242. invenio_vocabularies/records/mappings/v7/vocabularies/vocabulary-v1.0.0.json +109 -0
  243. invenio_vocabularies/records/models.py +90 -0
  244. invenio_vocabularies/records/pidprovider.py +118 -0
  245. invenio_vocabularies/records/systemfields/__init__.py +16 -0
  246. invenio_vocabularies/records/systemfields/pid.py +125 -0
  247. invenio_vocabularies/records/systemfields/relations.py +51 -0
  248. invenio_vocabularies/resources/__init__.py +23 -0
  249. invenio_vocabularies/resources/config.py +105 -0
  250. invenio_vocabularies/resources/resource.py +156 -0
  251. invenio_vocabularies/resources/schema.py +21 -0
  252. invenio_vocabularies/resources/serializer.py +39 -0
  253. invenio_vocabularies/services/__init__.py +19 -0
  254. invenio_vocabularies/services/components.py +58 -0
  255. invenio_vocabularies/services/config.py +173 -0
  256. invenio_vocabularies/services/custom_fields/__init__.py +17 -0
  257. invenio_vocabularies/services/custom_fields/subject.py +82 -0
  258. invenio_vocabularies/services/custom_fields/vocabulary.py +96 -0
  259. invenio_vocabularies/services/facets.py +114 -0
  260. invenio_vocabularies/services/generators.py +38 -0
  261. invenio_vocabularies/services/permissions.py +30 -0
  262. invenio_vocabularies/services/querystr.py +57 -0
  263. invenio_vocabularies/services/results.py +110 -0
  264. invenio_vocabularies/services/schema.py +163 -0
  265. invenio_vocabularies/services/service.py +189 -0
  266. invenio_vocabularies/services/tasks.py +38 -0
  267. invenio_vocabularies/templates/semantic-ui/invenio_vocabularies/subjects.html +23 -0
  268. invenio_vocabularies/templates/semantic-ui/invenio_vocabularies/vocabularies-list.html +12 -0
  269. invenio_vocabularies/templates/semantic-ui/invenio_vocabularies/vocabulary-details.html +71 -0
  270. invenio_vocabularies/translations/ar/LC_MESSAGES/messages.mo +0 -0
  271. invenio_vocabularies/translations/ar/LC_MESSAGES/messages.po +277 -0
  272. invenio_vocabularies/translations/bg/LC_MESSAGES/messages.mo +0 -0
  273. invenio_vocabularies/translations/bg/LC_MESSAGES/messages.po +275 -0
  274. invenio_vocabularies/translations/ca/LC_MESSAGES/messages.mo +0 -0
  275. invenio_vocabularies/translations/ca/LC_MESSAGES/messages.po +276 -0
  276. invenio_vocabularies/translations/cs/LC_MESSAGES/messages.mo +0 -0
  277. invenio_vocabularies/translations/cs/LC_MESSAGES/messages.po +281 -0
  278. invenio_vocabularies/translations/da/LC_MESSAGES/messages.mo +0 -0
  279. invenio_vocabularies/translations/da/LC_MESSAGES/messages.po +271 -0
  280. invenio_vocabularies/translations/de/LC_MESSAGES/messages.mo +0 -0
  281. invenio_vocabularies/translations/de/LC_MESSAGES/messages.po +293 -0
  282. invenio_vocabularies/translations/el/LC_MESSAGES/messages.mo +0 -0
  283. invenio_vocabularies/translations/el/LC_MESSAGES/messages.po +275 -0
  284. invenio_vocabularies/translations/es/LC_MESSAGES/messages.mo +0 -0
  285. invenio_vocabularies/translations/es/LC_MESSAGES/messages.po +281 -0
  286. invenio_vocabularies/translations/et/LC_MESSAGES/messages.mo +0 -0
  287. invenio_vocabularies/translations/et/LC_MESSAGES/messages.po +276 -0
  288. invenio_vocabularies/translations/fa/LC_MESSAGES/messages.mo +0 -0
  289. invenio_vocabularies/translations/fa/LC_MESSAGES/messages.po +275 -0
  290. invenio_vocabularies/translations/fr/LC_MESSAGES/messages.mo +0 -0
  291. invenio_vocabularies/translations/fr/LC_MESSAGES/messages.po +279 -0
  292. invenio_vocabularies/translations/hr/LC_MESSAGES/messages.mo +0 -0
  293. invenio_vocabularies/translations/hr/LC_MESSAGES/messages.po +275 -0
  294. invenio_vocabularies/translations/hu/LC_MESSAGES/messages.mo +0 -0
  295. invenio_vocabularies/translations/hu/LC_MESSAGES/messages.po +280 -0
  296. invenio_vocabularies/translations/it/LC_MESSAGES/messages.mo +0 -0
  297. invenio_vocabularies/translations/it/LC_MESSAGES/messages.po +277 -0
  298. invenio_vocabularies/translations/ja/LC_MESSAGES/messages.mo +0 -0
  299. invenio_vocabularies/translations/ja/LC_MESSAGES/messages.po +275 -0
  300. invenio_vocabularies/translations/ka/LC_MESSAGES/messages.mo +0 -0
  301. invenio_vocabularies/translations/ka/LC_MESSAGES/messages.po +275 -0
  302. invenio_vocabularies/translations/ko/LC_MESSAGES/messages.mo +0 -0
  303. invenio_vocabularies/translations/ko/LC_MESSAGES/messages.po +275 -0
  304. invenio_vocabularies/translations/lt/LC_MESSAGES/messages.mo +0 -0
  305. invenio_vocabularies/translations/lt/LC_MESSAGES/messages.po +275 -0
  306. invenio_vocabularies/translations/messages.pot +270 -0
  307. invenio_vocabularies/translations/no/LC_MESSAGES/messages.mo +0 -0
  308. invenio_vocabularies/translations/no/LC_MESSAGES/messages.po +275 -0
  309. invenio_vocabularies/translations/pl/LC_MESSAGES/messages.mo +0 -0
  310. invenio_vocabularies/translations/pl/LC_MESSAGES/messages.po +275 -0
  311. invenio_vocabularies/translations/pt/LC_MESSAGES/messages.mo +0 -0
  312. invenio_vocabularies/translations/pt/LC_MESSAGES/messages.po +275 -0
  313. invenio_vocabularies/translations/ro/LC_MESSAGES/messages.mo +0 -0
  314. invenio_vocabularies/translations/ro/LC_MESSAGES/messages.po +280 -0
  315. invenio_vocabularies/translations/ru/LC_MESSAGES/messages.mo +0 -0
  316. invenio_vocabularies/translations/ru/LC_MESSAGES/messages.po +276 -0
  317. invenio_vocabularies/translations/sk/LC_MESSAGES/messages.mo +0 -0
  318. invenio_vocabularies/translations/sk/LC_MESSAGES/messages.po +276 -0
  319. invenio_vocabularies/translations/sv/LC_MESSAGES/messages.mo +0 -0
  320. invenio_vocabularies/translations/sv/LC_MESSAGES/messages.po +280 -0
  321. invenio_vocabularies/translations/tr/LC_MESSAGES/messages.mo +0 -0
  322. invenio_vocabularies/translations/tr/LC_MESSAGES/messages.po +277 -0
  323. invenio_vocabularies/translations/uk/LC_MESSAGES/messages.mo +0 -0
  324. invenio_vocabularies/translations/uk/LC_MESSAGES/messages.po +275 -0
  325. invenio_vocabularies/translations/zh_CN/LC_MESSAGES/messages.mo +0 -0
  326. invenio_vocabularies/translations/zh_CN/LC_MESSAGES/messages.po +276 -0
  327. invenio_vocabularies/translations/zh_TW/LC_MESSAGES/messages.mo +0 -0
  328. invenio_vocabularies/translations/zh_TW/LC_MESSAGES/messages.po +275 -0
  329. invenio_vocabularies/views.py +53 -0
  330. invenio_vocabularies/webpack.py +51 -0
  331. invenio_vocabularies-9.1.2.dist-info/METADATA +517 -0
  332. invenio_vocabularies-9.1.2.dist-info/RECORD +337 -0
  333. invenio_vocabularies-9.1.2.dist-info/WHEEL +6 -0
  334. invenio_vocabularies-9.1.2.dist-info/entry_points.txt +73 -0
  335. invenio_vocabularies-9.1.2.dist-info/licenses/AUTHORS.rst +13 -0
  336. invenio_vocabularies-9.1.2.dist-info/licenses/LICENSE +21 -0
  337. 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,9 @@
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
+ """ROR-related module."""
@@ -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
+ )
@@ -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
+ """Funders JSONSchemas module."""