# HG changeset patch # User Pierre-Yves David # Date 1365425110 -7200 # Node ID 6ad000b91347fb7780f3514aa19f2d7fa1ff8790 # Parent 59a29405688c4f71fe5ecf19da7d5ab9ed672052# Parent 64f24ecad1777df46ae8c52b25f95592575cc536 merge 3.16.x fix in 3.17.x branch diff -r 59a29405688c -r 6ad000b91347 .hgtags --- a/.hgtags Thu Apr 04 17:45:09 2013 +0200 +++ b/.hgtags Mon Apr 08 14:45:10 2013 +0200 @@ -258,6 +258,8 @@ 81394043ad226942ac0019b8e1d4f7058d67a49f cubicweb-debian-version-3.14.8-1 9337812cef6b949eee89161190e0c3d68d7f32ea cubicweb-version-3.14.9 68c762adf2d5a2c338910ef1091df554370586f0 cubicweb-debian-version-3.14.9-1 +0ff798f80138ca8f50a59f42284380ce8f6232e8 cubicweb-version-3.14.10 +197bcd087c87cd3de9f21f5bf40bd6203c074f1f cubicweb-debian-version-3.14.10-1 783a5df54dc742e63c8a720b1582ff08366733bd cubicweb-version-3.15.1 fe5e60862b64f1beed2ccdf3a9c96502dfcd811b cubicweb-debian-version-3.15.1-1 2afc157ea9b2b92eccb0f2d704094e22ce8b5a05 cubicweb-version-3.15.2 @@ -278,6 +280,8 @@ 29fbc632a69667840294d7b38b0ca00e5f66ec19 cubicweb-debian-version-3.15.9-1 89bdb5444cd20213d5af03c2612ceb28340cb760 cubicweb-version-3.15.10 feca12e4a6188fbaae0cc48c6f8cc5f4202e1662 cubicweb-debian-version-3.15.10-1 +38c6a3ea8252e1a40452aad05e4aa25b43f66cd8 cubicweb-version-3.15.11 +09d65bc1f0253eacef4b480716b7c139ab9efc35 cubicweb-debian-version-3.15.11-1 6c7c2a02c9a0ca870accfc8ed1bb120e9c858d5d cubicweb-version-3.16.0 853237d1daf6710af94cc2ec8ee12aa7dba16934 cubicweb-debian-version-3.16.0-1 d95cbb7349f01b9e02e5da65d55a92582bbee6db cubicweb-version-3.16.1 diff -r 59a29405688c -r 6ad000b91347 __pkginfo__.py diff -r 59a29405688c -r 6ad000b91347 debian/changelog --- a/debian/changelog Thu Apr 04 17:45:09 2013 +0200 +++ b/debian/changelog Mon Apr 08 14:45:10 2013 +0200 @@ -10,6 +10,12 @@ -- Aurélien Campéas Wed, 23 Jan 2013 17:40:00 +0100 +cubicweb (3.15.11-1) squeeze; urgency=low + + * New upstream release + + -- Pierre-Yves David Mon, 08 Apr 2013 12:43:02 +0200 + cubicweb (3.15.10-1) squeeze; urgency=low * New upstream release @@ -85,6 +91,12 @@ -- Sylvain Thénault Thu, 12 Apr 2012 13:52:05 +0200 +cubicweb (3.14.10-1) unstable; urgency=low + + * new upstream release + + -- Pierre-Yves David Mon, 08 Apr 2013 12:18:20 +0200 + cubicweb (3.14.9-1) unstable; urgency=low * new upstream release diff -r 59a29405688c -r 6ad000b91347 devtools/devctl.py --- a/devtools/devctl.py Thu Apr 04 17:45:09 2013 +0200 +++ b/devtools/devctl.py Mon Apr 08 14:45:10 2013 +0200 @@ -675,13 +675,13 @@ class ExamineLogCommand(Command): """Examine a rql log file. - will print out the following table + Will print out the following table - total execution time || number of occurences || rql query + Percentage; Cumulative Time (clock); Cumulative Time (CPU); Occurences; Query - sorted by descending total execution time + sorted by descending cumulative time (clock). Time are expressed in seconds. - chances are the lines at the top are the ones that will bring the higher + Chances are the lines at the top are the ones that will bring the higher benefit after optimisation. Start there. """ arguments = 'rql.log' diff -r 59a29405688c -r 6ad000b91347 predicates.py --- a/predicates.py Thu Apr 04 17:45:09 2013 +0200 +++ b/predicates.py Mon Apr 08 14:45:10 2013 +0200 @@ -1,4 +1,4 @@ -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This file is part of CubicWeb. @@ -479,11 +479,8 @@ def __call__(self, cls, req, **kwargs): for regid in self.regids: - try: - req.vreg[self.registry].select(regid, req, **kwargs) + if req.vreg[self.registry].select_or_none(regid, req, **kwargs) is not None: return self.selectable_score - except NoSelectableObject: - continue return 0 @@ -501,11 +498,30 @@ def __call__(self, cls, req, **kwargs): kwargs.setdefault('accept_none', False) - # being adaptable to an interface should takes precedence other is_instance('Any'), - # but not other explicit is_instance('SomeEntityType'), and: + score = super(adaptable, self).__call__(cls, req, **kwargs) + if score == 0 and kwargs.get('rset') and len(kwargs['rset']) > 1 and not 'row' in kwargs: + # on rset containing several entity types, each row may be + # individually adaptable, while the whole rset won't be if the + # same adapter can't be used for each type + for row in xrange(len(kwargs['rset'])): + kwargs.setdefault('col', 0) + _score = super(adaptable, self).__call__(cls, req, row=row, **kwargs) + if not _score: + return 0 + # adjust score per row as expected by default adjust_score + # implementation + score += self.adjust_score(_score) + else: + score = self.adjust_score(score) + return score + + @staticmethod + def adjust_score(score): + # being adaptable to an interface should takes precedence other + # is_instance('Any'), but not other explicit + # is_instance('SomeEntityType'), and, for **a single entity**: # * is_instance('Any') score is 1 # * is_instance('SomeEntityType') score is at least 2 - score = super(adaptable, self).__call__(cls, req, **kwargs) if score >= 2: return score - 0.5 if score == 1: diff -r 59a29405688c -r 6ad000b91347 server/querier.py --- a/server/querier.py Thu Apr 04 17:45:09 2013 +0200 +++ b/server/querier.py Mon Apr 08 14:45:10 2013 +0200 @@ -63,8 +63,9 @@ def check_no_password_selected(rqlst): """check that Password entities are not selected""" for solution in rqlst.solutions: - if 'Password' in solution.itervalues(): - raise Unauthorized('Password selection is not allowed') + for var, etype in solution.iteritems(): + if etype == 'Password': + raise Unauthorized('Password selection is not allowed (%s)' % var) def term_etype(session, term, solution, args): """return the entity type for the given term (a VariableRef or a Constant diff -r 59a29405688c -r 6ad000b91347 server/ssplanner.py --- a/server/ssplanner.py Thu Apr 04 17:45:09 2013 +0200 +++ b/server/ssplanner.py Mon Apr 08 14:45:10 2013 +0200 @@ -76,7 +76,12 @@ checkread = session.read_security eschema = session.vreg.schema.eschema for rel in rqlst.where.get_nodes(Relation): - if rel.r_type == 'eid' and not rel.neged(strict=True): + # only care for 'eid' relations ... + if (rel.r_type == 'eid' + # ... that are not part of a NOT clause ... + and not rel.neged(strict=True) + # ... and where eid is specified by '=' operator. + and rel.children[1].operator == '='): lhs, rhs = rel.get_variable_parts() if isinstance(rhs, Constant): eid = int(rhs.eval(plan.args)) diff -r 59a29405688c -r 6ad000b91347 server/test/unittest_querier.py --- a/server/test/unittest_querier.py Thu Apr 04 17:45:09 2013 +0200 +++ b/server/test/unittest_querier.py Mon Apr 08 14:45:10 2013 +0200 @@ -1562,5 +1562,28 @@ res = self.execute('Any X WHERE X has_text %(text)s', {'text': 'aff2'}) self.assertEqual(res.rows, [[aff2.eid]]) + def test_set_relations_eid(self): + req = self.request() + # create 3 email addresses + a1 = req.create_entity('EmailAddress', address=u'a1') + a2 = req.create_entity('EmailAddress', address=u'a2') + a3 = req.create_entity('EmailAddress', address=u'a3') + # SET relations using '>=' operator on eids + req.execute('SET U use_email A WHERE U login "admin", A eid >= %s' % a2.eid) + self.assertEqual( + [[a2.eid], [a3.eid]], + req.execute('Any A ORDERBY A WHERE U use_email A, U login "admin"').rows) + # DELETE + req.execute('DELETE U use_email A WHERE U login "admin", A eid > %s' % a2.eid) + self.assertEqual( + [[a2.eid]], + req.execute('Any A ORDERBY A WHERE U use_email A, U login "admin"').rows) + req.execute('DELETE U use_email A WHERE U login "admin"') + # SET relations using '<' operator on eids + req.execute('SET U use_email A WHERE U login "admin", A eid < %s' % a2.eid) + self.assertEqual( + [[a1.eid]], + req.execute('Any A ORDERBY A WHERE U use_email A, U login "admin"').rows) + if __name__ == '__main__': unittest_main() diff -r 59a29405688c -r 6ad000b91347 test/unittest_predicates.py --- a/test/unittest_predicates.py Thu Apr 04 17:45:09 2013 +0200 +++ b/test/unittest_predicates.py Mon Apr 08 14:45:10 2013 +0200 @@ -1,4 +1,4 @@ -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This file is part of CubicWeb. @@ -26,6 +26,7 @@ multi_lines_rset, score_entity, is_in_state, rql_condition, relation_possible) from cubicweb.selectors import on_transition # XXX on_transition is deprecated +from cubicweb.view import EntityAdapter from cubicweb.web import action @@ -336,6 +337,22 @@ selector = rql_condition('U login "toto"', user_condition=True) self.assertEqual(selector(None, req), 0) + +class AdaptablePredicateTC(CubicWebTC): + + def test_multiple_entity_types_rset(self): + class CWUserIWhatever(EntityAdapter): + __regid__ = 'IWhatever' + __select__ = is_instance('CWUser') + class CWGroupIWhatever(EntityAdapter): + __regid__ = 'IWhatever' + __select__ = is_instance('CWGroup') + with self.temporary_appobjects(CWUserIWhatever, CWGroupIWhatever): + req = self.request() + selector = adaptable('IWhatever') + rset = req.execute('Any X WHERE X is IN(CWGroup, CWUser)') + self.assertTrue(selector(None, req, rset=rset)) + if __name__ == '__main__': unittest_main() diff -r 59a29405688c -r 6ad000b91347 web/facet.py --- a/web/facet.py Thu Apr 04 17:45:09 2013 +0200 +++ b/web/facet.py Mon Apr 08 14:45:10 2013 +0200 @@ -66,7 +66,7 @@ from cubicweb import Unauthorized from cubicweb.schema import display_name -from cubicweb.uilib import css_em_num_value +from cubicweb.uilib import css_em_num_value, domid from cubicweb.utils import make_uid from cubicweb.predicates import match_context_prop, partial_relation_possible from cubicweb.appobject import AppObject @@ -1449,7 +1449,7 @@ def _render(self): w = self.w title = xml_escape(self.facet.title) - facetid = make_uid(self.facet.__regid__) + facetid = domid(make_uid(self.facet.__regid__)) w(u'
\n' % facetid) cssclass = 'facetTitle' if self.facet.allow_hide: