[sqlalchemy] Re: Use of new_instance() in the user-defined-state branch?
On Mar 28, 2008, at 12:55 AM, Phillip J. Eby wrote: Sadly, about the only way for me to implement that without code duplication will be to temporarily change the item's __class__ to a subclass with an empty __init__ method. Unless there's a way to change the generated __init__ method to take an extra flag or check a per-thread variable to skip the bits you don't want? What are the bits you don't want run, anyway? That is, what specifically mustn't happen? an end-user's __init__ method is not run when the object is loaded from the DB since the ORM is going to populate its state explicitly. its for similar reasons that pickle.loads() doesn't call __init__. Its a common use case that someone's class needs to be constructed differently when it is newly created vs. when it is re-populated from the DB. The usual method we have of modifying this behavior is to use a MapperExtension where you implement create_instance(). Then you can build the object any way you want, using __init__, whatever. Why is that not an option here ? ( or has it just not been mentioned ?) --~--~-~--~~~---~--~~ 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: Use of new_instance() in the user-defined-state branch?
At 09:45 AM 3/28/2008 -0400, Michael Bayer wrote: On Mar 28, 2008, at 12:55 AM, Phillip J. Eby wrote: Sadly, about the only way for me to implement that without code duplication will be to temporarily change the item's __class__ to a subclass with an empty __init__ method. Unless there's a way to change the generated __init__ method to take an extra flag or check a per-thread variable to skip the bits you don't want? What are the bits you don't want run, anyway? That is, what specifically mustn't happen? an end-user's __init__ method is not run when the object is loaded from the DB since the ORM is going to populate its state explicitly. its for similar reasons that pickle.loads() doesn't call __init__. Its a common use case that someone's class needs to be constructed differently when it is newly created vs. when it is re-populated from the DB. The usual method we have of modifying this behavior is to use a MapperExtension where you implement create_instance(). Then you can build the object any way you want, using __init__, whatever. Why is that not an option here ? ( or has it just not been mentioned ?) Because Jason said this: At 06:08 PM 3/27/2008 -0700, jason kirtland wrote: Phillip J. Eby wrote: At 02:26 PM 3/27/2008 -0700, jason kirtland wrote: new_instance creates an instance without invoking __init__. The ORM uses it to recreate instances when loading from the database. new_instance can be added to InstrumentationManager as an extension method... The ORM doesn't care how empty instances are manufactured so long as they can be created without initialization arguments, e.g. a no-arg constructor. Does that mean that no attributes must be set from new_instance(), either? You should be able to set whatever you like there. So... new_instance() could literally just be a call to 'self.class_()', with no other behavior, as long as the constructor requires no arguments? The modified __init__ that SA inserts won't be a problem there? Sorry, I should have included more detail. You don't want to trigger the logic in SA's __init__ decorator or call the user's __init__. The ORM policy is not to __init__ on load, and will soon support a symmetric __on_load__ type of hook that the ORM can call post-__new__ when reconstituting instances. So, which one of you is right? :) --~--~-~--~~~---~--~~ 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: Use of new_instance() in the user-defined-state branch?
So you're still disagreeing with Jason, who's quite explicitly saying that SA's __init__ will blow up if it gets called. Which of you is right? :) At 11:38 AM 3/28/2008 -0400, Michael Bayer wrote: On Mar 28, 2008, at 10:58 AM, Phillip J. Eby wrote: Sorry, I should have included more detail. You don't want to trigger the logic in SA's __init__ decorator or call the user's __init__. The ORM policy is not to __init__ on load, and will soon support a symmetric __on_load__ type of hook that the ORM can call post-__new__ when reconstituting instances. So, which one of you is right? :) Well, I'm not entirely sure how your users will be using their objects. If they just want to take any old application and enable trellis + sqlalchemy, if they are accustomed to writing for SA then it would be a surprise for their __init__() method to be called. Like, if I wrote a class like this: class MyClass(object): def __init__(self, a, b): self.a = a self.b = b then I mapped it to Trellis + SQLA, we *can't* call MyClass() upon load from the database - we dont have the constructor arguments available and TypeError will be thrown. If OTOH, using Trellis implies that you must already have an __init__() that is compatible with a no-arg calling style and that they should expect population of attributes to occur after it's called, then theres no issue with configuring the SA mappings to call __init__(). I think you mentioned earlier that Trellis doesn't care what the user does with __init__()neither does SQLAlchemy, and thats why we never call it by default with no args, since we make no assumptions about what it expects or what it does. --~--~-~--~~~---~--~~ 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: Use of new_instance() in the user-defined-state branch?
On Mar 28, 2008, at 12:13 PM, Phillip J. Eby wrote: So you're still disagreeing with Jason, who's quite explicitly saying that SA's __init__ will blow up if it gets called. Which of you is right? :) SA's __init__ does not blow up if it gets called. It just checks that mappers are compiled and sets up InstanceState if not already present. I'm not sure if recent changes on the branch have changed this, though I doubt it, since we have a lot of users that do implement MapperExtension.create_instance() to call their __init__() method. --~--~-~--~~~---~--~~ 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: Use of new_instance() in the user-defined-state branch?
On Mar 28, 2008, at 12:28 PM, Michael Bayer wrote: On Mar 28, 2008, at 12:13 PM, Phillip J. Eby wrote: So you're still disagreeing with Jason, who's quite explicitly saying that SA's __init__ will blow up if it gets called. Which of you is right? :) SA's __init__ does not blow up if it gets called. It just checks that mappers are compiled and sets up InstanceState if not already present. I'm not sure if recent changes on the branch have changed this, though I doubt it, since we have a lot of users that do implement MapperExtension.create_instance() to call their __init__() method. I think I should summarize what is known about this: 1. being able to configure the ORM to call __init__() instead of __new__() has always been a supported use case. 2. there are general issues when you have an ORM or any other instrumentation layer call __init__(), which is that people like to define argument signatures and behaviors for their __init__() which may conflict with just being able to call it in a plain vanilla style. So you may not actually want to call __init__() across the board. 3. Our long-existing hook to change how an object is created is MapperExtension.create_instance(), which just expects an instance back, no opinion on how it's created. That isn't going anywhere. 4. Jason is working on new hooks in the branch that would be an alternative to using create_instance(). The new_instance hook specifically would *not* be where you'd just call __init__() from. But the management interface will allow you to define exactly how __init__ is decorated on mapped classes, including marking it with the reconsitute hook which means it would be called after new_instance is called. So an immediate workaround would be to play with MapperExtension.create_instance(), but our plan is that before the branch is merged, we will have more hooks at the instrumentation layer as well. --~--~-~--~~~---~--~~ 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: Use of new_instance() in the user-defined-state branch?
Phillip J. Eby wrote: I just noticed that in the latest version of the branch, there's a new_instance() call that is using a class' __new__ method in order to create a new instance, rather than using 'class()'. What I'd like to find out is how to get around this, because Trellis objects will not be properly initialized unless the 'class()' is called, with any initialization taking place inside __new__ and/or __init__. Trellis doesn't override __new__ or __init__, and doesn't care what they do. But the creation of an instance *must* be wrapped by the class' __call__ (i.e. class()), as there is a try/finally involved that must execute. Any thoughts on how this might be refactored? What is new_instance() used for? new_instance creates an instance without invoking __init__. The ORM uses it to recreate instances when loading from the database. new_instance can be added to InstrumentationManager as an extension method... The ORM doesn't care how empty instances are manufactured so long as they can be created without initialization arguments, e.g. a no-arg constructor. --~--~-~--~~~---~--~~ 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: Use of new_instance() in the user-defined-state branch?
On Mar 27, 2008, at 2:51 PM, Phillip J. Eby wrote: I just noticed that in the latest version of the branch, there's a new_instance() call that is using a class' __new__ method in order to create a new instance, rather than using 'class()'. What I'd like to find out is how to get around this, because Trellis objects will not be properly initialized unless the 'class()' is called, with any initialization taking place inside __new__ and/or __init__. Trellis doesn't override __new__ or __init__, and doesn't care what they do. But the creation of an instance *must* be wrapped by the class' __call__ (i.e. class()), as there is a try/finally involved that must execute. Any thoughts on how this might be refactored? What is new_instance() used for? also, rev4361 has broken some tests. --~--~-~--~~~---~--~~ 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: Use of new_instance() in the user-defined-state branch?
On Mar 27, 2008, at 3:11 PM, Michael Bayer wrote: also, rev4361 has broken some tests. rev 4362 fixes that particular issue. I know that the sweep function there is sensitive in other cases, such as ticket #882, where if not done properly it can also trip up zope.interface...so it might be good to ensure that we aren't breaking that ticket again. --~--~-~--~~~---~--~~ 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: Use of new_instance() in the user-defined-state branch?
Phillip J. Eby wrote: At 12:02 PM 3/27/2008 -0700, jason kirtland wrote: Phillip J. Eby wrote: I just noticed that in the latest version of the branch, there's a new_instance() call that is using a class' __new__ method in order to create a new instance, rather than using 'class()'. What I'd like to find out is how to get around this, because Trellis objects will not be properly initialized unless the 'class()' is called, with any initialization taking place inside __new__ and/or __init__. Trellis doesn't override __new__ or __init__, and doesn't care what they do. But the creation of an instance *must* be wrapped by the class' __call__ (i.e. class()), as there is a try/finally involved that must execute. Any thoughts on how this might be refactored? What is new_instance() used for? new_instance creates an instance without invoking __init__. The ORM uses it to recreate instances when loading from the database. new_instance can be added to InstrumentationManager as an extension method... The ORM doesn't care how empty instances are manufactured so long as they can be created without initialization arguments, e.g. a no-arg constructor. Does that mean that no attributes must be set from new_instance(), either? You should be able to set whatever you like there. On a separate note, I noticed that the class manager machinery allowed one to just directly subclass ClassManager instead of making an InstrumentationManager. Was that intentional? I preserved this behavior when I corrected the staticmethod failure problem, but the tests don't appear to test for that. Yes, that's an intentional capability. I'm actively refactoring the entire mechanism to work in the MapperExtension-driven instrumentation election that's desired for the Zope security proxy integration; covering tests will be committed shortly as the whole starts to take a usable shape. --~--~-~--~~~---~--~~ 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: Use of new_instance() in the user-defined-state branch?
At 02:26 PM 3/27/2008 -0700, jason kirtland wrote: new_instance creates an instance without invoking __init__. The ORM uses it to recreate instances when loading from the database. new_instance can be added to InstrumentationManager as an extension method... The ORM doesn't care how empty instances are manufactured so long as they can be created without initialization arguments, e.g. a no-arg constructor. Does that mean that no attributes must be set from new_instance(), either? You should be able to set whatever you like there. So... new_instance() could literally just be a call to 'self.class_()', with no other behavior, as long as the constructor requires no arguments? The modified __init__ that SA inserts won't be a problem there? --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---