Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
    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()
Esempio n. 4
0
    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()