[sqlalchemy] Re: Abstract base class

2008-12-19 Thread FrankB

Hi,

I have a similar task, so I tried to use your proposal, but it didn't
work for me:

===

from sqlalchemy import types as satypes
from sqlalchemy import schema as saschema
from sqlalchemy.engine import create_engine
from sqlalchemy.ext.declarative import declarative_base,
DeclarativeMeta
from sqlalchemy.orm import scoped_session, sessionmaker

class BaseType(DeclarativeMeta):
def __init__(newcls, classname, bases, dict_):
newcls.notes = saschema.Column(satypes.String)
DeclarativeMeta.__init__(newcls, classname, bases, dict_)

MetaData = saschema.MetaData(bind=create_engine('sqlite:///:memory:'))
Session = scoped_session(sessionmaker(bind=MetaData.bind))
Base = declarative_base(metadata=MetaData, mapper=Session.mapper,
metaclass=BaseType)

class MasterEntity(Base):
__tablename__ = master
id = saschema.Column(satypes.Integer, primary_key=True)
status = saschema.Column(satypes.CHAR(length=1), default=A)

print [ _c.key for _c in MasterEntity.__table__.columns ]
# ['id', 'status']
# = the 'notes' column is missing

=== snip

So, what am I doing wrong?

Thanks in advance,
Frank

Btw.: Hello group and many thanks to Michael for this great piece of
software!



On Dec 16, 6:58 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 anabstractbaseclassisn't going to set up the same fields on all  
 descendants since the mapper()/Table() setup occurs during the  
 creation of the individualclassusing the non-inheritedclassdict,  
 and unique instances of each of the Column, etc. elements are required  
 as well.

 concrete inheritance, as referenced in that post, was not designed  
 to be used as a configurational spacesaver and always requires a  
 mapped selectable for the base, which you don't have here, so it's  
 not appropriate for this use case.

 So for this you'd need a custom metaclass:

 classMyMeta(DeclarativeMeta):
      def __init__(cls, classname, bases, dict_):
         cls.notes = Column(String)
         DeclarativeMeta.__init__(cls, classname, bases, dict_)

 Base= declarative_base(metaclass=MyMeta)

 On Dec 16, 2008, at 12:36 PM, Joril wrote:



  Hi everyone!
  I need to declare a few unrelated classes (from a business
  perspective) that share some attributes/fields, so I thought I could
  use anabstractclassto group these common attributes (note that just
  a few classes should have them, not every one)

  This post
 http://groups.google.it/group/sqlalchemy/msg/d3de02f609a0bbd9?hl=it
  suggests to use mixins, but I can't get it to work, SQLA generates the
  tables without the common fields.

  I'm testing it with this script:

  from sqlalchemy.ext.declarative import declarative_base
  from sqlalchemy import Column, Integer, String
  from sqlalchemy import create_engine

  # --- Tables definition
 Base= declarative_base()

 classAbstract(object):
    notes = Column(String)

 classConcrete(Base,Abstract):
    __tablename__ = 'concrete'
    id = Column(Integer, primary_key=True)
  # ---

  # DB creation
  engine = create_engine('sqlite:///:memory:', echo=True)
 Base.metadata.create_all(engine)

  Here's the sql call:
  CREATE TABLE concrete (
         id INTEGER NOT NULL,
         PRIMARY KEY (id)
  )

  What am I missing? Did I misunderstood how the mixin should be used?
  (I'm using SQLA 0.5rc4)

  Many thanks!

--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Abstract base class

2008-12-19 Thread Michael Bayer

oops, do it like this:

class BaseType(DeclarativeMeta):
def __init__(newcls, classname, bases, dict_):
dict_['notes'] = saschema.Column(satypes.String)
DeclarativeMeta.__init__(newcls, classname, bases, dict_)


clearly we'll have to figure out a more user friendly pattern for this  
use case.

On Dec 19, 2008, at 5:27 AM, FrankB wrote:


 Hi,

 I have a similar task, so I tried to use your proposal, but it didn't
 work for me:

 ===

 from sqlalchemy import types as satypes
 from sqlalchemy import schema as saschema
 from sqlalchemy.engine import create_engine
 from sqlalchemy.ext.declarative import declarative_base,
 DeclarativeMeta
 from sqlalchemy.orm import scoped_session, sessionmaker

 class BaseType(DeclarativeMeta):
def __init__(newcls, classname, bases, dict_):
newcls.notes = saschema.Column(satypes.String)
DeclarativeMeta.__init__(newcls, classname, bases, dict_)

 MetaData = saschema.MetaData(bind=create_engine('sqlite:///:memory:'))
 Session = scoped_session(sessionmaker(bind=MetaData.bind))
 Base = declarative_base(metadata=MetaData, mapper=Session.mapper,
 metaclass=BaseType)

 class MasterEntity(Base):
__tablename__ = master
id = saschema.Column(satypes.Integer, primary_key=True)
status = saschema.Column(satypes.CHAR(length=1), default=A)

 print [ _c.key for _c in MasterEntity.__table__.columns ]
 # ['id', 'status']
 # = the 'notes' column is missing

 === snip

 So, what am I doing wrong?

 Thanks in advance,
Frank

 Btw.: Hello group and many thanks to Michael for this great piece of
 software!



 On Dec 16, 6:58 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 anabstractbaseclassisn't going to set up the same fields on all
 descendants since the mapper()/Table() setup occurs during the
 creation of the individualclassusing the non-inheritedclassdict,
 and unique instances of each of the Column, etc. elements are  
 required
 as well.

 concrete inheritance, as referenced in that post, was not designed
 to be used as a configurational spacesaver and always requires a
 mapped selectable for the base, which you don't have here, so it's
 not appropriate for this use case.

 So for this you'd need a custom metaclass:

 classMyMeta(DeclarativeMeta):
  def __init__(cls, classname, bases, dict_):
 cls.notes = Column(String)
 DeclarativeMeta.__init__(cls, classname, bases, dict_)

 Base= declarative_base(metaclass=MyMeta)

 On Dec 16, 2008, at 12:36 PM, Joril wrote:



 Hi everyone!
 I need to declare a few unrelated classes (from a business
 perspective) that share some attributes/fields, so I thought I could
 use anabstractclassto group these common attributes (note that just
 a few classes should have them, not every one)

 This post
 http://groups.google.it/group/sqlalchemy/msg/d3de02f609a0bbd9?hl=it
 suggests to use mixins, but I can't get it to work, SQLA generates  
 the
 tables without the common fields.

 I'm testing it with this script:

 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy import Column, Integer, String
 from sqlalchemy import create_engine

 # --- Tables definition
 Base= declarative_base()

 classAbstract(object):
   notes = Column(String)

 classConcrete(Base,Abstract):
   __tablename__ = 'concrete'
   id = Column(Integer, primary_key=True)
 # ---

 # DB creation
 engine = create_engine('sqlite:///:memory:', echo=True)
 Base.metadata.create_all(engine)

 Here's the sql call:
 CREATE TABLE concrete (
id INTEGER NOT NULL,
PRIMARY KEY (id)
 )

 What am I missing? Did I misunderstood how the mixin should be used?
 (I'm using SQLA 0.5rc4)

 Many thanks!

 


--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Abstract base class

2008-12-19 Thread az

On Friday 19 December 2008 16:58:12 Michael Bayer wrote:
 oops, do it like this:

 class BaseType(DeclarativeMeta):
 def __init__(newcls, classname, bases, dict_):
 dict_['notes'] = saschema.Column(satypes.String)
 DeclarativeMeta.__init__(newcls, classname, bases, dict_)


 clearly we'll have to figure out a more user friendly pattern for
 this use case.
can't u use multiple inheritance, in the case, as mixin/s?
i use it in dbcook this way, using the bases[1:] only as 
declaration-bringers.

--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Abstract base class

2008-12-18 Thread Joril

Michael Bayer wrote:

 meta = MetaData()
 Base1 = declarative_base(metadata=meta, metaclass=MyMetaClass)
 Base2 = declarative_base(metadata=meta, metaclass=MyOtherMetaClass)
 Base2._decl_class_registry = Base1._decl_class_registry

Great!
So now I have a MetaClass2 that extends MetaClass1, and they share a
set of fields.. Works perfectly :)

Another question if I may.. What would be the recommended way to
identify a mapped object now? I mean, I could use something like
isinstance(obj, Base1) or isinstance(obj, Base2)
but is there a more concise way? It looks like Base1 and Base2 extend
object directly..

 This is a use case we can make easier in a future release.

That'd be appreciated, surely :)

Many thanks for your time, as always!
--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Abstract base class

2008-12-18 Thread Michael Bayer



isinstance(obj, (Base1, Base2)), or you could make yet another Base  
class below Base1 and Base2 and specify it as cls to  
declarative_base().

On Dec 18, 2008, at 3:06 AM, Joril wrote:


 Michael Bayer wrote:

 meta = MetaData()
 Base1 = declarative_base(metadata=meta, metaclass=MyMetaClass)
 Base2 = declarative_base(metadata=meta, metaclass=MyOtherMetaClass)
 Base2._decl_class_registry = Base1._decl_class_registry

 Great!
 So now I have a MetaClass2 that extends MetaClass1, and they share a
 set of fields.. Works perfectly :)

 Another question if I may.. What would be the recommended way to
 identify a mapped object now? I mean, I could use something like
 isinstance(obj, Base1) or isinstance(obj, Base2)
 but is there a more concise way? It looks like Base1 and Base2 extend
 object directly..

 This is a use case we can make easier in a future release.

 That'd be appreciated, surely :)

 Many thanks for your time, as always!
 


--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Abstract base class

2008-12-18 Thread Joril

Michael Bayer wrote():

 isinstance(obj, (Base1, Base2)), or you could make yet another Base
 class below Base1 and Base2 and specify it as cls to
 declarative_base().

I see.. Thanks again, you are very helpful!
--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Abstract base class

2008-12-17 Thread Michael Bayer


On Dec 17, 2008, at 2:28 AM, Joril wrote:


 Michael Bayer ha scritto:

 concrete inheritance, as referenced in that post, was not designed
 to be used as a configurational spacesaver and always requires a
 mapped selectable for the base, which you don't have here, so it's
 not appropriate for this use case.


 So for this you'd need a custom metaclass:

 I see, thanks! Now my problem is that I already have a custom
 metaclass, defining a set of common attributes for ALL my classes..
 So, to declare additional fields for just a few classes, would it be
 ok to subclass the custom metaclass again and re-call declarative_base
 ()?

 To clarify:
 All classes have a timestamp attribute, and a few of them has a
 notes attribute too.

 Thanks again!

yes that is entirely OK.   A second declarative_base may share the  
metadata of the first, Base =  
declarative_base(metadata=somemetadata).   If you want to use strings  
for relation() classes across the two bases, the _decl_class_registry  
would need to be shared as well:

meta = MetaData()
Base1 = declarative_base(metadata=meta, metaclass=MyMetaClass)
Base2 = declarative_base(metadata=meta, metaclass=MyOtherMetaClass)
Base2._decl_class_registry = Base1._decl_class_registry

This is a use case we can make easier in a future release.

--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Abstract base class

2008-12-16 Thread Michael Bayer

an abstract base class isn't going to set up the same fields on all  
descendants since the mapper()/Table() setup occurs during the  
creation of the individual class using the non-inherited class dict,  
and unique instances of each of the Column, etc. elements are required  
as well.

concrete inheritance, as referenced in that post, was not designed  
to be used as a configurational spacesaver and always requires a  
mapped selectable for the base, which you don't have here, so it's  
not appropriate for this use case.


So for this you'd need a custom metaclass:

class MyMeta(DeclarativeMeta):
 def __init__(cls, classname, bases, dict_):
cls.notes = Column(String)
DeclarativeMeta.__init__(cls, classname, bases, dict_)

Base = declarative_base(metaclass=MyMeta)



On Dec 16, 2008, at 12:36 PM, Joril wrote:


 Hi everyone!
 I need to declare a few unrelated classes (from a business
 perspective) that share some attributes/fields, so I thought I could
 use an abstract class to group these common attributes (note that just
 a few classes should have them, not every one)

 This post
 http://groups.google.it/group/sqlalchemy/msg/d3de02f609a0bbd9?hl=it
 suggests to use mixins, but I can't get it to work, SQLA generates the
 tables without the common fields.

 I'm testing it with this script:

 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy import Column, Integer, String
 from sqlalchemy import create_engine

 # --- Tables definition
 Base = declarative_base()

 class Abstract(object):
   notes = Column(String)

 class Concrete(Base, Abstract):
   __tablename__ = 'concrete'
   id = Column(Integer, primary_key=True)
 # ---

 # DB creation
 engine = create_engine('sqlite:///:memory:', echo=True)
 Base.metadata.create_all(engine)

 Here's the sql call:
 CREATE TABLE concrete (
  id INTEGER NOT NULL,
  PRIMARY KEY (id)
 )

 What am I missing? Did I misunderstood how the mixin should be used?
 (I'm using SQLA 0.5rc4)

 Many thanks!
 


--~--~-~--~~~---~--~~
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 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Abstract base class

2008-12-04 Thread Guillaume



On Dec 3, 7:39 pm, Michael Bayer [EMAIL PROTECTED] wrote:
 On Dec 3, 2008, at 1:26 PM, Guillaume wrote:



  Hello,

  is there a way with the ORM layer to have abstract base class like in
  django ?
  http://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-
  classes

 sure, just pass along cls=MyBaseClass along to declarative_base().
 You can also make your own metaclass if you wanted, and pass it in as
 metaclass=MyMetaClass, or you can use the individual components within
 declarative_base explicitly if you wanted to roll it yourself.   This
 is all in the docstrings for declarative.

So:
class A(object): pass
Base = declarative_base(cls=A)
class B(Base):
  __tablename__ = 'b'
  id = Column(Integer, primary_key=True)
b = B()
if isinstance(b, A):
  print 'Success !'

completes successfully, great !

  Another somehow related question is there any plan for declarative
  base to support inheritance ala django ?

 declarative supports all three of SQLA's table inheritance forms
 fully.It pretty much happens automatically when you make a
 subclass, and you just need to pass along polymorphic_on/
 polymorphic_identity into __mapper_args__.   If Django supported some
 kind of inheritance scenario that we don't I'd be very interested to
 see that :) .

The problem is not directly in the inheritance scenario, but rather
creating an association to an abstract class.

Let's say I have the following classes: CorporateCustomer and
PrivateCustomer inheriting from the abstract class Customer. On the
database side, I have the two following table: corporate_customer(id,
customer_info, corporate_info) and private_customer(id, customer_info,
private_info) (ids are generated by a unique sequence for all the
database). Now I have also Order objects associated to Customer
objects; the table looks like order(id, customer_id, order_info). Can
I map this scenario directly in SQLA without creating some dummy view
customer in the database ?

(Just checked how I did it with Django: with a set of ugly wrapper
method and views.)

Regards,
  Guillaume

--~--~-~--~~~---~--~~
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: Abstract base class

2008-12-04 Thread Michael Bayer


On Dec 4, 2008, at 7:44 AM, Guillaume wrote:


 The problem is not directly in the inheritance scenario, but rather
 creating an association to an abstract class.

 Let's say I have the following classes: CorporateCustomer and
 PrivateCustomer inheriting from the abstract class Customer. On the
 database side, I have the two following table: corporate_customer(id,
 customer_info, corporate_info) and private_customer(id, customer_info,
 private_info) (ids are generated by a unique sequence for all the
 database). Now I have also Order objects associated to Customer
 objects; the table looks like order(id, customer_id, order_info). Can
 I map this scenario directly in SQLA without creating some dummy view
 customer in the database ?

sure this is called concrete table inheritance.   Though when you  
make a relation to Order, you need to declare these separately for  
CorporateCustomer and PrivateCustomer since the connection from a  
relational perspective is different.   When concrete inheritance uses  
an abc, it maps to a union of the subtables so that you can load  
polymorphically.  To do that with declarative you'd also have to  
create the Table objects separately and pull them in to each class  
using __table__.

So with those limitations, if it were me I wouldn't use the concrete  
inheritance feature unless i needed to load Customer objects  
generically, I'd instead use Customer as a mixin class stated after  
the declarative base class.


--~--~-~--~~~---~--~~
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: Abstract base class

2008-12-04 Thread Guillaume


 sure this is called concrete table inheritance.   Though when you  
 make a relation to Order, you need to declare these separately for  
 CorporateCustomer and PrivateCustomer since the connection from a  
 relational perspective is different.   When concrete inheritance uses  
 an abc, it maps to a union of the subtables so that you can load  
 polymorphically.  To do that with declarative you'd also have to  
 create the Table objects separately and pull them in to each class  
 using __table__.

 So with those limitations, if it were me I wouldn't use the concrete  
 inheritance feature unless i needed to load Customer objects  
 generically, I'd instead use Customer as a mixin class stated after  
 the declarative base class.

Which prety much means no generic query for Customer objects ...

I'll go down the concrete inheritance path and create a couple of
views for handling my abstract classes.
--~--~-~--~~~---~--~~
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: Abstract base class

2008-12-04 Thread Michael Bayer


On Dec 4, 2008, at 11:18 AM, Guillaume wrote:



 sure this is called concrete table inheritance.   Though when you
 make a relation to Order, you need to declare these separately for
 CorporateCustomer and PrivateCustomer since the connection from a
 relational perspective is different.   When concrete inheritance uses
 an abc, it maps to a union of the subtables so that you can load
 polymorphically.  To do that with declarative you'd also have to
 create the Table objects separately and pull them in to each class
 using __table__.

 So with those limitations, if it were me I wouldn't use the concrete
 inheritance feature unless i needed to load Customer objects
 generically, I'd instead use Customer as a mixin class stated after
 the declarative base class.

 Which prety much means no generic query for Customer objects ...

 I'll go down the concrete inheritance path and create a couple of
 views for handling my abstract classes.

getting different concrete tables to connect to a common related  
table, with the configuration on the base class is definitely possible  
and its even clear where the code to do this would occur (right at the  
TODO in _adapt_inherited_property)...its just some complexity that I  
have balked on for now.


--~--~-~--~~~---~--~~
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: Abstract base class

2008-12-03 Thread Michael Bayer


On Dec 3, 2008, at 1:26 PM, Guillaume wrote:


 Hello,

 is there a way with the ORM layer to have abstract base class like in
 django ?
 http://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-
 classes

sure, just pass along cls=MyBaseClass along to declarative_base().
You can also make your own metaclass if you wanted, and pass it in as  
metaclass=MyMetaClass, or you can use the individual components within  
declarative_base explicitly if you wanted to roll it yourself.   This  
is all in the docstrings for declarative.

 Another somehow related question is there any plan for declarative
 base to support inheritance ala django ?

declarative supports all three of SQLA's table inheritance forms  
fully.It pretty much happens automatically when you make a  
subclass, and you just need to pass along polymorphic_on/ 
polymorphic_identity into __mapper_args__.   If Django supported some  
kind of inheritance scenario that we don't I'd be very interested to  
see that :) .




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