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 = session.query(Feature).filter_by(name='Gender').one() > > Year = session.query(Feature).filter_by(name='Year').one() > > > ---snip--- > > > (to anyone who wants to play with this and doesn't know how, save the > > above code as testcase.py, and then run it from shell with python -i > > testcase.py; you then have a Python interpreter with all of the above > > objects still active, including the sqlalchemy session, with the > > ability to query and experiment). > > > Notes on what this is supposed to model: Here are some of the facts in > > the problem domain. > > > Each Itemtype inherits from others above it, except for root itemtypes > > (the only one of which in this example is Product). The reason for > > using an inheritance paradigm here is so that you can set Features on > > any Itemtype and have them inherited by all of the subcategories (sub- > > Itemtypes) of that Itemtype. In other words, once you give the > > itemtype > > ... > > 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 -~----------~----~----~----~------~----~------~--~---