TurboEntity

0 views
Skip to first unread message

Jonathan LaCour

unread,
Oct 30, 2006, 11:06:43 AM10/30/06
to turbo...@googlegroups.com
For those of you who haven't seen yet:

http://turboentity.ematia.de/

Its a declarative layer on top of SQLAlchemy a'la ActiveMapper (and
apparently "heavily inspired by ActiveMapper" according to the source).
It feels much more like SQLObject than ActiveMapper, has documentation,
and examples. In all respects, it seems like an excellent replacement
for ActiveMapper (and SQLObject, for that matter).

Also, the web site specifically mentions that it was built with
TurboGears in mind, and even includes an example for providing an
identity model for turbogears. Very exciting news, and I have already
contacted the author about the possibility of supplanting ActiveMapper
as the recommended declarative layer for SQLAlchemy.

Check it out, and I hope I didn't steal the author's thunder :)

--
Jonathan LaCour
http://cleverdevil.org

percious

unread,
Oct 30, 2006, 11:57:49 AM10/30/06
to TurboGears
Two questions.

With TurboEntity work with tg-admin sql create

~and~

Can the author provide better documentation on the use of "select"
queries? IE select(id>50 and id<100)

Otherwise, looks great.

Thanks!
-chris

Karl Guertin

unread,
Oct 30, 2006, 8:26:17 PM10/30/06
to turbo...@googlegroups.com
On 10/30/06, percious <christoph...@pw.utc.com> wrote:
> With TurboEntity work with tg-admin sql create

I'm not 100% sure but I'd be surprised if it didn't.

> Can the author provide better documentation on the use of "select"
> queries? IE select(id>50 and id<100)

Syntax is the same as standard sqlalchemy. The select is the same as
used in ActiveMapper and assign_mapper:

TableName.select(and_(TableName.c.id > 50, TableName.c.id < 100))

Doug Woos

unread,
Oct 30, 2006, 10:11:53 PM10/30/06
to turbo...@googlegroups.com
On 10/30/06, Karl Guertin <gray...@gmail.com> wrote:
>
> On 10/30/06, percious <christoph...@pw.utc.com> wrote:
> > With TurboEntity work with tg-admin sql create
>
> I'm not 100% sure but I'd be surprised if it didn't.
>

The website says that "automatic table creation works as normal."

This looks intriguing- I think I'll use it to make the switch to SQLAlchemy.

Kevin Dangoor

unread,
Oct 30, 2006, 10:16:03 PM10/30/06
to turbo...@googlegroups.com
On Oct 30, 2006, at 11:06 AM, Jonathan LaCour wrote:

>
> For those of you who haven't seen yet:
>
> http://turboentity.ematia.de/
>
> Its a declarative layer on top of SQLAlchemy a'la ActiveMapper (and
> apparently "heavily inspired by ActiveMapper" according to the
> source).
> It feels much more like SQLObject than ActiveMapper, has
> documentation,
> and examples. In all respects, it seems like an excellent replacement
> for ActiveMapper (and SQLObject, for that matter).

Sounds like a good project, though I haven't looked at the details.
There's certainly a lot that can be done in that area, and the
featurelist is good.

> Also, the web site specifically mentions that it was built with
> TurboGears in mind, and even includes an example for providing an
> identity model for turbogears. Very exciting news, and I have already
> contacted the author about the possibility of supplanting ActiveMapper
> as the recommended declarative layer for SQLAlchemy.

Shh... we've got a book coming out in a few days that has a chapter
on using ActiveMapper ;)

Kevin

gasolin

unread,
Oct 31, 2006, 2:07:40 AM10/31/06
to TurboGears
I think we should create a doc to collect those candidates in an arena
:-D

Till now we have three candidates for default SA:

1. ActiveMapper
2. plain SA definitions
3. TurboEntity

Lee McFadden has checked in [1997] to replace ActiveMapper with plain
SA definitions.

Though plain SA makes SA users feel comfortable that they can take full
advantage of SA with turbogears, it doen't make sense for sqlobject
users that they could do the same thing with half size of code.

Though to use 'turboentity' class to specify the 'tablename' doesn't
make sense to me,
it did a good job for support 'Self-referential' field that SQLObject
did not (without magic
)

Here's a list of how TurboEntity, SQLObject, Active Mapper specify
their table name:

TurboEntity:

class turboentity:
tablename = "tg_user"

SQLObject:

class sqlmeta:
table = "tg_user"

Active Mapper:

class mapping:
__table__ = "tg_user"

Daniel Haus

unread,
Oct 31, 2006, 4:17:10 AM10/31/06
to TurboGears
I did write a reply yesterday, and I was wondering when my answer would
actually appear. I'll write a second, maybe there was some trouble with


1. Yes, "tg-admin sql create" does work
(see http://turboentity.ematia.de/examples.html#s3 )

2. Select queries work exactly like the way they do
in ActiveMapper or plain SQLAlchemy. You can
read a lot about that at http://www.sqlalchemy.org/docs/

Daniel

Daniel Haus

unread,
Oct 31, 2006, 5:26:14 AM10/31/06
to TurboGears
> Though to use 'turboentity' class to specify the 'tablename' doesn't
> make sense to me,

I'm not fully happy with that choice, either. I chose it because I
don't think that it will cause any naming conflicts (as eg.
"settings" possibly could).

Kevin Horn

unread,
Oct 31, 2006, 7:40:43 PM10/31/06
to turbo...@googlegroups.com
Do you have an example using the polymorphic inheritance features?

Kevin H

Daniel Haus

unread,
Oct 31, 2006, 8:17:17 PM10/31/06
to TurboGears
Good point, somehow I forgot about that. Actually
polymorphic inheritance is very simple, here's a
small example:

import sqlalchemy

from turboentity import *
from turboentity import objectstore

metadata = sqlalchemy.BoundMetaData("sqlite:///:memory:", True)

class Employee (Entity):
name = Column(Unicode(30))

class Engineer (Employee):
engineer_info = Column(Unicode(60))

class Marketer (Employee):
marketer_info = Column(Unicode(60))

create_all()

worker = Employee(name="Some Worker")
engineer = Engineer(name="Joe Engineer", engineer_info="joe's an
engineer")
marketer = Marketer(name="Pete Marketer", marketer_info="pete's a
marketer")

objectstore.flush()
objectstore.clear()

print Employee.get_by(Employee.c.name.like("Joe%")).name
print Employee.get_by(Employee.c.name.like("%Worker")).name

print Employee.get_by(Employee.c.name.like("Joe%")).engineer_info
print type(Employee.get_by(Employee.c.name.like("Pete%"))).__name__

---------------- 8< ----------------

I just found that there is a problem with inheritance
and relationships. I'm sure it worked before, I'll
investigate that soon.

Daniel

gasolin

unread,
Oct 31, 2006, 11:25:09 PM10/31/06
to TurboGears
Daniel:

I tried to learn TurboEntity by porting simpleblog-part-2 to
TurboEntity
(porting simpleblog-part-1 is a pretty nice experience)
http://www.splee.co.uk/2006/10/20/simpleblog-part-2/

I've meet some problems:

1. How to use OneToMany map for Post-Comments relationship?

2. how to make backref work?

Without document It seems not that obvious.

Steve Holden

unread,
Nov 1, 2006, 12:23:53 AM11/1/06
to turbo...@googlegroups.com
gasolin wrote:
> Daniel:
[...]

>
> Without document It seems not that obvious.
>
Unfortunately a position that I find myself in concerning many aspects
of this fine system.

Can we have a documentation sprint at PyCon - I know that much will have
improved by then, but I can bring a unique ignorance to the party to
help try and focus improvement where they will do most good.

Documentation is never finished ...

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Daniel Haus

unread,
Nov 1, 2006, 6:16:25 AM11/1/06
to TurboGears
I don't see the Problem here, one-to-many for Post-Comments
should work exactly like Director-Movies in this example:
http://turboentity.ematia.de/examples.html#s1

ie.

class Post (Entity):
# properties here...
comments = OneToMany("Comment")

class Comment (Entity):
# properties here...
post = ManyToOne("Post")

You might want to specify backrefs, if you'd have more
one-to-many-relationships between Post and Comments, like
this:

class Post (Entity):
# properties here...
comments = OneToMany("Comment", backref="post")

class Comment (Entity):
# properties here...
post = ManyToOne("Post", backref="comments")

details here:
http://turboentity.ematia.de/docs.html#s3

Daniel

gasolin

unread,
Nov 2, 2006, 5:22:34 AM11/2/06
to TurboGears
Hi:

Thanks Daniel, I've made the simpleblog-part-1/part-2 porting to
turboentity, turboentity saved lots of code indeed.

Here's the Turboentity version of Simpleblog:

Simpleblog I
http://inet6.blogspot.com/2006/10/turboentity-simpleblog.html

Simpleblog II
http://inet6.blogspot.com/2006/11/turboentity-simpleblog.html

Daniel Haus

unread,
Nov 2, 2006, 5:39:04 AM11/2/06
to TurboGears
Awsome!

Most of the text looks cryptic to me (I'm german),
still the source code looks nice, thank you.

Mark Ramm

unread,
Nov 8, 2006, 7:16:16 PM11/8/06
to turbo...@googlegroups.com
> > Also, the web site specifically mentions that it was built with
> > TurboGears in mind, and even includes an example for providing an
> > identity model for turbogears. Very exciting news, and I have already
> > contacted the author about the possibility of supplanting ActiveMapper
> > as the recommended declarative layer for SQLAlchemy.
>
> Shh... we've got a book coming out in a few days that has a chapter
> on using ActiveMapper ;)

If you decide to use TurboEntity, I think I could be persuaded to
create a second downloadble appendix to cover that too. ;)

iain duncan

unread,
Nov 8, 2006, 7:24:36 PM11/8/06
to turbo...@googlegroups.com

Persuading, right here! Twist, twist. ;)

Iain


gasolin

unread,
Nov 8, 2006, 10:41:30 PM11/8/06
to TurboGears
I'm not sure if I missed something but ManyToMany relationship didn't
work for Simpleblog III


class Post(Entity):
tags = ManyToMany('Tag')

class Tag(Entity):
posts = ManyToMany('Post')


Besides that, its still the best of breed choice for me.

----
Fred

Jonathan LaCour

unread,
Nov 9, 2006, 1:36:57 PM11/9/06
to turbo...@googlegroups.com
Mark Ramm wrote:

>> Shh... we've got a book coming out in a few days that has a chapter
>> on using ActiveMapper ;)
>
> If you decide to use TurboEntity, I think I could be persuaded to
> create a second downloadble appendix to cover that too. ;)

Expect an announcement in the next few weeks about TurboEntity and
ActiveMapper joining forces. We are in active talks, and the end
result will likely be slightly different than what is available now.

Tim Lesher

unread,
Nov 9, 2006, 10:44:07 PM11/9/06
to turbo...@googlegroups.com

Any chance that this "end result" will include something like Rails' "Acts"?
--
Tim Lesher <tle...@gmail.com>

Karl Guertin

unread,
Nov 9, 2006, 11:08:47 PM11/9/06
to turbo...@googlegroups.com
On 11/9/06, Tim Lesher <tle...@gmail.com> wrote:
> Any chance that this "end result" will include something like Rails' "Acts"?

Got an explanation for this? My google-fu is lacking.

Adam Jones

unread,
Nov 10, 2006, 12:11:20 AM11/10/06
to TurboGears

I'm guessing it is a reference to the various "acts_as_*" plugins that
make it relatively easy to add row metadata (tags, voting, commenting,
etc) to your model.

In looking at it, TG could go one step further with a
widgets-and-decorator combo. The idea would be that any acts_as_*
plugin comes with some widgets and a decorator that allow the following
to make the change from non-voteable to voteable:

Original:
@expose(template)
def entries(self):
return dict(entries=model.entries.select(), entry_widget=mywidget)

@acts_as_voteable(mywidget, voteable.vote_widget)
@expose(template)
def entries(self):
...

Same for commenting, tagging, and anything else you might want to do.
I've had this idea sitting in the back of my head for a while, it
probably needs some fleshing out before it will work, but I think the
"you can make stuff voteable/taggable/etc with just a decorator and
some widgets" idea is a solid one.

-Adam

gasolin

unread,
Nov 10, 2006, 5:55:14 AM11/10/06
to TurboGears
> Karl Guertin wrote:
> > On 11/9/06, Tim Lesher <tle...@gmail.com> wrote:
> > > Any chance that this "end result" will include something like Rails' "Acts"?
> >
> > Got an explanation for this? My google-fu is lacking.
>
> I'm guessing it is a reference to the various "acts_as_*" plugins that
> make it relatively easy to add row metadata (tags, voting, commenting,
> etc) to your model.
>

I took a look at Agile Rails book.
Besides the relationship between tables(OneToMany, ManyToMany...etc),
"acts_as_*" are the metadata(such as tablename is the metadata for sql
table, but acts_as_* are the metadata for model) for ActiveRecord
(rails ORM), which add an predefined set of methods to manipulate the
model.

For example, add a line to specify "acts_as_list" in model's metadata
could put results in order and act as a list;
"acts_as_tree" add some methods to play model like the tree structure.

SQLAlchemy/TurboEntity didn't have such stuff currently, but its not a
hard thing to warp a method to access SQLAlchemy/TurboEntity model in
native python code.

--
Fred

Robin Haswell

unread,
Nov 10, 2006, 10:10:59 AM11/10/06
to turbo...@googlegroups.com
Jonathan LaCour wrote:
> Expect an announcement in the next few weeks about TurboEntity and
> ActiveMapper joining forces. We are in active talks, and the end
> result will likely be slightly different than what is available now.

That sounds great, I really appreciate the work you guys are putting in
on the SA front. I left TG because of SO!

I wonder will there be an oppertunity to request some features? There
are bits of SO that I really liked that I miss, but I don't want to
sound whine-y :-)

Cheers

-Rob

Jonathan LaCour

unread,
Nov 10, 2006, 11:30:26 AM11/10/06
to turbo...@googlegroups.com
Tim Lesher wrote:

>> Expect an announcement in the next few weeks about TurboEntity and
>> ActiveMapper joining forces. We are in active talks, and the end
>> result will likely be slightly different than what is available now.
>
> Any chance that this "end result" will include something like Rails'
> "Acts"?

We are looking at other such projects for inspiration to be sure. I
have used Rails' ActiveRecord a bit, and definitely found some things
there that are inspiring, and some things that aren't so inspiring.

And we are definitely open to suggestions. At this point there are
three of us with three different code bases with three slightly
different APIs. We are discussing any and every idea, and all of our
different approaches to the same problem. We welcome any ideas that
you may have!

Tim Lesher

unread,
Nov 12, 2006, 12:44:50 PM11/12/06
to turbo...@googlegroups.com
On 11/10/06, Adam Jones <ajo...@gmail.com> wrote:
>
>
> Karl Guertin wrote:
> > On 11/9/06, Tim Lesher <tle...@gmail.com> wrote:
> > > Any chance that this "end result" will include something like Rails' "Acts"?
> >
> > Got an explanation for this? My google-fu is lacking.
>
> I'm guessing it is a reference to the various "acts_as_*" plugins that
> make it relatively easy to add row metadata (tags, voting, commenting,
> etc) to your model.

It's a bit more than metadata. If you go back to the original
definition of the "active record" pattern (not the ActiveRecord
implemention in rails), it's all about encapsulating both data and
logic.

In practical terms, an "Act" adds metadata, domain logic, and
rendering logic (and customization hooks) to an object in a single
line of code, in a way that's easy to extend and easy to predict
(reducing interoperability issues).

For example, taking the "taggable" example, making an object
definition "taggable" would add not only the data columns and relation
tables to store tags, but it also would add methods like tag() and
untag() to the object itself. Votable might add (using SQLObject
notation) methods like vote(self, voter, vote_amount),
_get_avg_vote(self), _get_num_votes(self), _get_voters(self), etc.

> In looking at it, TG could go one step further with a
> widgets-and-decorator combo. The idea would be that any acts_as_*
> plugin comes with some widgets and a decorator that allow the following
> to make the change from non-voteable to voteable:
>
> Original:
> @expose(template)
> def entries(self):
> return dict(entries=model.entries.select(), entry_widget=mywidget)
>
> @acts_as_voteable(mywidget, voteable.vote_widget)
> @expose(template)
> def entries(self):
> ...
>

I'm not sure what purpose the decorator serves in your example. I
think the voteable object be enough to bring the appropriate widgets
along.

I haven't dug too deeply into the Ruby magic that implements Act, but
I believe that their approach is aggregation-based rather than
inheritance-based. It seems that one way to get this behavior would
be making TurboEntity support MI, but that has the usual set of
issues.

--
Tim Lesher <tle...@gmail.com>

isaac

unread,
Nov 13, 2006, 11:49:08 AM11/13/06
to turbo...@googlegroups.com
On 11/10/06, Jonathan LaCour <jonatha...@cleverdevil.org> wrote:

> And we are definitely open to suggestions. At this point there are
> three of us with three different code bases with three slightly
> different APIs. We are discussing any and every idea, and all of our
> different approaches to the same problem. We welcome any ideas that
> you may have!

I'd like to see migrate come along with this project.
http://erosson.com/migrate/docs/

gasolin

unread,
Nov 19, 2006, 4:48:20 AM11/19/06
to TurboGears
> "acts_as_*" are the metadata(such as tablename is the metadata for sql
> table, but acts_as_* are the metadata for model) for ActiveRecord
> (rails ORM), which add an predefined set of methods to manipulate the
> model.
>
> For example, add a line to specify "acts_as_list" in model's metadata
> could put results in order and act as a list;
> "acts_as_tree" add some methods to play model like the tree structure.
>
> SQLAlchemy/TurboEntity didn't have such stuff currently, but its not a
> hard thing to warp a method to access SQLAlchemy/TurboEntity model in
> native python code.
>
> --
> Fred


To provide extra methods to implement "act_as" function,
I wonder if it's possible to inherit "Entity" class rather than declare
"act_as" in metadata?

For example:

class Book (List): # declare in class, multiple inheritance possible
class turboentity:
tablename = "book"

rather than:

class Book (Entity):
class turboentity:
tablename = "book"
act_as = "List" # declare "act_as" in metadata


----
Fred

Jorge Godoy

unread,
Nov 19, 2006, 5:51:57 AM11/19/06
to turbo...@googlegroups.com
"gasolin" <gas...@gmail.com> writes:

> To provide extra methods to implement "act_as" function,
> I wonder if it's possible to inherit "Entity" class rather than declare
> "act_as" in metadata?
>
> For example:
>
> class Book (List): # declare in class, multiple inheritance possible
> class turboentity:
> tablename = "book"
>
> rather than:
>
> class Book (Entity):
> class turboentity:
> tablename = "book"
> act_as = "List" # declare "act_as" in metadata

Personally I prefer the second option. It is more readable and lets your
intentions clearer.

--
Jorge Godoy <jgo...@gmail.com>

Tim Lesher

unread,
Nov 19, 2006, 7:21:41 PM11/19/06
to turbo...@googlegroups.com
On 11/19/06, Jorge Godoy <jgo...@gmail.com> wrote:
> > class Book (Entity):
> > class turboentity:
> > tablename = "book"
> > act_as = "List" # declare "act_as" in metadata
>
> Personally I prefer the second option. It is more readable and lets your
> intentions clearer.

Rails uses Ruby mixins for this, which do end up looking a lot like
the above approach, but that's the standard Ruby idiom (since Ruby
doesn't support multiple inheritance).

I'd very slightly prefer a MI approach (assuming the usual issues with
MI can be worked around), if for no other reason than it's more
idiomatic in Python, and it's more discoverable and explorable from an
interactive shell (one of my complaints with SQLObject right now).

--
Tim Lesher <tle...@gmail.com>

Reply all
Reply to author
Forward
0 new messages