Protect against crash in the `relation_possible` predicate with ambiguous relations.
It was still possible to get a KeyError when using relations that are ambiguous
at both ends, like (Executable, version_of, Program) & (Version, version_of, Project).
Closes #3010148.
--- a/predicates.py Fri Jun 14 16:02:39 2013 +0200
+++ b/predicates.py Mon Jul 15 10:40:49 2013 +0200
@@ -994,7 +994,11 @@
return 0 # relation not supported
if self.action:
if self.target_etype is not None:
- rschema = rschema.role_rdef(entity.e_schema, self.target_etype, self.role)
+ try:
+ rschema = rschema.role_rdef(entity.e_schema,
+ self.target_etype, self.role)
+ except KeyError:
+ return 0
if self.role == 'subject':
if not rschema.has_perm(entity._cw, self.action, fromeid=entity.eid):
return 0
--- a/test/unittest_predicates.py Fri Jun 14 16:02:39 2013 +0200
+++ b/test/unittest_predicates.py Mon Jul 15 10:40:49 2013 +0200
@@ -203,6 +203,17 @@
select=select, filtered_variable=select.defined_vars['X'])
self.assertEqual(score, 1)
+ def test_ambiguous(self):
+ # Ambiguous relations are :
+ # (Service, fabrique_par, Personne) and (Produit, fabrique_par, Usine)
+ # There used to be a crash here with a bad rdef choice in the strict
+ # checking case.
+ selector = relation_possible('fabrique_par', role='object',
+ target_etype='Personne', strict=True)
+ req = self.request()
+ usine = req.create_entity('Usine', lieu=u'here')
+ score = selector(None, req, rset=usine.as_rset())
+ self.assertEqual(0, score)
class MatchUserGroupsTC(CubicWebTC):
def test_owners_group(self):