# HG changeset patch # User Sylvain Thénault # Date 1292710334 -3600 # Node ID 02091c91520f29b11002a093a147b82fd742ec9e # Parent de49060d4be3c253552ae120128eea86375a4720# Parent ef513c03a22489d7f8d151ae75ca9953d2f46997 backport stable diff -r de49060d4be3 -r 02091c91520f __pkginfo__.py --- a/__pkginfo__.py Thu Dec 09 15:27:02 2010 +0100 +++ b/__pkginfo__.py Sat Dec 18 23:12:14 2010 +0100 @@ -52,7 +52,7 @@ 'Twisted': '', # XXX graphviz # server dependencies - 'logilab-database': '>= 1.3.1', + 'logilab-database': '>= 1.3.2', 'pysqlite': '>= 2.5.5', # XXX install pysqlite2 } diff -r de49060d4be3 -r 02091c91520f cwconfig.py --- a/cwconfig.py Thu Dec 09 15:27:02 2010 +0100 +++ b/cwconfig.py Sat Dec 18 23:12:14 2010 +0100 @@ -142,7 +142,7 @@ from smtplib import SMTP from threading import Lock from os.path import (exists, join, expanduser, abspath, normpath, - basename, isdir, dirname) + basename, isdir, dirname, splitext) from warnings import warn from logilab.common.decorators import cached, classproperty from logilab.common.deprecation import deprecated @@ -400,6 +400,13 @@ return join(cls.shared_dir(), 'i18n') @classmethod + def cw_languages(cls): + for fname in os.listdir(join(cls.i18n_lib_dir())): + if fname.endswith('.po'): + yield splitext(fname)[0] + + + @classmethod def available_cubes(cls): import re cubes = set() @@ -682,8 +689,8 @@ def __init__(self, debugmode=False): register_stored_procedures() - ConfigurationMixIn.__init__(self) self._cubes = None + super(CubicWebNoAppConfiguration, self).__init__() self.debugmode = debugmode self.adjust_sys_path() self.load_defaults() @@ -973,11 +980,15 @@ def __init__(self, appid, debugmode=False): self.appid = appid - CubicWebNoAppConfiguration.__init__(self, debugmode) + super(CubicWebConfiguration, self).__init__(debugmode) + fake_gettext = (unicode, lambda ctx, msgid: unicode(msgid)) + for lang in self.available_languages(): + self.translations[lang] = fake_gettext + self._cubes = None self.load_file_configuration(self.main_config_file()) def adjust_sys_path(self): - CubicWebNoAppConfiguration.adjust_sys_path(self) + super(CubicWebConfiguration, self).adjust_sys_path() # adding apphome to python path is not usually necessary in production # environments, but necessary for tests if self.apphome and not self.apphome in sys.path: @@ -1075,8 +1086,8 @@ if not force and hasattr(self, '_logging_initialized'): return self._logging_initialized = True - CubicWebNoAppConfiguration.init_log(self, logthreshold, - logfile=self.get('log-file')) + super_self = super(CubicWebConfiguration, self) + super_self.init_log(logthreshold, logfile=self.get('log-file')) # read a config file if it exists logconfig = join(self.apphome, 'logging.conf') if exists(logconfig): diff -r de49060d4be3 -r 02091c91520f cwvreg.py --- a/cwvreg.py Thu Dec 09 15:27:02 2010 +0100 +++ b/cwvreg.py Sat Dec 18 23:12:14 2010 +0100 @@ -462,7 +462,6 @@ def clear(self): pass def initialization_completed(self): pass - class CubicWebVRegistry(VRegistry): """Central registry for the cubicweb instance, extending the generic VRegistry with some cubicweb specific stuff. @@ -560,14 +559,6 @@ if self.is_reload_needed(path): self.reload(path) - def load_file(self, filepath, modname): - try: - super(CubicWebVRegistry, self).load_file(filepath, modname) - except ImportError: - if self.config.debugmode: - raise - self.exception('failed to load %s from %s', filepath, modname) - def reload(self, path, force_reload=True): """modification detected, reset and reload the vreg""" CW_EVENT_MANAGER.emit('before-registry-reload') diff -r de49060d4be3 -r 02091c91520f debian/control --- a/debian/control Thu Dec 09 15:27:02 2010 +0100 +++ b/debian/control Sat Dec 18 23:12:14 2010 +0100 @@ -33,7 +33,7 @@ Conflicts: cubicweb-multisources Replaces: cubicweb-multisources Provides: cubicweb-multisources -Depends: ${python:Depends}, cubicweb-common (= ${source:Version}), cubicweb-ctl (= ${source:Version}), python-logilab-database (>= 1.3.1), cubicweb-postgresql-support | cubicweb-mysql-support | python-pysqlite2 +Depends: ${python:Depends}, cubicweb-common (= ${source:Version}), cubicweb-ctl (= ${source:Version}), python-logilab-database (>= 1.3.2), cubicweb-postgresql-support | cubicweb-mysql-support | python-pysqlite2 Recommends: pyro (< 4.0.0), cubicweb-documentation (= ${source:Version}) Description: server part of the CubicWeb framework CubicWeb is a semantic web application framework. diff -r de49060d4be3 -r 02091c91520f devtools/__init__.py --- a/devtools/__init__.py Thu Dec 09 15:27:02 2010 +0100 +++ b/devtools/__init__.py Sat Dec 18 23:12:14 2010 +0100 @@ -24,7 +24,7 @@ import logging from datetime import timedelta from os.path import (abspath, join, exists, basename, dirname, normpath, split, - isfile, isabs) + isfile, isabs, splitext) from logilab.common.date import strptime from cubicweb import CW_SOFTWARE_ROOT, ConfigurationError, schema, cwconfig @@ -181,7 +181,7 @@ cube_appobject_path = TestServerConfiguration.cube_appobject_path | TwistedConfiguration.cube_appobject_path def available_languages(self, *args): - return ('en', 'fr', 'de') + return self.cw_languages() def pyro_enabled(self): # but export PYRO_MULTITHREAD=0 or you get problems with sqlite and diff -r de49060d4be3 -r 02091c91520f devtools/devctl.py --- a/devtools/devctl.py Thu Dec 09 15:27:02 2010 +0100 +++ b/devtools/devctl.py Sat Dec 18 23:12:14 2010 +0100 @@ -26,7 +26,7 @@ # completion). So import locally in command helpers. import sys from datetime import datetime -from os import mkdir, chdir, listdir, path as osp +from os import mkdir, chdir, path as osp from warnings import warn from logilab.common import STD_BLACKLIST @@ -34,6 +34,7 @@ from cubicweb.__pkginfo__ import version as cubicwebversion from cubicweb import CW_SOFTWARE_ROOT as BASEDIR, BadCommandUsage from cubicweb.cwctl import CWCTL +from cubicweb.cwconfig import CubicWebNoAppConfiguration from cubicweb.toolsutils import (SKEL_EXCLUDE, Command, copy_skeleton, underline_title) from cubicweb.web.webconfig import WebConfiguration @@ -64,6 +65,10 @@ @property def apphome(self): return None + + def available_languages(self): + return self.cw_languages() + def main_config_file(self): return None def init_log(self): @@ -264,11 +269,6 @@ ''' % cubicwebversion -def cw_languages(): - for fname in listdir(osp.join(WebConfiguration.i18n_lib_dir())): - if fname.endswith('.po'): - yield osp.splitext(fname)[0] - class UpdateCubicWebCatalogCommand(Command): """Update i18n catalogs for cubicweb library. @@ -330,7 +330,7 @@ print '-> merging main pot file with existing translations.' chdir(cwi18ndir) toedit = [] - for lang in cw_languages(): + for lang in CubicWebNoAppConfiguration.cw_languages(): target = '%s.po' % lang execute('msgmerge -N --sort-output -o "%snew" "%s" "%s"' % (target, target, cubicwebpot)) @@ -445,7 +445,7 @@ print '-> merging main pot file with existing translations:' chdir('i18n') toedit = [] - for lang in cw_languages(): + for lang in CubicWebNoAppConfiguration.cw_languages(): print '-> language', lang cubepo = '%s.po' % lang if not osp.exists(cubepo): diff -r de49060d4be3 -r 02091c91520f doc/book/en/admin/cubicweb-ctl.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/admin/cubicweb-ctl.rst Sat Dec 18 23:12:14 2010 +0100 @@ -0,0 +1,122 @@ +.. -*- coding: utf-8 -*- + +.. _cubicweb-ctl: + +``cubicweb-ctl`` tool +===================== + +`cubicweb-ctl` is the swiss knife to manage *CubicWeb* instances. +The general syntax is :: + + cubicweb-ctl [options command] + +To view available commands :: + + cubicweb-ctl + cubicweb-ctl --help + +Please note that the commands available depends on the *CubicWeb* packages +and cubes that have been installed. + +To view the help menu on specific command :: + + cubicweb-ctl --help + +Listing available cubes and instance +------------------------------------- + +* ``list``, provides a list of the available configuration, cubes + and instances. + + +Creation of a new cube +----------------------- + +Create your new cube cube :: + + cubicweb-ctl newcube + +This will create a new cube in +``/path/to/forest/cubicweb/cubes/`` for a Mercurial forest +installation, or in ``/usr/share/cubicweb/cubes`` for a debian +packages installation. + +Create an instance +------------------- + +You must ensure `~/cubicweb.d/` exists prior to this. On windows, the +'~' part will probably expand to 'Documents and Settings/user'. + +To create an instance from an existing cube, execute the following +command :: + + cubicweb-ctl create + +This command will create the configuration files of an instance in +``~/etc/cubicweb.d/``. + +The tool ``cubicweb-ctl`` executes the command ``db-create`` and +``db-init`` when you run ``create`` so that you can complete an +instance creation in a single command. But of course it is possible +to issue these separate commands separately, at a later stage. + +Command to create/initialize an instance database +------------------------------------------------- + +* ``db-create``, creates the system database of an instance (tables and + extensions only) +* ``db-init``, initializes the system database of an instance + (schema, groups, users, workflows...) + +Commands to control instances +----------------------------- + +* ``start``, starts one or more or all instances + +of special interest:: + + start -D + +will start in debug mode (under windows, starting without -D will not +work; you need instead to setup your instance as a service). + +* ``stop``, stops one or more or all instances +* ``restart``, restarts one or more or all instances +* ``status``, returns the status of the instance(s) + +Commands to maintain instances +------------------------------ + +* ``upgrade``, launches the existing instances migration when a new version + of *CubicWeb* or the cubes installed is available +* ``shell``, opens a (Python based) migration shell for manual maintenance of the instance +* ``db-dump``, creates a dump of the system database +* ``db-restore``, restores a dump of the system database +* ``db-check``, checks data integrity of an instance. If the automatic correction + is activated, it is recommanded to create a dump before this operation. +* ``schema-sync``, synchronizes the persistent schema of an instance with + the instance schema. It is recommanded to create a dump before this operation. + +Commands to maintain i18n catalogs +---------------------------------- +* ``i18ncubicweb``, regenerates messages catalogs of the *CubicWeb* library +* ``i18ncube``, regenerates the messages catalogs of a cube +* ``i18ninstance``, recompiles the messages catalogs of an instance. + This is automatically done while upgrading. + +See also chapter :ref:`internationalization`. + +Other commands +-------------- +* ``delete``, deletes an instance (configuration files and database) + +Command to create an instance for Google AppEngine datastore source +------------------------------------------------------------------- +* ``newgapp``, creates the configuration files for an instance + +This command needs to be followed by the commands responsible for +the database initialization. As those are specific to the `datastore`, +specific Google AppEgine database, they are not available for now +in cubicweb-ctl, but they are available in the instance created. + +For more details, please see :ref:`GoogleAppEngineSource` . diff -r de49060d4be3 -r 02091c91520f doc/book/en/admin/index.rst --- a/doc/book/en/admin/index.rst Thu Dec 09 15:27:02 2010 +0100 +++ b/doc/book/en/admin/index.rst Sat Dec 18 23:12:14 2010 +0100 @@ -14,6 +14,7 @@ :numbered: setup + cubicweb-ctl create-instance instance-config site-config diff -r de49060d4be3 -r 02091c91520f doc/book/en/annexes/cubicweb-ctl.rst --- a/doc/book/en/annexes/cubicweb-ctl.rst Thu Dec 09 15:27:02 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -.. -*- coding: utf-8 -*- - -.. _cubicweb-ctl: - -``cubicweb-ctl`` tool -===================== - -`cubicweb-ctl` is the swiss knife to manage *CubicWeb* instances. -The general syntax is :: - - cubicweb-ctl [options command] - -To view available commands :: - - cubicweb-ctl - cubicweb-ctl --help - -Please note that the commands available depends on the *CubicWeb* packages -and cubes that have been installed. - -To view the help menu on specific command :: - - cubicweb-ctl --help - -Listing available cubes and instance -------------------------------------- - -* ``list``, provides a list of the available configuration, cubes - and instances. - - -Creation of a new cube ------------------------ - -Create your new cube cube :: - - cubicweb-ctl newcube - -This will create a new cube in -``/path/to/forest/cubicweb/cubes/`` for a Mercurial forest -installation, or in ``/usr/share/cubicweb/cubes`` for a debian -packages installation. - -Create an instance -------------------- - -You must ensure `~/cubicweb.d/` exists prior to this. On windows, the -'~' part will probably expand to 'Documents and Settings/user'. - -To create an instance from an existing cube, execute the following -command :: - - cubicweb-ctl create - -This command will create the configuration files of an instance in -``~/etc/cubicweb.d/``. - -The tool ``cubicweb-ctl`` executes the command ``db-create`` and -``db-init`` when you run ``create`` so that you can complete an -instance creation in a single command. But of course it is possible -to issue these separate commands separately, at a later stage. - -Command to create/initialize an instance database -------------------------------------------------- - -* ``db-create``, creates the system database of an instance (tables and - extensions only) -* ``db-init``, initializes the system database of an instance - (schema, groups, users, workflows...) - -Commands to control instances ------------------------------ - -* ``start``, starts one or more or all instances - -of special interest:: - - start -D - -will start in debug mode (under windows, starting without -D will not -work; you need instead to setup your instance as a service). - -* ``stop``, stops one or more or all instances -* ``restart``, restarts one or more or all instances -* ``status``, returns the status of the instance(s) - -Commands to maintain instances ------------------------------- - -* ``upgrade``, launches the existing instances migration when a new version - of *CubicWeb* or the cubes installed is available -* ``shell``, opens a migration shell for manual maintenance of the instance -* ``db-dump``, creates a dump of the system database -* ``db-restore``, restores a dump of the system database -* ``db-check``, checks data integrity of an instance. If the automatic correction - is activated, it is recommanded to create a dump before this operation. -* ``schema-sync``, synchronizes the persistent schema of an instance with - the instance schema. It is recommanded to create a dump before this operation. - -Commands to maintain i18n catalogs ----------------------------------- -* ``i18ncubicweb``, regenerates messages catalogs of the *CubicWeb* library -* ``i18ncube``, regenerates the messages catalogs of a cube -* ``i18ninstance``, recompiles the messages catalogs of an instance. - This is automatically done while upgrading. - -See also chapter :ref:`internationalization`. - -Other commands --------------- -* ``delete``, deletes an instance (configuration files and database) - -Command to create an instance for Google AppEngine datastore source -------------------------------------------------------------------- -* ``newgapp``, creates the configuration files for an instance - -This command needs to be followed by the commands responsible for -the database initialization. As those are specific to the `datastore`, -specific Google AppEgine database, they are not available for now -in cubicweb-ctl, but they are available in the instance created. - -For more details, please see :ref:`GoogleAppEngineSource` . diff -r de49060d4be3 -r 02091c91520f doc/book/en/annexes/index.rst --- a/doc/book/en/annexes/index.rst Thu Dec 09 15:27:02 2010 +0100 +++ b/doc/book/en/annexes/index.rst Sat Dec 18 23:12:14 2010 +0100 @@ -13,7 +13,6 @@ :numbered: faq - cubicweb-ctl rql/index mercurial depends diff -r de49060d4be3 -r 02091c91520f doc/book/en/devrepo/testing.rst --- a/doc/book/en/devrepo/testing.rst Thu Dec 09 15:27:02 2010 +0100 +++ b/doc/book/en/devrepo/testing.rst Sat Dec 18 23:12:14 2010 +0100 @@ -343,6 +343,60 @@ therefore making new entity types and relations available to the tests. +Literate programming +-------------------- + +CubicWeb provides some literate programming capabilities. The :ref:`cubicweb-ctl` +`shell` command accepts differents format files. If your file ends with `.txt` +or `.rst`, the file will be parsed by :mod:`doctest.testfile` with CubicWeb +:ref:`migration` API enabled in it. + +Create a `scenario.txt` file into `test/` directory and fill with some content. +Please refer the :mod:`doctest.testfile` `documentation`_. + +.. _documentation: http://docs.python.org/library/doctest.html + +Then, you can run it directly by:: + + $ cubicweb-ctl shell test/scenario.txt + +When your scenario file is ready, put it in a new test case to be able to run +it automatically. + +.. sourcecode:: python + + from os.path import dirname, join + from logilab.common.testlib import unittest_main + from cubicweb.devtools.testlib import CubicWebTC + + class AcceptanceTC(CubicWebTC): + + def test_scenario(self): + self.assertDocTestFile(join(dirname(__file__), 'scenario.txt')) + + if __name__ == '__main__': + unittest_main() + +Skipping a scenario +``````````````````` + +If you want to set up initial conditions that you can't put in your unit test +case, you have to use a :exc:`KeyboardInterrupt` exception only because of the +way :mod:`doctest` module will catch all the exceptions internally. + + >>> if condition_not_met: + ... raise KeyboardInterrupt('please, check your fixture.') + +Passing paramaters +`````````````````` +Using extra arguments to parametrize your scenario is possible by prepend them +by double dashes. + +Please refer to the `cubicweb-ctl shell --help` usage. + +.. important:: + Your scenario file must be utf-8 encoded. + Test APIS --------- diff -r de49060d4be3 -r 02091c91520f hooks/syncschema.py --- a/hooks/syncschema.py Thu Dec 09 15:27:02 2010 +0100 +++ b/hooks/syncschema.py Sat Dec 18 23:12:14 2010 +0100 @@ -285,13 +285,15 @@ self.session.vreg.schema.rename_entity_type(oldname, newname) # we need sql to operate physical changes on the system database sqlexec = self.session.system_sql - sqlexec('ALTER TABLE %s%s RENAME TO %s%s' % (SQL_PREFIX, oldname, - SQL_PREFIX, newname)) + dbhelper= self.session.pool.source('system').dbhelper + sql = dbhelper.sql_rename_table(SQL_PREFIX+oldname, + SQL_PREFIX+newname) + sqlexec(sql) self.info('renamed table %s to %s', oldname, newname) - sqlexec('UPDATE entities SET type=%s WHERE type=%s', - (newname, oldname)) - sqlexec('UPDATE deleted_entities SET type=%s WHERE type=%s', - (newname, oldname)) + sqlexec('UPDATE entities SET type=%(newname)s WHERE type=%(oldname)s', + {'newname': newname, 'oldname': oldname}) + sqlexec('UPDATE deleted_entities SET type=%(newname)s WHERE type=%(oldname)s', + {'newname': newname, 'oldname': oldname}) # XXX transaction records def precommit_event(self): diff -r de49060d4be3 -r 02091c91520f migration.py --- a/migration.py Thu Dec 09 15:27:02 2010 +0100 +++ b/migration.py Sat Dec 18 23:12:14 2010 +0100 @@ -361,6 +361,9 @@ import doctest return doctest.testfile(migrscript, module_relative=False, optionflags=doctest.ELLIPSIS, + # verbose mode when user input is expected + verbose=self.verbosity==2, + report=True, encoding='utf-8', globs=scriptlocals) self._context_stack.pop() diff -r de49060d4be3 -r 02091c91520f req.py --- a/req.py Thu Dec 09 15:27:02 2010 +0100 +++ b/req.py Sat Dec 18 23:12:14 2010 +0100 @@ -142,7 +142,7 @@ def ensure_ro_rql(self, rql): """raise an exception if the given rql is not a select query""" - first = rql.split(' ', 1)[0].lower() + first = rql.split(None, 1)[0].lower() if first in ('insert', 'set', 'delete'): raise Unauthorized(self._('only select queries are authorized')) diff -r de49060d4be3 -r 02091c91520f server/hook.py --- a/server/hook.py Thu Dec 09 15:27:02 2010 +0100 +++ b/server/hook.py Sat Dec 18 23:12:14 2010 +0100 @@ -747,7 +747,7 @@ MyOperation.get_instance(self._cw).add_data(self.entity) - class MyOperation(DataOperation, DataOperationMixIn): + class MyOperation(DataOperationMixIn, Operation): def precommit_event(self): for bucket in self.get_data(): process(bucket) diff -r de49060d4be3 -r 02091c91520f server/schemaserial.py --- a/server/schemaserial.py Thu Dec 09 15:27:02 2010 +0100 +++ b/server/schemaserial.py Sat Dec 18 23:12:14 2010 +0100 @@ -126,8 +126,9 @@ sqlexec('UPDATE %(p)sCWEType SET %(p)sname=%%(n)s WHERE %(p)seid=%%(x)s' % {'p': sqlutils.SQL_PREFIX}, {'x': eid, 'n': netype}) if etype.lower() != netype.lower(): - sqlexec('ALTER TABLE %s%s RENAME TO %s%s' % ( - sqlutils.SQL_PREFIX, etype, sqlutils.SQL_PREFIX, netype)) + alter_table_sql = dbhelper.sql_rename_table(sqlutils.SQL_PREFIX+etype, + sqlutils.SQL_PREFIX+netype) + sqlexec(alter_table_sql) sqlexec('UPDATE entities SET type=%(n)s WHERE type=%(x)s', {'x': etype, 'n': netype}) session.commit(False) diff -r de49060d4be3 -r 02091c91520f server/sources/ldapuser.py --- a/server/sources/ldapuser.py Thu Dec 09 15:27:02 2010 +0100 +++ b/server/sources/ldapuser.py Sat Dec 18 23:12:14 2010 +0100 @@ -126,6 +126,12 @@ 'help': 'classes of user', 'group': 'ldap-source', 'level': 1, }), + ('user-filter', + {'type': 'string', + 'default': '', + 'help': 'additional filters to be set in the ldap query to find valid users', + 'group': 'ldap-source', 'level': 2, + }), ('user-login-attr', {'type' : 'string', 'default': 'uid', @@ -177,11 +183,11 @@ self.user_login_attr = source_config['user-login-attr'] self.user_default_groups = splitstrip(source_config['user-default-group']) self.user_attrs = dict(v.split(':', 1) for v in splitstrip(source_config['user-attrs-map'])) + self.user_filter = source_config.get('user-filter') self.user_rev_attrs = {'eid': 'dn'} for ldapattr, cwattr in self.user_attrs.items(): self.user_rev_attrs[cwattr] = ldapattr - self.base_filters = [filter_format('(%s=%s)', ('objectClass', o)) - for o in self.user_classes] + self.base_filters = self._make_base_filters() self._conn = None self._cache = {} # ttlm is in minutes! @@ -194,6 +200,13 @@ source_config.get('synchronization-interval', 24*60*60)) + def _make_base_filters(self): + filters = [filter_format('(%s=%s)', ('objectClass', o)) + for o in self.user_classes] + if self.user_filter: + filters += [self.user_filter] + return filters + def reset_caches(self): """method called during test to reset potential source caches""" self._cache = {} @@ -287,8 +300,7 @@ # we really really don't want that raise AuthenticationError() searchfilter = [filter_format('(%s=%s)', (self.user_login_attr, login))] - searchfilter.extend([filter_format('(%s=%s)', ('objectClass', o)) - for o in self.user_classes]) + searchfilter.extend(self._make_base_filters()) searchstr = '(&%s)' % ''.join(searchfilter) # first search the user try: diff -r de49060d4be3 -r 02091c91520f test/unittest_req.py --- a/test/unittest_req.py Thu Dec 09 15:27:02 2010 +0100 +++ b/test/unittest_req.py Sat Dec 18 23:12:14 2010 +0100 @@ -18,7 +18,7 @@ from logilab.common.testlib import TestCase, unittest_main from cubicweb.req import RequestSessionBase from cubicweb.devtools.testlib import CubicWebTC - +from cubicweb import Unauthorized class RebuildURLTC(TestCase): def test_rebuild_url(self): @@ -42,6 +42,12 @@ self.assertRaises(AssertionError, req.build_url, 'one', 'two not allowed') self.assertRaises(AssertionError, req.build_url, 'view', test=None) + def test_ensure_no_rql(self): + req = RequestSessionBase(None) + self.assertEqual(req.ensure_ro_rql('Any X WHERE X is CWUser'), None) + self.assertEqual(req.ensure_ro_rql(' Any X WHERE X is CWUser '), None) + self.assertRaises(Unauthorized, req.ensure_ro_rql, 'SET X login "toto" WHERE X is CWUser') + self.assertRaises(Unauthorized, req.ensure_ro_rql, ' SET X login "toto" WHERE X is CWUser ') if __name__ == '__main__': unittest_main() diff -r de49060d4be3 -r 02091c91520f web/component.py --- a/web/component.py Thu Dec 09 15:27:02 2010 +0100 +++ b/web/component.py Sat Dec 18 23:12:14 2010 +0100 @@ -234,7 +234,7 @@ # argument def render(self, w, **kwargs): if hasattr(self, 'call'): - warn('[3.10] should not anymore implements call on %s, see new CtxComponent api' + warn('[3.10] should not anymore implement call on %s, see new CtxComponent api' % self.__class__, DeprecationWarning) self.w = w def wview(__vid, rset=None, __fallback_vid=None, **kwargs): diff -r de49060d4be3 -r 02091c91520f web/data/cubicweb.edition.js --- a/web/data/cubicweb.edition.js Thu Dec 09 15:27:02 2010 +0100 +++ b/web/data/cubicweb.edition.js Sat Dec 18 23:12:14 2010 +0100 @@ -11,7 +11,7 @@ /** * .. function:: setPropValueWidget(varname, tabindex) * - * called on Eproperty key selection: + * called on CWProperty key selection: * - get the selected value * - get a widget according to the key by a sync query to the server * - fill associated div with the returned html @@ -65,12 +65,12 @@ vid: 'unrelateddivs', relation: selectedValue, rql: rql_for_eid(eid), - '__notemplate': 1, - callback: function() { - _showMatchingSelect(eid, jQuery('#' + divId)); - } + '__notemplate': 1 }; - jQuery('#unrelatedDivs_' + eid).loadxhtml(baseuri() + 'view', args, 'post', 'append'); + var d = jQuery('#unrelatedDivs_' + eid).loadxhtml(baseuri() + 'view', args, 'post', 'append'); + d.addCallback(function() { + _showMatchingSelect(eid, jQuery('#' + divId)); + }); } else { _showMatchingSelect(eid, divNode); } @@ -209,7 +209,7 @@ } } elementId = elementId.substring(2, elementId.length); - loadRemote('json', ajaxFuncArgs('remove_pending_inserts', null, + loadRemote('json', ajaxFuncArgs('remove_pending_insert', null, elementId.split(':')), 'GET', true); } diff -r de49060d4be3 -r 02091c91520f web/data/cubicweb.widgets.js --- a/web/data/cubicweb.widgets.js Thu Dec 09 15:27:02 2010 +0100 +++ b/web/data/cubicweb.widgets.js Sat Dec 18 23:12:14 2010 +0100 @@ -91,6 +91,11 @@ }; var hiHandlers = methods.hiddenInputHandlers; $(this).data('cwautocomplete', instanceData); + // in case of an existing value, the hidden input must be initialized even if + // the value is not changed + if (($(instanceData.userInput).attr('cubicweb:initialvalue') !== undefined) && !instanceData.hiddenInput){ + hiHandlers.initializeHiddenInput(instanceData); + } $.ui.autocomplete.prototype._search = methods.search; if (settings.multiple) { $.ui.autocomplete.filter = methods.multiple.makeFilter(this); diff -r de49060d4be3 -r 02091c91520f web/views/autoform.py --- a/web/views/autoform.py Thu Dec 09 15:27:02 2010 +0100 +++ b/web/views/autoform.py Sat Dec 18 23:12:14 2010 +0100 @@ -550,6 +550,7 @@ pending_inserts = set(get_pending_inserts(form._cw, form.edited_entity.eid)) for pendingid in pending_inserts: eidfrom, rtype, eidto = pendingid.split(':') + pendingid = 'id' + pendingid if typed_eid(eidfrom) == entity.eid: # subject label = display_name(form._cw, rtype, 'subject', entity.__regid__) diff -r de49060d4be3 -r 02091c91520f web/views/baseviews.py --- a/web/views/baseviews.py Thu Dec 09 15:27:02 2010 +0100 +++ b/web/views/baseviews.py Sat Dec 18 23:12:14 2010 +0100 @@ -188,7 +188,7 @@ def cell_call(self, row, col): _ = self._cw._ entity = self.cw_rset.get_entity(row, col) - self.w(u'