# HG changeset patch # User Pierre-Yves David # Date 1366024681 -7200 # Node ID be91151107f6594e7681b6b32fc07243912a795c # Parent 738f97bc3e1983003cf0b72de204828be1f57a4c# Parent 7920f439f383200b7a7832dded3aeb03fc516cf3 merge 3.16.x fix diff -r 738f97bc3e19 -r be91151107f6 .hgtags --- a/.hgtags Wed Apr 10 16:46:18 2013 +0200 +++ b/.hgtags Mon Apr 15 13:18:01 2013 +0200 @@ -286,3 +286,8 @@ 853237d1daf6710af94cc2ec8ee12aa7dba16934 cubicweb-debian-version-3.16.0-1 d95cbb7349f01b9e02e5da65d55a92582bbee6db cubicweb-version-3.16.1 84fbcdc8021c9c198fef3c6a9ad90c298ee12566 cubicweb-debian-version-3.16.1-1 +a2b4f245aa57013cf8bbcfa2f3d021ee04bccfa0 cubicweb-version-3.16.2 +b3c1ad0cbf001883058ab82be9474544a31b5294 cubicweb-debian-version-3.16.2-1 +ee860c51f56bd65c4f6ea363462c02700d1dab5a cubicweb-version-3.16.3 +ee860c51f56bd65c4f6ea363462c02700d1dab5a cubicweb-debian-version-3.16.3-1 +ee860c51f56bd65c4f6ea363462c02700d1dab5a cubicweb-centos-version-3.16.3-1 diff -r 738f97bc3e19 -r be91151107f6 __pkginfo__.py --- a/__pkginfo__.py Wed Apr 10 16:46:18 2013 +0200 +++ b/__pkginfo__.py Mon Apr 15 13:18:01 2013 +0200 @@ -22,7 +22,7 @@ modname = distname = "cubicweb" -numversion = (3, 16, 1) +numversion = (3, 16, 3) version = '.'.join(str(num) for num in numversion) description = "a repository of entities / relations for knowledge management" diff -r 738f97bc3e19 -r be91151107f6 cubicweb.spec --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cubicweb.spec Mon Apr 15 13:18:01 2013 +0200 @@ -0,0 +1,56 @@ +%if 0%{?el5} +%define python python26 +%define __python /usr/bin/python2.6 +%else +%define python python +%define __python /usr/bin/python +%endif + +Name: cubicweb +Version: 3.16.3 +Release: logilab.1%{?dist} +Summary: CubicWeb is a semantic web application framework +Source0: http://download.logilab.org/pub/cubicweb/cubicweb-%{version}.tar.gz +License: LGPLv2+ +Group: Development/Languages/Python +Vendor: Logilab +Url: http://www.cubicweb.org/project/cubicweb + +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot +BuildArch: noarch + +Requires: %{python} +Requires: %{python}-logilab-common >= 0.59.0 +Requires: %{python}-logilab-mtconverter >= 0.8.0 +Requires: %{python}-rql >= 0.31.2 +Requires: %{python}-yams >= 0.36.0 +Requires: %{python}-logilab-database >= 1.9.0 +Requires: %{python}-passlib +Requires: %{python}-lxml +Requires: %{python}-twisted-web +# the schema view uses `dot'; at least on el5, png output requires graphviz-gd +Requires: graphviz-gd +Requires: gettext + +BuildRequires: %{python} + +%description +a repository of entities / relations for knowledge management + +%prep +%setup -q +%if 0%{?el5} +# change the python version in shebangs +find . -name '*.py' -type f -print0 | xargs -0 sed -i '1,3s;^#!.*python.*$;#! /usr/bin/python2.6;' +%endif + +%install +NO_SETUPTOOLS=1 %{__python} setup.py --quiet install --no-compile --prefix=%{_prefix} --root="$RPM_BUILD_ROOT" + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-, root, root) +/* + diff -r 738f97bc3e19 -r be91151107f6 debian/changelog --- a/debian/changelog Wed Apr 10 16:46:18 2013 +0200 +++ b/debian/changelog Mon Apr 15 13:18:01 2013 +0200 @@ -1,3 +1,15 @@ +cubicweb (3.16.3-1) unstable; urgency=low + + * New upstream release + + -- David Douard Wed, 10 Apr 2013 10:37:37 +0200 + +cubicweb (3.16.2-1) unstable; urgency=low + + * New upstream release + + -- David Douard Mon, 08 Apr 2013 19:29:33 +0200 + cubicweb (3.16.1-1) squeeze; urgency=low * New upstream release diff -r 738f97bc3e19 -r be91151107f6 devtools/cwwindmill.py --- a/devtools/cwwindmill.py Wed Apr 10 16:46:18 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of CubicWeb. -# -# CubicWeb is free software: you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free -# Software Foundation, either version 2.1 of the License, or (at your option) -# any later version. -# -# CubicWeb is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -# details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with CubicWeb. If not, see . -"""this module contains base classes for windmill integration - -:todo: - - * import CubicWeb session object into windmill scope to be able to run RQL - * manage command line option from pytest to run specific use tests only -""" - - -import os, os.path as osp -from logging import getLogger, ERROR -import sys - -# imported by default to simplify further import statements -from logilab.common.testlib import TestCase, unittest_main, Tags - -try: - import windmill - from windmill.dep import functest - from windmill.bin.admin_lib import configure_global_settings, setup, teardown -except ImportError: - windmill = None - -from cubicweb.devtools.httptest import CubicWebServerTC, CubicWebServerConfig - -if windmill is None: - class CubicWebWindmillUseCase(CubicWebServerTC): - tags = CubicWebServerTC.tags & Tags(('windmill',)) - - def testWindmill(self): - self.skipTest("can't import windmill") -else: - # Excerpt from :ref:`windmill.authoring.unit` - class UnitTestReporter(functest.reports.FunctestReportInterface): - def summary(self, test_list, totals_dict, stdout_capture): - self.test_list = test_list - - unittestreporter = UnitTestReporter() - functest.reports.register_reporter(unittestreporter) - - class CubicWebWindmillUseCase(CubicWebServerTC): - """basic class for Windmill use case tests - - If you want to change cubicweb test server parameters, define a new - :class:`CubicWebServerConfig` and override the :var:`configcls` - attribute: - - configcls = CubicWebServerConfig - - From Windmill configuration: - - .. attribute:: browser - identification string (firefox|ie|safari|chrome) (firefox by default) - .. attribute :: edit_test - load and edit test for debugging (False by default) - .. attribute:: test_dir (optional) - testing file path or directory (windmill directory under your unit case - file by default) - - Examples: - - browser = 'firefox' - test_dir = osp.join(__file__, 'windmill') - edit_test = False - - If you prefer, you can put here the use cases recorded by windmill GUI - (services transformer) instead of the windmill sub-directory - You can change `test_dir` as following: - - test_dir = __file__ - - Instead of toggle `edit_test` value, try `python -f` - """ - browser = 'firefox' - - edit_test = "-i" in sys.argv # detection for pytest invocation - # Windmill use case are written with no anonymous user - anonymous_allowed = False - - tags = CubicWebServerTC.tags & Tags(('windmill',)) - - def _test_dir(self): - """access to class attribute if possible or make assumption - of expected directory""" - try: - return getattr(self, 'test_dir') - except AttributeError: - if os.path.basename(sys.argv[0]) == "pytest": - test_dir = os.getcwd() - else: - import inspect - test_dir = os.path.dirname(inspect.stack()[-1][1]) - return osp.join(test_dir, 'windmill') - - def setUp(self): - # Start CubicWeb session before running the server to populate self.vreg - CubicWebServerTC.setUp(self) - # XXX reduce log output (should be done in a cleaner way) - # windmill fu** up our logging configuration - for logkey in ('windmill', 'logilab', 'cubicweb'): - getLogger(logkey).setLevel(ERROR) - self.test_dir = self._test_dir() - msg = "provide a valid 'test_dir' as the given test file/dir (current: %s)" - assert os.path.exists(self.test_dir), (msg % self.test_dir) - # windmill setup - windmill.stdout, windmill.stdin = sys.stdout, sys.stdin - configure_global_settings() - windmill.settings['TEST_URL'] = self.config['base-url'] - if hasattr(self,"windmill_settings"): - for (setting,value) in self.windmill_settings.iteritems(): - windmill.settings[setting] = value - self.windmill_shell_objects = setup() - - def tearDown(self): - teardown(self.windmill_shell_objects) - CubicWebServerTC.tearDown(self) - - def testWindmill(self): - if self.edit_test: - # see windmill.bin.admin_options.Firebug - windmill.settings['INSTALL_FIREBUG'] = 'firebug' - windmill.settings.setdefault('MOZILLA_PLUGINS', []).extend( - ['/usr/share/mozilla-extensions/', - '/usr/share/xul-ext/']) - controller = self.windmill_shell_objects['start_' + self.browser]() - self.windmill_shell_objects['do_test'](self.test_dir, - load=self.edit_test, - threaded=False) - # set a breakpoint to be able to debug windmill test - if self.edit_test: - import pdb; pdb.set_trace() - return - - # reporter - for test in unittestreporter.test_list: - msg = "" - self._testMethodDoc = getattr(test, "__doc__", None) - self._testMethodName = test.__name__ - # try to display a better message in case of failure - if hasattr(test, "tb"): - msg = '\n'.join(test.tb) - self.assertEqual(test.result, True, msg=msg) - diff -r 738f97bc3e19 -r be91151107f6 devtools/data/xvfb-run.sh --- a/devtools/data/xvfb-run.sh Wed Apr 10 16:46:18 2013 +0200 +++ b/devtools/data/xvfb-run.sh Mon Apr 15 13:18:01 2013 +0200 @@ -86,6 +86,7 @@ error "problem while cleaning up temporary directory" exit 5 fi + XVFB_RUN_TMPDIR= fi if [ -n "$XVFBPID" ]; then kill "$XVFBPID" diff -r 738f97bc3e19 -r be91151107f6 devtools/qunit.py --- a/devtools/qunit.py Wed Apr 10 16:46:18 2013 +0200 +++ b/devtools/qunit.py Mon Apr 15 13:18:01 2013 +0200 @@ -70,7 +70,8 @@ stderr = TemporaryFile() self.firefox_cmd = ['firefox', '-no-remote'] if os.name == 'posix': - self.firefox_cmd = [osp.join(osp.dirname(__file__), 'data', 'xvfb-run.sh'), '-a'] + self.firefox_cmd + self.firefox_cmd = [osp.join(osp.dirname(__file__), 'data', 'xvfb-run.sh'), + '-a', '-s', '-noreset -screen 0 640x480x8'] + self.firefox_cmd try: home = osp.expanduser('~') user = getlogin() diff -r 738f97bc3e19 -r be91151107f6 predicates.py --- a/predicates.py Wed Apr 10 16:46:18 2013 +0200 +++ b/predicates.py Mon Apr 15 13:18:01 2013 +0200 @@ -190,7 +190,7 @@ from logilab.common.compat import all, any from logilab.common.interface import implements as implements_iface -from logilab.common.registry import Predicate, objectify_predicate +from logilab.common.registry import Predicate, objectify_predicate, yes from yams.schema import BASE_TYPES, role_name from rql.nodes import Function @@ -201,6 +201,9 @@ from cubicweb.uilib import eid_param from cubicweb.schema import split_expression +# remember, these imports are there for bw compat only +__BACKWARD_COMPAT_IMPORTS = (yes,) + def score_interface(etypesreg, eclass, iface): """Return XXX if the give object (maybe an instance or class) implements the interface. diff -r 738f97bc3e19 -r be91151107f6 server/repository.py --- a/server/repository.py Wed Apr 10 16:46:18 2013 +0200 +++ b/server/repository.py Mon Apr 15 13:18:01 2013 +0200 @@ -898,8 +898,12 @@ self.threaded_task(task) else: self.info('calling service %s synchronously', regid) - service = session.vreg['services'].select(regid, session, **kwargs) - return service.call(**kwargs) + session.set_cnxset() + try: + service = session.vreg['services'].select(regid, session, **kwargs) + return service.call(**kwargs) + finally: + session.free_cnxset() def user_info(self, sessionid, props=None): """this method should be used by client to: diff -r 738f97bc3e19 -r be91151107f6 server/test/unittest_repository.py --- a/server/test/unittest_repository.py Wed Apr 10 16:46:18 2013 +0200 +++ b/server/test/unittest_repository.py Mon Apr 15 13:18:01 2013 +0200 @@ -42,9 +42,6 @@ from cubicweb.server.hook import Hook from cubicweb.server.sources import native -# start name server anyway, process will fail if already running -os.system('pyro-ns >/dev/null 2>/dev/null &') - class RepositoryTC(CubicWebTC): """ singleton providing access to a persistent storage for entities @@ -350,10 +347,12 @@ import Pyro Pyro.config.PYRO_MULTITHREADED = 0 done = [] - # the client part has to be in the thread due to sqlite limitations - t = threading.Thread(target=self._pyro_client, args=(done,)) + self.repo.config.global_set_option('pyro-ns-host', 'NO_PYRONS') + daemon = self.repo.pyro_register() try: - daemon = self.repo.pyro_register() + uri = self.repo.pyro_uri.replace('PYRO', 'pyroloc') + # the client part has to be in the thread due to sqlite limitations + t = threading.Thread(target=self._pyro_client, args=(uri, done)) t.start() while not done: daemon.handleRequests(1.0) @@ -366,8 +365,8 @@ pyro_ext._DAEMONS.clear() - def _pyro_client(self, done): - cnx = connect('pyro:///'+self.repo.config.appid, + def _pyro_client(self, uri, done): + cnx = connect(uri, u'admin', password='gingkow', initlog=False) # don't reset logging configuration try: diff -r 738f97bc3e19 -r be91151107f6 server/utils.py --- a/server/utils.py Wed Apr 10 16:46:18 2013 +0200 +++ b/server/utils.py Mon Apr 15 13:18:01 2013 +0200 @@ -219,9 +219,6 @@ def add_looping_task(self, interval, func, *args): """register a function to be called every `interval` seconds. - - looping tasks can only be registered during repository initialization, - once done this method will fail. """ task = LoopTask(self, interval, func, args) if self.running: diff -r 738f97bc3e19 -r be91151107f6 testfunc/test/jstests/ajax_url0.html --- a/testfunc/test/jstests/ajax_url0.html Wed Apr 10 16:46:18 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -
-

Hello

-
diff -r 738f97bc3e19 -r be91151107f6 testfunc/test/jstests/ajax_url1.html --- a/testfunc/test/jstests/ajax_url1.html Wed Apr 10 16:46:18 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -
-
- -
-

Hello

-
diff -r 738f97bc3e19 -r be91151107f6 testfunc/test/jstests/ajax_url2.html --- a/testfunc/test/jstests/ajax_url2.html Wed Apr 10 16:46:18 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -
-
- - -
-

Hello

-
diff -r 738f97bc3e19 -r be91151107f6 testfunc/test/jstests/ajaxresult.json --- a/testfunc/test/jstests/ajaxresult.json Wed Apr 10 16:46:18 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -['foo', 'bar'] diff -r 738f97bc3e19 -r be91151107f6 testfunc/test/jstests/test_ajax.html --- a/testfunc/test/jstests/test_ajax.html Wed Apr 10 16:46:18 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - -
-

cubicweb.ajax.js functions tests

-

-
    - - diff -r 738f97bc3e19 -r be91151107f6 testfunc/test/jstests/test_ajax.js --- a/testfunc/test/jstests/test_ajax.js Wed Apr 10 16:46:18 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,244 +0,0 @@ -$(document).ready(function() { - - module("ajax", { - setup: function() { - this.scriptsLength = $('head script[src]').length-1; - this.cssLength = $('head link[rel=stylesheet]').length-1; - // re-initialize cw loaded cache so that each tests run in a - // clean environment, have a lookt at _loadAjaxHtmlHead implementation - // in cubicweb.ajax.js for more information. - cw.loaded_src = []; - cw.loaded_href = []; - }, - teardown: function() { - $('head script[src]:gt(' + this.scriptsLength + ')').remove(); - $('head link[rel=stylesheet]:gt(' + this.cssLength + ')').remove(); - } - }); - - function jsSources() { - return $.map($('head script[src]'), function(script) { - return script.getAttribute('src'); - }); - } - - test('test simple h1 inclusion (ajax_url0.html)', function() { - expect(3); - equals(jQuery('#main').children().length, 0); - stop(); - jQuery('#main').loadxhtml('/../ajax_url0.html', { - callback: function() { - equals(jQuery('#main').children().length, 1); - equals(jQuery('#main h1').html(), 'Hello'); - start(); - } - }); - }); - - test('test simple html head inclusion (ajax_url1.html)', function() { - expect(6); - var scriptsIncluded = jsSources(); - equals(jQuery.inArray('http://foo.js', scriptsIncluded), - 1); - stop(); - jQuery('#main').loadxhtml('/../ajax_url1.html', { - callback: function() { - var origLength = scriptsIncluded.length; - scriptsIncluded = jsSources(); - // check that foo.js has been *appended* to - equals(scriptsIncluded.length, origLength + 1); - equals(scriptsIncluded[origLength].indexOf('http://foo.js'), 0); - // check that
    has been removed - equals(jQuery('#main').children().length, 1); - equals(jQuery('div.ajaxHtmlHead').length, 0); - equals(jQuery('#main h1').html(), 'Hello'); - start(); - } - }); - }); - - test('test addCallback', function() { - expect(3); - equals(jQuery('#main').children().length, 0); - stop(); - var d = jQuery('#main').loadxhtml('/../ajax_url0.html'); - d.addCallback(function() { - equals(jQuery('#main').children().length, 1); - equals(jQuery('#main h1').html(), 'Hello'); - start(); - }); - }); - - test('test callback after synchronous request', function() { - expect(1); - var deferred = new Deferred(); - var result = jQuery.ajax({ - url: './ajax_url0.html', - async: false, - beforeSend: function(xhr) { - deferred._req = xhr; - }, - success: function(data, status) { - deferred.success(data); - } - }); - stop(); - deferred.addCallback(function() { - // add an assertion to ensure the callback is executed - ok(true, "callback is executed"); - start(); - }); - }); - - test('test addCallback with parameters', function() { - expect(3); - equals(jQuery('#main').children().length, 0); - stop(); - var d = jQuery('#main').loadxhtml('/../ajax_url0.html'); - d.addCallback(function(data, req, arg1, arg2) { - equals(arg1, 'Hello'); - equals(arg2, 'world'); - start(); - }, - 'Hello', 'world'); - }); - - test('test callback after synchronous request with parameters', function() { - var deferred = new Deferred(); - var result = jQuery.ajax({ - url: '/../ajax_url0.html', - async: false, - beforeSend: function(xhr) { - deferred._req = xhr; - }, - success: function(data, status) { - deferred.success(data); - } - }); - deferred.addCallback(function(data, req, arg1, arg2) { - // add an assertion to ensure the callback is executed - ok(true, "callback is executed"); - equals(arg1, 'Hello'); - equals(arg2, 'world'); - }, - 'Hello', 'world'); - }); - - test('test addErrback', function() { - expect(1); - stop(); - var d = jQuery('#main').loadxhtml('/../ajax_url0.html'); - d.addCallback(function() { - // throw an exception to start errback chain - throw new Error(); - }); - d.addErrback(function() { - ok(true, "errback is executed"); - start(); - }); - }); - - test('test callback / errback execution order', function() { - expect(4); - var counter = 0; - stop(); - var d = jQuery('#main').loadxhtml('/../ajax_url0.html', { - callback: function() { - equals(++counter, 1); // should be executed first - start(); - } - }); - d.addCallback(function() { - equals(++counter, 2); // should be executed and break callback chain - throw new Error(); - }); - d.addCallback(function() { - // should not be executed since second callback raised an error - ok(false, "callback is executed"); - }); - d.addErrback(function() { - // should be executed after the second callback - equals(++counter, 3); - }); - d.addErrback(function() { - // should be executed after the first errback - equals(++counter, 4); - }); - }); - - test('test already included resources are ignored (ajax_url1.html)', function() { - expect(10); - var scriptsIncluded = jsSources(); - // NOTE: - equals(jQuery.inArray('http://foo.js', scriptsIncluded), -1); - equals(jQuery('head link').length, 1); - /* use endswith because in pytest context we have an absolute path */ - ok(jQuery('head link').attr('href').endswith('/qunit.css')); - stop(); - jQuery('#main').loadxhtml('/../ajax_url1.html', { - callback: function() { - var origLength = scriptsIncluded.length; - scriptsIncluded = jsSources(); - try { - // check that foo.js has been inserted in - equals(scriptsIncluded.length, origLength + 1); - equals(scriptsIncluded[origLength].indexOf('http://foo.js'), 0); - // check that
    has been removed - equals(jQuery('#main').children().length, 1); - equals(jQuery('div.ajaxHtmlHead').length, 0); - equals(jQuery('#main h1').html(), 'Hello'); - // qunit.css is not added twice - equals(jQuery('head link').length, 1); - /* use endswith because in pytest context we have an absolute path */ - ok(jQuery('head link').attr('href').endswith('/qunit.css')); - } finally { - start(); - } - } - }); - }); - - test('test synchronous request loadRemote', function() { - var res = loadRemote('/../ajaxresult.json', {}, - 'GET', true); - same(res, ['foo', 'bar']); - }); - - test('test event on CubicWeb', function() { - expect(1); - stop(); - var events = null; - jQuery(CubicWeb).bind('server-response', function() { - // check that server-response event on CubicWeb is triggered - events = 'CubicWeb'; - }); - jQuery('#main').loadxhtml('/../ajax_url0.html', { - callback: function() { - equals(events, 'CubicWeb'); - start(); - } - }); - }); - - test('test event on node', function() { - expect(3); - stop(); - var nodes = []; - jQuery('#main').bind('server-response', function() { - nodes.push('node'); - }); - jQuery(CubicWeb).bind('server-response', function() { - nodes.push('CubicWeb'); - }); - jQuery('#main').loadxhtml('/../ajax_url0.html', { - callback: function() { - equals(nodes.length, 2); - // check that server-response event on CubicWeb is triggered - // only once and event server-response on node is triggered - equals(nodes[0], 'CubicWeb'); - equals(nodes[1], 'node'); - start(); - } - }); - }); -}); - diff -r 738f97bc3e19 -r be91151107f6 testfunc/test/jstests/test_htmlhelpers.html --- a/testfunc/test/jstests/test_htmlhelpers.html Wed Apr 10 16:46:18 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ - - - - - - - - - - - - - -
    -
    -

    cubicweb.htmlhelpers.js functions tests

    -

    -

    -
      - - diff -r 738f97bc3e19 -r be91151107f6 testfunc/test/jstests/test_htmlhelpers.js --- a/testfunc/test/jstests/test_htmlhelpers.js Wed Apr 10 16:46:18 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -$(document).ready(function() { - - module("module2", { - setup: function() { - $('#main').append(''); - } - }); - - test("test first selected", function() { - $('#theselect').append('' + - '' + - '' + - ''); - var selected = firstSelected(document.getElementById("theselect")); - equals(selected.value, 'bar'); - }); - - test("test first selected 2", function() { - $('#theselect').append('' + - '' + - '' + - ''); - var selected = firstSelected(document.getElementById("theselect")); - equals(selected, null); - }); - - module("visibilty"); - test('toggleVisibility', function() { - $('#main').append('
      '); - toggleVisibility('foo'); - ok($('#foo').hasClass('hidden'), 'check hidden class is set'); - }); - -}); - diff -r 738f97bc3e19 -r be91151107f6 testfunc/test/jstests/test_utils.html --- a/testfunc/test/jstests/test_utils.html Wed Apr 10 16:46:18 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - -
      -
      -

      cw.utils functions tests

      -

      -

      -
        - - diff -r 738f97bc3e19 -r be91151107f6 testfunc/test/jstests/test_utils.js --- a/testfunc/test/jstests/test_utils.js Wed Apr 10 16:46:18 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -$(document).ready(function() { - - module("datetime"); - - test("test full datetime", function() { - equals(cw.utils.toISOTimestamp(new Date(1986, 3, 18, 10, 30, 0, 0)), - '1986-04-18 10:30:00'); - }); - - test("test only date", function() { - equals(cw.utils.toISOTimestamp(new Date(1986, 3, 18)), '1986-04-18 00:00:00'); - }); - - test("test null", function() { - equals(cw.utils.toISOTimestamp(null), null); - }); - - module("parsing"); - test("test basic number parsing", function() { - var d = strptime('2008/08/08', '%Y/%m/%d'); - same(datetuple(d), [2008, 8, 8, 0, 0]); - d = strptime('2008/8/8', '%Y/%m/%d'); - same(datetuple(d), [2008, 8, 8, 0, 0]); - d = strptime('8/8/8', '%Y/%m/%d'); - same(datetuple(d), [8, 8, 8, 0, 0]); - d = strptime('0/8/8', '%Y/%m/%d'); - same(datetuple(d), [0, 8, 8, 0, 0]); - d = strptime('-10/8/8', '%Y/%m/%d'); - same(datetuple(d), [-10, 8, 8, 0, 0]); - d = strptime('-35000', '%Y'); - same(datetuple(d), [-35000, 1, 1, 0, 0]); - }); - - test("test custom format parsing", function() { - var d = strptime('2008-08-08', '%Y-%m-%d'); - same(datetuple(d), [2008, 8, 8, 0, 0]); - d = strptime('2008 - ! 08: 08', '%Y - ! %m: %d'); - same(datetuple(d), [2008, 8, 8, 0, 0]); - d = strptime('2008-08-08 12:14', '%Y-%m-%d %H:%M'); - same(datetuple(d), [2008, 8, 8, 12, 14]); - d = strptime('2008-08-08 1:14', '%Y-%m-%d %H:%M'); - same(datetuple(d), [2008, 8, 8, 1, 14]); - d = strptime('2008-08-08 01:14', '%Y-%m-%d %H:%M'); - same(datetuple(d), [2008, 8, 8, 1, 14]); - }); - - module("sliceList"); - test("test slicelist", function() { - var list = ['a', 'b', 'c', 'd', 'e', 'f']; - same(sliceList(list, 2), ['c', 'd', 'e', 'f']); - same(sliceList(list, 2, -2), ['c', 'd']); - same(sliceList(list, -3), ['d', 'e', 'f']); - same(sliceList(list, 0, -2), ['a', 'b', 'c', 'd']); - same(sliceList(list), list); - }); - - module("formContents", { - setup: function() { - $('#main').append('
        '); - } - }); - // XXX test fckeditor - test("test formContents", function() { - $('#test-form').append(''); - $('#test-form').append(' '); - $('#test-form').append(''); - $('#test-form').append(''); - $('#test-form').append(''); - $('#test-form').append(''); - $('#test-form').append(''); - $('#theselect').append('' + - ''); - //Append an unchecked radio input : should not be in formContents list - $('#test-form').append(''); - $('#test-form').append(''); - same(formContents($('#test-form')[0]), [ - ['input-text', 'mytextarea', 'choice', 'check', 'theselect'], - ['toto', 'Hello World!', 'no', 'no', 'foo'] - ]); - }); -}); - diff -r 738f97bc3e19 -r be91151107f6 testfunc/test/jstests/utils.js --- a/testfunc/test/jstests/utils.js Wed Apr 10 16:46:18 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -function datetuple(d) { - return [d.getFullYear(), d.getMonth()+1, d.getDate(), - d.getHours(), d.getMinutes()]; -} - -function pprint(obj) { - print('{'); - for(k in obj) { - print(' ' + k + ' = ' + obj[k]); - } - print('}'); -} - -function arrayrepr(array) { - return '[' + array.join(', ') + ']'; -} - -function assertArrayEquals(array1, array2) { - if (array1.length != array2.length) { - throw new crosscheck.AssertionFailure(array1.join(', ') + ' != ' + array2.join(', ')); - } - for (var i=0; i +

        Hello

        +
    diff -r 738f97bc3e19 -r be91151107f6 web/test/jstests/ajax_url1.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/jstests/ajax_url1.html Mon Apr 15 13:18:01 2013 +0200 @@ -0,0 +1,6 @@ +
    +
    + +
    +

    Hello

    +
    diff -r 738f97bc3e19 -r be91151107f6 web/test/jstests/ajax_url2.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/jstests/ajax_url2.html Mon Apr 15 13:18:01 2013 +0200 @@ -0,0 +1,7 @@ +
    +
    + + +
    +

    Hello

    +
    diff -r 738f97bc3e19 -r be91151107f6 web/test/jstests/ajaxresult.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/jstests/ajaxresult.json Mon Apr 15 13:18:01 2013 +0200 @@ -0,0 +1,1 @@ +['foo', 'bar'] diff -r 738f97bc3e19 -r be91151107f6 web/test/jstests/test_ajax.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/jstests/test_ajax.html Mon Apr 15 13:18:01 2013 +0200 @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + +
    +

    cubicweb.ajax.js functions tests

    +

    +
      + + diff -r 738f97bc3e19 -r be91151107f6 web/test/jstests/test_ajax.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/jstests/test_ajax.js Mon Apr 15 13:18:01 2013 +0200 @@ -0,0 +1,289 @@ +$(document).ready(function() { + + module("ajax", { + setup: function() { + this.scriptsLength = $('head script[src]').length-1; + this.cssLength = $('head link[rel=stylesheet]').length-1; + // re-initialize cw loaded cache so that each tests run in a + // clean environment, have a lookt at _loadAjaxHtmlHead implementation + // in cubicweb.ajax.js for more information. + cw.loaded_src = []; + cw.loaded_href = []; + }, + teardown: function() { + $('head script[src]:gt(' + this.scriptsLength + ')').remove(); + $('head link[rel=stylesheet]:gt(' + this.cssLength + ')').remove(); + } + }); + + function jsSources() { + return $.map($('head script[src]'), function(script) { + return script.getAttribute('src'); + }); + } + + test('test simple h1 inclusion (ajax_url0.html)', function() { + expect(3); + equals(jQuery('#main').children().length, 0); + stop(); + jQuery('#main').loadxhtml('/../ajax_url0.html', { + callback: function() { + try { + equals(jQuery('#main').children().length, 1); + equals(jQuery('#main h1').html(), 'Hello'); + } finally { + start(); + }; + } + }); + }); + + test('test simple html head inclusion (ajax_url1.html)', function() { + expect(6); + var scriptsIncluded = jsSources(); + equals(jQuery.inArray('http://foo.js', scriptsIncluded), - 1); + stop(); + jQuery('#main').loadxhtml('/../ajax_url1.html', { + callback: function() { + try { + var origLength = scriptsIncluded.length; + scriptsIncluded = jsSources(); + // check that foo.js has been *appended* to + equals(scriptsIncluded.length, origLength + 1); + equals(scriptsIncluded[origLength].indexOf('http://foo.js'), 0); + // check that
      has been removed + equals(jQuery('#main').children().length, 1); + equals(jQuery('div.ajaxHtmlHead').length, 0); + equals(jQuery('#main h1').html(), 'Hello'); + } finally { + start(); + }; + } + }); + }); + + test('test addCallback', function() { + expect(3); + equals(jQuery('#main').children().length, 0); + stop(); + var d = jQuery('#main').loadxhtml('/../ajax_url0.html'); + d.addCallback(function() { + try { + equals(jQuery('#main').children().length, 1); + equals(jQuery('#main h1').html(), 'Hello'); + } finally { + start(); + }; + }); + }); + + test('test callback after synchronous request', function() { + expect(1); + var deferred = new Deferred(); + var result = jQuery.ajax({ + url: './ajax_url0.html', + async: false, + beforeSend: function(xhr) { + deferred._req = xhr; + }, + success: function(data, status) { + deferred.success(data); + } + }); + stop(); + deferred.addCallback(function() { + try { + // add an assertion to ensure the callback is executed + ok(true, "callback is executed"); + } finally { + start(); + }; + }); + }); + + test('test addCallback with parameters', function() { + expect(3); + equals(jQuery('#main').children().length, 0); + stop(); + var d = jQuery('#main').loadxhtml('/../ajax_url0.html'); + d.addCallback(function(data, req, arg1, arg2) { + try { + equals(arg1, 'Hello'); + equals(arg2, 'world'); + } finally { + start(); + }; + }, + 'Hello', 'world'); + }); + + test('test callback after synchronous request with parameters', function() { + expect(2); + var deferred = new Deferred(); + deferred.addCallback(function(data, req, arg1, arg2) { + // add an assertion to ensure the callback is executed + try { + ok(true, "callback is executed"); + equals(arg1, 'Hello'); + equals(arg2, 'world'); + } finally { + start(); + }; + }, + 'Hello', 'world'); + deferred.addErrback(function() { + // throw an exception to start errback chain + try { + throw this._error; + } finally { + start(); + }; + }); + stop(); + var result = jQuery.ajax({ + url: '/../ajax_url0.html', + async: false, + beforeSend: function(xhr) { + deferred._req = xhr; + }, + success: function(data, status) { + deferred.success(data); + } + }); + }); + + test('test addErrback', function() { + expect(1); + stop(); + var d = jQuery('#main').loadxhtml('/../ajax_url0.html'); + d.addCallback(function() { + // throw an exception to start errback chain + try { + throw new Error(); + } finally { + start(); + }; + }); + d.addErrback(function() { + try { + ok(true, "errback is executed"); + } finally { + start(); + }; + }); + }); + + test('test callback / errback execution order', function() { + expect(4); + var counter = 0; + stop(); + var d = jQuery('#main').loadxhtml('/../ajax_url0.html', { + callback: function() { + try { + equals(++counter, 1); // should be executed first + } finally { + start(); + }; + } + }); + d.addCallback(function() { + equals(++counter, 2); // should be executed and break callback chain + throw new Error(); + }); + d.addCallback(function() { + // should not be executed since second callback raised an error + ok(false, "callback is executed"); + }); + d.addErrback(function() { + // should be executed after the second callback + equals(++counter, 3); + }); + d.addErrback(function() { + // should be executed after the first errback + equals(++counter, 4); + }); + }); + + test('test already included resources are ignored (ajax_url1.html)', function() { + expect(10); + var scriptsIncluded = jsSources(); + // NOTE: + equals(jQuery.inArray('http://foo.js', scriptsIncluded), -1); + equals(jQuery('head link').length, 1); + /* use endswith because in pytest context we have an absolute path */ + ok(jQuery('head link').attr('href').endswith('/qunit.css')); + stop(); + jQuery('#main').loadxhtml('/../ajax_url1.html', { + callback: function() { + var origLength = scriptsIncluded.length; + scriptsIncluded = jsSources(); + try { + // check that foo.js has been inserted in + equals(scriptsIncluded.length, origLength + 1); + equals(scriptsIncluded[origLength].indexOf('http://foo.js'), 0); + // check that
      has been removed + equals(jQuery('#main').children().length, 1); + equals(jQuery('div.ajaxHtmlHead').length, 0); + equals(jQuery('#main h1').html(), 'Hello'); + // qunit.css is not added twice + equals(jQuery('head link').length, 1); + /* use endswith because in pytest context we have an absolute path */ + ok(jQuery('head link').attr('href').endswith('/qunit.css')); + } finally { + start(); + } + } + }); + }); + + test('test synchronous request loadRemote', function() { + var res = loadRemote('/../ajaxresult.json', {}, + 'GET', true); + same(res, ['foo', 'bar']); + }); + + test('test event on CubicWeb', function() { + expect(1); + stop(); + var events = null; + jQuery(CubicWeb).bind('server-response', function() { + // check that server-response event on CubicWeb is triggered + events = 'CubicWeb'; + }); + jQuery('#main').loadxhtml('/../ajax_url0.html', { + callback: function() { + try { + equals(events, 'CubicWeb'); + } finally { + start(); + }; + } + }); + }); + + test('test event on node', function() { + expect(3); + stop(); + var nodes = []; + jQuery('#main').bind('server-response', function() { + nodes.push('node'); + }); + jQuery(CubicWeb).bind('server-response', function() { + nodes.push('CubicWeb'); + }); + jQuery('#main').loadxhtml('/../ajax_url0.html', { + callback: function() { + try { + equals(nodes.length, 2); + // check that server-response event on CubicWeb is triggered + // only once and event server-response on node is triggered + equals(nodes[0], 'CubicWeb'); + equals(nodes[1], 'node'); + } finally { + start(); + }; + } + }); + }); +}); + diff -r 738f97bc3e19 -r be91151107f6 web/test/jstests/test_htmlhelpers.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/jstests/test_htmlhelpers.html Mon Apr 15 13:18:01 2013 +0200 @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + +
      +

      cubicweb.htmlhelpers.js functions tests

      +

      +
        + + diff -r 738f97bc3e19 -r be91151107f6 web/test/jstests/test_htmlhelpers.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/jstests/test_htmlhelpers.js Mon Apr 15 13:18:01 2013 +0200 @@ -0,0 +1,36 @@ +$(document).ready(function() { + + module("module2", { + setup: function() { + $('#main').append(''); + } + }); + + test("test first selected", function() { + $('#theselect').append('' + + '' + + '' + + ''); + var selected = firstSelected(document.getElementById("theselect")); + equals(selected.value, 'bar'); + }); + + test("test first selected 2", function() { + $('#theselect').append('' + + '' + + '' + + ''); + var selected = firstSelected(document.getElementById("theselect")); + equals(selected, null); + }); + + module("visibilty"); + test('toggleVisibility', function() { + $('#main').append('
        '); + toggleVisibility('foo'); + ok($('#foo').hasClass('hidden'), 'check hidden class is set'); + }); + +}); + diff -r 738f97bc3e19 -r be91151107f6 web/test/jstests/test_utils.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/jstests/test_utils.html Mon Apr 15 13:18:01 2013 +0200 @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + +
        +

        cw.utils functions tests

        +

        +
          + + diff -r 738f97bc3e19 -r be91151107f6 web/test/jstests/test_utils.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/jstests/test_utils.js Mon Apr 15 13:18:01 2013 +0200 @@ -0,0 +1,92 @@ +$(document).ready(function() { + + module("datetime"); + + test("test full datetime", function() { + equals(cw.utils.toISOTimestamp(new Date(1986, 3, 18, 10, 30, 0, 0)), + '1986-04-18 10:30:00'); + }); + + test("test only date", function() { + equals(cw.utils.toISOTimestamp(new Date(1986, 3, 18)), '1986-04-18 00:00:00'); + }); + + test("test null", function() { + equals(cw.utils.toISOTimestamp(null), null); + }); + + module("parsing"); + test("test basic number parsing", function() { + var d = strptime('2008/08/08', '%Y/%m/%d'); + same(datetuple(d), [2008, 8, 8, 0, 0]); + d = strptime('2008/8/8', '%Y/%m/%d'); + same(datetuple(d), [2008, 8, 8, 0, 0]); + d = strptime('8/8/8', '%Y/%m/%d'); + same(datetuple(d), [8, 8, 8, 0, 0]); + d = strptime('0/8/8', '%Y/%m/%d'); + same(datetuple(d), [0, 8, 8, 0, 0]); + d = strptime('-10/8/8', '%Y/%m/%d'); + same(datetuple(d), [-10, 8, 8, 0, 0]); + d = strptime('-35000', '%Y'); + same(datetuple(d), [-35000, 1, 1, 0, 0]); + }); + + test("test custom format parsing", function() { + var d = strptime('2008-08-08', '%Y-%m-%d'); + same(datetuple(d), [2008, 8, 8, 0, 0]); + d = strptime('2008 - ! 08: 08', '%Y - ! %m: %d'); + same(datetuple(d), [2008, 8, 8, 0, 0]); + d = strptime('2008-08-08 12:14', '%Y-%m-%d %H:%M'); + same(datetuple(d), [2008, 8, 8, 12, 14]); + d = strptime('2008-08-08 1:14', '%Y-%m-%d %H:%M'); + same(datetuple(d), [2008, 8, 8, 1, 14]); + d = strptime('2008-08-08 01:14', '%Y-%m-%d %H:%M'); + same(datetuple(d), [2008, 8, 8, 1, 14]); + }); + + module("sliceList"); + test("test slicelist", function() { + var list = ['a', 'b', 'c', 'd', 'e', 'f']; + same(sliceList(list, 2), ['c', 'd', 'e', 'f']); + same(sliceList(list, 2, -2), ['c', 'd']); + same(sliceList(list, -3), ['d', 'e', 'f']); + same(sliceList(list, 0, -2), ['a', 'b', 'c', 'd']); + same(sliceList(list), list); + }); + + module("formContents", { + setup: function() { + $('#main').append('
          '); + } + }); + // XXX test fckeditor + test("test formContents", function() { + $('#test-form').append(''); + $('#test-form').append(' '); + $('#test-form').append(''); + $('#test-form').append(''); + $('#test-form').append(''); + $('#test-form').append(''); + $('#test-form').append(''); + $('#theselect').append('' + + ''); + //Append an unchecked radio input : should not be in formContents list + $('#test-form').append(''); + $('#test-form').append(''); + same(formContents($('#test-form')[0]), [ + ['input-text', 'mytextarea', 'choice', 'check', 'theselect'], + ['toto', 'Hello World!', 'no', 'no', 'foo'] + ]); + }); +}); + diff -r 738f97bc3e19 -r be91151107f6 web/test/jstests/utils.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/jstests/utils.js Mon Apr 15 13:18:01 2013 +0200 @@ -0,0 +1,29 @@ +function datetuple(d) { + return [d.getFullYear(), d.getMonth()+1, d.getDate(), + d.getHours(), d.getMinutes()]; +} + +function pprint(obj) { + print('{'); + for(k in obj) { + print(' ' + k + ' = ' + obj[k]); + } + print('}'); +} + +function arrayrepr(array) { + return '[' + array.join(', ') + ']'; +} + +function assertArrayEquals(array1, array2) { + if (array1.length != array2.length) { + throw new crosscheck.AssertionFailure(array1.join(', ') + ' != ' + array2.join(', ')); + } + for (var i=0; i') + box = MenuWidget('', '', _class='tableActionsBox', islist=False) + label = tags.span(self._cw._('action menu')) + menu = PopupBoxMenu(label, isitem=False, link_class='actionsBox', + ident='%sActions' % self.view.domid) + box.append(menu) for action in actions: - w(u'') - action.render(w) - w(u'') - w(u'
      ') + menu.append(action) + box.render(w=w) + w(u'
      ') def show_hide_filter_actions(self, currentlydisplayed=False): divid = self.view.domid showhide = u';'.join(toggle_action('%s%s' % (divid, what))[11:] - for what in ('Form', 'Actions')) + for what in ('Form', 'Show', 'Hide', 'Actions')) showhide = 'javascript:' + showhide self._cw.add_onload(u'''\ $(document).ready(function() { @@ -310,8 +313,10 @@ $('#%(id)sShow').attr('class', 'hidden'); } });''' % {'id': divid}) - showlabel = self._cw._('toggle filter') - return [component.Link(showhide, showlabel, id='%sToggle' % divid)] + showlabel = self._cw._('show filter form') + hidelabel = self._cw._('hide filter form') + return [component.Link(showhide, showlabel, id='%sShow' % divid), + component.Link(showhide, hidelabel, id='%sHide' % divid)] class AbstractColumnRenderer(object): diff -r 738f97bc3e19 -r be91151107f6 web/webconfig.py --- a/web/webconfig.py Wed Apr 10 16:46:18 2013 +0200 +++ b/web/webconfig.py Mon Apr 15 13:18:01 2013 +0200 @@ -81,7 +81,6 @@ """ cubicweb_appobject_path = CubicWebConfiguration.cubicweb_appobject_path | set([join('web', 'views')]) cube_appobject_path = CubicWebConfiguration.cube_appobject_path | set(['views']) - uiprops = {'FCKEDITOR_PATH': ''} options = merge_options(CubicWebConfiguration.options + ( ('repository-uri', @@ -244,8 +243,17 @@ }), )) + def __init__(self, *args, **kwargs): + super(WebConfiguration, self).__init__(*args, **kwargs) + self.uiprops = None + self.https_uiprops = None + self.datadir_url = None + self.https_datadir_url = None + def fckeditor_installed(self): - return exists(self.uiprops['FCKEDITOR_PATH']) + if self.uiprops is None: + return False + return exists(self.uiprops.get('FCKEDITOR_PATH', '')) def cwproperty_definitions(self): for key, pdef in super(WebConfiguration, self).cwproperty_definitions():