Skip to content

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.

import metaseed

print(metaseed.__all__)

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 MetaseedError for 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).