mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-08-28 18:08:19 +08:00
Regenerate collection_semantics.md
`39597b3366` added the Type Compatibility Algebra section to `collection_semantics.yml` without regenerating the doc it is the source of, so those 102 lines have been missing from `doc/source/dev/collection_semantics.md` since April. Pure output of `python lib/galaxy/model/dataset_collections/types/semantics.py` against the unchanged YAML - no prose is written here. Nothing catches this drift: `--check` only validates the test references, and the generated file is excluded from prettier because prettier fights the generator. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ra8S7P5FFZSmJChT3rvUgN
This commit is contained in:
@@ -1118,3 +1118,105 @@ $$tool(i=C) \rightarrow \left\{o: \text{dataset}\right\}$$
|
||||
|
||||
|
||||
|
||||
## Type Compatibility Algebra
|
||||
|
||||
This section is for implementers. It describes the three operations that
|
||||
answer "do these collection types fit together?" — used at workflow
|
||||
editor connection time and at runtime when sibling inputs are matched
|
||||
under a common map-over.
|
||||
|
||||
### The lattice
|
||||
|
||||
The base types form a small subtype lattice:
|
||||
|
||||
```
|
||||
list paired_or_unpaired
|
||||
| |
|
||||
sample_sheet paired
|
||||
```
|
||||
|
||||
Edges are subtype relations. A `sample_sheet` value carries column
|
||||
metadata that a `list` does not, so it can be substituted where a
|
||||
`list` is required (information is preserved); the reverse is not safe.
|
||||
A `paired` value always has two elements; `paired_or_unpaired` admits
|
||||
1 or 2, so a `paired` can be substituted where `paired_or_unpaired` is
|
||||
required, but not the reverse.
|
||||
|
||||
Nesting composes. `list:paired_or_unpaired` is a supertype of both
|
||||
`list:paired` and `list` (the latter via the "single-dataset wrapped
|
||||
as unpaired" interpretation), so it has two incomparable subtypes.
|
||||
|
||||
### Three operations
|
||||
|
||||
| Operation | Symmetry | Question | Used at |
|
||||
|---|---|---|---|
|
||||
| `accepts(other)` | Asymmetric | Does an input slot of type `self` accept an output of type `other`? | Workflow-editor edge validation |
|
||||
| `compatible(other)` | Symmetric | Do `self` and `other` match such that they could drive a common map-over over sibling inputs of one tool? | Sibling-matching: matching sibling HDCAs / sibling map-over states under a common mapping |
|
||||
| `can_map_over(other)` | Asymmetric | Does `self` have proper subcollections of type `other` — i.e. can `self` be mapped over to feed an `other` slot? | Connection-time map-over decisions; runtime `effective_collection_type` arithmetic |
|
||||
|
||||
Conventions: `input_type.accepts(output_type)` for direct edges;
|
||||
`output_type.can_map_over(input_type)` for map-over. `accepts` and
|
||||
`can_map_over` differ in that `accepts` is the direct-edge case
|
||||
where ranks already align, while `can_map_over` is the strict nesting
|
||||
case where the output has *more* rank than the input. `compatible`
|
||||
is symmetric and either side may go first.
|
||||
|
||||
`compatible(a, b)` is implemented as `a.accepts(b) or b.accepts(a)`.
|
||||
|
||||
### Where each is used
|
||||
|
||||
- `accepts` is called at single-edge validation: connecting one output
|
||||
to one input. The asymmetry between input and output sides matters
|
||||
here. Examples: `connection_types.can_match`,
|
||||
`query.HistoryQuery.direct_match`, and the workflow-editor input
|
||||
attachment paths in `terminals.ts`.
|
||||
|
||||
- `compatible` is called when two collections must drive a common
|
||||
map-over as siblings. Neither side is the input slot; both are
|
||||
concrete shapes (observed HDCA shapes at runtime, sibling map-over
|
||||
states at connection time). Order of arrival must not change the
|
||||
answer. Examples: Python `Tree.compatible_shape` (matching.py,
|
||||
execute.py) and the `mappingConstraints` checks in `terminals.ts`.
|
||||
|
||||
- `can_map_over` is called when deciding whether an output of higher
|
||||
rank can drive a map-over into a lower-rank input — for instance, a
|
||||
`list:paired` output feeding a `paired` input by iterating the outer
|
||||
list. The Python and TypeScript names match
|
||||
(`can_map_over` / `canMapOver`) because it is the same operational
|
||||
question in both layers.
|
||||
|
||||
Routing a sibling-matching question through `accepts` instead of
|
||||
`compatible` produces order-dependent behavior — which sibling input
|
||||
arrived first changes whether the workflow validates. This was a real
|
||||
bug in earlier revisions of both the Python and TypeScript code.
|
||||
|
||||
### Worked examples
|
||||
|
||||
- `paired.accepts(paired_or_unpaired)` is `False`. A 1-element
|
||||
paired_or_unpaired output cannot be connected to an input slot
|
||||
that strictly requires a pair. Test: `test_paired_accepts_relation`.
|
||||
|
||||
- `paired.compatible(paired_or_unpaired)` is `True`. If both observed
|
||||
sibling collections happen to align in cardinality, they match for
|
||||
sibling iteration; cardinality checking happens later at the
|
||||
children level. Test:
|
||||
`test_paired_and_paired_or_unpaired_match_symmetric`.
|
||||
|
||||
- `sample_sheet.accepts(list)` is `False`; `list.accepts(sample_sheet)`
|
||||
is `True`. Tests:
|
||||
`test_sample_sheet_accepts_relation`, workflow editor
|
||||
`"rejects list -> sample_sheet connection (asymmetry)"`.
|
||||
|
||||
- `sample_sheet.compatible(list)` and `list.compatible(sample_sheet)`
|
||||
are both `True`. Tests: `test_compatible`,
|
||||
`test_tree_compatible_shape_sample_sheet_list_symmetric`.
|
||||
|
||||
### Cross-language synchronization
|
||||
|
||||
The Python implementation lives in
|
||||
`lib/galaxy/model/dataset_collections/type_description.py`. The
|
||||
TypeScript implementation lives in
|
||||
`client/src/components/Workflow/Editor/modules/collectionTypeDescription.ts`.
|
||||
Both must stay in sync; method names and conventions are identical.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user