sbml4humans 0.6.1__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.
- sbml4humans-0.6.1/.gitignore +28 -0
- sbml4humans-0.6.1/.python-version +1 -0
- sbml4humans-0.6.1/PKG-INFO +49 -0
- sbml4humans-0.6.1/README.md +19 -0
- sbml4humans-0.6.1/pyproject.toml +148 -0
- sbml4humans-0.6.1/sbml4humans/__init__.py +16 -0
- sbml4humans-0.6.1/sbml4humans/annotations.py +54 -0
- sbml4humans-0.6.1/sbml4humans/api.py +207 -0
- sbml4humans-0.6.1/sbml4humans/cli.py +46 -0
- sbml4humans-0.6.1/sbml4humans/examples.py +165 -0
- sbml4humans-0.6.1/sbml4humans/external.py +203 -0
- sbml4humans-0.6.1/sbml4humans/glossary.py +1167 -0
- sbml4humans-0.6.1/sbml4humans/links.py +1204 -0
- sbml4humans-0.6.1/sbml4humans/local.py +325 -0
- sbml4humans-0.6.1/sbml4humans/localstate.py +79 -0
- sbml4humans-0.6.1/sbml4humans/mathml.py +158 -0
- sbml4humans-0.6.1/sbml4humans/model.py +973 -0
- sbml4humans-0.6.1/sbml4humans/report.py +257 -0
- sbml4humans-0.6.1/sbml4humans/resources/__init__.py +126 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000001.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000002.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000003.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000004.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000005.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000006.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000007.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000008.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000009.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000010.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000011.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000012.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000013.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000014.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000015.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000016.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000017.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000018.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000019.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000020.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000021.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000022.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000023.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000024.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000025.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000026.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000027.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000028.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000029.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000030.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000031.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000032.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000033.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000034.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000035.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000036.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000037.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000038.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000039.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000040.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000041.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000042.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000043.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000044.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000045.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000046.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000047.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000048.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/biomodels/BIOMD0000000049.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/algebraic_rule.xml +129 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/annotation.xml +271 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/assignment.xml +196 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/comp_deletion.xml +172 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/constraint_event.xml +207 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/distrib_comp.xml +99 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/distrib_comp_flat.xml +96 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/distrib_distributions.xml +311 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/distrib_spans.xml +152 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/distrib_uncertainties.xml +96 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/fbc_bounds_v1.xml +84 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/fbc_constraints_v3.xml +138 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/fbc_example.xml +282 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/fbc_mass_charge.xml +220 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/linear_chain.xml +454 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/minimal_model.xml +57 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/minimal_model_comp.xml +174 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/minimal_model_comp_flat.xml +275 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/model_composition.xml +79 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/model_definitions.xml +96 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/multiple_substance_units.xml +297 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/notes.xml +305 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/parameter.xml +228 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/qual_example.xml +154 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/random_network.xml +292 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/reaction.xml +241 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/reaction_with_units.xml +190 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/species.xml +218 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/unit_definitions.xml +287 -0
- sbml4humans-0.6.1/sbml4humans/resources/examples/units_namespace.xml +111 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/android-chrome-192x192.png +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/android-chrome-512x512.png +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/apple-touch-icon.png +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/ExamplesPage-CnbZ-oue.js +1 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/HomePage-BRCewGXp.js +2 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/ReportPage-B-i4UOZc.js +260 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/client-B5IBRb_N.js +1 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/index-BJK4yKgP.js +3 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/index-DZt_LUrF.css +2 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/logo-DuScVwo2.png +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/assets/report-DblabAAI.js +1 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/favicon-16x16.png +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/favicon-32x32.png +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/favicon.ico +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/index.html +20 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/robots.txt +2 -0
- sbml4humans-0.6.1/sbml4humans/resources/frontend/site.webmanifest +11 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/cyp2d6.xml +2730 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/dex_body.xml +4636 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/dex_body_flat.xml +7935 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/dex_intestine.xml +406 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/dex_kidney.xml +377 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/dex_liver.xml +3251 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/icg_body.xml +2789 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/icg_body_flat.xml +3096 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/icg_liver.xml +548 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/spt_body.xml +3309 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/spt_body_flat.xml +4688 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/spt_intestine.xml +606 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/spt_kidney.xml +290 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/comp/spt_liver.xml +1155 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/fbc/Recon3D.xml.gz +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/fbc/e_coli_core.xml.gz +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/glucose/Hepatic_glucose_3.xml +7518 -0
- sbml4humans-0.6.1/sbml4humans/resources/models/repressilator/BIOMD0000000012_urn.xml +1009 -0
- sbml4humans-0.6.1/sbml4humans/resources/omex/CombineArchiveShowCase.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/omex/CompModels.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/omex/icg_model.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/omex/omeprazole_model.omex +0 -0
- sbml4humans-0.6.1/sbml4humans/resources/xslt/ctopff.xsl +2154 -0
- sbml4humans-0.6.1/sbml4humans/resources/xslt/xsltml/README +97 -0
- sbml4humans-0.6.1/sbml4humans/resources/xslt/xsltml/cmarkup.xsl +1106 -0
- sbml4humans-0.6.1/sbml4humans/resources/xslt/xsltml/entities.xsl +459 -0
- sbml4humans-0.6.1/sbml4humans/resources/xslt/xsltml/glayout.xsl +222 -0
- sbml4humans-0.6.1/sbml4humans/resources/xslt/xsltml/mmltex.xsl +36 -0
- sbml4humans-0.6.1/sbml4humans/resources/xslt/xsltml/scripts.xsl +375 -0
- sbml4humans-0.6.1/sbml4humans/resources/xslt/xsltml/tables.xsl +130 -0
- sbml4humans-0.6.1/sbml4humans/resources/xslt/xsltml/tokens.xsl +328 -0
- sbml4humans-0.6.1/sbml4humans/sbml.py +78 -0
- sbml4humans-0.6.1/sbml4humans/sbmlinfo.py +1577 -0
- sbml4humans-0.6.1/sbml4humans/schema.py +58 -0
- sbml4humans-0.6.1/sbml4humans/units.py +147 -0
- sbml4humans-0.6.1/sbml4humans/viewer.py +221 -0
- sbml4humans-0.6.1/tests/conftest.py +33 -0
- sbml4humans-0.6.1/tests/data/glossary/core.toml +171 -0
- sbml4humans-0.6.1/tests/test_annotations.py +67 -0
- sbml4humans-0.6.1/tests/test_api.py +286 -0
- sbml4humans-0.6.1/tests/test_examples.py +299 -0
- sbml4humans-0.6.1/tests/test_external.py +255 -0
- sbml4humans-0.6.1/tests/test_glossary.py +563 -0
- sbml4humans-0.6.1/tests/test_links.py +1681 -0
- sbml4humans-0.6.1/tests/test_local.py +249 -0
- sbml4humans-0.6.1/tests/test_mathml.py +186 -0
- sbml4humans-0.6.1/tests/test_model.py +259 -0
- sbml4humans-0.6.1/tests/test_report.py +313 -0
- sbml4humans-0.6.1/tests/test_sbmlinfo.py +1861 -0
- sbml4humans-0.6.1/tests/test_schema.py +54 -0
- sbml4humans-0.6.1/tests/test_show.py +162 -0
- sbml4humans-0.6.1/uv.lock +1064 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
.venv/
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.pytest_cache/
|
|
7
|
+
.mypy_cache/
|
|
8
|
+
.ruff_cache/
|
|
9
|
+
|
|
10
|
+
# node
|
|
11
|
+
node_modules/
|
|
12
|
+
frontend/dist/
|
|
13
|
+
# the build of the frontend which ships with the python package (npm run build:package)
|
|
14
|
+
backend/sbml4humans/resources/frontend/
|
|
15
|
+
frontend/playwright-report/
|
|
16
|
+
frontend/test-results/
|
|
17
|
+
|
|
18
|
+
# the documentation site built by zensical
|
|
19
|
+
site/
|
|
20
|
+
|
|
21
|
+
# editors, operating system
|
|
22
|
+
.idea/
|
|
23
|
+
.vscode/
|
|
24
|
+
*~
|
|
25
|
+
.DS_Store
|
|
26
|
+
|
|
27
|
+
# brainstorming sessions of the superpowers plugin
|
|
28
|
+
.superpowers/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: sbml4humans
|
|
3
|
+
Version: 0.6.1
|
|
4
|
+
Summary: Interactive, human readable reports of SBML models, in the browser and from python.
|
|
5
|
+
Project-URL: Homepage, https://sbml4humans.de
|
|
6
|
+
Project-URL: Documentation, https://matthiaskoenig.github.io/sbml4humans/
|
|
7
|
+
Project-URL: Repository, https://github.com/matthiaskoenig/sbml4humans
|
|
8
|
+
Author-email: Matthias König <konigmatt@googlemail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Keywords: COMBINE archive,SBML,computational modelling,report,systems biology
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
17
|
+
Requires-Python: >=3.14
|
|
18
|
+
Requires-Dist: fastapi>=0.141.1
|
|
19
|
+
Requires-Dist: httpx>=0.28.1
|
|
20
|
+
Requires-Dist: lxml>=6.0.0
|
|
21
|
+
Requires-Dist: numpy>=2.2.2
|
|
22
|
+
Requires-Dist: pint>=0.25.3
|
|
23
|
+
Requires-Dist: platformdirs>=4.4
|
|
24
|
+
Requires-Dist: pydantic>=2.12
|
|
25
|
+
Requires-Dist: pymetadata>=0.6.2
|
|
26
|
+
Requires-Dist: python-libsbml>=5.21.1
|
|
27
|
+
Requires-Dist: python-multipart>=0.0.32
|
|
28
|
+
Requires-Dist: uvicorn>=0.52.4
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# SBML4Humans
|
|
32
|
+
|
|
33
|
+
SBML4Humans creates interactive, human readable reports of [SBML](https://sbml.org) models: one table per element type, a search over everything, and an inspector which follows every reference between the objects of a model, for SBML core and the packages comp, fbc, qual and distrib.
|
|
34
|
+
|
|
35
|
+
The package opens the report of a file of your machine in the browser. The file is read by a local server and never leaves the machine:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from sbml4humans import show
|
|
39
|
+
|
|
40
|
+
show("model.xml")
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
sbml4humans model.xml
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The web application is at [sbml4humans.de](https://sbml4humans.de), the documentation at [matthiaskoenig.github.io/sbml4humans](https://matthiaskoenig.github.io/sbml4humans/), with [Reports from python](https://matthiaskoenig.github.io/sbml4humans/python/) for this package, and the source at [github.com/matthiaskoenig/sbml4humans](https://github.com/matthiaskoenig/sbml4humans).
|
|
48
|
+
|
|
49
|
+
SBML4Humans is released under the MIT license. If you use it in your work, please cite it as the [documentation](https://matthiaskoenig.github.io/sbml4humans/#how-to-cite) describes.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SBML4Humans
|
|
2
|
+
|
|
3
|
+
SBML4Humans creates interactive, human readable reports of [SBML](https://sbml.org) models: one table per element type, a search over everything, and an inspector which follows every reference between the objects of a model, for SBML core and the packages comp, fbc, qual and distrib.
|
|
4
|
+
|
|
5
|
+
The package opens the report of a file of your machine in the browser. The file is read by a local server and never leaves the machine:
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from sbml4humans import show
|
|
9
|
+
|
|
10
|
+
show("model.xml")
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
sbml4humans model.xml
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The web application is at [sbml4humans.de](https://sbml4humans.de), the documentation at [matthiaskoenig.github.io/sbml4humans](https://matthiaskoenig.github.io/sbml4humans/), with [Reports from python](https://matthiaskoenig.github.io/sbml4humans/python/) for this package, and the source at [github.com/matthiaskoenig/sbml4humans](https://github.com/matthiaskoenig/sbml4humans).
|
|
18
|
+
|
|
19
|
+
SBML4Humans is released under the MIT license. If you use it in your work, please cite it as the [documentation](https://matthiaskoenig.github.io/sbml4humans/#how-to-cite) describes.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sbml4humans"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Interactive, human readable reports of SBML models, in the browser and from python."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.14"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
keywords = ["SBML", "systems biology", "computational modelling", "report", "COMBINE archive"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 4 - Beta",
|
|
15
|
+
"Intended Audience :: Science/Research",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.14",
|
|
19
|
+
"Topic :: Scientific/Engineering :: Bio-Informatics",
|
|
20
|
+
]
|
|
21
|
+
authors = [
|
|
22
|
+
{name = "Matthias König", email = "konigmatt@googlemail.com"},
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
# the report: libsbml reads the models, lxml renders the math with xslt,
|
|
26
|
+
# pint formats the units, pymetadata handles combine archives and annotations
|
|
27
|
+
"python-libsbml>=5.21.1",
|
|
28
|
+
"lxml>=6.0.0",
|
|
29
|
+
"numpy>=2.2.2",
|
|
30
|
+
"pint>=0.25.3",
|
|
31
|
+
"pymetadata>=0.6.2",
|
|
32
|
+
"pydantic>=2.12",
|
|
33
|
+
# the http api
|
|
34
|
+
"fastapi>=0.141.1",
|
|
35
|
+
"uvicorn>=0.52.4",
|
|
36
|
+
"python-multipart>=0.0.32",
|
|
37
|
+
# downloading models from urls, and the client of the local server of `show`
|
|
38
|
+
"httpx>=0.28.1",
|
|
39
|
+
# the state file of the local server of `show`, in the cache directory of the user
|
|
40
|
+
"platformdirs>=4.4",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.scripts]
|
|
44
|
+
sbml4humans = "sbml4humans.cli:main"
|
|
45
|
+
|
|
46
|
+
[project.urls]
|
|
47
|
+
Homepage = "https://sbml4humans.de"
|
|
48
|
+
Documentation = "https://matthiaskoenig.github.io/sbml4humans/"
|
|
49
|
+
Repository = "https://github.com/matthiaskoenig/sbml4humans"
|
|
50
|
+
|
|
51
|
+
[dependency-groups]
|
|
52
|
+
dev = [
|
|
53
|
+
"bump-my-version>=1.5.1",
|
|
54
|
+
"pytest>=9.1.1",
|
|
55
|
+
"ruff>=0.16.6",
|
|
56
|
+
"ty>=0.0.78",
|
|
57
|
+
"zensical>=0.0.60",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[tool.hatch.version]
|
|
61
|
+
path = "sbml4humans/__init__.py"
|
|
62
|
+
|
|
63
|
+
[tool.bumpversion]
|
|
64
|
+
# the version of sbml4humans is the version of the backend package, the frontend
|
|
65
|
+
# follows it. Run from this directory: `uv run bump-my-version bump minor`.
|
|
66
|
+
# No tag: the bump is merged into develop with squash or rebase, which rewrites
|
|
67
|
+
# the commit, so the tag is created on develop after the merge (see docs/development.md)
|
|
68
|
+
current_version = "0.6.1"
|
|
69
|
+
commit = true
|
|
70
|
+
tag = false
|
|
71
|
+
tag_name = "{new_version}"
|
|
72
|
+
tag_message = "Bump version: {current_version} → {new_version}"
|
|
73
|
+
message = "Bump version: {current_version} → {new_version}"
|
|
74
|
+
|
|
75
|
+
[[tool.bumpversion.files]]
|
|
76
|
+
filename = "sbml4humans/__init__.py"
|
|
77
|
+
|
|
78
|
+
[[tool.bumpversion.files]]
|
|
79
|
+
filename = "../frontend/package.json"
|
|
80
|
+
search = "\"version\": \"{current_version}\""
|
|
81
|
+
replace = "\"version\": \"{new_version}\""
|
|
82
|
+
|
|
83
|
+
# the lock carries the version of the package twice, at its root and as the entry of the
|
|
84
|
+
# package itself; the search names the package, so that a dependency which shares the number
|
|
85
|
+
# of a version is left alone
|
|
86
|
+
[[tool.bumpversion.files]]
|
|
87
|
+
filename = "../frontend/package-lock.json"
|
|
88
|
+
search = "\"name\": \"sbml4humans\",\n \"version\": \"{current_version}\""
|
|
89
|
+
replace = "\"name\": \"sbml4humans\",\n \"version\": \"{new_version}\""
|
|
90
|
+
|
|
91
|
+
[[tool.bumpversion.files]]
|
|
92
|
+
filename = "../frontend/package-lock.json"
|
|
93
|
+
search = "\"name\": \"sbml4humans\",\n \"version\": \"{current_version}\""
|
|
94
|
+
replace = "\"name\": \"sbml4humans\",\n \"version\": \"{new_version}\""
|
|
95
|
+
|
|
96
|
+
# the frontend which `sbml4humans.show` serves is built into the package before the wheel
|
|
97
|
+
# (`npm run build:package` in frontend/). It is git ignored, which hatch takes as excluded,
|
|
98
|
+
# so it is named as an artifact of the build.
|
|
99
|
+
[tool.hatch.build]
|
|
100
|
+
artifacts = ["sbml4humans/resources/frontend/**"]
|
|
101
|
+
|
|
102
|
+
[tool.hatch.build.targets.wheel]
|
|
103
|
+
packages = ["sbml4humans"]
|
|
104
|
+
|
|
105
|
+
[tool.pytest.ini_options]
|
|
106
|
+
testpaths = ["tests"]
|
|
107
|
+
addopts = "-ra"
|
|
108
|
+
|
|
109
|
+
[tool.ruff]
|
|
110
|
+
line-length = 88
|
|
111
|
+
target-version = "py314"
|
|
112
|
+
|
|
113
|
+
[tool.ruff.lint]
|
|
114
|
+
# Pyflakes (`F`) and a subset of pycodestyle (`E`), plus:
|
|
115
|
+
# W pycodestyle warnings
|
|
116
|
+
# I import sorting
|
|
117
|
+
# D docstrings (google convention, see [tool.ruff.lint.pydocstyle])
|
|
118
|
+
# UP pyupgrade, keeps the code on current python syntax
|
|
119
|
+
# B bugbear, likely bugs and design problems
|
|
120
|
+
# C4 comprehensions
|
|
121
|
+
# SIM simplifications
|
|
122
|
+
# RET return statements
|
|
123
|
+
# G logging format, lazy `%s` instead of f-strings
|
|
124
|
+
# PIE misc lints
|
|
125
|
+
# RUF ruff specific rules
|
|
126
|
+
select = [
|
|
127
|
+
"E4", "E7", "E9", "F", "W", "I", "D", "UP", "B", "C4", "SIM", "RET", "G", "PIE", "RUF",
|
|
128
|
+
]
|
|
129
|
+
ignore = [
|
|
130
|
+
# names such as `König` are not ambiguous unicode, they are german
|
|
131
|
+
"RUF001",
|
|
132
|
+
"RUF002",
|
|
133
|
+
"RUF003",
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
[tool.ruff.lint.isort]
|
|
137
|
+
lines-after-imports = 2
|
|
138
|
+
known-first-party = ["sbml4humans"]
|
|
139
|
+
|
|
140
|
+
[tool.ruff.lint.pydocstyle]
|
|
141
|
+
convention = "google"
|
|
142
|
+
|
|
143
|
+
[tool.ty.src]
|
|
144
|
+
include = ["sbml4humans", "tests"]
|
|
145
|
+
|
|
146
|
+
[tool.ty.terminal]
|
|
147
|
+
# warnings are failures: keep the codebase free of any diagnostic
|
|
148
|
+
error-on-warning = true
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""sbml4humans, the human readable report of SBML models.
|
|
2
|
+
|
|
3
|
+
`sbml4humans.sbmlinfo` creates the report of an SBML document, `sbml4humans.api`
|
|
4
|
+
serves it over http for the sbml4humans frontend, and `sbml4humans.show` opens
|
|
5
|
+
the report of a local file in the browser:
|
|
6
|
+
|
|
7
|
+
from sbml4humans import show
|
|
8
|
+
show("model.xml")
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__version__ = "0.6.1"
|
|
12
|
+
|
|
13
|
+
from sbml4humans.viewer import show, stop
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = ["__version__", "show", "stop"]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Resolution of annotation resources.
|
|
2
|
+
|
|
3
|
+
Used by the frontend to display information (label, description, cross
|
|
4
|
+
references) for the identifiers in the annotations of a model.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from pymetadata.core.annotation import RDFAnnotation, RDFAnnotationData
|
|
10
|
+
from pymetadata.core.miriam import BQB
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# fields the report shows as text; the Ontology Lookup Service reports a missing
|
|
14
|
+
# definition as an empty list, which ends up in the description of the term
|
|
15
|
+
TEXT_FIELDS = (
|
|
16
|
+
"resource_normalized",
|
|
17
|
+
"collection",
|
|
18
|
+
"term",
|
|
19
|
+
"label",
|
|
20
|
+
"description",
|
|
21
|
+
"url",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# fields the report shows as messages; a failing request is collected as the error itself
|
|
25
|
+
MESSAGE_FIELDS = ("errors", "warnings")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _text(value: Any) -> str | None:
|
|
29
|
+
"""Convert a field to text; a field which carries no text has no value."""
|
|
30
|
+
if isinstance(value, str) and value.strip():
|
|
31
|
+
return value.strip()
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _messages(value: Any) -> list[str]:
|
|
36
|
+
"""Convert a field to a list of messages."""
|
|
37
|
+
if not isinstance(value, list):
|
|
38
|
+
return []
|
|
39
|
+
return [str(message) for message in value]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def annotation_info(resource: str) -> dict[str, Any]:
|
|
43
|
+
"""Resolve the information of an annotation resource.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
resource: identifier of the resource (url or MIRIAM urn).
|
|
47
|
+
"""
|
|
48
|
+
annotation = RDFAnnotation(qualifier=BQB.IS, resource=resource)
|
|
49
|
+
data = RDFAnnotationData(annotation=annotation).to_dict()
|
|
50
|
+
for field in TEXT_FIELDS:
|
|
51
|
+
data[field] = _text(data.get(field))
|
|
52
|
+
for field in MESSAGE_FIELDS:
|
|
53
|
+
data[field] = _messages(data.get(field))
|
|
54
|
+
return data
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"""The http api of sbml4humans.
|
|
2
|
+
|
|
3
|
+
Served with `uvicorn sbml4humans.api:api`.
|
|
4
|
+
|
|
5
|
+
Error contract: the frontend expects every response with status 200. Failures
|
|
6
|
+
are reported in the body as `{"errors": [message, traceback], "warnings": [],
|
|
7
|
+
"info": {...}}`, with the query parameters of the request as `info`.
|
|
8
|
+
|
|
9
|
+
A report endpoint returns its `ReportResponse` as it is. FastAPI takes an
|
|
10
|
+
instance of the response model without validating it again and writes its JSON
|
|
11
|
+
in one pass of pydantic, which applies the configuration of the model: camelCase
|
|
12
|
+
keys and an infinite value or a value which is not a number as the strings
|
|
13
|
+
`"Infinity"`, `"-Infinity"` and `"NaN"`.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import traceback
|
|
18
|
+
from collections.abc import AsyncIterator
|
|
19
|
+
from contextlib import asynccontextmanager
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
import httpx
|
|
23
|
+
from fastapi import FastAPI, Request, UploadFile
|
|
24
|
+
from fastapi.concurrency import run_in_threadpool
|
|
25
|
+
from fastapi.exceptions import RequestValidationError
|
|
26
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
27
|
+
from fastapi.responses import JSONResponse
|
|
28
|
+
from starlette.middleware.base import RequestResponseEndpoint
|
|
29
|
+
from starlette.responses import Response
|
|
30
|
+
|
|
31
|
+
from sbml4humans import __version__
|
|
32
|
+
from sbml4humans.annotations import annotation_info
|
|
33
|
+
from sbml4humans.examples import ExampleMetaData, load_examples
|
|
34
|
+
from sbml4humans.model import ReportResponse
|
|
35
|
+
from sbml4humans.report import report_for_bytes, report_for_path
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
logger = logging.getLogger(__name__)
|
|
39
|
+
|
|
40
|
+
DOWNLOAD_TIMEOUT = 60.0 # [s]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ExampleNotFoundError(KeyError):
|
|
44
|
+
"""Raised for an unknown example id."""
|
|
45
|
+
|
|
46
|
+
def __init__(self, example_id: str) -> None:
|
|
47
|
+
"""Create the error for the unknown example id."""
|
|
48
|
+
super().__init__(example_id)
|
|
49
|
+
self.example_id = example_id
|
|
50
|
+
|
|
51
|
+
def __str__(self) -> str:
|
|
52
|
+
"""Message for the frontend."""
|
|
53
|
+
return f"example for id does not exist '{self.example_id}'"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@asynccontextmanager
|
|
57
|
+
async def lifespan(_: FastAPI) -> AsyncIterator[None]:
|
|
58
|
+
"""Read the examples on startup, so that the first requests are fast."""
|
|
59
|
+
load_examples()
|
|
60
|
+
yield
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
api = FastAPI(
|
|
64
|
+
title="sbml4humans",
|
|
65
|
+
description="sbml4humans backend api",
|
|
66
|
+
version=__version__,
|
|
67
|
+
terms_of_service="https://github.com/matthiaskoenig/sbml4humans/blob/main/frontend/privacy_notice.md",
|
|
68
|
+
contact={
|
|
69
|
+
"name": "Matthias König",
|
|
70
|
+
"url": "https://livermetabolism.com",
|
|
71
|
+
"email": "konigmatt@googlemail.com",
|
|
72
|
+
},
|
|
73
|
+
license_info={
|
|
74
|
+
"name": "MIT",
|
|
75
|
+
"url": "https://opensource.org/license/MIT",
|
|
76
|
+
},
|
|
77
|
+
openapi_tags=[
|
|
78
|
+
{"name": "examples", "description": "Query examples."},
|
|
79
|
+
{"name": "reports", "description": "Create report data."},
|
|
80
|
+
{"name": "metadata", "description": "Query metadata."},
|
|
81
|
+
],
|
|
82
|
+
lifespan=lifespan,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def error_response(request: Request, exc: Exception) -> JSONResponse:
|
|
87
|
+
"""Report an exception to the frontend in the body of a 200 response."""
|
|
88
|
+
logger.error("%s %s failed: %s", request.method, request.url.path, exc)
|
|
89
|
+
return JSONResponse(
|
|
90
|
+
status_code=200,
|
|
91
|
+
content={
|
|
92
|
+
"errors": [
|
|
93
|
+
str(exc),
|
|
94
|
+
"".join(traceback.format_exception(exc)),
|
|
95
|
+
],
|
|
96
|
+
"warnings": [],
|
|
97
|
+
"info": dict(request.query_params),
|
|
98
|
+
},
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def add_error_contract(app: FastAPI) -> None:
|
|
103
|
+
"""Make every failure of the app an error response with status 200.
|
|
104
|
+
|
|
105
|
+
Starlette's own exception handling runs in the outermost
|
|
106
|
+
`ServerErrorMiddleware`, outside a `CORSMiddleware`, so its responses carry
|
|
107
|
+
no CORS headers. The middleware of the contract has to be added before the
|
|
108
|
+
`CORSMiddleware`, which makes it the innermost one (Starlette wraps
|
|
109
|
+
middleware in the order they are added, most recent outermost), so the
|
|
110
|
+
`CORSMiddleware` wraps it and adds its headers to the error response as it
|
|
111
|
+
would to any other response.
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
@app.middleware("http")
|
|
115
|
+
async def error_response_middleware(
|
|
116
|
+
request: Request, call_next: RequestResponseEndpoint
|
|
117
|
+
) -> Response:
|
|
118
|
+
"""Turn an exception of any endpoint into an error response."""
|
|
119
|
+
try:
|
|
120
|
+
return await call_next(request)
|
|
121
|
+
except Exception as exc:
|
|
122
|
+
return error_response(request, exc)
|
|
123
|
+
|
|
124
|
+
# Safety net for exceptions raised outside the middleware stack above, for
|
|
125
|
+
# example during request parsing before `error_response_middleware` runs.
|
|
126
|
+
app.add_exception_handler(Exception, error_response)
|
|
127
|
+
app.add_exception_handler(RequestValidationError, error_response)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
add_error_contract(api)
|
|
131
|
+
api.add_middleware(
|
|
132
|
+
CORSMiddleware,
|
|
133
|
+
allow_origins=["*"],
|
|
134
|
+
allow_methods=["*"],
|
|
135
|
+
allow_headers=["*"],
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def download(url: str) -> bytes:
|
|
140
|
+
"""Download the content behind url."""
|
|
141
|
+
response = httpx.get(url, follow_redirects=True, timeout=DOWNLOAD_TIMEOUT)
|
|
142
|
+
response.raise_for_status()
|
|
143
|
+
return response.content
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@api.get("/api/examples", tags=["examples"])
|
|
147
|
+
def examples() -> dict[str, list[dict[str, Any]]]:
|
|
148
|
+
"""List the metadata of all examples."""
|
|
149
|
+
return {
|
|
150
|
+
"examples": [
|
|
151
|
+
example.model_dump(exclude={"file"}) for example in load_examples().values()
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@api.get(
|
|
157
|
+
"/api/examples/{example_id}",
|
|
158
|
+
tags=["examples"],
|
|
159
|
+
response_model=ReportResponse,
|
|
160
|
+
response_model_by_alias=True,
|
|
161
|
+
)
|
|
162
|
+
def example(example_id: str) -> ReportResponse:
|
|
163
|
+
"""Create the report data of an example."""
|
|
164
|
+
example: ExampleMetaData | None = load_examples().get(example_id)
|
|
165
|
+
if example is None:
|
|
166
|
+
raise ExampleNotFoundError(example_id)
|
|
167
|
+
return report_for_path(example.file, trusted=True)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@api.post(
|
|
171
|
+
"/api/file",
|
|
172
|
+
tags=["reports"],
|
|
173
|
+
response_model=ReportResponse,
|
|
174
|
+
response_model_by_alias=True,
|
|
175
|
+
)
|
|
176
|
+
def report_from_file(source: UploadFile) -> ReportResponse:
|
|
177
|
+
"""Create the report data of an uploaded SBML file or COMBINE archive."""
|
|
178
|
+
return report_for_bytes(source.file.read())
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@api.get(
|
|
182
|
+
"/api/url",
|
|
183
|
+
tags=["reports"],
|
|
184
|
+
response_model=ReportResponse,
|
|
185
|
+
response_model_by_alias=True,
|
|
186
|
+
)
|
|
187
|
+
def report_from_url(url: str) -> ReportResponse:
|
|
188
|
+
"""Create the report data of an SBML file or COMBINE archive behind a url."""
|
|
189
|
+
return report_for_bytes(download(url))
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@api.post(
|
|
193
|
+
"/api/content",
|
|
194
|
+
tags=["reports"],
|
|
195
|
+
response_model=ReportResponse,
|
|
196
|
+
response_model_by_alias=True,
|
|
197
|
+
)
|
|
198
|
+
async def report_from_content(request: Request) -> ReportResponse:
|
|
199
|
+
"""Create the report data of the SBML content in the request body."""
|
|
200
|
+
content = await request.body()
|
|
201
|
+
return await run_in_threadpool(report_for_bytes, content)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@api.get("/api/annotation_resource", tags=["metadata"])
|
|
205
|
+
def annotation_resource(resource: str) -> dict[str, Any]:
|
|
206
|
+
"""Resolve the information of an annotation resource (url or MIRIAM urn)."""
|
|
207
|
+
return annotation_info(resource)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""The command `sbml4humans`: the report of a local file in the browser."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import sys
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
|
|
7
|
+
from sbml4humans import __version__
|
|
8
|
+
from sbml4humans.viewer import show, stop
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main(argv: Sequence[str] | None = None) -> int:
|
|
12
|
+
"""Run the command and return its exit code."""
|
|
13
|
+
parser = argparse.ArgumentParser(
|
|
14
|
+
prog="sbml4humans",
|
|
15
|
+
description=(
|
|
16
|
+
"Open the report of an SBML file or COMBINE archive in the browser. The "
|
|
17
|
+
"file is read by a local server and never leaves this machine."
|
|
18
|
+
),
|
|
19
|
+
)
|
|
20
|
+
parser.add_argument("path", nargs="?", help="SBML file or COMBINE archive")
|
|
21
|
+
parser.add_argument(
|
|
22
|
+
"--no-browser",
|
|
23
|
+
action="store_true",
|
|
24
|
+
help="print the url of the report without opening it",
|
|
25
|
+
)
|
|
26
|
+
parser.add_argument("--stop", action="store_true", help="end the local server")
|
|
27
|
+
parser.add_argument("--version", action="version", version=__version__)
|
|
28
|
+
arguments = parser.parse_args(argv)
|
|
29
|
+
|
|
30
|
+
if arguments.stop:
|
|
31
|
+
stopped = stop()
|
|
32
|
+
print("the local server stopped" if stopped else "no local server is running")
|
|
33
|
+
return 0
|
|
34
|
+
if arguments.path is None:
|
|
35
|
+
parser.error("the path of an SBML file or COMBINE archive is required")
|
|
36
|
+
try:
|
|
37
|
+
url = show(arguments.path, open_browser=not arguments.no_browser)
|
|
38
|
+
except (OSError, ValueError, RuntimeError) as error:
|
|
39
|
+
print(f"sbml4humans: {error}", file=sys.stderr)
|
|
40
|
+
return 1
|
|
41
|
+
print(url)
|
|
42
|
+
return 0
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
sys.exit(main())
|