silkroute 0.1.0__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 (289) hide show
  1. silkroute-0.1.0/.github/workflows/pre-commit.yml +17 -0
  2. silkroute-0.1.0/.github/workflows/publish-pypi.yml +68 -0
  3. silkroute-0.1.0/.github/workflows/refresh-fixtures.yml +167 -0
  4. silkroute-0.1.0/.github/workflows/tests.yml +34 -0
  5. silkroute-0.1.0/.gitignore +67 -0
  6. silkroute-0.1.0/AGENTS.md +69 -0
  7. silkroute-0.1.0/CLAUDE.md +1 -0
  8. silkroute-0.1.0/DEVELOPMENT.md +196 -0
  9. silkroute-0.1.0/LICENSE +21 -0
  10. silkroute-0.1.0/PKG-INFO +510 -0
  11. silkroute-0.1.0/README.md +467 -0
  12. silkroute-0.1.0/TODO.md +63 -0
  13. silkroute-0.1.0/docs/workflow_yaml.md +811 -0
  14. silkroute-0.1.0/examples/API_usage_demo.ipynb +30953 -0
  15. silkroute-0.1.0/examples/activity_search_demo.ipynb +892 -0
  16. silkroute-0.1.0/examples/data/unknown_ids.csv +4 -0
  17. silkroute-0.1.0/examples/data/unknown_sequences.csv +3 -0
  18. silkroute-0.1.0/examples/new_interface_template.py +71 -0
  19. silkroute-0.1.0/examples/notebooks/01_workflow_yaml_validation.ipynb +137 -0
  20. silkroute-0.1.0/examples/notebooks/02_protein_query_first_workflow.ipynb +119 -0
  21. silkroute-0.1.0/examples/notebooks/03_query_composition_and_gui_metadata.ipynb +100 -0
  22. silkroute-0.1.0/examples/notebooks/04_compound_ic50_workflow.ipynb +112 -0
  23. silkroute-0.1.0/examples/notebooks/05_metadata_and_summary_walkthrough.ipynb +113 -0
  24. silkroute-0.1.0/examples/uniprot_usage_demo.ipynb +1373 -0
  25. silkroute-0.1.0/examples/workflows/compound_chembl_ic50_ranges.yml +40 -0
  26. silkroute-0.1.0/examples/workflows/full_options_reference.yml +82 -0
  27. silkroute-0.1.0/examples/workflows/interaction_pli_chembl.yml +36 -0
  28. silkroute-0.1.0/examples/workflows/interaction_ppi_uniprot.yml +35 -0
  29. silkroute-0.1.0/examples/workflows/invalid/forbidden_version_key.yml +18 -0
  30. silkroute-0.1.0/examples/workflows/invalid/invalid_query_composition.yml +20 -0
  31. silkroute-0.1.0/examples/workflows/invalid/missing_schema_version.yml +15 -0
  32. silkroute-0.1.0/examples/workflows/invalid/unknown_top_level_section.yml +21 -0
  33. silkroute-0.1.0/examples/workflows/invalid/unsupported_schema_version.yml +17 -0
  34. silkroute-0.1.0/examples/workflows/protein_query_composition_labels.yml +40 -0
  35. silkroute-0.1.0/examples/workflows/protein_query_first_minimal.yml +31 -0
  36. silkroute-0.1.0/examples/workflows/protein_query_first_with_fields.yml +39 -0
  37. silkroute-0.1.0/examples/workflows/protein_query_first_with_gui_metadata.yml +47 -0
  38. silkroute-0.1.0/examples/workflows_demo.ipynb +2339 -0
  39. silkroute-0.1.0/prek.toml +37 -0
  40. silkroute-0.1.0/pyproject.toml +164 -0
  41. silkroute-0.1.0/silkroute/__init__.py +116 -0
  42. silkroute-0.1.0/silkroute/cli/__init__.py +8 -0
  43. silkroute-0.1.0/silkroute/cli/_shared.py +396 -0
  44. silkroute-0.1.0/silkroute/cli/collect_data.py +67 -0
  45. silkroute-0.1.0/silkroute/cli/helper_commands.py +99 -0
  46. silkroute-0.1.0/silkroute/cli/interfaces/__init__.py +1 -0
  47. silkroute-0.1.0/silkroute/cli/interfaces/alphafold.py +35 -0
  48. silkroute-0.1.0/silkroute/cli/interfaces/biodbnet.py +71 -0
  49. silkroute-0.1.0/silkroute/cli/interfaces/biogrid.py +39 -0
  50. silkroute-0.1.0/silkroute/cli/interfaces/brenda.py +345 -0
  51. silkroute-0.1.0/silkroute/cli/interfaces/chebi.py +106 -0
  52. silkroute-0.1.0/silkroute/cli/interfaces/chembl.py +51 -0
  53. silkroute-0.1.0/silkroute/cli/interfaces/chemical_search_query.py +254 -0
  54. silkroute-0.1.0/silkroute/cli/interfaces/genontology.py +27 -0
  55. silkroute-0.1.0/silkroute/cli/interfaces/interpro.py +48 -0
  56. silkroute-0.1.0/silkroute/cli/interfaces/kegg.py +41 -0
  57. silkroute-0.1.0/silkroute/cli/interfaces/panther.py +74 -0
  58. silkroute-0.1.0/silkroute/cli/interfaces/pathwaycommons.py +116 -0
  59. silkroute-0.1.0/silkroute/cli/interfaces/pride.py +70 -0
  60. silkroute-0.1.0/silkroute/cli/interfaces/proteindatabank.py +30 -0
  61. silkroute-0.1.0/silkroute/cli/interfaces/pubchem.py +201 -0
  62. silkroute-0.1.0/silkroute/cli/interfaces/reactome.py +36 -0
  63. silkroute-0.1.0/silkroute/cli/interfaces/refseq.py +56 -0
  64. silkroute-0.1.0/silkroute/cli/interfaces/rhea.py +27 -0
  65. silkroute-0.1.0/silkroute/cli/interfaces/stringdb.py +50 -0
  66. silkroute-0.1.0/silkroute/cli/interfaces/uniprot.py +18 -0
  67. silkroute-0.1.0/silkroute/cli/interfaces/uniprot_crossref.py +130 -0
  68. silkroute-0.1.0/silkroute/cli/interfaces/uniprot_search_ids.py +70 -0
  69. silkroute-0.1.0/silkroute/cli/interfaces/uniprot_search_query.py +74 -0
  70. silkroute-0.1.0/silkroute/cli/interfaces/uniprot_search_sequences.py +155 -0
  71. silkroute-0.1.0/silkroute/cli/main.py +42 -0
  72. silkroute-0.1.0/silkroute/cli/workflows.py +2138 -0
  73. silkroute-0.1.0/silkroute/config/.env.example +7 -0
  74. silkroute-0.1.0/silkroute/config/alphafold/fields.yml +7 -0
  75. silkroute-0.1.0/silkroute/config/alphafold/init.yml +1 -0
  76. silkroute-0.1.0/silkroute/config/biodbnet/fields.yml +157 -0
  77. silkroute-0.1.0/silkroute/config/biogrid/fields.yml +6 -0
  78. silkroute-0.1.0/silkroute/config/brenda/fields.yml +58 -0
  79. silkroute-0.1.0/silkroute/config/chebi/fields.yml +58 -0
  80. silkroute-0.1.0/silkroute/config/chembl/fields.yml +206 -0
  81. silkroute-0.1.0/silkroute/config/go/fields.yml +24 -0
  82. silkroute-0.1.0/silkroute/config/interpro/fields.yml +22 -0
  83. silkroute-0.1.0/silkroute/config/kegg/fields.yml +36 -0
  84. silkroute-0.1.0/silkroute/config/panther/fields.yml +5 -0
  85. silkroute-0.1.0/silkroute/config/pathwaycommons/fields.yml +91 -0
  86. silkroute-0.1.0/silkroute/config/pdb/fields.yml +7 -0
  87. silkroute-0.1.0/silkroute/config/pdb/init.yml +1 -0
  88. silkroute-0.1.0/silkroute/config/pride/fields.yml +90 -0
  89. silkroute-0.1.0/silkroute/config/pubchem/fields.yml +147 -0
  90. silkroute-0.1.0/silkroute/config/reactome/fields.yml +7 -0
  91. silkroute-0.1.0/silkroute/config/refseq/fields.yml +6 -0
  92. silkroute-0.1.0/silkroute/config/rhea/fields.yml +0 -0
  93. silkroute-0.1.0/silkroute/config/sabiork/fields.yml +0 -0
  94. silkroute-0.1.0/silkroute/config/string/fields.yml +18 -0
  95. silkroute-0.1.0/silkroute/config/uniprot_crossref/config_endpoints.yml +148 -0
  96. silkroute-0.1.0/silkroute/constants/__init__.py +1 -0
  97. silkroute-0.1.0/silkroute/constants/biodbnet.py +40 -0
  98. silkroute-0.1.0/silkroute/constants/brenda.py +166 -0
  99. silkroute-0.1.0/silkroute/constants/databases.py +69 -0
  100. silkroute-0.1.0/silkroute/constants/interpro.py +19 -0
  101. silkroute-0.1.0/silkroute/constants/kegg.py +26 -0
  102. silkroute-0.1.0/silkroute/constants/pathwaycommons.py +47 -0
  103. silkroute-0.1.0/silkroute/constants/pubchem.py +53 -0
  104. silkroute-0.1.0/silkroute/constants/reactome.py +14 -0
  105. silkroute-0.1.0/silkroute/constants/refseq.py +3 -0
  106. silkroute-0.1.0/silkroute/constants/stringdb.py +59 -0
  107. silkroute-0.1.0/silkroute/constants/uniprot.py +189 -0
  108. silkroute-0.1.0/silkroute/core/__init__.py +1 -0
  109. silkroute-0.1.0/silkroute/core/cache.py +241 -0
  110. silkroute-0.1.0/silkroute/core/credentials.py +127 -0
  111. silkroute-0.1.0/silkroute/core/crossref_enricher.py +962 -0
  112. silkroute-0.1.0/silkroute/core/dbconfig.py +21 -0
  113. silkroute-0.1.0/silkroute/core/exceptions.py +42 -0
  114. silkroute-0.1.0/silkroute/core/export.py +210 -0
  115. silkroute-0.1.0/silkroute/core/interfaces/__init__.py +1 -0
  116. silkroute-0.1.0/silkroute/core/interfaces/alphafold.py +323 -0
  117. silkroute-0.1.0/silkroute/core/interfaces/base.py +1496 -0
  118. silkroute-0.1.0/silkroute/core/interfaces/biodbnet.py +62 -0
  119. silkroute-0.1.0/silkroute/core/interfaces/biogrid.py +122 -0
  120. silkroute-0.1.0/silkroute/core/interfaces/brenda.py +148 -0
  121. silkroute-0.1.0/silkroute/core/interfaces/chebi.py +162 -0
  122. silkroute-0.1.0/silkroute/core/interfaces/chembl.py +669 -0
  123. silkroute-0.1.0/silkroute/core/interfaces/genontology.py +133 -0
  124. silkroute-0.1.0/silkroute/core/interfaces/interpro.py +185 -0
  125. silkroute-0.1.0/silkroute/core/interfaces/kegg.py +322 -0
  126. silkroute-0.1.0/silkroute/core/interfaces/panther.py +58 -0
  127. silkroute-0.1.0/silkroute/core/interfaces/pathwaycommons.py +92 -0
  128. silkroute-0.1.0/silkroute/core/interfaces/pride.py +74 -0
  129. silkroute-0.1.0/silkroute/core/interfaces/proteindatabank.py +314 -0
  130. silkroute-0.1.0/silkroute/core/interfaces/pubchem.py +679 -0
  131. silkroute-0.1.0/silkroute/core/interfaces/reactome.py +131 -0
  132. silkroute-0.1.0/silkroute/core/interfaces/refseq.py +128 -0
  133. silkroute-0.1.0/silkroute/core/interfaces/rhea.py +35 -0
  134. silkroute-0.1.0/silkroute/core/interfaces/sabiork.py +447 -0
  135. silkroute-0.1.0/silkroute/core/interfaces/stringdb.py +99 -0
  136. silkroute-0.1.0/silkroute/core/interfaces/uniprot.py +911 -0
  137. silkroute-0.1.0/silkroute/core/interfacesconfig.py +40 -0
  138. silkroute-0.1.0/silkroute/core/metadata.py +299 -0
  139. silkroute-0.1.0/silkroute/core/utils/__init__.py +1 -0
  140. silkroute-0.1.0/silkroute/core/utils/base_auxiliary_methods.py +111 -0
  141. silkroute-0.1.0/silkroute/core/utils/blast_search.py +215 -0
  142. silkroute-0.1.0/silkroute/core/utils/crossref_enrichment.py +410 -0
  143. silkroute-0.1.0/silkroute/core/utils/frames.py +59 -0
  144. silkroute-0.1.0/silkroute/core/utils/query_builders.py +415 -0
  145. silkroute-0.1.0/silkroute/core/utils/structure_files.py +64 -0
  146. silkroute-0.1.0/silkroute/core/utils/uniprot_auxiliary_methods.py +341 -0
  147. silkroute-0.1.0/silkroute/core/utils/xmlhandler.py +143 -0
  148. silkroute-0.1.0/silkroute/core/workflow/__init__.py +1 -0
  149. silkroute-0.1.0/silkroute/core/workflow/chebi_execution.py +165 -0
  150. silkroute-0.1.0/silkroute/core/workflow/chebi_query_catalog.py +119 -0
  151. silkroute-0.1.0/silkroute/core/workflow/chebi_query_parser.py +78 -0
  152. silkroute-0.1.0/silkroute/core/workflow/chembl_query_catalog.py +416 -0
  153. silkroute-0.1.0/silkroute/core/workflow/chembl_query_parser.py +97 -0
  154. silkroute-0.1.0/silkroute/core/workflow/main_workflow.py +1696 -0
  155. silkroute-0.1.0/silkroute/core/workflow/pubchem_execution.py +204 -0
  156. silkroute-0.1.0/silkroute/core/workflow/pubchem_query_catalog.py +176 -0
  157. silkroute-0.1.0/silkroute/core/workflow/pubchem_query_parser.py +145 -0
  158. silkroute-0.1.0/silkroute/core/workflow/query_field_catalog.py +244 -0
  159. silkroute-0.1.0/silkroute/core/workflow/query_interpreter.py +716 -0
  160. silkroute-0.1.0/silkroute/core/workflow/query_prefixes.py +53 -0
  161. silkroute-0.1.0/silkroute/core/workflow/schema.py +1078 -0
  162. silkroute-0.1.0/silkroute/gui/__init__.py +24 -0
  163. silkroute-0.1.0/silkroute/gui/form_helpers.py +828 -0
  164. silkroute-0.1.0/silkroute/gui/nicegui_app.py +2053 -0
  165. silkroute-0.1.0/silkroute/gui/query_builders/__init__.py +5 -0
  166. silkroute-0.1.0/silkroute/gui/query_builders/chebi.py +71 -0
  167. silkroute-0.1.0/silkroute/gui/query_builders/chembl.py +356 -0
  168. silkroute-0.1.0/silkroute/gui/query_builders/common.py +17 -0
  169. silkroute-0.1.0/silkroute/gui/query_builders/metadata.py +550 -0
  170. silkroute-0.1.0/silkroute/gui/query_builders/pubchem.py +107 -0
  171. silkroute-0.1.0/silkroute/gui/query_builders/registry.py +230 -0
  172. silkroute-0.1.0/silkroute/gui/query_builders/uniprot.py +140 -0
  173. silkroute-0.1.0/silkroute/gui/uniprot_return_fields.py +99 -0
  174. silkroute-0.1.0/silkroute/gui/yaml_builder.py +1795 -0
  175. silkroute-0.1.0/silkroute/logging/__init__.py +16 -0
  176. silkroute-0.1.0/silkroute/logging/logger.py +266 -0
  177. silkroute-0.1.0/tests/__init__.py +0 -0
  178. silkroute-0.1.0/tests/_capture/__init__.py +4 -0
  179. silkroute-0.1.0/tests/_capture/capture.py +379 -0
  180. silkroute-0.1.0/tests/_helpers.py +143 -0
  181. silkroute-0.1.0/tests/cli/__init__.py +0 -0
  182. silkroute-0.1.0/tests/cli/test_app_structure.py +36 -0
  183. silkroute-0.1.0/tests/cli/test_fetch_metadata_flag.py +49 -0
  184. silkroute-0.1.0/tests/cli/test_graph_externalization.py +168 -0
  185. silkroute-0.1.0/tests/cli/test_logging_apply.py +20 -0
  186. silkroute-0.1.0/tests/cli/test_shared.py +180 -0
  187. silkroute-0.1.0/tests/cli/test_workflow_example_configs.py +127 -0
  188. silkroute-0.1.0/tests/cli/test_workflow_invalid_examples.py +31 -0
  189. silkroute-0.1.0/tests/cli/test_workflow_notebooks.py +29 -0
  190. silkroute-0.1.0/tests/cli/test_workflow_schema.py +405 -0
  191. silkroute-0.1.0/tests/cli/test_workflow_validate.py +174 -0
  192. silkroute-0.1.0/tests/cli/test_workflows_validation.py +405 -0
  193. silkroute-0.1.0/tests/conftest.py +10 -0
  194. silkroute-0.1.0/tests/core/__init__.py +0 -0
  195. silkroute-0.1.0/tests/core/interfaces/__init__.py +0 -0
  196. silkroute-0.1.0/tests/core/interfaces/_contract.py +70 -0
  197. silkroute-0.1.0/tests/core/interfaces/test_alphafold.py +53 -0
  198. silkroute-0.1.0/tests/core/interfaces/test_base_transforms.py +338 -0
  199. silkroute-0.1.0/tests/core/interfaces/test_biodbnet.py +65 -0
  200. silkroute-0.1.0/tests/core/interfaces/test_biogrid.py +55 -0
  201. silkroute-0.1.0/tests/core/interfaces/test_brenda.py +72 -0
  202. silkroute-0.1.0/tests/core/interfaces/test_characterization_base.py +166 -0
  203. silkroute-0.1.0/tests/core/interfaces/test_chebi.py +45 -0
  204. silkroute-0.1.0/tests/core/interfaces/test_chembl.py +151 -0
  205. silkroute-0.1.0/tests/core/interfaces/test_chembl_filters.py +120 -0
  206. silkroute-0.1.0/tests/core/interfaces/test_fetch_batch_cache.py +63 -0
  207. silkroute-0.1.0/tests/core/interfaces/test_genontology.py +44 -0
  208. silkroute-0.1.0/tests/core/interfaces/test_interpro_fetch.py +49 -0
  209. silkroute-0.1.0/tests/core/interfaces/test_kegg.py +53 -0
  210. silkroute-0.1.0/tests/core/interfaces/test_metadata_provenance.py +50 -0
  211. silkroute-0.1.0/tests/core/interfaces/test_panther.py +47 -0
  212. silkroute-0.1.0/tests/core/interfaces/test_pathwaycommons.py +61 -0
  213. silkroute-0.1.0/tests/core/interfaces/test_pride.py +44 -0
  214. silkroute-0.1.0/tests/core/interfaces/test_proteindatabank.py +83 -0
  215. silkroute-0.1.0/tests/core/interfaces/test_pubchem.py +86 -0
  216. silkroute-0.1.0/tests/core/interfaces/test_pubchem_parsing.py +153 -0
  217. silkroute-0.1.0/tests/core/interfaces/test_reactome.py +34 -0
  218. silkroute-0.1.0/tests/core/interfaces/test_reactome_fetch.py +48 -0
  219. silkroute-0.1.0/tests/core/interfaces/test_refseq.py +68 -0
  220. silkroute-0.1.0/tests/core/interfaces/test_response_field_coverage.py +388 -0
  221. silkroute-0.1.0/tests/core/interfaces/test_rhea.py +64 -0
  222. silkroute-0.1.0/tests/core/interfaces/test_sabiork.py +144 -0
  223. silkroute-0.1.0/tests/core/interfaces/test_stringdb.py +48 -0
  224. silkroute-0.1.0/tests/core/interfaces/test_uniprot.py +143 -0
  225. silkroute-0.1.0/tests/core/test_application_identity.py +22 -0
  226. silkroute-0.1.0/tests/core/test_cache.py +81 -0
  227. silkroute-0.1.0/tests/core/test_characterization_crossref.py +100 -0
  228. silkroute-0.1.0/tests/core/test_characterization_export.py +74 -0
  229. silkroute-0.1.0/tests/core/test_credentials.py +69 -0
  230. silkroute-0.1.0/tests/core/test_crossref_graph_xml.py +51 -0
  231. silkroute-0.1.0/tests/core/test_crossref_per_row.py +41 -0
  232. silkroute-0.1.0/tests/core/test_exceptions.py +28 -0
  233. silkroute-0.1.0/tests/core/test_export.py +106 -0
  234. silkroute-0.1.0/tests/core/test_metadata.py +111 -0
  235. silkroute-0.1.0/tests/core/utils/__init__.py +0 -0
  236. silkroute-0.1.0/tests/core/utils/test_base_auxiliary_methods.py +56 -0
  237. silkroute-0.1.0/tests/core/utils/test_blast_search.py +98 -0
  238. silkroute-0.1.0/tests/core/utils/test_characterization_query_builders.py +74 -0
  239. silkroute-0.1.0/tests/core/utils/test_characterization_xmlhandler.py +71 -0
  240. silkroute-0.1.0/tests/core/utils/test_crossref_enrichment.py +111 -0
  241. silkroute-0.1.0/tests/core/utils/test_query_builders.py +69 -0
  242. silkroute-0.1.0/tests/core/utils/test_uniprot_auxiliary_methods.py +208 -0
  243. silkroute-0.1.0/tests/core/utils/test_validate_parameters.py +54 -0
  244. silkroute-0.1.0/tests/core/utils/test_xmlhandler.py +64 -0
  245. silkroute-0.1.0/tests/core/workflow/__init__.py +0 -0
  246. silkroute-0.1.0/tests/core/workflow/test_compound_query_parsers.py +47 -0
  247. silkroute-0.1.0/tests/core/workflow/test_compound_routing.py +65 -0
  248. silkroute-0.1.0/tests/core/workflow/test_labeling.py +63 -0
  249. silkroute-0.1.0/tests/core/workflow/test_query_interpreter.py +123 -0
  250. silkroute-0.1.0/tests/core/workflow/test_schema.py +176 -0
  251. silkroute-0.1.0/tests/core/workflow/test_structure_download_validation.py +38 -0
  252. silkroute-0.1.0/tests/core/workflow/test_workflow_helpers.py +223 -0
  253. silkroute-0.1.0/tests/core/workflow/test_workflow_run.py +450 -0
  254. silkroute-0.1.0/tests/fixtures/_field_coverage_baseline.json +175 -0
  255. silkroute-0.1.0/tests/fixtures/alphafold/prediction.json +51 -0
  256. silkroute-0.1.0/tests/fixtures/biodbnet/getpathways.json +626 -0
  257. silkroute-0.1.0/tests/fixtures/biogrid/interactions.json +28 -0
  258. silkroute-0.1.0/tests/fixtures/brenda/getKmValue.json +2174 -0
  259. silkroute-0.1.0/tests/fixtures/chebi/compound.json +600 -0
  260. silkroute-0.1.0/tests/fixtures/chembl/activity.json +65 -0
  261. silkroute-0.1.0/tests/fixtures/genontology/term.json +31 -0
  262. silkroute-0.1.0/tests/fixtures/interpro/entry.json +213 -0
  263. silkroute-0.1.0/tests/fixtures/kegg/get.json +1 -0
  264. silkroute-0.1.0/tests/fixtures/panther/geneinfo.json +1131 -0
  265. silkroute-0.1.0/tests/fixtures/pathwaycommons/fetch.json +31 -0
  266. silkroute-0.1.0/tests/fixtures/pdb/entry.json +1258 -0
  267. silkroute-0.1.0/tests/fixtures/pride/project.json +128 -0
  268. silkroute-0.1.0/tests/fixtures/pubchem/pug_view_compound.json +575 -0
  269. silkroute-0.1.0/tests/fixtures/reactome/discover.json +125 -0
  270. silkroute-0.1.0/tests/fixtures/refseq/protein.json +1880 -0
  271. silkroute-0.1.0/tests/fixtures/rhea/reaction.json +14 -0
  272. silkroute-0.1.0/tests/fixtures/sabiork/kineticlaws.json +2414 -0
  273. silkroute-0.1.0/tests/fixtures/stringdb/get_string_ids.json +11 -0
  274. silkroute-0.1.0/tests/fixtures/uniprot/idmapping_results.json +1978 -0
  275. silkroute-0.1.0/tests/gui/__init__.py +1 -0
  276. silkroute-0.1.0/tests/gui/test_chembl_query_builder.py +109 -0
  277. silkroute-0.1.0/tests/gui/test_form_helpers.py +156 -0
  278. silkroute-0.1.0/tests/gui/test_query_builder_metadata.py +44 -0
  279. silkroute-0.1.0/tests/gui/test_query_builder_registry.py +94 -0
  280. silkroute-0.1.0/tests/gui/test_uniprot_query_builder.py +114 -0
  281. silkroute-0.1.0/tests/gui/test_yaml_builder.py +1758 -0
  282. silkroute-0.1.0/tests/test_chembl_query_field_catalog.py +20 -0
  283. silkroute-0.1.0/tests/test_chembl_query_parser.py +35 -0
  284. silkroute-0.1.0/tests/test_package.py +42 -0
  285. silkroute-0.1.0/tests/test_uniprot_query_field_catalog.py +36 -0
  286. silkroute-0.1.0/tests/test_uniprot_query_interpreter.py +79 -0
  287. silkroute-0.1.0/tests/test_uniprot_return_fields.py +34 -0
  288. silkroute-0.1.0/tests/test_workflow_routing.py +183 -0
  289. silkroute-0.1.0/uv.lock +2649 -0
@@ -0,0 +1,17 @@
1
+ name: pre-commit
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ prek:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v7
12
+ - uses: astral-sh/setup-uv@v9.0.0
13
+ with:
14
+ python-version: "3.12"
15
+ - name: Install dependencies
16
+ run: uv sync --extra dev --extra tests
17
+ - uses: j178/prek-action@v2
@@ -0,0 +1,68 @@
1
+ name: publish-pypi
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: publish-pypi-${{ github.ref }}
14
+ cancel-in-progress: false
15
+
16
+ jobs:
17
+ build:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v7
21
+ - uses: astral-sh/setup-uv@v9.0.0
22
+ with:
23
+ python-version: "3.12"
24
+
25
+ # The version is dynamic (hatch reads silkroute/__init__.py), so a tag can
26
+ # disagree with the package. Catch that before anything reaches PyPI, where
27
+ # a filename is permanent.
28
+ - name: Check the tag matches __version__
29
+ if: startsWith(github.ref, 'refs/tags/v')
30
+ env:
31
+ TAG: ${{ github.ref_name }}
32
+ run: |
33
+ version="$(sed -n 's/^__version__ = "\(.*\)"$/\1/p' silkroute/__init__.py)"
34
+ if [ -z "$version" ]; then
35
+ echo "::error::could not read __version__ from silkroute/__init__.py"
36
+ exit 1
37
+ fi
38
+ if [ "$TAG" != "v$version" ]; then
39
+ echo "::error::tag $TAG does not match silkroute.__version__ ($version)"
40
+ exit 1
41
+ fi
42
+
43
+ - name: Build distributions
44
+ run: uv build
45
+
46
+ - name: Upload distributions
47
+ uses: actions/upload-artifact@v7
48
+ with:
49
+ name: python-package-distributions
50
+ path: dist/
51
+
52
+ publish:
53
+ if: startsWith(github.ref, 'refs/tags/v')
54
+ needs: build
55
+ runs-on: ubuntu-latest
56
+ environment:
57
+ name: pypi
58
+ url: https://pypi.org/p/silkroute
59
+ permissions:
60
+ id-token: write
61
+ steps:
62
+ - name: Download distributions
63
+ uses: actions/download-artifact@v8
64
+ with:
65
+ name: python-package-distributions
66
+ path: dist/
67
+ - name: Publish package distributions to PyPI
68
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,167 @@
1
+ name: refresh-fixtures
2
+
3
+ # Re-captures the frozen API fixtures in tests/fixtures/ from the live APIs twice
4
+ # a month. Clean drift (offline suite still green) is committed straight to `dev`;
5
+ # breaking drift goes to a PR against `dev` for a human to reconcile. Never runs
6
+ # on push/PR: the offline test suite must stay offline.
7
+ #
8
+ # This file must live on the default branch for `schedule` to fire at all, but the
9
+ # capture itself always runs against `dev` (see the checkout `ref` below).
10
+ on:
11
+ schedule:
12
+ # 06:00 UTC on the 1st and the 15th.
13
+ - cron: "0 6 1,15 * *"
14
+ workflow_dispatch:
15
+ inputs:
16
+ apis:
17
+ description: "Space-separated API names to capture (empty = all)"
18
+ required: false
19
+ default: ""
20
+
21
+ permissions:
22
+ contents: write
23
+ pull-requests: write
24
+
25
+ concurrency:
26
+ group: refresh-fixtures
27
+ cancel-in-progress: false
28
+
29
+ env:
30
+ TARGET: dev
31
+ PR_BRANCH: chore/refresh-fixtures
32
+
33
+ jobs:
34
+ capture:
35
+ runs-on: ubuntu-latest
36
+ steps:
37
+ - uses: actions/checkout@v7
38
+ with:
39
+ ref: dev
40
+
41
+ - uses: astral-sh/setup-uv@v9.0.0
42
+ with:
43
+ python-version: "3.12"
44
+
45
+ - name: Install dependencies
46
+ run: uv sync --extra dev --extra tests
47
+
48
+ - name: Validate api selection
49
+ env:
50
+ APIS: ${{ inputs.apis }}
51
+ run: |
52
+ if [ -n "$APIS" ] && ! printf '%s' "$APIS" | grep -qE '^[a-z0-9 ]+$'; then
53
+ echo "::error::invalid apis input: $APIS"
54
+ exit 1
55
+ fi
56
+
57
+ # Credentialed captures (biogrid, refseq, brenda) skip themselves with a log
58
+ # line when their secret is absent, so unset secrets are not an error.
59
+ - name: Capture fixtures
60
+ id: capture
61
+ continue-on-error: true
62
+ env:
63
+ SILKROUTE_CAPTURE: "1"
64
+ APIS: ${{ inputs.apis }}
65
+ SILKROUTE_BIOGRID_API_KEY: ${{ secrets.SILKROUTE_BIOGRID_API_KEY }}
66
+ SILKROUTE_REFSEQ_EMAIL: ${{ secrets.SILKROUTE_REFSEQ_EMAIL }}
67
+ SILKROUTE_BRENDA_EMAIL: ${{ secrets.SILKROUTE_BRENDA_EMAIL }}
68
+ SILKROUTE_BRENDA_PASSWORD: ${{ secrets.SILKROUTE_BRENDA_PASSWORD }}
69
+ run: |
70
+ # shellcheck disable=SC2086 # intentional word splitting: APIS is a list
71
+ uv run python -m tests._capture.capture $APIS 2>&1 | tee capture.log
72
+
73
+ - name: Detect drift
74
+ id: drift
75
+ run: |
76
+ if [ -n "$(git status --porcelain tests/fixtures)" ]; then
77
+ echo "changed=true" >> "$GITHUB_OUTPUT"
78
+ git --no-pager diff --stat tests/fixtures
79
+ else
80
+ echo "changed=false" >> "$GITHUB_OUTPUT"
81
+ fi
82
+
83
+ - name: Run offline test suite against the new fixtures
84
+ id: tests
85
+ if: steps.drift.outputs.changed == 'true'
86
+ continue-on-error: true
87
+ run: uv run pytest -q 2>&1 | tail -n 60 | tee pytest.log
88
+
89
+ - name: Configure git
90
+ if: steps.drift.outputs.changed == 'true'
91
+ run: |
92
+ git config user.name "github-actions[bot]"
93
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
94
+
95
+ # Suite still green on the fresh fixtures -> nothing for a human to decide.
96
+ - name: Commit to dev
97
+ if: steps.drift.outputs.changed == 'true' && steps.tests.outcome == 'success'
98
+ run: |
99
+ set -euo pipefail
100
+ git add tests/fixtures
101
+ git commit -m "test: refresh API fixtures from live APIs"
102
+ # Rebase onto whatever landed on dev while the capture was running; the
103
+ # commit only touches tests/fixtures so a conflict here is a real one.
104
+ git pull --rebase origin "$TARGET"
105
+ git push origin "HEAD:$TARGET"
106
+
107
+ # Suite broke -> an API changed shape. Park it on a branch and let a human
108
+ # reconcile the assertions.
109
+ - name: Open pull request
110
+ if: steps.drift.outputs.changed == 'true' && steps.tests.outcome != 'success'
111
+ env:
112
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
113
+ CAPTURE_OUTCOME: ${{ steps.capture.outcome }}
114
+ TESTS_OUTCOME: ${{ steps.tests.outcome }}
115
+ run: |
116
+ set -euo pipefail
117
+ git switch -c "$PR_BRANCH"
118
+ git add tests/fixtures
119
+ git commit -m "test: refresh API fixtures from live APIs"
120
+ git push --force origin "$PR_BRANCH"
121
+
122
+ {
123
+ echo "Automated re-capture of \`tests/fixtures/\` from the live APIs."
124
+ echo
125
+ echo "- capture step: **$CAPTURE_OUTCOME**"
126
+ echo "- offline suite on the new fixtures: **$TESTS_OUTCOME**"
127
+ echo
128
+ echo "The suite no longer passes on the fresh fixtures, so this drift was"
129
+ echo "**not** committed to \`$TARGET\` directly. An API changed shape: update"
130
+ echo "the affected assertions on this branch (and re-run"
131
+ echo "\`REGEN_FIELD_BASELINE=1 uv run pytest\` if the field-coverage baseline"
132
+ echo "moved) before merging."
133
+ echo
134
+ echo "<details><summary>capture log</summary>"
135
+ echo
136
+ echo '```'
137
+ tail -n 60 capture.log
138
+ echo '```'
139
+ echo
140
+ echo "</details>"
141
+ if [ -f pytest.log ]; then
142
+ echo
143
+ echo "<details><summary>pytest tail</summary>"
144
+ echo
145
+ echo '```'
146
+ cat pytest.log
147
+ echo '```'
148
+ echo
149
+ echo "</details>"
150
+ fi
151
+ } > pr-body.md
152
+
153
+ if [ -n "$(gh pr list --head "$PR_BRANCH" --state open --json number --jq '.[].number')" ]; then
154
+ gh pr edit "$PR_BRANCH" --body-file pr-body.md
155
+ else
156
+ gh pr create \
157
+ --head "$PR_BRANCH" \
158
+ --base "$TARGET" \
159
+ --title "test: refresh API fixtures (suite needs reconciling)" \
160
+ --body-file pr-body.md
161
+ fi
162
+
163
+ - name: Report capture failures
164
+ if: steps.capture.outcome == 'failure'
165
+ run: |
166
+ echo "::error::capture exited non-zero; see the capture log for the failing APIs"
167
+ exit 1
@@ -0,0 +1,34 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - "silkroute/**"
7
+ - "tests/**"
8
+ - "pyproject.toml"
9
+ - "uv.lock"
10
+ - ".github/workflows/tests.yml"
11
+ pull_request:
12
+ paths:
13
+ - "silkroute/**"
14
+ - "tests/**"
15
+ - "pyproject.toml"
16
+ - "uv.lock"
17
+ - ".github/workflows/tests.yml"
18
+
19
+ jobs:
20
+ tests:
21
+ runs-on: ubuntu-latest
22
+ strategy:
23
+ fail-fast: false
24
+ matrix:
25
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
26
+ steps:
27
+ - uses: actions/checkout@v7
28
+ - uses: astral-sh/setup-uv@v9.0.0
29
+ with:
30
+ python-version: ${{ matrix.python-version }}
31
+ - name: Install dependencies
32
+ run: uv sync --extra dev --extra tests --extra gui
33
+ - name: Run tests
34
+ run: uv run pytest -q
@@ -0,0 +1,67 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ .ipynb_checkpoints/
6
+
7
+ # Distribution / packaging
8
+ .Python
9
+ build/
10
+ develop-eggs/
11
+ dist/
12
+ downloads/
13
+ eggs/
14
+ .eggs/
15
+ lib/
16
+ lib64/
17
+ parts/
18
+ sdist/
19
+ var/
20
+ wheels/
21
+ share/python-wheels/
22
+ *.egg-info/
23
+ .installed.cfg
24
+ *.egg
25
+ MANIFEST
26
+
27
+ # Environments
28
+ .env
29
+ .venv
30
+ env/
31
+ venv/
32
+ ENV/
33
+ env.bak/
34
+ venv.bak/
35
+
36
+ # IDEs / Editors
37
+ .vscode/
38
+ .idea/
39
+ *.sublime-project
40
+ *.sublime-workspace
41
+
42
+
43
+ # Custom directories and files
44
+ input/
45
+ src/db
46
+ output/
47
+ tmp/
48
+ results/
49
+ src/.alphafold_cache/
50
+ src/.pdb_cache/
51
+
52
+ *.json
53
+ *.csv
54
+ *.cif
55
+ *.pdb
56
+ *.html
57
+ *.log
58
+ *.backup
59
+ *.parquet
60
+ .env
61
+
62
+ !examples/data/*.csv
63
+
64
+ # Test fixtures must be tracked despite the global *.json / *.csv rules above
65
+ !tests/**/*.json
66
+ !tests/**/*.csv
67
+ !tests/**/
@@ -0,0 +1,69 @@
1
+ # AGENTS.md
2
+
3
+ This file provides guidance to AI agents when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ **SilkRoute** is a Python library and CLI to download and integrate biological
8
+ data from many web APIs (UniProt, AlphaFold, BioGRID, KEGG, ChEMBL, Reactome, etc.).
9
+ It is part of the Kren AI Lab ecosystem alongside **Sylphy** (sequence encoders /
10
+ embeddings) and **Roxy** (classical descriptors).
11
+
12
+ Input: identifiers / queries per database. Output: parsed records as
13
+ `polars.DataFrame` / JSON / XML, with on-disk caching.
14
+
15
+ ## Package Layout
16
+
17
+ ```
18
+ silkroute/
19
+ __init__.py # public API (lazy via __getattr__) + __version__
20
+ cli/
21
+ main.py # Typer root app
22
+ interfaces/ # per-database CLI sub-apps
23
+ constants/ # per-database constants + DBConfig instances (databases.py)
24
+ core/
25
+ interfaces/
26
+ base.py # BaseAPIInterface (fetch_single/fetch_batch/cache/parse)
27
+ <db>.py # one client per database, subclass of BaseAPIInterface
28
+ utils/ # query builders, parsing helpers, BLAST
29
+ workflow/ # multi-step download workflows
30
+ cache.py, export.py, dbconfig.py, interfacesconfig.py
31
+ logging/ # get_logger, unified setup
32
+ tests/ # mirrors source tree, offline
33
+ examples/ # standalone demo scripts
34
+ ```
35
+
36
+ ## Development Commands
37
+
38
+ This project uses `uv` and `taskipy`.
39
+
40
+ ```bash
41
+ uv sync --extra dev --extra tests
42
+ uv run task test # pytest -q
43
+ uv run task lint # ruff check
44
+ uv run task lint-fix
45
+ uv run task format
46
+ uv run task ty # ty check
47
+ uv run task pyrefly
48
+ uv run silkroute --help
49
+ ```
50
+
51
+ ## Architecture Notes
52
+
53
+ - New API clients inherit from `BaseAPIInterface` and declare their `DBConfig`
54
+ (URL + cache/config dirs) from `constants/databases.py`.
55
+ - `fetch_single` / `fetch_batch` handle caching, optional parsing, and output
56
+ format conversion (json / dataframe / xml). `parse` + `fetch` are abstract.
57
+ - Per-database field extraction is config-driven (YAML in the config dir).
58
+
59
+ ## Key Invariants
60
+
61
+ - No import side effects: the top-level public API is lazy (`__getattr__`); importing
62
+ `silkroute` must not pull heavy deps (e.g. `zeep` for BRENDA).
63
+ - Use `logging` (`get_logger`), never `print`.
64
+ - A `fetch` override returns the empty of its own success type (a list endpoint
65
+ returns `[]`, an object endpoint `{}`); never `None`. The error-vs-empty reason
66
+ is recorded in `metadata.failed` (`request_error` / `empty_result`), not the
67
+ return value. (`chebi`/`pubchem` are genuinely method-polymorphic and return `{}`.)
68
+ - Tests run offline: HTTP is mocked (`niquests_mock`) behind `conftest` fixtures.
69
+ - Tests mirror the source layout.
@@ -0,0 +1 @@
1
+ AGENTS.md
@@ -0,0 +1,196 @@
1
+ # Development
2
+
3
+ This guide covers local setup, day-to-day commands, and the code structure behind
4
+ SilkRoute.
5
+
6
+ ## Local Setup
7
+
8
+ SilkRoute uses `uv` for environment management and `taskipy` for common developer
9
+ commands.
10
+
11
+ Install development dependencies:
12
+
13
+ ```bash
14
+ uv sync --extra dev --extra tests
15
+ ```
16
+
17
+ Editable install with `pip` also works:
18
+
19
+ ```bash
20
+ pip install -e ".[dev,tests]"
21
+ ```
22
+
23
+ ## Common Commands
24
+
25
+ Run tests:
26
+
27
+ ```bash
28
+ uv run task test
29
+ uv run task test-v
30
+ uv run task test-cov
31
+ uv run pytest tests/core/interfaces/test_reactome.py -v
32
+ ```
33
+
34
+ Lint, format, and type-check:
35
+
36
+ ```bash
37
+ uv run task lint
38
+ uv run task lint-fix
39
+ uv run task format
40
+ uv run task sort-imports
41
+ uv run task ty
42
+ uv run task pyrefly
43
+ ```
44
+
45
+ Build the package:
46
+
47
+ ```bash
48
+ uv build
49
+ ```
50
+
51
+ Smoke-test the CLI:
52
+
53
+ ```bash
54
+ uv run silkroute --help
55
+ ```
56
+
57
+ ## Project Layout
58
+
59
+ ```text
60
+ silkroute/
61
+ ├── cli/ # Typer commands (root in cli/main.py)
62
+ │ └── interfaces/ # Per-database CLI sub-apps
63
+ ├── constants/ # Per-database constants and DBConfig values
64
+ ├── core/
65
+ │ ├── interfaces/ # BaseAPIInterface + per-database API clients
66
+ │ ├── utils/ # Shared helpers (query builders, parsing, BLAST)
67
+ │ ├── workflow/ # Multi-step download workflows
68
+ │ ├── cache.py # Cache helpers
69
+ │ └── export.py # Output/export helpers
70
+ ├── logging/ # Unified logging setup
71
+ └── __init__.py # Public API (lazy) + __version__
72
+
73
+ tests/ # Mirrors the source tree
74
+ examples/ # Scripts for manual exploration
75
+ ```
76
+
77
+ ## Design Rules
78
+
79
+ - Avoid side effects on import (public top-level API is lazy via `__getattr__`).
80
+ - Use logging instead of `print`.
81
+ - New interfaces inherit from `BaseAPIInterface` and declare their `DBConfig`.
82
+ - Keep the public API small and explicit.
83
+
84
+ ## Testing Notes
85
+
86
+ The test suite is designed to run offline.
87
+
88
+ - HTTP interactions are mocked (`niquests_mock`), isolated behind `conftest` fixtures.
89
+ - Test layout mirrors the source layout.
90
+ - New features should ship with focused unit tests and CLI coverage when applicable.
91
+
92
+ ### Offline interface suite and fixtures
93
+
94
+ Every API interface has an offline test module under
95
+ `tests/core/interfaces/test_<api>.py`. Each one replays a frozen API response
96
+ from `tests/fixtures/<api>/<case>.json` and asserts three things:
97
+
98
+ - **fetch** builds the right URL/params and unwraps the body as expected;
99
+ - **parse** returns the expected keys/shape (not exact values);
100
+ - **fetch_single** round-trips through the cache (1 request on the first call,
101
+ 0 on the second).
102
+
103
+ Non-HTTP / credentialed clients are mocked at the client boundary instead of via
104
+ `niquests_mock`: BRENDA (zeep SOAP `Client`), RefSeq (`Bio.Entrez`), BioGRID (API key
105
+ supplied explicitly), and the standalone UniProt id-mapping flow
106
+ (submit → status → details → results).
107
+
108
+ Fixtures are loaded with the helpers in `tests/_helpers.py`
109
+ (`load_fixture` / `load_fixture_text`). They are committed despite the global
110
+ `*.json` gitignore rule thanks to the `!tests/**/*.json` exception.
111
+
112
+ ### Regenerating fixtures (network-gated)
113
+
114
+ `tests/_capture/capture.py` regenerates the fixtures from the real APIs. It is
115
+ **never** run by the test suite (and never on push / pull request) and refuses to
116
+ do anything unless `SILKROUTE_CAPTURE=1` is set:
117
+
118
+ ```bash
119
+ SILKROUTE_CAPTURE=1 uv run python -m tests._capture.capture # all APIs
120
+ SILKROUTE_CAPTURE=1 uv run python -m tests._capture.capture rhea chebi
121
+ ```
122
+
123
+ Each capture drives the real interface, so the request (URL, params, method,
124
+ body) matches production exactly, and records the raw HTTP body the interface
125
+ receives — the same payload the offline tests register with `niquests_mock`.
126
+
127
+ Credentialed / non-HTTP APIs are captured only when their env vars are present
128
+ (`SILKROUTE_BIOGRID_API_KEY`, `SILKROUTE_REFSEQ_EMAIL`,
129
+ `SILKROUTE_BRENDA_EMAIL`/`SILKROUTE_BRENDA_PASSWORD`); otherwise they are skipped
130
+ with a log line. These read from a gitignored `.env` at the repo root, loaded
131
+ automatically by the capture script.
132
+
133
+ Because fixtures are real bodies, re-capturing can change response shape and
134
+ require updating the affected test assertions — that is expected and the point:
135
+ the tests then reflect what the APIs actually return.
136
+
137
+ ### Scheduled re-capture (`refresh-fixtures` workflow)
138
+
139
+ `.github/workflows/refresh-fixtures.yml` runs the capture script on the 1st and
140
+ 15th of every month at 06:00 UTC (also on `workflow_dispatch`, with an optional
141
+ space-separated `apis` input). It always checks out and targets `dev`, never `main`
142
+ — the file only lives on the default branch because that is where GitHub fires
143
+ `schedule` from.
144
+
145
+ What happens next depends on the offline suite, run in-job against the fresh
146
+ fixtures:
147
+
148
+ | fixtures changed | `pytest -q` | outcome |
149
+ | --- | --- | --- |
150
+ | no | not run | nothing; job green |
151
+ | yes | passes | committed straight to `dev` |
152
+ | yes | fails | pushed to `chore/refresh-fixtures`, PR opened against `dev` |
153
+
154
+ So a PR appearing means an API changed shape and the assertions need reconciling:
155
+ fix them on the branch, and re-run `REGEN_FIELD_BASELINE=1 uv run pytest` if the
156
+ field-coverage baseline moved. The PR body carries the capture log and the tail of
157
+ the failing run. A re-run reuses the same branch and PR rather than stacking new
158
+ ones.
159
+
160
+ The job itself goes red only when the capture script exits non-zero, so a dead or
161
+ renamed endpoint is visible in the Actions tab. That is independent of the commit
162
+ decision: a partial capture whose fixtures still pass is committed to `dev` (the
163
+ APIs that answered gave valid bodies) *and* leaves the run red for the one that
164
+ did not.
165
+
166
+ Credentialed captures need repository secrets with the same names as the env vars
167
+ above (`SILKROUTE_BIOGRID_API_KEY`, `SILKROUTE_REFSEQ_EMAIL`,
168
+ `SILKROUTE_BRENDA_EMAIL`, `SILKROUTE_BRENDA_PASSWORD`); without them those three
169
+ APIs skip themselves and their fixtures stay frozen.
170
+
171
+ ## Releasing
172
+
173
+ `.github/workflows/publish-pypi.yml` builds with `uv build` and publishes to PyPI
174
+ via [trusted publishing](https://docs.pypi.org/trusted-publishers/) (OIDC, no API
175
+ token stored in the repo). It triggers on any `v*` tag, and on `workflow_dispatch`
176
+ for a build-only dry run — the `publish` job is gated on `startsWith(github.ref,
177
+ 'refs/tags/v')`, so a manual run only produces artifacts.
178
+
179
+ The version is dynamic: hatch reads `__version__` from `silkroute/__init__.py`. To
180
+ cut a release, bump it, commit, then tag the same number:
181
+
182
+ ```bash
183
+ git tag v0.2.0 && git push origin v0.2.0
184
+ ```
185
+
186
+ The build job refuses to continue when the tag and `__version__` disagree, because
187
+ a filename on PyPI cannot be reused after upload.
188
+
189
+ One-time setup on PyPI: add a trusted publisher for project `silkroute` with owner
190
+ `kren-ai-lab`, repository `silk-route`, workflow `publish-pypi.yml`, environment
191
+ `pypi`. The `pypi` GitHub environment is where any release approvals or reviewers
192
+ would go.
193
+
194
+ ## Additional Context
195
+
196
+ For more architecture detail, see [AGENTS.md](AGENTS.md).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kren AI Lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.