110 global TRACED_OIDS |
110 global TRACED_OIDS |
111 TRACED_OIDS = () |
111 TRACED_OIDS = () |
112 return traceback is None |
112 return traceback is None |
113 |
113 |
114 |
114 |
115 def score_interface(cls_or_inst, cls, iface): |
115 def score_interface(etypesreg, cls_or_inst, cls, iface): |
116 """Return XXX if the give object (maybe an instance or class) implements |
116 """Return XXX if the give object (maybe an instance or class) implements |
117 the interface. |
117 the interface. |
118 """ |
118 """ |
119 if getattr(iface, '__registry__', None) == 'etypes': |
119 if getattr(iface, '__registry__', None) == 'etypes': |
120 # adjust score if the interface is an entity class |
120 # adjust score if the interface is an entity class |
121 parents = cls_or_inst.parent_classes() |
121 parents = etypesreg.parent_classes(cls_or_inst.id) |
122 if iface is cls: |
122 if iface is cls: |
123 return len(parents) + 4 |
123 return len(parents) + 4 |
124 if iface is parents[-1]: # Any |
124 if iface is parents[-1]: # Any |
125 return 1 |
125 return 1 |
126 for index, basecls in enumerate(reversed(parents[:-1])): |
126 for index, basecls in enumerate(reversed(parents[:-1])): |
155 |
155 |
156 def __str__(self): |
156 def __str__(self): |
157 return '%s(%s)' % (self.__class__.__name__, |
157 return '%s(%s)' % (self.__class__.__name__, |
158 ','.join(str(s) for s in self.expected_ifaces)) |
158 ','.join(str(s) for s in self.expected_ifaces)) |
159 |
159 |
160 def score_interfaces(self, cls_or_inst, cls): |
160 def score_interfaces(self, req, cls_or_inst, cls): |
161 score = 0 |
161 score = 0 |
162 vreg, eschema = cls_or_inst.vreg, cls_or_inst.e_schema |
162 etypesreg = req.vreg['etypes'] |
|
163 eschema = cls_or_inst.e_schema |
163 for iface in self.expected_ifaces: |
164 for iface in self.expected_ifaces: |
164 if isinstance(iface, basestring): |
165 if isinstance(iface, basestring): |
165 # entity type |
166 # entity type |
166 try: |
167 try: |
167 iface = vreg['etypes'].etype_class(iface) |
168 iface = etypesreg.etype_class(iface) |
168 except KeyError: |
169 except KeyError: |
169 continue # entity type not in the schema |
170 continue # entity type not in the schema |
170 score += score_interface(cls_or_inst, cls, iface) |
171 score += score_interface(etypesreg, cls_or_inst, cls, iface) |
171 return score |
172 return score |
172 |
173 |
173 |
174 |
174 class EClassSelector(Selector): |
175 class EClassSelector(Selector): |
175 """abstract class for selectors working on the entity classes of the result |
176 """abstract class for selectors working on the entity classes of the result |
209 return score |
210 return score |
210 |
211 |
211 def score(self, cls, req, etype): |
212 def score(self, cls, req, etype): |
212 if etype in BASE_TYPES: |
213 if etype in BASE_TYPES: |
213 return 0 |
214 return 0 |
214 return self.score_class(cls.vreg['etypes'].etype_class(etype), req) |
215 return self.score_class(req.vreg['etypes'].etype_class(etype), req) |
215 |
216 |
216 def score_class(self, eclass, req): |
217 def score_class(self, eclass, req): |
217 raise NotImplementedError() |
218 raise NotImplementedError() |
218 |
219 |
219 |
220 |
558 self.registry = registry |
559 self.registry = registry |
559 self.oid = oid |
560 self.oid = oid |
560 |
561 |
561 def __call__(self, cls, req, **kwargs): |
562 def __call__(self, cls, req, **kwargs): |
562 try: |
563 try: |
563 cls.vreg[self.registry].select(self.oid, req, **kwargs) |
564 req.vreg[self.registry].select(self.oid, req, **kwargs) |
564 return 1 |
565 return 1 |
565 except NoSelectableObject: |
566 except NoSelectableObject: |
566 return 0 |
567 return 0 |
567 |
568 |
568 |
569 |
582 |
583 |
583 note: when interface is an entity class, the score will reflect class |
584 note: when interface is an entity class, the score will reflect class |
584 proximity so the most specific object'll be selected |
585 proximity so the most specific object'll be selected |
585 """ |
586 """ |
586 def score_class(self, eclass, req): |
587 def score_class(self, eclass, req): |
587 return self.score_interfaces(eclass, eclass) |
588 return self.score_interfaces(req, eclass, eclass) |
588 |
589 |
589 |
590 |
590 class specified_etype_implements(implements): |
591 class specified_etype_implements(implements): |
591 """accept if entity class specified using an 'etype' parameters in name |
592 """accept if entity class specified using an 'etype' parameters in name |
592 argument or request form implements at least one of the interfaces given as |
593 argument or request form implements at least one of the interfaces given as |
612 return 0 |
613 return 0 |
613 else: |
614 else: |
614 # only check this is a known type if etype comes from req.form, |
615 # only check this is a known type if etype comes from req.form, |
615 # else we want the error to propagate |
616 # else we want the error to propagate |
616 try: |
617 try: |
617 etype = cls.vreg.case_insensitive_etypes[etype.lower()] |
618 etype = req.vreg.case_insensitive_etypes[etype.lower()] |
618 req.form['etype'] = etype |
619 req.form['etype'] = etype |
619 except KeyError: |
620 except KeyError: |
620 return 0 |
621 return 0 |
621 return self.score_class(cls.vreg['etypes'].etype_class(etype), req) |
622 return self.score_class(req.vreg['etypes'].etype_class(etype), req) |
622 |
623 |
623 |
624 |
624 class entity_implements(ImplementsMixIn, EntitySelector): |
625 class entity_implements(ImplementsMixIn, EntitySelector): |
625 """accept if entity instances found in the result set implements at least one |
626 """accept if entity instances found in the result set implements at least one |
626 of the interfaces given as argument. Returned score is the number of |
627 of the interfaces given as argument. Returned score is the number of |
635 |
636 |
636 note: when interface is an entity class, the score will reflect class |
637 note: when interface is an entity class, the score will reflect class |
637 proximity so the most specific object'll be selected |
638 proximity so the most specific object'll be selected |
638 """ |
639 """ |
639 def score_entity(self, entity): |
640 def score_entity(self, entity): |
640 return self.score_interfaces(entity, entity.__class__) |
641 return self.score_interfaces(entity.req, entity, entity.__class__) |
641 |
642 |
642 |
643 |
643 class relation_possible(EClassSelector): |
644 class relation_possible(EClassSelector): |
644 """accept if entity class found in the result set support the relation. |
645 """accept if entity class found in the result set support the relation. |
645 |
646 |