F
flori
i try to greate somthing like this
class ca(object): __slots__ = ("a",)
class cb(ca): __slots__ = ("a","b")
class cc(ca): __slots__ = ("a","c")
class cd(cb,cc): __slots__ = ("a","b","c","d")
but i didn't find a simple solution
so i'm using a metaclass that generate a __slots__-free and a
__slots__-version
the __slots__ -free is returned
the __new__ of the base class look for the sloted verion
the classes defines a (class)-attribute __object_slots__ with their
new attribute names.
killer? someone a good idea?
my soure (something not important i'm cutting away)
import sys
import types
import inspect
import weakref
#import
#
class const(object):
__slots__=()
cs_classid = intern("_classid")
cs__all_persitent_slots__ = intern("__all_persitent_slots__")
cs__all_nonpersitent_slots__ =
intern("__all_nonpersitent_slots__")
cs__all_slots__ = intern("__all_slots__")
cs__cls_unsloted__ = intern("__cls_unsloted__")
cs__nonpersitent_slots__ = intern("__nonpersitent_slots__")
cs__object_slots__ = intern("__object_slots__")
cs__object_slots_nomore__ = intern("__object_slots_nomore__")
cs__slots__ = intern("__slots__")
cs__slots_fixed__ = intern("__slots_fixed__")
cs_lstobjProperty = intern("_lstobjProperty")
cslstSlots = intern("lstSlots")
cs_sloted_prefix = intern("_sloted_")
cslstNonPersitentSlots = intern("lstNonPersitentSlots")
#
#
class ClCustomBase(object):
""" no really need for this but i like it
may be i need for debugging, if..
"""
pass
#
class ClMetaClass(ClCustomBase):
#
def __new__(cls, sName, tupBases, dctClassDefinition):
""" calculates the class-attribute.
calcs
__all_slots__ := __object_slots__ + (for all
tupBases).__all_slots__
__all_nonpersitent_slots__ := __nonpersitent_slots__ +
(for all tupBases).__all_nonpersitent_slots__
__all_persitent_slots__ := __all_slots__ -
__all_nonpersitent_slots__
"""
# init
objClsUnsloted=None
dctDefinitionLocals = sys._getframe(1).f_locals
# create a (hopefully) unique name
# first i try to use the id(objClsUnsloted) but it's not known
before creation
# - and i should know it before
dctClassDefinition[const.cs_classid] = sName +
hex(id(tupBases) ^ id(sys._getframe(0)) ) ^
id(dctClassDefinition.get(const.cs__object_slots__, None))
dctAddInfo = {
const.cslstSlots: list(),
const.cslstNonPersitentSlots: list(),
}
# prepare definition of unsloted
cls.calculateSlots(sName, tupBases, dctClassDefinition,
dctAddInfo, dctDefinitionLocals)
objClsUnsloted = type(sName, tupBases, dctClassDefinition)
#
# prepare definition of sloted
dctClassDefinition[const.cs__slots__] =
tuple(dctAddInfo[const.cslstSlots])
dctClassDefinition[const.cs__cls_unsloted__] = objClsUnsloted
# definition of the sloted class
objClsSloted = type(const.cs_sloted_prefix+sName,
(objClsUnsloted,), dctClassDefinition)
objClsUnsloted.__cls_sloted__ = objClsSloted
dctDefinitionLocals[const.cs_sloted_prefix+sName] =
objClsSloted
# done
dctDefinitionLocals = None # help gc
return objClsUnsloted
#
def __init__(self, sName, tupBases, dctClassDefinition):
super(ClMetaBase,self).__init__(sName, tupBases,
dctClassDefinition)
#
def calculateSlots(cls, sName, tupBases, dctClassDefinition,
dctAddInfo, dctDefinitionLocals):
""" calculates all slot things needed fo the sloted version -
ah you geuess it
"""
lstSlots=dctAddInfo[const.cslstSlots]
tupClassSlots =
dctClassDefinition.get(const.cs__object_slots__, None)
if isinstance(tupClassSlots, basestring):
raise TypeError, "in class "+sName+":__object_slots__ is
defined as string (may be you forgotten a ,?)"
if tupClassSlots is None:
# or should we simply pass ?
raise TypeError, "The class "+sName+" (with ClBase as
superclass) must have a __object_slots__-attribute like
\n__object_slots__ = "+str(tuple(lstSlots))+".\n"+", but
-"+str(tupClassSlots)+"- found \n"
else:
lstSlots.extend( tupClassSlots )
#
lstNonPersitentSlots=dctAddInfo[const.cslstNonPersitentSlots]
lstNonPersitentSlots.extend(
dctClassDefinition.get(const.cs__nonpersitent_slots__, ()) )
#
for objCls in tupBases:
tupSubSlots = getattr(objCls, const.cs__all_slots__, None)
if tupSubSlots is not None:
lstSlots.extend(tupSubSlots)
#
tupSubSlots = getattr(objCls,
const.cs__nonpersitent_slots__, None)
if tupSubSlots is not None:
lstNonPersitentSlots.extend(tupSubSlots)
#no more needed
#lstBasesUnsloted.append(getattr(objCls,
cs__cls_unsloted__, objCls))
#
#no more needed
#dctAddInfo["tupBasesUnsloted"] = tuple( lstBasesUnsloted )
#add nonpersitent slots to the all slots
#
lstNonPersitentSlots.sort()
for iIndex in xrange(len(lstNonPersitentSlots)-2, -1, -1):
if lstNonPersitentSlots[iIndex] ==
lstNonPersitentSlots[iIndex+1]:
del lstNonPersitentSlots[iIndex+1]
#
#
tupObjectSlotsNoMore =
dctClassDefinition.get(const.cs__object_slots_nomore__, None)
if tupObjectSlotsNoMore is not None:
for sObjectSlotsNoMore in tupObjectSlotsNoMore:
try:
lstNonPersitentSlots.remove(sObjectSlotsNoMore)
except ValueError:
pass
#
#
#
lstSlots.extend(lstNonPersitentSlots)
#sort slots and remove doubles
lstSlots.sort()
for iIndex in xrange(len(lstSlots)-2, -1, -1):
s=intern(lstSlots[iIndex])
if s == lstSlots[iIndex+1]:
del lstSlots[iIndex+1]
else:
lstSlots[iIndex]=s
#
#
if tupObjectSlotsNoMore is not None:
for sObjectSlotsNoMore in tupObjectSlotsNoMore:
try:
lstSlots.remove(sObjectSlotsNoMore)
except ValueError:
pass
#
#
#
# non persitent and persitent are disjunct ==> persitent :=
slots - non persitenten
lstPersitentSlots=lstSlots[:]
for sKey in lstNonPersitentSlots:
lstPersitentSlots.remove(sKey)
#
# update class definition
dctClassDefinition[const.cs__all_slots__]=tuple(lstSlots)
dctClassDefinition[const.cs__all_nonpersitent_slots__]=tuple(lstNonPersitentSlots)
dctClassDefinition[const.cs__all_persitent_slots__]=tuple(lstPersitentSlots)
#
# normally there isn't a __slots__ - definition, but if we
cannot trust it
try:
dctClassDefinition.remove(const.cs__slots__)
except:
pass
dctDefinitionLocals = None # help gc
#
calculateSlots=classmethod(calculateSlots)
#
#
class ClBase(ClCustomBase):
""" base of all
"""
#
__metaclass__ = ClMetaClass
__object_slots__ = ()
#__object_slots__ = ("gna", "__weakref__", )
#__weakref__ = 1
#
def __new__(cls, *lstArgs, **kwArgs):
self = super(ClBase,
cls).__new__(getattr(cls,"__cls_sloted__",cls))
return self
#now __init__ is called
# / __new__
def __init__(self, *lstArgs, **kwArgs):
super(ClBase, self).__init__()
#
#
class ca(object): __slots__ = ("a",)
class cb(ca): __slots__ = ("a","b")
class cc(ca): __slots__ = ("a","c")
class cd(cb,cc): __slots__ = ("a","b","c","d")
but i didn't find a simple solution
so i'm using a metaclass that generate a __slots__-free and a
__slots__-version
the __slots__ -free is returned
the __new__ of the base class look for the sloted verion
the classes defines a (class)-attribute __object_slots__ with their
new attribute names.
killer? someone a good idea?
my soure (something not important i'm cutting away)
import sys
import types
import inspect
import weakref
#import
#
class const(object):
__slots__=()
cs_classid = intern("_classid")
cs__all_persitent_slots__ = intern("__all_persitent_slots__")
cs__all_nonpersitent_slots__ =
intern("__all_nonpersitent_slots__")
cs__all_slots__ = intern("__all_slots__")
cs__cls_unsloted__ = intern("__cls_unsloted__")
cs__nonpersitent_slots__ = intern("__nonpersitent_slots__")
cs__object_slots__ = intern("__object_slots__")
cs__object_slots_nomore__ = intern("__object_slots_nomore__")
cs__slots__ = intern("__slots__")
cs__slots_fixed__ = intern("__slots_fixed__")
cs_lstobjProperty = intern("_lstobjProperty")
cslstSlots = intern("lstSlots")
cs_sloted_prefix = intern("_sloted_")
cslstNonPersitentSlots = intern("lstNonPersitentSlots")
#
#
class ClCustomBase(object):
""" no really need for this but i like it
may be i need for debugging, if..
"""
pass
#
class ClMetaClass(ClCustomBase):
#
def __new__(cls, sName, tupBases, dctClassDefinition):
""" calculates the class-attribute.
calcs
__all_slots__ := __object_slots__ + (for all
tupBases).__all_slots__
__all_nonpersitent_slots__ := __nonpersitent_slots__ +
(for all tupBases).__all_nonpersitent_slots__
__all_persitent_slots__ := __all_slots__ -
__all_nonpersitent_slots__
"""
# init
objClsUnsloted=None
dctDefinitionLocals = sys._getframe(1).f_locals
# create a (hopefully) unique name
# first i try to use the id(objClsUnsloted) but it's not known
before creation
# - and i should know it before
dctClassDefinition[const.cs_classid] = sName +
hex(id(tupBases) ^ id(sys._getframe(0)) ) ^
id(dctClassDefinition.get(const.cs__object_slots__, None))
dctAddInfo = {
const.cslstSlots: list(),
const.cslstNonPersitentSlots: list(),
}
# prepare definition of unsloted
cls.calculateSlots(sName, tupBases, dctClassDefinition,
dctAddInfo, dctDefinitionLocals)
objClsUnsloted = type(sName, tupBases, dctClassDefinition)
#
# prepare definition of sloted
dctClassDefinition[const.cs__slots__] =
tuple(dctAddInfo[const.cslstSlots])
dctClassDefinition[const.cs__cls_unsloted__] = objClsUnsloted
# definition of the sloted class
objClsSloted = type(const.cs_sloted_prefix+sName,
(objClsUnsloted,), dctClassDefinition)
objClsUnsloted.__cls_sloted__ = objClsSloted
dctDefinitionLocals[const.cs_sloted_prefix+sName] =
objClsSloted
# done
dctDefinitionLocals = None # help gc
return objClsUnsloted
#
def __init__(self, sName, tupBases, dctClassDefinition):
super(ClMetaBase,self).__init__(sName, tupBases,
dctClassDefinition)
#
def calculateSlots(cls, sName, tupBases, dctClassDefinition,
dctAddInfo, dctDefinitionLocals):
""" calculates all slot things needed fo the sloted version -
ah you geuess it
"""
lstSlots=dctAddInfo[const.cslstSlots]
tupClassSlots =
dctClassDefinition.get(const.cs__object_slots__, None)
if isinstance(tupClassSlots, basestring):
raise TypeError, "in class "+sName+":__object_slots__ is
defined as string (may be you forgotten a ,?)"
if tupClassSlots is None:
# or should we simply pass ?
raise TypeError, "The class "+sName+" (with ClBase as
superclass) must have a __object_slots__-attribute like
\n__object_slots__ = "+str(tuple(lstSlots))+".\n"+", but
-"+str(tupClassSlots)+"- found \n"
else:
lstSlots.extend( tupClassSlots )
#
lstNonPersitentSlots=dctAddInfo[const.cslstNonPersitentSlots]
lstNonPersitentSlots.extend(
dctClassDefinition.get(const.cs__nonpersitent_slots__, ()) )
#
for objCls in tupBases:
tupSubSlots = getattr(objCls, const.cs__all_slots__, None)
if tupSubSlots is not None:
lstSlots.extend(tupSubSlots)
#
tupSubSlots = getattr(objCls,
const.cs__nonpersitent_slots__, None)
if tupSubSlots is not None:
lstNonPersitentSlots.extend(tupSubSlots)
#no more needed
#lstBasesUnsloted.append(getattr(objCls,
cs__cls_unsloted__, objCls))
#
#no more needed
#dctAddInfo["tupBasesUnsloted"] = tuple( lstBasesUnsloted )
#add nonpersitent slots to the all slots
#
lstNonPersitentSlots.sort()
for iIndex in xrange(len(lstNonPersitentSlots)-2, -1, -1):
if lstNonPersitentSlots[iIndex] ==
lstNonPersitentSlots[iIndex+1]:
del lstNonPersitentSlots[iIndex+1]
#
#
tupObjectSlotsNoMore =
dctClassDefinition.get(const.cs__object_slots_nomore__, None)
if tupObjectSlotsNoMore is not None:
for sObjectSlotsNoMore in tupObjectSlotsNoMore:
try:
lstNonPersitentSlots.remove(sObjectSlotsNoMore)
except ValueError:
pass
#
#
#
lstSlots.extend(lstNonPersitentSlots)
#sort slots and remove doubles
lstSlots.sort()
for iIndex in xrange(len(lstSlots)-2, -1, -1):
s=intern(lstSlots[iIndex])
if s == lstSlots[iIndex+1]:
del lstSlots[iIndex+1]
else:
lstSlots[iIndex]=s
#
#
if tupObjectSlotsNoMore is not None:
for sObjectSlotsNoMore in tupObjectSlotsNoMore:
try:
lstSlots.remove(sObjectSlotsNoMore)
except ValueError:
pass
#
#
#
# non persitent and persitent are disjunct ==> persitent :=
slots - non persitenten
lstPersitentSlots=lstSlots[:]
for sKey in lstNonPersitentSlots:
lstPersitentSlots.remove(sKey)
#
# update class definition
dctClassDefinition[const.cs__all_slots__]=tuple(lstSlots)
dctClassDefinition[const.cs__all_nonpersitent_slots__]=tuple(lstNonPersitentSlots)
dctClassDefinition[const.cs__all_persitent_slots__]=tuple(lstPersitentSlots)
#
# normally there isn't a __slots__ - definition, but if we
cannot trust it
try:
dctClassDefinition.remove(const.cs__slots__)
except:
pass
dctDefinitionLocals = None # help gc
#
calculateSlots=classmethod(calculateSlots)
#
#
class ClBase(ClCustomBase):
""" base of all
"""
#
__metaclass__ = ClMetaClass
__object_slots__ = ()
#__object_slots__ = ("gna", "__weakref__", )
#__weakref__ = 1
#
def __new__(cls, *lstArgs, **kwArgs):
self = super(ClBase,
cls).__new__(getattr(cls,"__cls_sloted__",cls))
return self
#now __init__ is called
# / __new__
def __init__(self, *lstArgs, **kwArgs):
super(ClBase, self).__init__()
#
#