Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

What pipekit ships

Report 2 · pipekit's surface, now documented in pipekit; the planning stays here

Abstract

This report began as the proposal for pipekit’s first public surface and became a record of what pipekit 0.0.2 ships. The record now lives with the code, as pipekit’s tour of the core: every module, group by group, with examples checked against a real run and a list of today’s limits. This page keeps what is GeoStack planning rather than pipekit documentation: where the deferred operators went, the open questions and the upcoming work.

Keywords:pipekitoperatorscompositionparallelismserialisation

Where each group went

The proposal organised pipekit by semantic group, one module each, and that organisation shipped (Figure 1). Each group below links its section in the tour and keeps the one difference from the plan that matters to a user; the full inventory has the symbols and line counts.

Fifteen cards, one per pipekit module. Composition, building blocks, combination, caching and quality control shipped as planned. Foundations, control flow, observers, shape inference, parallelism, serialisation and state differ from the plan. Protocols and hashing are new. Group K is reserved and ships nothing.

Figure 1:pipekit 0.0.2 by group, coloured by how each matches the plan.

Group A · Foundations

Now Foundations in the tour. Operator, ConfigMixin, Sequential, Graph, Input, Node. Differs from the plan: no Graph.summary() and no signatures through Graph.

Group B · Composition

Now Composition in the tour. pipe, compose, compose_left, juxt, complement, as planned.

Group C · Building blocks

Now Building blocks in the tour. Identity, Const, Lambda, Sink, as planned.

Group D · Control flow

Now Control flow in the tour. Branch, Switch, Try, Coalesce, Retry. Differs: Try and Retry are not flagged forbid_in_yaml.

Group E · Observers

Now Observers in the tour. Tap, Snapshot, ShapeTrace, Profile, Histogram. Differs: no ShapeTrace hook for an extra line.

Group F · Combination

Now Combination in the tour. Fanout, as planned.

Group G · Caching

Now Caching in the tour. Cache, Memoize, as planned.

Group H · Quality control

Now Quality control in the tour. Quarantine, four Assert* operators and QCError, as planned plus QCError.

Group I · Shape inference

Now Shape inference in the tour. Signature, compute_output_signature. Differs: an unknown dimension prints ? instead of raising, and inference stops at Sequential.

Group J · Parallelism

Now Parallelism in the tour. ThreadMap, ProcessMap, AsyncMap, BatchedMap, check_pickleable. Differs: BatchedMap batches lists, not array axis 0.

The pickleability discipline

Every operator in a process-pool pipeline must pickle, and closures do not. The discipline (forbid_in_yaml, check_pickleable) is in the tour’s Parallelism section.

Group K · Where the deferred operators went

The proposal used Group K for operators that are carrier-specific and so do not belong in core. pipekit 0.0.2 reuses the letter: its docstring reserves Group K for a disk-cache backend, and nothing ships under it. The deferred list is still worth tracking, because most of it has not landed anywhere. Table 1 checks each one against the capability index of every upstream library.

Table 1:The proposal’s deferred operators, and where each one is at pipekit 0.0.2, geotoolz 0.10.2 and xrtoolz 0.0.5.

OperatorWhy not corePlanned homeStatus
ModelOpNumPy-specific (np.asarray, np.concatenate)pipekit-array, or geotoolz / xr_toolzin geotoolz; pipekit-jax adds JaxModelOp
ApplyToBandsNumPy (np.take, np.stack)pipekit-arraynot shipped
SubsampleNumPy slicingpipekit-arraynot shipped
DiffNumPy reductionspipekit-arraynot shipped
AssertValueRange, AssertNoNaN, AssertValidFractionreductions on the arraypipekit-array, or geotoolz / xr_toolznot shipped
Mode, ModeGated, pipeline_modeglobal mode state (contextvars)deferred: open design questionsnot shipped, as planned
Provenance, Watermarkcarrier-specific metadatageotoolz / xr_toolznot shipped
Augmentxr.mergexr_toolzin xrtoolz, as planned
ApplyToEachxr.mergexr_toolzin xrtoolz, as planned
Spy, Hookcross-cutting hooks: open design questionsdeferred; the hook stub is reservednot shipped, as planned

pipekit-array exists (0.0.2), but it ships four names (array_namespace, ConcatenateAlong, StackAlong, MeanScalar), none of them from this list. It is the planned home for most of the list, which makes it the biggest gap between plan and code. Report 3 covers it.

Group L · Serialisation

Now Serialisation in the tour. dumps, loads, loads_sandboxed, register, unregister, allowed. Differs: no YAML or Hydra extras in core; nested pipelines do not round-trip.

Group M · State

Now State in the tour. StatefulOperator, CarryState. Differs: Graph does not thread state.

Group N · Protocols, new

Now Protocols in the tour. Predictor, FittableTransformer: structural seams the plan did not have.

Shared hashing (hashing.py), new

stable_json, stable_repr and sha256_hex, shared by pipekit-experiment’s registry; pipekit’s patterns page uses them for orchestrator task keys.

The full inventory

Table 2 is the canonical list of what each group ships, with the proposed and shipped line counts side by side.

Table 2:The v0.1 inventory as proposed, against pipekit 0.0.2. The proposal’s line counts are estimates; the shipped counts include docstrings.

GroupModuleShipped symbolsProposed linesShipped linesMatches the plan
A · Foundations_base/Operator, ConfigMixin, Carrier, Sequential, Input, Node, Graph~600837differs: no Graph.summary or signatures
B · Compositioncompose.pypipe, compose, compose_left, complement, juxt~60104yes
C · Building blocksblocks.pyIdentity, Const, Lambda, Sink~120145yes
D · Control flowcontrol.pyBranch, Switch, Try, Coalesce, Retry~200373differs: Try, Retry unflagged
E · Observersobserve.pyTap, Snapshot, ShapeTrace, Profile, Histogram~250348differs: no ShapeTrace hook
F · Combinationcombine.pyFanout~8064yes
G · Cachingcache.pyCache, Memoize~80120yes
H · Quality controlqc.pyQuarantine, four Assert*, QCError~130228yes, plus QCError
I · Shape inferencesignature.pySignature, compute_output_signature~150105differs: ? not raise
J · Parallelismparallel.pyThreadMap, ProcessMap, AsyncMap, BatchedMap, check_pickleable~250286differs: list batching
K—nothing (reserved for a disk cache)——repurposed
L · Serialisationserial.pydumps, loads, loads_sandboxed, register, unregister, allowed~80144differs: no extras
M · Statestate.pyStatefulOperator, CarryState~150123differs: no Graph support
N · Protocolsprotocols.pyPredictor, FittableTransformer—61new
Hashinghashing.pyinternal—84new
Total52 public names~2,1503,164

What is intentionally not here

The proposal’s exclusions all held at 0.0.2:

Open questions

The proposal carried seven scoping questions, each with a lean (Table 3). The shipped code settles six of them and partly settles question 4; its leans on questions 3 and 5 were overturned.

Table 3:The proposal’s scoping questions, and how pipekit 0.0.2 answered them.

#QuestionThe proposal’s leanAt 0.0.2
1Name: pipekit, or opkit, composable, pipekit-core?pipekitsettled: pipekit (the PyPI distribution name is revisited in Report 16 §F)
2Is ConfigMixin always on?yes, with __config_mixin_auto__ and __config_exclude__settled as leaned
3How does Signature meet carriers without named dims?None opts out; summary raises a clean errorsettled differently: None opts out, summary prints ?
4How is YAML round-trip enforced?the YAML loader rejects flagged operators; an optional strict=True dumperpartly settled: pipekit-experiment’s HydraConfigLoader.from_yaml loads YAML, nested pipelines included; nothing dumps a nested pipeline, and from_state already rejects flagged operators
5Hydra-zen built in, or an extra?an extra, pipekit[hydra]settled differently: an extra on pipekit-experiment, pipekit-experiment[hydra] (hydra-core and hydra-zen), not on pipekit
6Which of Coalesce, Retry, Mode, Provenance to promote?ship Coalesce and Retry; defer Mode and Provenancesettled as leaned
7AsyncMap only, or AsyncSequential too?AsyncMap onlysettled as leaned

The differences recorded above raise six new questions that need a decision rather than a fix:

  1. Should Graph thread state? Today Sequential does and Graph does not. Either Graph learns to, or the docs say stateful operators are Sequential-only. DA cycles with several inputs would want the former.

  2. Should CarryState be frozen? If yes, it becomes a frozen dataclass and the hash is safe. If not, it should stop defining __hash__, since states routinely hold arrays.

  3. What dumps a nested pipeline? Flat operators round-trip through dumps / loads; Sequential, Try, Cache and the rest do not. Loading is answered by pipekit-experiment’s HydraConfigLoader, which builds nested pipelines from hand-written YAML; the open half is the other direction, a dumper that writes a built pipeline as nested {"class", "config"} payloads or _target_ YAML.

  4. Should AsyncMap.__call__ work inside a running loop? At the moment a server handler must know to call .run. An alternative is to detect a running loop and fail with a message that names .run.

  5. Should shape inference be wired through Graph and Fanout? Only Sequential threads signatures today, so a Graph reports its input signature as its output.

  6. Should a Graph’s state describe the whole graph? Today it records the inputs and the operators that produce the outputs, not the steps upstream of them, so two graphs that differ in an upstream step have equal state and hash the same. Anything that keys work by a pipeline’s hash (the registry, orchestrator tasks, use cases 9, 12 and 15) needs the whole graph, which is also what a Graph dumper (question 3) would write.

Upcoming work

Changes whose shape is already clear (Table 4). Each is a candidate issue on pipekit or a sister library.

Table 4:Follow-ups from checking the proposal against pipekit 0.0.2.

Follow-upWhereWhy
Fix the compute_output_signature docstring: summary shows ?, it does not raisepipekit _base/operator.pythe docstring contradicts the behaviour
Fix the dumps docstring: a flagged operator fails with RuntimeError, not TypeErrorpipekit serial.pythe same
Add Graph.summary() and signature propagation through Graphpipekit _base/graph.pyproposed and not shipped
Make Graph.state record every node, not only the output operatorspipekit _base/graph.pytwo graphs differing upstream hash the same (question 6)
Override compute_output_signature in Fanout and the parallel maps, returning Nonepipekit combine.py, parallel.pytoday they report a passthrough signature for a dict or a list
Route ProcessMap(on_error="log_and_continue") through loggingpipekit parallel.pydeployments cannot capture or silence stderr prints
Add a ShapeTrace hook for an extra line (the geotoolz CRS line)pipekit observe.pyproposed and not shipped
Ship axis-0 batching, ApplyToBands, Subsample, Diff and the numeric assertspipekit-arrayassigned there by the proposal; nothing has shipped
Decide where Provenance and Watermark live, and build themgeotoolz, xrtoolzassigned there by the proposal; not shipped
Build CatalogPipeline on ProcessMap / ThreadMapa sister library (geotoolz-catalog)use cases 2 and 12 assume it

References

Citations

To be added: toolz, the Python Array API standard, and the use-case gallery, as entries in references.bib.