M07 summary + bridge к mypy — Run-on-Your-Machine
Этот финальный урок Module 07 — bridge между in-browser learning environment (Pyodide-driven challenges) и production toolchain на вашей local machine. Type hints сами по себе ничего не enforce’ят — нужен type checker (mypy / pyright / ty), запускаемый на вашем коде. В этом уроке: M07 recap + Run-on-Your-Machine instructions для mypy.
В этом уроке:
- M07 recap — 6 уроков, ключевые концепции.
- Why mypy — браузер не может type-check.
- Run-on-Your-Machine —
pip install mypy+mypy --strict file.py+ samplemypy.ini. - Brief mypy alternatives — pyright, ty (deferred к v2).
- Forward-link Phase 69 — mypy в pre-commit hook / CI workflow.
M07 recap — 6 уроков, 6 концепций
| # | Урок | Ключевая концепция | Cite |
|---|---|---|---|
| 1 | basic-syntax | PEP 585 built-in generics + PEP 604 unions | PEP 585, PEP 604, Lib/types.py UnionType |
| 2 | generics | PEP 695 inline syntax + ParamSpec | PEP 695, PEP 612, Lib/typing.py TypeVar |
| 3 | protocol-typeddict | Protocol structural subtyping + TypedDict | PEP 544, PEP 589, PEP 655 Required |
| 4 | runtime-introspection | get_type_hints + inspect.signature + dataclasses.fields | Lib/typing.py, Lib/inspect.py, Lib/dataclasses.py |
| 5 | narrowing-and-type-guards | isinstance / TypeGuard / TypeIs (Python 3.13) | PEP 647, PEP 742 forward note |
| 6 | typed-exceptions | Custom Exception + try/except/else/finally + chaining | PEP 654, PEP 3134, Lib/builtins.py |
Cross-module bridges уже накоплены:
- M02 урок 06 → M07 урок 01:
tuple[int, ...]immutable hashable handle, теперь typed. - M03 урок 04 → M07 урок 02: closure carries
*args/**kwargs; ParamSpec — type-system overlay поверх. - M04 урок 04 → M07 урок 03: Protocol vs ABC — structural vs nominal subtyping.
- M04 урок 05 → M07 урок 04:
@dataclass(frozen=True, slots=True)+ type hints +dataclasses.fields()= framework basis. - M06 урок 04 → M07 урок 06: context-manager vs try/finally — when to choose.
- M07 урок 07 (этот) → Phase 69: mypy в CI workflow.
Type-hints — overlay поверх runtime stack. Существующие primitives (closure, generator, dataclass, context-manager) не меняются — они получают type-system view.
Why mypy — браузер не может type-check
Type hints — аннотации. Python interpreter их хранит в __annotations__, но не enforce’ит — def f(x: int) -> int: return x спокойно вызывается с f('hello') и returns 'hello'. Type checking — отдельный инструмент:
- mypy — оригинальный, reference implementation. Python-based, slower but feature-complete.
- pyright — Microsoft, TypeScript-based, faster, used VSCode Pylance.
- ty (“type” — Astral.sh, 2024+) — Rust-based, ultra-fast, early stage. Astral акредитована OpenAI в марте 2026 (deal pending regulatory close); ty / ruff / uv остаются OSS commitment per OpenAI и Astral CEO Charlie Marsh.
Pyodide (browser Python) — interpreter, не type-checker. Чтобы реально проверить ваш typed code — нужно local install и запуск на вашей машине.
Это invariant курса: все type-checking happens locally. Browser challenges — runtime correctness only (does code produce expected output).
Run-on-Your-Machine — mypy installation
Run-on-Your-Machine: install и запустить mypy locally
Шаги для проверки typed code из M07 на вашей machine:
# 1. Install mypy в virtual environment
python3 -m venv .venv
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
pip install mypyПроверьте version:
mypy --version
# mypy 1.8.0 (compiled: yes)2. Создайте файл example.py (любой код из M07):
# example.py
def parse_age(s: str) -> int | None:
try:
return int(s)
except ValueError:
return None
def use_age(s: str) -> str:
age = parse_age(s)
return f'age + 1 = {age + 1}' # ← BUG: age may be None!3. Run mypy:
mypy example.pyExpected output:
example.py:9: error: Unsupported operand types for + ("None" and "int") [operator]
example.py:9: note: Left operand is of type "int | None"
Found 1 error in 1 file (checked 1 source file)mypy поймал bug до запуска! age может быть None — age + 1 поднимет TypeError в runtime. Лечение: if age is None: ... narrowing (M07 урок 05) → mypy approves.
4. Run в strict mode:
mypy --strict example.pyStrict mode включает все warnings: --disallow-untyped-defs, --warn-return-any, --strict-equality и т.д. Production-grade hygiene.
Run-on-Your-Machine — mypy.ini configuration
Run-on-Your-Machine: project-wide mypy.ini
Configuration через mypy.ini (или pyproject.toml [tool.mypy]):
1. Создайте mypy.ini в корне проекта:
[mypy]
python_version = 3.13
strict = True
warn_unused_ignores = True
warn_redundant_casts = True
disallow_any_generics = True
implicit_reexport = False
show_error_codes = True
show_column_numbers = True
# Per-module overrides — useful для third-party libraries без stubs
[mypy-some_legacy_lib.*]
ignore_missing_imports = True2. Run без аргументов — mypy использует mypy.ini:
mypy .Expected output (если example.py clean):
Success: no issues found in 1 source file3. Strictness flags — что включает strict = True:
| Flag | Effect |
|---|---|
--disallow-untyped-defs | All functions must have type annotations |
--disallow-untyped-calls | Cannot call untyped functions |
--warn-return-any | Warn if function returns Any |
--no-implicit-optional | def f(x: int = None) — error (must write `int |
--warn-unused-ignores | Warn on # type: ignore comments больше не nededed |
--strict-equality | 1 == 'hello' — error (incompatible types) |
--warn-redundant-casts | Warn on cast(int, x) if x уже int |
Это — production baseline. Rolling out strict постепенно: start с relaxed, add flags as project matures.
Brief alternatives — pyright и ty
pyright (Microsoft, OSS):
- TypeScript-based — installed via
npm install -g pyright(илиpip install pyright). - Faster чем mypy (incremental, multi-core).
- Used by VSCode Pylance extension under the hood.
- Strict mode default-er чем mypy.
# Run pyright:
pyright example.py
ty (Astral.sh, 2024+):
- Rust-based — ultra-fast (10-100x mypy).
- Early stage (0.x version, 2026); production-readiness emerging.
- Drop-in replacement aspirations для mypy CLI.
- OpenAI acquired Astral в марте 2026 (OpenAI announcement) — deal pending regulatory review. Astral CEO Charlie Marsh подтвердил продолжение OSS development всех инструментов (uv, ruff, ty); OpenAI committed support. Для DE-команд это означает: ty / ruff / uv остаются open-source — но roadmap может integrate с Codex/AI tooling сильнее.
# Install (when available stable):
# pip install ty
# ty check example.py
Choice rationale для M07 курса: mypy — reference implementation, most mature, official Python.org documentation references. pyright worth knowing для VSCode users. ty — следить, но ещё early. Deferred глубокое лечение alternatives к v2 курса.
Forward-link Phase 69 — CI integration
mypy + pre-commit hook + CI workflow — production hygiene. Phase 69 (Production Skills) будет cover:
pre-commithook —pip install pre-commit+.pre-commit-config.yamlс mypy entry. Runs before every commit, blocks bad commits locally.- GitHub Actions workflow —
.github/workflows/typecheck.ymlrunningmypy --strict src/on PR. - Strictness ratchet — start
strict = False, add per-module strict overrides, ratchet к full strict per milestone. # type: ignore[error-code]— surgical bypass для third-party limitations.
# .github/workflows/typecheck.yml (Phase 69 preview):
name: Type Check
on: [push, pull_request]
jobs:
mypy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python_version: '3.13'
- run: pip install mypy
- run: mypy --strict src/
Это — carrying Phase 69 forward-link: type hints (M07) → strict mypy (M07 урок 07) → CI integration (Phase 69).
What’s next — Phase 67 продолжается M08
M07 завершает type-system overlay. Phase 67 продолжается M08 (Testing с pytest) — Plan 67-03:
- pytest taught conceptually (in-browser challenges использует platform test harness — pytest forbidden в Pyodide per SC#4).
- Run-on-Your-Machine convention (pre-promised M00 урок 03) — этот урок 07 fulfilled first instance; M08 add ≥3 more callouts (pip install pytest + pytest -v + pytest —cov + conftest.py).
- Type hints + pytest — typed fixtures, parametrize с типами,
def test_foo(client: APIClient) -> None:pattern.
M07 self-assessment checklist
Перед переходом к M08 — убедитесь, что можете ответить без подсказки:
- ☐ Запишите signature функции принимающей
list of int or Noneи возвращающейdict mapping str to list of float. (Solution:def f(items: list[int] | None) -> dict[str, list[float]]:) - ☐ Объясните, почему
class Stack[T]:(PEP 695) эквивалентclass Stack(Generic[T])сT = TypeVar('T'). Что хранится в__type_params__? - ☐ Реализуйте Protocol
Comparableс методом__lt__(self, other: object) -> bool. Покажите, чтоint,str,tupleвсе structurally compatible (никакого inheritance). - ☐ Что вернёт
dataclasses.fields(User)[0].typeдля@dataclass class User: id: int? (Answer:<class 'int'>— real type object). А послеfrom __future__ import annotations? (Answer:'int'— string. Pitfall 11.) - ☐ Реализуйте
TypeGuard[list[str]]predicate, который returns True iff list содержит только str. Объясните, почему без TypeGuard mypy не может narrow. - ☐ Запишите
class ValidationError(Exception)hierarchy с двумя sub-typesInvalidFormatError+OutOfRangeError. Show full try/except/else/finally pattern вvalidate_ageфункции. - ☐ Назовите
mypy --strictкоманду + 5 flags, что она включает. Что такоеmypy.inistrict = True?
Если уверенно отвечаете на все 7 — M07 пройдён. Сомневаетесь — re-read соответствующий урок.
Cross-course context
Cross-course → Spark: 03/06 spark-sql-catalog — mypy strict-mode валидация type hints до runtime — параллель Spark SQL Catalog:
df.printSchema()показывает schema до execution; analyzer проверяет column types в plan resolution стадии и raises AnalysisException если type mismatch. Оба механизма — pre-execution static checking, отделяющие type-correctness от runtime errors. mypy работает на Python source level; Spark Catalog — на DataFrame plan level; принцип общий.
Ключевые выводы
- M07 — type-system overlay поверх runtime stack (closure, generator, dataclass, context-manager). Existing primitives получают typed view.
- PEP 585/604/695 + Protocol/TypedDict + runtime introspection + TypeGuard + typed exceptions = full vocabulary M07.
- Type checker (mypy / pyright / ty) — отдельный tool. Pyodide не type-check’ит — Run-on-Your-Machine для real validation.
- mypy — reference implementation.
pip install mypy+mypy --strict file.py— basic workflow.mypy.iniдля project-wide config. strict = True— production baseline strictness. Включаетdisallow-untyped-defs,warn-return-any,no-implicit-optional, etc.- pyright (Microsoft) — faster alternative, used VSCode. ty (Astral.sh, акредитована OpenAI в марте 2026, OSS commitment сохраняется) — Rust-based, ultra-fast, emerging. Mature treatment alternatives — v2 курса.
- Forward-link Phase 69 — mypy в pre-commit hook + GitHub Actions workflow. Production hygiene: type hints meaningful только если CI enforces.
- M07 self-assessment — 7-item checklist для verification understanding перед M08.
Поздравляем — вы прошли type-system overlay. Дальше — M08 Testing с pytest.