#$Id: statictype1.py,v 1.1 2004/03/18 17:21:51 sdobrev Exp $
#s.dobrev 2k4

from statictype_base import StaticTyper_factory_base

class StaticTyper_factory( StaticTyper_factory_base):
    """ inherit yourBaseType from StaticTyper with
        class attribute = type  for each required instance attribute-name.
        your-classes for actual instances must subclass one or more of these yourBaseTypes.
        Supports exact type check only - no default_value, auto_conv, validators etc.
    """

    def convert( klas, name, bases, adict):
        for base in bases:
            if isinstance( base, StaticTyper_factory):
                for a,t in base.__dict__.iteritems():
                    if isinstance( t, type):
                        if not a.startswith('__'):
                            adict[a] = _make_property( a,t)
    convert = classmethod( convert)
StaticTyper = StaticTyper_factory( 'StaticTyper', (), {})     #empty

#XXX may have become a class, so a_get, a_set are override-able
def _make_property( a, t):

    #!!!! local bind to current value(s);
    # else 'a' is bound at outer namespace, and references to last value there.
    # Well when not in a separate function.
    attr = a
    base_type = t

    def a_get( me):
        if me._debug_props_get_set: print 'getattr', attr, base_type
        return getattr( me._props, attr)

    def a_set( me, v):
        if me._debug_props_get_set: print 'setattr', attr,v, base_type
        if type(v) is not base_type:
            raise TypeError, 'set attribute "%s" of type %s with value %r of type %s' % (attr, base_type, v, type(v) )
        return setattr( me._props, attr, v)

    return property( a_get, a_set)


#########

if __name__=='__main__':

    class BozaType( StaticTyper):
        x = int
        y = float

    class boza( BozaType):
        #x = 1
        #y = 'a'
        #z = '3'
        pass

    a = boza()

    print '----'
    try: print a.x
    except :
        import traceback
        traceback.print_exc(1)

    print '----'
    a.x = 2 #ok
    print 'x ', a.x

    print '----'
    try: a.x = '2'
    except :
        import traceback
        traceback.print_exc(1)


    print '----'
    try: a.y = 500
    except :
        import traceback
        traceback.print_exc(1)


# vim:ts=4:sw=4:expandtab
