def table_namer( klas, short =False): 'table auto-naming' r = getattr_local_instance_only( klas, 'DBCOOK_dbname', None) or klas.__name__ if short: r = getattr_local_instance_only( klas, 'DBCOOK_dbname_short', None) or r if isinstance( r, classmethod): r = klas.DBCOOK_dbname() return r
def mappable(me, klas): if klas and issubclass(klas, me.base_klas) and klas is not me.base_klas: DBCOOK_no_mapping = getattr_local_instance_only( klas, 'DBCOOK_no_mapping', None) if not DBCOOK_no_mapping: return True return False
def subclasses4db_in(klasi, *args, **kargs): #klasi= locals() or list exclude_ = kargs.pop('exclude_', True) return [ c for c in subclasses_in(klasi, *args, **kargs) if not getattr_local_instance_only(c, 'DBCOOK_no_mapping', False) and not (exclude_ and c.__name__.startswith('_')) ]
def base4table_inheritance( me, klas): base = me.base( klas) inheritype = table_inheritance_types.DEFAULT if base: inheritype = getattr( klas, 'DBCOOK_inheritance', None) #local: inheritype = getattr_local_instance_only( klas, 'DBCOOK_inheritance_local', inheritype) or table_inheritance_types.DEFAULT try: inheritype = table_inheritance_types._all[ inheritype] except KeyError, e: assert 0, '%(klas)s: unknown DBCOOK_inheritance=%(inheritype)r' % locals()
def __getattr_local_or_nonmappable_base( me, klas, attr, *default): # allow non-mapped classes to declare certain DBCOOK_xxxxxxx for their children # TODO see below iter_attr_local klas0 = klas for klas in klas.__mro__: r = getattr_local_instance_only( klas, attr, _NOTFOUND) if r is not _NOTFOUND: if klas is not klas0 and me.mappable( klas): break #not found #XXX tricky: klas.__dict__['xyz'] is not klas.xyz, esp. classmethods/descriptors #this is the only place so far, it is safe to getattr return getattr( klas0, attr) if default: return default[0] raise AttributeError, 'no attr %(attr)s in %(klas)s' % locals()
def base4table_inheritance(me, klas): base = me.base(klas) inheritype = table_inheritance_types.DEFAULT if base: inheritype = getattr(klas, 'DBCOOK_inheritance', None) #local: inheritype = getattr_local_instance_only( klas, 'DBCOOK_inheritance_local', inheritype) or table_inheritance_types.DEFAULT try: inheritype = table_inheritance_types._all[inheritype] except KeyError, e: assert 0, '%(klas)s: unknown DBCOOK_inheritance=%(inheritype)r' % locals( )
def __getattr_local_or_nonmappable_base(me, klas, attr, *default): # allow non-mapped classes to declare certain DBCOOK_xxxxxxx for their children # TODO see below iter_attr_local klas0 = klas for klas in klas.__mro__: r = getattr_local_instance_only(klas, attr, _NOTFOUND) if r is not _NOTFOUND: if klas is not klas0 and me.mappable(klas): break #not found #XXX tricky: klas.__dict__['xyz'] is not klas.xyz, esp. classmethods/descriptors #this is the only place so far, it is safe to getattr return getattr(klas0, attr) if default: return default[0] raise AttributeError, 'no attr %(attr)s in %(klas)s' % locals()
def _order_Statics( klas, items =False): r = getattr_local_instance_only( klas, '_order_Statics_cache', None) #cleanup? if r is None: r = klas._order_Statics_cache = [] order = klas._order_maker( klas) _order_Statics_gettype = klas._order_Statics_gettype for k in order: try: typ = _order_Statics_gettype( klas, k) except KeyError: continue r.append( (k,typ) ) for k,typ in r: if items: yield k,typ else: yield k
def iter_attr( me, klas, attr_base_klas =None, local =False, denote_nonmappable_origin =False, dbg =False, **kargs4attrtypes ): 'sorted' base_klas, inheritype = me.base4table_inheritance( klas) is_joined_table = (inheritype == table_inheritance_types.JOINED) dir_base_klas = is_joined_table and dir( base_klas) or () #joined_table: subclass' tables consist of extra attributes -> joins for k,typ in sorted( me.reflector.attrtypes( klas, **kargs4attrtypes ).iteritems()): if attr_base_klas and not isinstance( typ, attr_base_klas): continue if local and k in dir_base_klas: if dbg: print ' inherited:', k continue if denote_nonmappable_origin: nonmappable_origin = getattr_local_instance_only( klas, k, _NOTFOUND) is _NOTFOUND yield k,typ, nonmappable_origin else: yield k,typ
def iter_attr(me, klas, attr_base_klas=None, local=False, denote_nonmappable_origin=False, dbg=False, **kargs4attrtypes): 'sorted' base_klas, inheritype = me.base4table_inheritance(klas) is_joined_table = (inheritype == table_inheritance_types.JOINED) dir_base_klas = is_joined_table and dir(base_klas) or () #joined_table: subclass' tables consist of extra attributes -> joins for k, typ in sorted( me.reflector.attrtypes(klas, **kargs4attrtypes).iteritems()): if attr_base_klas and not isinstance(typ, attr_base_klas): continue if local and k in dir_base_klas: if dbg: print ' inherited:', k continue if denote_nonmappable_origin: nonmappable_origin = getattr_local_instance_only( klas, k, _NOTFOUND) is _NOTFOUND yield k, typ, nonmappable_origin else: yield k, typ
def subclasses4db_in( klasi, *args,**kargs): #klasi= locals() or list exclude_ = kargs.pop('exclude_',True) return [ c for c in subclasses_in( klasi, *args, **kargs) if not getattr_local_instance_only( c, 'DBCOOK_no_mapping', False) and not (exclude_ and c.__name__.startswith( '_')) ]
def needs_id( klas): return getattr_local_instance_only( klas, 'DBCOOK_needs_id', None)
def has_instances( me, klas): #if not me.mappable( klas): return False if len( me.subklasi[ klas]) == 1: return True #leaf DBCOOK_has_instances = getattr_local_instance_only( klas, 'DBCOOK_has_instances', None) return bool( DBCOOK_has_instances)
def mappable( me, klas): if klas and issubclass( klas, me.base_klas) and klas is not me.base_klas: DBCOOK_no_mapping = getattr_local_instance_only( klas, 'DBCOOK_no_mapping', None) if not DBCOOK_no_mapping: return True return False
def needs_id(klas): return getattr_local_instance_only(klas, 'DBCOOK_needs_id', None)
def has_instances(me, klas): #if not me.mappable( klas): return False if len(me.subklasi[klas]) == 1: return True #leaf DBCOOK_has_instances = getattr_local_instance_only( klas, 'DBCOOK_has_instances', None) return bool(DBCOOK_has_instances)