On Oct 4, 2010, at 12:50 PM, Nikolaj wrote:

> Hey,
> 
> I had trouble deepcopying model instances that use attribute mapped
> collection classes. I'm aware that copying an instance implies a
> certain use case with a better solution - I accidentally hit this
> error when I had an instance as an attribute on an object I was
> deepcopy()ing. The following example fails with "TypeError: attrgetter
> expected 1 arguments, got 0".
> 
> Is there a way to remedy the situation a bit so the deepcopy doesn't
> fail so spectacularly?

well deepcopy() isn't something we have supported right now, since it wont work 
in any case - you really don't want to copy the "_sa_instance_state" attribute 
along, and special rules need to take place when that attribute is copied.     
There's probably lots of gotchas which lead us to not have the resources to 
support "deepcopy()" as a first class use case right now.

The usual method to copy state is to use session.merge(), which will copy the 
ORM-persisted state of an object while also providing reasonable defaults 
involving state management.

Supporting deepcopy() would mostly involve porting the various 
__setstate__/__getstate__ hooks, which are on _sa_instance_state, the 
association proxy attributes, and possibly elsewhere, to the system that 
deepcopy() expects (assuming the approaches are roughly compatible).   At the 
moment, you can effectively deepcopy the object by dumping/loading with pickle, 
i.e. dumps()/loads().   
  


> 
> Thanks,
> 
> N
> 
> from sqlalchemy import create_engine, Column, ForeignKey
> from sqlalchemy.ext.declarative import declarative_base
> from sqlalchemy.orm import scoped_session, sessionmaker, relationship
> from sqlalchemy.orm.collections import attribute_mapped_collection
> from sqlalchemy.types import Integer, String
> 
> import copy
> 
> engine = create_engine('sqlite:///:memory:', echo=True)
> Base = declarative_base(bind=engine)
> Session = scoped_session(sessionmaker(bind=engine))
> 
> class Note(Base):
>    __tablename__ = 'notes'
>    keyword = Column(String, primary_key=True)
>    item_name = Column(String, ForeignKey('items.name'))
> 
> class Item(Base):
>    __tablename__ = 'items'
>    name = Column(String, primary_key=True)
> 
>    notes = relationship(Note,
> collection_class=attribute_mapped_collection('keyword'))
> 
> Base.metadata.create_all()
> 
> item = Item(name='Foo')
> 
> note = Note(keyword='Bar')
> item.notes.set(note)
> 
> Session.commit()
> 
> assert item.notes['Bar'] is note
> 
> copy.deepcopy(note) # Passes
> copy.deepcopy(item) # Fails
> 
> -- 
> 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.

Reply via email to