Re: [sqlalchemy] Mapping dictionaries with string keys and record values
Hi Michael. On Sun, 2010-04-25 at 22:32 -0400, Michael Bayer wrote: You should be able to roll this yourself as a custom dictlike collection class . That's what I did :-) I wrote mostly to share my code and to suggest that this should be available out of the box. sorry, it seems you've done that already. I'm surprised the existing attribute_mapped_collection doesn't do this already ? I was surprised as well. well, it doesn't. It should, and maybe should raise an error if the two values don't match. It doesn't make much sense to add another collection class to do what the first one should. Agreed. I'm sure you noticed that you can remove the repetition by working the other way, i.e.: item.note.set(Note(key=color, value=blue, desc=This should be blue because)) item.note.set(Note(key=shape, value=rectangular)) Indeed, although I find it unintuitive that set actually does an append/insert/add operation. Apart from that, I try to keep the mapping code and the data objects (which carry application logic) separate in case we ever want to use a non-SQL data backend (NoSQL DB, ZODB, ...). So usually, there is no set method on item.notes and there is no key property in the Note class (it's added by the mapper as _key). also, never do this: class Note(object): def __init__(self, **args): self.__dict__.update(args) That's not production code. I just added it to get initialization in one line. you bypass all of SQLAlchemy's history tracking logic. do this instead: class Note(object): def __init__(self, **args): for k, v in args.items(): setattr(self, k, v) I usually name the possible keyword arguments explicitly as the output of help(Note) is otherwise quite unhelpful. Thanks for your reply and the remarks! Do you plan to extend attribute_mapped_collection to update the key like in my example? Be aware that this approach also has it's downside. For example, assigning item2 = Item() item2.notes['color'] = item.notes['color'] will not work contrary to what one might expect (it generated a conflict on the id column). The solution is to have the target collection copy the assigned object if it has a key already. But that might be too much magic to be easy to understand. So I think, the automatic key update should be an option. Greetings, 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.
Re: [sqlalchemy] Mapping dictionaries with string keys and record values
Torsten Landschoff wrote: Thanks for your reply and the remarks! Do you plan to extend attribute_mapped_collection to update the key like in my example? here's some things to note on that: 1. I'm not sure why it wasn't that way already, and I'd want to hear from Jason Kirtland, its author, on if we are missing something or otherwise whats up. I have a vague notion that there was a reason for this, or maybe not. 2. I wonder if there's a way to make this happen more deeply than within setattr(). Like the collection internals would include an event to operate upon the target object that includes the other args from the collection decorator. 3. corresponding delete() event. Set the attribute on the replaced object to None ? that seems potentially surprising ? Be aware that this approach also has it's downside. For example, assigning item2 = Item() item2.notes['color'] = item.notes['color'] will not work contrary to what one might expect (it generated a conflict on the id column). The solution is to have the target collection copy the assigned object if it has a key already. But that might be too much magic to be easy to understand. the target can only be in one collection at a time so I would think item2's id wins. its a primary key switch. -- 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.
Re: [sqlalchemy] Mapping dictionaries with string keys and record values
On Mon, Apr 26, 2010 at 8:24 AM, Michael Bayer mike...@zzzcomputing.com wrote: Torsten Landschoff wrote: Thanks for your reply and the remarks! Do you plan to extend attribute_mapped_collection to update the key like in my example? here's some things to note on that: 1. I'm not sure why it wasn't that way already, and I'd want to hear from Jason Kirtland, its author, on if we are missing something or otherwise whats up. I have a vague notion that there was a reason for this, or maybe not. It's not something that can be easily solved in the general case with the current API. The mapped collections use a 'keyfunc' to figure out the dictionary key for loaded instances, for example 'operator.attrgetter(name)' for attribute_mapped_collection(name). Mechanically reversing that logic in a setting operation sounds pretty hard to me, but perhaps if we allowed an 'assignfunc' function to be supplied that would do the trick. Internally, the collection code would call it during a dict['key'] = instance assignment operation, maybe passing just the key value and the instance: def assignfunc(key, instance): instance.name = key For highly constrained types like the attribute- and column-mapped collections, these functions would be easy to generate. A good test for the feature would be a mapped collection that maps a tuple of attributes, such as one created by attribute_mapped_collection(('x', 'y')). Assigning collection[1, 2] = instance should assign both instance.x and instance.y in that case. 2. I wonder if there's a way to make this happen more deeply than within setattr(). Like the collection internals would include an event to operate upon the target object that includes the other args from the collection decorator. I have a hunch this is only meaningful for mapped collections- mutations like list_collection[2:5] would be difficult to translate and I'm not sure what information one would want to capture there. Worth a look though. -- 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.
Re: [sqlalchemy] Mapping dictionaries with string keys and record values
On Mon, 2010-04-26 at 11:24 -0400, Michael Bayer wrote: 2. I wonder if there's a way to make this happen more deeply than within setattr(). Like the collection internals would include an event to operate upon the target object that includes the other args from the collection decorator. Sorry, I was unable to follow you here. You think there should be an event generated to be handled by the collection internals? What arguments of the decorator are you talking about? 3. corresponding delete() event. Set the attribute on the replaced object to None ? that seems potentially surprising ? In my case it did not matter much since the object is owned by the mapped collection. So after the delete, it is garbage collected anyway. As the client code does not know about the key attribute, it would not notice the change anyway even if it still has a pointer. For me this is the same as some code still having a reference to a value that was stored in a dict. If you remove it from the dictionary, you may still keep a reference but it is not reachable anymore from the dict. To make this match with the database, I am using cascade=delete-orphan. item2 = Item() item2.notes['color'] = item.notes['color'] will not work contrary to what one might expect (it generated a conflict on the id column). The solution is to have the target collection copy the assigned object if it has a key already. But that might be too much magic to be easy to understand. the target can only be in one collection at a time so I would think item2's id wins. its a primary key switch. Can't it belong to two collections if there is a secondary join? In plain Python code, both mappings would have a reference to the same object. Greetings, 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.
Re: [sqlalchemy] Mapping dictionaries with string keys and record values
On Mon, 2010-04-26 at 11:08 -0700, jason kirtland wrote: 1. I'm not sure why it wasn't that way already, and I'd want to hear from Jason Kirtland, its author, on if we are missing something or otherwise whats up. I have a vague notion that there was a reason for this, or maybe not. It's not something that can be easily solved in the general case with the current API. The mapped collections use a 'keyfunc' to figure out the dictionary key for loaded instances, for example 'operator.attrgetter(name)' for attribute_mapped_collection(name). Mechanically reversing that logic in a setting operation sounds pretty hard to me, but perhaps if we allowed an 'assignfunc' function to be supplied that would do the trick. Internally, the collection I agree. The idea of an assignfunc crossed my mind as well. Greetings, 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.
Re: [sqlalchemy] Mapping dictionaries with string keys and record values
On Apr 25, 2010, at 7:31 PM, Michael Bayer wrote: On Apr 25, 2010, at 1:38 PM, Torsten Landschoff torsten.landsch...@dynamore.de wrote: Hi everybody. After reading the documentation on dictionary based collections at http://www.sqlalchemy.org/docs/mappers.html#dictionary-based-collections, I am wondering if I am the only one who things that this code is intuitive: item = Item() item.notes['color'] = Note('color', 'blue') print item.notes['color'] I'd rather write item.notes['color'] = Note('blue') That the key is stored with the value should be an implementation detail I think. I extended sqlalchemy.orm.collections.MappedCollection with a few lines to implement this (attached). Shouldn't something like is be included with SQLAlchemy? Or is this a bad id You should be able to roll this yourself as a custom dictlike collection class . sorry, it seems you've done that already. I'm surprised the existing attribute_mapped_collection doesn't do this already ? Greetings, 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. dictmapping.py -- 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.
Re: [sqlalchemy] Mapping dictionaries with string keys and record values
On Apr 25, 2010, at 10:18 PM, Michael Bayer wrote: On Apr 25, 2010, at 7:31 PM, Michael Bayer wrote: On Apr 25, 2010, at 1:38 PM, Torsten Landschoff torsten.landsch...@dynamore.de wrote: Hi everybody. After reading the documentation on dictionary based collections at http://www.sqlalchemy.org/docs/mappers.html#dictionary-based-collections, I am wondering if I am the only one who things that this code is intuitive: item = Item() item.notes['color'] = Note('color', 'blue') print item.notes['color'] I'd rather write item.notes['color'] = Note('blue') That the key is stored with the value should be an implementation detail I think. I extended sqlalchemy.orm.collections.MappedCollection with a few lines to implement this (attached). Shouldn't something like is be included with SQLAlchemy? Or is this a bad id You should be able to roll this yourself as a custom dictlike collection class . sorry, it seems you've done that already. I'm surprised the existing attribute_mapped_collection doesn't do this already ? well, it doesn't. It should, and maybe should raise an error if the two values don't match. It doesn't make much sense to add another collection class to do what the first one should. I'm sure you noticed that you can remove the repetition by working the other way, i.e.: item.note.set(Note(key=color, value=blue, desc=This should be blue because)) item.note.set(Note(key=shape, value=rectangular)) also, never do this: class Note(object): def __init__(self, **args): self.__dict__.update(args) you bypass all of SQLAlchemy's history tracking logic. do this instead: class Note(object): def __init__(self, **args): for k, v in args.items(): setattr(self, k, v) Greetings, 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. dictmapping.py -- 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. -- 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.