Public API Contract¶
This document defines metaseed's public surface — the symbols a consumer may import and rely on — and the policy governing how that surface changes across releases.
What is public¶
The public API is exactly the set of names exported from the top-level
metaseed package (its __all__). Anything reachable only through a submodule,
and any name prefixed with an underscore, is an implementation detail and is
not covered by the guarantees below.
Stable surface¶
| Symbol | Kind | Contract |
|---|---|---|
MetaseedClient |
class | The primary boundary: create/edit/validate/serialize a dataset for one profile. |
ProfileFacade |
class | In-process entity store; the interactive/notebook entry point. |
get_model |
function | Return the generated Pydantic model for an entity type. |
SpecLoader |
class | Load and cache profile specifications. |
validate |
function | Validate a dataset and return a ValidationResult. |
Entity, EntityNode, EntitySchema, FieldInfo |
classes | Immutable domain objects returned by the client. |
SkippedNode |
class | A payload node a permissive MetaseedClient.load dropped, passed to its on_skip callback. |
ValidationResult, ValidationIssue |
classes | Structured validation output. |
JsonStorage, YamlStorage |
classes | Default storage adapters. |
MetaseedError, EntityNotFoundError, EntityTypeNotFoundError, ProfileNotFoundError |
exceptions | The exception hierarchy; all library errors derive from MetaseedError. |
list_profiles |
function | Discover installed profile names. |
miappe, miappe_htp, isa, darwin_core, dissco, ena, pride, metabolights |
functions | Convenience constructors for a profile facade. The SEEK profile has none: metaseed.seek is the adapter that talks to a SEEK instance, so a facade named seek would shadow it. Use ProfileFacade("seek"). |
__version__ |
attribute | The installed version string. |
Every symbol above resolves from the top-level package:
from metaseed import (
MetaseedClient,
ProfileFacade,
SpecLoader,
get_model,
validate,
Entity,
EntityNode,
EntitySchema,
FieldInfo,
SkippedNode,
ValidationResult,
ValidationIssue,
JsonStorage,
YamlStorage,
MetaseedError,
EntityNotFoundError,
EntityTypeNotFoundError,
ProfileNotFoundError,
list_profiles,
)
The client contract¶
MetaseedClient MUST:
- return immutable domain objects (
Entity,EntityNode,FieldInfo) rather than internal types, so callers cannot mutate engine state through a result; - raise only exceptions derived from
MetaseedErrorfor its own error conditions; and - report ordinary validation failures as a
ValidationResult, not as an exception.
Not public¶
- Any submodule path (
metaseed.facade.store,metaseed.repositories.file, …). These move and change without notice; import from the top-level package. - Underscore-prefixed names and members.
- The adapter internals. The supported entry point for each adapter is its
documented
import_accession/ export function under the corresponding extra, not the modules beneath it.
Extras¶
The core installs with no web or network dependencies. Adapters are optional extras and MUST import without pulling in the web framework:
| Extra | Adds |
|---|---|
metaseed[ena] |
ENA import/export |
metaseed[brapi] |
BrAPI v2 import/export |
metaseed[pride] |
PRIDE / ProteomeXchange import/export |
metaseed[metabolights] |
MetaboLights import/export |
metaseed[seek] |
FAIRDOM-SEEK provisioning/export |
metaseed[dcat] |
DCAT catalog export |
metaseed[docs], metaseed[dev] |
Documentation and development tooling |
Importing an adapter without its extra MUST fail with a clear message naming the
extra to install, not an opaque ModuleNotFoundError.
Versioning and compatibility¶
metaseed follows Semantic Versioning. The version is derived from the Git tag at
build time (hatch-vcs); a v* tag is the single source of release truth and
publishes the release to PyPI.
Pre-1.0 status. While the version is 0.y.z, the public surface is still
settling: a minor bump (0.y) MAY include a breaking change to the public API.
Such changes MUST be recorded in the changelog.
Patch bumps (0.y.z) MUST NOT break the public API.
After 1.0, breaking changes to the public API will be confined to major bumps.
Requires Python 3.11 or newer.
Deprecation policy¶
When a public symbol is to be removed, it SHOULD first be marked deprecated in a release — kept working, documented as deprecated in the changelog — before removal in a later release. Because the project is pre-1.0, a deprecation-then-removal cycle MAY span minor versions rather than requiring a major bump.
How to deprecate¶
A deprecation MUST be machine-visible, not only prose: mark the callable with @deprecated so consumers see it at runtime rather than at removal.
from metaseed.deprecation import deprecated
@deprecated(since="0.23", removed_in="1.0", use_instead="MetaseedClient.load")
def load_dataset(path: str) -> None:
"""Load a dataset from a file."""
Calling it emits a DeprecationWarning naming the callable, the version that deprecated it, the replacement, and the version scheduled for removal, reported against the caller's line. The decorator also appends the same note to the docstring, so help() and the rendered API docs carry it.
deprecated is a maintenance tool, not consumer surface: it is imported from metaseed.deprecation and is deliberately absent from the top-level __all__, so decorating a symbol never enlarges the public API it governs.
since and removed_in are both required. removed_in gives the consumer a deadline instead of an open-ended warning, and it is what makes the policy enforceable — the removal release is decided when the deprecation ships, not when someone remembers. use_instead is optional, for a symbol that goes away with no replacement.
Deprecating a symbol is a change to the public surface and MUST be recorded in the changelog for the release that introduces the warning, and again for the release that removes the symbol.
Consumer contract¶
metaseed-hub is a first-class downstream consumer. Changes that remove or rename a public symbol MUST be checked against metaseed-hub before release.
The table above is the snapshot: tests/test_public_api.py compares it against
metaseed.__all__ and fails when they disagree in either direction, so a symbol
cannot become public without the promise being written down, and a documented
symbol cannot quietly stop being exported. It also checks that every promised
name resolves and that the import example above still runs.
One qualification on "depends only on the public surface": metaseed-hub imports
metaseed.ui.state.AppState and TreeNode, which are not on this list. Those
imports are confined to a single boundary module on the hub side and enforced
there; the session layer they belong to is not yet part of the core (see
ADR 004 and
issue #168).