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:[email protected]
> 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 [email protected].
> 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.
>
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
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.