[sqlalchemy] Re: dictionaries collection_class
Ok, I applied that change to the version I'm using (0.3.8). That fixed it. But I think I stumbled on another bug/inconcistancy. If I tried to str/repr obj.attr it failed. I looked around the code and this fix seemed to work, but I'm not sure if it fits in with how the class is intended to function. In /sqlalchemy/ext/associationproxy.py in class class _AssociationDict(object) change def items(self): return [(k, self._get(self.col[k])) for k in self] to def items(self): return [(k, self._get(self.col[k])) for k in self.keys()] Does that make sense? Or is the problem deeper in the code? It seems to go along with what you said earlier about how the iteration was made to work like an instrumentedlist. -Ron On Jun 16, 3:07 pm, jason kirtland [EMAIL PROTECTED] wrote: Ron wrote: Now I'm having trouble with updating values in AttributeDict: so obj.attrs['key'] = 'somevalue' (works) obj.attrs['key'] = 'newvalue'(second one doesn't work) I get this error: File /usr/local/lib/python2.4/site-packages/SQLAlchemy-0.3.8- py2.4.egg/sqlalchemy/orm/mapper.py, line 679, in init raise e TypeError: lambda() takes exactly 2 arguments (3 given) Any more ideas? -Ron Fixed in 2739. (a silly typo) -jek --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: dictionaries collection_class
Ron wrote: Ok, I applied that change to the version I'm using (0.3.8). That fixed it. But I think I stumbled on another bug/inconcistancy. If I tried to str/repr obj.attr it failed. [...] Does that make sense? Or is the problem deeper in the code? It seems to go along with what you said earlier about how the iteration was made to work like an instrumentedlist. Yeah, that's the funky iteration in effect. __iter__ on the proxy was changed to be fully dict-like in the trunk and for 0.3.9. The matching change to the underlying InstrumentedDict iterator won't be in until 0.4. -jek --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: dictionaries collection_class
Now I'm having trouble with updating values in AttributeDict: so obj.attrs['key'] = 'somevalue' (works) obj.attrs['key'] = 'newvalue'(second one doesn't work) I get this error: File /usr/local/lib/python2.4/site-packages/SQLAlchemy-0.3.8- py2.4.egg/sqlalchemy/orm/mapper.py, line 679, in init raise e TypeError: lambda() takes exactly 2 arguments (3 given) Any more ideas? -Ron On Jun 12, 2:52 pm, jason kirtland [EMAIL PROTECTED] wrote: Ron wrote: Nevermind. I see what I was doing. In much of my code it worked fine, just like a dictionary. But in another part of my code I do: for i in self.attrs: ...blah which works like a list. I remember when I saw the __iter__ implementation requirement noting that that may be confusing. That's a side-effect of the way dict collections are managed by the InstrumentedList. The iterator behavior will be over keys as you'd expect in 0.4, both on dict collection classes and in dict-based association proxies. I think the 0.3 association proxy does that only to be consistent with the underlying attribute's iterator, but I don't see any strong reason to keep that behavior in 0.3, especially as association dict support is pretty much brand new. Making the assoc proxy's iterator truly dict-like can go in 0.3.9 if there's call. Cheers, Jason --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: dictionaries collection_class
Now I'm having trouble with updating values in AttributeDict: so obj.attrs['key'] = 'somevalue' (works) obj.attrs['key'] = 'newvalue'(second one doesn't work) I get this error: File /usr/local/lib/python2.4/site-packages/SQLAlchemy-0.3.8- py2.4.egg/sqlalchemy/orm/mapper.py, line 679, in init raise e TypeError: lambda() takes exactly 2 arguments (3 given) Any more ideas? -Ron On Jun 12, 2:52 pm, jason kirtland [EMAIL PROTECTED] wrote: Ron wrote: Nevermind. I see what I was doing. In much of my code it worked fine, just like a dictionary. But in another part of my code I do: for i in self.attrs: ...blah which works like a list. I remember when I saw the __iter__ implementation requirement noting that that may be confusing. That's a side-effect of the way dict collections are managed by the InstrumentedList. The iterator behavior will be over keys as you'd expect in 0.4, both on dict collection classes and in dict-based association proxies. I think the 0.3 association proxy does that only to be consistent with the underlying attribute's iterator, but I don't see any strong reason to keep that behavior in 0.3, especially as association dict support is pretty much brand new. Making the assoc proxy's iterator truly dict-like can go in 0.3.9 if there's call. Cheers, Jason --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: dictionaries collection_class
Ron wrote: Now I'm having trouble with updating values in AttributeDict: so obj.attrs['key'] = 'somevalue' (works) obj.attrs['key'] = 'newvalue'(second one doesn't work) I get this error: File /usr/local/lib/python2.4/site-packages/SQLAlchemy-0.3.8- py2.4.egg/sqlalchemy/orm/mapper.py, line 679, in init raise e TypeError: lambda() takes exactly 2 arguments (3 given) Any more ideas? -Ron Fixed in 2739. (a silly typo) -jek --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: dictionaries collection_class
the legal way is the association_proxy and family. here another shorter ... a hack: i did have similar need - obj.somerelation.append( left=.., right=..), so i did monkeypatch the InstrumentedList's append to use the item returned from collection's append - def append( self, *args, **kwargs): item = self._data_appender( *args,**kwargs) self._InstrumentedList__setrecord( item) #private __setrecord; was _before_ _data_appender sqlalchemy.orm.attributes.InstrumentedList.append = append and use my own collection which creates the association object from append's keywordargs, then factory for it and give that to collection_class= of relation() class Association: 'base for all assoc_klas' class MyCollection( list): factory = None def append( me, obj =_Relation, **kargs): if obj is _Relation:#just marker for notset obj = me.factory( **kargs) list.append( me, obj) return obj @classmethod def myCollectionFactory( klas): m = Association.MyCollection() m.factory = klas#the assoc-obj-type return m mapper ( ... relation( collection_class = assoc_klas.myCollectionFactory ) ) --- u'll have to do it over __setitem__. have fun. svil On Tuesday 12 June 2007 21:26:52 Ron wrote: I have an object that has a relation to an Attributes table. The Attributes table is just key/value pairs with a pointer to the object in the main table. I'd like to make the use of my object very simple by exposing these object attributes as a dictionary. So, I'd like to be able to do this: obj.attrs['foo'] = 'a' instead of obj.attrs.append(Attribute('foo', 'a')) The documentation has an example for using the collection_class argument to relation() but in order to make things actually work as above I think I'd need to override __setitem__ but that sqlalchemy doesn't seem to let me do that. What am I missing? -Ron --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: dictionaries collection_class
Using the association_proxy extension in combination with your dictionary collection class is an easy way to get this kind of simplified access. Assuming your Attribute's value is in a property called 'value', you can set up simple dict access like so: class Obj(object): attrs = association_proxy('_attrs', 'value') mapper(Obj, ..., properties = { '_attrs': relation(Attribute, collection_class=your_dict_class) } obj.attrs['foo'] = 'a' -jek When I try the above I get this error at flush time: InvalidRequestError: Class 'str' entity name 'None' has no mapper associated with it Here is my dictionary collection_class: class AttributeDictNEW(dict): My Attribute Dict def append(self, item): super(AttributeDictNEW, self).__setitem__(item.name, item) def test__iter__(self): return iter(self.values()) def test__getitem__(self, name): return super(AttributeDictNEW, self).__getitem__(name).value def __setitem__(self, name, value): if not isinstance(value, Attribute): newattr = Attribute(name, str(value)) self.append(newattr) else: self.append(value) The test__ functions are named such to get out of the way of the parent class's functions while testing. I may be misunderstanding how an association_proxy works. -Ron --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: dictionaries collection_class
Ron wrote: When I try the above I get this error at flush time: InvalidRequestError: Class 'str' entity name 'None' has no mapper associated with it Here is my dictionary collection_class: class AttributeDictNEW(dict): My Attribute Dict def append(self, item): super(AttributeDictNEW, self).__setitem__(item.name, item) def test__iter__(self): return iter(self.values()) def test__getitem__(self, name): return super(AttributeDictNEW, self).__getitem__(name).value def __setitem__(self, name, value): if not isinstance(value, Attribute): newattr = Attribute(name, str(value)) self.append(newattr) else: self.append(value) The test__ functions are named such to get out of the way of the parent class's functions while testing. The association proxy will take care of Attribute construction for you, so you can get away with just: class AttributeDictNEW(dict): def append(self, item): self[item.key] = item def __iter__(self): return self.itervalues() However, newattr = Attribute(name, str(value)) For the stringification of values on construction, you can either do that in Attribute's __init__ or supply a creator function to the association proxy: stringy_attr = lambda name, value: Attribute(name, str(value)) ... attrs = association_proxy('_attrs', 'value', creator=stringy_attr) -jek --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: dictionaries collection_class
The association proxy will take care of Attribute construction for you, so you can get away with just: class AttributeDictNEW(dict): def append(self, item): self[item.key] = item def __iter__(self): return self.itervalues() So now I if I try to get something from the dict: obj.attr['foo'] I get this error: KeyError: schema.Attribute object at 0xb78a8e0c ok, so it looks like something is turning 'foo' into an Attribute. Fine, so I add this to the AttributeDictNEW: def __getitem__(self, item): return super(AttributeDictNEW, self).__getitem__(item.name) But I get: return super(AttributeDictNEW, self).__getitem__(item.name) AttributeError: 'str' object has no attribute 'name' if I do a sys.stderr.write(str(type(item))) before the return it outputs this: class 'schema.Attribute' item is an Attribute, but the error indicates it's a str that doesn't have a 'name' member variable. So I'm totally confused. -Ron --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---