Changeset 798 for trunk/

Jan 30, 2016, 2:55:18 PM (3 years ago)

Port type cache and typecasting from pgdb to pg

So far, the typecasting in the classic module was been only done by
the C extension module and was not extensible through typecasting
functions in Python. This has now been made extensible by adding
a cast hook to the C extension module which has been hooked up to
a new type cache object that holds information on the types and the
associated typecast functions. All of this works very similar to the
pgdb module now, except that the basic types are still handled by
the C extension module and the Python typecast functions are only
called via the hook for types which are not supported internally.

Also added tests and a chapter on the type cache in the documentation,
and cleaned up the error messages in the C extension module.

1 edited


  • trunk/

    r797 r798  
     147def cast_int2vector(value):
     148    """Cast an int2vector value."""
     149    return [int(v) for v in value.split()]
    147152class Typecasts(dict):
    148153    """Dictionary mapping database types to typecast functions.
    150     The cast functions must accept one Python object as an argument and
    151     convert that object to a string representation of the corresponding type
    152     in the database.  The Python None object is always converted to NULL,
    153     so the cast functions can assume they never get passed None as argument.
    154     However, they may get passed an empty string or a numeric null value.
     155    The cast functions get passed the string representation of a value in
     156    the database which they need to convert to a Python object.  The
     157    passed string will never be None since NULL values are already be
     158    handled before the cast function is called.
    155159    """
    165169        'float4': float, 'float8': float,
    166170        'numeric': Decimal, 'money': cast_money,
     171        'int2vector': cast_int2vector,
    167172        'anyarray': cast_array, 'record': cast_record}
    172177        Note that this class never raises a KeyError,
    173         but return None when no special cast function exists.
     178        but returns None when no special cast function exists.
    174179        """
     180        if not isinstance(typ, str):
     181            raise TypeError('Invalid type: %s' % typ)
    175182        cast = self.defaults.get(typ)
    176183        if cast:
    334341            oid = key
    335342        else:
    336             if not '.' in key and not '"' in key:
     343            if '.' not in key and '"' not in key:
    337344                key = '"%s"' % key
    338345            oid = "'%s'::regtype" % self._escape_string(key)
    386393        self._typecasts.reset(typ)
    388     def typecast(self, typ, value):
     395    def typecast(self, value, typ):
    389396        """Cast the given value according to the given database type."""
    390397        if value is None:
    655662            raise _db_error(str(err))
    656663        typecast = self.type_cache.typecast
    657         return [self.row_factory([typecast(typ, value)
     664        return [self.row_factory([typecast(value, typ)
    658665            for typ, value in zip(self.coltypes, row)]) for row in result]
Note: See TracChangeset for help on using the changeset viewer.