galaxy-tool-codemod 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- galaxy_tool_codemod-0.2.0/.gitignore +22 -0
- galaxy_tool_codemod-0.2.0/CLAUDE.md +155 -0
- galaxy_tool_codemod-0.2.0/LICENSE +21 -0
- galaxy_tool_codemod-0.2.0/PKG-INFO +134 -0
- galaxy_tool_codemod-0.2.0/PLAN.md +454 -0
- galaxy_tool_codemod-0.2.0/README.md +120 -0
- galaxy_tool_codemod-0.2.0/docs/architecture.md +315 -0
- galaxy_tool_codemod-0.2.0/docs/behavior-preserving-upgrade.md +163 -0
- galaxy_tool_codemod-0.2.0/docs/decisions.md +1845 -0
- galaxy_tool_codemod-0.2.0/docs/macro-aware-normalization.md +162 -0
- galaxy_tool_codemod-0.2.0/pyproject.toml +50 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/__init__.py +12 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/_version.py +21 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/canonical.py +109 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/catalog.py +90 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/certify.py +47 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/change.py +63 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemod.py +136 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/__init__.py +7 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/_attribute_ordering.py +24 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/_cdata.py +46 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/_coarse_detect.py +65 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/_interpreter.py +125 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/_runtime_gated.py +21 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/_validation_repair.py +32 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/convert_help_markdown.py +117 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/drop_redundant_param_name.py +88 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/fix_from_work_dir_whitespace.py +57 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/fix_interpreter.py +126 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/fix_output_format_input.py +150 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/fix_typos.py +184 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/normalize_boolean_values.py +138 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/reorder_param_attributes.py +61 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/reorder_tool_attributes.py +52 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/reorder_tool_children.py +68 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/repair_help_rst.py +71 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/replace_output_element.py +113 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/single_quote_command_vars.py +139 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/tokenize_version.py +93 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/trim_attribute_whitespace.py +84 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/update_profile.py +110 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/upgrade_19_01.py +96 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/upgrade_21_09.py +245 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/upgrade_24_0.py +98 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/upgrade_24_1.py +74 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/upgrade_25_1.py +48 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/wrap_command_cdata.py +42 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/codemods/wrap_help_cdata.py +42 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/cursor.py +281 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/datatype_format.py +63 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/eligibility.py +81 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/module.py +65 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/parse.py +47 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/profile_semantics.py +620 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/py.typed +0 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/runtime_fixes.py +77 -0
- galaxy_tool_codemod-0.2.0/src/galaxy_tool_codemod/upgrades.py +137 -0
- galaxy_tool_codemod-0.2.0/tests/conftest.py +31 -0
- galaxy_tool_codemod-0.2.0/tests/data/minimal_tool.xml +5 -0
- galaxy_tool_codemod-0.2.0/tests/data/regressions/PROVENANCE.md +18 -0
- galaxy_tool_codemod-0.2.0/tests/data/tool_with_params.xml +16 -0
- galaxy_tool_codemod-0.2.0/tests/test_attribute_ordering.py +42 -0
- galaxy_tool_codemod-0.2.0/tests/test_canonical.py +144 -0
- galaxy_tool_codemod-0.2.0/tests/test_catalog.py +66 -0
- galaxy_tool_codemod-0.2.0/tests/test_change.py +73 -0
- galaxy_tool_codemod-0.2.0/tests/test_coarse_detect.py +61 -0
- galaxy_tool_codemod-0.2.0/tests/test_codemod.py +206 -0
- galaxy_tool_codemod-0.2.0/tests/test_convert_help_markdown.py +132 -0
- galaxy_tool_codemod-0.2.0/tests/test_cursor.py +437 -0
- galaxy_tool_codemod-0.2.0/tests/test_datatype_format.py +57 -0
- galaxy_tool_codemod-0.2.0/tests/test_drop_redundant_param_name.py +86 -0
- galaxy_tool_codemod-0.2.0/tests/test_eligibility.py +124 -0
- galaxy_tool_codemod-0.2.0/tests/test_fix_from_work_dir_whitespace.py +76 -0
- galaxy_tool_codemod-0.2.0/tests/test_fix_interpreter.py +181 -0
- galaxy_tool_codemod-0.2.0/tests/test_fix_output_format_input.py +162 -0
- galaxy_tool_codemod-0.2.0/tests/test_fix_typos.py +146 -0
- galaxy_tool_codemod-0.2.0/tests/test_interpreter.py +122 -0
- galaxy_tool_codemod-0.2.0/tests/test_module.py +75 -0
- galaxy_tool_codemod-0.2.0/tests/test_normalize_boolean_values.py +105 -0
- galaxy_tool_codemod-0.2.0/tests/test_parse.py +82 -0
- galaxy_tool_codemod-0.2.0/tests/test_profile_semantics.py +376 -0
- galaxy_tool_codemod-0.2.0/tests/test_regressions.py +139 -0
- galaxy_tool_codemod-0.2.0/tests/test_reorder_param_attributes.py +145 -0
- galaxy_tool_codemod-0.2.0/tests/test_reorder_tool_attributes.py +76 -0
- galaxy_tool_codemod-0.2.0/tests/test_reorder_tool_children.py +125 -0
- galaxy_tool_codemod-0.2.0/tests/test_repair_help_rst.py +77 -0
- galaxy_tool_codemod-0.2.0/tests/test_replace_output_element.py +128 -0
- galaxy_tool_codemod-0.2.0/tests/test_runtime_fixes.py +49 -0
- galaxy_tool_codemod-0.2.0/tests/test_single_quote_command_vars.py +191 -0
- galaxy_tool_codemod-0.2.0/tests/test_smoke.py +10 -0
- galaxy_tool_codemod-0.2.0/tests/test_tokenize_version.py +121 -0
- galaxy_tool_codemod-0.2.0/tests/test_trim_attribute_whitespace.py +73 -0
- galaxy_tool_codemod-0.2.0/tests/test_update_profile.py +146 -0
- galaxy_tool_codemod-0.2.0/tests/test_upgrade_19_01.py +130 -0
- galaxy_tool_codemod-0.2.0/tests/test_upgrade_21_09.py +217 -0
- galaxy_tool_codemod-0.2.0/tests/test_upgrade_24_0.py +163 -0
- galaxy_tool_codemod-0.2.0/tests/test_upgrade_24_1.py +165 -0
- galaxy_tool_codemod-0.2.0/tests/test_upgrade_25_1.py +63 -0
- galaxy_tool_codemod-0.2.0/tests/test_upgrades.py +133 -0
- galaxy_tool_codemod-0.2.0/tests/test_wrap_command_cdata.py +88 -0
- galaxy_tool_codemod-0.2.0/tests/test_wrap_help_cdata.py +78 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Build / dist artifacts
|
|
2
|
+
build/
|
|
3
|
+
dist/
|
|
4
|
+
*.egg-info/
|
|
5
|
+
|
|
6
|
+
# Python bytecode
|
|
7
|
+
__pycache__/
|
|
8
|
+
*.pyc
|
|
9
|
+
|
|
10
|
+
# Tooling caches
|
|
11
|
+
.mypy_cache/
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.ruff_cache/
|
|
14
|
+
|
|
15
|
+
# uv
|
|
16
|
+
.venv/
|
|
17
|
+
uv.lock
|
|
18
|
+
|
|
19
|
+
# Editor
|
|
20
|
+
.idea/
|
|
21
|
+
.vscode/
|
|
22
|
+
*.swp
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Guidance for Claude Code working in this repository.
|
|
4
|
+
|
|
5
|
+
## Project
|
|
6
|
+
|
|
7
|
+
`galaxy-tool-codemod` is the **structure** tier of the Galaxy tool
|
|
8
|
+
refactoring framework — one of seven tiers (this package depends only on tier 1
|
|
9
|
+
and the shared tier-0.5 rules metadata):
|
|
10
|
+
|
|
11
|
+
| Tier | Layer | Package | What it owns |
|
|
12
|
+
|---|---|---|---|
|
|
13
|
+
| 0.5 | **rule metadata** | `galaxy-tool-refactor-rules` | shared `RuleMeta` + `Violation` |
|
|
14
|
+
| 1 | **parsing & validation** | `galaxy-tool-source` | parsing, profile-aware XSD validation, typed views |
|
|
15
|
+
| 2 | **structure** | `galaxy-tool-codemod` *(this repo)* | structural mutations (attribute order, element shape) |
|
|
16
|
+
| 3 | **formatting** | `galaxy-tool-fmt` | whitespace / indentation / shorthand; the only tier that serialises canonical output XML |
|
|
17
|
+
| 3.5 | **advisory checks** | `galaxy-tool-lint` | detect-only IUC best-practice checks |
|
|
18
|
+
| 3.6 | **rule registry / rulesets** | `galaxy-tool-refactor-registry` | unified rule registry + rulesets; library-first facade |
|
|
19
|
+
| 4 | **app / CLI** | `galaxy-tool-refactor-cli` | composes the tiers via the facade (`format`/`upgrade`/`check`) |
|
|
20
|
+
|
|
21
|
+
This package supplies the **structural-refactor framework**: a
|
|
22
|
+
``CodemodCommand`` **detect-primitive** base with tag-PascalCase dispatch
|
|
23
|
+
(``detect_Param``, ``detect_Tool``, …) whose ``apply`` is derived from
|
|
24
|
+
``detect`` (each rule has a non-mutating detect phase + a fix phase), an
|
|
25
|
+
``lxml``-backed ``Cursor``
|
|
26
|
+
with typed mutation primitives (``set_attribute``, ``delete_attribute``,
|
|
27
|
+
``rename_attribute``, ``rename_tag``, ``reorder_attributes``,
|
|
28
|
+
``reorder_children``, ``remove``, ``add_child``, ``attribute_names``,
|
|
29
|
+
``set_text`` — the token-aware ``@PROFILE@`` rewrite, §21), a
|
|
30
|
+
``Module`` wrapper (over a tier-1 ``ToolDocument``), a ``parse_module`` entry
|
|
31
|
+
point (plus ``MacroModule`` / ``parse_macro_module`` — the macro-file
|
|
32
|
+
counterparts wrapping a tier-1 ``MacroDocument``; ``Cursor`` is generic, so its
|
|
33
|
+
mutators work on a ``<macros>`` tree unchanged. The ``CodemodCommand`` base
|
|
34
|
+
stays tool-only until a macro-subject codemod needs it — see ``docs/decisions.md``
|
|
35
|
+
§20), and the bundled codemods exposed via two ordered pipeline
|
|
36
|
+
contracts in ``canonical.py``:
|
|
37
|
+
|
|
38
|
+
- ``canonical_codemods()`` = ``FixTypos`` → ``NormalizeBooleanValues`` →
|
|
39
|
+
``RepairHelpRst`` → ``TrimAttributeWhitespace`` → ``ReplaceOutputElement`` →
|
|
40
|
+
``DropRedundantParamName`` → ``ReorderParamAttributes`` →
|
|
41
|
+
``ReorderToolAttributes`` → ``ReorderToolChildren`` → ``WrapCommandCdata`` →
|
|
42
|
+
``WrapHelpCdata`` → ``SingleQuoteCommandVars`` (the safe canonical/format
|
|
43
|
+
pipeline; ``TrimAttributeWhitespace`` / ``ReplaceOutputElement`` /
|
|
44
|
+
``DropRedundantParamName`` = GTR035.1/GTR036/GTR037, the planemo-parity fixes
|
|
45
|
+
(GTR035 partitioned: the name-trim residual is the GTR035.2 advisory, §33);
|
|
46
|
+
``ReorderToolChildren`` = GTR013, IUC #52 element order, validity-safe because
|
|
47
|
+
``<tool>`` is ``xs:all``; ``WrapCommandCdata`` / ``WrapHelpCdata`` =
|
|
48
|
+
GTR018.1/GTR019.1, IUC #34/#42, wrap a pure-text ``<command>``/``<help>`` body in
|
|
49
|
+
CDATA — behaviour-preserving, ``docs/decisions.md`` §29;
|
|
50
|
+
``SingleQuoteCommandVars`` = GTR020.1, IUC #36, single-quote the *provably*-
|
|
51
|
+
single-valued Cheetah vars in ``<command>`` — behaviour-preserving but the first
|
|
52
|
+
canonical codemod to shift default-``format`` bytes vs the pre-partition output,
|
|
53
|
+
``docs/decisions.md`` §30; ``RepairHelpRst`` = GTR089.1, repair
|
|
54
|
+
deterministically-fixable invalid ``<help>`` reStructuredText behind a
|
|
55
|
+
render-equivalence gate, ``docs/decisions.md`` §37. The five
|
|
56
|
+
``Wrap…``/``SingleQuote…``/``RepairHelpRst``/``TrimAttributeWhitespace`` codemods
|
|
57
|
+
are the fixable ``.1`` half of a partition practice — their advisory ``.2`` residual lives in the check tier;
|
|
58
|
+
registry ``docs/decisions.md`` D10).
|
|
59
|
+
- ``AUTO_UPGRADE_CODEMODS`` = ``FixTypos`` → ``NormalizeBooleanValues`` →
|
|
60
|
+
``UpgradeToLatest`` (the opt-in profile-upgrade pipeline).
|
|
61
|
+
|
|
62
|
+
``ConvertHelpToMarkdown`` (GTR092, ``docs/decisions.md`` §38) is in neither
|
|
63
|
+
pipeline: the first of the catalog's **opt-in-command-only** codemods (no ruleset; applied
|
|
64
|
+
solely by the app's ``convert-help``) — the RST → Markdown ``<help>`` conversion
|
|
65
|
+
behind tier-1 ``rst_markdown``'s render-equivalence gate + the profile ≥ 24.2 XSD
|
|
66
|
+
gate. Its sibling ``TokenizeVersion`` (GTR094, §43) is the second:
|
|
67
|
+
the @TOOL_VERSION@/@VERSION_SUFFIX@ extraction behind the expansion-equality
|
|
68
|
+
gate, applied solely by ``tokenize-version``.
|
|
69
|
+
|
|
70
|
+
``FixTypos``, ``NormalizeBooleanValues`` (GTR017 — boolean-case repair, the
|
|
71
|
+
``True``/``False`` → ``true``/``false`` fix ``FixTypos`` cannot reach), and
|
|
72
|
+
``UpgradeToLatest`` (which loops ``UpdateProfile`` + single-step ``upgrade_vN``
|
|
73
|
+
codemods from ``upgrades.py``) are validation-driven and override ``apply``. The upgrade registry is grown
|
|
74
|
+
empirically from ``corpus_check codemod`` discovery sweeps; see
|
|
75
|
+
``docs/decisions.md`` §11–14, §16 for the canonical/upgrade split, and
|
|
76
|
+
§17–18 for the element-order codemod (GTR013) + the `codemod` sweep's
|
|
77
|
+
`--source combined` default.
|
|
78
|
+
|
|
79
|
+
**Tier independence:** this package does not depend on fmt. The
|
|
80
|
+
orchestration — running these pipelines and writing output through fmt's
|
|
81
|
+
serializer — lives in the tier-3.6 registry facade
|
|
82
|
+
(``galaxy-tool-refactor-registry``), which consumes ``canonical_codemods()``
|
|
83
|
+
(its ``run`` / the app's ``format``) and ``AUTO_UPGRADE_CODEMODS`` (its
|
|
84
|
+
``upgrade``); the tier-4 app CLI (``galaxy-tool-refactor-cli``) is a thin
|
|
85
|
+
front-end over that facade. fmt's own CLI is cosmetic-only and does not
|
|
86
|
+
consume these contracts (see ``galaxy-tool-fmt/docs/decisions.md``
|
|
87
|
+
§D12).
|
|
88
|
+
|
|
89
|
+
The architecture rationale lives in `docs/architecture.md` (a working
|
|
90
|
+
copy forked from `galaxy-tool-source/docs/codemod-architecture.md` —
|
|
91
|
+
predates the M1-M3.5 implementation; the current shape is recorded in
|
|
92
|
+
`docs/decisions.md`). Milestone status and remaining work are in
|
|
93
|
+
`PLAN.md`.
|
|
94
|
+
|
|
95
|
+
## Coding standards
|
|
96
|
+
|
|
97
|
+
Hand-written code follows **dignified-python**, vendored at the workspace root
|
|
98
|
+
`.claude/skills/dignified-python/`:
|
|
99
|
+
|
|
100
|
+
- LBYL over `try/except`. Exceptions only at the CLI error boundary
|
|
101
|
+
(chained `from e`) and at third-party API boundaries with no LBYL form.
|
|
102
|
+
- `pathlib.Path` with explicit `encoding="utf-8"` on text I/O.
|
|
103
|
+
- Keyword-only arguments after the first.
|
|
104
|
+
- Absolute imports, no re-exports, no `__all__`.
|
|
105
|
+
- No import-time side effects (`@cache` for module state).
|
|
106
|
+
|
|
107
|
+
`optimized-python` (`.claude/skills/optimized-python/`) is a secondary
|
|
108
|
+
reference; **dignified-python governs on conflict**.
|
|
109
|
+
|
|
110
|
+
## Workflow
|
|
111
|
+
|
|
112
|
+
- **Test-driven development.** New code lands tests-first (failing test,
|
|
113
|
+
then minimum code to pass). One test module per source module under
|
|
114
|
+
`tests/`.
|
|
115
|
+
- **Plan-driven**: major changes get a written plan (either under
|
|
116
|
+
`~/.claude/plans/` for agent state, or in `PLAN.md` for repo-scoped
|
|
117
|
+
plans) before implementation.
|
|
118
|
+
- **Empirical claims must be backed by data.** Use the workspace corpus
|
|
119
|
+
artifacts (`../docs/corpus_data/`), `../scripts/measure.py`, and the
|
|
120
|
+
`corpus_check.py codemod` subcommand when answering questions about
|
|
121
|
+
real-world tool XML.
|
|
122
|
+
- **Decisions are recorded** in `docs/decisions.md` once they land
|
|
123
|
+
(mirror the parent's `docs/decisions.md` conventions: §-numbered,
|
|
124
|
+
each entry citing date and a reproduction command when relevant).
|
|
125
|
+
- See `galaxy-tool-source/docs/decisions.md` §9 for the three-tier
|
|
126
|
+
rationale.
|
|
127
|
+
|
|
128
|
+
## Commands
|
|
129
|
+
|
|
130
|
+
Run these from the **workspace root** (`galaxy-tool-refactor/`):
|
|
131
|
+
|
|
132
|
+
- `uv sync` — install dependencies
|
|
133
|
+
- `uv run --package galaxy-tool-codemod pytest galaxy-tool-codemod/tests/` — run tests
|
|
134
|
+
- `uv run ruff check galaxy-tool-codemod/src galaxy-tool-codemod/tests` — lint
|
|
135
|
+
- `uv run mypy --config-file galaxy-tool-codemod/pyproject.toml galaxy-tool-codemod/src` — type-check (strict)
|
|
136
|
+
- `uv run python -m scripts.corpus_check codemod <dotted.module>:<ClassName>` — sweep a codemod across the corpus, retain failures as fixtures
|
|
137
|
+
- e.g. `uv run python -m scripts.corpus_check codemod galaxy_tool_codemod.codemods.reorder_param_attributes:ReorderParamAttributes`
|
|
138
|
+
|
|
139
|
+
## Useful workspace references
|
|
140
|
+
|
|
141
|
+
- `galaxy-tool-source/README.md` — tier-1 public API
|
|
142
|
+
- `galaxy-tool-source/docs/decisions.md` §3 (trivia contract), §6 (corpus
|
|
143
|
+
stats), §9 (three-tier vision)
|
|
144
|
+
- `galaxy-tool-source/docs/codemod-architecture.md` — the original tier-2 design
|
|
145
|
+
- `galaxy-tool-refactor-registry/src/galaxy_tool_refactor_registry/apply.py` —
|
|
146
|
+
the tier-3.6 facade that runs ``canonical_codemods()`` order (consumed by
|
|
147
|
+
``run`` / the app's ``format``); `rulesets.py` derives the `default` ruleset from
|
|
148
|
+
per-rule ``RuleMeta.rulesets`` membership
|
|
149
|
+
- `canonical.py` — the public ``canonical_codemods()`` and
|
|
150
|
+
``AUTO_UPGRADE_CODEMODS`` pipeline contracts the registry facade consumes
|
|
151
|
+
- `codemods/` — bundled codemod implementations (verb-noun module names)
|
|
152
|
+
- `eligibility.py` — corpus-sweep profile-selection policy
|
|
153
|
+
- `../docs/corpus_data/combined_corpus_data.json` — every swept Galaxy
|
|
154
|
+
tool, indexed for ad-hoc analysis
|
|
155
|
+
- `../scripts/measure.py` — master script for empirical corpus queries
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Richard Burhans
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: galaxy-tool-codemod
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Structural-refactor framework for Galaxy tool XML — tier 2 of the galaxy-tool-source ecosystem.
|
|
5
|
+
Author: Richard Burhans
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: galaxy-tool-refactor-rules==0.2.0
|
|
10
|
+
Requires-Dist: galaxy-tool-source==0.2.0
|
|
11
|
+
Requires-Dist: lxml>=5
|
|
12
|
+
Requires-Dist: packaging>=23
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# galaxy-tool-codemod
|
|
16
|
+
|
|
17
|
+
A LibCST-shaped framework for structural refactors of Galaxy tool XML.
|
|
18
|
+
The **structure** tier of the Galaxy refactoring architecture:
|
|
19
|
+
|
|
20
|
+
| Tier | Layer | Package | Role |
|
|
21
|
+
|---|---|---|---|
|
|
22
|
+
| 0.5 | **rule metadata** | `galaxy-tool-refactor-rules` | shared `RuleMeta` descriptor |
|
|
23
|
+
| 1 | **parsing & validation** | `galaxy-tool-source` | parse · profile-aware validate · typed view |
|
|
24
|
+
| 2 | **structure** | **`galaxy-tool-codemod`** *(this repo)* | structural refactors |
|
|
25
|
+
| 3 | **formatting** | `galaxy-tool-fmt` | cosmetic `black`-like formatter |
|
|
26
|
+
| 3.5 | **advisory checks** | `galaxy-tool-lint` | detect-only checks |
|
|
27
|
+
| 3.6 | **rule registry / rulesets** | `galaxy-tool-refactor-registry` | unified rules + rulesets (facade) |
|
|
28
|
+
| 4 | **app / CLI** | `galaxy-tool-refactor-cli` | composes the tiers via the facade (`format` / `upgrade` / `check`) |
|
|
29
|
+
|
|
30
|
+
## Status
|
|
31
|
+
|
|
32
|
+
M1–M3.5 shipped: framework primitives (`Module`, `Cursor`,
|
|
33
|
+
`CodemodCommand`), the `corpus_check.py codemod` sweep (retains failures
|
|
34
|
+
as regression fixtures), and two ordered pipeline contracts run by the
|
|
35
|
+
tier-4 app (`galaxy-tool-refactor-cli`):
|
|
36
|
+
|
|
37
|
+
- **`canonical_codemods()`** = `FixTypos → NormalizeBooleanValues → RepairHelpRst →
|
|
38
|
+
TrimAttributeWhitespace → ReplaceOutputElement → DropRedundantParamName →
|
|
39
|
+
ReorderParamAttributes → ReorderToolAttributes → ReorderToolChildren →
|
|
40
|
+
WrapCommandCdata → WrapHelpCdata → SingleQuoteCommandVars` — the safe
|
|
41
|
+
canonical/format pipeline (the app's `format` command), **derived** from the codemods
|
|
42
|
+
declaring the `"default"` ruleset and ordered by `meta.order` (no hardcoded tuple,
|
|
43
|
+
§36). Never changes `profile=`.
|
|
44
|
+
- **`AUTO_UPGRADE_CODEMODS`** = `FixTypos → NormalizeBooleanValues →
|
|
45
|
+
UpgradeToLatest` — the opt-in profile-upgrade pipeline (the app's `upgrade`
|
|
46
|
+
command).
|
|
47
|
+
|
|
48
|
+
The codemods:
|
|
49
|
+
|
|
50
|
+
- `FixTypos` — repair near-miss spelling typos so a
|
|
51
|
+
well-formed-but-globally-invalid tool validates (in both pipelines);
|
|
52
|
+
- `NormalizeBooleanValues` — rewrite Python-style boolean attribute values
|
|
53
|
+
(`True`/`Yes`/…) to canonical `xs:boolean` so a globally-invalid tool
|
|
54
|
+
validates; schema-type-aware and behaviour-preserving (in both pipelines);
|
|
55
|
+
- `UpgradeToLatest` — loop `UpdateProfile` (declare the newest profile the
|
|
56
|
+
tool validates at, bump-up-only) + single-step `upgrade_vN` codemods from
|
|
57
|
+
`upgrades.py` to bring a tool to the latest profile (`UpdateProfile` is a
|
|
58
|
+
building block run *inside* this loop, not a separate pipeline entry);
|
|
59
|
+
- `ReorderParamAttributes` / `ReorderToolAttributes` — IUC `<param>` and
|
|
60
|
+
documented `<tool>` attribute order;
|
|
61
|
+
- `ReorderToolChildren` — IUC `<tool>` child-element order (best-practice #52);
|
|
62
|
+
validity-safe because the `<tool>` content model is order-free (`xs:all`).
|
|
63
|
+
|
|
64
|
+
Every bundled codemod carries a `RuleMeta` GTR code; `catalog.coded_codemods()` is the
|
|
65
|
+
authoritative enumeration (the prose list above is illustrative — `format` also runs the
|
|
66
|
+
planemo-parity fixers GTR035–037 and the partition `.1` fixers GTR018.1/019.1/020.1 and
|
|
67
|
+
GTR089.1 `RepairHelpRst`). See `docs/decisions.md` §15–37.
|
|
68
|
+
|
|
69
|
+
The upgrade registry is grown empirically: the `corpus_check codemod`
|
|
70
|
+
sweep reports `STICKING POINT` versions still needing an `upgrade_vN`, and
|
|
71
|
+
each `upgrade_vN`'s advance count. Upgrades shipped: `Upgrade24_1`
|
|
72
|
+
(24.1 → 24.2), `Upgrade25_1` (25.1 → 26.0). See `docs/decisions.md` §11–14.
|
|
73
|
+
|
|
74
|
+
M4 (matcher language) and M5 (Cheetah reference resolver) are not yet
|
|
75
|
+
implemented — see `PLAN.md`.
|
|
76
|
+
|
|
77
|
+
## Public API
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from pathlib import Path
|
|
81
|
+
|
|
82
|
+
from galaxy_tool_codemod.parse import parse_module
|
|
83
|
+
from galaxy_tool_codemod.canonical import canonical_codemods
|
|
84
|
+
|
|
85
|
+
module = parse_module(Path("tool.xml"))
|
|
86
|
+
for codemod_cls in canonical_codemods():
|
|
87
|
+
codemod_cls().apply(module)
|
|
88
|
+
# module.document.tree now reflects the canonical structural form
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
| Symbol | Purpose |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `parse.parse_module(source)` | Entry point — accepts `Path \| bytes \| ToolDocument`. |
|
|
94
|
+
| `module.Module` | Frozen wrapper carrying `document`, `model`, `cursor`. |
|
|
95
|
+
| `cursor.Cursor` | lxml-backed view with read + typed mutation primitives. |
|
|
96
|
+
| `codemod.CodemodCommand` | Base for user-authored codemods (tag-PascalCase dispatch). |
|
|
97
|
+
| `codemods.fix_typos.FixTypos` | Repair near-miss typos until a globally-invalid tool validates (canonical, runs first). |
|
|
98
|
+
| `codemods.normalize_boolean_values.NormalizeBooleanValues` | Normalize Python-style boolean values (`True`/`Yes`/…) to `xs:boolean` until a globally-invalid tool validates (canonical, GTR017). |
|
|
99
|
+
| `codemods.repair_help_rst.RepairHelpRst` | Repair deterministically-fixable invalid `<help>` reStructuredText behind a render-equivalence gate (canonical, GTR089.1; the fix half of the GTR089 partition). |
|
|
100
|
+
| `upgrades.UpgradeToLatest` | In `AUTO_UPGRADE_CODEMODS`. Loop UpdateProfile + single-step upgrades to reach the latest profile. |
|
|
101
|
+
| `codemods.update_profile.UpdateProfile` | Declare the newest profile the tool validates at, bump-up-only. Building block run *inside* `UpgradeToLatest` — not itself a pipeline member. |
|
|
102
|
+
| `upgrades.UPGRADE_CODEMODS` | Registry: sticking version → its single-step upgrade codemod. |
|
|
103
|
+
| `codemods.upgrade_24_1.Upgrade24_1` | Single-step 24.1 → 24.2 (normalize `format` / `ftype`). |
|
|
104
|
+
| `codemods.upgrade_25_1.Upgrade25_1` | Single-step 25.1 → 26.0 (drop obsolete `<trackster_conf>`). |
|
|
105
|
+
| `codemods.reorder_param_attributes.ReorderParamAttributes` | IUC `<param>` attribute order. |
|
|
106
|
+
| `codemods.reorder_tool_attributes.ReorderToolAttributes` | Documented `<tool>` attribute prefix. |
|
|
107
|
+
| `codemods.reorder_tool_children.ReorderToolChildren` | IUC `<tool>` child-element order (#52). |
|
|
108
|
+
| `canonical.canonical_codemods()` | Ordered canonical/format pipeline (the app's `format` command). |
|
|
109
|
+
| `canonical.AUTO_UPGRADE_CODEMODS` | Ordered opt-in upgrade pipeline (the app's `upgrade` command). |
|
|
110
|
+
| `catalog.coded_codemods` | Every GTR-coded codemod, sorted by code (for the rule registry). |
|
|
111
|
+
| `eligibility.corpus_test_profile` | Codemod-sweep validation-profile policy (sweep default). |
|
|
112
|
+
|
|
113
|
+
## Setup
|
|
114
|
+
|
|
115
|
+
From the workspace root:
|
|
116
|
+
|
|
117
|
+
```sh
|
|
118
|
+
uv sync
|
|
119
|
+
uv run --package galaxy-tool-codemod pytest galaxy-tool-codemod/tests/
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Relationship to fmt and the app
|
|
123
|
+
|
|
124
|
+
Neither `galaxy-tool-fmt`'s library nor its CLI depends on this
|
|
125
|
+
package — fmt is cosmetic-only. Orchestration lives one tier up: the
|
|
126
|
+
`galaxy-tool-refactor` app CLI (`galaxy-tool-refactor-cli`) hard-depends
|
|
127
|
+
on this package and on fmt, runs `canonical_codemods()` (its `format`
|
|
128
|
+
command) or `AUTO_UPGRADE_CODEMODS` (its `upgrade` command), and writes
|
|
129
|
+
the result through fmt's serializer.
|
|
130
|
+
|
|
131
|
+
## Coding standards
|
|
132
|
+
|
|
133
|
+
Hand-written code follows **dignified-python** (vendored at
|
|
134
|
+
`.claude/skills/dignified-python/`). See `CLAUDE.md`.
|