[sqlalchemy] Re: Questions about polymorphic mappers

2007-01-18 Thread King Simon-NFHD78


Michael Bayer wrote:

Simon King wrote:
 [requirements for instances returned from
  MapperExtension.create_instance]

at this point the entity_name should get set after your 
custom create_instance is called (at least thats in the 
trunk).  init_attr is not required, it pre-sets attributes on 
the object that are otherwise auto-created later (but the 
autocreation step throws a single AttributeError per 
attribute, which hits performance a little bit).




Thanks a lot for explaining that. It looks to me like I would be better
off simply using this method to load my class hierarchy, rather than
trying to twist polymorphic_identity into something that it was never
meant to do. Also, adding get_polymorphic_identity as a MapperExtension
method would add an overhead for every single object load for what is
probably a very infrequently used feature - I'd hate to be responsible
for that! Yet again, SQLAlchemy is already able to do exactly what I
want - sorry it's taken a while for me to realise it.

Cheers,

Simon

--~--~-~--~~~---~--~~
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: Questions about polymorphic mappers

2007-01-15 Thread King Simon-NFHD78


Micheal Bayer wrote:


id rather just add another plugin point on MapperExtension 
for this, which takes place before the polymorphic decision 
stage at the top of the _instance method, like 
get_polymorphic_identity().  that way you could do all of 
this stuff cleanly in an extension (and id do that instead of 
making polymorphic_identity into a list).  hows that sound?




That would be ideal for me, and would seem to be the most flexible
solution as well - it leaves the decision for which class to use up to
the application. What would it actually return, though? An instance
ready to be populated?

Thanks a lot,

Simon

--~--~-~--~~~---~--~~
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: Questions about polymorphic mappers

2007-01-15 Thread Michael Bayer


at this point the entity_name should get set after your custom  
create_instance is called (at least thats in the trunk).  init_attr  
is not required, it pre-sets attributes on the object that are  
otherwise auto-created later (but the autocreation step throws a  
single AttributeError per attribute, which hits performance a little  
bit).



On Jan 15, 2007, at 12:19 PM, King Simon-NFHD78 wrote:



Michael Bayer wrote:
you can still override create_instance() as well and try to spit  
out subclasses that are otherwise not mapped.


This was something I looked at a while ago as well, and I wasn't sure
what the requirements on objects returned from create_instance  
were. If

it is not overridden, the mapper calls _create_instance, which sets
_entity_name and calls attribute_manager.init_attr. How important are
these things to the rest of the library?

Simon





--~--~-~--~~~---~--~~
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: Questions about polymorphic mappers

2007-01-12 Thread King Simon-NFHD78

Michael Bayer wrote:
 
 i think using the polymorphic_map is OK.  i downplayed its 
 existence since I felt it was confusing to people, which is 
 also the reason i made the _polymorphic_map argument to 
 mapper private; it was originally public.  but it seemed 
 like it was producing two ways of doing the same thing so i 
 made it private.

OK - I'll carry on using that then.


 using class_mapper() function instead of class.mapper


Ah - that's what I was missing. I hadn't seen the class_mapper function.
Thanks for that.

 
 as far as having multiple polymorphic_identity values map 
 to the same class, i would think we could just have 
 polymorphic_identity be a list instead of a scalar.  right 
 now, if you just inserted multiple values for the same class 
 in polymorphic_map, it would *almost* work except that the 
 save() process is hardwiring the polymorphic_on column to the 
 single polymorphic_identity value no matter what its set to.
 
 so attached is an untested patch which accepts either a 
 scalar or a list value for polymorphic_identity, and if its a 
 list then instances need their polymorphic_on attribute set 
 to a valid entry before flushing.  try this out and see if it 
 does what you need, and i can easily enough add this to the 
 trunk to be available in the next release (though id need to 
 write some tests also).
 

I think this would definitely be a useful feature, and in fact I was
originally going to attempt (or at least suggest!) something like that
myself. I'll try the patch and let you know how well it works.

However, I still have a situation where I would like to be able to use a
default class for unknown types. I don't want to hard-code all the
possible options up-front - only the ones that I actually want to treat
specially. I've been playing around with some different options, and
this is what I've ended up with:

class EmployeeMeta(type):
def __call__(cls, kind, _fix_class=True, **kwargs):
if not _fix_class:
return type.__call__(cls, kind=kind, **kwargs)
cls = get_employee_class(kind)
return cls(kind=kind, _fix_class=False, **kwargs)

def get_employee_class(kind):
if kind == 'manager':
return Manager
else:
return Employee

class Employee(object):
__metaclass__ = EmployeeMeta

class Manager(Employee):
pass


class EmployeeMapperExtension(sa.MapperExtension):
def create_instance(self, mapper, selectcontext, row, class_):
cls = get_employee_class(row[employee_table.c.kind])
if class_ != cls:
return sa.class_mapper(cls)._instance(selectcontext, row)
return sa.EXT_PASS

assign_mapper(ctx,
  Employee, employee_table,
  extension=EmployeeMapperExtension())
assign_mapper(ctx,
  Manager,
  inherits=Employee.mapper)


This seems to do the right thing - Manager instances get created for
managers, but any other row becomes an Employee. To add a subclass for
another row type, I just need to adapt the get_employee_class function
and add another call to assign_mapper. With a bit more work in the
metaclass, it could all be done with a special attribute in the
subclass.

The only thing I'm not sure about is the mapper extension - is it OK to
call the mapper._instance method, or is there a better way to do this?

Thanks again,

Simon


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


inheritance_test.py
Description: inheritance_test.py


[sqlalchemy] Re: Questions about polymorphic mappers

2007-01-12 Thread Michael Bayer


King Simon-NFHD78 wrote:

 class EmployeeMapperExtension(sa.MapperExtension):
 def create_instance(self, mapper, selectcontext, row, class_):
 cls = get_employee_class(row[employee_table.c.kind])
 if class_ != cls:
 return sa.class_mapper(cls)._instance(selectcontext, row)
 return sa.EXT_PASS
 

 The only thing I'm not sure about is the mapper extension - is it OK to
 call the mapper._instance method, or is there a better way to do this?

if you call _instance like that, youre already well inside the
_instance method of the calling mapper...so its not a great way to do
it since a lot of redundant stuff will happen which may have negative
side effects.

id rather just add another plugin point on MapperExtension for this,
which takes place before the polymorphic decision stage at the top of
the _instance method, like get_polymorphic_identity().  that way you
could do all of this stuff cleanly in an extension (and id do that
instead of making polymorphic_identity into a list).  hows that sound?


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