- 8 DB models (services, incidents, monitors, subscribers, etc.) - Full CRUD API for services, incidents, monitors - Public status page with live data - Incident detail page with timeline - API key authentication - Uptime monitoring scheduler - 13 tests passing - TECHNICAL_DESIGN.md with full spec
79 lines
3 KiB
Python
79 lines
3 KiB
Python
from __future__ import annotations
|
|
|
|
from mypyc.ir.class_ir import ClassIR
|
|
from mypyc.ir.deps import Dependency
|
|
from mypyc.ir.func_ir import FuncIR
|
|
from mypyc.ir.ops import Assign, CallC, PrimitiveOp
|
|
from mypyc.ir.rtypes import RStruct, RTuple, RType, RUnion, RVec
|
|
|
|
|
|
def find_implicit_op_dependencies(fn: FuncIR) -> set[Dependency] | None:
|
|
"""Find implicit dependencies that need to be imported.
|
|
|
|
Using primitives or types defined in librt submodules such as "librt.base64"
|
|
requires dependency imports (e.g., capsule imports).
|
|
|
|
Note that a module can depend on a librt module even if it doesn't explicitly
|
|
import it, for example via re-exported names or via return types of functions
|
|
defined in other modules.
|
|
"""
|
|
deps: set[Dependency] | None = None
|
|
# Check function signature types for dependencies
|
|
deps = find_type_dependencies(fn, deps)
|
|
# Check ops for dependencies
|
|
for block in fn.blocks:
|
|
for op in block.ops:
|
|
assert not isinstance(op, PrimitiveOp), "Lowered IR is expected"
|
|
if isinstance(op, CallC) and op.dependencies is not None:
|
|
for dep in op.dependencies:
|
|
if deps is None:
|
|
deps = set()
|
|
deps.add(dep)
|
|
deps = collect_type_deps(op.type, deps)
|
|
if isinstance(op, Assign):
|
|
deps = collect_type_deps(op.dest.type, deps)
|
|
return deps
|
|
|
|
|
|
def find_type_dependencies(fn: FuncIR, deps: set[Dependency] | None) -> set[Dependency] | None:
|
|
"""Find dependencies from RTypes in function signatures.
|
|
|
|
Some RTypes (e.g., those for librt types) have associated dependencies
|
|
that need to be imported when the type is used.
|
|
"""
|
|
# Check parameter types
|
|
for arg in fn.decl.sig.args:
|
|
deps = collect_type_deps(arg.type, deps)
|
|
# Check return type
|
|
deps = collect_type_deps(fn.decl.sig.ret_type, deps)
|
|
return deps
|
|
|
|
|
|
def find_class_dependencies(cl: ClassIR) -> set[Dependency] | None:
|
|
"""Find dependencies from class attribute types."""
|
|
deps: set[Dependency] | None = None
|
|
for base in cl.mro:
|
|
for attr_type in base.attributes.values():
|
|
deps = collect_type_deps(attr_type, deps)
|
|
return deps
|
|
|
|
|
|
def collect_type_deps(typ: RType, deps: set[Dependency] | None) -> set[Dependency] | None:
|
|
"""Collect dependencies from an RType, recursively checking compound types."""
|
|
if typ.dependencies is not None:
|
|
for dep in typ.dependencies:
|
|
if deps is None:
|
|
deps = set()
|
|
deps.add(dep)
|
|
if isinstance(typ, RUnion):
|
|
for item in typ.items:
|
|
deps = collect_type_deps(item, deps)
|
|
elif isinstance(typ, RTuple):
|
|
for item in typ.types:
|
|
deps = collect_type_deps(item, deps)
|
|
elif isinstance(typ, RStruct):
|
|
for item in typ.types:
|
|
deps = collect_type_deps(item, deps)
|
|
elif isinstance(typ, RVec):
|
|
deps = collect_type_deps(typ.item_type, deps)
|
|
return deps
|