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.
- scitex_linter/__init__.py +3 -0
- scitex_linter/_mcp/__init__.py +1 -0
- scitex_linter/_mcp/tools/__init__.py +8 -0
- scitex_linter/_mcp/tools/lint.py +67 -0
- scitex_linter/_server.py +23 -0
- scitex_linter/checker.py +469 -0
- scitex_linter/cli.py +449 -0
- scitex_linter/flake8_plugin.py +34 -0
- scitex_linter/formatter.py +95 -0
- scitex_linter/rules.py +384 -0
- scitex_linter/runner.py +72 -0
- scitex_linter-0.1.0.dist-info/METADATA +277 -0
- scitex_linter-0.1.0.dist-info/RECORD +17 -0
- scitex_linter-0.1.0.dist-info/WHEEL +5 -0
- scitex_linter-0.1.0.dist-info/entry_points.txt +5 -0
- scitex_linter-0.1.0.dist-info/licenses/LICENSE +661 -0
- scitex_linter-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -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,,
|