merge 3.18.4 into default
server/test/unittest_migractions fails due to interaction between new
constraint test (from 3.18) and composite deletion change (in 3.19).
--- a/.hgtags Mon Apr 07 14:15:35 2014 +0200
+++ b/.hgtags Mon Apr 07 17:02:04 2014 +0200
@@ -326,6 +326,9 @@
09b4ebb9b0f179009491410c07cd013a60258fc6 cubicweb-version-3.17.13
09b4ebb9b0f179009491410c07cd013a60258fc6 cubicweb-debian-version-3.17.13-1
09b4ebb9b0f179009491410c07cd013a60258fc6 cubicweb-centos-version-3.17.13-1
+fa00fc251d57f61e619d9c905502745fae21c58c cubicweb-centos-version-3.17.14-1
+fa00fc251d57f61e619d9c905502745fae21c58c cubicweb-version-3.17.14
+fa00fc251d57f61e619d9c905502745fae21c58c cubicweb-debian-version-3.17.14-1
db37bf35a1474843ded0a537f9cb4838f4a78cda cubicweb-version-3.18.0
db37bf35a1474843ded0a537f9cb4838f4a78cda cubicweb-debian-version-3.18.0-1
db37bf35a1474843ded0a537f9cb4838f4a78cda cubicweb-centos-version-3.18.0-1
@@ -338,3 +341,6 @@
afd21fea201a745051357b7aa6be3c7da1ae5bd2 cubicweb-version-3.18.3
afd21fea201a745051357b7aa6be3c7da1ae5bd2 cubicweb-debian-version-3.18.3-1
afd21fea201a745051357b7aa6be3c7da1ae5bd2 cubicweb-centos-version-3.18.3-1
+0176da9bc75293e200de4f7b934c5d4c7c805199 cubicweb-version-3.18.4
+0176da9bc75293e200de4f7b934c5d4c7c805199 cubicweb-debian-version-3.18.4-1
+0176da9bc75293e200de4f7b934c5d4c7c805199 cubicweb-centos-version-3.18.4-1
--- a/__pkginfo__.py Mon Apr 07 14:15:35 2014 +0200
+++ b/__pkginfo__.py Mon Apr 07 17:02:04 2014 +0200
@@ -22,7 +22,7 @@
modname = distname = "cubicweb"
-numversion = (3, 18, 3)
+numversion = (3, 18, 4)
version = '.'.join(str(num) for num in numversion)
description = "a repository of entities / relations for knowledge management"
@@ -42,7 +42,7 @@
'logilab-common': '>= 0.60.0',
'logilab-mtconverter': '>= 0.8.0',
'rql': '>= 0.31.2',
- 'yams': '>= 0.39.0',
+ 'yams': '>= 0.39.1',
#gettext # for xgettext, msgcat, etc...
# web dependancies
'simplejson': '>= 2.0.9',
--- a/cubicweb.spec Mon Apr 07 14:15:35 2014 +0200
+++ b/cubicweb.spec Mon Apr 07 17:02:04 2014 +0200
@@ -7,7 +7,7 @@
%endif
Name: cubicweb
-Version: 3.18.3
+Version: 3.18.4
Release: logilab.1%{?dist}
Summary: CubicWeb is a semantic web application framework
Source0: http://download.logilab.org/pub/cubicweb/cubicweb-%{version}.tar.gz
@@ -23,7 +23,7 @@
Requires: %{python}-logilab-common >= 0.60.0
Requires: %{python}-logilab-mtconverter >= 0.8.0
Requires: %{python}-rql >= 0.31.2
-Requires: %{python}-yams >= 0.39.0
+Requires: %{python}-yams >= 0.39.1
Requires: %{python}-logilab-database >= 1.12.0
Requires: %{python}-passlib
Requires: %{python}-lxml
--- a/dataimport.py Mon Apr 07 14:15:35 2014 +0200
+++ b/dataimport.py Mon Apr 07 17:02:04 2014 +0200
@@ -802,7 +802,7 @@
assert not rtype.startswith('reverse_')
self.add_relation(self.session, eid_from, rtype, eid_to,
self.rschema(rtype).inlined)
- if self.rschema[rtype].symmetric:
+ if self.rschema(rtype).symmetric:
self.add_relation(self.session, eid_to, rtype, eid_from,
self.rschema(rtype).inlined)
self._nb_inserted_relations += 1
@@ -931,7 +931,7 @@
# XXX Could subjtype be inferred ?
self.source.add_relation(self.session, subj_eid, rtype, obj_eid,
self.rschema(rtype).inlined, **kwargs)
- if self.rschema[rtype].symmetric:
+ if self.rschema(rtype).symmetric:
self.source.add_relation(self.session, obj_eid, rtype, subj_eid,
self.rschema(rtype).inlined, **kwargs)
--- a/debian/changelog Mon Apr 07 14:15:35 2014 +0200
+++ b/debian/changelog Mon Apr 07 17:02:04 2014 +0200
@@ -1,3 +1,9 @@
+cubicweb (3.18.4-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- Aurelien Campeas <aurelien.campeas@logilab.fr> Fri, 28 Mar 2014 17:12:48 +0100
+
cubicweb (3.18.3-1) unstable; urgency=low
* new upstream release
@@ -22,6 +28,12 @@
-- Julien Cristau <julien.cristau@logilab.fr> Fri, 10 Jan 2014 17:14:18 +0100
+cubicweb (3.17.14-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- Aurelien Campeas <aurelien.campeas@logilab.fr> Wed, 05 Mar 2014 15:48:38 +0100
+
cubicweb (3.17.13-1) unstable; urgency=low
* new upstream release
--- a/debian/control Mon Apr 07 14:15:35 2014 +0200
+++ b/debian/control Mon Apr 07 17:02:04 2014 +0200
@@ -15,7 +15,7 @@
python-unittest2 | python (>= 2.7),
python-logilab-mtconverter,
python-rql,
- python-yams (>= 0.39),
+ python-yams (>= 0.39.1),
python-lxml,
Standards-Version: 3.9.1
Homepage: http://www.cubicweb.org
@@ -153,7 +153,7 @@
gettext,
python-logilab-mtconverter (>= 0.8.0),
python-logilab-common (>= 0.60.0),
- python-yams (>= 0.39.0),
+ python-yams (>= 0.39.1),
python-rql (>= 0.31.2),
python-lxml
Recommends:
--- a/devtools/__init__.py Mon Apr 07 14:15:35 2014 +0200
+++ b/devtools/__init__.py Mon Apr 07 17:02:04 2014 +0200
@@ -118,6 +118,7 @@
repo._needs_refresh = True
repo._has_started = False
+
def turn_repo_on(repo):
"""Idea: this is less costly than a full re-creation of the repo object.
on:
@@ -850,7 +851,22 @@
# XXX a class method on Test ?
+
+_CONFIG = None
def get_test_db_handler(config):
+ global _CONFIG
+ if _CONFIG is not None and config is not _CONFIG:
+ from logilab.common.modutils import cleanup_sys_modules
+ # cleanup all dynamically loaded modules and everything in the instance
+ # directory
+ apphome = _CONFIG.apphome
+ if apphome: # may be unset in tests
+ cleanup_sys_modules([apphome])
+ # also cleanup sys.path
+ if apphome in sys.path:
+ sys.path.remove(apphome)
+ _CONFIG = config
+ config.adjust_sys_path()
handler = HCACHE.get(config)
if handler is not None:
return handler
--- a/devtools/testlib.py Mon Apr 07 14:15:35 2014 +0200
+++ b/devtools/testlib.py Mon Apr 07 17:02:04 2014 +0200
@@ -704,11 +704,6 @@
entity.cw_attr_cache.pop('modification_date', None)
self.assertTrue(entity.modification_date > olddate)
- def assertItemsEqual(self, it1, it2, *args, **kwargs):
- it1 = set(getattr(x, 'eid', x) for x in it1)
- it2 = set(getattr(x, 'eid', x) for x in it2)
- super(CubicWebTC, self).assertItemsEqual(it1, it2, *args, **kwargs)
-
def assertMessageEqual(self, req, params, expected_msg):
msg = req.session.data[params['_cwmsgid']]
self.assertEqual(expected_msg, msg)
--- a/doc/book/en/annexes/rql/debugging.rst Mon Apr 07 14:15:35 2014 +0200
+++ b/doc/book/en/annexes/rql/debugging.rst Mon Apr 07 17:02:04 2014 +0200
@@ -37,7 +37,7 @@
.. sourcecode:: python
- from cubicweb.server import debuged, DBG_HOOKS
+ from cubicweb.server import debugged, DBG_HOOKS
with debugged(DBG_HOOKS):
person.cw_set(works_for=company)
--- a/entity.py Mon Apr 07 14:15:35 2014 +0200
+++ b/entity.py Mon Apr 07 17:02:04 2014 +0200
@@ -788,13 +788,13 @@
assert role in ('subject', 'object'), role
skip_copy_for[role].add(rtype)
for rschema in self.e_schema.subject_relations():
+ if rschema.type in skip_copy_for['subject']:
+ continue
if rschema.final or rschema.meta:
continue
# skip already defined relations
if getattr(self, rschema.type):
continue
- if rschema.type in skip_copy_for['subject']:
- continue
# skip composite relation
rdef = self.e_schema.rdef(rschema)
if rdef.composite:
--- a/ext/rest.py Mon Apr 07 14:15:35 2014 +0200
+++ b/ext/rest.py Mon Apr 07 17:02:04 2014 +0200
@@ -437,7 +437,7 @@
# necessary for proper garbage collection, else a ref is kept somewhere in docutils...
del pub.settings.context
return res
- except Exception:
+ except BaseException:
LOGGER.exception('error while publishing ReST text')
if not isinstance(data, unicode):
data = unicode(data, encoding, 'replace')
--- a/hooks/syncschema.py Mon Apr 07 14:15:35 2014 +0200
+++ b/hooks/syncschema.py Mon Apr 07 17:02:04 2014 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
@@ -196,13 +196,11 @@
clear_cache(eschema, 'ordered_relations')
def postcommit_event(self):
- rebuildinfered = self.cnx.get_shared_data('rebuild-infered', True)
repo = self.cnx.repo
# commit event should not raise error, while set_schema has chances to
# do so because it triggers full vreg reloading
try:
- if rebuildinfered:
- repo.schema.rebuild_infered_relations()
+ repo.schema.rebuild_infered_relations()
# trigger vreg reload
repo.set_schema(repo.schema)
# CWUser class might have changed, update current session users
@@ -650,7 +648,11 @@
rdef = self.rdef
# in-place modification of in-memory schema first
_set_modifiable_constraints(rdef)
- rdef.constraints.remove(self.oldcstr)
+ if self.oldcstr in rdef.constraints:
+ rdef.constraints.remove(self.oldcstr)
+ else:
+ self.critical('constraint %s for rdef %s was missing or already removed',
+ self.oldcstr, rdef)
# then update database: alter the physical schema on size/unique
# constraint changes
syssource = cnx.repo.system_source
@@ -1136,7 +1138,7 @@
rdef = schema.schema_by_eid(entity.reverse_constrained_by[0].eid)
# IndexError
cstr = rdef.constraint_by_type(entity.type)
- except (IndexError, KeyError):
+ except (KeyError, IndexError):
self._cw.critical('constraint type no more accessible')
else:
CWConstraintDelOp(self._cw, rdef=rdef, oldcstr=cstr)
--- a/misc/migration/3.18.0_Any.py Mon Apr 07 14:15:35 2014 +0200
+++ b/misc/migration/3.18.0_Any.py Mon Apr 07 17:02:04 2014 +0200
@@ -74,7 +74,12 @@
rql('SET X to_entity B WHERE X is CWAttribute, X from_entity Y, Y name "CWAttribute", '
'X relation_type Z, Z name "defaultval", B name "Bytes", NOT X to_entity B')
-schema['defaultval'].rdefs.values()[0].object = schema['Bytes']
+oldrdef = schema['CWAttribute'].rdef('defaultval')
+import yams.buildobjs as ybo
+newrdef = ybo.RelationDefinition('CWAttribute', 'defaultval', 'Bytes')
+newrdef.eid = oldrdef.eid
+schema.add_relation_def(newrdef)
+schema.del_relation_def('CWAttribute', 'defaultval', 'String')
commit()
--- a/rqlrewrite.py Mon Apr 07 14:15:35 2014 +0200
+++ b/rqlrewrite.py Mon Apr 07 17:02:04 2014 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
@@ -405,7 +405,7 @@
assert len(subquery.children) == 1
subselect = subquery.children[0]
RQLRewriter(self.session).rewrite(subselect, [(varmap, rqlexprs)],
- subselect.solutions, self.kwargs)
+ self.kwargs)
return
if varexistsmap is None:
# build an index for quick access to relations
@@ -790,7 +790,7 @@
vargraph = self.current_expr.vargraph
for existingvar in self.existingvars:
#path = has_path(vargraph, varname, existingvar)
- if has_path(vargraph, varname, existingvar):
+ if not varname in vargraph or has_path(vargraph, varname, existingvar):
return True
# no path from this variable to an existing variable
return False
--- a/schema.py Mon Apr 07 14:15:35 2014 +0200
+++ b/schema.py Mon Apr 07 17:02:04 2014 +0200
@@ -350,6 +350,13 @@
return self._check(_cw, x=eid, **kwargs)
return self._check(_cw, **kwargs)
+def constraint_by_eid(self, eid):
+ for cstr in self.constraints:
+ if cstr.eid == eid:
+ return cstr
+ raise ValueError('No constraint with eid %d' % eid)
+RelationDefinitionSchema.constraint_by_eid = constraint_by_eid
+
def vargraph(rqlst):
""" builds an adjacency graph of variables from the rql syntax tree, e.g:
--- a/server/migractions.py Mon Apr 07 14:15:35 2014 +0200
+++ b/server/migractions.py Mon Apr 07 17:02:04 2014 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
@@ -103,7 +103,6 @@
# no config on shell to a remote instance
if config is not None and (cnx or connect):
repo = self.repo
- self.session.set_shared_data('rebuild-infered', False)
# register a hook to clear our group_mapping cache and the
# self._synchronized set when some group is added or updated
ClearGroupMap.mih = self
@@ -596,12 +595,18 @@
self.rqlexecall(ss.updaterdef2rql(rdef, repordef.eid),
ask_confirm=confirm)
# constraints
- newconstraints = list(rdef.constraints)
+ # 0. eliminate the set of unmodified constraints from the sets of
+ # old/new constraints
+ newconstraints = set(rdef.constraints)
+ oldconstraints = set(repordef.constraints)
+ unchanged_constraints = newconstraints & oldconstraints
+ newconstraints -= unchanged_constraints
+ oldconstraints -= unchanged_constraints
# 1. remove old constraints and update constraints of the same type
# NOTE: don't use rschema.constraint_by_type because it may be
# out of sync with newconstraints when multiple
# constraints of the same type are used
- for cstr in repordef.constraints:
+ for cstr in oldconstraints:
for newcstr in newconstraints:
if newcstr.type() == cstr.type():
break
--- a/server/test/data/migratedapp/schema.py Mon Apr 07 14:15:35 2014 +0200
+++ b/server/test/data/migratedapp/schema.py Mon Apr 07 17:02:04 2014 +0200
@@ -22,6 +22,7 @@
RichString, String, Int, Boolean, Datetime, Date)
from yams.constraints import SizeConstraint, UniqueConstraint
from cubicweb.schema import (WorkflowableEntityType, RQLConstraint,
+ RQLVocabularyConstraint,
ERQLExpression, RRQLExpression)
class Affaire(EntityType):
@@ -177,4 +178,3 @@
class same_as(RelationDefinition):
subject = ('Societe',)
object = 'ExternalUri'
-
--- a/server/test/data/schema.py Mon Apr 07 14:15:35 2014 +0200
+++ b/server/test/data/schema.py Mon Apr 07 17:02:04 2014 +0200
@@ -22,6 +22,7 @@
from yams.constraints import SizeConstraint
from cubicweb.schema import (WorkflowableEntityType,
RQLConstraint, RQLUniqueConstraint,
+ RQLVocabularyConstraint,
ERQLExpression, RRQLExpression)
class Affaire(WorkflowableEntityType):
@@ -157,6 +158,8 @@
}
subject = 'Personne'
object = 'Societe'
+ constraints = [RQLVocabularyConstraint('S owned_by U'),
+ RQLVocabularyConstraint('S created_by U')]
class comments(RelationDefinition):
subject = 'Comment'
@@ -187,6 +190,10 @@
class evaluee(RelationDefinition):
subject = ('Personne', 'CWUser', 'Societe')
object = ('Note')
+ constraints = [
+ RQLVocabularyConstraint('S created_by U'),
+ RQLVocabularyConstraint('S owned_by U'),
+ ]
class ecrit_par(RelationType):
inlined = True
--- a/server/test/unittest_migractions.py Mon Apr 07 14:15:35 2014 +0200
+++ b/server/test/unittest_migractions.py Mon Apr 07 17:02:04 2014 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
@@ -224,7 +224,6 @@
self.assertTrue(self.session.execute('CWEType X WHERE X name "Folder2"'))
self.assertTrue('filed_under2' in self.schema)
self.assertTrue(self.session.execute('CWRType X WHERE X name "filed_under2"'))
- self.schema.rebuild_infered_relations()
self.assertEqual(sorted(str(rs) for rs in self.schema['Folder2'].subject_relations()),
['created_by', 'creation_date', 'cw_source', 'cwuri',
'description', 'description_format',
@@ -270,7 +269,6 @@
def test_add_drop_relation_type(self):
self.mh.cmd_add_entity_type('Folder2', auto=False)
self.mh.cmd_add_relation_type('filed_under2')
- self.schema.rebuild_infered_relations()
self.assertTrue('filed_under2' in self.schema)
# Old will be missing as it has been renamed into 'New' in the migrated
# schema while New hasn't been added here.
@@ -327,17 +325,11 @@
self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()),
['Affaire', 'Personne'])
self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
- ['Affaire', 'Division', 'Note', 'SubDivision'])
- self.schema.rebuild_infered_relations() # need to be explicitly called once everything is in place
- self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
['Affaire', 'Note'])
self.mh.cmd_add_relation_definition('Affaire', 'concerne', 'Societe')
self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()),
['Affaire', 'Personne'])
self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
- ['Affaire', 'Note', 'Societe'])
- self.schema.rebuild_infered_relations() # need to be explicitly called once everything is in place
- self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
['Affaire', 'Division', 'Note', 'Societe', 'SubDivision'])
# trick: overwrite self.maxeid to avoid deletion of just reintroduced types
self.maxeid = self.session.execute('Any MAX(X)')[0][0]
@@ -371,6 +363,26 @@
self.mh.cmd_change_relation_props('Personne', 'adel', 'String',
fulltextindexed=False)
+ def test_sync_schema_props_perms_rqlconstraints(self):
+ # Drop one of the RQLConstraint.
+ rdef = self.schema['evaluee'].rdefs[('Personne', 'Note')]
+ oldconstraints = rdef.constraints
+ self.assertIn('S created_by U',
+ [cstr.expression for cstr in oldconstraints])
+ self.mh.cmd_sync_schema_props_perms('evaluee', commit=True)
+ newconstraints = rdef.constraints
+ self.assertNotIn('S created_by U',
+ [cstr.expression for cstr in newconstraints])
+
+ # Drop all RQLConstraint.
+ rdef = self.schema['travaille'].rdefs[('Personne', 'Societe')]
+ oldconstraints = rdef.constraints
+ self.assertEqual(len(oldconstraints), 2)
+ self.mh.cmd_sync_schema_props_perms('travaille', commit=True)
+ rdef = self.schema['travaille'].rdefs[('Personne', 'Societe')]
+ newconstraints = rdef.constraints
+ self.assertEqual(len(newconstraints), 0)
+
@tag('longrun')
def test_sync_schema_props_perms(self):
cursor = self.mh.session
@@ -598,12 +610,10 @@
@tag('longrun')
def test_introduce_base_class(self):
self.mh.cmd_add_entity_type('Para')
- self.mh.repo.schema.rebuild_infered_relations()
self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()),
['Note'])
self.assertEqual(self.schema['Note'].specializes().type, 'Para')
self.mh.cmd_add_entity_type('Text')
- self.mh.repo.schema.rebuild_infered_relations()
self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()),
['Note', 'Text'])
self.assertEqual(self.schema['Text'].specializes().type, 'Para')
@@ -627,12 +637,8 @@
#
# also we need more tests about introducing/removing base classes or
# specialization relationship...
- self.session.set_shared_data('rebuild-infered', True)
- try:
- self.session.execute('DELETE X specializes Y WHERE Y name "Para"')
- self.session.commit(free_cnxset=False)
- finally:
- self.session.set_shared_data('rebuild-infered', False)
+ self.session.execute('DELETE X specializes Y WHERE Y name "Para"')
+ self.session.commit(free_cnxset=False)
self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()),
[])
self.assertEqual(self.schema['Note'].specializes(), None)
--- a/server/test/unittest_security.py Mon Apr 07 14:15:35 2014 +0200
+++ b/server/test/unittest_security.py Mon Apr 07 17:02:04 2014 +0200
@@ -544,25 +544,6 @@
names = [t for t, in cu.execute('Any N ORDERBY lower(N) WHERE X name N')]
self.assertEqual(names, sorted(names, key=lambda x: x.lower()))
- def test_restrict_is_instance_ok(self):
- rset = self.execute('Any X WHERE X is_instance_of BaseTransition')
- rqlst = rset.syntax_tree()
- select = rqlst.children[0]
- x = select.get_selected_variables().next()
- self.assertRaises(RQLException, select.add_type_restriction,
- x.variable, 'CWUser')
- select.add_type_restriction(x.variable, 'BaseTransition')
- select.add_type_restriction(x.variable, 'WorkflowTransition')
- self.assertEqual(rqlst.as_string(), 'Any X WHERE X is_instance_of WorkflowTransition')
-
- def test_restrict_is_instance_no_supported(self):
- rset = self.execute('Any X WHERE X is_instance_of IN(CWUser, CWGroup)')
- rqlst = rset.syntax_tree()
- select = rqlst.children[0]
- x = select.get_selected_variables().next()
- self.assertRaises(NotImplementedError, select.add_type_restriction,
- x.variable, 'WorkflowTransition')
-
def test_in_state_without_update_perm(self):
"""check a user change in_state without having update permission on the
subject
--- a/test/data/rrqlexpr_on_attr.py Mon Apr 07 14:15:35 2014 +0200
+++ b/test/data/rrqlexpr_on_attr.py Mon Apr 07 17:02:04 2014 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
@@ -15,9 +15,7 @@
#
# You should have received a copy of the GNU Lesser General Public License along
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>.
-"""
-"""
from yams.buildobjs import EntityType, RelationType, String
from cubicweb.schema import RRQLExpression
@@ -34,4 +32,5 @@
__permissions__ = {
'read': ('managers', ),
'update': ('managers', RRQLExpression('S bla Y'),),
+ 'add': ('managers', RRQLExpression('S bla Y'),),
}
--- a/test/unittest_rqlrewrite.py Mon Apr 07 14:15:35 2014 +0200
+++ b/test/unittest_rqlrewrite.py Mon Apr 07 17:02:04 2014 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
@@ -555,5 +555,40 @@
'AC is CWUser, E is CWUser, X is IN(Division, Societe)',
union.as_string())
+ def test_question_mark_attribute_snippet(self):
+ # see #3661918
+ from cubicweb.rqlrewrite import RQLRewriter
+ from logilab.common.decorators import monkeypatch
+ repotest.undo_monkey_patch()
+ orig_insert_snippets = RQLRewriter.insert_snippets
+ # patch insert_snippets and not rewrite, insert_snippets is already
+ # monkey patches (see above setupModule/repotest)
+ @monkeypatch(RQLRewriter)
+ def insert_snippets(self, snippets, varexistsmap=None):
+ # crash occurs if snippets are processed in a specific order, force
+ # destiny
+ if snippets[0][0] != {u'N': 'X'}:
+ snippets = list(reversed(snippets))
+ return orig_insert_snippets(self, snippets, varexistsmap)
+ try:
+ with self.temporary_permissions(
+ (self.schema['Affaire'],
+ {'read': (ERQLExpression('X ref "blah"'), )}),
+ (self.schema['Note'],
+ {'read': (ERQLExpression(
+ 'EXISTS(X inlined_affaire Z), EXISTS(Z owned_by U)'), )}),
+ ):
+ union = self.process(
+ 'Any A,COUNT(N) GROUPBY A '
+ 'WHERE A is Affaire, N? inlined_affaire A')
+ self.assertEqual('Any A,COUNT(N) GROUPBY A WHERE A is Affaire '
+ 'WITH N,A BEING (Any N,A WHERE N? inlined_affaire A, '
+ '(N is NULL) OR (EXISTS(EXISTS(N inlined_affaire B), '
+ 'EXISTS(B owned_by %(E)s), B is Affaire)), '
+ 'A is Affaire, N is Note, EXISTS(A ref "blah"))',
+ union.as_string())
+ finally:
+ RQLRewriter.insert_snippets = orig_insert_snippets
+
if __name__ == '__main__':
unittest_main()
--- a/test/unittest_utils.py Mon Apr 07 14:15:35 2014 +0200
+++ b/test/unittest_utils.py Mon Apr 07 17:02:04 2014 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of CubicWeb.
@@ -271,6 +271,7 @@
self.assertEqual(list(result), expected)
def test_getvalue_with_concat(self):
+ self.config.global_set_option('concat-resources', True)
base_url = u'http://test.fr/data/'
head = self.htmlhead(base_url)
head.add_js(base_url + u'bob0.js')
--- a/web/component.py Mon Apr 07 14:15:35 2014 +0200
+++ b/web/component.py Mon Apr 07 17:02:04 2014 +0200
@@ -108,8 +108,12 @@
view = self.cw_extra_kwargs.get('view')
if view is not None and hasattr(view, 'page_navigation_url'):
url = view.page_navigation_url(self, path, params)
+ elif path in ('json', 'ajax'):
+ # 'ajax' is the new correct controller, but the old 'json'
+ # controller should still be supported
+ url = self.ajax_page_url(**params)
else:
- url = self.ajax_page_url(**params)
+ url = self._cw.build_url(path, **params)
# XXX hack to avoid opening a new page containing the evaluation of the
# js expression on ajax call
if url.startswith('javascript:'):
@@ -118,9 +122,9 @@
def ajax_page_url(self, **params):
divid = params.setdefault('divid', 'pageContent')
- params['fname'] = 'view'
params['rql'] = self.cw_rset.printable_rql()
- return self._cw.build_url('ajax', **params)
+ return js_href("$(%s).loadxhtml(AJAX_PREFIX_URL, %s, 'get', 'swap')" % (
+ json_dumps('#'+divid), js.ajaxFuncArgs('view', params)))
def page_link(self, path, params, start, stop, content):
url = xml_escape(self.page_url(path, params, start, stop))
--- a/web/views/editcontroller.py Mon Apr 07 14:15:35 2014 +0200
+++ b/web/views/editcontroller.py Mon Apr 07 17:02:04 2014 +0200
@@ -264,7 +264,7 @@
errors = dict((f.role_name(), unicode(ex)) for f, ex in self.errors)
raise ValidationError(valerror_eid(entity.eid), errors)
if eid is None: # creation or copy
- entity.eid = self._insert_entity(etype, formparams['eid'], rqlquery)
+ entity.eid = eid = self._insert_entity(etype, formparams['eid'], rqlquery)
elif rqlquery.edited: # edition of an existant entity
self._update_entity(eid, rqlquery)
if is_main_entity:
--- a/web/views/navigation.py Mon Apr 07 14:15:35 2014 +0200
+++ b/web/views/navigation.py Mon Apr 07 17:02:04 2014 +0200
@@ -55,7 +55,6 @@
from logilab.mtconverter import xml_escape
from logilab.common.deprecation import deprecated
-from cubicweb.utils import json_dumps
from cubicweb.predicates import paginated_rset, sorted_rset, adaptable
from cubicweb.uilib import cut
from cubicweb.view import EntityAdapter
@@ -281,13 +280,6 @@
nav = req.vreg['components'].select_or_none(
'navigation', req, rset=rset, page_size=page_size, view=view)
if nav:
- domid = getattr(view, 'domid', 'pageContent')
- view._cw.add_onload('''
- jQuery('div.displayAllLink a, div.pagination a').click(function() {
- cw.jqNode(%s).loadxhtml(this.href, null, 'get', 'swap');
- return false;
- });
- ''' % json_dumps(domid))
if w is None:
w = view.w
if req.form.get('__force_display'):
--- a/web/webconfig.py Mon Apr 07 14:15:35 2014 +0200
+++ b/web/webconfig.py Mon Apr 07 17:02:04 2014 +0200
@@ -225,7 +225,7 @@
}),
('concat-resources',
{'type' : 'yn',
- 'default': True,
+ 'default': False,
'help': 'use modconcat-like URLS to concat and serve JS / CSS files',
'group': 'web', 'level': 2,
}),