def find_best_base(space, bases_w): """The best base is one of the bases in the given list: the one whose layout a new type should use as a starting point. """ w_bestbase = None for w_candidate in bases_w: if not isinstance(w_candidate, W_TypeObject): continue if w_bestbase is None: w_bestbase = w_candidate # for now continue candtypedef = w_candidate.instancetypedef besttypedef = w_bestbase.instancetypedef if candtypedef is besttypedef: # two candidates with the same typedef are equivalent unless # one has extra slots over the other if w_candidate.nslots > w_bestbase.nslots: w_bestbase = w_candidate elif issubtypedef(candtypedef, besttypedef): w_bestbase = w_candidate return w_bestbase
def __init__(w_self, space, name, bases_w, dict_w, overridetypedef=None): w_self.space = space w_self.name = name w_self.bases_w = bases_w w_self.dict_w = dict_w w_self.ensure_static__new__() w_self.nslots = 0 w_self.needsdel = False w_self.w_bestbase = None w_self.weak_subclasses_w = [] # make sure there is a __doc__ in dict_w if '__doc__' not in dict_w: dict_w['__doc__'] = space.w_None if overridetypedef is not None: w_self.instancetypedef = overridetypedef w_self.hasdict = overridetypedef.hasdict w_self.weakrefable = overridetypedef.weakrefable w_self.__flags__ = 0 # not a heaptype if overridetypedef.base is not None: w_self.w_bestbase = space.gettypeobject(overridetypedef.base) else: w_self.__flags__ = _HEAPTYPE # initialize __module__ in the dict if '__module__' not in dict_w: try: caller = space.getexecutioncontext().framestack.top() except IndexError: w_globals = w_locals = space.newdict() else: w_globals = caller.w_globals w_str_name = space.wrap('__name__') w_name = space.finditem(w_globals, w_str_name) if w_name is not None: dict_w['__module__'] = w_name # find the most specific typedef instancetypedef = object_typedef for w_base in bases_w: if not isinstance(w_base, W_TypeObject): continue if issubtypedef(w_base.instancetypedef, instancetypedef): if instancetypedef is not w_base.instancetypedef: instancetypedef = w_base.instancetypedef w_self.w_bestbase = w_base elif not issubtypedef(instancetypedef, w_base.instancetypedef): raise OperationError(space.w_TypeError, space.wrap("instance layout conflicts in " "multiple inheritance")) if not instancetypedef.acceptable_as_base_class: raise OperationError(space.w_TypeError, space.wrap("type '%s' is not an " "acceptable base class" % instancetypedef.name)) w_self.instancetypedef = instancetypedef w_self.hasdict = False w_self.weakrefable = False hasoldstylebase = False w_most_derived_base_with_slots = None w_newstyle = None for w_base in bases_w: if not isinstance(w_base, W_TypeObject): hasoldstylebase = True continue if not w_newstyle: w_newstyle = w_base if w_base.nslots != 0: if w_most_derived_base_with_slots is None: w_most_derived_base_with_slots = w_base else: if space.is_true(space.issubtype(w_base, w_most_derived_base_with_slots)): w_most_derived_base_with_slots = w_base elif not space.is_true(space.issubtype(w_most_derived_base_with_slots, w_base)): raise OperationError(space.w_TypeError, space.wrap("instance layout conflicts in " "multiple inheritance")) w_self.hasdict = w_self.hasdict or w_base.hasdict w_self.needsdel = w_self.needsdel or w_base.needsdel w_self.weakrefable = w_self.weakrefable or w_base.weakrefable if not w_newstyle: # only classic bases raise OperationError(space.w_TypeError, space.wrap("a new-style class can't have only classic bases")) if w_most_derived_base_with_slots: nslots = w_most_derived_base_with_slots.nslots w_self.w_bestbase = w_most_derived_base_with_slots else: nslots = 0 if w_self.w_bestbase is None: w_self.w_bestbase = w_newstyle wantdict = True wantweakref = True if '__slots__' in dict_w: wantdict = False wantweakref = False w_slots = dict_w['__slots__'] if space.is_true(space.isinstance(w_slots, space.w_str)): if space.int_w(space.len(w_slots)) == 0: raise OperationError(space.w_TypeError, space.wrap('__slots__ must be identifiers')) slot_names_w = [w_slots] else: slot_names_w = space.unpackiterable(w_slots) for w_slot_name in slot_names_w: slot_name = space.str_w(w_slot_name) # slot_name should be a valid identifier if len(slot_name) == 0: raise OperationError(space.w_TypeError, space.wrap('__slots__ must be identifiers')) first_char = slot_name[0] if not first_char.isalpha() and first_char != '_': raise OperationError(space.w_TypeError, space.wrap('__slots__ must be identifiers')) for c in slot_name: if not c.isalnum() and c!= '_': raise OperationError(space.w_TypeError, space.wrap('__slots__ must be identifiers')) if slot_name == '__dict__': if wantdict or w_self.hasdict: raise OperationError(space.w_TypeError, space.wrap("__dict__ slot disallowed: we already got one")) wantdict = True elif slot_name == '__weakref__': if wantweakref or w_self.weakrefable: raise OperationError(space.w_TypeError, space.wrap("__weakref__ slot disallowed: we already got one")) wantweakref = True else: # create member slot_name = _mangle(slot_name, name) # Force interning of slot names. slot_name = space.str_w(space.new_interned_str(slot_name)) w_self.dict_w[slot_name] = space.wrap(Member(nslots, slot_name, w_self)) nslots += 1 w_self.nslots = nslots wantdict = wantdict or hasoldstylebase if wantdict and not w_self.hasdict: w_self.dict_w['__dict__'] = space.wrap(std_dict_descr) w_self.hasdict = True if '__del__' in dict_w: w_self.needsdel = True if wantweakref and not w_self.weakrefable: w_self.dict_w['__weakref__'] = space.wrap(weakref_descr) w_self.weakrefable = True w_type = space.type(w_self) if not space.is_w(w_type, space.w_type): if space.config.objspace.std.withtypeversion: w_self.version_tag = None w_self.mro_w = [] mro_func = space.lookup(w_self, 'mro') mro_func_args = Arguments(space, [w_self]) w_mro = space.call_args(mro_func, mro_func_args) w_self.mro_w = space.unpackiterable(w_mro) return w_self.mro_w = w_self.compute_mro() if space.config.objspace.std.withtypeversion: if w_self.instancetypedef.hasdict: w_self.version_tag = None else: w_self.version_tag = VersionTag()
def __init__(w_self, space, name, bases_w, dict_w, overridetypedef=None): w_self.space = space w_self.name = name w_self.bases_w = bases_w w_self.dict_w = dict_w w_self.ensure_static__new__() w_self.nslots = 0 w_self.needsdel = False w_self.w_bestbase = None w_self.weak_subclasses = [] # make sure there is a __doc__ in dict_w if '__doc__' not in dict_w: dict_w['__doc__'] = space.w_None if overridetypedef is not None: w_self.instancetypedef = overridetypedef w_self.hasdict = overridetypedef.hasdict w_self.weakrefable = overridetypedef.weakrefable w_self.__flags__ = 0 # not a heaptype if overridetypedef.base is not None: w_self.w_bestbase = space.gettypeobject(overridetypedef.base) else: w_self.__flags__ = _HEAPTYPE # initialize __module__ in the dict if '__module__' not in dict_w: try: caller = space.getexecutioncontext().framestack.top() except IndexError: w_globals = w_locals = space.newdict() else: w_globals = caller.w_globals w_str_name = space.wrap('__name__') w_name = space.finditem(w_globals, w_str_name) if w_name is not None: dict_w['__module__'] = w_name # find the most specific typedef instancetypedef = object_typedef for w_base in bases_w: if not isinstance(w_base, W_TypeObject): continue if issubtypedef(w_base.instancetypedef, instancetypedef): if instancetypedef is not w_base.instancetypedef: instancetypedef = w_base.instancetypedef w_self.w_bestbase = w_base elif not issubtypedef(instancetypedef, w_base.instancetypedef): raise OperationError(space.w_TypeError, space.wrap("instance layout conflicts in " "multiple inheritance")) if not instancetypedef.acceptable_as_base_class: raise OperationError(space.w_TypeError, space.wrap("type '%s' is not an " "acceptable base class" % instancetypedef.name)) w_self.instancetypedef = instancetypedef w_self.hasdict = False w_self.weakrefable = False hasoldstylebase = False w_most_derived_base_with_slots = None w_newstyle = None for w_base in bases_w: if not isinstance(w_base, W_TypeObject): hasoldstylebase = True continue if not w_newstyle: w_newstyle = w_base if w_base.nslots != 0: if w_most_derived_base_with_slots is None: w_most_derived_base_with_slots = w_base else: if space.is_true(space.issubtype(w_base, w_most_derived_base_with_slots)): w_most_derived_base_with_slots = w_base elif not space.is_true(space.issubtype(w_most_derived_base_with_slots, w_base)): raise OperationError(space.w_TypeError, space.wrap("instance layout conflicts in " "multiple inheritance")) w_self.hasdict = w_self.hasdict or w_base.hasdict w_self.needsdel = w_self.needsdel or w_base.needsdel w_self.weakrefable = w_self.weakrefable or w_base.weakrefable if not w_newstyle: # only classic bases raise OperationError(space.w_TypeError, space.wrap("a new-style class can't have only classic bases")) if w_most_derived_base_with_slots: nslots = w_most_derived_base_with_slots.nslots w_self.w_bestbase = w_most_derived_base_with_slots else: nslots = 0 if w_self.w_bestbase is None: w_self.w_bestbase = w_newstyle wantdict = True wantweakref = True if '__slots__' in dict_w: wantdict = False wantweakref = False w_slots = dict_w['__slots__'] if space.is_true(space.isinstance(w_slots, space.w_str)): if space.int_w(space.len(w_slots)) == 0: raise OperationError(space.w_TypeError, space.wrap('__slots__ must be identifiers')) slot_names_w = [w_slots] else: slot_names_w = space.unpackiterable(w_slots) for w_slot_name in slot_names_w: slot_name = space.str_w(w_slot_name) # slot_name should be a valid identifier if len(slot_name) == 0: raise OperationError(space.w_TypeError, space.wrap('__slots__ must be identifiers')) first_char = slot_name[0] if not first_char.isalpha() and first_char != '_': raise OperationError(space.w_TypeError, space.wrap('__slots__ must be identifiers')) for c in slot_name: if not c.isalnum() and c!= '_': raise OperationError(space.w_TypeError, space.wrap('__slots__ must be identifiers')) if slot_name == '__dict__': if wantdict or w_self.hasdict: raise OperationError(space.w_TypeError, space.wrap("__dict__ slot disallowed: we already got one")) wantdict = True elif slot_name == '__weakref__': if wantweakref or w_self.weakrefable: raise OperationError(space.w_TypeError, space.wrap("__weakref__ slot disallowed: we already got one")) wantweakref = True else: # create member slot_name = _mangle(slot_name, name) # Force interning of slot names. slot_name = space.str_w(space.new_interned_str(slot_name)) w_self.dict_w[slot_name] = space.wrap(Member(nslots, slot_name, w_self)) nslots += 1 w_self.nslots = nslots wantdict = wantdict or hasoldstylebase if wantdict and not w_self.hasdict: w_self.dict_w['__dict__'] = space.wrap(std_dict_descr) w_self.hasdict = True if '__del__' in dict_w: w_self.needsdel = True if wantweakref and not w_self.weakrefable: w_self.dict_w['__weakref__'] = space.wrap(weakref_descr) w_self.weakrefable = True w_type = space.type(w_self) if not space.is_w(w_type, space.w_type): if space.config.objspace.std.withtypeversion: w_self.version_tag = None w_self.mro_w = [] mro_func = space.lookup(w_self, 'mro') mro_func_args = Arguments(space, [w_self]) w_mro = space.call_args(mro_func, mro_func_args) w_self.mro_w = space.unpackiterable(w_mro) return w_self.mro_w = w_self.compute_mro() if space.config.objspace.std.withtypeversion: if w_self.instancetypedef.hasdict: w_self.version_tag = None else: w_self.version_tag = VersionTag()