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