def _get_class_attribute(self, node, cls, name, valself=None): """Get an attribute from a class.""" assert isinstance(cls, abstract.Class) if (not valself or not abstract_utils.equivalent_to(valself, cls) or cls == self.ctx.convert.type_type): # Since type(type) == type, the type_type check prevents an infinite loop. meta = None else: # We treat a class as an instance of its metaclass, but only if we are # looking for a class rather than an instance attribute. (So, for # instance, if we're analyzing int.mro(), we want to retrieve the mro # method on the type class, but for (3).mro(), we want to report that the # method does not exist.) meta = cls.cls return self._get_attribute(node, cls, meta, name, valself)
def get_special_attribute(self, node, name, valself): # Based on the definitions of object_init and object_new in # cpython/Objects/typeobject.c (https://goo.gl/bTEBRt). It is legal to pass # extra arguments to object.__new__ if the calling class overrides # object.__init__, and vice versa. if valself and not abstract_utils.equivalent_to(valself, self): val = valself.data if name == "__new__" and self._has_own(node, val, "__init__"): self.load_lazy_attribute("__new__extra_args") return self.members["__new__extra_args"] elif (name == "__init__" and isinstance(val, abstract.Instance) and self._has_own(node, val.cls, "__new__")): self.load_lazy_attribute("__init__extra_args") return self.members["__init__extra_args"] return super().get_special_attribute(node, name, valself)
def _lookup_from_mro(self, node, cls, name, valself, skip): """Find an identifier in the MRO of the class.""" if isinstance(cls, (abstract.Unknown, abstract.Unsolvable)): # We don't know the object's MRO, so it's possible that one of its # bases has the attribute. return self.ctx.new_unsolvable(node) ret = self.ctx.program.NewVariable() add_origins = [valself] if valself else [] for base in cls.mro: # Potentially skip part of MRO, for super() if base in skip: continue # When a special attribute is defined on a class buried in the MRO, # get_attribute (which calls get_special_attribute) is never called on # that class, so we have to call get_special_attribute here as well. var = base.get_special_attribute(node, name, valself) if var is None: node, var = self._get_attribute_flat(node, base, name, valself) if var is None or not var.bindings: continue for varval in var.bindings: value = varval.data if valself: # Check if we got a PyTDFunction from an InterpreterClass. If so, # then we must have aliased an imported function inside a class, so # we shouldn't bind the function to the class. if (not isinstance(value, abstract.PyTDFunction) or not isinstance(base, abstract.InterpreterClass)): # See BaseValue.property_get for an explanation of the # parameters we're passing here. value = value.property_get( valself.AssignToNewVariable(node), abstract_utils.equivalent_to(valself, cls)) if isinstance(value, abstract.Property): node, value = value.call(node, None, None) final_values = value.data else: final_values = [value] else: final_values = [value] for final_value in final_values: ret.AddBinding(final_value, [varval] + add_origins, node) break # we found a class which has this attribute return ret
def get_special_attribute(self, node, name, valself): if (valself and not abstract_utils.equivalent_to(valself, self) and name in self._slots): return mixin.HasSlots.get_special_attribute( self, node, name, valself) return super().get_special_attribute(node, name, valself)