# HG changeset patch # User Julien Cristau # Date 1396882924 -7200 # Node ID aaf099172bb93b8b0a8701f5668bfbfcb68e665d # Parent c60c8dec0e0ece5d639f8e980dcb431b1d3cea9f# Parent e01121bbd4fea7078596bdebf13815be8370f62a 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). diff -r c60c8dec0e0e -r aaf099172bb9 .hgtags --- 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 diff -r c60c8dec0e0e -r aaf099172bb9 __pkginfo__.py --- 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', diff -r c60c8dec0e0e -r aaf099172bb9 cubicweb.spec --- 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 diff -r c60c8dec0e0e -r aaf099172bb9 dataimport.py --- 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) diff -r c60c8dec0e0e -r aaf099172bb9 debian/changelog --- 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 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 Fri, 10 Jan 2014 17:14:18 +0100 +cubicweb (3.17.14-1) unstable; urgency=low + + * new upstream release + + -- Aurelien Campeas Wed, 05 Mar 2014 15:48:38 +0100 + cubicweb (3.17.13-1) unstable; urgency=low * new upstream release diff -r c60c8dec0e0e -r aaf099172bb9 debian/control --- 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: diff -r c60c8dec0e0e -r aaf099172bb9 devtools/__init__.py --- 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 diff -r c60c8dec0e0e -r aaf099172bb9 devtools/testlib.py --- 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) diff -r c60c8dec0e0e -r aaf099172bb9 doc/book/en/annexes/rql/debugging.rst --- 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) diff -r c60c8dec0e0e -r aaf099172bb9 entity.py --- 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: diff -r c60c8dec0e0e -r aaf099172bb9 ext/rest.py --- 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') diff -r c60c8dec0e0e -r aaf099172bb9 hooks/syncschema.py --- 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) diff -r c60c8dec0e0e -r aaf099172bb9 misc/migration/3.18.0_Any.py --- 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() diff -r c60c8dec0e0e -r aaf099172bb9 rqlrewrite.py --- 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 diff -r c60c8dec0e0e -r aaf099172bb9 schema.py --- 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: diff -r c60c8dec0e0e -r aaf099172bb9 server/migractions.py --- 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 diff -r c60c8dec0e0e -r aaf099172bb9 server/test/data/migratedapp/schema.py --- 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' - diff -r c60c8dec0e0e -r aaf099172bb9 server/test/data/schema.py --- 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 diff -r c60c8dec0e0e -r aaf099172bb9 server/test/unittest_migractions.py --- 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) diff -r c60c8dec0e0e -r aaf099172bb9 server/test/unittest_security.py --- 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 diff -r c60c8dec0e0e -r aaf099172bb9 test/data/rrqlexpr_on_attr.py --- 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 . -""" -""" 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'),), } diff -r c60c8dec0e0e -r aaf099172bb9 test/unittest_rqlrewrite.py --- 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() diff -r c60c8dec0e0e -r aaf099172bb9 test/unittest_utils.py --- 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') diff -r c60c8dec0e0e -r aaf099172bb9 web/component.py --- 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)) diff -r c60c8dec0e0e -r aaf099172bb9 web/views/editcontroller.py --- 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: diff -r c60c8dec0e0e -r aaf099172bb9 web/views/navigation.py --- 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'): diff -r c60c8dec0e0e -r aaf099172bb9 web/webconfig.py --- 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, }),