Architecture

httk₂ is a PEP 420 native namespace package. The top-level httk package has no implementation of its own; independently released repositories contribute subpackages such as httk.core, httk.io, and httk.atomistic.

The layering rule is simple: contracts and models belong in httk-core, while capabilities belong in the modules that implement them. Core therefore provides the shared vocabulary used in signatures — vectors, datastreams, OPTIMADE definitions, entry-provider contracts, record models, and DataLoader — without external dependencies. Parsing, data management, protocol serving, and workflow execution remain capabilities in other repositories.

Modules expose capabilities through handler packages such as httk.handlers.io. Import-time discovery finds these packages and lets them register loaders or entry providers with core. A feature module and its handler registration package can consequently remain separate while sharing the core registry contracts.

One typical integration path is httk-iohttk-atomistichttk-optimade: the I/O module reads a neutral file-format mapping, atomistic turns it into an exact structure model, and an OPTIMADE adapter serves described records through the provider contract. The layers communicate through stable core types rather than importing one another’s implementation details.

Core design decisions

The modules in httk₂ are independent packages, but they follow the same small set of design contracts. These contracts are what let data move between modules, representations, and storage systems without silently changing its meaning.

Backends own data; views expose representations

Data-representation classes consistently follow the Backend/View pattern. A backend owns the original representation and its data, while views expose that backend through another public interface. This separates what an object is from how a caller needs to work with it and allows new representations to be added without pairwise conversion code between every class.

Exact by default

httk₂ does not perform lossy conversions behind the user’s back. Exact values and the original backend remain the source of truth; data is approximated or otherwise modified only when the caller explicitly requests a lossy operation or presentation. View round-trips retain the backend object, so constructing View B from View A and then returning to View A recovers the original backend and preserves its data exactly—even if View B presented an approximation.

Immutable by default

Data-representation objects are to be treated as immutable unless their class name starts with Mutable. Python cannot enforce this contract in every case, so callers must not mutate internal data merely because an implementation detail happens to be reachable. Immutability makes shared backends, safe views, exact round-trips, hashing, and deduplication dependable.

Semantic properties through OPTIMADE definitions

OPTIMADE property and entry-type definitions are central to httk₂. They give data fields machine-readable identity, type, shape, units, and meaning, allowing modules, databases, and protocol adapters to exchange semantically described records rather than unrelated dictionaries with coincidentally similar keys.

Storage independent of the database backend

The httk₂ ORM stores and reconstructs ordinary frozen dataclasses through a database-backend-agnostic API. The same domain objects and query expressions work across supported databases; SQL generation and dialect details remain behind the storage backend instead of leaking into the models or their callers.

Views are usually lazy

Most views convert from their backend only when data is actually requested. Constructing a view does not eagerly convert the underlying data, which avoids unnecessary conversions when a view is only passed along or partially used.