[sqlalchemy] Re: dictionaries collection_class

2007-06-18 Thread Ron

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

2007-06-18 Thread jason kirtland

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

2007-06-16 Thread Ron

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

2007-06-16 Thread Ron

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

2007-06-16 Thread jason kirtland

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

2007-06-12 Thread sdobrev

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

2007-06-12 Thread Ron


 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

2007-06-12 Thread jason kirtland

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

2007-06-12 Thread Ron


 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
-~--~~~~--~~--~--~---