Arghh.  Accidentally hitting 'Tab' in google groups takes you to the
'Send' button, then your next spacebar press prematurely sends your
post.

Ok, add the following property on Itemtype:

@property
def full_heritage(self):
    result = self.inherits[:]
    if result:
        for inherited in self.inherits:
            result.extend(inherited.full_heritage)
    return result

... this is just recursively building a list of all nodes involved in
inheritance from a given Itemtype node upward through the graph.

Then change the method on Feature:

def determinants_in_scope_of(self, itemtype):
    targets = map(lambda x: x.name, itemtype.full_heritage)
    targets.append(itemtype.name)
    return (session.query(Feature)
        .join(FeatureDependency.determinant)
        .join(Feature.root_itemtype)
        .filter(and_(FeatureDependency.dependent_id==self.id,
            Itemtype.name.in_(targets)))).all()

Now this machinery does exactly what I want.  I look forward to
showing you what it's really used for eventually.  Ciao!

Eric


On Nov 25, 1:57 am, Eric Ongerth <[EMAIL PROTECTED]> wrote:
> Well!  I guess that's exactly why we post sometimes -- the process of
> producing the test case bumps the unconscious forward a few steps.  I
> quit and did some pleasure reading for a while then came back.  Here's
> my own answer that does exactly what I needed it to do.
>
> Add the following property on Itemtype:
>
> @property
> def full_heritage(self):
>
> On Nov 25, 12:42 am, Eric Ongerth <[EMAIL PROTECTED]> wrote:
>
> > Unfortunately, I posted the wrong version of my Itemtype class above;
> > fortunately it wasn't important for what I was trying to show.  Please
> > replace class Itemtype with the following, and note the additional
> > test lines and commentary which I also forgot to include.
>
> > class Itemtype(object):
>
> >     def __repr__(self):
> >         return 'Itemtype: %s' % (self.name)
>
> >     @property
> >     def inherited_features(self):
> >         return ([feature for base_itemtype in self.inherits for
> > feature in base_itemtype.features])
>
> >     @property
> >     def features(self):
> >         result = self.own_features[:]
> >         if self.inherits:
> >             result.extend(self.inherited_features[:])
> >         return result
>
> >     @property
> >     def dependent_features(self):
> >         return [f for f in self.features if f.determinants]
>
> >     @property
> >     def independent_features(self):
> >         return [f for f in self.features if not f.determinants]
>
> > The code i posted the first time was not the right code for the
> > inherited_features and features properties on Itemtype.  I must have
> > cut and pasted from the wrong test file.
>
> > Please observe the following interactions which may help paint a
> > clearer picture of what I'm doing with this stuff.
>
> > >>>Boot.features
>
> > [Footwear Gender, Footwear US Shoe Size, Product Manufacturer, Product
> > Model, Product Year, Product Weight]
>
> > >>>Boot.dependent_features
>
> > [Product Weight]
>
> > >>>Boot.independent_features
>
> > [Footwear Gender, Footwear US Shoe Size, Product Manufacturer, Product
> > Model, Product Year]
>
> > >>>Footwear.inherited_features
>
> > [Product Manufacturer, Product Model, Product Year, Product Weight]
>
> > >>>Footwear.own_features
>
> > [Footwear Gender, Footwear US Shoe Size]
>
> > These are all examples of some of the useful things I'm using this for
> > -- keeping track of which variables ('features'), in an inheriting/
> > cascading type system, are dependent and which ones are independent.
> > Later, when values are entered and stored for each feature, the
> > relationships between the values will be constrained by these same
> > feature dependency links, without having to repeat them at that time.
>
> > Sorry for the wrong code before.  Oh yeah, I forgot to demonstrate
> > this too, but it's trivial:
>
> > >>>Model = session.query(Feature).filter_by(name='Model').one()
> > >>>Model.dependents
> > [Product weight]
> > >>>Gender.dependents
>
> > [Product weight]
>
> > ... so all this works the other way around too, though requesting the
> > dependents of a given feature is not as interesting as requesting a
> > given feature's determinants.
>
> > Eric
>
> > On Nov 24, 11:51 pm, Eric Ongerth <[EMAIL PROTECTED]> wrote:
>
> > > Below, I have attached a working testcase.  It works, yes -- but my
> > > question is that I need to make an improved version of a particular
> > > method on one of my classes.  The following model will probably
> > > explain itself for the most part.  I'll let you read it first, then
> > > offer a few explanatory notes afterward just in case.  Finally, at the
> > > end, I will describe the difference between what the method in
> > > question does now, and what I would like it to do.
>
> > > The nature of the response I am seeking is: a description of what I
> > > need to do to build a better version of the method I'm speaking of,
> > > including any further insight on the practice of joining at multiple
> > > levels of a recursive / self-referential (but loop-free) graph.
>
> > > ---snip---
>
> > > from sqlalchemy import *
> > > from sqlalchemy.sql import *
> > > from sqlalchemy.orm import *
>
> > > engine = create_engine('sqlite://')
>
> > > metadata = MetaData(bind=engine)
>
> > > itemtypes = Table('itemtypes', metadata,
> > >     Column('name', Text, primary_key=True))
>
> > > itemtype_inheritance = Table('itemtype_inheritance', metadata,
> > >     Column('itemtype_name', Text, ForeignKey('itemtypes.name'),
> > > primary_key=True),
> > >     Column('parent_name', Text, ForeignKey('itemtypes.name'),
> > > primary_key=True))
>
> > > features = Table('features', metadata,
> > >     Column('id', Integer, primary_key=True),
> > >     Column('name', Text),
> > >     Column('root_itemtype_name', Text, ForeignKey('itemtypes.name')))
>
> > > feature_dependencies = Table('feature_dependencies', metadata,
> > >     Column('dependent_id', Integer, ForeignKey('features.id'),
> > > primary_key=True),
> > >     Column('determinant_id', Integer, ForeignKey('features.id'),
> > > primary_key=True))
>
> > > metadata.drop_all()
> > > metadata.create_all()
>
> > > itemtypes.insert().execute([
> > >     {'name': 'Product'},
> > >     {'name': 'Footwear'},
> > >     {'name': 'Boot'},
> > >     {'name': 'Ski'}
> > > ])
>
> > > itemtype_inheritance.insert().execute([
> > >     {'itemtype_name': 'Footwear', 'parent_name': 'Product'},
> > >     {'itemtype_name': 'Boot', 'parent_name': 'Footwear'},
> > >     {'itemtype_name': 'Ski', 'parent_name': 'Product'}
> > > ])
>
> > > features.insert().execute([
> > >     {'id': 1, 'name': 'Manufacturer',
> > > 'root_itemtype_name':'Product' },
> > >     {'id': 2, 'name': 'Model', 'root_itemtype_name':'Product' },
> > >     {'id': 3, 'name': 'Year', 'root_itemtype_name':'Product' },
> > >     {'id': 4, 'name': 'Gender', 'root_itemtype_name':'Footwear' },
> > >     {'id': 5, 'name': 'US Shoe Size',
> > > 'root_itemtype_name':'Footwear' },
> > >     {'id': 6, 'name': 'Length', 'root_itemtype_name':'Ski' },
> > >     {'id': 7, 'name': 'Weight', 'root_itemtype_name':'Product' }
>
> > > ])
>
> > > feature_dependencies.insert().execute([
> > >     {'dependent_id': 7, 'determinant_id': 1},
> > >     {'dependent_id': 7, 'determinant_id': 2},
> > >     {'dependent_id': 7, 'determinant_id': 3},
> > >     {'dependent_id': 7, 'determinant_id': 4},
> > >     {'dependent_id': 7, 'determinant_id': 5},
> > >     {'dependent_id': 7, 'determinant_id': 6}
> > > ])
>
> > > class Itemtype(object):
>
> > >     def __repr__(self):
> > >         return 'Itemtype: %s' % (self.name)
>
> > >     @property
> > >     def inherited_features(self):
> > >         return reduce(list.extend,
> > >                       [base_itemtype.features for base_itemtype in
> > > self.inherits],
> > >                       [])
>
> > >     @property
> > >     def features(self):
> > >         return self.own_features.extend(self.inherited_features)
>
> > >     @property
> > >     def dependent_features(self):
> > >         return [f for f in self.features if f.determinants]
>
> > >     @property
> > >     def independent_features(self):
> > >         return [f for f in self.features if not f.determinants]
>
> > > class Feature(object):
>
> > >     def __repr__(self):
> > >         return '%s %s' % (self.root_itemtype_name, self.name)
>
> > >     def determinants_in_scope_of(self, itemtype):
> > >         return (session.query(Feature)
> > >                 .join(FeatureDependency.determinant)
> > >                 .join(Feature.root_itemtype)
> > >                 .filter(and_(FeatureDependency.dependent_id==self.id,
> > >                              Itemtype.name==itemtype.name))).all()
>
> > > class FeatureDependency(object):
>
> > >     def __repr__(self):
> > >         return "F_D: %s depends on %s" % (self.dependent.name,
> > >                                           self.determinant.name)
>
> > > mapper(Itemtype, itemtypes, properties={
> > >     'inherits':relation(Itemtype,
> > >         secondary=itemtype_inheritance,
> > >         primaryjoin=
> > > (itemtypes.c.name==itemtype_inheritance.c.itemtype_name),
> > >         secondaryjoin=
> > > (itemtype_inheritance.c.parent_name==itemtypes.c.name),
> > >         backref='progeny'),
> > >     'own_features':relation(Feature,
> > >         primaryjoin=(features.c.root_itemtype_name==itemtypes.c.name),
> > >         backref=backref('root_itemtype', uselist=False))
> > >     })
>
> > > mapper(Feature, features, properties={
> > >     'dependents':relation(Feature,
> > >         secondary=feature_dependencies,
> > >         primaryjoin=
> > > (feature_dependencies.c.determinant_id==features.c.id),
> > >         secondaryjoin=
> > > (feature_dependencies.c.dependent_id==features.c.id),
> > >         backref=backref('determinants'))
> > >     })
>
> > > mapper(FeatureDependency, feature_dependencies, properties={
> > >     'dependent':relation(Feature,
> > >         uselist=False,
> > >         primaryjoin=
> > > (feature_dependencies.c.dependent_id==features.c.id),
> > >         backref='feature_dependencies_as_dependent'),
> > >     'determinant':relation(Feature,
> > >         uselist=False,
> > >         primaryjoin=
> > > (feature_dependencies.c.determinant_id==features.c.id),
> > >         backref='feature_dependencies_as_determinant')
> > >     })
>
> > > Session = sessionmaker(bind=engine)
> > > session = Session()
>
> > > Product = session.query(Itemtype).filter_by(name='Product').one()
> > > Ski = session.query(Itemtype).filter_by(name='Ski').one()
> > > Footwear = session.query(Itemtype).filter_by(name='Footwear').one()
> > > Boot = session.query(Itemtype).filter_by(name='Boot').one()
> > > Weight = session.query(Feature).filter_by(name='Weight').one()
> > > Gender =
>
> ...
>
> read more »
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to