MCPcopy Index your code
hub / github.com/python/cpython / __getattribute__

Method __getattribute__

Lib/importlib/util.py:171–224  ·  view source on GitHub ↗

Trigger the load of the module and return the attribute.

(self, attr)

Source from the content-addressed store, hash-verified

169 """A subclass of the module type which triggers loading upon attribute access."""
170
171 def __getattribute__(self, attr):
172 """Trigger the load of the module and return the attribute."""
173 __spec__ = object.__getattribute__(self, '__spec__')
174 loader_state = __spec__.loader_state
175 with loader_state['lock']:
176 # Only the first thread to get the lock should trigger the load
177 # and reset the module's class. The rest can now getattr().
178 if object.__getattribute__(self, '__class__') is _LazyModule:
179 __class__ = loader_state['__class__']
180
181 # Reentrant calls from the same thread must be allowed to proceed without
182 # triggering the load again.
183 # exec_module() and self-referential imports are the primary ways this can
184 # happen, but in any case we must return something to avoid deadlock.
185 if loader_state['is_loading']:
186 return __class__.__getattribute__(self, attr)
187 loader_state['is_loading'] = True
188
189 __dict__ = __class__.__getattribute__(self, '__dict__')
190
191 # All module metadata must be gathered from __spec__ in order to avoid
192 # using mutated values.
193 # Get the original name to make sure no object substitution occurred
194 # in sys.modules.
195 original_name = __spec__.name
196 # Figure out exactly what attributes were mutated between the creation
197 # of the module and now.
198 attrs_then = loader_state['__dict__']
199 attrs_now = __dict__
200 attrs_updated = {}
201 for key, value in attrs_now.items():
202 # Code that set an attribute may have kept a reference to the
203 # assigned object, making identity more important than equality.
204 if key not in attrs_then:
205 attrs_updated[key] = value
206 elif id(attrs_now[key]) != id(attrs_then[key]):
207 attrs_updated[key] = value
208 __spec__.loader.exec_module(self)
209 # If exec_module() was used directly there is no guarantee the module
210 # object was put into sys.modules.
211 if original_name in sys.modules:
212 if id(self) != id(sys.modules[original_name]):
213 raise ValueError(f"module object for {original_name!r} "
214 "substituted in sys.modules during a lazy "
215 "load")
216 # Update after loading since that's what would happen in an eager
217 # loading situation.
218 __dict__.update(attrs_updated)
219 # Finally, stop triggering this method, if the module did not
220 # already update its own __class__.
221 if isinstance(self, _LazyModule):
222 object.__setattr__(self, '__class__', __class__)
223
224 return getattr(self, attr)
225
226 def __delattr__(self, attr):
227 """Trigger the load and then perform the deletion."""

Callers 1

__delattr__Method · 0.95

Calls 5

idFunction · 0.85
itemsMethod · 0.45
exec_moduleMethod · 0.45
updateMethod · 0.45
__setattr__Method · 0.45

Tested by

no test coverage detected