Coverage for src / lexigram / admin / bootstrap / factory.py: 0%

46 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-11 02:25 +0800

1"""Factory functions for creating admin applications.""" 

2 

3from __future__ import annotations 

4 

5from pathlib import Path 

6from typing import TYPE_CHECKING, Any 

7 

8from starlette.applications import Starlette 

9from starlette.middleware import Middleware 

10from starlette.middleware.sessions import SessionMiddleware 

11 

12from lexigram.admin.auth.services._cookie_config import build_session_cookie_kwargs 

13from lexigram.admin.di.bundle_provider import AdminProvider 

14from lexigram.admin.middleware.correlation import AdminCorrelationMiddleware 

15from lexigram.admin.settings.loader import AdminConfigLoader 

16from lexigram.logging import get_logger 

17 

18if TYPE_CHECKING: 

19 from collections.abc import Sequence 

20 

21 from lexigram.admin.config import AdminConfig 

22 from lexigram.admin.resources.base import Resource 

23 

24logger = get_logger(__name__) 

25 

26 

27async def create_app( 

28 *, 

29 resources: Sequence[type | Resource] | dict[str, type | Resource] | None = None, 

30 config: AdminConfig | None = None, 

31 config_path: Path | str | None = None, 

32 title: str = "Lexigram Admin", 

33 prefix: str = "/admin", 

34 debug: bool = False, 

35 **kwargs: Any, 

36) -> Starlette: 

37 """Create a complete admin ASGI application.""" 

38 from lexigram.admin.config import AdminConfig as AdminConfigCls 

39 

40 if config is None and config_path is not None: 

41 loader = AdminConfigLoader(yaml_path=Path(config_path)) 

42 config = await loader.load() 

43 

44 if config is None: 

45 config = AdminConfigCls(title=title, prefix=prefix, debug=debug) 

46 

47 resources_list: list[Any] = [] 

48 if resources: 

49 if isinstance(resources, dict): 

50 resources_list = list(resources.values()) 

51 else: 

52 resources_list = list(resources) 

53 

54 AdminProvider(config=config, resources=resources_list) 

55 

56 cookie_kwargs = build_session_cookie_kwargs(config.auth) 

57 middleware = [ 

58 Middleware(AdminCorrelationMiddleware), 

59 Middleware(SessionMiddleware, **cookie_kwargs), 

60 ] 

61 

62 app = Starlette( 

63 debug=debug, 

64 middleware=middleware, 

65 ) 

66 

67 logger.info("Admin application created at %s", prefix) 

68 return app 

69 

70 

71async def create_admin_provider( 

72 *, 

73 resources: Sequence[type | Resource] | dict[str, type | Resource] | None = None, 

74 config: AdminConfig | None = None, 

75 config_path: Path | str | None = None, 

76 title: str = "Lexigram Admin", 

77 prefix: str = "/admin", 

78 debug: bool = False, 

79 **kwargs: Any, 

80) -> AdminProvider: 

81 """Create an AdminProvider for use with Application.""" 

82 from lexigram.admin.config import AdminConfig as AdminConfigCls 

83 

84 if config is None and config_path is not None: 

85 loader = AdminConfigLoader(yaml_path=Path(config_path)) 

86 config = await loader.load() 

87 

88 if config is None: 

89 config = AdminConfigCls(title=title, prefix=prefix, debug=debug) 

90 

91 resources_list: list[Any] = [] 

92 if resources: 

93 if isinstance(resources, dict): 

94 resources_list = list(resources.values()) 

95 else: 

96 resources_list = list(resources) 

97 

98 admin = AdminProvider(config=config, resources=resources_list) 

99 logger.info("AdminProvider created for prefix %s", prefix) 

100 return admin 

101 

102 

103__all__ = [ 

104 "create_admin_provider", 

105 "create_app", 

106]