[sqlalchemy] Re: Use of new_instance() in the user-defined-state branch?

2008-03-28 Thread Michael Bayer


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?

2008-03-28 Thread Phillip J. Eby

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?

2008-03-28 Thread Phillip J. Eby

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?

2008-03-28 Thread Michael Bayer


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?

2008-03-28 Thread Michael Bayer


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?

2008-03-27 Thread jason kirtland

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?

2008-03-27 Thread Michael Bayer


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?

2008-03-27 Thread Michael Bayer


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?

2008-03-27 Thread jason kirtland

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?

2008-03-27 Thread Phillip J. Eby

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