--- 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:
--- 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,
--- 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,
--- 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
--- 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):
--- 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):
--- 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 <http://www.gnu.org/licenses/>.
-"""Some utilities for CubicWeb server/clients.
+"""Some utilities for CubicWeb server/clients."""
-"""
__docformat__ = "restructuredtext en"
import os
--- 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
--- 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;
--- 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 = ''
--- 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')")
--- 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'<div>%s' % _('Parent classes:'))
+ self.w(u'<div>%s' % _('Parent class:'))
self.wview('csv', entity.related('specializes', 'subject'))
self.w(u'</div>')
if entity.reverse_specializes: