feat: indie status page MVP -- FastAPI + SQLite

- 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
This commit is contained in:
IndieStatusBot 2026-04-25 05:00:00 +00:00
commit 902133edd3
4655 changed files with 1342691 additions and 0 deletions

View file

@ -0,0 +1,125 @@
from __future__ import annotations
import os
import re
from librt.internal import ReadBuffer
from mypy import errorcodes as codes
from mypy.cache import read_int
from mypy.errors import Errors
from mypy.nodes import FileRawData, MypyFile
from mypy.options import Options
def parse(
source: str | bytes,
fnam: str,
module: str | None,
errors: Errors,
options: Options,
raise_on_error: bool = False,
imports_only: bool = False,
) -> MypyFile:
"""Parse a source file, without doing any semantic analysis.
Return the parse tree. If errors is not provided, raise ParseError
on failure. Otherwise, use the errors object to report parse errors.
The python_version (major, minor) option determines the Python syntax variant.
"""
if options.native_parser:
# Native parser only works with actual files on disk
# Fall back to fastparse for in-memory source or non-existent files
if os.path.exists(fnam):
import mypy.nativeparse
ignore_errors = options.ignore_errors or fnam in errors.ignored_files
# If errors are ignored, we can drop many function bodies to speed up type checking.
strip_function_bodies = ignore_errors and not options.preserve_asts
errors.set_file(fnam, module, options=options)
tree, parse_errors, type_ignores = mypy.nativeparse.native_parse(
fnam,
options,
skip_function_bodies=strip_function_bodies,
imports_only=imports_only,
)
# Convert type ignores list to dict
tree.ignored_lines = dict(type_ignores)
# Set is_stub based on file extension
tree.is_stub = fnam.endswith(".pyi")
# Note: tree.imports is populated directly by native_parse with deserialized
# import metadata, so we don't need to collect imports via AST traversal
# Report parse errors
for error in parse_errors:
message = error["message"]
# Standardize error message by capitalizing the first word
message = re.sub(r"^(\s*\w)", lambda m: m.group(1).upper(), message)
# Respect blocker status from error, default to True for syntax errors
is_blocker = error.get("blocker", True)
error_code = error.get("code")
if error_code is None:
error_code = codes.SYNTAX
else:
# Fallback to [syntax] for backwards compatibility.
error_code = codes.error_codes.get(error_code) or codes.SYNTAX
errors.report(
error["line"], error["column"], message, blocker=is_blocker, code=error_code
)
if raise_on_error and errors.is_errors():
errors.raise_error()
return tree
# Fall through to fastparse for non-existent files
assert not imports_only
if options.transform_source is not None:
source = options.transform_source(source)
import mypy.fastparse
tree = mypy.fastparse.parse(source, fnam=fnam, module=module, errors=errors, options=options)
if raise_on_error and errors.is_errors():
errors.raise_error()
return tree
def load_from_raw(
fnam: str, module: str | None, raw_data: FileRawData, errors: Errors, options: Options
) -> MypyFile:
"""Load AST from parsed binary data.
This essentially replicates parse() above but expects FileRawData instead of actually
parsing the source code in the file.
"""
from mypy.nativeparse import State, deserialize_imports, read_statements
# This part mimics the logic in native_parse().
data = ReadBuffer(raw_data.defs)
n = read_int(data)
state = State(options)
defs = read_statements(state, data, n)
imports = deserialize_imports(raw_data.imports)
tree = MypyFile(defs, imports)
tree.path = fnam
tree.ignored_lines = raw_data.ignored_lines
tree.is_partial_stub_package = raw_data.is_partial_stub_package
tree.uses_template_strings = raw_data.uses_template_strings
tree.is_stub = fnam.endswith(".pyi")
# Report parse errors, this replicates the logic in parse().
all_errors = raw_data.raw_errors + state.errors
errors.set_file(fnam, module, options=options)
for error in all_errors:
message = error["message"]
message = re.sub(r"^(\s*\w)", lambda m: m.group(1).upper(), message)
is_blocker = error.get("blocker", True)
error_code = error.get("code")
if error_code is None:
error_code = codes.SYNTAX
else:
error_code = codes.error_codes.get(error_code) or codes.SYNTAX
# Note we never raise in this function, so it should not be called in coordinator.
errors.report(error["line"], error["column"], message, blocker=is_blocker, code=error_code)
return tree