# HG changeset patch # User Sylvain Thénault # Date 1280488688 -7200 # Node ID 3fd4a34c4a09850d69d2877b09e4d37f4f1cb2b0 # Parent f414a587075dc31fb74eef24fb1caec1f00313fc [selectors] fix is_instance bug w/ parent classes. Also slight performance enhancements by changing what's returned by vreg['etypes'].parent_classes method (dedicated for this usage...) and removing no more necessary methods diff -r f414a587075d -r 3fd4a34c4a09 cwvreg.py --- a/cwvreg.py Fri Jul 30 13:16:01 2010 +0200 +++ b/cwvreg.py Fri Jul 30 13:18:08 2010 +0200 @@ -310,11 +310,10 @@ @cached def parent_classes(self, etype): if etype == 'Any': - return [self.etype_class('Any')] - eschema = self.schema.eschema(etype) - parents = [self.etype_class(e.type) for e in eschema.ancestors()] - parents.append(self.etype_class('Any')) - return parents + return (), self.etype_class('Any') + parents = tuple(self.etype_class(e.type) + for e in self.schema.eschema(etype).ancestors()) + return parents, self.etype_class('Any') @cached def etype_class(self, etype): diff -r f414a587075d -r 3fd4a34c4a09 selectors.py --- a/selectors.py Fri Jul 30 13:16:01 2010 +0200 +++ b/selectors.py Fri Jul 30 13:18:08 2010 +0200 @@ -212,24 +212,24 @@ from cubicweb.appobject import traced_selection # XXX for bw compat -def score_interface(etypesreg, cls_or_inst, cls, iface): +def score_interface(etypesreg, eclass, iface): """Return XXX if the give object (maybe an instance or class) implements the interface. """ if getattr(iface, '__registry__', None) == 'etypes': # adjust score if the interface is an entity class - parents = etypesreg.parent_classes(cls_or_inst.__regid__) - if iface is cls: + parents, any = etypesreg.parent_classes(eclass.__regid__) + if iface is eclass: return len(parents) + 4 - if iface is parents[-1]: # Any + if iface is any: # Any return 1 - for index, basecls in enumerate(reversed(parents[:-1])): + for index, basecls in enumerate(reversed(parents)): if iface is basecls: return index + 3 return 0 # XXX iface in implements deprecated in 3.9 - if implements_iface(cls_or_inst, iface): - # implenting an interface takes precedence other special Any interface + if implements_iface(eclass, iface): + # implementing an interface takes precedence other special Any interface return 2 return 0 @@ -699,9 +699,6 @@ ','.join(str(s) for s in self.expected_ifaces)) def score_class(self, eclass, req): - return self.score_interfaces(req, eclass, eclass) - - def score_interfaces(self, req, cls_or_inst, cls): score = 0 etypesreg = req.vreg['etypes'] for iface in self.expected_ifaces: @@ -711,7 +708,7 @@ iface = etypesreg.etype_class(iface) except KeyError: continue # entity type not in the schema - score += score_interface(etypesreg, cls_or_inst, cls, iface) + score += score_interface(etypesreg, eclass, iface) return score def _reset_is_instance_cache(vreg): @@ -744,9 +741,6 @@ ','.join(str(s) for s in self.expected_etypes)) def score_class(self, eclass, req): - return self.score_etypes(req, eclass, eclass) - - def score_etypes(self, req, cls_or_inst, cls): # cache on vreg to avoid reloading issues cache = req.vreg._is_instance_selector_cache try: @@ -758,22 +752,20 @@ expected_eclasses = cache[self] = [] for etype in self.expected_etypes: try: - expected_eclasses.append( - (etypesreg.etype_class(etype), - etypesreg.parent_classes(etype)) - ) + expected_eclasses.append(etypesreg.etype_class(etype)) except KeyError: continue # entity type not in the schema + parents, any = req.vreg['etypes'].parent_classes(eclass.__regid__) score = 0 - for iface, parents in expected_eclasses: + for expectedcls in expected_eclasses: # adjust score according to class proximity - if iface is cls: + if expectedcls is eclass: score += len(parents) + 4 - elif iface is parents[-1]: # Any + elif expectedcls is any: # Any score += 1 else: - for index, basecls in enumerate(reversed(parents[:-1])): - if iface is basecls: + for index, basecls in enumerate(reversed(parents)): + if expectedcls is basecls: score += index + 3 break return score diff -r f414a587075d -r 3fd4a34c4a09 test/unittest_selectors.py --- a/test/unittest_selectors.py Fri Jul 30 13:16:01 2010 +0200 +++ b/test/unittest_selectors.py Fri Jul 30 13:18:08 2010 +0200 @@ -151,6 +151,11 @@ cls = self.vreg['etypes'].etype_class('Personne') self.failIf(is_instance('Societe').score_class(cls, self.request())) + def test_yams_inheritance(self): + cls = self.vreg['etypes'].etype_class('Transition') + self.assertEquals(is_instance('BaseTransition').score_class(cls, self.request()), + 3) + class MatchUserGroupsTC(CubicWebTC): def test_owners_group(self):