jekhator/strict-suite
GitHub: jekhator/strict-suite
基于 AST 的 Python 代码检查工具,通过结构化规则强制执行 DTO 规范、模块纪律与类型合规,帮助团队维持清晰的 API 边界。
Stars: 0 | Forks: 0
# strict-suite
[](https://pypi.org/project/strict-suite/)
[](https://github.com/jekhator/strict-suite/actions)
[](LICENSE)
[](https://www.python.org/downloads/)
整合的 Python linter,包含用于 DTO 规范、模块结构、类型合规、常量强制执行和格式化标准的 R001-R015 规则。
**从 strict-module 0.5.0 合并而来。** 此 monorepo 整合了 strict-module 包及相关的 lint 基础设施。保留了向后兼容的 CLI 入口点(`strict-module` 和 `dto-strict`)。
## 概述
数据传输对象(DTO)和外观模式规范对于清晰的 API 边界至关重要,尤其是在受监管的环境中(医疗保健、合规、金融系统)。**stricts** 通过静态 AST 分析执行这些模式,包含 6 条专注的规则:
1. **R001 (HIGH)**:检测 service 层函数签名中的 `Dict[str, Any]` 或裸 `dict`/`list`/`tuple`。
2. **R002 (MEDIUM)**:标记包含 3 个及以上字符串键的内联字典字面量;异常标签可要求提供理由。
3. **R003 (MEDIUM)**:标记 dataclass 中的 `repr=False`(标准规范:普通的 `@dataclass(frozen=True, slots=True)`)。
4. **R004 (HIGH)**:要求模块级函数带有异常标签(例如 `# facade - celery schedule`)。
5. **R005 (LOW)**:鼓励验证器使用 `DTO.from_dict()` 模式。
6. **R006 (HIGH)**:检测函数签名中的 `typing.Any`(参数和返回类型)。
所有规则均可配置;可以禁用违规、覆盖严重级别或限定路径范围。
## 安装
```
pip install strict-suite
```
或包含可选的开发依赖:
```
pip install strict-suite[dev]
```
安装后即可使用两个 CLI 入口点(strict-module 和 dto-strict)。
## 快速开始
### 基础 CLI 用法
```
# Lint 单个文件
strict-module apps/compliance/services.py
# Lint 目录
strict-module apps/
# 输出为 GitHub Actions annotations
strict-module apps/ --format github
# 输出为 JSON
strict-module apps/ --format json
# 使用 compat alias
dto-strict apps/
```
### 运行验证示例
创建一个包含合规代码的测试文件 `example.py`:
```
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class UserDTO:
"""User data transfer object."""
user_id: int
email: str
class UserService:
"""Service to process users."""
def process_user(self, user: UserDTO) -> None:
"""Process a user."""
print(f"Processing {user.email}")
```
然后进行 lint 检查:
```
$ strict-module example.py
# (无输出 = clean)
```
现在创建一个违规示例。将其保存为 `apps/test/services/bad_user.py`:
```
from typing import Any
class UserService:
def process_user(self, config: dict[str, Any]) -> None: # R001: Dict[str, Any] in signature
"""Process a user."""
return config.get("user_id")
```
运行 linter(从仓库根目录):
```
$ strict-module apps/test/services/bad_user.py
apps/test/services/bad_user.py:4: R001 Dict[str, Any] in signature: process_user
apps/test/services/bad_user.py:4: R006 typing.Any in parameter: process_user
```
### 所有规则演示
**R002**(包含 3 个及以上键的内联字典字面量):
```
# violation
def example():
data = {"key1": "val1", "key2": "val2", "key3": "val3"}
```
**R003**(在 dataclass 上使用非标准的 repr=False):
```
# violation
from dataclasses import dataclass
@dataclass(repr=False)
class MyDTO:
value: int
```
**R004**(没有异常标签的模块级函数):
```
# violation (在 non-conftest 文件中)
def process_data(item):
return item["id"]
```
**R007**(conftest.py 之外的 pytest fixtures):
```
# violation
import pytest
@pytest.fixture
def my_fixture():
return "value"
```
**R008**(裸模块级测试函数):
```
# violation
def test_something():
assert True
```
### LOC 限制强制执行
检查代码行数限制:
```
$ strict-module loc-cap src/
src/long_module.py: soft-target 500 exceeded (523 lines)
src/another.py: hard-cap 694 exceeded (750 lines) FAIL
```
生成基线:
```
$ strict-module loc-cap src/ --generate-baseline > .loc-cap-baseline.txt
```
### 使用两个 CLI 入口点
`strict-module` 和 `dto-strict` 是等效的别名:
```
strict-module apps/
dto-strict apps/
```
## 配置
配置存在于 `pyproject.toml` 中:
```
[tool.strict-module]
service_paths = ["apps/*/services/*.py", "**/services/*.py"]
dto_paths = ["**/dtos.py", "**/dtos/*.py"]
exception_tags = [
"facade - celery schedule",
"FRAMEWORK",
"aws-boundary"
]
disabled_rules = []
severity_overrides = {}
```
- **service_paths**:用于通过 R001(严格模式)进行 lint 的文件的 Glob 匹配模式。
- **dto_paths**:预期包含 DTO 定义的文件的 Glob 匹配模式。
- **exception_tags**:模块级函数可识别的合理性标签(R004 和 R009)。例如:`aws-boundary` 可以豁免函数使其不受模块级函数规则的约束。
- **disabled_rules**:要禁用的规则 ID 列表(例如,["R005"])。
- **severity_overrides**:将规则 ID 映射到覆盖严重级别的字典(例如,{"R002": "HIGH", "R011": "INFO"})。
向后兼容性:支持 `[tool.strict-module]` 配置和 `.strict-module-baseline.json` 基线文件。
### 抑制违规
使用 `# noqa` 注释来抑制特定行的违规。支持的形式:
- **裸 `# noqa`**:抑制该行上的任何规则。
x = {1: 2, 3: 4, 5: 6} # noqa
- **特定规则 `# noqa: R006`**:通过 ID 抑制单个规则。
def process(x: Any) -> None: # noqa: R006
pass
- **命名空间形式 `# noqa: strict-module-R006`**:使用 ruff 外部友好的命名空间形式(推荐在同时运行 ruff 时使用)。
def process(x: Any) -> None: # noqa: strict-module-R006
pass
- **多个规则 `# noqa: R006, R011`**:在一行上抑制多个规则。
def process(x: Any) -> None: # noqa: R006, R011
pass
**关于 R014(kwarg 分组)的特殊说明:** R014 的检查结果会在违规的 kwarg 行报告,但 noqa 抑制仅在使用调用开始的行生效。请将 noqa 注释放在 CALL(调用)行,而不是 kwarg 行:
```
self.log_event( # noqa: R014
const.LOG_EVENT_SUCCESS, a=1, b=2, c=3, d=4,
)
```
当同时使用 ruff 时,在 `pyproject.toml` 中声明 `[tool.ruff.lint] external = ["strict-module"]` 以防止 ruff 对外部规则代码发出警告。
## Public API
该包导出以下公共符号:
- **`__version__`**:包版本字符串(例如,"0.1.0")
- **`DtoStrictLinter`**:用于运行 AST 分析的主要 linter 类
- **`Rule`**:规则定义 dataclass
- **`RuleSeverity`**:规则严重级别的枚举(HIGH、MEDIUM、LOW)
用法示例:
```
from strict_module import DtoStrictLinter, Rule, RuleSeverity, __version__
print(f"strict-suite {__version__}")
linter = DtoStrictLinter()
violations = linter.lint_file("mymodule.py")
for v in violations:
print(f"{v.rule_id} ({v.severity.value}): {v.message}")
```
## 文档
完整文档(包括规则详情、配置选项和集成指南)可在 `docs/` 目录中获取。
历史更新日志:有关 strict-module v0.1.0 到 v0.5.0 的发布历史,请参见 `CHANGELOG-history.md`。
## 开发
安装开发依赖:
```
pip install -e ".[dev]"
```
运行测试:
```
python3.12 -m pytest strict_module/tests/ -v
```
运行自检检查:
```
strict-module strict_module/ --format text
dto-strict strict_module/
```
运行格式和样式检查:
```
ruff check strict_module/
ruff format --check strict_module/
```
运行 LOC 限制检查:
```
strict-module loc-cap strict_module/
```
## 许可证
Apache License 2.0。完整文本请参见 [LICENSE](LICENSE)。
## 贡献
欢迎贡献。请确保:
- 所有测试均通过。
- 代码遵循项目的 lint 规则(对您的更改运行 `strict-module`)。
- 提交信息清晰并描述更改。
- 提交信息中不要包含 AI 署名。
标签:Python, SOC Prime, 云安全监控, 代码规范, 开发工具, 无后门, 自动化payload嵌入, 逆向工具, 静态分析