Coverage for src/lektor_ng/admin/context.py: 100%
49 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-03 22:18 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-03 22:18 +0000
1from __future__ import annotations
3from typing import TYPE_CHECKING, Any, NamedTuple
5from flask import Flask, current_app, g
6from werkzeug.utils import cached_property
8from lektor_ng.builder import Builder
9from lektor_ng.buildfailures import FailureController
10from lektor_ng.db import Database, Pad, Tree
11from lektor_ng.environment import Environment
12from lektor_ng.environment.config import Config
13from lektor_ng.reporter import CliReporter
15if TYPE_CHECKING:
16 from _typeshed import StrPath
19class LektorInfo(NamedTuple):
20 env: Environment
21 output_path: StrPath
22 verbosity: int = 0
23 extra_flags: dict[str, str] | None = None
26class LektorContext(LektorInfo):
27 """Per-request object which provides the interface to Lektor for the Flask app(s).
29 This does not provide any logic. It just provides access to the
30 needed Lektor internals and instances.
31 """
33 @property
34 def project_id(self) -> str:
35 return self.env.project.id
37 @cached_property
38 def database(self) -> Database:
39 return Database(self.env)
41 @cached_property
42 def pad(self) -> Pad:
43 return self.database.new_pad()
45 @cached_property
46 def tree(self) -> Tree:
47 return Tree(self.pad)
49 @property
50 def config(self) -> Config:
51 return self.database.config
53 @cached_property
54 def builder(self) -> Builder:
55 return Builder(self.pad, self.output_path, extra_flags=self.extra_flags)
57 @cached_property
58 def failure_controller(self) -> FailureController:
59 return FailureController(self.pad, self.output_path)
61 def cli_reporter(self) -> CliReporter:
62 return CliReporter(self.env, verbosity=self.verbosity)
65class LektorApp(Flask):
66 """A Flask app that has a lektor_info attribute."""
68 def __init__(
69 self,
70 lektor_info: LektorInfo,
71 **kwargs: Any,
72 ) -> None:
73 Flask.__init__(self, "lektor_ng.admin", **kwargs)
74 self.lektor_info = lektor_info
77def get_lektor_context() -> LektorContext:
78 if not hasattr(g, "lektor_context"):
79 assert isinstance(current_app, LektorApp)
80 lektor_info = current_app.lektor_info
81 # pylint: disable=assigning-non-slot
82 g.lektor_context = LektorContext._make(lektor_info)
83 return g.lektor_context