02.01 — Ocarina’s technical identity#
pyproject.toml#
[project]
name = "ocarina"
version = "1.1.10"
description = "Websites test framework for Igor"
requires-python = ">=3.14"
authors = [{ name="Igor Casanova", email="[REDACTED]" }]
license = "MIT"
license-files = ["LICEN[CS]E*"]
readme = "README.md"
dependencies = ["python-docx>=1.2.0"]
version = "1.1.10": stable 1.x, not a pre-release.requires-python = ">=3.14": PEP 695 generic typing everywhere.dependencies = ["python-docx>=1.2.0"]: one runtime dependency. The rest lives in dev.license = "MIT".description = "Websites test framework for Igor": not “for everyone,” not “for humans,” explicitly “for Igor.” Lines up with ../01-philosophy/05-political-stance.md: “It’s my car.”
dev dependencies#
[dependency-groups]
dev = [
"ruff>=0.15.0",
"mypy>=1.17.0",
"mypy-extensions>=1.1.0",
"typing-extensions>=4.14.0",
"pytest>=9.0.0",
"pytest-cov>=7.0.0",
"hypothesis>=6.151.0",
"pytest-mypy-plugins>=3.1.0",
"allure-pytest>=2.15.3",
"allure-python-commons>=2.15.3",
"pre-commit>=4.5.1",
"syrupy>=5.1.0",
"selenium>=4.40.0",
"playwright>=1.60.0",
"twine>=6.2.0",
"build>=1.4.2",
"prysk>=0.20.0",
]
| Tool | Role in Ocarina |
|---|
ruff | Linter + formatter (replaces flake8 + isort + black). select = ["ALL"]. |
mypy (+ extensions) | Type-checker. strict = true (see mypy.ini). |
pytest | Unit-test runner (the framework is itself tested). |
pytest-cov | Test coverage (of the framework itself). Configured in pyproject.toml#tool.coverage. |
hypothesis | Property-based testing (PBT) → test_invariants_properties.py. |
pytest-mypy-plugins | Static typing tests (checks expected mypy errors and type-inference tests with reveal_type). |
allure-pytest / allure-python-commons | Allure report (deployed to GH Pages). |
pre-commit | Local git hooks (ruff-format). |
syrupy | Snapshot testing (output of pretty_print_results, results_to_json). |
selenium | Present in dev because Ocarina doesn’t depend on Selenium to work; it just ships a Selenium adapter so the framework is immediately operational out of box. |
playwright | Same logic: a second shipped adapter (since 1.1.3). Ocarina now drives both Selenium and Playwright out of the box, behind the same ports. |
twine / build | PyPI publishing. |
prysk | CLI tests in the cram (.t) format. Successor to cram. |
mypy.ini#
[mypy]
python_version = 3.14
strict = true
# * ... Allow missing annotations (type inference is cool)
disallow_incomplete_defs = false
# * ... Allow missing annotations (type inference is cool)
disallow_untyped_defs = false
strict = true: enables --warn-redundant-casts, --warn-unused-ignores, --no-implicit-optional, --check-untyped-defs, etc.- Two exceptions:
disallow_incomplete_defs and disallow_untyped_defs are off. mypy’s type inference is good enough when explicit annotations don’t add value. Annotations live where they actually matter.
[tool.ruff.lint]
select = ["ALL"]
ignore = [
"ANN002", "ANN003", "ANN201",
"TRY003",
"C901",
"D203", # conflict with D211
"D213", # conflict with D212
"COM812", # conflict with the ruff formatter (auto-fix)
]
[tool.ruff]
exclude = ["**/.venv/**", "**/bin/**", "**/__init__.py", "**/__bypass_linter__"]
select = ["ALL"]: every ruff rule on (~800).- Short ignore list: six rules, each one justified.
B008 must NEVER be ignored ("# "B008", # * ... NEVER ignore this rule without knowing very well what you are doing: https://docs.astral.sh/ruff/rules/function-call-in-default-argument/"). Note left so the past mistake doesn’t repeat.- **
**/**bypass_linter****: directory convention for explicitly un-linted code (handy for internal experimental modules).
testpaths = ["tests"]
python_files = ["test_*.py"]
norecursedirs = [".*", "__pycache__"]
log_cli = true
log_cli_level = "DEBUG"
log_cli_format = "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
log_cli_date_format = "%Y-%m-%d %H:%M:%S"
addopts = """
--cov=src
--cov-branch
--cov-report=term-missing
--cov-report=html
--cov-report=xml:coverage.xml
"""
| Setting | Effect |
|---|
log_cli = true | All test logs surface in the CLI (useful for scenarios that go through ILogger). |
--cov=src + --cov-branch | Branch coverage, not just line coverage. |
--cov-report=html + xml | Three outputs: terminal, local HTML, XML for CI ingestion. |
Full detail at ../04-internal-tests/07-coverage-policy.md. Short version: anything that’s pure shape (custom_types, ports, errors), anything that needs a real browser (Selenium adapters), and anything covered by cram tests (cli/store, cli/builder) is explicitly omitted. Otherwise the metrics lie.