Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/sqlalchemy/util/preloaded.py: 28%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

94 statements  

1# util/preloaded.py 

2# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors 

3# <see AUTHORS file> 

4# 

5# This module is part of SQLAlchemy and is released under 

6# the MIT License: https://www.opensource.org/licenses/mit-license.php 

7# mypy: allow-untyped-defs, allow-untyped-calls 

8 

9"""supplies the "preloaded" registry to resolve circular module imports at 

10runtime. 

11 

12""" 

13 

14from __future__ import annotations 

15 

16import sys 

17from typing import Any 

18from typing import Callable 

19from typing import TYPE_CHECKING 

20from typing import TypeVar 

21 

22_FN = TypeVar("_FN", bound=Callable[..., Any]) 

23 

24 

25if TYPE_CHECKING: 

26 from sqlalchemy import dialects as _dialects 

27 from sqlalchemy import orm as _orm 

28 from sqlalchemy.engine import cursor as _engine_cursor 

29 from sqlalchemy.engine import default as _engine_default 

30 from sqlalchemy.engine import reflection as _engine_reflection 

31 from sqlalchemy.engine import result as _engine_result 

32 from sqlalchemy.engine import url as _engine_url 

33 from sqlalchemy.orm import attributes as _orm_attributes 

34 from sqlalchemy.orm import base as _orm_base 

35 from sqlalchemy.orm import clsregistry as _orm_clsregistry 

36 from sqlalchemy.orm import decl_api as _orm_decl_api 

37 from sqlalchemy.orm import decl_base as _orm_decl_base 

38 from sqlalchemy.orm import dependency as _orm_dependency 

39 from sqlalchemy.orm import descriptor_props as _orm_descriptor_props 

40 from sqlalchemy.orm import mapperlib as _orm_mapper 

41 from sqlalchemy.orm import properties as _orm_properties 

42 from sqlalchemy.orm import relationships as _orm_relationships 

43 from sqlalchemy.orm import session as _orm_session 

44 from sqlalchemy.orm import state as _orm_state 

45 from sqlalchemy.orm import strategies as _orm_strategies 

46 from sqlalchemy.orm import strategy_options as _orm_strategy_options 

47 from sqlalchemy.orm import util as _orm_util 

48 from sqlalchemy.sql import ddl as _sql_ddl 

49 from sqlalchemy.sql import default_comparator as _sql_default_comparator 

50 from sqlalchemy.sql import dml as _sql_dml 

51 from sqlalchemy.sql import elements as _sql_elements 

52 from sqlalchemy.sql import functions as _sql_functions 

53 from sqlalchemy.sql import naming as _sql_naming 

54 from sqlalchemy.sql import schema as _sql_schema 

55 from sqlalchemy.sql import selectable as _sql_selectable 

56 from sqlalchemy.sql import sqltypes as _sql_sqltypes 

57 from sqlalchemy.sql import traversals as _sql_traversals 

58 from sqlalchemy.sql import util as _sql_util 

59 

60 # sigh, appease mypy 0.971 which does not accept imports as instance 

61 # variables of a module 

62 dialects = _dialects 

63 engine_cursor = _engine_cursor 

64 engine_default = _engine_default 

65 engine_reflection = _engine_reflection 

66 engine_result = _engine_result 

67 engine_url = _engine_url 

68 orm_clsregistry = _orm_clsregistry 

69 orm_base = _orm_base 

70 orm = _orm 

71 orm_attributes = _orm_attributes 

72 orm_decl_api = _orm_decl_api 

73 orm_decl_base = _orm_decl_base 

74 orm_descriptor_props = _orm_descriptor_props 

75 orm_dependency = _orm_dependency 

76 orm_mapper = _orm_mapper 

77 orm_properties = _orm_properties 

78 orm_relationships = _orm_relationships 

79 orm_session = _orm_session 

80 orm_strategies = _orm_strategies 

81 orm_strategy_options = _orm_strategy_options 

82 orm_state = _orm_state 

83 orm_util = _orm_util 

84 sql_ddl = _sql_ddl 

85 sql_default_comparator = _sql_default_comparator 

86 sql_dml = _sql_dml 

87 sql_elements = _sql_elements 

88 sql_functions = _sql_functions 

89 sql_naming = _sql_naming 

90 sql_selectable = _sql_selectable 

91 sql_traversals = _sql_traversals 

92 sql_schema = _sql_schema 

93 sql_sqltypes = _sql_sqltypes 

94 sql_util = _sql_util 

95 

96 

97class _ModuleRegistry: 

98 """Registry of modules to load in a package init file. 

99 

100 To avoid potential thread safety issues for imports that are deferred 

101 in a function, like https://bugs.python.org/issue38884, these modules 

102 are added to the system module cache by importing them after the packages 

103 has finished initialization. 

104 

105 A global instance is provided under the name :attr:`.preloaded`. Use 

106 the function :func:`.preload_module` to register modules to load and 

107 :meth:`.import_prefix` to load all the modules that start with the 

108 given path. 

109 

110 While the modules are loaded in the global module cache, it's advisable 

111 to access them using :attr:`.preloaded` to ensure that it was actually 

112 registered. Each registered module is added to the instance ``__dict__`` 

113 in the form `<package>_<module>`, omitting ``sqlalchemy`` from the package 

114 name. Example: ``sqlalchemy.sql.util`` becomes ``preloaded.sql_util``. 

115 """ 

116 

117 def __init__(self, prefix="sqlalchemy."): 

118 self.module_registry = set() 

119 self.prefix = prefix 

120 

121 def preload_module(self, *deps: str) -> Callable[[_FN], _FN]: 

122 """Adds the specified modules to the list to load. 

123 

124 This method can be used both as a normal function and as a decorator. 

125 No change is performed to the decorated object. 

126 """ 

127 self.module_registry.update(deps) 

128 return lambda fn: fn 

129 

130 def import_prefix(self, path: str) -> None: 

131 """Resolve all the modules in the registry that start with the 

132 specified path. 

133 """ 

134 for module in self.module_registry: 

135 if self.prefix: 

136 key = module.split(self.prefix)[-1].replace(".", "_") 

137 else: 

138 key = module 

139 if ( 

140 not path or module.startswith(path) 

141 ) and key not in self.__dict__: 

142 __import__(module, globals(), locals()) 

143 self.__dict__[key] = globals()[key] = sys.modules[module] 

144 

145 

146_reg = _ModuleRegistry() 

147preload_module = _reg.preload_module 

148import_prefix = _reg.import_prefix 

149 

150# this appears to do absolutely nothing for any version of mypy 

151# if TYPE_CHECKING: 

152# def __getattr__(key: str) -> ModuleType: 

153# ...