On Nov 22, 2010, at 6:17 PM, Torsten Landschoff wrote:

> Hi again!
> 
> Sorry for all the questions, here is another one.
> 
> What I really would like to do is to read a chunk of data for a mapped
> instance and disseminate that into a number of attributes (not the usual
> one column <-> one attribute mapping). This could easily be done using
> an orm.reconstructor.
> 
> Writing to that data triggers an internal flag which I would like the
> ORM to take into account to detect that the instance is dirty (even
> better: signal the ORM at the same time that it is dirty). During flush,
> I would like to have a orm.deconstructor ;-) method run that collects
> the data from the instance attributes for flushing it to the database.

The simplest way to approach not using mutable types is to assign a new value 
to the attribute.   So if you copied im.image = im.image.update(new data), that 
results in just a single comparison at flush time.   If you expire() the 
attribute first, then the comparison is against NO_VALUE so would avoid a long 
comparison.    You could make StoredImage.image a proxy object of some kind 
that replaces the contents of StoredImage._image, the real object, whenever an 
event occurs.   Or, for more efficiency, StoredImage.image just adds itself to 
a set() somewhere when a change is detected, and stores the changes given in an 
internal dictionary - then you do a SessionExtension.before_flush(), look in 
the set() for all the StoredImages, then write their _image attribute with 
their changes.





> 
> I am far from having this implemented. I tried starting with a simple
> example using the MutableType mixin:
> 
> from sqlalchemy import *
> from sqlalchemy.orm import *
> from sqlalchemy.types import TypeDecorator, MutableType
> import Image
> import ImageEnhance
> import numpy
> from cStringIO import StringIO
> 
> engine = create_engine("sqlite:////tmp/test.db", echo=True)
> 
> class _ImageType(TypeDecorator):
>    impl = LargeBinary
>    def process_bind_param(self, value, dialect):
>        im = Image.fromarray(value)
>        fakefile = StringIO()
>        im.save(fakefile, 'png')
>        return fakefile.getvalue()
>    def process_result_value(self, value, dialect):
>        fakefile = StringIO(value)
>        return numpy.array(Image.open(fakefile))
> 
> class ImageType(MutableType, _ImageType):
>    def copy_value(self, value):
>        print "creating a copy"
>        return numpy.copy(value)
>    def compare_values(self, x, y):
>        print "compare: {0} vs. {1}".format(id(x), id(y))
>        result = (x == y).all()
>        print "result: {0}".format(result)
>        return result
> 
> metadata = MetaData()
> image_table = Table("images", metadata,
>    Column("id", Integer, primary_key=True),
>    Column("image", ImageType))
> metadata.create_all(engine)
> 
> class StoredImage(object):
>    def __init__(self, fname):
>        self.image = numpy.array(Image.open(fname))
> 
> mapper(StoredImage, image_table)
> 
> Session = sessionmaker(engine)
> session = Session()
> 
> images = session.query(StoredImage).all()
> if images:
>    for im in images:
>        data = im.image
>        for row in xrange(len(data)):
>            for col in xrange(len(data[0])):
>                r, g, b = data[row][col]
>                data[row][col] = b, g, r
>    # Image.fromarray(im.image).show()
>    print "dirty", session.dirty
> else:
>    im = StoredImage("/usr/share/backgrounds/Daisy.jpg")
>    session.add(im)
> session.commit()
> 
> 
> This lacks almost everything that I really want:
> 
> o data is still in a single attribute
> o no dirty flag handling, but full content comparison
> o the comparison is run each time the ORM looks up its dirty instances.
> 
> 
> Just pondering...
> 
> Torsten
> 
> -- 
> DYNAmore Gesellschaft fuer Ingenieurdienstleistungen mbH
> Torsten Landschoff
> 
> Office Dresden
> Tel: +49-(0)351-4519587
> Fax: +49-(0)351-4519561
> 
> mailto:torsten.landsch...@dynamore.de
> http://www.dynamore.de
> 
> Registration court: Mannheim, HRB: 109659, based in Karlsruhe,
> Managing director:  Prof. Dr. K. Schweizerhof, Dipl.-Math. U. Franz
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To post to this group, send email to sqlalch...@googlegroups.com.
> To unsubscribe from this group, send email to 
> sqlalchemy+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/sqlalchemy?hl=en.
> 

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

Reply via email to