On 06/03/2010 02:33 PM, Az wrote:
> Firstly, apologies if I'm demanding too much but basically I'm quite a
> beginner at Python programming and this is for a University project,
> which is why I'm keen to get this done (due in a few days!). So I hope
> you won't mind me asking some questions that may seem really basic.
>
>   
>> deepcopy has issues because SQLAlchemy places extra information on your 
>> objects, i.e. an _sa_instance_state attribute, that you dont want in your
>> copy.  You *do* however need one to exist on your object.  Therefore 
>> deepcopy is not supported right now by SQLAlchemy ORM objects.
>>     
>   
>> There are ways to manually blow away the old _sa_instance_state and put a 
>> new one on the object, but the most straightforward is to make a new
>> object with __init__() and set up the attributes that are significant, 
>> instead of doing a full deep copy.
>>     
> Could you explain what you mean by creating a new object with
> __init__() and setting up the attributes? Would this be a new class
> that isn't mapped using SQLA?
>
>   

He just means creating a new instance of your mapped class and settings
its attributes manually, e.g.:

def copy(self):
   copy = MyMappedClass()
   copy.attr1 = self.attr1
   copy.attr2 = self.attr2
   return copy

>> if you do really want to use deepcopy, you'd have to implement 
>> __deepcopy__() on your objects and ensure that a new _sa_instance_state is 
>> set up,
>> there are functions in sqlalchemy.orm.attributes which can help with that.   
>>  This *should* be made an official SQLA recipe, but we haven't gotten
>> around to it.
>>     
> Could you please explain what you mean by that? Would it be possible
> to give me an idea or an example of how such would work?
>
>   

In theory you can use a generic __deepcopy__ implementation for ORM
classes. A very simple version might be:

def orm_deepcopy(self, memo):
    mapper = class_mapper(self.__class__)
    result = self.__class__()
    memo[id(self)] = result
    for prop in mapper.iterate_properties():
        value = getattr(self, prop.key)
        setattr(result, prop.key, deepcopy(value, memo))
    return result

class MyMappedClass(...):
    __deepcopy__ = orm_deepcopy

Beware that this implementation does not handle overlapping properties
well (e.g. relations and their corresponding foreign key columns),
lazy-loading properties, read-only properties, clearing out
auto-incrementing primary keys, etc. I would not recommend this
approach, as a use-case-specific copy() method will be much easier to
tailor to your needs.

>>> How can I stop it from closing the
>>> sessions?
>>>       
>   
>> nothing in SQLA closes sessions.  Your program is doing that.
>>     
> I'm not issuing a session.close() anywhere (I checked). Are there any
> other ways of closing a session besides that? (If the answer is
> "Plenty", don't worry about it... I'll try to track it down then)
>   

If you are in a web framework, it may be closing the session for you
(usually by calling Session.remove() on a ScopedSession). Additionally,
are you sure that your object-to-copy is not transient when you make
your deepcopy?

-Conor

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