Spaces:
Configuration error
Configuration error
File size: 6,733 Bytes
33a4fd2 d231444 33a4fd2 d231444 33a4fd2 d231444 33a4fd2 d231444 33a4fd2 d231444 33a4fd2 d231444 33a4fd2 d231444 33a4fd2 d231444 33a4fd2 d231444 33a4fd2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | """API Surface Intelligence data models.
Uses Python enums for all categorical values to eliminate raw-string bugs
and make exhaustive-match checking possible in tests.
Kept in a dedicated module following the existing convention:
models/churn.py, models/call_graph.py, models/symbol.py, etc.
"""
from __future__ import annotations
from enum import Enum
from typing import Dict, List, Optional
from pydantic import BaseModel, Field
# ---------------------------------------------------------------------------
# Enumerations
# ---------------------------------------------------------------------------
class Visibility(str, Enum):
"""How broadly a symbol is accessible."""
PUBLIC = "public" # exported / part of the module's public interface
INTERNAL = "internal" # used within the package but not exported
PRIVATE = "private" # convention-private (underscore prefix, etc.)
UNKNOWN = "unknown" # could not be determined with sufficient confidence
class ApiKind(str, Enum):
"""What role the API plays in the system."""
EXPORTED = "exported" # explicit export statement (JS/TS)
ROUTE = "route" # HTTP route handler (FastAPI, Flask, Express)
CLI_ENTRY = "cli_entry" # CLI command entry point
MAIN_ENTRY = "main_entry" # __main__ or if __name__ == '__main__'
PUBLIC_CLASS = "public_class" # exported / non-private class
PUBLIC_FUNCTION = "public_function" # exported / non-private top-level function
PUBLIC_METHOD = "public_method" # non-private method of a public class
INTERFACE = "interface" # TypeScript interface
ENUM_TYPE = "enum_type" # TypeScript / Python enum
INTERNAL_HELPER = (
"internal_helper" # internal function/method not part of public surface
)
UNKNOWN = "unknown"
class ApiStatus(str, Enum):
"""Lifecycle status of an API."""
STABLE = "stable"
DEPRECATED = "deprecated" # annotated as deprecated
EXPERIMENTAL = "experimental" # annotated as experimental / beta
UNKNOWN = "unknown"
class BreakingChangeKind(str, Enum):
"""Type of breaking change detected."""
REMOVED_EXPORT = "removed_export" # public symbol removed entirely
RENAMED_EXPORT = "renamed_export" # likely rename (remove + add with similar name)
SIGNATURE_CHANGED = "signature_changed" # param count changed
VISIBILITY_REDUCED = "visibility_reduced" # was public, now private/internal
# ---------------------------------------------------------------------------
# Core classification unit
# ---------------------------------------------------------------------------
class ClassifiedSymbol(BaseModel):
"""A symbol from the Symbol Index enriched with API surface metadata.
Attributes:
name: Symbol name.
qualified: Dot-qualified name (Class.method or function).
symbol_type: function | class | method | interface | enum.
file_path: Relative file path.
line_number: 1-indexed definition line.
language: Source language.
parent_class: Enclosing class for methods.
visibility: PUBLIC | INTERNAL | PRIVATE | UNKNOWN.
api_kind: Categorical role.
status: STABLE | DEPRECATED | EXPERIMENTAL | UNKNOWN.
confidence: 0.0–1.0 classification confidence.
classification_reason: Human-readable explanation of the classification.
param_count: Number of formal parameters (for breaking-change detection).
is_async: True if the function/method is declared async.
decorators: Decorator names found on this symbol (best-effort).
fan_in: Number of distinct callers from the call graph (0 if unavailable).
is_orphan: True when visibility=PUBLIC but fan_in=0 (unused public API).
"""
name: str
qualified: str
symbol_type: str
file_path: str
line_number: int = 1
language: str = "unknown"
parent_class: Optional[str] = None
visibility: Visibility = Visibility.UNKNOWN
api_kind: ApiKind = ApiKind.UNKNOWN
status: ApiStatus = ApiStatus.UNKNOWN
confidence: float = Field(0.0, ge=0.0, le=1.0)
classification_reason: str = ""
param_count: int = 0
is_async: bool = False
decorators: List[str] = Field(default_factory=list)
fan_in: int = 0
is_orphan: bool = False
# ---------------------------------------------------------------------------
# Breaking change record
# ---------------------------------------------------------------------------
class BreakingChange(BaseModel):
"""A single breaking API change between two surface snapshots.
Attributes:
kind: Type of change.
symbol_name: Affected symbol name.
file_path: File path (from the before snapshot, or after for additions).
before_param_count: Parameter count before the change (None if not applicable).
after_param_count: Parameter count after the change.
severity: "high" | "medium" | "low".
description: Human-readable explanation.
"""
kind: BreakingChangeKind
symbol_name: str
file_path: str = ""
before_param_count: Optional[int] = None
after_param_count: Optional[int] = None
severity: str = "high"
description: str = ""
# ---------------------------------------------------------------------------
# Summary / persisted report
# ---------------------------------------------------------------------------
class APISurfaceStats(BaseModel):
"""Aggregate statistics for one API surface report."""
total_symbols: int = 0
public_count: int = 0
internal_count: int = 0
private_count: int = 0
unknown_count: int = 0
deprecated_count: int = 0
experimental_count: int = 0
route_count: int = 0
entry_point_count: int = 0
orphan_public_count: int = 0
by_language: Dict[str, int] = Field(default_factory=dict)
class APISurface(BaseModel):
"""Full API surface report for a repository.
Written to data/api_surface/{owner}_{repo}.json by APISurfaceService.
Attributes:
repo: Repository identifier (owner/repo).
generated_at: ISO-8601 UTC timestamp.
symbols: All classified symbols.
stats: Aggregate statistics.
warning: Optional diagnostic message.
"""
repo: str
generated_at: str
symbols: List[ClassifiedSymbol] = Field(default_factory=list)
stats: APISurfaceStats = Field(default_factory=APISurfaceStats)
warning: Optional[str] = None
|