"""Typed public Python API models for high-level inspection workflows."""
from __future__ import annotations
from dataclasses import asdict, dataclass
from dataclasses import field as dataclass_field
from typing import Any
[docs]
@dataclass
class DictModel:
"""Mixin that exposes a stable ``to_dict()`` helper."""
[docs]
def to_dict(self) -> dict[str, Any]:
"""Return the dataclass as a plain dictionary."""
return asdict(self)
[docs]
@dataclass
class EnvironmentSource(DictModel):
"""Source metadata for an inspected environment."""
name: str | None = None
source: str | None = None
config_path: str | None = None
[docs]
@dataclass
class BinaryProbe(DictModel):
"""Resolved binary metadata for an environment."""
value: str | None = None
resolved_path: str | None = None
exists: bool = False
executable: bool = False
configured: bool = False
auto_detected: bool = False
[docs]
@dataclass
class AddonsPathStatus(DictModel):
"""Resolved addon path information."""
configured: list[str] = dataclass_field(default_factory=list)
base: list[str] = dataclass_field(default_factory=list)
all: list[str] = dataclass_field(default_factory=list)
valid: list[str] = dataclass_field(default_factory=list)
invalid: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class OdooVersionInfo(DictModel):
"""Resolved Odoo version and series information."""
version: str | None = None
series: str | None = None
[docs]
@dataclass
class DatabaseSummary(DictModel):
"""Safe database configuration summary."""
db_name: str | None = None
db_host: str | None = None
db_user: str | None = None
[docs]
@dataclass
class EnvironmentContext(DictModel):
"""Typed environment snapshot for planning and inspection."""
environment: EnvironmentSource
resolved_binaries: dict[str, BinaryProbe]
addons_paths: AddonsPathStatus
odoo: OdooVersionInfo
database: DatabaseSummary
duplicate_modules: dict[str, list[str]] = dataclass_field(default_factory=dict)
available_module_count: int = 0
invalid_addon_paths: list[str] = dataclass_field(default_factory=list)
missing_critical_config: list[str] = dataclass_field(default_factory=list)
doctor_summary: dict[str, int] = dataclass_field(default_factory=dict)
doctor_checks: list[dict[str, Any]] = dataclass_field(default_factory=list)
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class AddonInspection(DictModel):
"""Typed addon inspection payload."""
module: str
exists: bool
module_path: str | None
addon_type: str
version_display: str
manifest: dict[str, Any]
manifest_fields: list[str]
direct_dependencies: list[str] = dataclass_field(default_factory=list)
reverse_dependencies: list[str] = dataclass_field(default_factory=list)
reverse_dependency_count: int = 0
install_order_slice: list[str] = dataclass_field(default_factory=list)
install_order_available: bool = False
dependency_cycle: list[str] = dataclass_field(default_factory=list)
missing_dependencies: list[str] = dataclass_field(default_factory=list)
impacted_modules: list[str] = dataclass_field(default_factory=list)
series: str | None = None
python_dependencies: list[str] = dataclass_field(default_factory=list)
binary_dependencies: list[str] = dataclass_field(default_factory=list)
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class AddonInstallState(DictModel):
"""Typed runtime install-state lookup result for one addon."""
success: bool
operation: str
module: str
record_found: bool = False
state: str = "uninstalled"
installed: bool = False
database: str | None = None
error: str | None = None
error_type: str | None = None
[docs]
@dataclass
class InstalledAddonRecord(DictModel):
"""One runtime addon record read from ``ir.module.module``."""
module: str
state: str
installed: bool
shortdesc: str | None = None
application: bool | None = None
auto_install: bool | None = None
[docs]
@dataclass
class InstalledAddonInventory(DictModel):
"""Typed runtime addon inventory for one environment."""
success: bool
operation: str
addons: list[InstalledAddonRecord] = dataclass_field(default_factory=list)
total: int = 0
states: list[str] = dataclass_field(default_factory=list)
modules_filter: list[str] = dataclass_field(default_factory=list)
database: str | None = None
error: str | None = None
error_type: str | None = None
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class UpdatePlan(DictModel):
"""Typed read-only update planning payload."""
module: str
exists: bool
impact_set: list[str] = dataclass_field(default_factory=list)
impact_count: int = 0
missing_dependencies: list[str] = dataclass_field(default_factory=list)
duplicate_name_risk: bool = False
duplicate_module_locations: list[str] = dataclass_field(default_factory=list)
dependency_cycle: list[str] = dataclass_field(default_factory=list)
cycle_risk: bool = False
ordering_constraints: list[str] = dataclass_field(default_factory=list)
recommended_sequence: list[str] = dataclass_field(default_factory=list)
backup_advised: bool = False
write_protect_db: bool = False
agent_write_protect_db: bool = False
needs_mutation_flag: bool = False
agent_needs_mutation_flag: bool = False
human_runtime_db_mutation_policy: str = "allow"
human_runtime_db_mutation_allowed: bool = True
human_runtime_db_mutation_requires_flag: bool = False
agent_runtime_db_mutation_policy: str = "allow"
agent_runtime_db_mutation_allowed: bool = True
agent_runtime_db_mutation_requires_flag: bool = False
risk_score: int = 0
risk_level: str = "low"
risk_factors: list[str] = dataclass_field(default_factory=list)
verification_steps: list[str] = dataclass_field(default_factory=list)
inspection: AddonInspection | None = None
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class QueryModelResult(DictModel):
"""Typed wrapper for ``OdooQuery.query_model()`` results."""
success: bool
operation: str
model: str
domain: list[Any] = dataclass_field(default_factory=list)
fields: list[str] | None = None
limit: int = 0
count: int = 0
total_count: int | None = None
limited: bool = False
ids: list[int] = dataclass_field(default_factory=list)
records: list[dict[str, Any]] = dataclass_field(default_factory=list)
database: str | None = None
error: str | None = None
error_type: str | None = None
[docs]
@classmethod
def from_dict(cls, result: dict[str, Any]) -> QueryModelResult:
"""Create a typed result from a raw ``OdooQuery`` dictionary."""
return cls(
success=bool(result.get("success", False)),
operation=str(result.get("operation", "query_model")),
model=str(result.get("model", "")),
domain=list(result.get("domain", [])),
fields=result.get("fields"),
limit=int(result.get("limit", 0) or 0),
count=int(result.get("count", 0) or 0),
total_count=(
int(result.get("total_count", 0))
if result.get("total_count") is not None
else None
),
limited=bool(result.get("limited", False)),
ids=list(result.get("ids", [])),
records=list(result.get("records", [])),
database=result.get("database"),
error=result.get("error"),
error_type=result.get("error_type"),
)
[docs]
@dataclass
class RecordReadResult(DictModel):
"""Typed wrapper for ``OdooQuery.read_record()`` results."""
success: bool
operation: str
model: str
record_id: int
found: bool
record: dict[str, Any] | None
fields: list[str] | None = None
database: str | None = None
error: str | None = None
error_type: str | None = None
[docs]
@classmethod
def from_dict(cls, result: dict[str, Any]) -> RecordReadResult:
"""Create a typed result from a raw ``OdooQuery`` dictionary."""
return cls(
success=bool(result.get("success", False)),
operation=str(result.get("operation", "read_record")),
model=str(result.get("model", "")),
record_id=int(result.get("record_id", 0) or 0),
found=bool(result.get("found", False)),
record=result.get("record"),
fields=result.get("fields"),
database=result.get("database"),
error=result.get("error"),
error_type=result.get("error_type"),
)
[docs]
@dataclass
class SearchCountResult(DictModel):
"""Typed wrapper for ``OdooQuery.search_count()`` results."""
success: bool
operation: str
model: str
domain: list[Any] = dataclass_field(default_factory=list)
count: int = 0
database: str | None = None
error: str | None = None
error_type: str | None = None
[docs]
@classmethod
def from_dict(cls, result: dict[str, Any]) -> SearchCountResult:
"""Create a typed result from a raw ``OdooQuery`` dictionary."""
return cls(
success=bool(result.get("success", False)),
operation=str(result.get("operation", "search_count")),
model=str(result.get("model", "")),
domain=list(result.get("domain", [])),
count=int(result.get("count", 0) or 0),
database=result.get("database"),
error=result.get("error"),
error_type=result.get("error_type"),
)
[docs]
@dataclass
class ModelFieldsResult(DictModel):
"""Typed wrapper for ``OdooQuery.get_model_fields()`` results."""
success: bool
operation: str
model: str
attributes: list[str] | None = None
module: str | None = None
field_names: list[str] = dataclass_field(default_factory=list)
field_definitions: dict[str, dict[str, Any]] = dataclass_field(default_factory=dict)
database: str | None = None
error: str | None = None
error_type: str | None = None
[docs]
@classmethod
def from_dict(cls, result: dict[str, Any]) -> ModelFieldsResult:
"""Create a typed result from a raw ``OdooQuery`` dictionary."""
return cls(
success=bool(result.get("success", False)),
operation=str(result.get("operation", "get_model_fields")),
model=str(result.get("model", "")),
attributes=result.get("attributes"),
module=result.get("module"),
field_names=list(result.get("field_names", [])),
field_definitions=dict(result.get("field_definitions", {})),
database=result.get("database"),
error=result.get("error"),
error_type=result.get("error_type"),
)
[docs]
@dataclass
class ModelViewRecord(DictModel):
"""One database-backed view record for a model."""
id: int
name: str
view_type: str
mode: str | None = None
priority: int | None = None
inherit_id: list[Any] | None = None
key: str | None = None
active: bool | None = None
arch_db: str | None = None
[docs]
@dataclass
class ModelViewInventory(DictModel):
"""Database-backed view inventory for a model."""
model: str
requested_types: list[str] = dataclass_field(default_factory=list)
primary_views: list[ModelViewRecord] = dataclass_field(default_factory=list)
extension_views: list[ModelViewRecord] = dataclass_field(default_factory=list)
view_counts: dict[str, int] = dataclass_field(default_factory=dict)
database: str | None = None
error: str | None = None
error_type: str | None = None
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class DocumentationRuntimeInventory(DictModel):
"""Batched runtime metadata for many models in documentation flows."""
models: dict[str, ModelFieldsResult] = dataclass_field(default_factory=dict)
views: dict[str, ModelViewInventory] = dataclass_field(default_factory=dict)
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class SourceEvidence(DictModel):
"""Machine-readable evidence attached to source-location candidates."""
kind: str
message: str
path: str
line_hint: int | None = None
[docs]
@dataclass
class ModelSourceCandidate(DictModel):
"""Ranked model source candidate for static source localization."""
path: str
class_name: str
match_kind: str
declared_model: str
confidence: float
match_strength: str = "confirmed"
evidence: list[SourceEvidence] = dataclass_field(default_factory=list)
line_hint: int | None = None
reason: str | None = None
[docs]
@dataclass
class ModelSourceLocation(DictModel):
"""Static source localization result for one addon/model pair."""
model: str
module: str
addon_root: str
resolution: str = "not_found"
ambiguous: bool = False
ambiguity_reason: str | None = None
candidates: list[ModelSourceCandidate] = dataclass_field(default_factory=list)
scanned_python_files: list[str] = dataclass_field(default_factory=list)
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class FieldSourceCandidate(DictModel):
"""Ranked field source candidate for static source localization."""
path: str
class_name: str
field_name: str
match_kind: str
declared_model: str
confidence: float
match_strength: str = "confirmed"
evidence: list[SourceEvidence] = dataclass_field(default_factory=list)
line_hint: int | None = None
reason: str | None = None
[docs]
@dataclass
class FieldSourceLocation(DictModel):
"""Static source localization result for one addon/model/field target."""
model: str
field: str
module: str
addon_root: str
exists: bool
resolution: str = "not_found"
ambiguous: bool = False
ambiguity_reason: str | None = None
source_exists: bool = False
runtime_exists: bool | None = None
runtime_only: bool = False
runtime_source_modules: list[str] = dataclass_field(default_factory=list)
candidates: list[FieldSourceCandidate] = dataclass_field(default_factory=list)
insertion_candidate: ModelSourceCandidate | None = None
insertion_line_range: list[int] | None = None
insertion_reason: str | None = None
insertion_confidence: float | None = None
related_files: list[str] = dataclass_field(default_factory=list)
scanned_python_files: list[str] = dataclass_field(default_factory=list)
rationale: str | None = None
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class AddonTestFile(DictModel):
"""Ranked addon test file entry."""
path: str
test_type: str
references_model: bool = False
references_field: bool = False
confidence: float = 0.0
ranking_signals: list[str] = dataclass_field(default_factory=list)
related_paths: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class AddonTestInventory(DictModel):
"""Static addon test inventory for coding-agent test selection."""
module: str
addon_root: str
model: str | None = None
field: str | None = None
tests: list[AddonTestFile] = dataclass_field(default_factory=list)
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class AddonInfo(DictModel):
"""Combined static and runtime addon summary for onboarding workflows."""
module: str
module_path: str | None
addon_type: str
version_display: str
name: str = ""
summary: str = ""
description: str = ""
category: str = ""
author: str = ""
website: str = ""
license: str = ""
external_dependencies: dict[str, list[str]] = dataclass_field(default_factory=dict)
depends: list[str] = dataclass_field(default_factory=list)
reverse_dependencies: list[str] = dataclass_field(default_factory=list)
reverse_dependency_count: int = 0
missing_dependencies: list[str] = dataclass_field(default_factory=list)
installable: bool = False
auto_install: bool = False
models: list[str] = dataclass_field(default_factory=list)
inherit_models: list[str] = dataclass_field(default_factory=list)
model_count: int = 0
test_cases: list[AddonTestFile] = dataclass_field(default_factory=list)
test_count: int = 0
languages: list[str] = dataclass_field(default_factory=list)
installed_state: AddonInstallState | None = None
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class AddonDocTarget(DictModel):
"""Resolved addon target for technical documentation workflows."""
module: str
addon_root: str
target_kind: str
manifest_path: str
inside_configured_addons_path: bool = False
warnings: list[str] = dataclass_field(default_factory=list)
candidate_addon_roots: list[str] = dataclass_field(default_factory=list)
ambiguous: bool = False
[docs]
@dataclass
class AddonTechnicalFile(DictModel):
"""Compact file entry used for technical documentation inventories."""
path: str
category: str
size_bytes: int | None = None
[docs]
@dataclass
class AddonXmlRecord(DictModel):
"""Compact XML inventory record for addon-local architecture evidence."""
path: str
record_id: str | None = None
model: str | None = None
name: str | None = None
xml_tag: str = "record"
attributes: dict[str, str] = dataclass_field(default_factory=dict)
[docs]
@dataclass
class AddonHttpRoute(DictModel):
"""Static controller route discovered from addon Python sources."""
path: str
class_name: str
method_name: str
route: str | list[str]
auth: str | None = None
route_type: str | None = None
methods: list[str] = dataclass_field(default_factory=list)
csrf: bool | None = None
website: bool | None = None
line_hint: int | None = None
[docs]
@dataclass
class AddonTechnicalInventory(DictModel):
"""Read-only technical inventory for addon-local architecture docs."""
module: str
addon_root: str
files: list[AddonTechnicalFile] = dataclass_field(default_factory=list)
xml_records: list[AddonXmlRecord] = dataclass_field(default_factory=list)
http_routes: list[AddonHttpRoute] = dataclass_field(default_factory=list)
security_files: list[str] = dataclass_field(default_factory=list)
migration_files: list[str] = dataclass_field(default_factory=list)
todo_markers: list[SourceEvidence] = dataclass_field(default_factory=list)
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class DocumentationTrackedFile(DictModel):
"""Tracked addon source file entry used for documentation freshness checks."""
path: str
category: str
size_bytes: int | None = None
sha256: str | None = None
[docs]
@dataclass
class DocumentationSourceSnapshot(DictModel):
"""Deterministic fingerprint of addon source inputs."""
algorithm: str = "sha256"
fingerprint: str = ""
file_count: int = 0
files: list[DocumentationTrackedFile] = dataclass_field(default_factory=list)
[docs]
@dataclass
class DocumentationDocumentSnapshot(DictModel):
"""Fingerprint of the generated Markdown document."""
algorithm: str = "sha256"
fingerprint: str = ""
size_bytes: int | None = None
line_count: int | None = None
[docs]
@dataclass
class TechnicalDocumentationGeneratedBlock(DictModel):
"""Persisted metadata for one managed generated markdown block."""
id: str
renderer: str
schema_version: str = "oduit.generated_markdown_block.v1"
source_sha256: str = ""
content_sha256: str = ""
line_count: int | None = None
updated_at: str | None = None
[docs]
@dataclass
class TechnicalEvidenceSnapshot(DictModel):
block_id: str
renderer: str
evidence_path: str
evidence_version: int
source_sha256: str
content_sha256: str
snapshot_sha256: str
start_line: int | None = None
end_line: int | None = None
body: str = ""
[docs]
@dataclass
class TechnicalEvidenceDiffEntry(DictModel):
block_id: str
renderer: str = ""
status: str = "unknown"
old_evidence_version: int | None = None
current_evidence_version: int | None = None
old_source_sha256: str | None = None
current_source_sha256: str | None = None
old_content_sha256: str | None = None
current_content_sha256: str | None = None
snapshot_sha256: str | None = None
current_snapshot_sha256: str | None = None
significant: bool = False
diff: str | None = None
message: str | None = None
[docs]
@dataclass
class TechnicalEvidenceDiffResult(DictModel):
module: str
addon_root: str
report_path: str
evidence_path: str
evidence_metadata_path: str
status: str
current_evidence_version: int | None = None
snapshot_count: int = 0
stale_count: int = 0
edited_snapshot_count: int = 0
missing_current_block_count: int = 0
entries: list[TechnicalEvidenceDiffEntry] = dataclass_field(default_factory=list)
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class TechnicalDocumentationStatus(DictModel):
"""Current tracking status for one addon-local technical document."""
module: str
addon_root: str
doc_path: str
metadata_path: str
status: str
has_document: bool = False
has_metadata: bool = False
generated_by_oduit: bool = False
up_to_date: bool = False
document_edited_since_last_generation: bool = False
source_changed_since_last_generation: bool = False
generated_block_count: int = 0
stale_generated_blocks: list[str] = dataclass_field(default_factory=list)
edited_generated_blocks: list[str] = dataclass_field(default_factory=list)
missing_generated_blocks: list[str] = dataclass_field(default_factory=list)
unknown_generated_blocks: list[str] = dataclass_field(default_factory=list)
generated_blocks_up_to_date: bool = False
created_at: str | None = None
last_generated_at: str | None = None
generation_count: int | None = None
generation_options: dict[str, Any] = dataclass_field(default_factory=dict)
evidence_counts: dict[str, int] = dataclass_field(default_factory=dict)
template: str | None = None
changed_files: list[str] = dataclass_field(default_factory=list)
added_files: list[str] = dataclass_field(default_factory=list)
removed_files: list[str] = dataclass_field(default_factory=list)
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class TechnicalDocumentation(DictModel):
"""Typed architecture-documentation bundle for one addon."""
module: str
addon_root: str
source_addon_root: str | None = None
template: str = "arc42"
target: AddonDocTarget | None = None
output_path: str | None = None
metadata_path: str | None = None
generated_at: str | None = None
source_only: bool = False
addon_documentation: AddonDocumentation | None = None
technical_inventory: AddonTechnicalInventory | None = None
sections: list[DocumentSection] = dataclass_field(default_factory=list)
markdown: str = ""
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
used_existing_evidence: bool = False
[docs]
@dataclass
class RecommendedTestPlan(DictModel):
"""Changed-file to test recommendation plan for coding-agent workflows."""
module: str
addon_root: str
paths: list[str] = dataclass_field(default_factory=list)
tests: list[AddonTestFile] = dataclass_field(default_factory=list)
suggested_test_tags: list[str] = dataclass_field(default_factory=list)
full_addon_suite_recommended: bool = False
rationale: list[str] = dataclass_field(default_factory=list)
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class AddonModelEntry(DictModel):
"""One model declaration or extension discovered in addon source."""
model: str
relation_kind: str
class_name: str
path: str
line_hint: int | None = None
added_fields: list[str] = dataclass_field(default_factory=list)
added_methods: list[str] = dataclass_field(default_factory=list)
inherited_models: list[str] = dataclass_field(default_factory=list)
delegated_models: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class AddonModelInventory(DictModel):
"""Static addon model inventory for coding-agent inspection workflows."""
module: str
addon_root: str
models: list[AddonModelEntry] = dataclass_field(default_factory=list)
model_count: int = 0
scanned_python_files: list[str] = dataclass_field(default_factory=list)
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class ModelExtensionSource(DictModel):
"""Static Python source extension for a model across addons."""
module: str
addon_root: str
path: str
class_name: str
line_hint: int | None = None
relation_kind: str = "extends"
added_fields: list[str] = dataclass_field(default_factory=list)
added_methods: list[str] = dataclass_field(default_factory=list)
inherited_models: list[str] = dataclass_field(default_factory=list)
delegated_models: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class ModelDeclarationSource(DictModel):
"""Static source declaration for the model itself."""
module: str
addon_root: str
path: str
class_name: str
line_hint: int | None = None
added_fields: list[str] = dataclass_field(default_factory=list)
added_methods: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class InstalledModelField(DictModel):
"""Runtime field metadata for one installed model field."""
name: str
ttype: str
relation: str | None = None
modules: str | None = None
state: str | None = None
[docs]
@dataclass
class InstalledViewExtension(DictModel):
"""Installed inherited view metadata for a model."""
name: str
key: str | None = None
priority: int | None = None
inherit_id: list[Any] | None = None
[docs]
@dataclass
class ViewExtensionSource(DictModel):
"""Static XML view extension for a model across addons."""
module: str
addon_root: str
path: str
record_id: str | None = None
name: str | None = None
priority: int | None = None
inherit_ref: str | None = None
[docs]
@dataclass
class ModelExtensionInventory(DictModel):
"""Combined source and runtime inventory for model extensions."""
model: str
base_declarations: list[ModelDeclarationSource] = dataclass_field(
default_factory=list
)
source_extensions: list[ModelExtensionSource] = dataclass_field(
default_factory=list
)
source_extension_modules: list[str] = dataclass_field(default_factory=list)
installed_fields: list[InstalledModelField] = dataclass_field(default_factory=list)
installed_extension_fields: list[InstalledModelField] = dataclass_field(
default_factory=list
)
source_view_extensions: list[ViewExtensionSource] = dataclass_field(
default_factory=list
)
installed_view_extensions: list[InstalledViewExtension] = dataclass_field(
default_factory=list
)
installed_extension_modules: list[str] = dataclass_field(default_factory=list)
scanned_python_files: list[str] = dataclass_field(default_factory=list)
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class DocumentationDiagram(DictModel):
"""Rendered documentation diagram artifact."""
kind: str
title: str
format: str
content: str
[docs]
@dataclass
class DocumentSection(DictModel):
"""Rendered documentation section."""
title: str
markdown: str
summary: str = ""
order: int = 0
[docs]
@dataclass
class ModelDocumentation(DictModel):
"""Documentation bundle for one model."""
model: str
database: str | None = None
source_only: bool = False
field_attributes: list[str] = dataclass_field(default_factory=list)
requested_view_types: list[str] = dataclass_field(default_factory=list)
extension_inventory: ModelExtensionInventory | None = None
field_metadata: ModelFieldsResult | None = None
view_inventory: ModelViewInventory | None = None
diagrams: list[DocumentationDiagram] = dataclass_field(default_factory=list)
sections: list[DocumentSection] = dataclass_field(default_factory=list)
markdown: str = ""
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class AddonDocumentationModel(DictModel):
"""Per-model documentation detail inside one addon bundle."""
model: str
relation_kinds: list[str] = dataclass_field(default_factory=list)
source_entries: list[AddonModelEntry] = dataclass_field(default_factory=list)
documentation: ModelDocumentation | None = None
[docs]
@dataclass
class AddonContributionSummary(DictModel):
"""Compact per-addon summary for one shared model."""
model: str
module: str
relation_kinds: list[str] = dataclass_field(default_factory=list)
class_names: list[str] = dataclass_field(default_factory=list)
added_fields: list[str] = dataclass_field(default_factory=list)
added_methods: list[str] = dataclass_field(default_factory=list)
source_paths: list[str] = dataclass_field(default_factory=list)
line_hints: list[int] = dataclass_field(default_factory=list)
shared_model_doc_path: str | None = None
shared_model_doc_anchor: str | None = None
[docs]
@dataclass
class SharedModelDocumentation(DictModel):
"""Full shared-model documentation within a multi-addon bundle."""
model: str
owning_modules: list[str] = dataclass_field(default_factory=list)
contributing_modules: list[str] = dataclass_field(default_factory=list)
documentation: ModelDocumentation | None = None
output_path: str | None = None
markdown: str = ""
[docs]
@dataclass
class AddonDocumentation(DictModel):
"""Documentation bundle for one addon."""
module: str
database: str | None = None
source_only: bool = False
addon_info: AddonInfo | None = None
dependency_graph: dict[str, Any] = dataclass_field(default_factory=dict)
model_inventory: AddonModelInventory | None = None
models: list[AddonDocumentationModel] = dataclass_field(default_factory=list)
shared_model_contributions: list[AddonContributionSummary] = dataclass_field(
default_factory=list
)
recommended_tests: dict[str, Any] = dataclass_field(default_factory=dict)
diagrams: list[DocumentationDiagram] = dataclass_field(default_factory=list)
sections: list[DocumentSection] = dataclass_field(default_factory=list)
output_path: str | None = None
markdown: str = ""
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class MultiAddonDocumentation(DictModel):
"""Documentation bundle for multiple addons in one selected scope."""
modules: list[str] = dataclass_field(default_factory=list)
database: str | None = None
source_only: bool = False
addon_docs: list[AddonDocumentation] = dataclass_field(default_factory=list)
shared_models: list[SharedModelDocumentation] = dataclass_field(
default_factory=list
)
index_markdown: str = ""
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)
[docs]
@dataclass
class DependencyGraphDocumentation(DictModel):
"""Documentation bundle for addon dependency graphs."""
modules: list[str] = dataclass_field(default_factory=list)
database: str | None = None
source_only: bool = False
installed_only: bool = False
transitive: bool = True
dependency_graph: dict[str, Any] = dataclass_field(default_factory=dict)
installed_addons: InstalledAddonInventory | None = None
diagrams: list[DocumentationDiagram] = dataclass_field(default_factory=list)
sections: list[DocumentSection] = dataclass_field(default_factory=list)
markdown: str = ""
warnings: list[str] = dataclass_field(default_factory=list)
remediation: list[str] = dataclass_field(default_factory=list)