GTR036 — Replace deprecated <output type="data"> (codemod)
Contract: behaviour-preserving.
Claim
Renaming <output type="data"> to <data> (dropping the attribute) is a
parse-level no-op.
Proof
Galaxy routes an <output type="data"> through the same _parse as
<data> (tool_util/parser/xml.py:548-563).
Proof — the collection variant (ledger item C3, shipped)
The same routing block remaps the deprecated collection path in place —
attrib["type"] = unicodify(collection_type), attrib["type_source"] = unicodify(collection_type_source) — then parses via the same
_parse_collection as a <collection>. unicodify(None) is None (typed
overload, util/__init__.py:1190-1196), which reads identically to an absent
attribute, so when collection_type is present the static rewrite mirrors the
remap exactly.
Scope boundary
<output type="collection"> with no collection_type stays advisory — and
the degenerate case is now verified broken (2026-06-10): Galaxy’s tree is
lxml (galaxy.util re-exports from lxml import etree,
util/__init__.py:85), so the deprecated path’s
attrib["type"] = unicodify(None) raises TypeError at load — the tool never
worked. <output> with no type (an expression output — a different kind)
also stays advisory. Shipped at
~1-tool / ~0-tool corpus incidence — “not gated on corpus frequency” (the
ledger’s precedent rule).