galaxy-tool-source 0.1.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.
Files changed (172) hide show
  1. galaxy_tool_source-0.1.0/.gitignore +28 -0
  2. galaxy_tool_source-0.1.0/.python-version +1 -0
  3. galaxy_tool_source-0.1.0/CLAUDE.md +140 -0
  4. galaxy_tool_source-0.1.0/LICENSE +21 -0
  5. galaxy_tool_source-0.1.0/PKG-INFO +126 -0
  6. galaxy_tool_source-0.1.0/PLAN.md +654 -0
  7. galaxy_tool_source-0.1.0/README.md +90 -0
  8. galaxy_tool_source-0.1.0/docs/codemod-architecture.md +314 -0
  9. galaxy_tool_source-0.1.0/docs/decisions.md +1283 -0
  10. galaxy_tool_source-0.1.0/docs/per-version-models-plan.md +356 -0
  11. galaxy_tool_source-0.1.0/hatch_build.py +39 -0
  12. galaxy_tool_source-0.1.0/pyproject.toml +138 -0
  13. galaxy_tool_source-0.1.0/src/galaxy_tool_source/__init__.py +6 -0
  14. galaxy_tool_source-0.1.0/src/galaxy_tool_source/_codegen.py +159 -0
  15. galaxy_tool_source-0.1.0/src/galaxy_tool_source/binding.py +338 -0
  16. galaxy_tool_source-0.1.0/src/galaxy_tool_source/boolean_values.py +201 -0
  17. galaxy_tool_source-0.1.0/src/galaxy_tool_source/bundle.py +186 -0
  18. galaxy_tool_source-0.1.0/src/galaxy_tool_source/cdata.py +70 -0
  19. galaxy_tool_source-0.1.0/src/galaxy_tool_source/cheetah_cdm.py +165 -0
  20. galaxy_tool_source-0.1.0/src/galaxy_tool_source/cheetah_refs.py +290 -0
  21. galaxy_tool_source-0.1.0/src/galaxy_tool_source/cheetah_rename.py +801 -0
  22. galaxy_tool_source-0.1.0/src/galaxy_tool_source/cli.py +129 -0
  23. galaxy_tool_source-0.1.0/src/galaxy_tool_source/command_text.py +151 -0
  24. galaxy_tool_source-0.1.0/src/galaxy_tool_source/command_vars.py +225 -0
  25. galaxy_tool_source-0.1.0/src/galaxy_tool_source/corrections.py +245 -0
  26. galaxy_tool_source-0.1.0/src/galaxy_tool_source/document.py +196 -0
  27. galaxy_tool_source-0.1.0/src/galaxy_tool_source/macros.py +365 -0
  28. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/__init__.py +10 -0
  29. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/any_tool.py +32 -0
  30. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/registry.py +46 -0
  31. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v16_10/__init__.py +201 -0
  32. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v16_10/galaxy.py +5576 -0
  33. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v17_01/__init__.py +207 -0
  34. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v17_01/galaxy.py +5692 -0
  35. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v17_05/__init__.py +207 -0
  36. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v17_05/galaxy.py +5793 -0
  37. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v17_09/__init__.py +209 -0
  38. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v17_09/galaxy.py +5878 -0
  39. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v18_01/__init__.py +211 -0
  40. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v18_01/galaxy.py +5965 -0
  41. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v18_05/__init__.py +211 -0
  42. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v18_05/galaxy.py +5996 -0
  43. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v18_09/__init__.py +211 -0
  44. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v18_09/galaxy.py +6044 -0
  45. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v19_01/__init__.py +215 -0
  46. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v19_01/galaxy.py +6120 -0
  47. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v19_05/__init__.py +223 -0
  48. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v19_05/galaxy.py +6526 -0
  49. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v19_09/__init__.py +239 -0
  50. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v19_09/galaxy.py +6779 -0
  51. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v20_01/__init__.py +239 -0
  52. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v20_01/galaxy.py +6839 -0
  53. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v20_05/__init__.py +239 -0
  54. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v20_05/galaxy.py +6875 -0
  55. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v20_09/__init__.py +241 -0
  56. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v20_09/galaxy.py +6950 -0
  57. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v21_01/__init__.py +249 -0
  58. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v21_01/galaxy.py +7380 -0
  59. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v21_05/__init__.py +249 -0
  60. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v21_05/galaxy.py +7419 -0
  61. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v21_09/__init__.py +259 -0
  62. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v21_09/galaxy.py +7620 -0
  63. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v22_01/__init__.py +291 -0
  64. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v22_01/galaxy.py +8605 -0
  65. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v22_05/__init__.py +297 -0
  66. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v22_05/galaxy.py +8737 -0
  67. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v23_0/__init__.py +297 -0
  68. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v23_0/galaxy.py +8807 -0
  69. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v23_1/__init__.py +303 -0
  70. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v23_1/galaxy.py +9078 -0
  71. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v23_2/__init__.py +309 -0
  72. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v23_2/galaxy.py +9248 -0
  73. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v24_0/__init__.py +319 -0
  74. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v24_0/galaxy.py +9460 -0
  75. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v24_1/__init__.py +333 -0
  76. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v24_1/galaxy.py +9985 -0
  77. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v24_2/__init__.py +343 -0
  78. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v24_2/galaxy.py +11327 -0
  79. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v25_0/__init__.py +347 -0
  80. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v25_0/galaxy.py +11437 -0
  81. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v25_1/__init__.py +353 -0
  82. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v25_1/galaxy.py +11686 -0
  83. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v26_0/__init__.py +349 -0
  84. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v26_0/galaxy.py +11678 -0
  85. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v26_1/__init__.py +355 -0
  86. galaxy_tool_source-0.1.0/src/galaxy_tool_source/models/v26_1/galaxy.py +11805 -0
  87. galaxy_tool_source-0.1.0/src/galaxy_tool_source/profiles.py +190 -0
  88. galaxy_tool_source-0.1.0/src/galaxy_tool_source/py.typed +0 -0
  89. galaxy_tool_source-0.1.0/src/galaxy_tool_source/rst.py +222 -0
  90. galaxy_tool_source-0.1.0/src/galaxy_tool_source/rst_markdown.py +407 -0
  91. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/PROVENANCE.md +55 -0
  92. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-16.10.xsd +5125 -0
  93. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-17.01.xsd +5214 -0
  94. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-17.05.xsd +5336 -0
  95. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-17.09.xsd +5389 -0
  96. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-18.01.xsd +5431 -0
  97. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-18.05.xsd +5452 -0
  98. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-18.09.xsd +5470 -0
  99. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-19.01.xsd +5507 -0
  100. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-19.05.xsd +5594 -0
  101. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-19.09.xsd +5773 -0
  102. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-20.01.xsd +5793 -0
  103. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-20.05.xsd +5807 -0
  104. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-20.09.xsd +5855 -0
  105. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-21.01.xsd +6250 -0
  106. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-21.05.xsd +6289 -0
  107. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-21.09.xsd +6407 -0
  108. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-22.01.xsd +7045 -0
  109. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-22.05.xsd +7151 -0
  110. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-23.0.xsd +7230 -0
  111. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-23.1.xsd +7353 -0
  112. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-23.2.xsd +7494 -0
  113. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-24.0.xsd +7704 -0
  114. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-24.1.xsd +7966 -0
  115. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-24.2.xsd +8249 -0
  116. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-25.0.xsd +8351 -0
  117. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-25.1.xsd +8569 -0
  118. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-26.0.xsd +8565 -0
  119. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/galaxy-26.1.xsd +8637 -0
  120. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema/manifest.json +229 -0
  121. galaxy_tool_source-0.1.0/src/galaxy_tool_source/schema_content.py +103 -0
  122. galaxy_tool_source-0.1.0/src/galaxy_tool_source/shell_oracle.py +346 -0
  123. galaxy_tool_source-0.1.0/tests/conftest.py +11 -0
  124. galaxy_tool_source-0.1.0/tests/data/invalid_tool.xml +6 -0
  125. galaxy_tool_source-0.1.0/tests/data/macros.xml +5 -0
  126. galaxy_tool_source-0.1.0/tests/data/malformed_tool.xml +7 -0
  127. galaxy_tool_source-0.1.0/tests/data/minimal_tool.xml +5 -0
  128. galaxy_tool_source-0.1.0/tests/data/nested_macros.xml +3 -0
  129. galaxy_tool_source-0.1.0/tests/data/nested_macros_inner.xml +5 -0
  130. galaxy_tool_source-0.1.0/tests/data/regressions/PROVENANCE.md +13 -0
  131. galaxy_tool_source-0.1.0/tests/data/regressions/bedtools/macros.xml +263 -0
  132. galaxy_tool_source-0.1.0/tests/data/regressions/bedtools/tool.xml +384 -0
  133. galaxy_tool_source-0.1.0/tests/data/regressions/dazeone__kleborate__kleborate/tool.xml +76 -0
  134. galaxy_tool_source-0.1.0/tests/data/regressions/nml__hivtrace__hivtrace/tool.xml +303 -0
  135. galaxy_tool_source-0.1.0/tests/data/regressions/tools-iuc__samtools_consensus/macros.xml +246 -0
  136. galaxy_tool_source-0.1.0/tests/data/regressions/tools-iuc__samtools_consensus/macros_tool_specific.xml +65 -0
  137. galaxy_tool_source-0.1.0/tests/data/regressions/tools-iuc__samtools_consensus/tool.xml +615 -0
  138. galaxy_tool_source-0.1.0/tests/data/representative_tool.xml +14 -0
  139. galaxy_tool_source-0.1.0/tests/data/token_macros.xml +4 -0
  140. galaxy_tool_source-0.1.0/tests/data/tool_imported_tokens.xml +8 -0
  141. galaxy_tool_source-0.1.0/tests/data/tool_inline_tokens.xml +8 -0
  142. galaxy_tool_source-0.1.0/tests/data/tool_macro_error.xml +10 -0
  143. galaxy_tool_source-0.1.0/tests/data/tool_nested_macros.xml +10 -0
  144. galaxy_tool_source-0.1.0/tests/data/tool_no_profile.xml +5 -0
  145. galaxy_tool_source-0.1.0/tests/data/tool_old_profile.xml +5 -0
  146. galaxy_tool_source-0.1.0/tests/data/tool_with_macros.xml +10 -0
  147. galaxy_tool_source-0.1.0/tests/data/tool_with_typos.xml +8 -0
  148. galaxy_tool_source-0.1.0/tests/test_binding.py +96 -0
  149. galaxy_tool_source-0.1.0/tests/test_boolean_values.py +89 -0
  150. galaxy_tool_source-0.1.0/tests/test_bundle.py +176 -0
  151. galaxy_tool_source-0.1.0/tests/test_cdata.py +63 -0
  152. galaxy_tool_source-0.1.0/tests/test_cheetah_cdm.py +135 -0
  153. galaxy_tool_source-0.1.0/tests/test_cheetah_refs.py +160 -0
  154. galaxy_tool_source-0.1.0/tests/test_cheetah_rename.py +654 -0
  155. galaxy_tool_source-0.1.0/tests/test_cli.py +75 -0
  156. galaxy_tool_source-0.1.0/tests/test_codegen.py +26 -0
  157. galaxy_tool_source-0.1.0/tests/test_command_text.py +87 -0
  158. galaxy_tool_source-0.1.0/tests/test_command_vars.py +137 -0
  159. galaxy_tool_source-0.1.0/tests/test_corpus_check.py +574 -0
  160. galaxy_tool_source-0.1.0/tests/test_corrections.py +70 -0
  161. galaxy_tool_source-0.1.0/tests/test_macros.py +172 -0
  162. galaxy_tool_source-0.1.0/tests/test_measure.py +1872 -0
  163. galaxy_tool_source-0.1.0/tests/test_models.py +47 -0
  164. galaxy_tool_source-0.1.0/tests/test_pr_impact.py +234 -0
  165. galaxy_tool_source-0.1.0/tests/test_profiles.py +82 -0
  166. galaxy_tool_source-0.1.0/tests/test_regressions.py +41 -0
  167. galaxy_tool_source-0.1.0/tests/test_rst.py +60 -0
  168. galaxy_tool_source-0.1.0/tests/test_rst_markdown.py +210 -0
  169. galaxy_tool_source-0.1.0/tests/test_schema_content.py +41 -0
  170. galaxy_tool_source-0.1.0/tests/test_shared.py +71 -0
  171. galaxy_tool_source-0.1.0/tests/test_shell_oracle.py +133 -0
  172. galaxy_tool_source-0.1.0/tests/test_validate.py +149 -0
@@ -0,0 +1,28 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Tooling caches
13
+ .pytest_cache/
14
+ .mypy_cache/
15
+ .ruff_cache/
16
+
17
+ # Per-version xsdata models — generated at build time by hatch_build.py
18
+ src/galaxy_tool_xml/models/v*/
19
+ src/galaxy_tool_xml/models/any_tool.py
20
+
21
+ # Dev-only corpus checkouts — public Galaxy tool repositories (and any
22
+ # future toolshed snapshots) cloned by scripts/corpus_check.py for deep
23
+ # testing and design decisions; never committed.
24
+ corpus/
25
+
26
+ # Local, per-developer Claude Code settings
27
+ .claude/settings.local.json
28
+
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,140 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with
4
+ code in this repository.
5
+
6
+ ## Project
7
+
8
+ `galaxy-tool-source` is a foundation library and CLI for parsing, profile-aware
9
+ validation, and typed inspection of Galaxy tool definition XML. It is the
10
+ foundation for a separate, `black`-like Galaxy tool linter/formatter — it has
11
+ **no serializer**: it exposes the mutable lxml tree and callers serialize it
12
+ themselves.
13
+
14
+ ## Commands
15
+
16
+ Run these from the **workspace root** (`galaxy-tool-refactor/`):
17
+
18
+ - `uv sync` — install dependencies; the build hook generates the per-version models.
19
+ - `uv run --package galaxy-tool-source pytest galaxy-tool-source/tests/` — run this package's tests.
20
+ - `uv run --package galaxy-tool-source pytest galaxy-tool-source/tests/test_binding.py::test_load_tool_returns_document` — run a single test.
21
+ - `uv run --package galaxy-tool-source pytest -m slow galaxy-tool-source/tests/` — run the xsdata codegen sweep over every vendored XSD.
22
+ - `uv run ruff check galaxy-tool-source/src` — lint.
23
+ - `uv run mypy --config-file galaxy-tool-source/pyproject.toml galaxy-tool-source/src` — type-check (strict).
24
+ - `uv run python -m scripts.fetch_schemas` — download release XSDs (`--force` re-downloads all).
25
+ - `uv run python -m scripts.regenerate` — regenerate the per-version typed models from every vendored XSD.
26
+ - `uv run python -m scripts.corpus_check validate` — sweep public Galaxy tool repositories for crashes (maintainer QA).
27
+ - `uv run galaxy-tool-source validate <file>` / `suggest <file>` / `profiles` — the CLI.
28
+ - `uv build --package galaxy-tool-source` — build the wheel (the build hook generates the per-version models).
29
+
30
+ ## Naming
31
+
32
+ The repo directory, the distribution, and the CLI command are all
33
+ `galaxy-tool-source`; the import package is `galaxy_tool_source`.
34
+
35
+ ## Architecture
36
+
37
+ `ToolDocument` (`document.py`) wraps a mutable lxml tree — the **source of
38
+ truth**, faithfully preserving CDATA, comments, and attribute order.
39
+ `binding.py` parses (`load_tool`, `parse_tool`; `load_macros` for a `<macros>`
40
+ file → `MacroDocument`), validates (`validate_tool`), and finds a tool's newest
41
+ valid profile (`newest_valid_profile`). `MacroDocument` (`document.py`) is the
42
+ macro-file counterpart to `ToolDocument` — a mutable tree with no profile/model
43
+ and no standalone XSD validation. `profiles.py`
44
+ resolves a tool's `profile` to one of the ~28 vendored per-release XSDs.
45
+ `macros.py` handles Galaxy macros and is the sole `galaxy-util` adapter; it also
46
+ exposes read-only macro-file resolution (`imported_macro_paths`) and
47
+ token-definition lookup (`token_definitions` / `TokenDefinition`) over a tool and
48
+ its imported macro files. `bundle.py` builds a `ToolBundle` (a tool + its
49
+ transitively-imported macro documents) via `load_bundle` and renames a parameter
50
+ across the whole bundle (`rename_param_in_bundle`) — the cross-file extension of
51
+ `cheetah_rename` (decisions §21).
52
+ `corrections.py` suggests near-miss typo fixes. `schema_content.py` derives
53
+ the text-bearing element-tag set from the vendored XSDs (the fmt tier's
54
+ payload-guard source of truth). `rst.py` / `rst_markdown.py` own
55
+ the `<help>` reStructuredText subsystem: validity + surgical repair (the GTR089
56
+ partition seam, decisions §23) and the render-equivalence-gated RST → Markdown
57
+ conversion (GTR092's engine, §24; markdown-it-py rides the `[markdown]` extra). `models/` holds an
58
+ xsdata-generated read-only typed model per vendored schema version, generated at
59
+ build time by `_codegen.py` and reached via `ToolDocument.model()`;
60
+ `models/registry.py` resolves a version to its model.
61
+
62
+ The public API is the prose-declared list in `README.md`; everything else is
63
+ private and may change. For the rationale behind each architectural choice
64
+ (profile-aware validation, the lxml-as-source-of-truth contract, the macro
65
+ expansion adapter, etc.) plus assumptions about the Galaxy ecosystem and
66
+ testing-derived data, see `docs/decisions.md`.
67
+
68
+ ## Coding standards
69
+
70
+ Hand-written code follows **dignified-python**, vendored at the workspace root
71
+ `.claude/skills/dignified-python/`: LBYL over `try/except`; exceptions only at
72
+ the click error boundary (chained `from e`); `pathlib` with explicit
73
+ `encoding` for text I/O; no import-time side effects (`@cache` for module
74
+ state); absolute imports, no re-exports, no `__all__`; keyword-only arguments
75
+ after the first. `optimized-python` (`.claude/skills/optimized-python/`) is
76
+ installed as a reference; **dignified-python governs on any conflict**. The
77
+ generated per-version model packages (`models/v*/`, `models/any_tool.py`) are
78
+ exempt — they are not hand-written; `models/__init__.py` and `models/registry.py`
79
+ are hand-written and are not exempt.
80
+
81
+ ## Non-obvious conventions
82
+
83
+ - The lxml tree is the source of truth; the typed model is a derived read-only
84
+ view, bound to the tool's own profile. The library does not emit XML.
85
+ - Parsing uses `strip_cdata=False`: CDATA, comments, and attribute order are
86
+ preserved. XML is parsed from `bytes`, never a decoded `str`, so the
87
+ document's own encoding declaration is honoured.
88
+ - The Galaxy XSD is a **post-macro-expansion** schema; `validate_tool`
89
+ transforms the tool per `macro_handling` (default `expand`) into a throwaway
90
+ copy and validates that — the `ToolDocument` tree is never mutated.
91
+ - `galaxy.util` is Galaxy's *internal* API; all use of it is confined to
92
+ `macros.py`, and `galaxy-util` is pinned to a version range.
93
+ - The per-version model packages (`models/v*/`, `models/any_tool.py`) are
94
+ generated — never hand-edit; they are gitignored, regenerated by the build
95
+ hook and by `scripts/regenerate.py`, and excluded from ruff and mypy. Each
96
+ generated `v*/__init__.py` re-exports its module — the one sanctioned
97
+ exception to the no-re-exports rule.
98
+ - `schema/` holds vendored XSDs downloaded once by `scripts/fetch_schemas.py`;
99
+ re-running is additive, `--force` re-downloads. `manifest.json` and
100
+ `PROVENANCE.md` are committed alongside the XSDs.
101
+ - `../docs/corpus_data/` (workspace root) holds the fine-grained per-tool data
102
+ (JSON + TSV) emitted alongside the aggregate `../docs/*_corpus_stats.md`
103
+ artifacts; both regenerate together on a full `corpus_check.py validate` sweep.
104
+ Toolshed row
105
+ versions come from `.local/corpus/galaxy-toolshed/manifest.json`, which
106
+ `fetch_toolshed.py` populates by capturing each clone's tip changeset
107
+ before `.hg/` is removed. The combined stats markdown also carries two
108
+ failure-reason tables (macro-expansion failures, no-valid-profile
109
+ reasons) categorising every tool whose validity vector is empty —
110
+ these answer the "are these our bugs?" question at a glance.
111
+ - Both validation and binding are profile-aware: `validate_tool` uses the
112
+ per-release XSD, and `ToolDocument.model()` binds against the model for the
113
+ tool's resolved profile (overridable via `model(version=...)`).
114
+ - Binding uses a lenient xsdata config: unknown elements/attributes are ignored,
115
+ and schema-required fields the tree omits (an element a macro would supply)
116
+ default to `None`, so binding an un-expanded tool never raises.
117
+ - `corrections.py` is suggest-only and independent of `validate_tool`; its
118
+ vocabulary comes from introspecting the generated model for the tool's own
119
+ profile, with a macro skip-set so an un-expanded tool's macro constructs are
120
+ never flagged.
121
+ - No-profile tools validate against `16.10` (our oldest vendored XSD), matching
122
+ Galaxy's `16.01` legacy default for a missing `profile` (`resolve_profile(None)`
123
+ → nearest vendored = 16.10). See `docs/decisions.md` §1.5.
124
+ - Failure modes: syntax errors (`load_tool` raises, the others collect them),
125
+ macro-expansion errors, and XSD validation errors. The XSD has no
126
+ `targetNamespace`, so Galaxy tool XML is namespace-free.
127
+
128
+ ## Implementation workarounds
129
+
130
+ Two deviations from a naive implementation, both forced by upstream bugs:
131
+
132
+ - **xsdata codegen** (`_codegen.py`): xsdata 26.2's circular-reference detector
133
+ raises `KeyError` on the Galaxy 24.2+ schema when inner classes are nested, so
134
+ codegen sets `output.unnest_classes = True`. Each version is generated in its
135
+ own subprocess — xsdata caches its resolved output path process-wide.
136
+ - **Schema compilation** (`profiles.py`): Galaxy releases 19.05 through 23.0
137
+ shipped an XSD whose `Output` type has a non-deterministic content model that
138
+ libxml2 refuses to compile. `compiled_schema` retries after applying Galaxy's
139
+ own release-23.1 fix (drop the redundant `Output` group) in memory — the
140
+ vendored XSD files on disk remain verbatim.
@@ -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,126 @@
1
+ Metadata-Version: 2.4
2
+ Name: galaxy-tool-source
3
+ Version: 0.1.0
4
+ Summary: Foundation library for parsing, profile-aware validation, and typed inspection of Galaxy tool XML
5
+ Project-URL: Homepage, https://github.com/richard-burhans/galaxy-tool-refactor
6
+ Project-URL: Repository, https://github.com/richard-burhans/galaxy-tool-refactor
7
+ Project-URL: Issues, https://github.com/richard-burhans/galaxy-tool-refactor/issues
8
+ Author-email: Richard Burhans <richard.burhans@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: bioinformatics,cheetah,galaxy,tool-xml,validation,xsd
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Classifier: Topic :: Text Processing :: Markup :: XML
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: click>=8
26
+ Requires-Dist: docutils>=0.21
27
+ Requires-Dist: galaxy-util[template]<27,>=24
28
+ Requires-Dist: lxml>=5
29
+ Requires-Dist: packaging>=23
30
+ Requires-Dist: xsdata[lxml]>=26.2
31
+ Provides-Extra: markdown
32
+ Requires-Dist: markdown-it-py>=4; extra == 'markdown'
33
+ Provides-Extra: shell-oracle
34
+ Requires-Dist: bashlex>=0.18; extra == 'shell-oracle'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # galaxy-tool-source
38
+
39
+ A Python library and small CLI for parsing, profile-aware validation, and typed
40
+ inspection of [Galaxy](https://galaxyproject.org/) tool definition XML — the
41
+ `<tool>` wrapper files that define Galaxy bioinformatics tools.
42
+
43
+ This package is the **foundation** for a separate, `black`-like program for
44
+ Galaxy tool XML (conformance checking, autofixing, reformatting). It provides
45
+ only the foundation — no rules, no formatter, no serializer:
46
+
47
+ 1. **Parse** tool XML into a mutable representation that faithfully preserves
48
+ CDATA, comments, attribute data and order, and significant element text.
49
+ 2. A **typed read-only view** of a parsed tool — bound to the model for the
50
+ tool's own schema profile — for convenient rule-checking.
51
+ 3. **Profile-aware XSD validation**, with configurable macro handling so
52
+ validation is accurate on real-world tools that use Galaxy macros.
53
+ 4. **Near-miss typo suggestions** against the schema vocabulary (suggest only).
54
+
55
+ ## Install
56
+
57
+ ```sh
58
+ uv sync
59
+ ```
60
+
61
+ ## Usage
62
+
63
+ ```python
64
+ from galaxy_tool_source.binding import load_tool, validate_tool
65
+
66
+ document = load_tool("my_tool.xml")
67
+ print(document.profile)
68
+
69
+ result = validate_tool("my_tool.xml")
70
+ if not result.valid:
71
+ for error in result.errors:
72
+ print(error)
73
+ ```
74
+
75
+ From the command line:
76
+
77
+ ```sh
78
+ uv run galaxy-tool-source validate my_tool.xml
79
+ uv run galaxy-tool-source suggest my_tool.xml
80
+ uv run galaxy-tool-source profiles
81
+ ```
82
+
83
+ ## Public API
84
+
85
+ The downstream formatter project may rely on exactly these symbols. Everything
86
+ else is private and may change without notice.
87
+
88
+ ```python
89
+ from galaxy_tool_source.binding import load_tool, parse_tool, validate_tool, newest_valid_profile
90
+ from galaxy_tool_source.binding import load_macros
91
+ from galaxy_tool_source.binding import ParseResult, ValidationResult, XmlError, ToolXmlSyntaxError
92
+ from galaxy_tool_source.document import ToolDocument, MacroDocument
93
+ from galaxy_tool_source.macros import MacroError, imported_macro_paths, token_definitions, TokenDefinition, expanded_detection_root
94
+ from galaxy_tool_source.corrections import suggest_corrections, Correction
95
+ from galaxy_tool_source.boolean_values import suggest_boolean_normalizations, normalize_boolean_token, BooleanNormalization
96
+ from galaxy_tool_source.cheetah_refs import tool_cheetah_references, CheetahRef
97
+ from galaxy_tool_source.cheetah_rename import rename_param, rename_param_plan, RenameOutcome, RenameEdit, RenamePlan
98
+ from galaxy_tool_source.bundle import ToolBundle, load_bundle, rename_param_in_bundle, BundleRenameOutcome
99
+ from galaxy_tool_source.profiles import available_profiles, latest_profile, UnknownProfileError
100
+ from galaxy_tool_source.schema_content import text_bearing_tags
101
+ from galaxy_tool_source.models.registry import model_module, tool_class
102
+ from galaxy_tool_source.models.any_tool import AnyTool
103
+ ```
104
+
105
+ ## Architecture
106
+
107
+ `ToolDocument` (`document.py`) wraps a mutable lxml tree — the source of truth,
108
+ faithfully preserving CDATA, comments, and attribute order. `binding.py` parses
109
+ and validates; `profiles.py` resolves the per-release vendored XSD; `macros.py`
110
+ handles Galaxy macros (the sole `galaxy-util` adapter); `corrections.py` suggests
111
+ near-miss typo fixes; `boolean_values.py` reports schema-boolean attribute value
112
+ normalizations (`True` → `true`); `cheetah_refs.py` / `cheetah_rename.py` find and
113
+ rename a parameter across a tool's Cheetah sections (the latter renders the rename
114
+ either as a tree mutation, `rename_param`, or as minimal source offsets,
115
+ `rename_param_plan`, for editor / LSP use); `bundle.py` extends the rename across a
116
+ tool *and its imported macro files* (`ToolBundle` / `load_bundle` /
117
+ `rename_param_in_bundle`); `rst.py` / `rst_markdown.py` own the `<help>`
118
+ reStructuredText subsystem — validity + surgical repair (the GTR089 partition seam)
119
+ and the render-equivalence-gated RST → Markdown conversion (GTR092; needs the
120
+ `[markdown]` extra); `models/` holds an xsdata-generated
121
+ read-only typed model for every vendored schema version, reached via
122
+ `ToolDocument.model()`.
123
+
124
+ ## License
125
+
126
+ MIT — see [LICENSE](LICENSE).