pymetadata 0.8.0__tar.gz → 0.8.2__tar.gz

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 (233) hide show
  1. {pymetadata-0.8.0 → pymetadata-0.8.2}/.bumpversion.toml +1 -1
  2. pymetadata-0.8.2/.github/dependabot.yml +34 -0
  3. {pymetadata-0.8.0 → pymetadata-0.8.2}/.github/workflows/ci-cd.yml +17 -24
  4. {pymetadata-0.8.0 → pymetadata-0.8.2}/.github/workflows/docs.yml +12 -4
  5. {pymetadata-0.8.0 → pymetadata-0.8.2}/.github/workflows/ruff.yml +4 -1
  6. {pymetadata-0.8.0 → pymetadata-0.8.2}/.github/workflows/ty.yml +1 -0
  7. {pymetadata-0.8.0 → pymetadata-0.8.2}/.gitignore +5 -2
  8. {pymetadata-0.8.0 → pymetadata-0.8.2}/CITATION.cff +2 -2
  9. {pymetadata-0.8.0 → pymetadata-0.8.2}/CLAUDE.md +22 -13
  10. {pymetadata-0.8.0 → pymetadata-0.8.2}/PKG-INFO +8 -7
  11. {pymetadata-0.8.0 → pymetadata-0.8.2}/README.md +5 -5
  12. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/development.md +8 -2
  13. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/index.md +5 -5
  14. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/installation.md +7 -1
  15. {pymetadata-0.8.0 → pymetadata-0.8.2}/pyproject.toml +4 -1
  16. pymetadata-0.8.2/release-notes/0.8.1.md +20 -0
  17. pymetadata-0.8.2/release-notes/0.8.2.md +9 -0
  18. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/__init__.py +1 -1
  19. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/cache.py +125 -26
  20. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/webservices/chebi.py +5 -18
  21. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/webservices/registry.py +23 -9
  22. pymetadata-0.8.2/tests/data/registry/identifiers_registry_response.json +596 -0
  23. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_cache.py +123 -0
  24. pymetadata-0.8.2/tests/test_registry.py +231 -0
  25. {pymetadata-0.8.0 → pymetadata-0.8.2}/tox.ini +3 -1
  26. pymetadata-0.8.2/uv.lock +1669 -0
  27. pymetadata-0.8.0/.github/dependabot.yml +0 -16
  28. pymetadata-0.8.0/tests/test_registry.py +0 -11
  29. {pymetadata-0.8.0 → pymetadata-0.8.2}/.github/CODEOWNERS +0 -0
  30. {pymetadata-0.8.0 → pymetadata-0.8.2}/.github/pull_request_template.md +0 -0
  31. {pymetadata-0.8.0 → pymetadata-0.8.2}/.github/rulesets/apply.sh +0 -0
  32. {pymetadata-0.8.0 → pymetadata-0.8.2}/.github/rulesets/develop.json +0 -0
  33. {pymetadata-0.8.0 → pymetadata-0.8.2}/.github/rulesets/main.json +0 -0
  34. {pymetadata-0.8.0 → pymetadata-0.8.2}/.github/rulesets/tags.json +0 -0
  35. {pymetadata-0.8.0 → pymetadata-0.8.2}/.pre-commit-config.yaml +0 -0
  36. {pymetadata-0.8.0 → pymetadata-0.8.2}/.python-version +0 -0
  37. {pymetadata-0.8.0 → pymetadata-0.8.2}/.ruff.toml +0 -0
  38. {pymetadata-0.8.0 → pymetadata-0.8.2}/.zenodo.json +0 -0
  39. {pymetadata-0.8.0 → pymetadata-0.8.2}/LICENSE +0 -0
  40. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/README.md +0 -0
  41. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/annotations.md +0 -0
  42. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/cache.md +0 -0
  43. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/console.md +0 -0
  44. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/core.annotation.md +0 -0
  45. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/core.creator.md +0 -0
  46. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/core.miriam.md +0 -0
  47. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/core.xref.md +0 -0
  48. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/index.md +0 -0
  49. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/log.md +0 -0
  50. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/omex.md +0 -0
  51. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/ontologies.term.md +0 -0
  52. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/webservices.chebi.md +0 -0
  53. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/webservices.ols.md +0 -0
  54. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/webservices.registry.md +0 -0
  55. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/webservices.unichem.md +0 -0
  56. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/webservices.uniprot.md +0 -0
  57. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/api/webservices.webservice.md +0 -0
  58. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/images/HARMONY2026_slides.png +0 -0
  59. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/images/favicon/about.txt +0 -0
  60. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/images/favicon/android-chrome-192x192.png +0 -0
  61. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/images/favicon/android-chrome-512x512.png +0 -0
  62. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/images/favicon/apple-touch-icon.png +0 -0
  63. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/images/favicon/favicon-16x16.png +0 -0
  64. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/images/favicon/favicon-32x32.png +0 -0
  65. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/images/favicon/favicon.ico +0 -0
  66. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/images/favicon/favicon_io.zip +0 -0
  67. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/images/favicon/pymetadata-100x100-300dpi.png +0 -0
  68. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/images/favicon/site.webmanifest +0 -0
  69. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/omex.md +0 -0
  70. {pymetadata-0.8.0 → pymetadata-0.8.2}/docs/robots.txt +0 -0
  71. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/annotation.py +0 -0
  72. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/cache_path.py +0 -0
  73. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/MODEL2402290004.4_pymetadata.omex +0 -0
  74. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/create_omex.py +0 -0
  75. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/BioModelsMetadata_MODEL2402290004.csv +0 -0
  76. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/EndoAcuteBZ1.m +0 -0
  77. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/EndoAcuteBZ2.m +0 -0
  78. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/EndoAcuteBZ3.m +0 -0
  79. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/EndoChronicBZ.m +0 -0
  80. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/EndoChronicRZ1.m +0 -0
  81. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/EndoChronicRZ2.m +0 -0
  82. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/EndoNZ.m +0 -0
  83. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/POM253.mat +0 -0
  84. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/PlotAPCaTTaAcuteAndChronic.m +0 -0
  85. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/Zhou2024_Updated-model.m +0 -0
  86. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/getCurrentsStructureCaMKSKJrelpKinetics.m +0 -0
  87. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/getStartingState.m +0 -0
  88. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/main.m +0 -0
  89. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/manifest.xml +0 -0
  90. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/metadata.rdf +0 -0
  91. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/modelRunnerCaMKSKJrelpKinetics1ms.m +0 -0
  92. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/biomodels_omex/files/model_ToRORd_LandCaMKSKJrelpKinetics.m +0 -0
  93. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/omex.py +0 -0
  94. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/omex_from_url.py +0 -0
  95. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/omex/test.omex +0 -0
  96. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/pbpko.py +0 -0
  97. {pymetadata-0.8.0 → pymetadata-0.8.2}/examples/sbo.py +0 -0
  98. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/.gitignore +0 -0
  99. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/README.md +0 -0
  100. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/_extensions/grantmcdermott/clean/_extension.yml +0 -0
  101. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/_extensions/grantmcdermott/clean/clean.scss +0 -0
  102. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/_extensions/grantmcdermott/clean/mathjax-config.js +0 -0
  103. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/custom.scss +0 -0
  104. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/images/annotation_example.png +0 -0
  105. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/images/annotation_resolved.png +0 -0
  106. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/images/annotation_resolved_small.png +0 -0
  107. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/images/github_screenshot.png +0 -0
  108. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/images/headshot.png +0 -0
  109. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/images/omex_logo.png +0 -0
  110. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/images/omex_overview.png +0 -0
  111. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/images/pymetadata.png +0 -0
  112. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/images/pymetadata_large.png +0 -0
  113. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/images/qr_livermetabolism.png +0 -0
  114. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/mathjax-config.js +0 -0
  115. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/pymetadata.bib +0 -0
  116. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/pymetadata.qmd +0 -0
  117. {pymetadata-0.8.0 → pymetadata-0.8.2}/presentations/HARMONY2026/styles.css +0 -0
  118. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.10.md +0 -0
  119. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.11.md +0 -0
  120. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.12.md +0 -0
  121. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.13.md +0 -0
  122. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.14.md +0 -0
  123. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.15.md +0 -0
  124. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.16.md +0 -0
  125. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.17.md +0 -0
  126. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.18.md +0 -0
  127. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.19.md +0 -0
  128. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.2.md +0 -0
  129. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.20.md +0 -0
  130. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.21.md +0 -0
  131. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.22.md +0 -0
  132. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.3.md +0 -0
  133. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.4.md +0 -0
  134. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.5.md +0 -0
  135. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.6.md +0 -0
  136. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.7.md +0 -0
  137. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.8.md +0 -0
  138. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.0.9.md +0 -0
  139. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.1.0.md +0 -0
  140. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.2.1.md +0 -0
  141. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.2.10.md +0 -0
  142. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.2.2.md +0 -0
  143. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.2.3.md +0 -0
  144. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.2.4.md +0 -0
  145. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.2.5.md +0 -0
  146. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.2.6.md +0 -0
  147. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.2.7.md +0 -0
  148. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.2.8.md +0 -0
  149. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.2.9.md +0 -0
  150. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.3.0.md +0 -0
  151. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.3.1.md +0 -0
  152. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.3.10.md +0 -0
  153. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.3.11.md +0 -0
  154. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.3.2.md +0 -0
  155. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.3.3.md +0 -0
  156. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.3.4.md +0 -0
  157. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.3.5.md +0 -0
  158. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.3.6.md +0 -0
  159. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.3.7.md +0 -0
  160. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.3.8.md +0 -0
  161. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.3.9.md +0 -0
  162. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.4.0.md +0 -0
  163. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.4.1.md +0 -0
  164. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.4.2.md +0 -0
  165. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.4.3.md +0 -0
  166. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.4.4.md +0 -0
  167. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.0.md +0 -0
  168. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.1.md +0 -0
  169. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.10.md +0 -0
  170. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.11.md +0 -0
  171. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.12.md +0 -0
  172. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.2.md +0 -0
  173. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.3.md +0 -0
  174. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.4.md +0 -0
  175. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.5.md +0 -0
  176. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.6.md +0 -0
  177. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.7.md +0 -0
  178. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.8.md +0 -0
  179. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.5.9.md +0 -0
  180. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.6.0.md +0 -0
  181. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.6.1.md +0 -0
  182. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.6.2.md +0 -0
  183. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.6.3.md +0 -0
  184. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.6.4.md +0 -0
  185. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.6.5.md +0 -0
  186. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.6.6.md +0 -0
  187. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.7.0.md +0 -0
  188. {pymetadata-0.8.0 → pymetadata-0.8.2}/release-notes/0.8.0.md +0 -0
  189. {pymetadata-0.8.0 → pymetadata-0.8.2}/scripts/llms_txt.py +0 -0
  190. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/_files.py +0 -0
  191. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/console.py +0 -0
  192. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/core/__init__.py +0 -0
  193. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/core/annotation.py +0 -0
  194. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/core/creator.py +0 -0
  195. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/core/miriam.py +0 -0
  196. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/core/synonym.py +0 -0
  197. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/core/xref.py +0 -0
  198. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/log.py +0 -0
  199. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/omex.py +0 -0
  200. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/ontologies/__init__.py +0 -0
  201. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/ontologies/_ontology_builder.py +0 -0
  202. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/ontologies/kisao.py +0 -0
  203. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/ontologies/pbpko.py +0 -0
  204. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/ontologies/sbo.py +0 -0
  205. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/ontologies/term.py +0 -0
  206. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/py.typed +0 -0
  207. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/resources/ontologies/README.md +0 -0
  208. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/webservices/__init__.py +0 -0
  209. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/webservices/ols.py +0 -0
  210. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/webservices/unichem.py +0 -0
  211. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/webservices/uniprot.py +0 -0
  212. {pymetadata-0.8.0 → pymetadata-0.8.2}/src/pymetadata/webservices/webservice.py +0 -0
  213. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/core/test_annotation.py +0 -0
  214. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/core/test_creator.py +0 -0
  215. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/data/omex/BIOMD0000000001.omex +0 -0
  216. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/data/omex/CombineArchiveShowCase.omex +0 -0
  217. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/data/omex/CombineArchiveShowCase_manifest.xml +0 -0
  218. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/data/omex/CompModels.omex +0 -0
  219. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/data/omex/CompModels_manifest.xml +0 -0
  220. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/data/omex/iCGB21FR.omex +0 -0
  221. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_annotation_resolution.py +0 -0
  222. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_chebi.py +0 -0
  223. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_log.py +0 -0
  224. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_offline.py +0 -0
  225. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_ols.py +0 -0
  226. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_omex.py +0 -0
  227. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_ontology.py +0 -0
  228. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_ontology_builder.py +0 -0
  229. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_sbo_kisao.py +0 -0
  230. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_unichem.py +0 -0
  231. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_uniprot.py +0 -0
  232. {pymetadata-0.8.0 → pymetadata-0.8.2}/tests/test_webservice.py +0 -0
  233. {pymetadata-0.8.0 → pymetadata-0.8.2}/zensical.toml +0 -0
@@ -1,5 +1,5 @@
1
1
  [tool.bumpversion]
2
- current_version = "0.8.0"
2
+ current_version = "0.8.2"
3
3
  commit = true
4
4
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
5
5
  serialize = ["{major}.{minor}.{patch}"]
@@ -0,0 +1,34 @@
1
+ # Keep the GitHub Actions used in the workflows and the locked python dependencies up to date,
2
+ # monthly, since every update pull request runs the checks.
3
+ # See https://docs.github.com/code-security/dependabot/dependabot-version-updates
4
+ version: 2
5
+ updates:
6
+ - package-ecosystem: "github-actions"
7
+ directory: "/"
8
+ schedule:
9
+ interval: "monthly"
10
+ # a single pull request for all action updates instead of one per action
11
+ groups:
12
+ github-actions:
13
+ patterns:
14
+ - "*"
15
+ open-pull-requests-limit: 5
16
+ commit-message:
17
+ prefix: "ci"
18
+
19
+ # the locked python dependencies (uv.lock), bumped together
20
+ - package-ecosystem: "uv"
21
+ directory: "/"
22
+ # only uv.lock is updated: the default would raise the lower bounds in
23
+ # pyproject.toml, which are what a user of the library installs against,
24
+ # so they are only ever changed by hand
25
+ versioning-strategy: lockfile-only
26
+ schedule:
27
+ interval: "monthly"
28
+ groups:
29
+ python-dependencies:
30
+ patterns:
31
+ - "*"
32
+ open-pull-requests-limit: 5
33
+ commit-message:
34
+ prefix: "build"
@@ -15,8 +15,9 @@ permissions:
15
15
 
16
16
  concurrency:
17
17
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
18
- # superseded branch runs are cancelled, release runs are never cancelled
19
- cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }}
18
+ # a newer run supersedes the running one of the same branch or pull request;
19
+ # a release is never superseded, every tag is a group of its own
20
+ cancel-in-progress: true
20
21
 
21
22
  jobs:
22
23
  test:
@@ -25,26 +26,11 @@ jobs:
25
26
  strategy:
26
27
  fail-fast: false
27
28
  matrix:
29
+ # continuous integration tests the newest python on every platform, the
30
+ # older and newer versions are tested locally with `tox run-parallel`,
31
+ # see docs/development.md
28
32
  os: [ubuntu-latest, windows-latest, macos-latest]
29
- python-version: ["3.11", "3.12", "3.13", "3.14", "3.15"]
30
- # linux covers the full range, windows and macos only the newest version
31
- exclude:
32
- - os: windows-latest
33
- python-version: "3.11"
34
- - os: windows-latest
35
- python-version: "3.12"
36
- - os: windows-latest
37
- python-version: "3.13"
38
- - os: windows-latest
39
- python-version: "3.14"
40
- - os: macos-latest
41
- python-version: "3.11"
42
- - os: macos-latest
43
- python-version: "3.12"
44
- - os: macos-latest
45
- python-version: "3.13"
46
- - os: macos-latest
47
- python-version: "3.14"
33
+ python-version: ["3.14"]
48
34
 
49
35
  steps:
50
36
  - uses: actions/checkout@v7
@@ -55,10 +41,16 @@ jobs:
55
41
  uses: astral-sh/setup-uv@v10.2.0
56
42
  with:
57
43
  python-version: ${{ matrix.python-version }}
58
- enable-cache: true
44
+ # a release run restores no cache, which zizmor cannot tell from the
45
+ # expression; the distributions are built without one, see `release`
46
+ enable-cache: ${{ !startsWith(github.ref, 'refs/tags/') }} # zizmor: ignore[cache-poisoning]
47
+ # the interpreter is cached with the packages instead of downloaded by every run
48
+ cache-python: ${{ !startsWith(github.ref, 'refs/tags/') }} # zizmor: ignore[cache-poisoning]
59
49
  - name: Test with tox
50
+ # the runner is billed by wall time: the tests run on every core, the
51
+ # slowest are listed so they stay visible
60
52
  run:
61
- uvx --with tox-uv tox -e py${{ matrix.python-version }}
53
+ uvx --with tox-uv tox -e py${{ matrix.python-version }} -- -n auto --durations=15
62
54
 
63
55
  tests:
64
56
  # the one check the branch protection requires; the names of the matrix
@@ -95,7 +87,8 @@ jobs:
95
87
  uses: astral-sh/setup-uv@v10.2.0
96
88
  with:
97
89
  python-version: "3.14"
98
- enable-cache: true
90
+ # a release is built from a clean state, never from a restored cache
91
+ enable-cache: false
99
92
  - name: Build package
100
93
  run: uvx hatch build
101
94
  - name: Check the package
@@ -13,8 +13,9 @@ permissions:
13
13
 
14
14
  concurrency:
15
15
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
16
- # never cancel a running deployment, it would leave the site half published
17
- cancel-in-progress: false
16
+ # a newer run supersedes the running one; a cancelled deployment leaves the
17
+ # published site as it was, the newer run deploys
18
+ cancel-in-progress: true
18
19
 
19
20
  jobs:
20
21
  docs:
@@ -27,14 +28,19 @@ jobs:
27
28
  with:
28
29
  persist-credentials: false
29
30
  - name: Configure GitHub Pages
31
+ # only needed for the deployment, see `deploy`
32
+ if: github.ref == 'refs/heads/develop'
30
33
  uses: actions/configure-pages@v6
31
34
  - name: Install uv and set the python version
32
35
  uses: astral-sh/setup-uv@v10.2.0
33
36
  with:
34
37
  python-version: "3.14"
35
38
  enable-cache: true
36
- - name: Install dependencies
37
- run: uv sync --extra dev
39
+ cache-python: true
40
+ - name: Install the locked dependencies (fails if uv.lock is out of date with pyproject.toml, run `uv lock`)
41
+ # `--locked` refuses to update the lock: a change of the dependencies
42
+ # in pyproject.toml has to come with the `uv lock` which records it
43
+ run: uv sync --locked --extra dev
38
44
  - name: Build the documentation
39
45
  # the API reference is rendered from the docstrings by mkdocstrings,
40
46
  # so the package has to be importable
@@ -43,6 +49,8 @@ jobs:
43
49
  # llms.txt, llms-full.txt and the markdown of every page
44
50
  run: uv run python scripts/llms_txt.py
45
51
  - name: Upload the site
52
+ # only needed for the deployment, see `deploy`
53
+ if: github.ref == 'refs/heads/develop'
46
54
  uses: actions/upload-pages-artifact@v5
47
55
  with:
48
56
  path: site
@@ -25,13 +25,16 @@ jobs:
25
25
  - uses: actions/checkout@v7
26
26
  with:
27
27
  persist-credentials: false
28
- # the ruff version is read from the dev dependencies in pyproject.toml
28
+ # the ruff version is read from the lock (the same file `uv run ruff` uses locally), not from the
29
+ # `ruff>=` bound in pyproject.toml, which would resolve to the latest release
29
30
  - name: Lint
30
31
  # astral-sh/ruff-action publishes no floating major tag beyond v3
31
32
  uses: astral-sh/ruff-action@v4.1.0
32
33
  with:
34
+ version-file: uv.lock
33
35
  args: check --output-format=github
34
36
  - name: Format
35
37
  uses: astral-sh/ruff-action@v4.1.0
36
38
  with:
39
+ version-file: uv.lock
37
40
  args: format --check --diff
@@ -30,6 +30,7 @@ jobs:
30
30
  with:
31
31
  python-version: "3.14"
32
32
  enable-cache: true
33
+ cache-python: true
33
34
  - name: Type check with tox
34
35
  env:
35
36
  # render diagnostics as GitHub Actions workflow annotations
@@ -17,8 +17,11 @@ coverage.xml
17
17
  # rendered documentation, built by the `documentation` workflow
18
18
  site/
19
19
 
20
- # the lock file is not committed, pymetadata is a library and pins nothing
21
- uv.lock
20
+ # working files of coding agents, their design documents and plans are not committed
21
+ .superpowers/
22
+ docs/superpowers/
23
+ .claude/plans/
24
+ .claude/specs/
22
25
 
23
26
  # editors, operating system
24
27
  .idea/
@@ -8,8 +8,8 @@ authors:
8
8
  given-names: "Matthias"
9
9
  orcid: "https://orcid.org/0000-0003-1725-179X"
10
10
  affiliation: "Humboldt-University Berlin, Faculty of Life Science, Institute for Biology, Biology, Berlin; University Lübeck; University Hospital Schleswig-Holstein, Campus Lübeck, First Department of Medicine, Germany"
11
- version: "0.8.0"
12
- date-released: "2026-09-23"
11
+ version: "0.8.2"
12
+ date-released: "2026-10-05"
13
13
  doi: "10.5281/zenodo.5308801"
14
14
  license: MIT
15
15
  repository-code: "https://github.com/matthiaskoenig/pymetadata"
@@ -4,12 +4,7 @@ This file provides guidance when working with code in this repository.
4
4
 
5
5
  ## Project
6
6
 
7
- `pymetadata` is a python library for metadata in the context of COMBINE standards:
8
- COMBINE archives (OMEX), MIRIAM/RDF annotations, and ontology terms (SBO, KISAO, PBPKO).
9
- Pure library, no CLI entry points. Requires python >= 3.11, packaged with hatchling
10
- (version is read from `src/pymetadata/__init__.py`). Runtime dependencies are
11
- `rich`, `requests` and `pydantic`; `pronto` is the optional `ontology` extra,
12
- needed only to regenerate the ontology modules.
7
+ `pymetadata` is a python library for metadata in the context of COMBINE standards: COMBINE archives (OMEX), MIRIAM/RDF annotations, and ontology terms (SBO, KISAO, PBPKO). Pure library, no CLI entry points. Requires python >= 3.11, packaged with hatchling (version is read from `src/pymetadata/__init__.py`). Runtime dependencies are `rich`, `requests` and `pydantic`, plus the floors of `urllib3` and `certifi`, which are not imported but reached through `requests` (`certifi>=2026.10.19` excludes the CA store with the compromised emSign intermediates, GHSA-6q48-6c7w-9gw2); `pronto` is the optional `ontology` extra, needed only to regenerate the ontology modules.
13
8
 
14
9
  ## Commands
15
10
 
@@ -17,13 +12,14 @@ needed only to regenerate the ontology modules.
17
12
  # environment (uv based); the dev extra includes the ontology extra
18
13
  uv sync --extra dev
19
14
  uv run pre-commit install
15
+ uv lock # after every change of a dependency in pyproject.toml
20
16
 
21
17
  # tests
22
18
  pytest # all tests
23
19
  pytest tests/test_omex.py # single file
24
20
  pytest tests/test_omex.py::test_entry_from_dict # single test
25
21
  tox r -e py3.15 # single tox env (py3.11-3.15 available)
26
- tox run-parallel # full matrix + ty
22
+ tox run-parallel # full matrix + ty, run before opening a pull request
27
23
 
28
24
  # lint / format / types
29
25
  ruff check
@@ -32,11 +28,7 @@ tox -e ty # ty type check (config in [tool.ty] in pyprojec
32
28
  uvx ty check # same check, straight from the working tree
33
29
  ```
34
30
 
35
- `develop` is the default branch and takes every change through a pull request;
36
- direct pushes are rejected by the rulesets in `.github/rulesets/` (applied with
37
- `.github/rulesets/apply.sh`), which require the `tests`, `ruff`, `ty` and `docs`
38
- checks. `main` only tracks the latest release and is fast-forwarded by the
39
- `sync-main` job of the release workflow, never by hand.
31
+ `develop` is the default branch and takes every change through a pull request; direct pushes are rejected by the rulesets in `.github/rulesets/` (applied with `.github/rulesets/apply.sh`), which require the `tests`, `ruff`, `ty` and `docs` checks. Continuous integration is kept minimal: `tests` runs only `py3.14`, on linux, macos and windows, with pytest-xdist (`-n auto`), every workflow cancels a superseded run (`cancel-in-progress: true`), uv caches packages and interpreters, dependabot runs monthly. The other python versions run only locally. `main` only tracks the latest release and is fast-forwarded by the `sync-main` job of the release workflow, never by hand.
40
32
 
41
33
  Release steps are in `docs/development.md` (there is no separate `RELEASE.md`):
42
34
  the release is prepared on a branch, `uvx bump-my-version bump [major|minor|patch]`
@@ -121,7 +113,14 @@ registry). When a refresh fails, `read_json_cache_fallback` returns the outdated
121
113
  content with a warning instead of failing, so queries answered before keep
122
114
  working offline; `tests/test_offline.py` covers this per service. The corresponding tests
123
115
  (`test_ols.py`, `test_registry.py`, `test_chebi.py`, `test_unichem.py`, `test_uniprot.py`) require
124
- network access.
116
+ network access. Processes share the cache (pytest-xdist workers): `write_bytes_cache`
117
+ and `write_json_cache` write a temporary file next to the cache file and `os.replace`
118
+ it, so a reader never sees a partial file, and the write is best effort, a failure is
119
+ a warning and the caller keeps its data. On Windows a file another process has open
120
+ cannot be replaced and a file being replaced cannot be opened, so both are retried
121
+ (`CACHE_IN_USE_ATTEMPTS`); `Registry` uses the downloaded namespaces and does not read
122
+ them back. `test_registry.py` loads the registry from several processes into one empty
123
+ cache, with the download answered from `tests/data/registry/` (#102).
125
124
 
126
125
  `console.py` (rich console, for scripts and `__main__` blocks) and `log.py`
127
126
  provide the shared output/logging. Modules get their logger from the standard
@@ -138,6 +137,16 @@ lazy `%s` formatting rather than f-strings (enforced by ruff `G`).
138
137
  `project.requires-python`. Suppress a diagnostic with a rule-specific
139
138
  `# ty: ignore[rule-name]`, never a blanket `# type: ignore`. ty also runs as a
140
139
  pre-commit hook (`--extra dev`, so the hook syncs the dev environment it checks against).
140
+ - `uv.lock` is committed and pins the local development environment (`uv sync`,
141
+ `uv run`, so also `uv run ty check`), the `documentation` workflow, which runs
142
+ `uv sync --locked`, and the ruff version of the `ruff` workflow; the tox
143
+ environments, i.e. the test matrix and the `ty` check of continuous
144
+ integration, resolve from `pyproject.toml` and do not use it. After changing a
145
+ dependency in `pyproject.toml` run `uv lock`, otherwise the `documentation`
146
+ workflow fails; `uv lock --upgrade` moves the lock to the newest releases.
147
+ Dependabot bumps the lock monthly with `versioning-strategy: lockfile-only`, so
148
+ the lower bounds in `pyproject.toml`, which users install against, are only
149
+ changed by hand.
141
150
  - Every module, class and function carries full type annotations and a google-style
142
151
  docstring.
143
152
  - `examples/` at the top level holds the runnable usage examples, they are not
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pymetadata
3
- Version: 0.8.0
3
+ Version: 0.8.2
4
4
  Summary: pymetadata are python utilities for working with metadata.
5
5
  Project-URL: Homepage, https://matthiaskoenig.github.io/pymetadata
6
6
  Project-URL: Documentation, https://matthiaskoenig.github.io/pymetadata
@@ -25,7 +25,8 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
25
25
  Classifier: Topic :: Scientific/Engineering
26
26
  Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
27
27
  Requires-Python: >=3.11
28
- Requires-Dist: pydantic>=2.13.5
28
+ Requires-Dist: certifi>=2026.10.19
29
+ Requires-Dist: pydantic>=2.12
29
30
  Requires-Dist: requests>=2.34.2
30
31
  Requires-Dist: rich>=15.0.0
31
32
  Requires-Dist: urllib3>=2.5.0
@@ -65,18 +66,18 @@ If you have any questions or issues please [open an issue](https://github.com/ma
65
66
 
66
67
  If you use `pymetadata` please cite the archived software on [Zenodo](https://doi.org/10.5281/zenodo.5308801):
67
68
 
68
- > König, M. (2026). *pymetadata are python utilities for working with metadata* (Version 0.6.6) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.22914125
69
+ > König, M. (2026). *pymetadata are python utilities for working with metadata* (Version 0.8.0) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.23159552
69
70
 
70
71
  ```bibtex
71
72
  @software{konig_pymetadata,
72
73
  author = {König, Matthias},
73
74
  title = {pymetadata are python utilities for working with metadata},
74
75
  year = {2026},
75
- month = sep,
76
- version = {0.6.6},
76
+ month = oct,
77
+ version = {0.8.0},
77
78
  publisher = {Zenodo},
78
- doi = {10.5281/zenodo.22914125},
79
- url = {https://doi.org/10.5281/zenodo.22914125},
79
+ doi = {10.5281/zenodo.23159552},
80
+ url = {https://doi.org/10.5281/zenodo.23159552},
80
81
  }
81
82
  ```
82
83
 
@@ -19,18 +19,18 @@ If you have any questions or issues please [open an issue](https://github.com/ma
19
19
 
20
20
  If you use `pymetadata` please cite the archived software on [Zenodo](https://doi.org/10.5281/zenodo.5308801):
21
21
 
22
- > König, M. (2026). *pymetadata are python utilities for working with metadata* (Version 0.6.6) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.22914125
22
+ > König, M. (2026). *pymetadata are python utilities for working with metadata* (Version 0.8.0) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.23159552
23
23
 
24
24
  ```bibtex
25
25
  @software{konig_pymetadata,
26
26
  author = {König, Matthias},
27
27
  title = {pymetadata are python utilities for working with metadata},
28
28
  year = {2026},
29
- month = sep,
30
- version = {0.6.6},
29
+ month = oct,
30
+ version = {0.8.0},
31
31
  publisher = {Zenodo},
32
- doi = {10.5281/zenodo.22914125},
33
- url = {https://doi.org/10.5281/zenodo.22914125},
32
+ doi = {10.5281/zenodo.23159552},
33
+ url = {https://doi.org/10.5281/zenodo.23159552},
34
34
  }
35
35
  ```
36
36
 
@@ -27,7 +27,7 @@ A pull request can only be merged once the four required checks are green:
27
27
 
28
28
  | check | workflow | content |
29
29
  | ------- | ------------- | -------------------------------------------------------------------- |
30
- | `tests` | `ci-cd.yml` | the test matrix, linux, macos and windows with python 3.11 to 3.15 |
30
+ | `tests` | `ci-cd.yml` | the test matrix, python 3.14 on linux, macos and windows |
31
31
  | `ruff` | `ruff.yml` | `ruff check` and `ruff format --check` |
32
32
  | `ty` | `ty.yml` | `tox r -e ty` |
33
33
  | `docs` | `docs.yml` | the zensical build including the api reference and the agent files |
@@ -35,6 +35,8 @@ A pull request can only be merged once the four required checks are green:
35
35
  `tests` aggregates the test matrix into a single job, so the name of the
36
36
  required check stays the same when the matrix changes.
37
37
 
38
+ Continuous integration is kept small: every workflow cancels its running build when a newer commit of the same branch or pull request arrives, uv caches the packages and the interpreters between runs, dependabot proposes its updates once a month, and the matrix tests only python 3.14. The other python versions are tested locally, see [Testing](#testing), before a pull request is opened.
39
+
38
40
  Further rules of a pull request:
39
41
 
40
42
  - conversations have to be resolved before the merge
@@ -94,6 +96,8 @@ A single sync creates the virtual environment in `.venv`, installs `pymetadata`
94
96
  uv sync --extra dev
95
97
  ```
96
98
 
99
+ The environment is resolved from `uv.lock`, which is committed, so local development, including `uv run ty check`, and the documentation build use the same versions. The tox environments, i.e. the test matrix and the `ty` check of continuous integration, resolve from `pyproject.toml` and do not use the lock; the lower bounds in `pyproject.toml` are what a user of the library installs against. After changing a dependency in `pyproject.toml` run `uv lock`: the `documentation` workflow syncs with `uv sync --locked`, which fails when `pyproject.toml` and the lock disagree. `uv lock --upgrade` moves the lock to the newest releases. Dependabot bumps the locked dependencies as one grouped monthly pull request, with `versioning-strategy: lockfile-only`, so the lower bounds in `pyproject.toml` are never raised by it and only ever changed by hand.
100
+
97
101
  The `dev` extra contains everything used below, i.e., pytest, ruff, ty, tox, pre-commit, zensical and bump-my-version, and it pulls in the optional `ontology` extra, so nothing has to be installed separately. The python version is taken from `.python-version` (currently 3.14); to work against the oldest supported version instead use `uv sync --extra dev --python 3.11`, which replaces the environment.
98
102
 
99
103
  The tools are then run either with `uv run <command>`, which uses the environment without activating it, or from the activated environment:
@@ -127,7 +131,7 @@ and the complete matrix, including the `ty` environment, in parallel with
127
131
  tox run-parallel
128
132
  ```
129
133
 
130
- This needs the interpreters to be available, which uv installs with `uv python install 3.11 3.12 3.13 3.14 3.15`. Continuous integration runs the same environments as `uvx --with tox-uv tox -e py3.15`.
134
+ This needs the interpreters to be available, which uv installs with `uv python install 3.11 3.12 3.13 3.14 3.15`. It is the complete test and is run before a pull request is opened: continuous integration runs only `py3.14`, on linux, macos and windows, as `uvx --with tox-uv tox -e py3.14 -- -n auto --durations=15`, i.e., with the tests distributed over the cores of the runner by pytest-xdist and the 15 slowest tests listed. What follows `--` is passed on to pytest, so `tox r -e py3.14 -- -n auto` does the same locally.
131
135
 
132
136
  To run the tests directly against the development environment use
133
137
 
@@ -148,6 +152,8 @@ ruff check # lint
148
152
  ruff format # format
149
153
  ```
150
154
 
155
+ The `ruff` workflow installs the ruff version locked in `uv.lock`, so continuous integration and `uv run ruff` agree.
156
+
151
157
  ## Type checking
152
158
 
153
159
  Type checking is performed with [ty](https://docs.astral.sh/ty/):
@@ -70,18 +70,18 @@ If you have any questions or issues please [open an issue](https://github.com/ma
70
70
 
71
71
  If you use `pymetadata` please cite the archived software on [Zenodo](https://doi.org/10.5281/zenodo.5308801):
72
72
 
73
- > König, M. (2026). *pymetadata are python utilities for working with metadata* (Version 0.6.6) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.22914125
73
+ > König, M. (2026). *pymetadata are python utilities for working with metadata* (Version 0.8.0) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.23159552
74
74
 
75
75
  ```bibtex
76
76
  @software{konig_pymetadata,
77
77
  author = {König, Matthias},
78
78
  title = {pymetadata are python utilities for working with metadata},
79
79
  year = {2026},
80
- month = sep,
81
- version = {0.6.6},
80
+ month = oct,
81
+ version = {0.8.0},
82
82
  publisher = {Zenodo},
83
- doi = {10.5281/zenodo.22914125},
84
- url = {https://doi.org/10.5281/zenodo.22914125},
83
+ doi = {10.5281/zenodo.23159552},
84
+ url = {https://doi.org/10.5281/zenodo.23159552},
85
85
  }
86
86
  ```
87
87
 
@@ -1,6 +1,6 @@
1
1
  # Installation
2
2
 
3
- `pymetadata` requires python >= 3.11 and is available from [pypi](https://pypi.python.org/pypi/pymetadata). It is pure python and tested with python 3.11 to 3.15 on Linux, macOS and Windows. The only compiled dependency is `pydantic-core`, which comes with [pydantic](https://docs.pydantic.dev/) and is installed from a wheel; for python 3.15 these wheels are part of pydantic 2.14, with an older pydantic it is built from source, which requires a Rust toolchain.
3
+ `pymetadata` requires python >= 3.11 and is available from [pypi](https://pypi.python.org/pypi/pymetadata). It is pure python and tested with python 3.11 to 3.15: continuous integration tests python 3.14 on Linux, macOS and Windows, all supported versions are tested locally on Linux before every pull request. The only compiled dependency is `pydantic-core`, which comes with [pydantic](https://docs.pydantic.dev/) and is installed from a wheel; for python 3.15 these wheels are part of pydantic 2.14, with an older pydantic it is built from source, which requires a Rust toolchain.
4
4
 
5
5
  ## With uv
6
6
 
@@ -103,6 +103,12 @@ Using the cache from 1080.0 h ago, it could not be refreshed:
103
103
 
104
104
  A query which was answered before therefore keeps working offline. Only a query which was never cached fails: `ChebiQuery.query` and `OLSQuery.query_ols` report the problem in their result, `UnichemQuery` and `Registry` raise a `WebserviceError`.
105
105
 
106
+ ### Several processes
107
+
108
+ Processes which run at the same time can share the cache, e.g., the workers of [pytest-xdist](https://pytest-xdist.readthedocs.io). A cache file is written to a temporary file in the same directory, which then replaces the cache file atomically, so a process never reads a partially written file. Processes which start on an empty cache each download what they need once, e.g., the registry.
109
+
110
+ Writing the cache is best effort, the process has the content already: a cache file which cannot be written is a warning, and the query returns its result anyway. On Windows a file which another process has open cannot be replaced, and a file which another process replaces cannot be opened; both are retried for about a second, after which the cache file of the other process is kept.
111
+
106
112
  ### The registry
107
113
 
108
114
  The identifiers.org registry is cached independently of `CACHE_USE`. It is downloaded to `CACHE_PATH / "identifiers_registry.json"` and refreshed when the local copy is older than the cache duration:
@@ -41,7 +41,10 @@ dependencies = [
41
41
  "rich>=15.0.0",
42
42
  "requests>=2.34.2",
43
43
  "urllib3>=2.5.0",
44
- "pydantic>=2.13.5",
44
+ # not imported, reached through requests; the floor excludes the CA store
45
+ # with the compromised emSign intermediates, GHSA-6q48-6c7w-9gw2
46
+ "certifi>=2026.10.19",
47
+ "pydantic>=2.12",
45
48
  ]
46
49
 
47
50
  [project.optional-dependencies]
@@ -0,0 +1,20 @@
1
+ # Release notes for pymetadata 0.8.1
2
+ ![pymetadata](./docs/images/favicon/pymetadata-100x100-300dpi.png)
3
+
4
+ ## Dependencies
5
+
6
+ - `pydantic>=2.12` instead of `pydantic>=2.13.5` (#105). The lower bound was the newest release when the bounds were pinned, not a requirement: the tests pass with pydantic 2.12.0 on python 3.11 and 3.14. The strict bound made pymetadata uninstallable with pip next to `pydantic-numpy` 9.0.2 (which requires `pydantic~=2.12.5`, and is the only release pip can install on python 3.14), e.g. in `sbmlsim[sciml]` through `petab-sciml`.
7
+
8
+ ## Fixes
9
+
10
+ - Processes which load the identifiers.org registry into the same empty cache at the same time, e.g., the workers of pytest-xdist, no longer fail on Windows with `PermissionError: [WinError 5] Access is denied` (#102). A cache file which another process has open is retried for about a second, and a cache file which cannot be written is a warning instead of an error, the query returns its result anyway. `Registry` uses the namespaces it downloaded instead of reading them back from the cache.
11
+ - Reading a cache file which another process replaces at the same moment is retried on Windows.
12
+ - Cache files have the permissions of a regular file again (`0o666` minus the umask) instead of being readable only by their owner, so a cache directory can be shared.
13
+ - A corrupt cached registry is downloaded again instead of failing.
14
+
15
+ ## Development
16
+
17
+ - The lock of the development environment, `uv.lock`, is tracked, and continuous integration installs it (#101).
18
+ - Continuous integration runs with less load (#104).
19
+
20
+ Your pymetadata team
@@ -0,0 +1,9 @@
1
+ # Release notes for pymetadata 0.8.2
2
+ ![pymetadata](./docs/images/favicon/pymetadata-100x100-300dpi.png)
3
+
4
+ ## Security
5
+
6
+ - `certifi>=2026.10.19` is a runtime dependency (#106). certifi 2026.10.19 removes the emSign root CA, whose intermediates have compromised keys ([GHSA-6q48-6c7w-9gw2](https://github.com/advisories/GHSA-6q48-6c7w-9gw2)). pymetadata reaches the web services through `requests`, which verifies the certificates with the CA store of certifi, so the floor applies although certifi is not imported.
7
+ - The lock of the development environment, `uv.lock`, has certifi 2026.10.19 and virtualenv 21.14.12, which seeds pip 26.2.2 (vendoring certifi 2026.10.19) into the environments of tox (#106). uv is pinned nowhere: continuous integration installs the latest uv, 0.13.4 or newer, which fixes its bundled CA store ([GHSA-hq85-5cpj-mr62](https://github.com/advisories/GHSA-hq85-5cpj-mr62)); a local uv older than 0.13.4 should be updated.
8
+
9
+ Your pymetadata team
@@ -7,7 +7,7 @@ from pathlib import Path
7
7
  logging.getLogger(__name__).addHandler(logging.NullHandler())
8
8
 
9
9
  __author__ = "Matthias Koenig"
10
- __version__ = "0.8.0"
10
+ __version__ = "0.8.2"
11
11
 
12
12
 
13
13
  program_name: str = "pymetadata"