Release notes for sbmlutils 0.10.0
We are pleased to release the next version of sbmlutils including the following changes. This is a large release which reorganizes the repository, so it starts with what has to be changed in existing code.
Breaking changes
-
sbml4humans moved into its own repository (#436), matthiaskoenig/sbml4humans, with its history. The Vue frontend, the deployment (
Dockerfile,docker-compose-*.yml,nginx/,deploy.sh,deploy.md,docker-purge.sh) and the FastAPI backend went there:sbmlutils.report.apiandsbmlutils.report.api_examplesare gone and thefastapi,uvicornandpython-multipartdependencies with them, sbmlutils no longer ships a web service. The report itself stays here, i.e.,report.sbmlinfo,report.unitsandreport.mathml, and it is what the api serves;report.sbmlreport.create_online_report, the client which opens a model on sbml4humans.de, stays as well -
pymetadata >= 0.6.0 is required, which reorganized its packages. Code which imports from pymetadata through sbmlutils is unaffected, code which imports from pymetadata directly changes
from pymetadata.identifiers.miriam import BQBtofrom pymetadata.core.miriam import BQBandfrom pymetadata.metadata import SBOtofrom pymetadata.ontologies import SBO -
sbmlutils.metadata.sboremoved, it only re-exportedSBO:from sbmlutils.metadata.sbo import SBObecomesfrom sbmlutils.metadata import SBO.sbmlutils.metadatare-exportsBQB,BQMandSBOexplicitly instead of through star imports, the qualifier maps of libsbml stay insbmlutils.metadata.miriam -
SBOis a class of ontology terms now instead of a str enum. A term is still its identifier, i.e.,SBO.SIMPLE_CHEMICAL == "SBO_0000247", and it carrieslabel,definition,synonyms,curieandurl -
the examples moved out of the package to
examples/in the repository, sofrom sbmlutils.examples import ...andpython -m sbmlutils.examples.<name>becomefrom examples import ...andpython -m examples.<name>, run from the root of a checkout. They are documentation and are no longer installed with the package, which shipped megabytes of models -
log.get_logger()removed. sbmlutils configured logging on import: every module attached a rich handler to its logger and set its level, so an application had no say over the messages of the library. Code which called it changes fromlog.get_logger(__name__)tologging.getLogger(__name__);log.enable_rich_logging()is the opt-in for scripts, examples and interactive work.log.set_level_for_all_loggers()is gone as well, it set the level on every logger of the interpreter, including those of other libraries. Importingsbmlutils.consoleno longer replaces the interpreterdisplayhookthroughrich.pretty.install() -
utils.timeitandutils.deprecatedremoved. Nothing used them anddeprecatedreadf.func_code, a python 2 attribute, so it raised as soon as it was applied -
comp.create_portsreturnslist[libsbml.Port], which is what it always returned; the annotation saidlist[factory.Port].comp.replace_element_in_submodelsreturnsNone, it never returned theReplacedElementits annotation promised -
the coefficient of a
UserDefinedConstraintComponentis the id of a parameter, not a number, as fbc version 3 defines it. A constraint is written ascomponents={"RGLX": "coef_plus_one"}with the coefficients declared as parameters; passing numbers raised aTypeErrorfrom libsbml -
unused dependencies dropped:
depinfo,scipy,xmlschemaandsetuptools, which worked around apkg_resourcesimport of py4cytoscape that no longer exists -
the installation is less than half the size (#461), 521 MB before, 201 MB now. The package reads, writes, annotates and validates models; it neither simulates nor plots, and
libroadrunner(137 MB) andmatplotlibwere runtime dependencies although nothing in the package imports them. They are theexamplesextra now,py4cytoscapeis thecytoscapeextra and cobrapy thecobraextra, which the documentation promised but which was never declared:pip install sbmlutils[cytoscape] # visualization in a running Cytoscape pip install sbmlutils[cobra] # flux balance analysis with cobrapy pip install sbmlutils[examples] # simulation and plotting, to run the examples
sbmlutils.cytoscapestill imports without its extra; its functions log a warning and do nothing, exactly as they already did when Cytoscape was not running.uv sync --extra devinstallscytoscapeandexamples, so a development environment is unchanged -
the SBML test suite (56 MB) and the biomodels archives (21 MB) under
sbmlutils/resources/models/are excluded from the distribution, see[tool.hatch.build]inpyproject.toml. They are test data of the repository, not resources of the package;tests/test_parser.pyresolves them from the checkout, so no test was lost -
minimum versions raised to the current releases:
python-libsbml>=5.21.1,antimony>=3.1.3,pint>=0.25.3,markdown-it-py>=4.2.0,pymetadata>=0.6.0,pydantic>=2.13.5,requests>=2.34.2and, in thecytoscapeextra,py4cytoscape>=1.13.0
Fixes
SBMLDocumentInfo._get_pkraised aNameErrorwhenever the primary key was already cached on an element: it returned a variable which is only bound in the branch which computes itcomp._create_portcalledfactory.UnitDefinition.get_unit_string, which does not exist, so creating a port for a unit raised anAttributeError. The unit reference is the id of the unit definition and is set directlyfbc.cobracalledreactions.get_by_sidandreaction.getId(), neither of which is cobrapy API, socobra_reaction_infoandcheck_mass_balancefailed on the first reaction, and the unbalanced reactions were logged as a format stringExternalAnnotationnever uppercased the qualifier of an annotation file, the key it compared against was misspelled asqualifer- the
CompartmentGlyphof the layout package declared its glyph as aSpeciesGlyph, copied from the class above it libsbml.FBC_FBCVARIABLETYPE_LINEARdoes not exist, the constant isFBC_VARIABLE_TYPE_LINEARUnitDefinition._create_unitdeclared the unit kind as astr, the libsbml kinds are integers- an error while creating an SBML object reported an unbound variable (
UnboundLocalError) instead of the object which failed visualize_antimonyleaked aNamedTemporaryFilewhich was never closed- the deprecated
Thread.setDaemon,tempfile.mktempand pydantic.dict()calls are replaced - the downloads of
sbmlutils.biomodelsretry the transient error responses (429, 500, 502, 503, 504) with an exponential backoff and time out after 30 seconds, instead of failing on the first hiccup of the BioModels service. They use the shared session of pymetadata rather than a second copy of it, andquery_curated_biomodelsgoes through it as well - the XPP converter is documented and covered for every packaged ode file (#213):
112836_HH-extandSkM_AP_KCawere commented out oftests/converters/test_xpp.py, both convert to models which validate without an error or a warning. They do not integrate with the default solver of roadrunner, which is a property of those stiff models rather than of the conversion, see Converters
Features
- no example opens a GUI window any more. A plotting example builds its figure, returns it and writes it to a file, which blocked the test suite on a machine with a display and failed on one without; the
conftest.pyat the root selects the non-interactiveAggbackend for the test session and the example scripts run withMPLBACKEND=Agg - no example writes into the repository or into the package: the models, the figures and the generated code go into the current working directory
tests/examples/test_example_scripts.pyruns the examples which convert, merge, interpolate or simulate in a temporary working directory, so an example which breaks fails the test suite.examples/fbc/fbc_userdefinedconstraints.pyis part of the tested examples now, which is how itsTypeErrorsurfaced
Documentation
- the documentation is built and published again (#448), migrated from sphinx to Zensical, the static site generator of the Material for MkDocs authors: markdown sources in
docs/, configured inzensical.toml, built and published to https://matthiaskoenig.github.io/sbmlutils by a GitHub workflow on every push todevelop. Nothing rendered is committed anddocs_builder/is gone - new user guides for model creation, units, annotations, notes, validation, reading and writing, model composition, flux balance constraints, distributions and uncertainties, COMBINE archives, reports, converters, interpolation and visualization. Every code block was run against the package. This covers model creation with its objects, annotation, model import and merging (#408) and the comp package with ports, submodels, replacements and flattening (#214)
- API reference of 29 modules, rendered from the docstrings by mkdocstrings
- the documentation is available as markdown for agents and language models: llms.txt, llms-full.txt and every page next to its html.
CLAUDE.mddescribes the repository itself examples/README.mddescribes what is where and how to run it- a References page cites the publications of SBML Level 3, of the Level 3 Version 2 core specification and of the fbc and distrib packages, and the guides link to the paper of the package they describe
- the presentations moved from
docs/presentations/topresentations/, sincedocs/is the documentation source now
Development
- mypy replaced by ty for type checking (#465); ty runs in CI, in
tox r -e tyand as a pre-commit hook. All 65# type: ignorecomments are gone and the tree is at zero diagnostics, which is what surfaced most of the fixes above. Annotations are accepted as aSequencerather than alist, so passing thelist[tuple[BQB, str]]a model definition naturally writes is no longer an error at every call site - more ruff rules (import sorting, docstrings, pyupgrade, bugbear, comprehensions, simplifications, returns, logging format) and additional pre-commit hooks (toml, json, case conflicts, line endings, forgotten debug statements). The blanket
F403/F405ignore of the star imports became a per file ignore of the model definitions which need them; log calls use lazy%sformatting instead of f-strings - type annotations modernized to
dict,listandX | None, mutable class attributes marked asClassVar - the project urls reach the metadata now: the table was written as
[project_urls]instead of[project.urls], so it was silently ignored and the pypi page carried no links at all.Documentationpoints to the documentation site and aChangelogurl was added. The license metadata follows PEP 639, i.e.,license = "MIT"withlicense-files, instead of the deprecatedLicense ::classifier - root configuration cleaned up: the
devandtestextras are merged into onedevextra, the pytest configuration moved fromtox.inito[tool.pytest.ini_options]inpyproject.toml, the unusedpytest-raisesdependency and itsraisesmarker are gone, as is theinstalltox environment which nothing referenced.MANIFEST.inwas removed, hatchling does not read it and it referred to aREADME.rstwhich no longer exists, andRELEASE.mdmoved into the documentation - the workflows pin their actions, declare least privilege permissions, cancel superseded runs and time out; the test matrix covers linux, windows and macos and the release job publishes with trusted publishing.
main.ymlbecameci-cd.ymlandmypy.ymlbecamety.yml; dependabot keeps the actions current CITATION.cffadded and bumped with the version,.gitignorelost the entries of tools which are not used and the stalebuild/andsrc/sbmlutils.egg-info/artifacts of setuptools are gone
Your sbmlutils team
