scitex-linter 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,277 @@
1
+ Metadata-Version: 2.4
2
+ Name: scitex-linter
3
+ Version: 0.1.0
4
+ Summary: AST-based linter enforcing SciTeX reproducible research patterns
5
+ Author: ywatanabe
6
+ License: AGPL-3.0
7
+ Project-URL: Documentation, https://scitex-linter.readthedocs.io
8
+ Project-URL: Repository, https://github.com/ywatanabe1989/scitex-linter
9
+ Requires-Python: >=3.8
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Provides-Extra: mcp
13
+ Requires-Dist: fastmcp; extra == "mcp"
14
+ Provides-Extra: docs
15
+ Requires-Dist: sphinx>=7.0; extra == "docs"
16
+ Requires-Dist: sphinx-rtd-theme>=2.0; extra == "docs"
17
+ Requires-Dist: myst-parser>=2.0; extra == "docs"
18
+ Requires-Dist: sphinx-copybutton>=0.5; extra == "docs"
19
+ Requires-Dist: sphinx-autodoc-typehints>=1.25; extra == "docs"
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest; extra == "dev"
22
+ Requires-Dist: pytest-cov; extra == "dev"
23
+ Requires-Dist: ruff; extra == "dev"
24
+ Provides-Extra: all
25
+ Requires-Dist: scitex-linter[mcp]; extra == "all"
26
+ Requires-Dist: scitex-linter[docs]; extra == "all"
27
+ Requires-Dist: scitex-linter[dev]; extra == "all"
28
+ Dynamic: license-file
29
+
30
+ <!-- ---
31
+ !-- Timestamp: 2026-02-06 20:53:45
32
+ !-- Author: ywatanabe
33
+ !-- File: /home/ywatanabe/proj/scitex-linter/README.md
34
+ !-- --- -->
35
+
36
+ # SciTeX Linter
37
+
38
+ <p align="center">
39
+ <a href="https://scitex.ai">
40
+ <img src="docs/scitex-logo-banner.png" alt="SciTeX Linter" width="400">
41
+ </a>
42
+ </p>
43
+
44
+ <p align="center">
45
+ <a href="https://badge.fury.io/py/scitex-linter"><img src="https://badge.fury.io/py/scitex-linter.svg" alt="PyPI version"></a>
46
+ <a href="https://pypi.org/project/scitex-linter/"><img src="https://img.shields.io/pypi/pyversions/scitex-linter.svg" alt="Python Versions"></a>
47
+ <a href="https://scitex-linter.readthedocs.io/"><img src="https://readthedocs.org/projects/scitex-linter/badge/?version=latest" alt="Documentation"></a>
48
+ <a href="https://github.com/ywatanabe1989/scitex-linter/blob/main/LICENSE"><img src="https://img.shields.io/github/license/ywatanabe1989/scitex-linter" alt="License"></a>
49
+ </p>
50
+
51
+ <p align="center">
52
+ <a href="https://scitex.ai">scitex.ai</a> ยท <a href="https://scitex-linter.readthedocs.io/">docs</a> ยท <code>pip install scitex-linter</code>
53
+ </p>
54
+
55
+ ---
56
+
57
+ **AST-based Python linter enforcing [SciTeX](https://scitex.ai) reproducible research patterns.**
58
+
59
+ Part of the [SciTeX](https://scitex.ai) ecosystem โ€” guides both human researchers and AI agents toward reproducible science.
60
+
61
+ ## Why SciTeX Linter?
62
+
63
+ SciTeX scripts follow strict patterns for reproducibility: `@stx.session` decorators, `stx.io` for provenance-tracked I/O, `stx.stats` for complete statistical reporting, and relative paths for portability. SciTeX Linter enforces these patterns at the AST level โ€” catching issues before they become irreproducible results.
64
+
65
+ ## Quick Start
66
+
67
+ ```bash
68
+ pip install scitex-linter
69
+ ```
70
+
71
+ ```bash
72
+ # Lint a file
73
+ scitex-linter lint script.py
74
+
75
+ # Lint then execute
76
+ scitex-linter python experiment.py --strict
77
+
78
+ # List all 35 rules
79
+ scitex-linter list-rules
80
+ ```
81
+
82
+ ## Four Interfaces
83
+
84
+ | Interface | For | Description |
85
+ |-----------|-----|-------------|
86
+ | ๐Ÿ–ฅ๏ธ **CLI** | Terminal users | `scitex-linter lint`, `scitex-linter python` |
87
+ | ๐Ÿ **Python API** | Programmatic use | `from scitex_linter.checker import lint_file` |
88
+ | ๐Ÿ”Œ **flake8 Plugin** | CI pipelines | `flake8 --select STX` |
89
+ | ๐Ÿ”ง **MCP Server** | AI agents | 3 tools for Claude/GPT integration |
90
+
91
+ <details>
92
+ <summary><strong>๐Ÿ–ฅ๏ธ CLI Commands</strong></summary>
93
+
94
+ <br>
95
+
96
+ ```bash
97
+ scitex-linter --help # Show all commands
98
+ scitex-linter --help-recursive # Show help for all subcommands
99
+
100
+ # Lint - Check for SciTeX pattern violations
101
+ scitex-linter lint script.py # Lint a file
102
+ scitex-linter lint ./src/ # Lint a directory
103
+ scitex-linter lint script.py --severity error # Only errors
104
+ scitex-linter lint script.py --category path # Only path rules
105
+ scitex-linter lint script.py --json # JSON output for CI
106
+
107
+ # Python - Lint then execute
108
+ scitex-linter python experiment.py # Lint and run
109
+ scitex-linter python experiment.py --strict # Abort on errors
110
+ scitex-linter python experiment.py -- --lr 0.001 # Pass script args
111
+
112
+ # Rules - Browse available rules
113
+ scitex-linter list-rules # List all 35 rules
114
+ scitex-linter list-rules --category stats # Filter by category
115
+ scitex-linter list-rules --json # JSON output
116
+
117
+ # MCP - AI agent server
118
+ scitex-linter mcp start # Start MCP server (stdio)
119
+ scitex-linter mcp list-tools # List MCP tools
120
+ ```
121
+
122
+ </details>
123
+
124
+ <details>
125
+ <summary><strong>๐Ÿ Python API</strong></summary>
126
+
127
+ <br>
128
+
129
+ ```python
130
+ from scitex_linter.checker import lint_file
131
+ from scitex_linter.formatter import format_issue
132
+
133
+ # Lint a file
134
+ issues = lint_file("script.py")
135
+ for issue in issues:
136
+ print(format_issue(issue, "script.py"))
137
+
138
+ # Check source code directly
139
+ from scitex_linter.checker import lint_source
140
+ issues = lint_source("import argparse\npass\n")
141
+ ```
142
+
143
+ </details>
144
+
145
+ <details>
146
+ <summary><strong>๐Ÿ”Œ flake8 Plugin</strong></summary>
147
+
148
+ <br>
149
+
150
+ SciTeX Linter registers as a flake8 plugin with the `STX` prefix:
151
+
152
+ ```bash
153
+ flake8 --select STX script.py
154
+ flake8 --select STX ./src/ --format=json
155
+ ```
156
+
157
+ Integrates with existing flake8 workflows, pre-commit hooks, and CI pipelines.
158
+
159
+ </details>
160
+
161
+ <details>
162
+ <summary><strong>๐Ÿ”ง MCP Server โ€” 3 Tools for AI Agents</strong></summary>
163
+
164
+ <br>
165
+
166
+ | Tool | Description |
167
+ |------|-------------|
168
+ | `linter_lint` | Lint a Python file for SciTeX compliance |
169
+ | `linter_list_rules` | List all available rules |
170
+ | `linter_check_source` | Lint source code string |
171
+
172
+ **Claude Desktop** (`~/.config/Claude/claude_desktop_config.json`):
173
+
174
+ ```json
175
+ {
176
+ "mcpServers": {
177
+ "scitex-linter": {
178
+ "command": "scitex-linter",
179
+ "args": ["mcp", "start"]
180
+ }
181
+ }
182
+ }
183
+ ```
184
+
185
+ Install MCP extra: `pip install scitex-linter[mcp]`
186
+
187
+ </details>
188
+
189
+ ## 35 Rules Across 7 Categories
190
+
191
+ | Category | Rules | Severity | What It Enforces |
192
+ |----------|------:|----------|-----------------|
193
+ | **S** Structure | 5 | error/warning | `@stx.session`, `__main__` guard, no argparse |
194
+ | **I** Import | 7 | warning/info | Use `stx.plt`, `stx.stats`, `stx.io` instead of raw libs |
195
+ | **IO** I/O Calls | 7 | warning | Use `stx.io.save()`/`stx.io.load()` for provenance |
196
+ | **P** Plot | 5 | info | Use `stx.plt` tracked methods, `logger` over `print()` |
197
+ | **ST** Stats | 6 | warning | Use `stx.stats` for auto effect size + CI + power |
198
+ | **PA** Path | 5 | warning/info | Relative paths with `./`, no `open()`, no `os.chdir()` |
199
+
200
+ <details>
201
+ <summary><strong>Example Output</strong></summary>
202
+
203
+ <br>
204
+
205
+ ```
206
+ script.py:1 STX-S003 [error] argparse detected โ€” @stx.session auto-generates CLI
207
+ Suggestion: Remove `import argparse` and define parameters as function arguments:
208
+ @stx.session
209
+ def main(data_path: str, threshold: float = 0.5):
210
+ # Auto-generates: --data-path, --threshold
211
+
212
+ script.py:5 STX-PA001 [warning] Absolute path in `stx.io` call โ€” use relative paths
213
+ Suggestion: Use `stx.io.save(obj, './relative/path.ext')` โ€” paths resolve to script_out/.
214
+
215
+ script.py: 2 issues (1 error, 1 warning)
216
+ ```
217
+
218
+ </details>
219
+
220
+ <details>
221
+ <summary><strong>Full Rules Reference</strong></summary>
222
+
223
+ <br>
224
+
225
+ See [Rules Reference](https://scitex-linter.readthedocs.io/en/latest/rules.html) for all 35 rules with descriptions and suggestions.
226
+
227
+ </details>
228
+
229
+ ## Claude Code Hook
230
+
231
+ SciTeX Linter works as a **post-tool-use hook** for Claude Code, automatically linting every Python file Claude writes or edits:
232
+
233
+ ```bash
234
+ # In ~/.claude/to_claude/hooks/post-tool-use/run_lint.sh
235
+ # Errors (exit 2) โ†’ Claude must fix
236
+ # Warnings (exit 1) โ†’ Claude sees feedback
237
+ ```
238
+
239
+ This ensures AI-generated code follows SciTeX patterns from the start.
240
+
241
+ ## What a Clean Script Looks Like
242
+
243
+ ```python
244
+ import scitex as stx
245
+
246
+ @stx.session
247
+ def main(data_path="./data.csv", threshold=0.5):
248
+ df = stx.io.load(data_path)
249
+ results = stx.stats.ttest_ind(df["group_a"], df["group_b"])
250
+ stx.io.save(results, "./results.csv")
251
+ return 0
252
+
253
+ if __name__ == "__main__":
254
+ main()
255
+ ```
256
+
257
+ Zero lint issues. Fully reproducible. Auto-CLI from function signature.
258
+
259
+ ## Documentation
260
+
261
+ ๐Ÿ“š **[Full Documentation on Read the Docs](https://scitex-linter.readthedocs.io/)**
262
+
263
+ - [Installation](https://scitex-linter.readthedocs.io/en/latest/installation.html)
264
+ - [Quick Start](https://scitex-linter.readthedocs.io/en/latest/quickstart.html)
265
+ - [Rules Reference](https://scitex-linter.readthedocs.io/en/latest/rules.html)
266
+ - [CLI Reference](https://scitex-linter.readthedocs.io/en/latest/cli.html)
267
+ - [Claude Code Hook](https://scitex-linter.readthedocs.io/en/latest/hook.html)
268
+
269
+ ---
270
+
271
+ <p align="center">
272
+ <a href="https://scitex.ai" target="_blank"><img src="docs/scitex-icon-navy-inverted.png" alt="SciTeX" width="40"/></a>
273
+ <br>
274
+ AGPL-3.0 ยท ywatanabe@scitex.ai
275
+ </p>
276
+
277
+ <!-- EOF -->
@@ -0,0 +1,17 @@
1
+ scitex_linter/__init__.py,sha256=3Jt4Nr1NFo5kd8ctgaTWrQXCfiECWZu32HuNl_SXLIM,104
2
+ scitex_linter/_server.py,sha256=yzhsPDfNZVjDxc0KkrNYqZ9625ZUdPL0820Sk0zfb3Q,544
3
+ scitex_linter/checker.py,sha256=_qDFxPvwUMOhQSAUQv-jT0eApV8uXUSjbhFMGPFVas4,16789
4
+ scitex_linter/cli.py,sha256=1Aau478i6BIxr5q4A8Xbuda8PYZQVw-78U-KxBYhIPk,13888
5
+ scitex_linter/flake8_plugin.py,sha256=2FfGpCy8lWNgdkk09jRTYOILMkGIP_EJS6x0l9q-Wvc,1024
6
+ scitex_linter/formatter.py,sha256=WgFHJCl0rPxdm6e2t0htjFSI5uyPyGVxX4VFtPs6XEs,3075
7
+ scitex_linter/rules.py,sha256=kLxUhb3H-zjeR3M-FRBT5JONhyBoPORCPjEU8qYhT2w,11372
8
+ scitex_linter/runner.py,sha256=JcSII85keuhOXxtCM8vS_HSH0FDUr6t48nqoSz8IGRU,2211
9
+ scitex_linter/_mcp/__init__.py,sha256=mrI1dFFxyTRq2F_yxoLYRnyYro2f8CrRNNk2NYLBpWM,41
10
+ scitex_linter/_mcp/tools/__init__.py,sha256=ZggLuukCaOZ2XhfkNQvYMuszY0BX0hDy9I50hUDJ_xo,208
11
+ scitex_linter/_mcp/tools/lint.py,sha256=cDSzzoCP0XrzVJ72PaeGpE4opz7gmV9jrwwNV2jb8XM,2118
12
+ scitex_linter-0.1.0.dist-info/licenses/LICENSE,sha256=TfPDBt3ar0uv_f9cqCDMZ5rIzW3CY8anRRd4PkL6ejs,34522
13
+ scitex_linter-0.1.0.dist-info/METADATA,sha256=ANqfwltlnFTmqcMHljHoqe7dLwUnWoxjh8415dYjwtY,8921
14
+ scitex_linter-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
15
+ scitex_linter-0.1.0.dist-info/entry_points.txt,sha256=a0bIGVJmB96OPDbcLMn_mO_ZCZpv8SKlHMIhpxjLt5M,131
16
+ scitex_linter-0.1.0.dist-info/top_level.txt,sha256=FVu-yranpm0Bt0QZA7ohavSovYgCAhhh5YqiPB2HTJQ,14
17
+ scitex_linter-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,5 @@
1
+ [console_scripts]
2
+ scitex-linter = scitex_linter.cli:main
3
+
4
+ [flake8.extension]
5
+ STX = scitex_linter.flake8_plugin:SciTeXFlake8Checker