--- 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
--- 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 <aurelien.campeas@logilab.fr> Wed, 23 Jan 2013 17:40:00 +0100
+cubicweb (3.15.11-1) squeeze; urgency=low
+
+ * New upstream release
+
+ -- Pierre-Yves David <pierre-yves.david@logilab.fr> 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 <sylvain.thenault@logilab.fr> Thu, 12 Apr 2012 13:52:05 +0200
+cubicweb (3.14.10-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- Pierre-Yves David <pierre-yves.david@logilab.fr> Mon, 08 Apr 2013 12:18:20 +0200
+
cubicweb (3.14.9-1) unstable; urgency=low
* new upstream release
--- 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'
--- 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:
--- 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
--- 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))
--- 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()
--- 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()
--- 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'<div id="%s" class="facet">\n' % facetid)
cssclass = 'facetTitle'
if self.facet.allow_hide: