gravitas-python

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GRAVITAS — Python Extension

GRAVITAS — Python 扩展

Extends the base GRAVITAS skill with Python-specific patterns. Load
skills/gravitas/SKILL.md
first, then this file.

扩展基础 GRAVITAS skill,添加 Python 专属模式。 先加载
skills/gravitas/SKILL.md
,然后加载本文件。

Python Recon Additions

Python 侦察补充项

□ pyproject.toml — [tool.mypy], [tool.ruff], [tool.pytest.ini_options]
□ setup.py / setup.cfg — legacy config
□ requirements.txt / requirements-dev.txt — dependency versions
□ conftest.py — pytest fixtures (critical for understanding test patterns)
□ __init__.py — package structure
□ Type stubs — are there py.typed markers? stub packages installed?
□ pyproject.toml — [tool.mypy], [tool.ruff], [tool.pytest.ini_options]
□ setup.py / setup.cfg — legacy config
□ requirements.txt / requirements-dev.txt — dependency versions
□ conftest.py — pytest fixtures (critical for understanding test patterns)
□ __init__.py — package structure
□ Type stubs — are there py.typed markers? stub packages installed?

Read pyproject.toml for type strictness

读取 pyproject.toml 了解类型严格程度

bash
cat pyproject.toml | grep -A 10 "\[tool.mypy\]"
cat pyproject.toml | grep -A 10 "\[tool.ruff\]"

bash
cat pyproject.toml | grep -A 10 "\[tool.mypy\]"
cat pyproject.toml | grep -A 10 "\[tool.ruff\]"

Python Verification Chain

Python 验证链

bash
undefined
bash
undefined

Full chain — in this order

Full chain — in this order

mypy . --strict # type correctness ruff check . # lint (fast, Rust-based) ruff format --check . # format check pytest -v --tb=short # all tests
mypy . --strict # type correctness ruff check . # lint (fast, Rust-based) ruff format --check . # format check pytest -v --tb=short # all tests

With coverage

With coverage

pytest --cov=src --cov-report=term-missing -v
pytest --cov=src --cov-report=term-missing -v

Type coverage

Type coverage

mypy . --strict 2>&1 | tail -5 # summary line shows error count

---
mypy . --strict 2>&1 | tail -5 # summary line shows error count

---

Python-Specific Anti-Patterns

Python 专属反模式

Never use bare
except

切勿使用裸
except

python
BAD:  except:
GOOD: except ValueError as e:
GOOD: except (TypeError, ValueError) as e:
python
BAD:  except:
GOOD: except ValueError as e:
GOOD: except (TypeError, ValueError) as e:

Never shadow builtins

切勿遮蔽内置函数

python
BAD:  list = [1, 2, 3]     # shadows list()
BAD:  id = user.id         # shadows id()
GOOD: items = [1, 2, 3]
GOOD: user_id = user.id
python
BAD:  list = [1, 2, 3]     # shadows list()
BAD:  id = user.id         # shadows id()
GOOD: items = [1, 2, 3]
GOOD: user_id = user.id

Type annotations required (with mypy strict)

必须添加类型注解(配合 mypy strict)

python
BAD:  def process(data):
GOOD: def process(data: dict[str, Any]) -> ProcessResult:
python
BAD:  def process(data):
GOOD:  def process(data: dict[str, Any]) -> ProcessResult:

Use dataclasses or Pydantic over dicts for structured data

结构化数据优先使用 dataclasses 或 Pydantic,而非 dicts

python
BAD:  return {"user_id": 1, "name": "Alice"}   # no type safety
GOOD: return UserResponse(user_id=1, name="Alice")

python
BAD:  return {"user_id": 1, "name": "Alice"}   # no type safety
GOOD: return UserResponse(user_id=1, name="Alice")

Common Python Failure Modes

常见的 Python 故障模式

FailureRoot CauseFix
Optional[X] has no attribute Y
None not handledAdd
if x is not None:
guard
Incompatible return value type
Wrong return typeCheck function signature
Missing return statement
Not all paths returnAdd explicit return
Module has no attribute X
Wrong importCheck module with
dir(module)
Cannot find implementation for X
Missing stubInstall
types-X
package
Circular importImport at module levelMove to function level or restructure

故障根本原因修复方式
Optional[X] has no attribute Y
未处理 None添加
if x is not None:
守卫
Incompatible return value type
返回类型错误检查函数签名
Missing return statement
并非所有路径都会返回添加显式 return
Module has no attribute X
导入错误使用
dir(module)
检查模块
Cannot find implementation for X
缺少 stub安装
types-X
包
Circular import在模块级导入移至函数级或重构

Test Patterns (pytest)

测试模式(pytest)

Fixture pattern

Fixture 模式

python
undefined
python
undefined

conftest.py

conftest.py

import pytest from myapp.db import get_db
@pytest.fixture def db(): conn = get_db(":memory:") yield conn conn.close()
@pytest.fixture def client(db): from myapp import create_app app = create_app({"TESTING": True}) with app.test_client() as c: yield c
undefined
import pytest from myapp.db import get_db
@pytest.fixture def db(): conn = get_db(":memory:") yield conn conn.close()
@pytest.fixture def client(db): from myapp import create_app app = create_app({"TESTING": True}) with app.test_client() as c: yield c
undefined

Standard test structure

标准测试结构

python
class TestUserAuth:
    def test_login_success(self, client, db):
        # Arrange
        db.execute("INSERT INTO users VALUES (1, 'alice', 'hash')")
        # Act
        response = client.post("/login", json={"username": "alice", "password": "pw"})
        # Assert
        assert response.status_code == 200
        assert response.json["token"] is not None

    def test_login_wrong_password(self, client, db):
        response = client.post("/login", json={"username": "alice", "password": "wrong"})
        assert response.status_code == 401
python
class TestUserAuth:
    def test_login_success(self, client, db):
        # Arrange
        db.execute("INSERT INTO users VALUES (1, 'alice', 'hash')")
        # Act
        response = client.post("/login", json={"username": "alice", "password": "pw"})
        # Assert
        assert response.status_code == 200
        assert response.json["token"] is not None

    def test_login_wrong_password(self, client, db):
        response = client.post("/login", json={"username": "alice", "password": "wrong"})
        assert response.status_code == 401

Parametrize for edge cases

使用 Parametrize 覆盖边界情况

python
@pytest.mark.parametrize("input,expected", [
    ("", ValueError),
    (None, TypeError),
    ("valid@email.com", None),
    ("not-an-email", ValueError),
])
def test_validate_email(input, expected):
    if expected:
        with pytest.raises(expected):
            validate_email(input)
    else:
        validate_email(input)  # should not raise

python
@pytest.mark.parametrize("input,expected", [
    ("", ValueError),
    (None, TypeError),
    ("valid@email.com", None),
    ("not-an-email", ValueError),
])
def test_validate_email(input, expected):
    if expected:
        with pytest.raises(expected):
            validate_email(input)
    else:
        validate_email(input)  # should not raise

Framework-Specific Notes

框架专属说明

FastAPI

FastAPI

python
undefined
python
undefined

Always test with TestClient, not raw function calls

Always test with TestClient, not raw function calls

from fastapi.testclient import TestClient client = TestClient(app)
from fastapi.testclient import TestClient client = TestClient(app)

Type all path/query params and bodies

Type all path/query params and bodies

@router.post("/users", response_model=UserResponse) async def create_user(body: CreateUserRequest) -> UserResponse: ...
undefined
@router.post("/users", response_model=UserResponse) async def create_user(body: CreateUserRequest) -> UserResponse: ...
undefined

Django

Django

python
undefined
python
undefined

Use pytest-django

Use pytest-django

settings for tests

settings for tests

@pytest.mark.django_db def test_user_creation(): user = User.objects.create_user(username="test", password="pass") assert user.id is not None

---
@pytest.mark.django_db def test_user_creation(): user = User.objects.create_user(username="test", password="pass") assert user.id is not None

---

Quick Reference

快速参考

bash
undefined
bash
undefined

Run single test file

Run single test file

pytest src/auth/test_session.py -v
pytest src/auth/test_session.py -v

Run single test

Run single test

pytest src/auth/test_session.py::TestSession::test_timeout -v
pytest src/auth/test_session.py::TestSession::test_timeout -v

Run with pdb on failure

Run with pdb on failure

pytest --pdb
pytest --pdb

Show slowest tests

Show slowest tests

pytest --durations=10
pytest --durations=10

Type check single file

Type check single file

mypy src/auth/session.py --strict
undefined
mypy src/auth/session.py --strict
undefined