Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/sqlalchemy/inspection.py: 73%

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

66 statements  

1# inspection.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 

8"""The inspection module provides the :func:`_sa.inspect` function, 

9which delivers runtime information about a wide variety 

10of SQLAlchemy objects, both within the Core as well as the 

11ORM. 

12 

13The :func:`_sa.inspect` function is the entry point to SQLAlchemy's 

14public API for viewing the configuration and construction 

15of in-memory objects. Depending on the type of object 

16passed to :func:`_sa.inspect`, the return value will either be 

17a related object which provides a known interface, or in many 

18cases it will return the object itself. 

19 

20The rationale for :func:`_sa.inspect` is twofold. One is that 

21it replaces the need to be aware of a large variety of "information 

22getting" functions in SQLAlchemy, such as 

23:meth:`_reflection.Inspector.from_engine` (deprecated in 1.4), 

24:func:`.orm.attributes.instance_state`, :func:`_orm.class_mapper`, 

25and others. The other is that the return value of :func:`_sa.inspect` 

26is guaranteed to obey a documented API, thus allowing third party 

27tools which build on top of SQLAlchemy configurations to be constructed 

28in a forwards-compatible way. 

29 

30""" 

31 

32from __future__ import annotations 

33 

34from typing import Any 

35from typing import Callable 

36from typing import Dict 

37from typing import Generic 

38from typing import Literal 

39from typing import Optional 

40from typing import overload 

41from typing import Protocol 

42from typing import Type 

43from typing import TypeVar 

44from typing import Union 

45 

46from . import exc 

47 

48_T = TypeVar("_T", bound=Any) 

49_TCov = TypeVar("_TCov", bound=Any, covariant=True) 

50_F = TypeVar("_F", bound=Callable[..., Any]) 

51 

52_IN = TypeVar("_IN", bound=Any) 

53 

54_registrars: Dict[type, Union[Literal[True], Callable[[Any], Any]]] = {} 

55 

56 

57class Inspectable(Generic[_T]): 

58 """define a class as inspectable. 

59 

60 This allows typing to set up a linkage between an object that 

61 can be inspected and the type of inspection it returns. 

62 

63 Unfortunately we cannot at the moment get all classes that are 

64 returned by inspection to suit this interface as we get into 

65 MRO issues. 

66 

67 """ 

68 

69 __slots__ = () 

70 

71 

72class _InspectableTypeProtocol(Protocol[_TCov]): 

73 """a protocol defining a method that's used when a type (ie the class 

74 itself) is passed to inspect(). 

75 

76 """ 

77 

78 def _sa_inspect_type(self) -> _TCov: ... 

79 

80 

81class _InspectableProtocol(Protocol[_TCov]): 

82 """a protocol defining a method that's used when an instance is 

83 passed to inspect(). 

84 

85 """ 

86 

87 def _sa_inspect_instance(self) -> _TCov: ... 

88 

89 

90@overload 

91def inspect( 

92 subject: Type[_InspectableTypeProtocol[_IN]], raiseerr: bool = True 

93) -> _IN: ... 

94 

95 

96@overload 

97def inspect( 

98 subject: _InspectableProtocol[_IN], raiseerr: bool = True 

99) -> _IN: ... 

100 

101 

102@overload 

103def inspect(subject: Inspectable[_IN], raiseerr: bool = True) -> _IN: ... 

104 

105 

106@overload 

107def inspect(subject: Any, raiseerr: Literal[False] = ...) -> Optional[Any]: ... 

108 

109 

110@overload 

111def inspect(subject: Any, raiseerr: bool = True) -> Any: ... 

112 

113 

114def inspect(subject: Any, raiseerr: bool = True) -> Any: 

115 """Produce an inspection object for the given target. 

116 

117 The returned value in some cases may be the 

118 same object as the one given, such as if a 

119 :class:`_orm.Mapper` object is passed. In other 

120 cases, it will be an instance of the registered 

121 inspection type for the given object, such as 

122 if an :class:`_engine.Engine` is passed, an 

123 :class:`_reflection.Inspector` object is returned. 

124 

125 :param subject: the subject to be inspected. 

126 :param raiseerr: When ``True``, if the given subject 

127 does not 

128 correspond to a known SQLAlchemy inspected type, 

129 :class:`sqlalchemy.exc.NoInspectionAvailable` 

130 is raised. If ``False``, ``None`` is returned. 

131 

132 """ 

133 type_ = type(subject) 

134 for cls in type_.__mro__: 

135 if cls in _registrars: 

136 reg = _registrars.get(cls, None) 

137 if reg is None: 

138 continue 

139 elif reg is True: 

140 return subject 

141 ret = reg(subject) 

142 if ret is not None: 

143 return ret 

144 else: 

145 reg = ret = None 

146 

147 if raiseerr and (reg is None or ret is None): 

148 raise exc.NoInspectionAvailable( 

149 "No inspection system is " 

150 "available for object of type %s" % type_ 

151 ) 

152 return ret 

153 

154 

155def _inspects( 

156 *types: Type[Any], 

157) -> Callable[[_F], _F]: 

158 def decorate(fn_or_cls: _F) -> _F: 

159 for type_ in types: 

160 if type_ in _registrars: 

161 raise AssertionError("Type %s is already registered" % type_) 

162 _registrars[type_] = fn_or_cls 

163 return fn_or_cls 

164 

165 return decorate 

166 

167 

168_TT = TypeVar("_TT", bound="Type[Any]") 

169 

170 

171def _self_inspects(cls: _TT) -> _TT: 

172 if cls in _registrars: 

173 raise AssertionError("Type %s is already registered" % cls) 

174 _registrars[cls] = True 

175 return cls