Enforce strict Pyright gate
This commit is contained in:
parent
90898cfd63
commit
2841042b9c
16 changed files with 214 additions and 77 deletions
|
|
@ -6,7 +6,7 @@ import hashlib
|
|||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Any, cast
|
||||
|
||||
from .errors import DocForgeError
|
||||
from .models import Node, ProjectService
|
||||
|
|
@ -80,14 +80,16 @@ def edge_dict(edge: tuple[str, str, str], *, action: str) -> dict[str, str]:
|
|||
}
|
||||
|
||||
|
||||
def validate_id(value: Any, field: str) -> None:
|
||||
def validate_id(value: object, field: str) -> str:
|
||||
if not isinstance(value, str) or ID_PATTERN.fullmatch(value) is None:
|
||||
raise DocForgeError("invalid_id", f"{field} must be a stable ID", field=field)
|
||||
return value
|
||||
|
||||
|
||||
def validate_hash(value: Any, field: str) -> None:
|
||||
def validate_hash(value: object, field: str) -> str:
|
||||
if not isinstance(value, str) or HASH_PATTERN.fullmatch(value) is None:
|
||||
raise DocForgeError("invalid_hash", f"{field} must be a lowercase SHA-256 hash")
|
||||
return value
|
||||
|
||||
|
||||
def normalize_operation(operation: dict[str, Any], *, sequence: int) -> dict[str, Any]:
|
||||
|
|
@ -109,21 +111,28 @@ def normalize_operation(operation: dict[str, Any], *, sequence: int) -> dict[str
|
|||
if not isinstance(relationships, list):
|
||||
raise DocForgeError("invalid_operation", "relationship_changes must be an array")
|
||||
normalized_relationships: list[dict[str, str]] = []
|
||||
for change in relationships:
|
||||
if not isinstance(change, dict) or set(change) != RELATIONSHIP_KEYS:
|
||||
for change_value in cast(list[object], relationships):
|
||||
if not isinstance(change_value, dict):
|
||||
raise DocForgeError(
|
||||
"invalid_operation", "Relationship changes require exact structured fields"
|
||||
)
|
||||
if change["action"] not in {"add", "remove"}:
|
||||
change = cast(dict[str, object], change_value)
|
||||
if set(change) != set(RELATIONSHIP_KEYS):
|
||||
raise DocForgeError(
|
||||
"invalid_operation", "Relationship changes require exact structured fields"
|
||||
)
|
||||
action = change["action"]
|
||||
if not isinstance(action, str) or action not in {"add", "remove"}:
|
||||
raise DocForgeError("invalid_operation", "Relationship action is invalid")
|
||||
for field in ("source_id", "relation", "target_id"):
|
||||
validate_id(change[field], field)
|
||||
source_id = validate_id(change["source_id"], "source_id")
|
||||
relation = validate_id(change["relation"], "relation")
|
||||
target_id = validate_id(change["target_id"], "target_id")
|
||||
normalized_relationships.append(
|
||||
{
|
||||
"action": change["action"],
|
||||
"source_id": change["source_id"],
|
||||
"relation": change["relation"],
|
||||
"target_id": change["target_id"],
|
||||
"action": action,
|
||||
"source_id": source_id,
|
||||
"relation": relation,
|
||||
"target_id": target_id,
|
||||
}
|
||||
)
|
||||
keys = [
|
||||
|
|
@ -136,6 +145,7 @@ def normalize_operation(operation: dict[str, Any], *, sequence: int) -> dict[str
|
|||
if metadata is not None and not isinstance(metadata, dict):
|
||||
raise DocForgeError("invalid_operation", "metadata must be an object or null")
|
||||
if isinstance(metadata, dict):
|
||||
metadata = cast(dict[str, object], metadata)
|
||||
unknown_metadata = sorted(set(metadata) - METADATA_KEYS)
|
||||
if unknown_metadata:
|
||||
raise DocForgeError(
|
||||
|
|
@ -172,7 +182,12 @@ def normalize_operation(operation: dict[str, Any], *, sequence: int) -> dict[str
|
|||
|
||||
|
||||
def validate_document(project: ProjectService, document: Any, *, path: Path) -> dict[str, Any]:
|
||||
if not isinstance(document, dict) or set(document) != CHANGESET_KEYS:
|
||||
if not isinstance(document, dict):
|
||||
raise DocForgeError(
|
||||
"invalid_changeset", "Changeset has missing or unknown fields", path=path.name
|
||||
)
|
||||
document = cast(dict[str, Any], document)
|
||||
if set(document) != set(CHANGESET_KEYS):
|
||||
raise DocForgeError(
|
||||
"invalid_changeset", "Changeset has missing or unknown fields", path=path.name
|
||||
)
|
||||
|
|
@ -207,11 +222,17 @@ def validate_document(project: ProjectService, document: Any, *, path: Path) ->
|
|||
operations = document["operations"]
|
||||
if not isinstance(operations, list):
|
||||
raise DocForgeError("invalid_changeset", "operations must be an array")
|
||||
if len(operations) > descriptor.limits.max_changeset_operations:
|
||||
typed_operations = cast(list[object], operations)
|
||||
if len(typed_operations) > descriptor.limits.max_changeset_operations:
|
||||
raise DocForgeError("changeset_operation_limit", "Changeset has too many operations")
|
||||
normalized: list[dict[str, Any]] = []
|
||||
for index, operation in enumerate(operations, start=1):
|
||||
if not isinstance(operation, dict) or set(operation) != OPERATION_KEYS:
|
||||
for index, operation_value in enumerate(typed_operations, start=1):
|
||||
if not isinstance(operation_value, dict):
|
||||
raise DocForgeError(
|
||||
"invalid_changeset", "Stored operation has missing or unknown fields"
|
||||
)
|
||||
operation = cast(dict[str, Any], operation_value)
|
||||
if set(operation) != set(OPERATION_KEYS):
|
||||
raise DocForgeError(
|
||||
"invalid_changeset", "Stored operation has missing or unknown fields"
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue