On Tuesday 14 August 2007 23:05:44 Michael Bayer wrote:
> On Aug 14, 2007, at 3:30 PM, [EMAIL PROTECTED] wrote:
> > databases/sqlite: (reflecttable)
> >   pragma_names is missing the BOOLEAN word/type -> nulltype
> >
> > btw why isn't each dialect-typeclass adding it's own entry to
> > that pragma_names, respectively to the colspecs ?
> > Or, each class to have those pragmaword and basetype, and the
> > dicts to be made by walking locals() if issubclass(..) ?
> >
> > Anyway, these dicts (the "grammar") should be automaticaly built
> > from available typeclasses...
>
> patches welcome....
>
> 
here 2 versions. 
One is simple, walking the module.namespace for 
issubclass(TypeEngine), expecting to find .pragma and .colspec in 
that class and collects them. The .colspec can probably be figured 
out from __bases__ (as in other version)

<pre>
def _issubclass( obj, klas):
    'fail/fool-proof issubclass() - works with ANY argument'
    from types import ClassType
    return isinstance(obj,(type,ClassType)) and issubclass(obj,klas)

def collect_colspecs( namespace):       #this can be moved out of here
    colspecs = {}
    pragma_names = {}
    for obj in namespace.itervalues():
        if _issubclass( kl, sqlalchemy.TypeEngine):
            c = getattr( kl, 'colspec', None) #or 'basetype'
            p = getattr( kl, 'pragma', None)  #or 'sqltype' or rawtype
            if c and p:
                colspec[c]=kl
                pragma_names[c]=kl
    return colspecs, pragma_names

class SLNumeric(sqltypes.Numeric):
    colspec,pragma = sqltypes.Numeric, 'NUMERIC'
    def get_col_spec(self):
        if self.precision is None:
            return "NUMERIC"
        else:
            return "NUMERIC(%(precision)s, %(length)s)"%self.__dict__

class SLInteger(sqltypes.Integer):
    colspec,pragma = sqltypes.Integer, 'INTEGER'
    def get_col_spec(self): return self.pragma
...
colspecs, pragma_names = collect_colspecs( locals() )

</pre>

========================

the other one uses metaclass, and .pragma is set up, and guesses 
colspec's abstract_type from __bases.

<pre>
class MetaDialectType( type):   #this can be moved out of here
    def __new__( metacls, name, bases, dict_):
        #find top-most abstract_type base 
        abstract_type = None
        for b in bases:
            #XXX is walk in depth needed? 
            #e.g. if allowed class SLInt2( SLInteger):...
            if issubclass( b, sqltypes.TypeEngine):
                abstract_type = b
                break
        assert abstract_type, 'class %s: cannot find any abstract \
            base type; do inherit from some sqlalchemy type' % name

        try:
            pragma = dict_['pragma']
        except KeyError:
            assert 0, 'class %s: cannot find any pragma' % name

        klas = type.__new__( metacls, name, bases, dict_)
        metacls.colspecs[ abstract_type] = klas
        metacls.pragma_names[ pragma]=klas
        return klas

class SLMetaDialectType( MetaDialectType):
    colspecs = {}
    pragma_names = {}

class SLNumeric( sqltypes.Numeric):
    __metaclass__ = SLMetaDialectType
    pragma = 'NUMERIC'
    def get_col_spec(self):
        r = self.pragma
        if self.precision is not None:
            r += "(%(precision)s, %(length)s)" % self.__dict__
        return r

class SLInteger( sqltypes.Integer):
    __metaclass__ = SLMetaDialectType
    pragma = 'INTEGER'
    def get_col_spec(self): return self.pragma

...
colspecs = SLMetaDialectType.colspecs
pragma_names = SLMetaDialectType.pragma_names 
</pre>

==========
There are 2 choices to make: 
 - walk locals() vs using metaclass
 - whether to touch get_col_spec()s 

i wanted to have everything specified only once.
Therefore the get_col_spec() redefinition. 
It can be:
 1 left as is, just adding a separate .pragma (no gain, 
consistency-wise, e.g. VARCHR in one place and VARCHAR in another)
 2 remade to use the self.pragma where equivalent (like 80% of 
places) - a lot of same code repeated
 3 put a default one in some base class for all dialect-types, e.g. 
DialectBaseType, which can be then used for filtering locals() or to 
bring metaclass
 4 created in the metaclass unless explicitly specified - this is most 
obscure.

btw i suggest some namechanges, colspec -> abstract_type and 
pragma_name -> rawdb_type; or something alike.

ciao
svil

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to