Re: [Repoze-dev] object graph traversal question

2009-11-12 Thread Malthe Borch
2009/11/12 F. Oliver Gathmann gathm...@cenix-bioscience.com:
 I guess I'm asking if there is a standard, bfg-approved way of avoiding
 artificial container model classes - or did I just not get it yet?!

You can use ``*subpath`` (or any other name of your choice) to
retrieve this match as-is, without invoking the traverser.

\malthe
___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


Re: [Repoze-dev] object graph traversal question

2009-11-12 Thread Chris McDonough
F. Oliver Gathmann wrote:
 Hello!
 
 Coming from Pylons, I'm a newbie to the object graph traversal world, so 
 this question might be slightly misplaced (but hopefully a no-brainer 
 for the bfg gurus...).
 
 I very much like the concept of looking up my model object before 
 dispatching to a view that operates on it. However, what bothers me 
 about the standard traversal algorithm is that, for a URL like
 
 /cars/beetle/wheels/front_left
 
 I have to promote the containers (cars and wheels) to first class 
 citizens in my model (by defining CarContainer and WheelContainer 
 classes that I can then instantiate and return as the context object 
 from the parent's __getitem__), where in fact they are just collections 
 held by their mutual parent model objects (the Root object in case of 
 the cars collection - which is in itself artificial, but I'm willing to 
 pay that price for traversability - and the Car object in case of the 
 wheels collection).

Great question.

The short answer is yes, you have to define the intermediate artificial 
objects if you want to use traversal.

There are number of ways to conceptualize this.

The first way would be to not consider this a traversal problem at all and do 
it as you might in Pylons by registering a route that had static parts and 
dynamic parts:

route
   name=wheel
   path=/cars/:type/wheels/:wheel
   view=.views.wheel_view/

This will do more or less what you expect, but your view will need to resolve 
the dynamic bits from your model.

The paster template closest to this model is bfg_routesalchemy.

Another way to do it would be to use *only* traversal and define an object 
graph:

class Root(dict):
  def __getitem__(self, name):
  return self[name]

class Cars(object):
 def __getitem__(self, name):
  use the rdb to find the car model and return a Car ...


class Car(object):
 def __getitem__(self, name):
  use the rdb to find the part (such as a Wheel) and return it...

class Wheel(object):
 # leaf node
 pass

model_graph = Root({'cars':Cars()})

def get_root(request):
 return model_graph

Then define a view like so:

view
view=.views.wheel_view
for=.models.Wheel
/

Then the URL to a wheel model might be:

/cars/beetle/front_wheel

You can choose to inject a wheels collection in there too should you want, 
but since objects have a type in this setup, it's not strictly necessary.

The paster template closest to this model is bfg_alchemy (or bfg_zodb but 
that uses ZODB rather than SQL).

Those are the two sanest ways to do this.  There's another mode that combines 
both traversal and url dispatch (routes), but I don't think it helps much here.

Malthe suggested that you can also use request.subpath.  This is the 
remainder of the path (as a tuple) when a traversal falls off the graph. 
Another (much cruder) way to getting this done would be to one root model and a 
single view and use request.subpath as a cue to that view about what needs to 
be done.  You could of course have a cars model that resolved a car and a 
view against the car, then use the remainder of the subpath to figure out which 
part to show; dialing use of request.subpath up or down in length.

 
 I guess I'm asking if there is a standard, bfg-approved way of 
 avoiding artificial container model classes - or did I just not get it 
 yet?!

No, you got it.

- C

___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


Re: [Repoze-dev] object graph traversal question

2009-11-12 Thread F. Oliver Gathmann


On 11/12/09 1:00 PM, Tim Hoffman wrote:

Hi

I have done some fairly extensive projects using traversal over a
relational model and we did use intermediate container classes alot.
Mainly because each major entity could have about 6 different classes
of sub items that we needed to group into containers anyway

I reverse engineered the entire relational model from the existing
database and then autogenerated all of the intermediate classes.
Quite easy to do.  I was using storm as an orm over the top, which
made things a lot easier
Hmm... still, this feels like an artifact to me. Presumably, in most 
cases what you want to return when the URL asks for a collection of 
sub-items is the very collection you already defined in your ORM on the 
model object that is the current context (we are using SQLAlchemy, BTW). 
I cannot help but think that there should be a way to automatically 
return an adapted collection that supports further traversal if 
necessary... but I'm not sure of all the ramifications of that idea.


Oliver


T

On Thu, Nov 12, 2009 at 7:43 PM, F. Oliver Gathmann
gathm...@cenix-bioscience.com  wrote:

On 11/12/09 11:03 AM, Tim Hoffman wrote:

Hi

I suppose it doesn't really matter how you go, and quite possibly the
deciding factor on why you might need
the wheel container and car container classes will depend on how you
access data,

For instance if you use something like zodb you can put arbitrary
entities inside other entities, (i.e someones/garage/beetle/frontleft)

where as  if you data is coming from a relational dbms the wheel
container class may in fact represent the table of all possible
wheels. and you
are using the beetle car to determine which instances of wheels
(wheels in the wheel table) that it owns.

That's precisely where we are coming from (we have a big legacy DB to deal
with).

If you have a really rigid relation model with a finite set of levels
then you may find you are creating arbitrary intermediate containers
just so you can define how you access the data. in this case maybe
routes may be a better alternative

Where as arbirtratry depth trees where each node can contain arbitrary
types (think of a filesystem containing many different file types or
potentially any depth)
really suit traversal as anything can probably be a container.

Oh - and I had hoped to be able to ditch routes now that I have model graph
traversal ;-). I'd say our relational model is neither rigid nor arbitrary -
we are constantly making changes but of course we stay within the limits of
our domain model.


Just my 2c worth.

I have to think some more about this, it seems - you 2c are much
appreciated, thanks!

Oliver

On Thu, Nov 12, 2009 at 5:40 PM, F. Oliver Gathmann
gathm...@cenix-bioscience.com  wrote:

Hello!

Coming from Pylons, I'm a newbie to the object graph traversal world, so
this question might be slightly misplaced (but hopefully a no-brainer for
the bfg gurus...).

I very much like the concept of looking up my model object before
dispatching to a view that operates on it. However, what bothers me about
the standard traversal algorithm is that, for a URL like

/cars/beetle/wheels/front_left

I have to promote the containers (cars and wheels) to first class
citizens in my model (by defining CarContainer and WheelContainer classes
that I can then instantiate and return as the context object from the
parent's __getitem__), where in fact they are just collections held by their
mutual parent model objects (the Root object in case of the cars collection
- which is in itself artificial, but I'm willing to pay that price for
traversability - and the Car object in case of the wheels collection).

I guess I'm asking if there is a standard, bfg-approved way of avoiding
artificial container model classes - or did I just not get it yet?!

I'm very grateful for any hints and pointers you may have on this issue.

Thanks,

Oliver

--

F. Oliver Gathmann, Ph.D.
Director IT Unit
Cenix BioScience GmbH
Tatzberg 47   phone: +49 (351) 4173-136
D-01307 Dresden, Germany  fax:   +49 (351) 4173-109


-
Sitz der Gesellschaft (Place of Business): Dresden
Geschaeftsfuehrer (CEO): Dr. Christophe J. Echeverri
Amtsgericht (Local Court): Dresden, HRB 19964
Ust-ID (VAT-No.): DE205824437
-



___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev



--

F. Oliver Gathmann, Ph.D.
Director IT Unit
Cenix BioScience GmbH
Tatzberg 47   phone: +49 (351) 4173-136
D-01307 Dresden, Germany  fax:   +49 (351) 4173-109

Re: [Repoze-dev] object graph traversal question

2009-11-12 Thread F. Oliver Gathmann

On 11/12/09 1:20 PM, Tim Hoffman wrote:

Hi

On Thu, Nov 12, 2009 at 8:09 PM, F. Oliver Gathmann
gathm...@cenix-bioscience.com  wrote:



Hmm... still, this feels like an artifact to me. Presumably, in most cases
what you want to return when the URL asks for a collection of sub-items is
the very collection you already defined in your ORM on the model object that
is the current context


Except if an entity has multiple sub collections you need to define a
way of differentiating each sub collection from a traversal point of
view
If you want a listing of all the wheels then you need /garage/beetle/wheels

Now that would return all of the wheels.  Its up to you then if you
want to directly traverse to front wheel either by
/garage/beetle/front_wheel or /garage/beetle/wheels/front_wheel
We might also have a collection of doors   /garage/beetle/doors
And as long as you don't name a door front_wheel you would be fine not
traversing the wheel container.
I definitely would not want to rely on my users *not* to call a door 
front_wheel ;-)




It all comes down to how you would be identifying any particular child entity.

Yes, that makes sense.

(we are using SQLAlchemy, BTW).

Never used that.


  I cannot help but

think that there should be a way to automatically return an adapted
collection that supports further traversal if necessary... but I'm not sure
of all the ramifications of that idea.



Yep you could definatley do that. However as I pointed out earlier if
you have multiple sub collections you still need to identify the
collection/adapter.
In the case above wheels might be an adatper name (though I don't see
the difference really between an adapter or container class. Neither
in itself is persistent and an instance will only exist whilst
traversing.
That's a good point. I guess nobody would force me to keep the 
intermediary container classes *in* my model tree, either.


Thanks for all these thoughtful comments; I think, slowly, a picture is 
emerging :-)


Oliver



On Thu, Nov 12, 2009 at 7:43 PM, F. Oliver Gathmann

gathm...@cenix-bioscience.com  wrote:

On 11/12/09 11:03 AM, Tim Hoffman wrote:

Hi

I suppose it doesn't really matter how you go, and quite possibly the
deciding factor on why you might need
the wheel container and car container classes will depend on how you
access data,

For instance if you use something like zodb you can put arbitrary
entities inside other entities, (i.e someones/garage/beetle/frontleft)

where as  if you data is coming from a relational dbms the wheel
container class may in fact represent the table of all possible
wheels. and you
are using the beetle car to determine which instances of wheels
(wheels in the wheel table) that it owns.

That's precisely where we are coming from (we have a big legacy DB to deal
with).

If you have a really rigid relation model with a finite set of levels
then you may find you are creating arbitrary intermediate containers
just so you can define how you access the data. in this case maybe
routes may be a better alternative

Where as arbirtratry depth trees where each node can contain arbitrary
types (think of a filesystem containing many different file types or
potentially any depth)
really suit traversal as anything can probably be a container.

Oh - and I had hoped to be able to ditch routes now that I have model graph
traversal ;-). I'd say our relational model is neither rigid nor arbitrary -
we are constantly making changes but of course we stay within the limits of
our domain model.


Just my 2c worth.

I have to think some more about this, it seems - you 2c are much
appreciated, thanks!

Oliver

On Thu, Nov 12, 2009 at 5:40 PM, F. Oliver Gathmann
gathm...@cenix-bioscience.com  wrote:

Hello!

Coming from Pylons, I'm a newbie to the object graph traversal world, so
this question might be slightly misplaced (but hopefully a no-brainer for
the bfg gurus...).

I very much like the concept of looking up my model object before
dispatching to a view that operates on it. However, what bothers me about
the standard traversal algorithm is that, for a URL like

/cars/beetle/wheels/front_left

I have to promote the containers (cars and wheels) to first class
citizens in my model (by defining CarContainer and WheelContainer classes
that I can then instantiate and return as the context object from the
parent's __getitem__), where in fact they are just collections held by their
mutual parent model objects (the Root object in case of the cars collection
- which is in itself artificial, but I'm willing to pay that price for
traversability - and the Car object in case of the wheels collection).

I guess I'm asking if there is a standard, bfg-approved way of avoiding
artificial container model classes - or did I just not get it yet?!

I'm very grateful for any hints and pointers you may have on this issue.

Thanks,

Oliver

--

F. Oliver Gathmann, Ph.D.
Director IT Unit
Cenix 

Re: [Repoze-dev] object graph traversal question

2009-11-12 Thread F. Oliver Gathmann

On 11/12/09 1:33 PM, Chris McDonough wrote:

F. Oliver Gathmann wrote:


On 11/12/09 1:00 PM, Tim Hoffman wrote:

Hi

I have done some fairly extensive projects using traversal over a
relational model and we did use intermediate container classes alot.
Mainly because each major entity could have about 6 different classes
of sub items that we needed to group into containers anyway

I reverse engineered the entire relational model from the existing
database and then autogenerated all of the intermediate classes.
Quite easy to do.  I was using storm as an orm over the top, which
made things a lot easier
Hmm... still, this feels like an artifact to me. Presumably, in most 
cases what you want to return when the URL asks for a collection of 
sub-items is the very collection you already defined in your ORM on 
the model object that is the current context (we are using 
SQLAlchemy, BTW). I cannot help but think that there should be a way 
to automatically return an adapted collection that supports further 
traversal if necessary... but I'm not sure of all the ramifications 
of that idea.


I suspect there should be a pattern for this.  This pattern might be a 
good one, though I don't know to what extent it can be generalized:


class TraversableCollection(object):
def __init__(self, parent, name, collection):
self.__parent__ = parent
self.__name__ = name
self.collection = collection

def __getitem__(self, name):
return getattr(self.collection, name) # or whatever the API is

class Cars(object):
def __getitem__(self, name):
collection = get_collection(model, name) # some helper thing
return TraversableCollection(self, name, collection)

Might be generalizable via a subclass:

class Collection(object):
def __getitem__(self, name):
collection = get_collection(model, name) # some helper thing
return self.collection_class(self, name, collection)

class Cars(Collection):
collection_class = TraversableCollection

Or via Zope-style adaptation.

- C


Cool - this is exactly what I had in mind.

I am really impressed by the number and quality of the comments I got on 
my little newbie question! Seems we made the right choice by basing our 
new server framework on repoze.bfg ;-)


Cheers,

Oliver

___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev


Re: [Repoze-dev] object graph traversal question

2009-11-12 Thread Tres Seaver
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

F. Oliver Gathmann wrote:
 On 11/12/09 1:00 PM, Tim Hoffman wrote:
 Hi

 I have done some fairly extensive projects using traversal over a
 relational model and we did use intermediate container classes alot.
 Mainly because each major entity could have about 6 different classes
 of sub items that we needed to group into containers anyway

 I reverse engineered the entire relational model from the existing
 database and then autogenerated all of the intermediate classes.
 Quite easy to do.  I was using storm as an orm over the top, which
 made things a lot easier
 Hmm... still, this feels like an artifact to me. Presumably, in most 
 cases what you want to return when the URL asks for a collection of 
 sub-items is the very collection you already defined in your ORM on the 
 model object that is the current context (we are using SQLAlchemy, BTW). 
 I cannot help but think that there should be a way to automatically 
 return an adapted collection that supports further traversal if 
 necessary... but I'm not sure of all the ramifications of that idea.

You might check out the BFG + Storm tutorial I dashed off:

  http://bfg.repoze.org/tutorialbin/6/

There, the container is responsible for mapping the URL segment onto the
ID used to look up the contained item from the ORM.  It also provides an
'__iter__' API for iterating the contents (for views on the container
itself) as well '__delitem__' as for removing an item, which is
logically an operation on the container in traversal land (think of a
directory on a filesystem).



Tres.
- --
===
Tres Seaver  +1 540-429-0999  tsea...@palladion.com
Palladion Software   Excellence by Designhttp://palladion.com
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkr8QzYACgkQ+gerLs4ltQ4bVQCdFtmdMPJh7Ud5fEcZcqVYeNvL
ynMAnAyeEjZIzQ7pshPpxGXYcBneUBi8
=Dvif
-END PGP SIGNATURE-
___
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev