On Dec 28, 2011, at 1:36 AM, Mike Orr wrote:
> On Tue, Dec 27, 2011 at 8:05 AM, Michael Bayer <[email protected]>
> wrote:
>> What's the use case for a Base being shared to a third party module that
>> doesn't know about your application? This sounds like a bad idea. A Base
>> might have any number of behaviors on it, like certain columns, naming
>> conventions, __mapper_args__(), attribute names, that can't be anticipated
>> by a third party library.
>
> The problem is that applications and libraries are all creating their
> own Bases and Sessions, and then it becomes complicated to make them
> work together.
Regarding Session, if someone builds a third party library that works on some
tables of it's own, and the author made the system use its own Session with no
way to plug into the main transaction of the calling application, that's just
bad design. If it calls session.commit() on its own yet is designed to work
inline with the same database and within a series of events inside of a view,
also bad design. It shouldn't assume transactional scope.
I would think if the plugin is designed for Pyramid, it would be based around
ZopeSQLAlchemy, which provides a master transaction for everyone to integrate
towards. Do the third party plugins at least integrate with that ?
I would say that's just something library authors would need to know how to do.
They need to understand that transactions are defined by the calling
application, and how a Session relates to that. It's just one click more
complicated than having to know nothing at all about how transactions work.
A convention here, a "how to" document of best practices for 3rd party stuff,
would make it clear how these should be done. Using the transaction manager
recommended with Pyramid would be best, assuming the transaction manager is
capable of this.
Also, just as a note, I've never seen a 3rd party plugin that uses SQLAlchemy
before, which is using a Session, defining tables, etc. Can I see one ? Are
there a lot , or like half a dozen ?
Regarding Base, Base corresponds to a class hierarchy, meaning it's how your
class structure is designed. SQLAHelper doesn't need to change here, it if
course can expose the default "Base" to everyone, and that's great. A shop
that has multiple apps of its own but are designed to work together can
certainly have them all call into SQLAHelper's "Base" and that is fine.
As far as a 3rd party thing, like "download this library and now you have a
standalone auth model/schema" (is there at least *one* 3rd party thing that is
*not* about auth?), that probably shouldn't use the same Base, as it implies
the app can't assume any kinds of conventions or behaviors on the Base class,
or if it does it means my own app now can't do X, Y, or Z because it will break
the 3rd party library. So I'd rather the standard practice is to share
configuration and namespaces, but not class structure except for mixins. But
if someone shows me an example here why they really want to share out the Base
that of course can make me more aware.
The sharing of configuration can integrate with the schema of the target system
by sharing MetaData(). It can integrate at the relationship() level using
real class objects, or by sharing _decl_class_registry, which has always been
something that could be monkeypatched, but not public...so r76d872dc77b9 now
contains this feature:
from sqlalchemy.ext.declarative import declarative_base
reg = {}
Base1 = declarative_base(class_registry = reg)
Base2 = declarative_base(class_registry = reg)
class A(Base1):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
class B(Base2):
__tablename__ = 'b'
id = Column(Integer, primary_key=True)
aid = Column(Integer, ForeignKey(A.id))
as_ = relationship("A")
assert B.as_.property.mapper.class_ is A
If you additionally share a MetaData() between two bases, now those two will
entirely share the same class name and table name registry.
Also note ticket 2338: http://www.sqlalchemy.org/trac/ticket/2338 , which I'm
leaning towards, would add the full module path of things to the registry, so
you could say:
group = relationship("myauth.classes.Group")
>
> Well, I'm inclined to do whatever MikeB suggests. But what would the
> module contain in this case; i.e., what would its globals be? You'd
> still need a module with globals in order to be a well-known rendevous
> point. 'helper = SQLAHelper()' as a variable in the application
> doesn't do that. Or would 'helper' be the global in the package?
never mind that part here, if it's a module global already that's fine.
>
> One thing SQLAHelper does is that if you call ``add_engine(engine)``
> without an engine name, it becomes the default engine, and the Session
> and Base.metadata are automatically bound to it. This is so that
> applications with a single database only need to make one function
> call to set everything up. It looks like the only way to do that in
> your 'helper' structure would be a 'helper.set_default_engine()'
> method? And 'helper.engines.default' would be None initially, because
> the engine is not known at import time?
perhaps helper.engine = some_engine would be the equivalent of
add_engine(engine) - or do we think using a "setter" approach belies that
nothing more than just a simple assignment is going on ?
--
You received this message because you are subscribed to the Google Groups
"pylons-discuss" 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/pylons-discuss?hl=en.