# HG changeset patch # User Sylvain Thénault # Date 1280488716 -7200 # Node ID ee6deb534f57c3ef76eb548fa7a9de74661e7be5 # Parent 31776723c0c5a8997de4f41fd735a2837ac5b811# Parent 3fd4a34c4a09850d69d2877b09e4d37f4f1cb2b0 backport stable diff -r 31776723c0c5 -r ee6deb534f57 cwvreg.py --- a/cwvreg.py Fri Jul 30 10:09:31 2010 +0200 +++ b/cwvreg.py Fri Jul 30 13:18:36 2010 +0200 @@ -205,7 +205,7 @@ ObjectNotFound, NoSelectableObject, RegistryNotFound, CW_EVENT_MANAGER) from cubicweb.utils import dump_class -from cubicweb.vregistry import VRegistry, Registry, class_regid +from cubicweb.vregistry import VRegistry, Registry, class_regid, classid from cubicweb.rtags import RTAGS def clear_rtag_objects(): @@ -310,11 +310,10 @@ @cached def parent_classes(self, etype): if etype == 'Any': - return [self.etype_class('Any')] - eschema = self.schema.eschema(etype) - parents = [self.etype_class(e.type) for e in eschema.ancestors()] - parents.append(self.etype_class('Any')) - return parents + return (), self.etype_class('Any') + parents = tuple(self.etype_class(e.type) + for e in self.schema.eschema(etype).ancestors()) + return parents, self.etype_class('Any') @cached def etype_class(self, etype): @@ -617,7 +616,7 @@ for iface in ifaces) if not ('Any' in ifaces or ifaces & implemented_interfaces): self.debug('unregister %s (no implemented ' - 'interface among %s)', obj, ifaces) + 'interface among %s)', classid(obj), ifaces) self.unregister(obj) # since 3.9: remove appobjects which depending on other, unexistant # appobjects @@ -625,7 +624,8 @@ try: registry = self[regname] except RegistryNotFound: - self.debug('unregister %s (no registry %s)', obj, regname) + self.debug('unregister %s (no registry %s)', classid(obj), + regname) self.unregister(obj) continue for regid in regids: @@ -633,7 +633,7 @@ break else: self.debug('unregister %s (no %s object in registry %s)', - obj, ' or '.join(regids), regname) + classid(obj), ' or '.join(regids), regname) self.unregister(obj) super(CubicWebVRegistry, self).initialization_completed() for rtag in RTAGS: diff -r 31776723c0c5 -r ee6deb534f57 devtools/cwwindmill.py --- a/devtools/cwwindmill.py Fri Jul 30 10:09:31 2010 +0200 +++ b/devtools/cwwindmill.py Fri Jul 30 13:18:36 2010 +0200 @@ -92,6 +92,8 @@ # see windmill.bin.admin_options.Firebug import windmill windmill.settings['INSTALL_FIREBUG'] = 'firebug' + windmill.settings['MOZILLA_PLUGINS'].append('/usr/share/mozilla-extensions/') + windmill.settings['MOZILLA_PLUGINS'].append('/usr/share/xul-ext/') self.windmill_shell_objects['start_' + self.browser]() self.windmill_shell_objects['do_test'](self.test_dir, diff -r 31776723c0c5 -r ee6deb534f57 migration.py --- a/migration.py Fri Jul 30 10:09:31 2010 +0200 +++ b/migration.py Fri Jul 30 13:18:36 2010 +0200 @@ -24,13 +24,15 @@ import logging import tempfile from os.path import exists, join, basename, splitext +from itertools import chain +from logilab.common import IGNORED_EXTENSIONS from logilab.common.decorators import cached from logilab.common.configuration import REQUIRED, read_old_config from logilab.common.shellutils import ASK from logilab.common.changelog import Version -from cubicweb import ConfigurationError +from cubicweb import ConfigurationError, ExecutionError def filter_scripts(config, directory, fromversion, toversion, quiet=True): @@ -51,8 +53,7 @@ return [] result = [] for fname in os.listdir(directory): - if fname.endswith('.pyc') or fname.endswith('.pyo') \ - or fname.endswith('~'): + if fname.endswith(IGNORED_EXTENSIONS): continue fpath = join(directory, fname) try: @@ -75,9 +76,6 @@ return sorted(result) -IGNORED_EXTENSIONS = ('.swp', '~') - - def execscript_confirm(scriptpath): """asks for confirmation before executing a script and provides the ability to show the script's content @@ -285,6 +283,16 @@ Display the migration script path, ask for confirmation and execute it if confirmed + Allowed input file formats for migration scripts: + - `python` (.py) + - `sql` (.sql) + - `doctest` (.txt or .rst) + + .. warning:: sql migration scripts are not available in web-only instance + + You can pass script parameters with using double dash (--) in the + command line + Context environment can have these variables defined: - __name__ : will be determine by funcname parameter - __file__ : is the name of the script if it exists @@ -295,13 +303,20 @@ :params args: optional arguments for funcname :keyword scriptargs: optional arguments of the script """ + ftypes = {'python': ('.py',), + 'doctest': ('.txt', '.rst'), + 'sql': ('.sql',)} + # sql migration scripts are not available in web-only instance + if not hasattr(self, "session"): + ftypes.pop('sql') migrscript = os.path.normpath(migrscript) - if migrscript.endswith('.py'): - script_mode = 'python' - elif migrscript.endswith(('.txt', '.rst')): - script_mode = 'doctest' + for (script_mode, ftype) in ftypes.items(): + if migrscript.endswith(ftype): + break else: - raise Exception('This is not a valid cubicweb shell input') + ftypes = ', '.join(chain(*ftypes.values())) + msg = 'ignoring %s, not a valid script extension (%s)' + raise ExecutionError(msg % (migrscript, ftypes)) if not self.execscript_confirm(migrscript): return scriptlocals = self._create_context().copy() @@ -322,6 +337,10 @@ self.critical('no %s in script %s', funcname, migrscript) return None return func(*args, **kwargs) + elif script_mode == 'sql': + from cubicweb.server.sqlutils import sqlexec + sqlexec(open(migrscript).read(), self.session.system_sql) + self.commit() else: # script_mode == 'doctest' import doctest doctest.testfile(migrscript, module_relative=False, diff -r 31776723c0c5 -r ee6deb534f57 selectors.py --- a/selectors.py Fri Jul 30 10:09:31 2010 +0200 +++ b/selectors.py Fri Jul 30 13:18:36 2010 +0200 @@ -212,24 +212,24 @@ from cubicweb.appobject import traced_selection # XXX for bw compat -def score_interface(etypesreg, cls_or_inst, cls, iface): +def score_interface(etypesreg, eclass, iface): """Return XXX if the give object (maybe an instance or class) implements the interface. """ if getattr(iface, '__registry__', None) == 'etypes': # adjust score if the interface is an entity class - parents = etypesreg.parent_classes(cls_or_inst.__regid__) - if iface is cls: + parents, any = etypesreg.parent_classes(eclass.__regid__) + if iface is eclass: return len(parents) + 4 - if iface is parents[-1]: # Any + if iface is any: # Any return 1 - for index, basecls in enumerate(reversed(parents[:-1])): + for index, basecls in enumerate(reversed(parents)): if iface is basecls: return index + 3 return 0 # XXX iface in implements deprecated in 3.9 - if implements_iface(cls_or_inst, iface): - # implenting an interface takes precedence other special Any interface + if implements_iface(eclass, iface): + # implementing an interface takes precedence other special Any interface return 2 return 0 @@ -699,9 +699,6 @@ ','.join(str(s) for s in self.expected_ifaces)) def score_class(self, eclass, req): - return self.score_interfaces(req, eclass, eclass) - - def score_interfaces(self, req, cls_or_inst, cls): score = 0 etypesreg = req.vreg['etypes'] for iface in self.expected_ifaces: @@ -711,7 +708,7 @@ iface = etypesreg.etype_class(iface) except KeyError: continue # entity type not in the schema - score += score_interface(etypesreg, cls_or_inst, cls, iface) + score += score_interface(etypesreg, eclass, iface) return score def _reset_is_instance_cache(vreg): @@ -744,9 +741,6 @@ ','.join(str(s) for s in self.expected_etypes)) def score_class(self, eclass, req): - return self.score_etypes(req, eclass, eclass) - - def score_etypes(self, req, cls_or_inst, cls): # cache on vreg to avoid reloading issues cache = req.vreg._is_instance_selector_cache try: @@ -758,22 +752,20 @@ expected_eclasses = cache[self] = [] for etype in self.expected_etypes: try: - expected_eclasses.append( - (etypesreg.etype_class(etype), - etypesreg.parent_classes(etype)) - ) + expected_eclasses.append(etypesreg.etype_class(etype)) except KeyError: continue # entity type not in the schema + parents, any = req.vreg['etypes'].parent_classes(eclass.__regid__) score = 0 - for iface, parents in expected_eclasses: + for expectedcls in expected_eclasses: # adjust score according to class proximity - if iface is cls: + if expectedcls is eclass: score += len(parents) + 4 - elif iface is parents[-1]: # Any + elif expectedcls is any: # Any score += 1 else: - for index, basecls in enumerate(reversed(parents[:-1])): - if iface is basecls: + for index, basecls in enumerate(reversed(parents)): + if expectedcls is basecls: score += index + 3 break return score diff -r 31776723c0c5 -r ee6deb534f57 server/migractions.py --- a/server/migractions.py Fri Jul 30 10:09:31 2010 +0200 +++ b/server/migractions.py Fri Jul 30 13:18:36 2010 +0200 @@ -49,7 +49,7 @@ from yams.constraints import SizeConstraint from yams.schema2sql import eschema2sql, rschema2sql -from cubicweb import AuthenticationError +from cubicweb import AuthenticationError, ExecutionError from cubicweb.schema import (ETYPE_NAME_MAP, META_RTYPES, VIRTUAL_RTYPES, PURE_VIRTUAL_RTYPES, CubicWebRelationSchema, order_eschemas) @@ -117,27 +117,18 @@ super(ServerMigrationHelper, self).migrate(vcconf, toupgrade, options) def cmd_process_script(self, migrscript, funcname=None, *args, **kwargs): - """execute a migration script - in interactive mode, display the migration script path, ask for - confirmation and execute it if confirmed - """ try: - if migrscript.endswith('.sql'): - if self.execscript_confirm(migrscript): - sqlexec(open(migrscript).read(), self.session.system_sql) - elif migrscript.endswith('.py') or migrscript.endswith('.txt'): - return super(ServerMigrationHelper, self).cmd_process_script( - migrscript, funcname, *args, **kwargs) - else: - print >> sys.stderr - print >> sys.stderr, ('-> ignoring %s, only .py .sql and .txt scripts are considered' % - migrscript) - print >> sys.stderr - self.commit() + return super(ServerMigrationHelper, self).cmd_process_script( + migrscript, funcname, *args, **kwargs) + except ExecutionError, err: + print >> sys.stderr, "-> %s" % err except: self.rollback() raise + # Adjust docstring + cmd_process_script.__doc__ = MigrationHelper.cmd_process_script.__doc__ + # server specific migration methods ######################################## def backup_database(self, backupfile=None, askconfirm=True): diff -r 31776723c0c5 -r ee6deb534f57 test/unittest_selectors.py --- a/test/unittest_selectors.py Fri Jul 30 10:09:31 2010 +0200 +++ b/test/unittest_selectors.py Fri Jul 30 13:18:36 2010 +0200 @@ -151,6 +151,11 @@ cls = self.vreg['etypes'].etype_class('Personne') self.failIf(is_instance('Societe').score_class(cls, self.request())) + def test_yams_inheritance(self): + cls = self.vreg['etypes'].etype_class('Transition') + self.assertEquals(is_instance('BaseTransition').score_class(cls, self.request()), + 3) + class MatchUserGroupsTC(CubicWebTC): def test_owners_group(self): diff -r 31776723c0c5 -r ee6deb534f57 utils.py --- a/utils.py Fri Jul 30 10:09:31 2010 +0200 +++ b/utils.py Fri Jul 30 13:18:36 2010 +0200 @@ -15,9 +15,8 @@ # # You should have received a copy of the GNU Lesser General Public License along # with CubicWeb. If not, see . -"""Some utilities for CubicWeb server/clients. +"""Some utilities for CubicWeb server/clients.""" -""" __docformat__ = "restructuredtext en" import os diff -r 31776723c0c5 -r ee6deb534f57 view.py --- a/view.py Fri Jul 30 10:09:31 2010 +0200 +++ b/view.py Fri Jul 30 13:18:36 2010 +0200 @@ -23,7 +23,6 @@ from cStringIO import StringIO from warnings import warn -from cubicweb.utils import json from logilab.common.deprecation import deprecated from logilab.mtconverter import xml_escape @@ -33,6 +32,7 @@ from cubicweb.selectors import yes, non_final_entity, nonempty_rset, none_rset from cubicweb.appobject import AppObject from cubicweb.utils import UStringIO, HTMLStream +from cubicweb.uilib import domid, js from cubicweb.schema import display_name from cubicweb.vregistry import classid @@ -325,7 +325,8 @@ return self._cw.vreg["etypes"].etype_class(etype).cw_create_url( self._cw, **kwargs) - def field(self, label, value, row=True, show_label=True, w=None, tr=True, table=False): + def field(self, label, value, row=True, show_label=True, w=None, tr=True, + table=False): """read-only field""" if w is None: w = self.w @@ -495,12 +496,11 @@ def build_update_js_call(self, cbname, msg): rql = self.cw_rset.printable_rql() - return "javascript:userCallbackThenUpdateUI('%s', '%s', %s, %s, '%s', '%s')" % ( - cbname, self.id, json.dumps(rql), json.dumps(msg), - self.__registry__, self.div_id()) + return "javascript: %s" % js.userCallbackThenUpdateUI( + cbname, self.__regid__, rql, msg, self.__registry__, self.domid) def build_reload_js_call(self, cbname, msg): - return "javascript:userCallbackThenReloadPage('%s', %s)" % (cbname, json.dumps(msg)) + return "javascript: %s" % js.userCallbackThenReloadPage(cbname, msg) build_js = build_update_js_call # expect updatable component by default diff -r 31776723c0c5 -r ee6deb534f57 web/data/cubicweb.edition.js --- a/web/data/cubicweb.edition.js Fri Jul 30 10:09:31 2010 +0200 +++ b/web/data/cubicweb.edition.js Fri Jul 30 13:18:36 2010 +0200 @@ -586,7 +586,7 @@ try { var zipped = cw.utils.formContents(formid); var args = ajaxFuncArgs('validate_form', null, action, zipped[0], zipped[1]); - var d = loadRemote('json', args); + var d = loadRemote('json', args, 'POST'); } catch(ex) { log('got exception', ex); return false; diff -r 31776723c0c5 -r ee6deb534f57 web/facet.py --- a/web/facet.py Fri Jul 30 10:09:31 2010 +0200 +++ b/web/facet.py Fri Jul 30 13:18:36 2010 +0200 @@ -271,13 +271,14 @@ __registry__ = 'facets' cw_property_defs = { _('visible'): dict(type='Boolean', default=True, - help=_('display the box or not')), + help=_('display the facet or not')), _('order'): dict(type='Int', default=99, - help=_('display order of the box')), + help=_('display order of the facet')), _('context'): dict(type='String', default='', # None <-> both vocabulary=(_('tablefilter'), _('facetbox'), ''), - help=_('context where this box should be displayed')), + help=_('context where this facet should be displayed, ' + 'leave empty for both')), } visible = True context = '' diff -r 31776723c0c5 -r ee6deb534f57 web/test/windmill/test_connexion.py --- a/web/test/windmill/test_connexion.py Fri Jul 30 10:09:31 2010 +0200 +++ b/web/test/windmill/test_connexion.py Fri Jul 30 13:18:36 2010 +0200 @@ -9,16 +9,21 @@ client = WindmillTestClient(__name__) client.open(url=u'/') + client.waits.forPageLoad(timeout=u'20000') client.asserts.assertJS(js=u"$('#loginForm').is(':visible')") client.type(text=LOGIN, id=u'__login') client.type(text=PASSWORD, id=u'__password') + client.execJS(js=u"$('#loginForm').submit()") client.waits.forPageLoad(timeout=u'20000') client.asserts.assertJS(js=u'$(\'.message\').text() == "welcome %s !"' % LOGIN) client.open(url=u'/logout') + client.waits.forPageLoad(timeout=u'20000') client.open(url=u'/') + client.waits.forPageLoad(timeout=u'20000') client.asserts.assertJS(js=u"$('#loginForm').is(':visible')") + def test_wrong_connect(): client = WindmillTestClient(__name__) @@ -32,4 +37,5 @@ client.waits.forPageLoad(timeout=u'20000') client.asserts.assertTextIn(validator=u'authentication failure', id=u'loginBox') client.open(url=u'/') + client.waits.forPageLoad(timeout=u'20000') client.asserts.assertJS(js=u"$('#loginForm').is(':visible')") diff -r 31776723c0c5 -r ee6deb534f57 web/views/schema.py --- a/web/views/schema.py Fri Jul 30 10:09:31 2010 +0200 +++ b/web/views/schema.py Fri Jul 30 13:18:36 2010 +0200 @@ -304,7 +304,7 @@ _ = self._cw._ # inheritance if entity.specializes: - self.w(u'
%s' % _('Parent classes:')) + self.w(u'
%s' % _('Parent class:')) self.wview('csv', entity.related('specializes', 'subject')) self.w(u'
') if entity.reverse_specializes: