sawmill-parser 0.3.2__tar.gz → 0.5.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 (216) hide show
  1. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/.gitignore +3 -0
  2. sawmill_parser-0.5.0/CLAUDE.md +83 -0
  3. sawmill_parser-0.5.0/PKG-INFO +115 -0
  4. sawmill_parser-0.5.0/README.md +70 -0
  5. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/docs/conf.py +3 -4
  6. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/docs/development/contributing.rst +2 -33
  7. sawmill_parser-0.5.0/docs/development/manifest-design.rst +373 -0
  8. sawmill_parser-0.5.0/docs/getting-started/quickstart.rst +82 -0
  9. sawmill_parser-0.5.0/docs/getting-started/what-is-sawmill.rst +57 -0
  10. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/docs/index.rst +15 -6
  11. sawmill_parser-0.5.0/docs/performance/overview.rst +103 -0
  12. sawmill_parser-0.5.0/docs/performance/plugin-api-2.rst +97 -0
  13. sawmill_parser-0.5.0/docs/performance/store-investigation.rst +127 -0
  14. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/docs/plugin-guide/pre-defined-filters.rst +15 -22
  15. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/docs/plugin-guide/what-is-a-plugin.rst +7 -7
  16. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/docs/plugin-guide/writing-a-plugin.rst +75 -14
  17. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/docs/reference/api.rst +8 -8
  18. sawmill_parser-0.5.0/docs/reference/cli-reference.rst +222 -0
  19. sawmill_parser-0.5.0/docs/reference/file-formats.rst +291 -0
  20. sawmill_parser-0.5.0/docs/user-guide/ci-integration.rst +181 -0
  21. sawmill_parser-0.5.0/docs/user-guide/cli-usage.rst +131 -0
  22. sawmill_parser-0.5.0/docs/user-guide/rules.rst +189 -0
  23. sawmill_parser-0.5.0/docs/user-guide/sawmill-directory.rst +175 -0
  24. sawmill_parser-0.5.0/docs/user-guide/tui-usage.rst +186 -0
  25. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/pyproject.toml +6 -3
  26. sawmill_parser-0.5.0/sawmill/cli/check.py +165 -0
  27. sawmill_parser-0.5.0/sawmill/cli/commands.py +71 -0
  28. sawmill_parser-0.5.0/sawmill/cli/common.py +123 -0
  29. sawmill_parser-0.5.0/sawmill/cli/init.py +88 -0
  30. sawmill_parser-0.5.0/sawmill/cli/plugins.py +120 -0
  31. sawmill_parser-0.5.0/sawmill/cli/report.py +92 -0
  32. sawmill_parser-0.5.0/sawmill/cli/rules.py +180 -0
  33. sawmill_parser-0.5.0/sawmill/cli/view.py +60 -0
  34. sawmill_parser-0.5.0/sawmill/core/__init__.py +116 -0
  35. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/core/aggregation.py +4 -0
  36. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/core/config.py +18 -36
  37. sawmill_parser-0.5.0/sawmill/core/discovery.py +184 -0
  38. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/core/filter.py +6 -72
  39. sawmill_parser-0.5.0/sawmill/core/junit.py +85 -0
  40. sawmill_parser-0.5.0/sawmill/core/manifest.py +185 -0
  41. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/core/plugin.py +22 -3
  42. sawmill_parser-0.5.0/sawmill/core/report.py +133 -0
  43. sawmill_parser-0.5.0/sawmill/core/rule_matcher.py +176 -0
  44. sawmill_parser-0.5.0/sawmill/core/rules.py +283 -0
  45. sawmill_parser-0.5.0/sawmill/core/runner.py +396 -0
  46. sawmill_parser-0.5.0/sawmill/core/scaffold.py +102 -0
  47. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/core/severity.py +35 -0
  48. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/models/__init__.py +6 -3
  49. sawmill_parser-0.5.0/sawmill/models/manifest.py +122 -0
  50. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/models/message.py +24 -9
  51. sawmill_parser-0.5.0/sawmill/models/rule.py +109 -0
  52. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/plugin/__init__.py +27 -9
  53. sawmill_parser-0.5.0/sawmill/plugin/hookspec.py +198 -0
  54. sawmill_parser-0.5.0/sawmill/tui/app.py +1286 -0
  55. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/tui/filter_parser.py +10 -0
  56. sawmill_parser-0.5.0/sawmill/tui/state.py +68 -0
  57. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/tui/widgets/__init__.py +4 -2
  58. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/tui/widgets/footer.py +1 -6
  59. sawmill_parser-0.5.0/sawmill/tui/widgets/help_modal.py +71 -0
  60. sawmill_parser-0.5.0/sawmill/tui/widgets/overview.py +137 -0
  61. sawmill_parser-0.5.0/sawmill/tui/widgets/rules_prompt.py +178 -0
  62. sawmill_parser-0.5.0/sawmill/tui/widgets/waive_modal.py +352 -0
  63. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/utils/author.py +1 -1
  64. sawmill_parser-0.5.0/sawmill/utils/globs.py +53 -0
  65. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/utils/toml.py +2 -2
  66. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/core/test_aggregation.py +37 -0
  67. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/core/test_config.py +31 -63
  68. sawmill_parser-0.5.0/tests/core/test_discovery.py +218 -0
  69. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/core/test_filter.py +6 -155
  70. sawmill_parser-0.5.0/tests/core/test_junit.py +171 -0
  71. sawmill_parser-0.5.0/tests/core/test_manifest.py +185 -0
  72. sawmill_parser-0.5.0/tests/core/test_plugin_load.py +25 -0
  73. sawmill_parser-0.5.0/tests/core/test_report.py +246 -0
  74. sawmill_parser-0.5.0/tests/core/test_rule_matcher.py +258 -0
  75. sawmill_parser-0.5.0/tests/core/test_rules.py +336 -0
  76. sawmill_parser-0.5.0/tests/core/test_runner.py +700 -0
  77. sawmill_parser-0.5.0/tests/core/test_scaffold.py +92 -0
  78. sawmill_parser-0.5.0/tests/core/test_severity.py +45 -0
  79. sawmill_parser-0.5.0/tests/models/test_manifest.py +103 -0
  80. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/models/test_message.py +41 -0
  81. sawmill_parser-0.5.0/tests/models/test_rule.py +35 -0
  82. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/plugin/test_hookspec.py +44 -10
  83. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/plugins/test_vivado.py +11 -11
  84. sawmill_parser-0.5.0/tests/test_cli.py +89 -0
  85. sawmill_parser-0.5.0/tests/test_cli_check.py +373 -0
  86. sawmill_parser-0.5.0/tests/test_cli_common.py +102 -0
  87. sawmill_parser-0.5.0/tests/test_cli_init.py +199 -0
  88. sawmill_parser-0.5.0/tests/test_cli_plugin_discovery.py +83 -0
  89. sawmill_parser-0.5.0/tests/test_cli_report.py +270 -0
  90. sawmill_parser-0.5.0/tests/test_cli_rules.py +366 -0
  91. sawmill_parser-0.5.0/tests/test_cli_view.py +179 -0
  92. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/test_plugin_api.py +0 -32
  93. sawmill_parser-0.5.0/tests/test_removed_modules.py +29 -0
  94. sawmill_parser-0.5.0/tests/tui/conftest.py +147 -0
  95. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/tui/test_app.py +400 -76
  96. sawmill_parser-0.5.0/tests/tui/test_base_styles.py +99 -0
  97. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/tui/test_filter_parser.py +16 -0
  98. sawmill_parser-0.5.0/tests/tui/test_overview.py +226 -0
  99. sawmill_parser-0.5.0/tests/tui/test_refresh_hide.py +334 -0
  100. sawmill_parser-0.5.0/tests/tui/test_rules_prompt.py +96 -0
  101. sawmill_parser-0.5.0/tests/tui/test_single_log_waive.py +183 -0
  102. sawmill_parser-0.5.0/tests/tui/test_state.py +86 -0
  103. sawmill_parser-0.5.0/tests/tui/test_waive_action.py +216 -0
  104. sawmill_parser-0.5.0/tests/tui/test_waive_modal.py +265 -0
  105. sawmill_parser-0.5.0/tests/tui/test_windowed_table.py +200 -0
  106. sawmill_parser-0.5.0/tests/utils/test_globs.py +43 -0
  107. sawmill_parser-0.5.0/tools/bench/bench_message.py +157 -0
  108. sawmill_parser-0.5.0/tools/bench/gen_xcelium_log.py +146 -0
  109. sawmill_parser-0.5.0/tools/bench/run_bench.py +246 -0
  110. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/generator.py +1 -1
  111. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/claude.md.j2 +11 -6
  112. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/plugin.py.j2 +17 -13
  113. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/test_parsing.py.j2 +13 -11
  114. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/test_plugin_contract.py.j2 +6 -4
  115. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/tests/test_generator.py +1 -1
  116. sawmill_parser-0.3.2/CHANGELOG.md +0 -701
  117. sawmill_parser-0.3.2/CLAUDE.md +0 -241
  118. sawmill_parser-0.3.2/Dockerfile +0 -52
  119. sawmill_parser-0.3.2/PKG-INFO +0 -210
  120. sawmill_parser-0.3.2/PRD.md +0 -590
  121. sawmill_parser-0.3.2/PROMPT.md +0 -230
  122. sawmill_parser-0.3.2/README.md +0 -168
  123. sawmill_parser-0.3.2/STATUS.md +0 -389
  124. sawmill_parser-0.3.2/docs/getting-started/quickstart.rst +0 -86
  125. sawmill_parser-0.3.2/docs/getting-started/what-is-sawmill.rst +0 -64
  126. sawmill_parser-0.3.2/docs/reference/cli-reference.rst +0 -135
  127. sawmill_parser-0.3.2/docs/reference/file-formats.rst +0 -148
  128. sawmill_parser-0.3.2/docs/user-guide/ci-integration.rst +0 -184
  129. sawmill_parser-0.3.2/docs/user-guide/cli-usage.rst +0 -166
  130. sawmill_parser-0.3.2/docs/user-guide/sawmill-directory.rst +0 -98
  131. sawmill_parser-0.3.2/docs/user-guide/tui-usage.rst +0 -180
  132. sawmill_parser-0.3.2/docs/user-guide/waivers.rst +0 -141
  133. sawmill_parser-0.3.2/ralph-loop.sh +0 -361
  134. sawmill_parser-0.3.2/sawmill/cli/commands.py +0 -620
  135. sawmill_parser-0.3.2/sawmill/cli/formatting.py +0 -250
  136. sawmill_parser-0.3.2/sawmill/cli/processing.py +0 -236
  137. sawmill_parser-0.3.2/sawmill/cli/reporting.py +0 -250
  138. sawmill_parser-0.3.2/sawmill/core/__init__.py +0 -68
  139. sawmill_parser-0.3.2/sawmill/core/suppress.py +0 -89
  140. sawmill_parser-0.3.2/sawmill/core/waiver.py +0 -588
  141. sawmill_parser-0.3.2/sawmill/models/waiver.py +0 -61
  142. sawmill_parser-0.3.2/sawmill/plugin/hookspec.py +0 -186
  143. sawmill_parser-0.3.2/sawmill/tui/app.py +0 -1109
  144. sawmill_parser-0.3.2/sawmill/tui/session.py +0 -135
  145. sawmill_parser-0.3.2/sawmill/tui/widgets/quit_modal.py +0 -103
  146. sawmill_parser-0.3.2/sawmill/tui/widgets/waive_modal.py +0 -242
  147. sawmill_parser-0.3.2/sawmill/utils/dirs.py +0 -66
  148. sawmill_parser-0.3.2/tests/core/test_suppress.py +0 -163
  149. sawmill_parser-0.3.2/tests/core/test_waiver.py +0 -680
  150. sawmill_parser-0.3.2/tests/core/test_waiver_matching.py +0 -693
  151. sawmill_parser-0.3.2/tests/test_ci_mode.py +0 -534
  152. sawmill_parser-0.3.2/tests/test_ci_report.py +0 -652
  153. sawmill_parser-0.3.2/tests/test_ci_waivers.py +0 -609
  154. sawmill_parser-0.3.2/tests/test_cli.py +0 -399
  155. sawmill_parser-0.3.2/tests/test_cli_formats.py +0 -331
  156. sawmill_parser-0.3.2/tests/test_cli_id_filter.py +0 -362
  157. sawmill_parser-0.3.2/tests/test_cli_integration.py +0 -594
  158. sawmill_parser-0.3.2/tests/test_cli_plugin_discovery.py +0 -126
  159. sawmill_parser-0.3.2/tests/test_cli_summary.py +0 -240
  160. sawmill_parser-0.3.2/tests/test_waiver_generation.py +0 -786
  161. sawmill_parser-0.3.2/tests/tui/test_base_styles.py +0 -194
  162. sawmill_parser-0.3.2/tests/tui/test_persistence.py +0 -724
  163. sawmill_parser-0.3.2/tests/tui/test_suppress.py +0 -287
  164. sawmill_parser-0.3.2/tests/tui/test_tabs.py +0 -373
  165. sawmill_parser-0.3.2/tests/tui/test_waive.py +0 -464
  166. sawmill_parser-0.3.2/tests/utils/test_dirs.py +0 -84
  167. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/.gitattributes +0 -0
  168. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/.github/workflows/docs.yml +0 -0
  169. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/.github/workflows/publish.yml +0 -0
  170. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/.pre-commit-config.yaml +0 -0
  171. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/assets/sawmill.png +0 -0
  172. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/docs/Makefile +0 -0
  173. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/__init__.py +0 -0
  174. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/__main__.py +0 -0
  175. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/cli/__init__.py +0 -0
  176. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/models/filter_def.py +0 -0
  177. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/models/plugin_api.py +0 -0
  178. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/tui/__init__.py +0 -0
  179. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/tui/base.tcss +0 -0
  180. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/tui/theme.py +0 -0
  181. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/utils/__init__.py +0 -0
  182. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sawmill/utils/git.py +0 -0
  183. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/sourceme +0 -0
  184. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/__init__.py +0 -0
  185. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/conftest.py +0 -0
  186. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/core/__init__.py +0 -0
  187. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/core/test_plugin_autodetect.py +0 -0
  188. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/core/test_plugin_manager.py +0 -0
  189. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/fixtures/vivado.log +0 -0
  190. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/models/__init__.py +0 -0
  191. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/models/test_filter_def.py +0 -0
  192. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/plugin/__init__.py +0 -0
  193. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/plugins/__init__.py +0 -0
  194. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/test_fixtures.py +0 -0
  195. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/test_project_setup.py +0 -0
  196. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/tui/__init__.py +0 -0
  197. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/tui/test_footer.py +0 -0
  198. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/utils/__init__.py +0 -0
  199. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/utils/test_git.py +0 -0
  200. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tests/utils/test_toml.py +0 -0
  201. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/pyproject.toml +0 -0
  202. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/__init__.py +0 -0
  203. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/cli.py +0 -0
  204. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/names.py +0 -0
  205. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/conftest.py.j2 +0 -0
  206. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/gitignore.j2 +0 -0
  207. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/init.py.j2 +0 -0
  208. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/makefile.j2 +0 -0
  209. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/patterns.py.j2 +0 -0
  210. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/pyproject.toml.j2 +0 -0
  211. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/readme.md.j2 +0 -0
  212. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/sample_log.j2 +0 -0
  213. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/test_detection.py.j2 +0 -0
  214. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/src/sawmill_plugin_generator/templates/test_severity.py.j2 +0 -0
  215. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/tests/test_cli.py +0 -0
  216. {sawmill_parser-0.3.2 → sawmill_parser-0.5.0}/tools/sawmill-plugin-generator/tests/test_names.py +0 -0
@@ -79,3 +79,6 @@ docs/_build/
79
79
  # OS
80
80
  .DS_Store
81
81
  Thumbs.db
82
+
83
+ # Claude Code local settings
84
+ .claude/
@@ -0,0 +1,83 @@
1
+ # Sawmill
2
+
3
+ Terminal log analyser for structured tool logs. Plugins parse tool-specific
4
+ formats (Vivado, Slang, ...); the base app filters, groups, waives
5
+ and reports. Batch CLI for CI, Textual TUI for interactive triage.
6
+
7
+ ## Setup
8
+
9
+ ```bash
10
+ source sourceme # creates .venv with uv, installs dev extras, installs pre-commit
11
+ source sourceme --clean # rebuild the venv
12
+ pytest tests/ -v
13
+ python -m sphinx -b html docs docs/_build/html # needs `uv sync --all-extras`
14
+ ```
15
+
16
+ Always use `uv`, never `pip`. Activate `.venv` before running anything.
17
+
18
+ ## Layout
19
+
20
+ ```
21
+ sawmill/
22
+ __main__.py CLI entry point
23
+ cli/ rich-click commands, processing, reporting, formatting
24
+ core/ filter, severity, aggregation, config, plugin manager, waivers
25
+ models/ pydantic models: Message, FilterDefinition, Waiver, plugin API
26
+ plugin/ SawmillPlugin base class and pluggy hookspec
27
+ tui/ Textual app, session persistence, widgets
28
+ utils/ dirs, git, toml, author helpers
29
+ tests/ mirrors sawmill/ (sawmill/core/filter.py -> tests/core/test_filter.py)
30
+ tools/bench/ synthetic log generator and benchmark runner
31
+ tools/sawmill-plugin-generator/ scaffolds a new plugin package
32
+ docs/ Sphinx, furo theme; built by .github/workflows/docs.yml
33
+ ```
34
+
35
+ Plugins live in their own repositories and register through the
36
+ `sawmill.plugins` entry point. There are no built-in plugins.
37
+
38
+ ## Architecture rules
39
+
40
+ **The plugin is the sole source of truth for the log format.** The base app
41
+ never parses log content, detects severity, or assumes severity names exist.
42
+
43
+ - Plugins implement `can_handle`, `load_and_parse` (an iterator of `Message`,
44
+ plugin API 2), `get_severity_levels` (required), and optionally
45
+ `get_filters`, `get_grouping_fields`, `extract_file_reference`.
46
+ - Severity comparisons in the base app use `SeverityLevel.level` (an int),
47
+ never the string id. Any severity scheme a plugin defines must work.
48
+ - Large logs are streamed; see `docs/performance/` before touching the
49
+ load path or the TUI table.
50
+
51
+ ## In-progress redesign
52
+
53
+ The waiver and suppression system is being replaced by a manifest and rule
54
+ model. The design, decisions and task plan are in
55
+ `docs/development/manifest-design.rst`. Read it before changing anything
56
+ under `core/waiver.py`, `core/suppress.py`, `core/config.py`, the CLI
57
+ options, or TUI session persistence. The user guide pages on waivers and the
58
+ `.sawmill` directory describe the old behaviour until Stage D of that plan.
59
+
60
+ ## Coding standards
61
+
62
+ - PEP 8, type hints on every signature, docstrings on public classes and
63
+ functions. Ruff and mypy run in pre-commit.
64
+ - Tests alongside or before implementation. Async Textual tests use
65
+ `app.run_test()` with `pilot`.
66
+ - `tomli` for reading TOML, `tomli_w` for writing. Validate regexes before
67
+ storing them.
68
+
69
+ ## Git
70
+
71
+ - Short, conventional commit messages. One logical change per commit.
72
+ - No `Co-Authored-By` or generated-by lines.
73
+ - Never modify git config.
74
+ - Use git worktrees for parallel work.
75
+
76
+ ## Testing
77
+
78
+ - testing will require additional plugins; see table below.
79
+
80
+ | Tool | Install Path |
81
+ |---|---|
82
+ | Xilinx Vivado | https://github.com/sjalloq/sawmill-plugin-vivado.git |
83
+ | Slang | https://github.com/sjalloq/sawmill-plugin-slang.git |
@@ -0,0 +1,115 @@
1
+ Metadata-Version: 2.5
2
+ Name: sawmill-parser
3
+ Version: 0.5.0
4
+ Summary: A configurable TUI for post-processing and filtering structured tool logs
5
+ Project-URL: Homepage, https://github.com/sjalloq/sawmill
6
+ Project-URL: Documentation, https://sjalloq.github.io/sawmill
7
+ Project-URL: Repository, https://github.com/sjalloq/sawmill
8
+ Author: Sawmill Contributors
9
+ License: MIT
10
+ Keywords: eda,filter,log,terminal,tui
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Utilities
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: pluggy>=1.3.0
23
+ Requires-Dist: pydantic>=2.0.0
24
+ Requires-Dist: rich-click>=1.7.0
25
+ Requires-Dist: rich>=13.0.0
26
+ Requires-Dist: textual>=0.40.0
27
+ Requires-Dist: tomli-w>=1.0.0
28
+ Requires-Dist: tomli>=2.0.0
29
+ Requires-Dist: tomlkit>=0.12
30
+ Provides-Extra: dev
31
+ Requires-Dist: mypy>=1.0.0; extra == 'dev'
32
+ Requires-Dist: pre-commit>=3.0.0; extra == 'dev'
33
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
34
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
35
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
36
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
37
+ Requires-Dist: sawmill-plugin-slang; extra == 'dev'
38
+ Requires-Dist: sawmill-plugin-vivado; extra == 'dev'
39
+ Provides-Extra: docs
40
+ Requires-Dist: furo; extra == 'docs'
41
+ Requires-Dist: sphinx; extra == 'docs'
42
+ Requires-Dist: sphinx-autodoc-typehints; extra == 'docs'
43
+ Requires-Dist: sphinx-copybutton; extra == 'docs'
44
+ Description-Content-Type: text/markdown
45
+
46
+ <p align="center">
47
+ <img src="assets/sawmill.png" alt="Sawmill - Cutting through the noise" width="600">
48
+ </p>
49
+
50
+ <h1 align="center">Sawmill</h1>
51
+
52
+ <p align="center">
53
+ <strong>A plugin-driven terminal log analyser</strong>
54
+ </p>
55
+
56
+ Sawmill filters, groups and waives messages from structured tool logs such as
57
+ Vivado and Slang output. A batch CLI gates CI pipelines on log
58
+ content; a terminal UI handles interactive triage. Plugins own the parsing,
59
+ so any log format can be supported.
60
+
61
+ ## Install
62
+
63
+ ```bash
64
+ uv tool install sawmill-parser sawmill-plugin-vivado
65
+ ```
66
+
67
+ Or from a clone:
68
+
69
+ ```bash
70
+ source sourceme # creates .venv with uv and installs dev extras
71
+ ```
72
+
73
+ ## Usage
74
+
75
+ ```bash
76
+ sawmill vivado.log # open one log in the TUI
77
+ sawmill init # create .sawmill/manifest.toml
78
+ sawmill init --target pnr 'build/pnr/*.log' # add a target
79
+ sawmill view # TUI over every target
80
+ sawmill check --report build/report.json # CI gate: exit 1 on unwaived failures
81
+ sawmill report --format junit -o build/sawmill.xml
82
+ sawmill rules unused # rules that matched nothing
83
+ sawmill plugins list
84
+ ```
85
+
86
+ Targets and rules live in a checked-in `.sawmill/` directory: a
87
+ `manifest.toml` naming the targets (plugin plus log globs) and rule files
88
+ under `.sawmill/rules/` that waive expected messages.
89
+
90
+ Full documentation, including the manifest and rule formats, CLI reference,
91
+ TUI guide, CI integration and plugin authoring, is at
92
+ https://sjalloq.github.io/sawmill.
93
+
94
+ ## Plugins
95
+
96
+ | Plugin | Repository |
97
+ |--------|------------|
98
+ | `vivado` | https://github.com/sjalloq/sawmill-plugin-vivado |
99
+ | `slang` | https://github.com/sjalloq/sawmill-plugin-slang |
100
+
101
+ Plugins register through the `sawmill.plugins` entry point and are
102
+ auto-detected from log content. `tools/sawmill-plugin-generator` scaffolds a
103
+ new one.
104
+
105
+ ## Development
106
+
107
+ ```bash
108
+ source sourceme
109
+ pytest tests/ -v
110
+ pre-commit run --all-files
111
+ ```
112
+
113
+ ## License
114
+
115
+ MIT
@@ -0,0 +1,70 @@
1
+ <p align="center">
2
+ <img src="assets/sawmill.png" alt="Sawmill - Cutting through the noise" width="600">
3
+ </p>
4
+
5
+ <h1 align="center">Sawmill</h1>
6
+
7
+ <p align="center">
8
+ <strong>A plugin-driven terminal log analyser</strong>
9
+ </p>
10
+
11
+ Sawmill filters, groups and waives messages from structured tool logs such as
12
+ Vivado and Slang output. A batch CLI gates CI pipelines on log
13
+ content; a terminal UI handles interactive triage. Plugins own the parsing,
14
+ so any log format can be supported.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ uv tool install sawmill-parser sawmill-plugin-vivado
20
+ ```
21
+
22
+ Or from a clone:
23
+
24
+ ```bash
25
+ source sourceme # creates .venv with uv and installs dev extras
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ```bash
31
+ sawmill vivado.log # open one log in the TUI
32
+ sawmill init # create .sawmill/manifest.toml
33
+ sawmill init --target pnr 'build/pnr/*.log' # add a target
34
+ sawmill view # TUI over every target
35
+ sawmill check --report build/report.json # CI gate: exit 1 on unwaived failures
36
+ sawmill report --format junit -o build/sawmill.xml
37
+ sawmill rules unused # rules that matched nothing
38
+ sawmill plugins list
39
+ ```
40
+
41
+ Targets and rules live in a checked-in `.sawmill/` directory: a
42
+ `manifest.toml` naming the targets (plugin plus log globs) and rule files
43
+ under `.sawmill/rules/` that waive expected messages.
44
+
45
+ Full documentation, including the manifest and rule formats, CLI reference,
46
+ TUI guide, CI integration and plugin authoring, is at
47
+ https://sjalloq.github.io/sawmill.
48
+
49
+ ## Plugins
50
+
51
+ | Plugin | Repository |
52
+ |--------|------------|
53
+ | `vivado` | https://github.com/sjalloq/sawmill-plugin-vivado |
54
+ | `slang` | https://github.com/sjalloq/sawmill-plugin-slang |
55
+
56
+ Plugins register through the `sawmill.plugins` entry point and are
57
+ auto-detected from log content. `tools/sawmill-plugin-generator` scaffolds a
58
+ new one.
59
+
60
+ ## Development
61
+
62
+ ```bash
63
+ source sourceme
64
+ pytest tests/ -v
65
+ pre-commit run --all-files
66
+ ```
67
+
68
+ ## License
69
+
70
+ MIT
@@ -18,14 +18,13 @@ templates_path = ["_templates"]
18
18
  exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
19
19
 
20
20
  html_theme = "furo"
21
- html_static_path = ["_static"]
22
21
 
23
22
  autodoc_member_order = "bysource"
24
23
  autodoc_typehints = "description"
25
24
 
26
- # Suppress duplicate object warnings from Pydantic model fields
27
- # and dataclass fields that appear as both class-level and instance-level
28
- suppress_warnings = ["autodoc.duplicate_object"]
25
+ # Render Google-style ``Attributes:`` sections as ``:ivar:`` fields so they
26
+ # do not duplicate the attribute entries autodoc already generates.
27
+ napoleon_use_ivar = True
29
28
 
30
29
  intersphinx_mapping = {
31
30
  "python": ("https://docs.python.org/3", None),
@@ -68,37 +68,6 @@ Run manually:
68
68
 
69
69
  $ pre-commit run --all-files
70
70
 
71
- Docker dev loop
72
- ---------------
73
-
74
- The ``ralph-loop.sh`` script runs Claude Code in a Docker container for
75
- autonomous development iterations:
76
-
77
- .. code-block:: console
78
-
79
- $ ./ralph-loop.sh --iterations 3
80
- $ ./ralph-loop.sh --continuous
81
-
82
- Options:
83
-
84
- ``--iterations N``
85
- Run N iterations (default: 1).
86
-
87
- ``--continuous``
88
- Run until all tasks complete or an error occurs.
89
-
90
- ``--dry-run``
91
- Show what would be done without executing.
92
-
93
- ``--no-docker``
94
- Run directly on the host instead of in a container.
95
-
96
- ``--interactive``
97
- Drop into an interactive shell after each iteration.
98
-
99
- The ``Dockerfile`` builds a container with Python 3.11, Node.js, and
100
- Claude Code CLI pre-installed.
101
-
102
71
  Building docs
103
72
  -------------
104
73
 
@@ -106,8 +75,8 @@ Install documentation dependencies and build:
106
75
 
107
76
  .. code-block:: console
108
77
 
109
- $ pip install -r docs/requirements.txt
110
- $ cd docs && make html
78
+ $ uv sync --all-extras
79
+ $ python -m sphinx -b html docs docs/_build/html
111
80
 
112
81
  The built documentation is in ``docs/_build/html/``. Open
113
82
  ``docs/_build/html/index.html`` in a browser to review.