---
created:
  source_filename: /home/runner/work/mknodes/mknodes/.venv/lib/python3.14t/site-packages/anyenv/async_run.py
  source_function: run_sync.<locals>.wrapper
  source_line_no: 52
icon: material/wrench
title: Dev Tools
---

## Pre-Commit

This project uses **pre-commit** to ensure code quality.
A `.pre-commit-config.yaml` configuration file tailored for this project is provided
in the root folder.

``` {.md }
# Setup pre-commit hooks for required formatting
pre-commit install
```

??? quote "Config"
    ``` {.yaml }
    default_language_version:
        python: python3.13
    default_stages: [pre-commit]
    repos:
        - repo: local
          hooks:
              - id: pytest-check
                name: pytest-check
                entry: uv run pytest
                language: system
                # stages: [push]
                types: [python]
                pass_filenames: false
                always_run: true
        - repo: https://github.com/pre-commit/pre-commit-hooks
          rev: v6.0.0
          hooks:
              # - id: trailing-whitespace
              # - id: check-ast
              - id: check-case-conflict
              - id: check-docstring-first
              - id: check-merge-conflict
              # - id: check-yaml
              - id: check-toml
              - id: check-json
              - id: detect-private-key
              - id: forbid-new-submodules
              # - id: check-added-large-files
        # https://pre-commit.com/hooks.html
        - repo: https://github.com/pre-commit/mirrors-mypy
          rev: v1.17.1
          hooks:
              - id: mypy
                # args: [--ignore-missing-imports]
                additional_dependencies: ["orjson"]

        - repo: https://github.com/charliermarsh/ruff-pre-commit
          rev: v0.13.0
          hooks:
              - id: ruff
              - id: ruff-format

        - repo: https://github.com/commitizen-tools/commitizen
          rev: v4.9.0
          hooks:
              - id: commitizen
                stages: [commit-msg]
                additional_dependencies: [typing-extensions]

    ```


??? info "Installing Pre-Commit"
    To install pre-commit:
    ``` {.bash }
    pip install pre-commit
    ```
    [More information](https://pre-commit.com)


## Coverage

**Coverage** is used to monitor test coverage.

``` {.md }
coverage run some_module.py
```

??? quote "Config"
    ``` {.toml }
    [report]
    exclude_lines = [
        "pragma: no cover",
        "if TYPE_CHECKING:",
        "@overload",
        "except ImportError",
        "if __name__ == \"__main__\":",
    ]

    ```


??? info "Installing Coverage"
    To install coverage:
    ``` {.bash }
    pip install coverage
    ```
    [More information](https://coverage.readthedocs.io/)


## MkDocs

**Ruff** is used as a linter. You can find the configuration in the
`pyproject.toml` file.


``` {.md }
ruff --help
```

??? quote "Config"
    ``` {.toml }
    line-length = 100
    extend-exclude = [
        "docs",
    ]
    target-version = "py313"

    [lint]
    future-annotations = true
    select = [
        "A",
        "B",
        "BLE",
        "C",
        "C4",
        "COM",
        "D",
        "E",
        "EM",
        "EXE",
        "F",
        "FA",
        "FLY",
        "G",
        "I",
        "ICN",
        "INP",
        "INT",
        "ISC",
        "N",
        "PERF",
        "PIE",
        "PLE",
        "PLC",
        "PLR",
        "PT",
        "PTH",
        "PYI",
        "Q",
        "RET",
        "RSE",
        "RUF",
        "SIM",
        "SLF",
        "SLOT",
        "T10",
        "TC",
        "TID",
        "TRY",
        "UP",
        "W",
        "YTT",
    ]
    ignore = [
        "C408",
        "B905",
        "C901",
        "D100",
        "D101",
        "D102",
        "D103",
        "D104",
        "D105",
        "D106",
        "D107",
        "D203",
        "D204",
        "D213",
        "D215",
        "D400",
        "D401",
        "D404",
        "D406",
        "D407",
        "D408",
        "D409",
        "D413",
        "N813",
        "PLC0415",
        "PLC2701",
        "PLR0904",
        "PLR0912",
        "PLR0913",
        "PLR0915",
        "PLR0917",
        "PLR6301",
        "SLF001",
        "RUF012",
        "TRY003",
        "COM812",
        "COM819",
        "D206",
        "E501",
        "ISC001",
        "Q000",
        "Q001",
        "Q002",
        "Q003",
        "W191",
    ]

    [lint.flake8-quotes]
    docstring-quotes = "double"

    [lint.flake8-type-checking]
    runtime-evaluated-base-classes = [
        "pydantic.BaseModel",
        "sqlalchemy.orm.DeclarativeBase",
        "schemez.Schema",
        "sqlmodel.SQLModel",
    ]
    runtime-evaluated-decorators = [
        "pydantic.validate_call",
        "fastapi.FastAPI.get",
        "fastapi.FastAPI.post",
        "fastmcp.FastMCP.tool",
        "typer.Typer.command",
    ]

    [lint.isort]
    lines-after-imports = 2
    force-sort-within-sections = true
    combine-as-imports = true

    [lint.per-file-ignores]
    "__init__.py" = [
        "E402",
        "I001",
    ]
    "scripts/*" = [
        "INP001",
    ]
    "*tests/*" = [
        "D100",
    ]

    [format]
    preview = true
    docstring-code-format = true

    ```


??? info "Installing MkDocs"
    To install mkdocs:
    ``` {.bash }
    pip install mkdocs
    ```
    [More information](https://mkdocs.org/)


## Ruff

**Ruff** is used as a linter. You can find the configuration in the
`pyproject.toml` file.


``` {.md }
ruff --help
```

??? quote "Config"
    ``` {.toml }
    line-length = 100
    extend-exclude = [
        "docs",
    ]
    target-version = "py313"

    [lint]
    future-annotations = true
    select = [
        "A",
        "B",
        "BLE",
        "C",
        "C4",
        "COM",
        "D",
        "E",
        "EM",
        "EXE",
        "F",
        "FA",
        "FLY",
        "G",
        "I",
        "ICN",
        "INP",
        "INT",
        "ISC",
        "N",
        "PERF",
        "PIE",
        "PLE",
        "PLC",
        "PLR",
        "PT",
        "PTH",
        "PYI",
        "Q",
        "RET",
        "RSE",
        "RUF",
        "SIM",
        "SLF",
        "SLOT",
        "T10",
        "TC",
        "TID",
        "TRY",
        "UP",
        "W",
        "YTT",
    ]
    ignore = [
        "C408",
        "B905",
        "C901",
        "D100",
        "D101",
        "D102",
        "D103",
        "D104",
        "D105",
        "D106",
        "D107",
        "D203",
        "D204",
        "D213",
        "D215",
        "D400",
        "D401",
        "D404",
        "D406",
        "D407",
        "D408",
        "D409",
        "D413",
        "N813",
        "PLC0415",
        "PLC2701",
        "PLR0904",
        "PLR0912",
        "PLR0913",
        "PLR0915",
        "PLR0917",
        "PLR6301",
        "SLF001",
        "RUF012",
        "TRY003",
        "COM812",
        "COM819",
        "D206",
        "E501",
        "ISC001",
        "Q000",
        "Q001",
        "Q002",
        "Q003",
        "W191",
    ]

    [lint.flake8-quotes]
    docstring-quotes = "double"

    [lint.flake8-type-checking]
    runtime-evaluated-base-classes = [
        "pydantic.BaseModel",
        "sqlalchemy.orm.DeclarativeBase",
        "schemez.Schema",
        "sqlmodel.SQLModel",
    ]
    runtime-evaluated-decorators = [
        "pydantic.validate_call",
        "fastapi.FastAPI.get",
        "fastapi.FastAPI.post",
        "fastmcp.FastMCP.tool",
        "typer.Typer.command",
    ]

    [lint.isort]
    lines-after-imports = 2
    force-sort-within-sections = true
    combine-as-imports = true

    [lint.per-file-ignores]
    "__init__.py" = [
        "E402",
        "I001",
    ]
    "scripts/*" = [
        "INP001",
    ]
    "*tests/*" = [
        "D100",
    ]

    [format]
    preview = true
    docstring-code-format = true

    ```


??? info "Installing Ruff"
    To install ruff:
    ``` {.bash }
    pip install ruff
    ```
    [More information](https://beta.ruff.rs/)


## MyPy

**MyPy** is used for type checking. You can find the configuration in the
`pyproject.toml` file.


``` {.md }
mypy --help
```

??? quote "Config"
    ``` {.toml }
    python_version = "3.13"
    pretty = true
    check_untyped_defs = true
    exclude = [
        "venv/",
        ".venv/",
        "tests/",
    ]
    plugins = []

    ```


??? info "Installing MyPy"
    To install mypy:
    ``` {.bash }
    pip install mypy
    ```
    [More information](https://mypy-lang.org)


## PyRight

**PyRight** is used for type checking. You can find the configuration in the
`pyproject.toml` file.


``` {.md }
pyright --help
```

??? quote "Config"
    ``` {.toml }
    venvPath = "."
    venv = ".venv"
    pythonVersion = "3.13"
    pythonPlatform = "All"
    typeCheckingMode = "basic"
    deprecateTypingAliases = true
    reportMissingTypeStubs = false
    reportUnusedCallResult = false
    reportUnknownVariableType = false
    reportAny = false
    reportImplicitOverride = false
    reportUnusedFunction = false
    reportImplicitStringConcatenation = false
    reportIgnoreCommentWithoutRule = false
    reportUnannotatedClassAttribute = false
    reportSelfClsParameterName = false
    reportPrivateImportUsage = false

    ```


??? info "Installing PyRight"
    To install pyright:
    ``` {.bash }
    pip install pyright
    ```
    [More information](https://microsoft.github.io/pyright/)
