Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/db/models/manager.py: 88%

99 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1import copy 

2import inspect 

3from importlib import import_module 

4 

5from django.db import router 

6from django.db.models.query import QuerySet 

7 

8 

9class BaseManager: 

10 # To retain order, track each time a Manager instance is created. 

11 creation_counter = 0 

12 

13 # Set to True for the 'objects' managers that are automatically created. 

14 auto_created = False 

15 

16 #: If set to True the manager will be serialized into migrations and will 

17 #: thus be available in e.g. RunPython operations. 

18 use_in_migrations = False 

19 

20 def __new__(cls, *args, **kwargs): 

21 # Capture the arguments to make returning them trivial. 

22 obj = super().__new__(cls) 

23 obj._constructor_args = (args, kwargs) 

24 return obj 

25 

26 def __init__(self): 

27 super().__init__() 

28 self._set_creation_counter() 

29 self.model = None 

30 self.name = None 

31 self._db = None 

32 self._hints = {} 

33 

34 def __str__(self): 

35 """Return "app_label.model_label.manager_name".""" 

36 return "%s.%s" % (self.model._meta.label, self.name) 

37 

38 def __class_getitem__(cls, *args, **kwargs): 

39 return cls 

40 

41 def deconstruct(self): 

42 """ 

43 Return a 5-tuple of the form (as_manager (True), manager_class, 

44 queryset_class, args, kwargs). 

45 

46 Raise a ValueError if the manager is dynamically generated. 

47 """ 

48 qs_class = self._queryset_class 

49 if getattr(self, "_built_with_as_manager", False): 49 ↛ 51line 49 didn't jump to line 51, because the condition on line 49 was never true

50 # using MyQuerySet.as_manager() 

51 return ( 

52 True, # as_manager 

53 None, # manager_class 

54 "%s.%s" % (qs_class.__module__, qs_class.__name__), # qs_class 

55 None, # args 

56 None, # kwargs 

57 ) 

58 else: 

59 module_name = self.__module__ 

60 name = self.__class__.__name__ 

61 # Make sure it's actually there and not an inner class 

62 module = import_module(module_name) 

63 if not hasattr(module, name): 63 ↛ 64line 63 didn't jump to line 64, because the condition on line 63 was never true

64 raise ValueError( 

65 "Could not find manager %s in %s.\n" 

66 "Please note that you need to inherit from managers you " 

67 "dynamically generated with 'from_queryset()'." 

68 % (name, module_name) 

69 ) 

70 return ( 

71 False, # as_manager 

72 "%s.%s" % (module_name, name), # manager_class 

73 None, # qs_class 

74 self._constructor_args[0], # args 

75 self._constructor_args[1], # kwargs 

76 ) 

77 

78 def check(self, **kwargs): 

79 return [] 

80 

81 @classmethod 

82 def _get_queryset_methods(cls, queryset_class): 

83 def create_method(name, method): 

84 def manager_method(self, *args, **kwargs): 

85 return getattr(self.get_queryset(), name)(*args, **kwargs) 

86 

87 manager_method.__name__ = method.__name__ 

88 manager_method.__doc__ = method.__doc__ 

89 return manager_method 

90 

91 new_methods = {} 

92 for name, method in inspect.getmembers( 

93 queryset_class, predicate=inspect.isfunction 

94 ): 

95 # Only copy missing methods. 

96 if hasattr(cls, name): 

97 continue 

98 # Only copy public methods or methods with the attribute 

99 # queryset_only=False. 

100 queryset_only = getattr(method, "queryset_only", None) 

101 if queryset_only or (queryset_only is None and name.startswith("_")): 

102 continue 

103 # Copy the method onto the manager. 

104 new_methods[name] = create_method(name, method) 

105 return new_methods 

106 

107 @classmethod 

108 def from_queryset(cls, queryset_class, class_name=None): 

109 if class_name is None: 109 ↛ 111line 109 didn't jump to line 111, because the condition on line 109 was never false

110 class_name = "%sFrom%s" % (cls.__name__, queryset_class.__name__) 

111 return type( 

112 class_name, 

113 (cls,), 

114 { 

115 "_queryset_class": queryset_class, 

116 **cls._get_queryset_methods(queryset_class), 

117 }, 

118 ) 

119 

120 def contribute_to_class(self, cls, name): 

121 self.name = self.name or name 

122 self.model = cls 

123 

124 setattr(cls, name, ManagerDescriptor(self)) 

125 

126 cls._meta.add_manager(self) 

127 

128 def _set_creation_counter(self): 

129 """ 

130 Set the creation counter value for this instance and increment the 

131 class-level copy. 

132 """ 

133 self.creation_counter = BaseManager.creation_counter 

134 BaseManager.creation_counter += 1 

135 

136 def db_manager(self, using=None, hints=None): 

137 obj = copy.copy(self) 

138 obj._db = using or self._db 

139 obj._hints = hints or self._hints 

140 return obj 

141 

142 @property 

143 def db(self): 

144 return self._db or router.db_for_read(self.model, **self._hints) 

145 

146 ####################### 

147 # PROXIES TO QUERYSET # 

148 ####################### 

149 

150 def get_queryset(self): 

151 """ 

152 Return a new QuerySet object. Subclasses can override this method to 

153 customize the behavior of the Manager. 

154 """ 

155 return self._queryset_class(model=self.model, using=self._db, hints=self._hints) 

156 

157 def all(self): 

158 # We can't proxy this method through the `QuerySet` like we do for the 

159 # rest of the `QuerySet` methods. This is because `QuerySet.all()` 

160 # works by creating a "copy" of the current queryset and in making said 

161 # copy, all the cached `prefetch_related` lookups are lost. See the 

162 # implementation of `RelatedManager.get_queryset()` for a better 

163 # understanding of how this comes into play. 

164 return self.get_queryset() 

165 

166 def __eq__(self, other): 

167 return ( 

168 isinstance(other, self.__class__) 

169 and self._constructor_args == other._constructor_args 

170 ) 

171 

172 def __hash__(self): 

173 return id(self) 

174 

175 

176class Manager(BaseManager.from_queryset(QuerySet)): 

177 pass 

178 

179 

180class ManagerDescriptor: 

181 def __init__(self, manager): 

182 self.manager = manager 

183 

184 def __get__(self, instance, cls=None): 

185 if instance is not None: 185 ↛ 186line 185 didn't jump to line 186, because the condition on line 185 was never true

186 raise AttributeError( 

187 "Manager isn't accessible via %s instances" % cls.__name__ 

188 ) 

189 

190 if cls._meta.abstract: 190 ↛ 191line 190 didn't jump to line 191, because the condition on line 190 was never true

191 raise AttributeError( 

192 "Manager isn't available; %s is abstract" % (cls._meta.object_name,) 

193 ) 

194 

195 if cls._meta.swapped: 195 ↛ 196line 195 didn't jump to line 196, because the condition on line 195 was never true

196 raise AttributeError( 

197 "Manager isn't available; '%s' has been swapped for '%s'" 

198 % ( 

199 cls._meta.label, 

200 cls._meta.swapped, 

201 ) 

202 ) 

203 

204 return cls._meta.managers_map[self.manager.name] 

205 

206 

207class EmptyManager(Manager): 

208 def __init__(self, model): 

209 super().__init__() 

210 self.model = model 

211 

212 def get_queryset(self): 

213 return super().get_queryset().none()