# HG changeset patch # User Sylvain Thénault # Date 1285769792 -7200 # Node ID 1806148d6ce877d79e6f7330e65ec37af4685bb0 # Parent e3994fcc21c3ca9afe8977e9e87cc5ec7559d998# Parent a15cc5e16178556aa26a7fe6039a317a168ccc24 backport stable diff -r e3994fcc21c3 -r 1806148d6ce8 _exceptions.py --- a/_exceptions.py Thu Sep 23 23:28:58 2010 +0200 +++ b/_exceptions.py Wed Sep 29 16:16:32 2010 +0200 @@ -130,14 +130,20 @@ """ class NoSelectableObject(RegistryException): - """some views with the given vid have been found but no - one is applicable to the result set - """ + """raised when no appobject is selectable for a given context.""" + def __init__(self, args, kwargs, appobjects): + self.args = args + self.kwargs = kwargs + self.appobjects = appobjects + + def __str__(self): + return ('args: %s, kwargs: %s\ncandidates: %s' + % (self.args, self.kwargs.keys(), self.appobjects)) + class UnknownProperty(RegistryException): """property found in database but unknown in registry""" - # query exception ############################################################# class QueryError(CubicWebRuntimeError): diff -r e3994fcc21c3 -r 1806148d6ce8 devtools/cwwindmill.py --- a/devtools/cwwindmill.py Thu Sep 23 23:28:58 2010 +0200 +++ b/devtools/cwwindmill.py Wed Sep 29 16:16:32 2010 +0200 @@ -26,10 +26,9 @@ import os, os.path as osp import sys -import unittest # imported by default to simplify further import statements -from logilab.common.testlib import unittest_main +from logilab.common.testlib import TestCase, unittest_main import windmill from windmill.dep import functest @@ -45,7 +44,7 @@ unittestreporter = UnitTestReporter() functest.reports.register_reporter(unittestreporter) -class WindmillUnitTestCase(unittest.TestCase): +class WindmillUnitTestCase(TestCase): def setUp(self): windmill.stdout, windmill.stdin = sys.stdout, sys.stdin from windmill.bin.admin_lib import configure_global_settings, setup diff -r e3994fcc21c3 -r 1806148d6ce8 devtools/devctl.py --- a/devtools/devctl.py Thu Sep 23 23:28:58 2010 +0200 +++ b/devtools/devctl.py Wed Sep 29 16:16:32 2010 +0200 @@ -26,8 +26,7 @@ # completion). So import locally in command helpers. import sys from datetime import datetime -from os import mkdir, chdir -from os.path import join, exists, abspath, basename, normpath, split, isdir +from os import mkdir, chdir, listdir, path as osp from warnings import warn from logilab.common import STD_BLACKLIST @@ -35,8 +34,8 @@ from cubicweb.__pkginfo__ import version as cubicwebversion from cubicweb import CW_SOFTWARE_ROOT as BASEDIR, BadCommandUsage from cubicweb.cwctl import CWCTL -from cubicweb.toolsutils import (SKEL_EXCLUDE, Command, - copy_skeleton, underline_title) +from cubicweb.toolsutils import (SKEL_EXCLUDE, Command, copy_skeleton, + underline_title) from cubicweb.web.webconfig import WebConfiguration from cubicweb.server.serverconfig import ServerConfiguration @@ -102,7 +101,7 @@ """ from cubicweb.cwvreg import CubicWebVRegistry if cubedir: - cube = split(cubedir)[-1] + cube = osp.split(cubedir)[-1] config = DevConfiguration(cube) depcubes = list(config._cubes) depcubes.remove(cube) @@ -125,7 +124,8 @@ from cubicweb.web import uicfg from cubicweb.schema import META_RTYPES, SYSTEM_RTYPES, CONSTRAINTS no_context_rtypes = META_RTYPES | SYSTEM_RTYPES - w('# schema pot file, generated on %s\n' % datetime.now().strftime('%Y-%m-%d %H:%M:%S')) + w('# schema pot file, generated on %s\n' + % datetime.now().strftime('%Y-%m-%d %H:%M:%S')) w('# \n') w('# singular and plural forms for each entity type\n') w('\n') @@ -177,7 +177,8 @@ add_msg(w, str(tschema), 'inlined:%s.%s.%s' % (etype, rschema, role)) if appearsin_addmenu.etype_get(eschema, rschema, role, tschema): - if libconfig is not None and libappearsin_addmenu.etype_get(eschema, rschema, role, tschema): + if libconfig is not None and libappearsin_addmenu.etype_get( + eschema, rschema, role, tschema): if eschema in libschema and tschema in libschema: continue if role == 'subject': @@ -200,7 +201,8 @@ for rschema in sorted(schema.relations()): rtype = rschema.type if rtype not in libschema: - # bw compat, necessary until all translation of relation are done properly... + # bw compat, necessary until all translation of relation are done + # properly... add_msg(w, rtype) if rschema.description and rschema.description not in done: done.add(rschema.description) @@ -222,7 +224,8 @@ if not objschema in libobjects: add_msg(w, '%s_object' % rtype, objschema.type) if rtype not in libschema: - # bw compat, necessary until all translation of relation are done properly... + # bw compat, necessary until all translation of relation are + # done properly... add_msg(w, '%s_object' % rtype) for objid in _iter_vreg_objids(vreg, vregdone): add_msg(w, '%s_description' % objid) @@ -246,8 +249,6 @@ break -LANGS = ('en', 'fr', 'es') -I18NDIR = join(BASEDIR, 'i18n') DEFAULT_POT_HEAD = r'''msgid "" msgstr "" "Project-Id-Version: cubicweb %s\n" @@ -262,6 +263,11 @@ ''' % 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. @@ -270,11 +276,10 @@ files to add translations of newly added messages. """ name = 'i18ncubicweb' + min_args = max_args = 0 def run(self, args): """run the command with its specific arguments""" - if args: - raise BadCommandUsage('Too many arguments') import shutil import tempfile import yams @@ -283,9 +288,10 @@ from logilab.common.modutils import get_module_files from cubicweb.i18n import extract_from_tal, execute tempdir = tempfile.mkdtemp() - potfiles = [join(I18NDIR, 'static-messages.pot')] + cwi18ndir = WebConfiguration.i18n_lib_dir() print '-> extract schema messages.' - schemapot = join(tempdir, 'schema.pot') + schemapot = osp.join(tempdir, 'schema.pot') + potfiles = [schemapot] potfiles.append(schemapot) # explicit close necessary else the file may not be yet flushed when # we'll using it below @@ -293,36 +299,43 @@ generate_schema_pot(schemapotstream.write, cubedir=None) schemapotstream.close() print '-> extract TAL messages.' - tali18nfile = join(tempdir, 'tali18n.py') - extract_from_tal(find(join(BASEDIR, 'web'), ('.py', '.pt')), tali18nfile) + tali18nfile = osp.join(tempdir, 'tali18n.py') + extract_from_tal(find(osp.join(BASEDIR, 'web'), ('.py', '.pt')), + tali18nfile) print '-> generate .pot files.' - for id, files, lang in [('pycubicweb', get_module_files(BASEDIR) + list(globfind(join(BASEDIR, 'misc', 'migration'), '*.py')), None), - ('schemadescr', globfind(join(BASEDIR, 'schemas'), '*.py'), None), + pyfiles = get_module_files(BASEDIR) + pyfiles += globfind(osp.join(BASEDIR, 'misc', 'migration'), '*.py') + schemafiles = globfind(osp.join(BASEDIR, 'schemas'), '*.py') + jsfiles = globfind(osp.join(BASEDIR, 'web'), 'cub*.js') + for id, files, lang in [('pycubicweb', pyfiles, None), + ('schemadescr', schemafiles, None), ('yams', get_module_files(yams.__path__[0]), None), ('tal', [tali18nfile], None), - ('js', globfind(join(BASEDIR, 'web'), 'cub*.js'), 'java'), + ('js', jsfiles, 'java'), ]: cmd = 'xgettext --no-location --omit-header -k_ -o %s %s' if lang is not None: cmd += ' -L %s' % lang - potfile = join(tempdir, '%s.pot' % id) + potfile = osp.join(tempdir, '%s.pot' % id) execute(cmd % (potfile, ' '.join('"%s"' % f for f in files))) - if exists(potfile): + if osp.exists(potfile): potfiles.append(potfile) else: print '-> WARNING: %s file was not generated' % potfile print '-> merging %i .pot files' % len(potfiles) - cubicwebpot = join(tempdir, 'cubicweb.pot') - execute('msgcat -o %s %s' % (cubicwebpot, ' '.join('"%s"' % f for f in potfiles))) + cubicwebpot = osp.join(tempdir, 'cubicweb.pot') + execute('msgcat -o %s %s' + % (cubicwebpot, ' '.join('"%s"' % f for f in potfiles))) print '-> merging main pot file with existing translations.' - chdir(I18NDIR) + chdir(cwi18ndir) toedit = [] - for lang in LANGS: + for lang in cw_languages(): target = '%s.po' % lang - execute('msgmerge -N --sort-output -o "%snew" "%s" "%s"' % (target, target, cubicwebpot)) + execute('msgmerge -N --sort-output -o "%snew" "%s" "%s"' + % (target, target, cubicwebpot)) ensure_fs_mode(target) shutil.move('%snew' % target, target) - toedit.append(abspath(target)) + toedit.append(osp.abspath(target)) # cleanup rm(tempdir) # instructions pour la suite @@ -346,13 +359,14 @@ else: cubes = [DevConfiguration.cube_dir(cube) for cube in DevConfiguration.available_cubes()] - cubes = [cubepath for cubepath in cubes if exists(join(cubepath, 'i18n'))] + cubes = [cubepath for cubepath in cubes + if osp.exists(osp.join(cubepath, 'i18n'))] update_cubes_catalogs(cubes) def update_cubes_catalogs(cubes): for cubedir in cubes: - if not isdir(cubedir): + if not osp.isdir(cubedir): print '-> ignoring %s that is not a directory.' % cubedir continue try: @@ -376,20 +390,20 @@ from logilab.common.fileutils import ensure_fs_mode from logilab.common.shellutils import find, rm from cubicweb.i18n import extract_from_tal, execute - cube = basename(normpath(cubedir)) + cube = osp.basename(osp.normpath(cubedir)) tempdir = tempfile.mkdtemp() print underline_title('Updating i18n catalogs for cube %s' % cube) chdir(cubedir) - if exists(join('i18n', 'entities.pot')): + if osp.exists(osp.join('i18n', 'entities.pot')): warn('entities.pot is deprecated, rename file to static-messages.pot (%s)' - % join('i18n', 'entities.pot'), DeprecationWarning) - potfiles = [join('i18n', 'entities.pot')] - elif exists(join('i18n', 'static-messages.pot')): - potfiles = [join('i18n', 'static-messages.pot')] + % osp.join('i18n', 'entities.pot'), DeprecationWarning) + potfiles = [osp.join('i18n', 'entities.pot')] + elif osp.exists(osp.join('i18n', 'static-messages.pot')): + potfiles = [osp.join('i18n', 'static-messages.pot')] else: potfiles = [] print '-> extract schema messages' - schemapot = join(tempdir, 'schema.pot') + schemapot = osp.join(tempdir, 'schema.pot') potfiles.append(schemapot) # explicit close necessary else the file may not be yet flushed when # we'll using it below @@ -397,30 +411,32 @@ generate_schema_pot(schemapotstream.write, cubedir) schemapotstream.close() print '-> extract TAL messages' - tali18nfile = join(tempdir, 'tali18n.py') - extract_from_tal(find('.', ('.py', '.pt'), blacklist=STD_BLACKLIST+('test',)), tali18nfile) + tali18nfile = osp.join(tempdir, 'tali18n.py') + ptfiles = find('.', ('.py', '.pt'), blacklist=STD_BLACKLIST+('test',)) + extract_from_tal(ptfiles, tali18nfile) print '-> extract Javascript messages' - jsfiles = [jsfile for jsfile in find('.', '.js') if basename(jsfile).startswith('cub')] + jsfiles = [jsfile for jsfile in find('.', '.js') + if osp.basename(jsfile).startswith('cub')] if jsfiles: - tmppotfile = join(tempdir, 'js.pot') - execute('xgettext --no-location --omit-header -k_ -L java --from-code=utf-8 -o %s %s' - % (tmppotfile, ' '.join(jsfiles))) + tmppotfile = osp.join(tempdir, 'js.pot') + execute('xgettext --no-location --omit-header -k_ -L java ' + '--from-code=utf-8 -o %s %s' % (tmppotfile, ' '.join(jsfiles))) # no pot file created if there are no string to translate - if exists(tmppotfile): + if osp.exists(tmppotfile): potfiles.append(tmppotfile) print '-> create cube-specific catalog' - tmppotfile = join(tempdir, 'generated.pot') + tmppotfile = osp.join(tempdir, 'generated.pot') cubefiles = find('.', '.py', blacklist=STD_BLACKLIST+('test',)) cubefiles.append(tali18nfile) execute('xgettext --no-location --omit-header -k_ -o %s %s' % (tmppotfile, ' '.join('"%s"' % f for f in cubefiles))) - if exists(tmppotfile): # doesn't exists of no translation string found + if osp.exists(tmppotfile): # doesn't exists of no translation string found potfiles.append(tmppotfile) - potfile = join(tempdir, 'cube.pot') + potfile = osp.join(tempdir, 'cube.pot') print '-> merging %i .pot files:' % len(potfiles) execute('msgcat -o %s %s' % (potfile, ' '.join('"%s"' % f for f in potfiles))) - if not exists(potfile): + if not osp.exists(potfile): print 'no message catalog for cube', cube, 'nothing to translate' # cleanup rm(tempdir) @@ -428,16 +444,16 @@ print '-> merging main pot file with existing translations:' chdir('i18n') toedit = [] - for lang in LANGS: + for lang in cw_languages(): print '-> language', lang cubepo = '%s.po' % lang - if not exists(cubepo): + if not osp.exists(cubepo): shutil.copy(potfile, cubepo) else: execute('msgmerge -N -s -o %snew %s %s' % (cubepo, cubepo, potfile)) ensure_fs_mode(cubepo) shutil.move('%snew' % cubepo, cubepo) - toedit.append(abspath(cubepo)) + toedit.append(osp.abspath(cubepo)) # cleanup rm(tempdir) return toedit @@ -465,7 +481,7 @@ """ name = 'newcube' arguments = '' - + min_args = max_args = 1 options = ( ("layout", {'short': 'L', 'type' : 'choice', 'metavar': '', @@ -546,32 +562,34 @@ def run(self, args): import re from logilab.common.shellutils import ASK - if len(args) != 1: - raise BadCommandUsage("exactly one argument (cube name) is expected") cubename = args[0] if not re.match('[_A-Za-z][_A-Za-z0-9]*$', cubename): - raise BadCommandUsage("cube name should be a valid python module name") + raise BadCommandUsage( + 'cube name must be a valid python module name') verbose = self.get('verbose') cubesdir = self.get('directory') if not cubesdir: cubespath = ServerConfiguration.cubes_search_path() if len(cubespath) > 1: - raise BadCommandUsage("can't guess directory where to put the new cube." - " Please specify it using the --directory option") + raise BadCommandUsage( + "can't guess directory where to put the new cube." + " Please specify it using the --directory option") cubesdir = cubespath[0] - if not isdir(cubesdir): + if not osp.isdir(cubesdir): print "-> creating cubes directory", cubesdir try: mkdir(cubesdir) except OSError, err: - self.fail("failed to create directory %r\n(%s)" % (cubesdir, err)) - cubedir = join(cubesdir, cubename) - if exists(cubedir): - self.fail("%s already exists !" % (cubedir)) - skeldir = join(BASEDIR, 'skeleton') + self.fail("failed to create directory %r\n(%s)" + % (cubesdir, err)) + cubedir = osp.join(cubesdir, cubename) + if osp.exists(cubedir): + self.fail("%s already exists !" % cubedir) + skeldir = osp.join(BASEDIR, 'skeleton') default_name = 'cubicweb-%s' % cubename.lower().replace('_', '-') if verbose: - distname = raw_input('Debian name for your cube ? [%s]): ' % default_name).strip() + distname = raw_input('Debian name for your cube ? [%s]): ' + % default_name).strip() if not distname: distname = default_name elif not distname.startswith('cubicweb-'): @@ -580,10 +598,13 @@ else: distname = default_name if not re.match('[a-z][-a-z0-9]*$', distname): - raise BadCommandUsage("cube distname should be a valid debian package name") - longdesc = shortdesc = raw_input('Enter a short description for your cube: ') + raise BadCommandUsage( + 'cube distname should be a valid debian package name') + longdesc = shortdesc = raw_input( + 'Enter a short description for your cube: ') if verbose: - longdesc = raw_input('Enter a long description (leave empty to reuse the short one): ') + longdesc = raw_input( + 'Enter a long description (leave empty to reuse the short one): ') dependencies = {'cubicweb': '>= %s' % cubicwebversion} if verbose: dependencies.update(self._ask_for_dependencies()) @@ -638,8 +659,7 @@ """ arguments = 'rql.log' name = 'exlog' - options = ( - ) + options = () def run(self, args): import re @@ -685,34 +705,43 @@ name = "schema" arguments = '' min_args = max_args = 1 - options = [('output-file', {'type':'file', 'default': None, - 'metavar': '', 'short':'o', 'help':'output image file', - 'input':False}), - ('viewer', {'type': 'string', 'default':None, - 'short': "d", 'metavar':'', - 'help':'command use to view the generated file (empty for none)'} - ), - ('show-meta', {'action': 'store_true', 'default':False, - 'short': "m", 'metavar': "", - 'help':'include meta and internal entities in schema'} - ), - ('show-workflow', {'action': 'store_true', 'default':False, - 'short': "w", 'metavar': "", - 'help':'include workflow entities in schema'} - ), - ('show-cw-user', {'action': 'store_true', 'default':False, - 'metavar': "", - 'help':'include cubicweb user entities in schema'} - ), - ('exclude-type', {'type':'string', 'default':'', - 'short': "x", 'metavar': "", - 'help':'coma separated list of entity types to remove from view'} - ), - ('include-type', {'type':'string', 'default':'', - 'short': "i", 'metavar': "", - 'help':'coma separated list of entity types to include in view'} - ), - ] + options = [ + ('output-file', + {'type':'file', 'default': None, + 'metavar': '', 'short':'o', 'help':'output image file', + 'input':False, + }), + ('viewer', + {'type': 'string', 'default':None, + 'short': "d", 'metavar':'', + 'help':'command use to view the generated file (empty for none)', + }), + ('show-meta', + {'action': 'store_true', 'default':False, + 'short': "m", 'metavar': "", + 'help':'include meta and internal entities in schema', + }), + ('show-workflow', + {'action': 'store_true', 'default':False, + 'short': "w", 'metavar': "", + 'help':'include workflow entities in schema', + }), + ('show-cw-user', + {'action': 'store_true', 'default':False, + 'metavar': "", + 'help':'include cubicweb user entities in schema', + }), + ('exclude-type', + {'type':'string', 'default':'', + 'short': "x", 'metavar': "", + 'help':'coma separated list of entity types to remove from view', + }), + ('include-type', + {'type':'string', 'default':'', + 'short': "i", 'metavar': "", + 'help':'coma separated list of entity types to include in view', + }), + ] def run(self, args): from subprocess import Popen diff -r e3994fcc21c3 -r 1806148d6ce8 devtools/test/unittest_dbfill.py --- a/devtools/test/unittest_dbfill.py Thu Sep 23 23:28:58 2010 +0200 +++ b/devtools/test/unittest_dbfill.py Wed Sep 29 16:16:32 2010 +0200 @@ -68,7 +68,7 @@ def test_string(self): """test string generation""" surname = self.person_valgen.generate_attribute_value({}, 'surname', 12) - self.assertEquals(surname, u'é&surname12') + self.assertEqual(surname, u'é&surname12') def test_domain_value(self): """test value generation from a given domain value""" @@ -100,21 +100,21 @@ def test_phone(self): """tests make_tel utility""" - self.assertEquals(make_tel(22030405), '22 03 04 05') + self.assertEqual(make_tel(22030405), '22 03 04 05') def test_customized_generation(self): - self.assertEquals(self.bug_valgen.generate_attribute_value({}, 'severity', 12), + self.assertEqual(self.bug_valgen.generate_attribute_value({}, 'severity', 12), u'dangerous') - self.assertEquals(self.bug_valgen.generate_attribute_value({}, 'description', 12), + self.assertEqual(self.bug_valgen.generate_attribute_value({}, 'description', 12), u'yo') - self.assertEquals(self.person_valgen.generate_attribute_value({}, 'description', 12), + self.assertEqual(self.person_valgen.generate_attribute_value({}, 'description', 12), u'yo') class ConstraintInsertionTC(TestCase): def test_writeme(self): - self.skip('Test automatic insertion / Schema Constraints') + self.skipTest('Test automatic insertion / Schema Constraints') if __name__ == '__main__': diff -r e3994fcc21c3 -r 1806148d6ce8 devtools/test/unittest_httptest.py --- a/devtools/test/unittest_httptest.py Thu Sep 23 23:28:58 2010 +0200 +++ b/devtools/test/unittest_httptest.py Wed Sep 29 16:16:32 2010 +0200 @@ -15,7 +15,7 @@ def test_response_anon(self): response = self.web_get() - self.assertEquals(response.status, httplib.OK) + self.assertEqual(response.status, httplib.OK) def test_base_url(self): @@ -29,20 +29,20 @@ def test_response_denied(self): response = self.web_get() - self.assertEquals(response.status, httplib.FORBIDDEN) + self.assertEqual(response.status, httplib.FORBIDDEN) def test_login(self): response = self.web_get() if response.status != httplib.FORBIDDEN: - self.skip('Already authenticated') + self.skipTest('Already authenticated') # login self.web_login(self.admlogin, self.admpassword) response = self.web_get() - self.assertEquals(response.status, httplib.OK, response.body) + self.assertEqual(response.status, httplib.OK, response.body) # logout self.web_logout() response = self.web_get() - self.assertEquals(response.status, httplib.FORBIDDEN, response.body) + self.assertEqual(response.status, httplib.FORBIDDEN, response.body) diff -r e3994fcc21c3 -r 1806148d6ce8 devtools/test/unittest_qunit.py --- a/devtools/test/unittest_qunit.py Thu Sep 23 23:28:58 2010 +0200 +++ b/devtools/test/unittest_qunit.py Wed Sep 29 16:16:32 2010 +0200 @@ -20,7 +20,7 @@ def test_simple_failure(self): js_tests = list(self._test_qunit(js('test_simple_failure.js'))) - self.assertEquals(len(js_tests), 3) + self.assertEqual(len(js_tests), 3) test_1, test_2, test_3 = js_tests self.assertRaises(self.failureException, test_1[0], *test_1[1:]) self.assertRaises(self.failureException, test_2[0], *test_2[1:]) diff -r e3994fcc21c3 -r 1806148d6ce8 devtools/test/unittest_testlib.py --- a/devtools/test/unittest_testlib.py Thu Sep 23 23:28:58 2010 +0200 +++ b/devtools/test/unittest_testlib.py Wed Sep 29 16:16:32 2010 +0200 @@ -20,9 +20,8 @@ """ from cStringIO import StringIO -from unittest import TestSuite -from logilab.common.testlib import (TestCase, unittest_main, +from logilab.common.testlib import (TestCase, unittest_main, TestSuite, SkipAwareTextTestRunner) from cubicweb.devtools import htmlparser @@ -47,9 +46,9 @@ tests = [MyWebTest('test_error_view'), MyWebTest('test_correct_view')] result = self.runner.run(TestSuite(tests)) - self.assertEquals(result.testsRun, 2) - self.assertEquals(len(result.errors), 0) - self.assertEquals(len(result.failures), 1) + self.assertEqual(result.testsRun, 2) + self.assertEqual(len(result.errors), 0) + self.assertEqual(len(result.failures), 1) clean_repo_test_cls(MyWebTest) @@ -104,7 +103,7 @@ def test_source1(self): """make sure source is stored correctly""" - self.assertEquals(self.page_info.source, HTML_PAGE2) + self.assertEqual(self.page_info.source, HTML_PAGE2) def test_source2(self): """make sure source is stored correctly - raise exception""" @@ -114,47 +113,47 @@ def test_has_title_no_level(self): """tests h? tags information""" - self.assertEquals(self.page_info.has_title('Test'), True) - self.assertEquals(self.page_info.has_title('Test '), False) - self.assertEquals(self.page_info.has_title('Tes'), False) - self.assertEquals(self.page_info.has_title('Hello world !'), True) + self.assertEqual(self.page_info.has_title('Test'), True) + self.assertEqual(self.page_info.has_title('Test '), False) + self.assertEqual(self.page_info.has_title('Tes'), False) + self.assertEqual(self.page_info.has_title('Hello world !'), True) def test_has_title_level(self): """tests h? tags information""" - self.assertEquals(self.page_info.has_title('Test', level = 1), True) - self.assertEquals(self.page_info.has_title('Test', level = 2), False) - self.assertEquals(self.page_info.has_title('Test', level = 3), False) - self.assertEquals(self.page_info.has_title('Test', level = 4), False) + self.assertEqual(self.page_info.has_title('Test', level = 1), True) + self.assertEqual(self.page_info.has_title('Test', level = 2), False) + self.assertEqual(self.page_info.has_title('Test', level = 3), False) + self.assertEqual(self.page_info.has_title('Test', level = 4), False) self.assertRaises(IndexError, self.page_info.has_title, 'Test', level = 5) def test_has_title_regexp_no_level(self): """tests has_title_regexp() with no particular level specified""" - self.assertEquals(self.page_info.has_title_regexp('h[23] title'), True) + self.assertEqual(self.page_info.has_title_regexp('h[23] title'), True) def test_has_title_regexp_level(self): """tests has_title_regexp() with a particular level specified""" - self.assertEquals(self.page_info.has_title_regexp('h[23] title', 2), True) - self.assertEquals(self.page_info.has_title_regexp('h[23] title', 3), True) - self.assertEquals(self.page_info.has_title_regexp('h[23] title', 4), False) + self.assertEqual(self.page_info.has_title_regexp('h[23] title', 2), True) + self.assertEqual(self.page_info.has_title_regexp('h[23] title', 3), True) + self.assertEqual(self.page_info.has_title_regexp('h[23] title', 4), False) def test_appears(self): """tests PageInfo.appears()""" - self.assertEquals(self.page_info.appears('CW'), True) - self.assertEquals(self.page_info.appears('Logilab'), True) - self.assertEquals(self.page_info.appears('Logilab introduces'), True) - self.assertEquals(self.page_info.appears('H2 title'), False) + self.assertEqual(self.page_info.appears('CW'), True) + self.assertEqual(self.page_info.appears('Logilab'), True) + self.assertEqual(self.page_info.appears('Logilab introduces'), True) + self.assertEqual(self.page_info.appears('H2 title'), False) def test_has_link(self): """tests has_link()""" - self.assertEquals(self.page_info.has_link('Logilab'), True) - self.assertEquals(self.page_info.has_link('logilab'), False) - self.assertEquals(self.page_info.has_link('Logilab', 'http://www.logilab.org'), True) - self.assertEquals(self.page_info.has_link('Logilab', 'http://www.google.com'), False) + self.assertEqual(self.page_info.has_link('Logilab'), True) + self.assertEqual(self.page_info.has_link('logilab'), False) + self.assertEqual(self.page_info.has_link('Logilab', 'http://www.logilab.org'), True) + self.assertEqual(self.page_info.has_link('Logilab', 'http://www.google.com'), False) def test_has_link_regexp(self): """test has_link_regexp()""" - self.assertEquals(self.page_info.has_link_regexp('L[oi]gilab'), True) - self.assertEquals(self.page_info.has_link_regexp('L[ai]gilab'), False) + self.assertEqual(self.page_info.has_link_regexp('L[oi]gilab'), True) + self.assertEqual(self.page_info.has_link_regexp('L[ai]gilab'), False) if __name__ == '__main__': diff -r e3994fcc21c3 -r 1806148d6ce8 devtools/testlib.py --- a/devtools/testlib.py Thu Sep 23 23:28:58 2010 +0200 +++ b/devtools/testlib.py Wed Sep 29 16:16:32 2010 +0200 @@ -347,15 +347,19 @@ """return a connection for the given login/password""" if login == self.admlogin: self.restore_connection() - else: - if not kwargs: - kwargs['password'] = str(login) - self.cnx = repo_connect(self.repo, unicode(login), **kwargs) - self.websession = DBAPISession(self.cnx) - self._cnxs.append(self.cnx) + # definitly don't want autoclose when used as a context manager + return self.cnx + autoclose = kwargs.pop('autoclose', True) + if not kwargs: + kwargs['password'] = str(login) + self.cnx = repo_connect(self.repo, unicode(login), **kwargs) + self.websession = DBAPISession(self.cnx) + self._cnxs.append(self.cnx) if login == self.vreg.config.anonymous_user()[0]: self.cnx.anonymous_connection = True - return TestCaseConnectionProxy(self, self.cnx) + if autoclose: + return TestCaseConnectionProxy(self, self.cnx) + return self.cnx def restore_connection(self): if not self.cnx is self._orig_cnx[0]: diff -r e3994fcc21c3 -r 1806148d6ce8 doc/book/en/annexes/faq.rst --- a/doc/book/en/annexes/faq.rst Thu Sep 23 23:28:58 2010 +0200 +++ b/doc/book/en/annexes/faq.rst Wed Sep 29 16:16:32 2010 +0200 @@ -402,6 +402,17 @@ mydb=> update cw_cwuser set cw_upassword='qHO8282QN5Utg' where cw_login='joe'; UPDATE 1 +if you're running over SQL Server, you need to use the CONVERT +function to convert the string to varbinary(255). The SQL query is +therefore:: + + update cw_cwuser set cw_upassword=CONVERT(varbinary(255), 'qHO8282QN5Utg') where cw_login='joe'; + +Be careful, the encryption algorithm is different on Windows and on +Unix. You cannot therefore use a hash generated on Unix to fill in a +Windows database, nor the other way round. + + You can prefer use a migration script similar to this shell invocation instead:: $ cubicweb-ctl shell diff -r e3994fcc21c3 -r 1806148d6ce8 doc/book/en/devrepo/datamodel/definition.rst --- a/doc/book/en/devrepo/datamodel/definition.rst Thu Sep 23 23:28:58 2010 +0200 +++ b/doc/book/en/devrepo/datamodel/definition.rst Wed Sep 29 16:16:32 2010 +0200 @@ -82,10 +82,16 @@ a set of attributes and relations, and some permissions which define who can add, read, update or delete entities of this type. -The following built-in types are available: ``String``, ``Int``, -``Float``, ``Decimal``, ``Boolean``, ``Date``, ``Datetime``, ``Time``, -``Interval``, ``Byte`` and ``Password``. They can only be used as -attributes of an other entity type. +The following built-in types are available: ``String``, +``Int``, ``Float``, ``Decimal``, ``Boolean``, +``Date``, ``Datetime``, ``Time``, ``Interval``, ``Byte`` and +``Password``. They can only be used as attributes of an other entity +type. + +There is also a `RichString` kindof type: + + .. autoclass:: yams.buildobjs.RichString + You can find more base entity types in :ref:`pre_defined_entity_types`. @@ -518,6 +524,8 @@ birth and a relation that connects a `Person` to another entity of type `Company` through the semantic `works_for`. + + :Naming convention: Entity class names must start with an uppercase letter. The common diff -r e3994fcc21c3 -r 1806148d6ce8 doc/book/en/devrepo/devcore/dbapi.rst --- a/doc/book/en/devrepo/devcore/dbapi.rst Thu Sep 23 23:28:58 2010 +0200 +++ b/doc/book/en/devrepo/devcore/dbapi.rst Wed Sep 29 16:16:32 2010 +0200 @@ -22,9 +22,12 @@ .. note:: - While executing update queries (SET, INSERT, DELETE), if a query generates - an error related to security, a rollback is automatically done on the current - transaction. + If a query generates an error related to security (:exc:`Unauthorized`) or to + integrity (:exc:`ValidationError`), a rollback is automatically done on the + current transaction. + + Also, a rollback is done if an error occurs during commit. + Executing RQL queries from a view or a hook ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff -r e3994fcc21c3 -r 1806148d6ce8 doc/book/en/devrepo/repo/hooks.rst --- a/doc/book/en/devrepo/repo/hooks.rst Thu Sep 23 23:28:58 2010 +0200 +++ b/doc/book/en/devrepo/repo/hooks.rst Wed Sep 29 16:16:32 2010 +0200 @@ -6,6 +6,7 @@ .. autodocstring:: cubicweb.server.hook + Example using dataflow hooks ---------------------------- @@ -30,8 +31,8 @@ class PersonAgeRange(Hook): __regid__ = 'person_age_range' + __select__ = Hook.__select__ & is_instance('Person') events = ('before_add_entity', 'before_update_entity') - __select__ = Hook.__select__ & is_instance('Person') def __call__(self): if 'age' in self.entity.cw_edited: @@ -96,6 +97,8 @@ .. sourcecode:: python + from cubicweb.server.hook import Hook, Operation, match_rtype + def check_cycle(self, session, eid, rtype, role='subject'): parents = set([eid]) parent = session.entity_from_eid(eid) @@ -146,15 +149,15 @@ class CheckSubsidiaryCycleOp(Operation): def precommit_event(self): - for eid in self._cw.transaction_data.pop('subsidiary_cycle_detection'): - check_cycle(self.session, eid, 'subsidiary_of') + for eid in self.session.transaction_data['subsidiary_cycle_detection']: + check_cycle(self.session, eid, self.rtype) Here, we call :func:`set_operation` so that we will simply accumulate eids of -entities to check at the end in a single CheckSubsidiaryCycleOp operation. Value -are stored in a set associated to the 'subsidiary_cycle_detection' transaction -data key. The set initialization and operation creation are handled nicely by -:func:set_operation. +entities to check at the end in a single `CheckSubsidiaryCycleOp` +operation. Value are stored in a set associated to the +'subsidiary_cycle_detection' transaction data key. The set initialization and +operation creation are handled nicely by :func:`set_operation`. A more realistic example can be found in the advanced tutorial chapter :ref:`adv_tuto_security_propagation`. diff -r e3994fcc21c3 -r 1806148d6ce8 doc/book/en/devrepo/testing.rst --- a/doc/book/en/devrepo/testing.rst Thu Sep 23 23:28:58 2010 +0200 +++ b/doc/book/en/devrepo/testing.rst Wed Sep 29 16:16:32 2010 +0200 @@ -42,6 +42,8 @@ `sync_schema_props_perms()` fonction of the migration environment need not a database regeneration step. +.. _hook_test: + Unit test by example ```````````````````` @@ -85,6 +87,14 @@ The test case itself checks that an Operation does it job of preventing cycles amongst Keyword entities. +`create_entity` is a useful method, which easily allows to create an +entity. You can link this entity to others entities, by specifying as +argument, the relation name, and the entity to link, as value. In the +above example, the `Classification` entity is linked to a `CWEtype` +via the relation `classifies`. Conversely, if you are creating a +`CWEtype` entity, you can link it to a `Classification` entity, by +adding `reverse_classifies` as argument. + .. note:: :meth:`commit` method is not called automatically in test_XXX diff -r e3994fcc21c3 -r 1806148d6ce8 doc/book/en/devweb/controllers.rst --- a/doc/book/en/devweb/controllers.rst Thu Sep 23 23:28:58 2010 +0200 +++ b/doc/book/en/devweb/controllers.rst Wed Sep 29 16:16:32 2010 +0200 @@ -15,13 +15,12 @@ `Browsing`: -* the View controlleris associated with most browsing actions within a - CubicWeb application: it always instantiates a - :ref:`the_main_template` and lets the ResultSet/Views dispatch - system build up the whole content; it handles ObjectNotFound and - NoSelectableObject errors that may bubble up to its entry point, in - an end-user-friendly way (but other programming errors will slip - through) +* the View controller is associated with most browsing actions within a + CubicWeb application: it always instantiates a :ref:`the_main_template` and + lets the ResultSet/Views dispatch system build up the whole content; it + handles :exc:`ObjectNotFound` and :exc:`NoSelectableObject` errors that may + bubble up to its entry point, in an end-user-friendly way (but other + programming errors will slip through) * the JSon controller (same module) provides services for Ajax calls, typically using JSON as a serialization format for input, and @@ -49,7 +48,7 @@ for outgoing email notifications * the MailBugReport controller (web/views/basecontrollers.py) allows - to quickly have a `repotbug` feature in one's application + to quickly have a `reportbug` feature in one's application Registration ++++++++++++ diff -r e3994fcc21c3 -r 1806148d6ce8 doc/book/en/devweb/views/table.rst --- a/doc/book/en/devweb/views/table.rst Thu Sep 23 23:28:58 2010 +0200 +++ b/doc/book/en/devweb/views/table.rst Wed Sep 29 16:16:32 2010 +0200 @@ -7,6 +7,10 @@ Creates a HTML table (``) and call the view `cell` for each cell of the result set. Applicable on any result set. +*editable-table* + Creates an **editable** HTML table (`
`) and call the view `cell` for each cell of + the result set. Applicable on any result set. + *cell* By default redirects to the `final` view if this is a final entity or `outofcontext` view otherwise @@ -17,3 +21,58 @@ .. autoclass:: cubicweb.web.views.tableview.TableView :members: + +Example +``````` + +Let us take an example from the timesheet cube: + +.. sourcecode:: python + + class ActivityTable(EntityView): + __regid__ = 'activitytable' + __select__ = is_instance('Activity') + title = _('activitytable') + + def call(self, showresource=True): + _ = self._cw._ + headers = [_("diem"), _("duration"), _("workpackage"), _("description"), _("state"), u""] + eids = ','.join(str(row[0]) for row in self.cw_rset) + rql = ('Any R, D, DUR, WO, DESCR, S, A, SN, RT, WT ORDERBY D DESC ' + 'WHERE ' + ' A is Activity, A done_by R, R title RT, ' + ' A diem D, A duration DUR, ' + ' A done_for WO, WO title WT, ' + ' A description DESCR, A in_state S, S name SN, A eid IN (%s)' % eids) + if showresource: + displaycols = range(7) + headers.insert(0, display_name(self._cw, 'Resource')) + else: # skip resource column if asked to + displaycols = range(1, 7) + rset = self._cw.execute(rql) + self.wview('editable-table', rset, 'null', + displayfilter=True, displayactions=False, + headers=headers, displaycols=displaycols, + cellvids={3: 'editable-final'}) + +To obtain an editable table, specify 'edtitable-table' as vid. You +have to select the entity in the rql request too (in order to kwnow +which entity must be edited). You can specify an optional +`displaycols` argument which defines column's indexes that will be +displayed. In the above example, setting `showresource` to `False` +will only render columns from index 1 to 7. + +The previous example results in: + +.. image:: ../../images/views-table-shadow.png + + +In order to activate table filter mechanism, set the `displayfilter` +argument to True. A small arrow will be displayed at the table's top +right corner. Clicking on `show filter form` action, will display the +filter form as below: + +.. image:: ../../images/views-table-filter-shadow.png + +By the same way, you can display all registered actions for the +selected entity, setting `displayactions` argument to True. diff -r e3994fcc21c3 -r 1806148d6ce8 doc/book/en/images/views-table-filter-shadow.png Binary file doc/book/en/images/views-table-filter-shadow.png has changed diff -r e3994fcc21c3 -r 1806148d6ce8 doc/book/en/images/views-table-filter.png Binary file doc/book/en/images/views-table-filter.png has changed diff -r e3994fcc21c3 -r 1806148d6ce8 doc/book/en/images/views-table-shadow.png Binary file doc/book/en/images/views-table-shadow.png has changed diff -r e3994fcc21c3 -r 1806148d6ce8 doc/book/en/images/views-table.png Binary file doc/book/en/images/views-table.png has changed diff -r e3994fcc21c3 -r 1806148d6ce8 entities/test/unittest_base.py --- a/entities/test/unittest_base.py Thu Sep 23 23:28:58 2010 +0200 +++ b/entities/test/unittest_base.py Wed Sep 29 16:16:32 2010 +0200 @@ -44,16 +44,16 @@ self.login(u'member') entity = self.request().create_entity('Bookmark', title=u"hello", path=u'project/cubicweb') self.commit() - self.assertEquals(entity.creator.eid, self.member.eid) - self.assertEquals(entity.dc_creator(), u'member') + self.assertEqual(entity.creator.eid, self.member.eid) + self.assertEqual(entity.dc_creator(), u'member') def test_type(self): - self.assertEquals(self.member.dc_type(), 'cwuser') + self.assertEqual(self.member.dc_type(), 'cwuser') def test_entity_meta_attributes(self): # XXX move to yams - self.assertEquals(self.schema['CWUser'].meta_attributes(), {}) - self.assertEquals(dict((str(k), v) for k, v in self.schema['State'].meta_attributes().iteritems()), + self.assertEqual(self.schema['CWUser'].meta_attributes(), {}) + self.assertEqual(dict((str(k), v) for k, v in self.schema['State'].meta_attributes().iteritems()), {'description_format': ('format', 'description')}) @@ -63,20 +63,20 @@ email2 = self.execute('INSERT EmailAddress X: X address "maarten@philips.com"').get_entity(0, 0) email3 = self.execute('INSERT EmailAddress X: X address "toto@logilab.fr"').get_entity(0, 0) email1.set_relations(prefered_form=email2) - self.assertEquals(email1.prefered.eid, email2.eid) - self.assertEquals(email2.prefered.eid, email2.eid) - self.assertEquals(email3.prefered.eid, email3.eid) + self.assertEqual(email1.prefered.eid, email2.eid) + self.assertEqual(email2.prefered.eid, email2.eid) + self.assertEqual(email3.prefered.eid, email3.eid) def test_mangling(self): email = self.execute('INSERT EmailAddress X: X address "maarten.ter.huurne@philips.com"').get_entity(0, 0) - self.assertEquals(email.display_address(), 'maarten.ter.huurne@philips.com') - self.assertEquals(email.printable_value('address'), 'maarten.ter.huurne@philips.com') + self.assertEqual(email.display_address(), 'maarten.ter.huurne@philips.com') + self.assertEqual(email.printable_value('address'), 'maarten.ter.huurne@philips.com') self.vreg.config.global_set_option('mangle-emails', True) - self.assertEquals(email.display_address(), 'maarten.ter.huurne at philips dot com') - self.assertEquals(email.printable_value('address'), 'maarten.ter.huurne at philips dot com') + self.assertEqual(email.display_address(), 'maarten.ter.huurne at philips dot com') + self.assertEqual(email.printable_value('address'), 'maarten.ter.huurne at philips dot com') email = self.execute('INSERT EmailAddress X: X address "syt"').get_entity(0, 0) - self.assertEquals(email.display_address(), 'syt') - self.assertEquals(email.printable_value('address'), 'syt') + self.assertEqual(email.display_address(), 'syt') + self.assertEqual(email.printable_value('address'), 'syt') class CWUserTC(BaseEntityTC): @@ -94,19 +94,19 @@ def test_dc_title_and_name(self): e = self.execute('CWUser U WHERE U login "member"').get_entity(0, 0) - self.assertEquals(e.dc_title(), 'member') - self.assertEquals(e.name(), 'member') + self.assertEqual(e.dc_title(), 'member') + self.assertEqual(e.name(), 'member') e.set_attributes(firstname=u'bouah') - self.assertEquals(e.dc_title(), 'member') - self.assertEquals(e.name(), u'bouah') + self.assertEqual(e.dc_title(), 'member') + self.assertEqual(e.name(), u'bouah') e.set_attributes(surname=u'lôt') - self.assertEquals(e.dc_title(), 'member') - self.assertEquals(e.name(), u'bouah lôt') + self.assertEqual(e.dc_title(), 'member') + self.assertEqual(e.name(), u'bouah lôt') def test_allowed_massmail_keys(self): e = self.execute('CWUser U WHERE U login "member"').get_entity(0, 0) # Bytes/Password attributes should be omited - self.assertEquals(e.cw_adapt_to('IEmailable').allowed_massmail_keys(), + self.assertEqual(e.cw_adapt_to('IEmailable').allowed_massmail_keys(), set(('surname', 'firstname', 'login', 'last_login_time', 'creation_date', 'modification_date', 'cwuri', 'eid')) ) @@ -144,7 +144,7 @@ # no specific class for Subdivisions, the default one should be selected eclass = self.select_eclass('SubDivision') self.failUnless(eclass.__autogenerated__) - #self.assertEquals(eclass.__bases__, (AnyEntity,)) + #self.assertEqual(eclass.__bases__, (AnyEntity,)) # build class from most generic to most specific and make # sure the most specific is always selected self.vreg._loadedmods[__name__] = {} @@ -156,12 +156,12 @@ self.failUnless(eclass.__autogenerated__) self.failIf(eclass is Foo) if etype == 'SubDivision': - self.assertEquals(eclass.__bases__, (Foo,)) + self.assertEqual(eclass.__bases__, (Foo,)) else: - self.assertEquals(eclass.__bases__[0].__bases__, (Foo,)) + self.assertEqual(eclass.__bases__[0].__bases__, (Foo,)) # check Division eclass is still selected for plain Division entities eclass = self.select_eclass('Division') - self.assertEquals(eclass.__regid__, 'Division') + self.assertEqual(eclass.__regid__, 'Division') if __name__ == '__main__': unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 entities/test/unittest_wfobjs.py --- a/entities/test/unittest_wfobjs.py Thu Sep 23 23:28:58 2010 +0200 +++ b/entities/test/unittest_wfobjs.py Wed Sep 29 16:16:32 2010 +0200 @@ -43,12 +43,12 @@ wf = add_wf(self, 'Company') foo = wf.add_state(u'foo', initial=True) bar = wf.add_state(u'bar') - self.assertEquals(wf.state_by_name('bar').eid, bar.eid) - self.assertEquals(wf.state_by_name('barrr'), None) + self.assertEqual(wf.state_by_name('bar').eid, bar.eid) + self.assertEqual(wf.state_by_name('barrr'), None) baz = wf.add_transition(u'baz', (foo,), bar, ('managers',)) - self.assertEquals(wf.transition_by_name('baz').eid, baz.eid) - self.assertEquals(len(baz.require_group), 1) - self.assertEquals(baz.require_group[0].name, 'managers') + self.assertEqual(wf.transition_by_name('baz').eid, baz.eid) + self.assertEqual(len(baz.require_group), 1) + self.assertEqual(baz.require_group[0].name, 'managers') def test_duplicated_state(self): wf = add_wf(self, 'Company') @@ -56,7 +56,7 @@ self.commit() wf.add_state(u'foo') ex = self.assertRaises(ValidationError, self.commit) - self.assertEquals(ex.errors, {'name-subject': 'workflow already have a state of that name'}) + self.assertEqual(ex.errors, {'name-subject': 'workflow already have a state of that name'}) # no pb if not in the same workflow wf2 = add_wf(self, 'Company') foo = wf2.add_state(u'foo', initial=True) @@ -66,7 +66,7 @@ self.commit() bar.set_attributes(name=u'foo') ex = self.assertRaises(ValidationError, self.commit) - self.assertEquals(ex.errors, {'name-subject': 'workflow already have a state of that name'}) + self.assertEqual(ex.errors, {'name-subject': 'workflow already have a state of that name'}) def test_duplicated_transition(self): wf = add_wf(self, 'Company') @@ -75,7 +75,7 @@ wf.add_transition(u'baz', (foo,), bar, ('managers',)) wf.add_transition(u'baz', (bar,), foo) ex = self.assertRaises(ValidationError, self.commit) - self.assertEquals(ex.errors, {'name-subject': 'workflow already have a transition of that name'}) + self.assertEqual(ex.errors, {'name-subject': 'workflow already have a transition of that name'}) # no pb if not in the same workflow wf2 = add_wf(self, 'Company') foo = wf.add_state(u'foo', initial=True) @@ -87,7 +87,7 @@ self.commit() biz.set_attributes(name=u'baz') ex = self.assertRaises(ValidationError, self.commit) - self.assertEquals(ex.errors, {'name-subject': 'workflow already have a transition of that name'}) + self.assertEqual(ex.errors, {'name-subject': 'workflow already have a transition of that name'}) class WorkflowTC(CubicWebTC): @@ -95,13 +95,13 @@ def setup_database(self): rschema = self.schema['in_state'] for rdef in rschema.rdefs.values(): - self.assertEquals(rdef.cardinality, '1*') + self.assertEqual(rdef.cardinality, '1*') self.member = self.create_user('member') def test_workflow_base(self): e = self.create_user('toto') iworkflowable = e.cw_adapt_to('IWorkflowable') - self.assertEquals(iworkflowable.state, 'activated') + self.assertEqual(iworkflowable.state, 'activated') iworkflowable.change_state('deactivated', u'deactivate 1') self.commit() iworkflowable.change_state('activated', u'activate 1') @@ -109,33 +109,33 @@ iworkflowable.change_state('deactivated', u'deactivate 2') self.commit() e.cw_clear_relation_cache('wf_info_for', 'object') - self.assertEquals([tr.comment for tr in e.reverse_wf_info_for], + self.assertEqual([tr.comment for tr in e.reverse_wf_info_for], ['deactivate 1', 'activate 1', 'deactivate 2']) - self.assertEquals(iworkflowable.latest_trinfo().comment, 'deactivate 2') + self.assertEqual(iworkflowable.latest_trinfo().comment, 'deactivate 2') def test_possible_transitions(self): user = self.execute('CWUser X').get_entity(0, 0) iworkflowable = user.cw_adapt_to('IWorkflowable') trs = list(iworkflowable.possible_transitions()) - self.assertEquals(len(trs), 1) - self.assertEquals(trs[0].name, u'deactivate') - self.assertEquals(trs[0].destination(None).name, u'deactivated') + self.assertEqual(len(trs), 1) + self.assertEqual(trs[0].name, u'deactivate') + self.assertEqual(trs[0].destination(None).name, u'deactivated') # test a std user get no possible transition cnx = self.login('member') # fetch the entity using the new session trs = list(cnx.user().cw_adapt_to('IWorkflowable').possible_transitions()) - self.assertEquals(len(trs), 0) + self.assertEqual(len(trs), 0) def _test_manager_deactivate(self, user): iworkflowable = user.cw_adapt_to('IWorkflowable') user.cw_clear_relation_cache('in_state', 'subject') - self.assertEquals(len(user.in_state), 1) - self.assertEquals(iworkflowable.state, 'deactivated') + self.assertEqual(len(user.in_state), 1) + self.assertEqual(iworkflowable.state, 'deactivated') trinfo = iworkflowable.latest_trinfo() - self.assertEquals(trinfo.previous_state.name, 'activated') - self.assertEquals(trinfo.new_state.name, 'deactivated') - self.assertEquals(trinfo.comment, 'deactivate user') - self.assertEquals(trinfo.comment_format, 'text/plain') + self.assertEqual(trinfo.previous_state.name, 'activated') + self.assertEqual(trinfo.new_state.name, 'deactivated') + self.assertEqual(trinfo.comment, 'deactivate user') + self.assertEqual(trinfo.comment_format, 'text/plain') return trinfo def test_change_state(self): @@ -143,7 +143,7 @@ iworkflowable = user.cw_adapt_to('IWorkflowable') iworkflowable.change_state('deactivated', comment=u'deactivate user') trinfo = self._test_manager_deactivate(user) - self.assertEquals(trinfo.transition, None) + self.assertEqual(trinfo.transition, None) def test_set_in_state_bad_wf(self): wf = add_wf(self, 'CWUser') @@ -153,7 +153,7 @@ ex = self.assertRaises(ValidationError, self.session.execute, 'SET X in_state S WHERE X eid %(x)s, S eid %(s)s', {'x': self.user().eid, 's': s.eid}) - self.assertEquals(ex.errors, {'in_state-subject': "state doesn't belong to entity's workflow. " + self.assertEqual(ex.errors, {'in_state-subject': "state doesn't belong to entity's workflow. " "You may want to set a custom workflow for this entity first."}) def test_fire_transition(self): @@ -161,10 +161,10 @@ iworkflowable = user.cw_adapt_to('IWorkflowable') iworkflowable.fire_transition('deactivate', comment=u'deactivate user') user.clear_all_caches() - self.assertEquals(iworkflowable.state, 'deactivated') + self.assertEqual(iworkflowable.state, 'deactivated') self._test_manager_deactivate(user) trinfo = self._test_manager_deactivate(user) - self.assertEquals(trinfo.transition.name, 'deactivate') + self.assertEqual(trinfo.transition.name, 'deactivate') def test_goback_transition(self): wf = self.session.user.cw_adapt_to('IWorkflowable').current_workflow @@ -179,7 +179,7 @@ self.commit() iworkflowable.fire_transition('wake up') self.commit() - self.assertEquals(iworkflowable.state, 'activated') + self.assertEqual(iworkflowable.state, 'activated') iworkflowable.fire_transition('deactivate') self.commit() iworkflowable.fire_transition('rest') @@ -187,7 +187,7 @@ iworkflowable.fire_transition('wake up') self.commit() user.clear_all_caches() - self.assertEquals(iworkflowable.state, 'deactivated') + self.assertEqual(iworkflowable.state, 'deactivated') # XXX test managers can change state without matching transition @@ -199,7 +199,7 @@ iworkflowable = req.entity_from_eid(self.member.eid).cw_adapt_to('IWorkflowable') ex = self.assertRaises(ValidationError, iworkflowable.fire_transition, 'deactivate') - self.assertEquals(ex.errors, {'by_transition-subject': "transition may not be fired"}) + self.assertEqual(ex.errors, {'by_transition-subject': "transition may not be fired"}) cnx.close() cnx = self.login('member') req = self.request() @@ -208,7 +208,7 @@ cnx.commit() ex = self.assertRaises(ValidationError, iworkflowable.fire_transition, 'activate') - self.assertEquals(ex.errors, {'by_transition-subject': "transition may not be fired"}) + self.assertEqual(ex.errors, {'by_transition-subject': "transition may not be fired"}) def test_fire_transition_owned_by(self): self.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", ' @@ -255,34 +255,34 @@ state3 = mwf.add_state(u'state3') swftr1 = mwf.add_wftransition(u'swftr1', swf, state1, [(swfstate2, state2), (swfstate3, state3)]) - self.assertEquals(swftr1.destination(None).eid, swfstate1.eid) + self.assertEqual(swftr1.destination(None).eid, swfstate1.eid) # workflows built, begin test group = self.request().create_entity('CWGroup', name=u'grp1') self.commit() iworkflowable = group.cw_adapt_to('IWorkflowable') - self.assertEquals(iworkflowable.current_state.eid, state1.eid) - self.assertEquals(iworkflowable.current_workflow.eid, mwf.eid) - self.assertEquals(iworkflowable.main_workflow.eid, mwf.eid) - self.assertEquals(iworkflowable.subworkflow_input_transition(), None) + self.assertEqual(iworkflowable.current_state.eid, state1.eid) + self.assertEqual(iworkflowable.current_workflow.eid, mwf.eid) + self.assertEqual(iworkflowable.main_workflow.eid, mwf.eid) + self.assertEqual(iworkflowable.subworkflow_input_transition(), None) iworkflowable.fire_transition('swftr1', u'go') self.commit() group.clear_all_caches() - self.assertEquals(iworkflowable.current_state.eid, swfstate1.eid) - self.assertEquals(iworkflowable.current_workflow.eid, swf.eid) - self.assertEquals(iworkflowable.main_workflow.eid, mwf.eid) - self.assertEquals(iworkflowable.subworkflow_input_transition().eid, swftr1.eid) + self.assertEqual(iworkflowable.current_state.eid, swfstate1.eid) + self.assertEqual(iworkflowable.current_workflow.eid, swf.eid) + self.assertEqual(iworkflowable.main_workflow.eid, mwf.eid) + self.assertEqual(iworkflowable.subworkflow_input_transition().eid, swftr1.eid) iworkflowable.fire_transition('tr1', u'go') self.commit() group.clear_all_caches() - self.assertEquals(iworkflowable.current_state.eid, state2.eid) - self.assertEquals(iworkflowable.current_workflow.eid, mwf.eid) - self.assertEquals(iworkflowable.main_workflow.eid, mwf.eid) - self.assertEquals(iworkflowable.subworkflow_input_transition(), None) + self.assertEqual(iworkflowable.current_state.eid, state2.eid) + self.assertEqual(iworkflowable.current_workflow.eid, mwf.eid) + self.assertEqual(iworkflowable.main_workflow.eid, mwf.eid) + self.assertEqual(iworkflowable.subworkflow_input_transition(), None) # force back to swfstate1 is impossible since we can't any more find # subworkflow input transition ex = self.assertRaises(ValidationError, iworkflowable.change_state, swfstate1, u'gadget') - self.assertEquals(ex.errors, {'to_state-subject': "state doesn't belong to entity's workflow"}) + self.assertEqual(ex.errors, {'to_state-subject': "state doesn't belong to entity's workflow"}) self.rollback() # force back to state1 iworkflowable.change_state('state1', u'gadget') @@ -291,10 +291,10 @@ iworkflowable.fire_transition('tr2', u'chapeau') self.commit() group.clear_all_caches() - self.assertEquals(iworkflowable.current_state.eid, state3.eid) - self.assertEquals(iworkflowable.current_workflow.eid, mwf.eid) - self.assertEquals(iworkflowable.main_workflow.eid, mwf.eid) - self.assertListEquals(parse_hist(iworkflowable.workflow_history), + self.assertEqual(iworkflowable.current_state.eid, state3.eid) + self.assertEqual(iworkflowable.current_workflow.eid, mwf.eid) + self.assertEqual(iworkflowable.main_workflow.eid, mwf.eid) + self.assertListEqual(parse_hist(iworkflowable.workflow_history), [('state1', 'swfstate1', 'swftr1', 'go'), ('swfstate1', 'swfstate2', 'tr1', 'go'), ('swfstate2', 'state2', 'swftr1', 'exiting from subworkflow subworkflow'), @@ -318,7 +318,7 @@ mwf.add_wftransition(u'swftr1', swf, state1, [(swfstate2, state2), (swfstate2, state3)]) ex = self.assertRaises(ValidationError, self.commit) - self.assertEquals(ex.errors, {'subworkflow_exit-subject': u"can't have multiple exits on the same state"}) + self.assertEqual(ex.errors, {'subworkflow_exit-subject': u"can't have multiple exits on the same state"}) def test_swf_fire_in_a_row(self): # sub-workflow @@ -382,7 +382,7 @@ iworkflowable.fire_transition(trans) self.commit() group.clear_all_caches() - self.assertEquals(iworkflowable.state, nextstate) + self.assertEqual(iworkflowable.state, nextstate) class CustomWorkflowTC(CubicWebTC): @@ -400,12 +400,12 @@ {'wf': wf.eid, 'x': self.member.eid}) self.member.clear_all_caches() iworkflowable = self.member.cw_adapt_to('IWorkflowable') - self.assertEquals(iworkflowable.state, 'activated')# no change before commit + self.assertEqual(iworkflowable.state, 'activated')# no change before commit self.commit() self.member.clear_all_caches() - self.assertEquals(iworkflowable.current_workflow.eid, wf.eid) - self.assertEquals(iworkflowable.state, 'asleep') - self.assertEquals(iworkflowable.workflow_history, ()) + self.assertEqual(iworkflowable.current_workflow.eid, wf.eid) + self.assertEqual(iworkflowable.state, 'asleep') + self.assertEqual(iworkflowable.workflow_history, ()) def test_custom_wf_replace_state_keep_history(self): """member in inital state with some history, state is redirected and @@ -420,9 +420,9 @@ {'wf': wf.eid, 'x': self.member.eid}) self.commit() self.member.clear_all_caches() - self.assertEquals(iworkflowable.current_workflow.eid, wf.eid) - self.assertEquals(iworkflowable.state, 'asleep') - self.assertEquals(parse_hist(iworkflowable.workflow_history), + self.assertEqual(iworkflowable.current_workflow.eid, wf.eid) + self.assertEqual(iworkflowable.state, 'asleep') + self.assertEqual(parse_hist(iworkflowable.workflow_history), [('activated', 'deactivated', 'deactivate', None), ('deactivated', 'activated', 'activate', None), ('activated', 'asleep', None, 'workflow changed to "CWUser"')]) @@ -436,7 +436,7 @@ self.execute('SET X custom_workflow WF WHERE X eid %(x)s, WF eid %(wf)s', {'wf': wf.eid, 'x': self.member.eid}) ex = self.assertRaises(ValidationError, self.commit) - self.assertEquals(ex.errors, {'custom_workflow-subject': u'workflow has no initial state'}) + self.assertEqual(ex.errors, {'custom_workflow-subject': u'workflow has no initial state'}) def test_custom_wf_bad_etype(self): """try to set a custom workflow which doesn't apply to entity type""" @@ -445,7 +445,7 @@ self.execute('SET X custom_workflow WF WHERE X eid %(x)s, WF eid %(wf)s', {'wf': wf.eid, 'x': self.member.eid}) ex = self.assertRaises(ValidationError, self.commit) - self.assertEquals(ex.errors, {'custom_workflow-subject': u"workflow isn't a workflow for this type"}) + self.assertEqual(ex.errors, {'custom_workflow-subject': u"workflow isn't a workflow for this type"}) def test_del_custom_wf(self): """member in some state shared by the new workflow, nothing has to be @@ -461,12 +461,12 @@ self.execute('DELETE X custom_workflow WF WHERE X eid %(x)s, WF eid %(wf)s', {'wf': wf.eid, 'x': self.member.eid}) self.member.clear_all_caches() - self.assertEquals(iworkflowable.state, 'asleep')# no change before commit + self.assertEqual(iworkflowable.state, 'asleep')# no change before commit self.commit() self.member.clear_all_caches() - self.assertEquals(iworkflowable.current_workflow.name, "default user workflow") - self.assertEquals(iworkflowable.state, 'activated') - self.assertEquals(parse_hist(iworkflowable.workflow_history), + self.assertEqual(iworkflowable.current_workflow.name, "default user workflow") + self.assertEqual(iworkflowable.state, 'activated') + self.assertEqual(parse_hist(iworkflowable.workflow_history), [('activated', 'deactivated', 'deactivate', None), ('deactivated', 'asleep', None, 'workflow changed to "CWUser"'), ('asleep', 'activated', None, 'workflow changed to "default user workflow"'),]) @@ -492,24 +492,24 @@ {'wf': wf.eid, 'x': user.eid}) self.commit() user.clear_all_caches() - self.assertEquals(iworkflowable.state, 'asleep') - self.assertEquals([t.name for t in iworkflowable.possible_transitions()], + self.assertEqual(iworkflowable.state, 'asleep') + self.assertEqual([t.name for t in iworkflowable.possible_transitions()], ['rest']) iworkflowable.fire_transition('rest') self.commit() user.clear_all_caches() - self.assertEquals(iworkflowable.state, 'asleep') - self.assertEquals([t.name for t in iworkflowable.possible_transitions()], + self.assertEqual(iworkflowable.state, 'asleep') + self.assertEqual([t.name for t in iworkflowable.possible_transitions()], ['rest']) - self.assertEquals(parse_hist(iworkflowable.workflow_history), + self.assertEqual(parse_hist(iworkflowable.workflow_history), [('asleep', 'asleep', 'rest', None)]) user.set_attributes(surname=u'toto') # fulfill condition self.commit() iworkflowable.fire_transition('rest') self.commit() user.clear_all_caches() - self.assertEquals(iworkflowable.state, 'dead') - self.assertEquals(parse_hist(iworkflowable.workflow_history), + self.assertEqual(iworkflowable.state, 'dead') + self.assertEqual(parse_hist(iworkflowable.workflow_history), [('asleep', 'asleep', 'rest', None), ('asleep', 'asleep', 'rest', None), ('asleep', 'dead', 'sick', None),]) @@ -521,7 +521,7 @@ {'wf': wf.eid, 'x': user.eid}) self.commit() iworkflowable = user.cw_adapt_to('IWorkflowable') - self.assertEquals(iworkflowable.state, 'dead') + self.assertEqual(iworkflowable.state, 'dead') def test_auto_transition_initial_state_fired(self): wf = self.execute('Any WF WHERE ET default_workflow WF, ' @@ -534,7 +534,7 @@ user = self.create_user('member', surname=u'toto') self.commit() iworkflowable = user.cw_adapt_to('IWorkflowable') - self.assertEquals(iworkflowable.state, 'dead') + self.assertEqual(iworkflowable.state, 'dead') class WorkflowHooksTC(CubicWebTC): @@ -555,7 +555,7 @@ self.commit() initialstate = self.execute('Any N WHERE S name N, X in_state S, X eid %(x)s', {'x' : ueid})[0][0] - self.assertEquals(initialstate, u'activated') + self.assertEqual(initialstate, u'activated') # give access to users group on the user's wf transitions # so we can test wf enforcing on euser (managers don't have anymore this # enforcement @@ -592,7 +592,7 @@ iworkflowable = user.cw_adapt_to('IWorkflowable') ex = self.assertRaises(ValidationError, iworkflowable.fire_transition, 'activate') - self.assertEquals(self._cleanup_msg(ex.errors['by_transition-subject']), + self.assertEqual(self._cleanup_msg(ex.errors['by_transition-subject']), u"transition isn't allowed from") cnx.close() @@ -602,7 +602,7 @@ iworkflowable = user.cw_adapt_to('IWorkflowable') ex = self.assertRaises(ValidationError, iworkflowable.fire_transition, 'dummy') - self.assertEquals(self._cleanup_msg(ex.errors['by_transition-subject']), + self.assertEqual(self._cleanup_msg(ex.errors['by_transition-subject']), u"transition isn't allowed from") cnx.close() @@ -616,7 +616,7 @@ session.set_pool() ex = self.assertRaises(ValidationError, iworkflowable.fire_transition, 'deactivate') - self.assertEquals(self._cleanup_msg(ex.errors['by_transition-subject']), + self.assertEqual(self._cleanup_msg(ex.errors['by_transition-subject']), u"transition isn't allowed from") # get back now iworkflowable.fire_transition('activate') diff -r e3994fcc21c3 -r 1806148d6ce8 ext/test/unittest_rest.py --- a/ext/test/unittest_rest.py Thu Sep 23 23:28:58 2010 +0200 +++ b/ext/test/unittest_rest.py Wed Sep 29 16:16:32 2010 +0200 @@ -29,9 +29,9 @@ def test_eid_role(self): context = self.context() - self.assertEquals(rest_publish(context, ':eid:`%s`' % context.eid), + self.assertEqual(rest_publish(context, ':eid:`%s`' % context.eid), '

#%s

\n' % context.eid) - self.assertEquals(rest_publish(context, ':eid:`%s:some text`' % context.eid), + self.assertEqual(rest_publish(context, ':eid:`%s:some text`' % context.eid), '

some text

\n') def test_bad_rest_no_crash(self): diff -r e3994fcc21c3 -r 1806148d6ce8 goa/__init__.py --- a/goa/__init__.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,159 +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 . -"""cubicweb on google appengine - -""" -__docformat__ = "restructuredtext en" - - -try: - # WARNING: do not import the google's db module here since it will take - # precedence over our own db submodule - from google.appengine.api.datastore import Key, Get, Query - from google.appengine.api.datastore_errors import BadKeyError -except ImportError: - # not in google app environment - pass -else: - - import os - _SS = os.environ.get('SERVER_SOFTWARE') - if _SS is None: - MODE = 'test' - elif _SS.startswith('Dev'): - MODE = 'dev' - else: - MODE = 'prod' - - from cubicweb.server import SOURCE_TYPES - from cubicweb.goa.gaesource import GAESource - SOURCE_TYPES['gae'] = GAESource - - - def do_monkey_patch(): - - # monkey patch yams Bytes validator since it should take a bytes string with gae - # and not a StringIO - def check_bytes(eschema, value): - """check value is a bytes string""" - return isinstance(value, str) - from yams import constraints - constraints.BASE_CHECKERS['Bytes'] = check_bytes - - def rql_for_eid(eid): - return 'Any X WHERE X eid "%s"' % eid - from cubicweb import uilib - uilib.rql_for_eid = rql_for_eid - - def typed_eid(eid): - try: - return str(Key(eid)) - except BadKeyError: - raise ValueError(eid) - import cubicweb - cubicweb.typed_eid = typed_eid - - # XXX monkey patch cubicweb.schema.CubicWebSchema to have string eid with - # optional cardinality (since eid is set after the validation) - - import re - from yams import buildobjs as ybo - - def add_entity_type(self, edef): - edef.name = edef.name.encode() - assert re.match(r'[A-Z][A-Za-z0-9]*[a-z]+[0-9]*$', edef.name), repr(edef.name) - eschema = super(CubicWebSchema, self).add_entity_type(edef) - if not eschema.final: - # automatically add the eid relation to non final entity types - rdef = ybo.RelationDefinition(eschema.type, 'eid', 'Bytes', - cardinality='?1', uid=True) - self.add_relation_def(rdef) - rdef = ybo.RelationDefinition(eschema.type, 'identity', eschema.type) - self.add_relation_def(rdef) - self._eid_index[eschema.eid] = eschema - return eschema - - from cubicweb.schema import CubicWebSchema - CubicWebSchema.add_entity_type = add_entity_type - - - # don't reset vreg on repository set_schema - from cubicweb.server import repository - orig_set_schema = repository.Repository.set_schema - def set_schema(self, schema, resetvreg=True): - orig_set_schema(self, schema, False) - repository.Repository.set_schema = set_schema - # deactivate function ensuring relation cardinality consistency - repository.del_existing_rel_if_needed = lambda *args: None - - def get_cubes(self): - """return the list of top level cubes used by this instance""" - config = self.config - cubes = config['included-cubes'] + config['included-yams-cubes'] - return config.expand_cubes(cubes) - repository.Repository.get_cubes = get_cubes - - from rql import RQLHelper - RQLHelper.simplify = lambda x, r: None - - # activate entity caching on the server side - - def set_entity_cache(self, entity): - self.transaction_data.setdefault('_eid_cache', {})[entity.eid] = entity - - def entity_cache(self, eid): - return self.transaction_data['_eid_cache'][eid] - - def drop_entity_cache(self, eid=None): - if eid is None: - self.transaction_data['_eid_cache'] = {} - elif '_eid_cache' in self.transaction_data: - self.transaction_data['_eid_cache'].pop(eid, None) - - def datastore_get(self, key): - if isinstance(key, basestring): - key = Key(key) - try: - gentity = self.transaction_data['_key_cache'][key] - #self.critical('cached %s', gentity) - except KeyError: - gentity = Get(key) - #self.critical('Get %s', gentity) - self.transaction_data.setdefault('_key_cache', {})[key] = gentity - return gentity - - def clear_datastore_cache(self, key=None): - if key is None: - self.transaction_data['_key_cache'] = {} - else: - if isinstance(key, basestring): - key = Key(key) - self.transaction_data['_key_cache'].pop(key, None) - - from cubicweb.server.session import Session - Session.set_entity_cache = set_entity_cache - Session.entity_cache = entity_cache - Session.drop_entity_cache = drop_entity_cache - Session.datastore_get = datastore_get - Session.clear_datastore_cache = clear_datastore_cache - - from docutils.frontend import OptionParser - # avoid a call to expanduser which is not available under gae - def get_standard_config_files(self): - return self.standard_config_files - OptionParser.get_standard_config_files = get_standard_config_files diff -r e3994fcc21c3 -r 1806148d6ce8 goa/appobjects/__init__.py --- a/goa/appobjects/__init__.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +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 . diff -r e3994fcc21c3 -r 1806148d6ce8 goa/appobjects/components.py --- a/goa/appobjects/components.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +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 . -"""overrides some base views for cubicweb on google appengine""" - -__docformat__ = "restructuredtext en" - -from logilab.mtconverter import xml_escape - -from cubicweb import typed_eid -from cubicweb.selectors import one_line_rset, match_search_state, accept -from cubicweb.schema import display_name -from cubicweb.view import StartupView, EntityView -from cubicweb.web import Redirect -from cubicweb.web.views import vid_from_rset - -from google.appengine.api import mail - - -class SearchForAssociationView(EntityView): - """view called by the edition view when the user asks - to search for something to link to the edited eid - """ - id = 'search-associate' - - __select__ = one_line_rset() & match_search_state('linksearch') & accept - - def cell_call(self, row, col): - entity = self.rset.get_entity(0, 0) - role, eid, rtype, etype = self.req.search_state[1] - assert entity.eid == typed_eid(eid) - rset = entity.unrelated(rtype, etype, role, ordermethod='fetch_order') - vid = vid_from_rset(self.req, rset, self.schema) - self.w(u'
') - self.pagination(self.req, rset, w=self.w) - self.wview(vid, rset) - self.w(u'
') - - -class SchemaImageView(StartupView): - id = 'schemagraph' - binary = True - content_type = 'image/png' - def call(self): - """display global schema information""" - skipmeta = int(self.req.form.get('skipmeta', 1)) - if skipmeta: - url = self.build_url('data/schema.png') - else: - url = self.build_url('data/metaschema.png') - raise Redirect(url) - - -from cubicweb.web.views.baseviews import MetaDataView - -class GAEMetaDataView(MetaDataView): - show_eid = False - - -from cubicweb.web.views.startup import ManageView - -def entity_types_no_count(self, eschemas): - """return a list of formatted links to get a list of entities of - a each entity's types - """ - req = self.req - for eschema in eschemas: - if eschema.final or not (eschema.has_perm(req, 'read') or - eschema.has_local_role('read')): - continue - etype = eschema.type - label = display_name(req, etype, 'plural') - view = self.vreg.select('views', 'list', req, req.etype_rset(etype)) - url = view.url() - etypelink = u' %s' % (xml_escape(url), label) - if eschema.has_perm(req, 'add'): - yield (label, etypelink, self.add_entity_link(etype)) - -ManageView.entity_types = entity_types_no_count - - -from cubicweb.web.views.basecontrollers import SendMailController - -def sendmail(self, recipient, subject, body): - sender = '%s <%s>' % ( - self.req.user.dc_title() or self.config['sender-name'], - self.req.user.cw_adapt_to('IEmailable').get_email() or self.config['sender-addr']) - mail.send_mail(sender=sender, to=recipient, - subject=subject, body=body) - -SendMailController.sendmail = sendmail diff -r e3994fcc21c3 -r 1806148d6ce8 goa/appobjects/dbmgmt.py --- a/goa/appobjects/dbmgmt.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +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 . -"""special management views to manage repository content (initialization and -restoration). - -""" -__docformat__ = "restructuredtext en" - -from os.path import exists, join, abspath -from pickle import loads, dumps - -from logilab.common.decorators import cached -from logilab.mtconverter import xml_escape - -from cubicweb.selectors import none_rset, match_user_groups -from cubicweb.view import StartupView -from cubicweb.web import Redirect -from cubicweb.goa.dbinit import fix_entities, init_persistent_schema, insert_versions - -from google.appengine.api.datastore import Entity, Key, Get, Put, Delete -from google.appengine.api.datastore_types import Blob -from google.appengine.api.datastore_errors import EntityNotFoundError - - -def _get_status(name, create=True): - key = Key.from_path('EApplicationStatus', name) - try: - status = Get(key) - except EntityNotFoundError: - if create: - status = Entity('EApplicationStatus', name=name) - else: - status = None - return status - - -class AuthInfo(StartupView): - """special management view to get cookie values to give to laxctl commands - which are doing datastore administration requests - """ - id = 'authinfo' - __select__ = none_rset() & match_user_groups('managers') - - def call(self): - cookie = self.req.get_cookie() - values = [] - if self.config['use-google-auth']: - for param in ('ACSID', 'dev_appserver_login'): - morsel = cookie.get(param) - if morsel: - values.append('%s=%s' % (param, morsel.value)) - break - values.append('__session=%s' % cookie['__session'].value) - self.w(u"

pass this flag to the client: --cookie='%s'

" - % xml_escape('; '.join(values))) - - - -class ContentInit(StartupView): - """special management view to initialize content of a repository, - step by step to avoid depassing quotas - """ - id = 'contentinit' - __select__ = none_rset() & match_user_groups('managers') - - def server_session(self): - ssession = self.config.repo_session(self.req.cnx.sessionid) - ssession.set_pool() - return ssession - - def end_core_step(self, msg, status, stepid): - status['cpath'] = '' - status['stepid'] = stepid - Put(status) - self.msg(msg) - - def call(self): - status = _get_status('creation') - if status.get('finished'): - self.redirect('process already completed') - config = self.config - # execute cubicweb's post script - #mhandler.exec_event_script('post%s' % event) - # execute cubes'post script if any - paths = [p for p in config.cubes_path() + [config.apphome] - if exists(join(p, 'migration'))] - paths = [abspath(p) for p in (reversed(paths))] - cpath = status.get('cpath') - if cpath is None and status.get('stepid') is None: - init_persistent_schema(self.server_session(), self.schema) - self.end_core_step(u'inserted schema entities', status, 0) - return - if cpath == '' and status.get('stepid') == 0: - fix_entities(self.schema) - self.end_core_step(u'fixed bootstrap groups and users', status, 1) - return - if cpath == '' and status.get('stepid') == 1: - insert_versions(self.server_session(), self.config) - self.end_core_step(u'inserted software versions', status, None) - return - for i, path in enumerate(paths): - if not cpath or cpath == path: - self.info('running %s', path) - stepid = status.get('stepid') - context = status.get('context') - if context is not None: - context = loads(context) - else: - context = {} - stepid = self._migrhandler.exec_event_script( - 'postcreate', path, 'stepable_postcreate', stepid, context) - if stepid is None: # finished for this script - # reset script state - context = stepid = None - # next time, go to the next script - self.msg(u'finished postcreate for %s' % path) - try: - path = paths[i+1] - self.continue_link() - except IndexError: - status['finished'] = True - path = None - self.redirect('process completed') - else: - if context.get('stepidx'): - self.msg(u'created %s entities for step %s of %s' % ( - context['stepidx'], stepid, path)) - else: - self.msg(u'finished postcreate step %s for %s' % ( - stepid, path)) - context = Blob(dumps(context)) - self.continue_link() - status['context'] = context - status['stepid'] = stepid - status['cpath'] = path - break - else: - if not cpath: - # nothing to be done - status['finished'] = True - self.redirect('process completed') - else: - # Note the error: is expected by the laxctl command line tool, - # deal with this if internationalization is introduced - self.msg(u'error: strange creation state, can\'t find %s' - % cpath) - self.w(u'
click here to ' - 'delete all datastore content so process can be ' - 'reinitialized
' % xml_escape(self.req.base_url())) - Put(status) - - @property - @cached - def _migrhandler(self): - return self.config.migration_handler(self.schema, interactive=False, - cnx=self.req.cnx, - repo=self.config.repository()) - - def msg(self, msg): - self.w(u'
%s
' % xml_escape(msg)) - def redirect(self, msg): - raise Redirect(self.req.build_url('', msg)) - def continue_link(self): - self.w(u'continue
' % xml_escape(self.req.url())) - - -class ContentClear(StartupView): - id = 'contentclear' - __select__ = none_rset() & match_user_groups('managers') - skip_etypes = ('CWGroup', 'CWUser') - - def call(self): - # XXX should use unsafe execute with all hooks deactivated - # XXX step by catching datastore errors? - for eschema in self.schema.entities(): - if eschema.final or eschema in self.skip_etypes: - continue - self.req.execute('DELETE %s X' % eschema) - self.w(u'deleted all %s entities
' % eschema) - status = _get_status('creation', create=False) - if status: - Delete(status) - self.w(u'done
') - self.w(u'click here to start the data ' - 'initialization process
' % self.req.base_url()) diff -r e3994fcc21c3 -r 1806148d6ce8 goa/appobjects/gauthservice.py --- a/goa/appobjects/gauthservice.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +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 . -"""authentication using google authentication service - -""" -__docformat__ = "restructuredtext en" - -from cubicweb.web.views.basecomponents import UserLink -from cubicweb.web.views.actions import LogoutAction - -from google.appengine.api import users - - -class GACWUserLink(UserLink): - - def anon_user_link(self): - self.w(self.req._('anonymous')) - self.w(u' [%s]' - % (users.create_login_url(self.req.url()), self.req._('login'))) - -class GAELogoutAction(LogoutAction): - - def url(self): - return users.create_logout_url(self.req.build_url('logout') ) - -def registration_callback(vreg): - if hasattr(vreg.config, 'has_resource'): - vreg.register(GACWUserLink, clear=True) - vreg.register(GAELogoutAction, clear=True) diff -r e3994fcc21c3 -r 1806148d6ce8 goa/appobjects/sessions.py --- a/goa/appobjects/sessions.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,291 +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 . -"""persistent sessions stored in big table - - -XXX TODO: -* cleanup persistent session -* use user as ancestor? -""" -__docformat__ = "restructuredtext en" - -from pickle import loads, dumps -from time import localtime, strftime - -from logilab.common.decorators import cached, clear_cache - -from cubicweb import BadConnectionId -from cubicweb.dbapi import Connection, ConnectionProperties, repo_connect -from cubicweb.selectors import none_rset, match_user_groups -from cubicweb.server.session import Session -from cubicweb.web import InvalidSession -from cubicweb.web.application import AbstractSessionManager -from cubicweb.web.application import AbstractAuthenticationManager - -from google.appengine.api.datastore import Key, Entity, Get, Put, Delete, Query -from google.appengine.api.datastore_errors import EntityNotFoundError -from google.appengine.api.datastore_types import Blob - -try: - del Connection.__del__ -except AttributeError: - pass # already deleted - - -class GAEAuthenticationManager(AbstractAuthenticationManager): - """authenticate user associated to a request and check session validity, - using google authentication service - """ - - def __init__(self, *args, **kwargs): - super(GAEAuthenticationManager, self).__init__(*args, **kwargs) - self._repo = self.config.repository(vreg=self.vreg) - - def authenticate(self, req, _login=None, _password=None): - """authenticate user and return an established connection for this user - - :raise ExplicitLogin: if authentication is required (no authentication - info found or wrong user/password) - """ - if _login is not None: - login, password = _login, _password - else: - login, password = req.get_authorization() - # remove possibly cached cursor coming from closed connection - clear_cache(req, 'cursor') - cnxprops = ConnectionProperties(self.vreg.config.repo_method, - close=False, log=False) - cnx = repo_connect(self._repo, login, password=password, cnxprops=cnxprops) - self._init_cnx(cnx, login, password) - # associate the connection to the current request - req.set_connection(cnx) - return cnx - - def _init_cnx(self, cnx, login, password): - cnx.anonymous_connection = self.config.is_anonymous_user(login) - cnx.vreg = self.vreg - cnx.login = login - cnx.password = password - - -class GAEPersistentSessionManager(AbstractSessionManager): - """manage session data associated to a session identifier""" - - def __init__(self, vreg, *args, **kwargs): - super(GAEPersistentSessionManager, self).__init__(vreg, *args, **kwargs) - self._repo = self.config.repository(vreg=vreg) - - def get_session(self, req, sessionid): - """return existing session for the given session identifier""" - # search a record for the given session - key = Key.from_path('CubicWebSession', 'key_' + sessionid, parent=None) - try: - record = Get(key) - except EntityNotFoundError: - raise InvalidSession() - repo = self._repo - if self.has_expired(record): - repo._sessions.pop(sessionid, None) - Delete(record) - raise InvalidSession() - # associate it with a repository session - try: - reposession = repo._get_session(sessionid) - user = reposession.user - # touch session to avoid closing our own session when sessions are - # cleaned (touch is done on commit/rollback on the server side, too - # late in that case) - reposession._touch() - except BadConnectionId: - # can't found session in the repository, this probably mean the - # session is not yet initialized on this server, hijack the repo - # to create it - # use an internal connection - ssession = repo.internal_session() - # try to get a user object - try: - user = repo.authenticate_user(ssession, record['login'], - record['password']) - finally: - ssession.close() - reposession = Session(user, self._repo, _id=sessionid) - self._repo._sessions[sessionid] = reposession - cnx = Connection(self._repo, sessionid) - return self._get_proxy(req, record, cnx, user) - - def open_session(self, req): - """open and return a new session for the given request""" - cnx = self.authmanager.authenticate(req) - # avoid rebuilding a user - user = self._repo._get_session(cnx.sessionid).user - # build persistent record for session data - record = Entity('CubicWebSession', name='key_' + cnx.sessionid) - record['login'] = cnx.login - record['password'] = cnx.password - record['anonymous_connection'] = cnx.anonymous_connection - Put(record) - return self._get_proxy(req, record, cnx, user) - - def close_session(self, proxy): - """close session on logout or on invalid session detected (expired out, - corrupted...) - """ - proxy.close() - - def current_sessions(self): - for record in Query('CubicWebSession').Run(): - yield ConnectionProxy(record) - - def _get_proxy(self, req, record, cnx, user): - proxy = ConnectionProxy(record, cnx, user) - user.req = req - req.set_connection(proxy, user) - return proxy - - -class ConnectionProxy(object): - - def __init__(self, record, cnx=None, user=None): - self.__record = record - self.__cnx = cnx - self.__user = user - self.__data = None - self.__is_dirty = False - self.sessionid = record.key().name()[4:] # remove 'key_' prefix - - def __repr__(self): - sstr = '') - self.w(u'%s web sessions closed
\n' % nbclosed) - # clean repository sessions - repo = self.config.repository(vreg=self.vreg) - nbclosed = repo.clean_sessions() - self.w(u'%s repository sessions closed
\n' % nbclosed) - self.w(u'%s remaining sessions
\n' % remaining) - self.w(u'') - - -def registration_callback(vreg): - vreg.register(SessionsCleaner) - vreg.register(GAEAuthenticationManager, clear=True) - vreg.register(GAEPersistentSessionManager, clear=True) diff -r e3994fcc21c3 -r 1806148d6ce8 goa/bin/laxctl --- a/goa/bin/laxctl Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -#!/usr/bin/env python - -import sys -import os.path as osp - -APPLROOT = osp.abspath(osp.join(osp.dirname(osp.abspath(__file__)), '..')) -if APPLROOT not in sys.path: - sys.path.insert(0, APPLROOT) -CUBES_DIR = osp.join(APPLROOT, 'cw-cubes') -if CUBES_DIR not in sys.path: - sys.path.insert(1, CUBES_DIR) - -try: - import custom -except ImportError, exc: - print exc - sys.exit(2) - -from tools.laxctl import run -run() diff -r e3994fcc21c3 -r 1806148d6ce8 goa/db.py --- a/goa/db.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,469 +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 . -"""provide replacement classes for gae db module, so that a gae model can be -used as base for a cubicweb application by simply replacing :: - - from google.appengine.ext import db - -by - - from cubicweb.goa import db - -The db.model api should be fully featured by replacement classes, with the -following differences: - -* all methods returning `google.appengine.ext.db.Model` instance(s) will return - `cubicweb.goa.db.Model` instance instead (though you should see almost no - difference since those instances have the same api) - -* class methods returning model instance take a `req` as first argument, unless - they are called through an instance, representing the current request - (accessible through `self.req` on almost all objects) - -* XXX no instance._set attributes, use instance.reverse_ - instead -* XXX reference property always return a list of objects, not the instance -* XXX name/collection_name argument of properties constructor are ignored -* XXX ListProperty - -""" -__docformat__ = "restructuredtext en" - -from copy import deepcopy - -from logilab.common.decorators import cached, iclassmethod - -from cubicweb import Binary, entities -from cubicweb.req import RequestSessionBase -from cubicweb.rset import ResultSet -from cubicweb.entity import metaentity -from cubicweb.server.utils import crypt_password -from cubicweb.goa import MODE -from cubicweb.goa.dbinit import init_relations - -from google.appengine.api.datastore import Get, Put, Key, Entity, Query -from google.appengine.api.datastore import NormalizeAndTypeCheck, RunInTransaction -from google.appengine.api.datastore_types import Text, Blob -from google.appengine.api.datastore_errors import BadKeyError - -# XXX remove this dependancy -from google.appengine.ext import db - - -def rset_from_objs(req, objs, attrs=('eid',), rql=None, args=None): - """return a ResultSet instance for list of objects""" - if objs is None: - objs = () - elif isinstance(objs, Entity): - objs = (objs,) - if rql is None: - rql = 'Any X' - rows = [] - description = [] - rset = ResultSet(rows, rql, args, description=description) - vreg = req.vreg - for i, obj in enumerate(objs): - line = [] - linedescr = [] - eschema = vreg.schema.eschema(obj.kind()) - for j, attr in enumerate(attrs): - if attr == 'eid': - value = obj.key() - obj.row, obj.col = i, j - descr = eschema.type - value = str(value) - else: - value = obj[attr] - descr = str(eschema.destination(attr)) - line.append(value) - linedescr.append(descr) - rows.append(line) - description.append(linedescr) - for j, attr in enumerate(attrs): - if attr == 'eid': - entity = vreg.etype_class(eschema.type)(req, rset, i, j) - rset._get_entity_cache_ = {(i, j): entity} - rset.rowcount = len(rows) - rset.req = req - return rset - - -def needrequest(wrapped): - def wrapper(cls, *args, **kwargs): - req = kwargs.pop('req', None) - if req is None and args and isinstance(args[0], RequestSessionBase): - args = list(args) - req = args.pop(0) - if req is None: - req = getattr(cls, 'req', None) - if req is None: - raise Exception('either call this method on an instance or ' - 'specify the req argument') - return wrapped(cls, req, *args, **kwargs) - return iclassmethod(wrapper) - - -class gaedbmetaentity(metaentity): - """metaclass for goa.db.Model classes: filter entity / db model part, - put aside the db model part for later creation of db model class. - """ - def __new__(mcs, name, bases, classdict): - if not 'id' in classdict: - classdict['id'] = name - entitycls = super(gaedbmetaentity, mcs).__new__(mcs, name, bases, classdict) - return entitycls - - -TEST_MODELS = {} - -def extract_dbmodel(entitycls): - if MODE == 'test' and entitycls in TEST_MODELS: - dbclassdict = TEST_MODELS[entitycls] - else: - dbclassdict = {} - for attr, value in entitycls.__dict__.items(): - if isinstance(value, db.Property) or isinstance(value, ReferencePropertyStub): - dbclassdict[attr] = value - # don't remove attr from entitycls, this make tests fail, and it's anyway - # overwritten by descriptor at class initialization time - #delattr(entitycls, attr) - if MODE == 'test': - TEST_MODELS[entitycls] = dbclassdict - dbclassdict = deepcopy(dbclassdict) - for propname, prop in TEST_MODELS[entitycls].iteritems(): - if getattr(prop, 'reference_class', None) is db._SELF_REFERENCE: - dbclassdict[propname].reference_class = db._SELF_REFERENCE - return dbclassdict - - -class Model(entities.AnyEntity): - id = 'Any' - __metaclass__ = gaedbmetaentity - - row = col = 0 - - @classmethod - def __initialize__(cls): - super(Model, cls).__initialize__() - cls._attributes = frozenset(rschema for rschema in cls.e_schema.subject_relations() - if rschema.final) - - def __init__(self, *args, **kwargs): - # db.Model prototype: - # __init__(self, parent=None, key_name=None, **kw) - # - # Entity prototype: - # __init__(self, req, rset, row=None, col=0) - if args and isinstance(args[0], RequestSessionBase) or 'req' in kwargs: - super(Model, self).__init__(*args, **kwargs) - self._gaeinitargs = None - else: - super(Model, self).__init__(None, None) - # if Model instances are given in kwargs, turn them into db model - for key, val in kwargs.iteritems(): - if key in self.e_schema.subject_relations() and not self.e_schema.schema[key].final: - if isinstance(kwargs, (list, tuple)): - val = [isinstance(x, Model) and x._dbmodel or x for x in val] - elif isinstance(val, Model): - val = val._dbmodel - kwargs[key] = val.key() - self._gaeinitargs = (args, kwargs) - - def __repr__(self): - return '' % ( - self.e_schema, self.eid, self.keys(), id(self)) - - def _cubicweb_to_datastore(self, attr, value): - attr = attr[2:] # remove 's_' / 'o_' prefix - if attr in self._attributes: - tschema = self.e_schema.destination(attr) - if tschema == 'String': - if len(value) > 500: - value = Text(value) - elif tschema == 'Password': - # if value is a Binary instance, this mean we got it - # from a query result and so it is already encrypted - if isinstance(value, Binary): - value = value.getvalue() - else: - value = crypt_password(value) - elif tschema == 'Bytes': - if isinstance(value, Binary): - value = value.getvalue() - value = Blob(value) - else: - value = Key(value) - return value - - def _to_gae_dict(self, convert=True): - gaedict = {} - for attr, value in self.iteritems(): - attr = 's_' + attr - if value is not None and convert: - value = self._cubicweb_to_datastore(attr, value) - gaedict[attr] = value - return gaedict - - def to_gae_model(self): - dbmodel = self._dbmodel - dbmodel.update(self._to_gae_dict()) - return dbmodel - - @property - @cached - def _dbmodel(self): - if self.has_eid(): - assert self._gaeinitargs is None - try: - return self.req.datastore_get(self.eid) - except AttributeError: # self.req is not a server session - return Get(self.eid) - self._cw_set_defaults() - values = self._to_gae_dict(convert=False) - parent = key_name = _app = None - if self._gaeinitargs is not None: - args, kwargs = self._gaeinitargs - args = list(args) - if args: - parent = args.pop(0) - if args: - key_name = args.pop(0) - if args: - _app = args.pop(0) - assert not args - if 'parent' in kwargs: - assert parent is None - parent = kwargs.pop('parent') - if 'key_name' in kwargs: - assert key_name is None - key_name = kwargs.pop('key_name') - if '_app' in kwargs: - assert _app is None - _app = kwargs.pop('_app') - - for key, value in kwargs.iteritems(): - if key in self._attributes: - values['s_'+key] = value - else: - kwargs = None - if key_name is None: - key_name = self.db_key_name() - if key_name is not None: - key_name = 'key_' + key_name - for key, value in values.iteritems(): - if value is None: - continue - values[key] = self._cubicweb_to_datastore(key, value) - entity = Entity(self.id, parent, _app, key_name) - entity.update(values) - init_relations(entity, self.e_schema) - return entity - - def db_key_name(self): - """override this method to control datastore key name that should be - used at entity creation. - - Note that if this function return something else than None, the returned - value will be prefixed by 'key_' to build the actual key name. - """ - return None - - def metainformation(self): - return {'type': self.id, 'source': {'uri': 'system'}, 'extid': None} - - def view(self, vid, __registry='views', **kwargs): - """shortcut to apply a view on this entity""" - return self.vreg[__registry].render(vid, self.req, rset=self.rset, - row=self.row, col=self.col, **kwargs) - - @classmethod - def _rest_attr_info(cls): - mainattr, needcheck = super(Model, cls)._rest_attr_info() - if needcheck: - return 'eid', False - return mainattr, needcheck - - def get_value(self, name): - try: - value = self[name] - except KeyError: - if not self.has_eid(): - return None - value = self._dbmodel.get('s_'+name) - if value is not None: - if isinstance(value, Text): - value = unicode(value) - elif isinstance(value, Blob): - value = Binary(str(value)) - self[name] = value - return value - - def has_eid(self): - if self.eid is None: - return False - try: - Key(self.eid) - return True - except BadKeyError: - return False - - def complete(self, skip_bytes=True): - pass - - def unrelated(self, rtype, targettype, role='subject', limit=None, - ordermethod=None): - # XXX dumb implementation - if limit is not None: - objs = Query(str(targettype)).Get(limit) - else: - objs = Query(str(targettype)).Run() - return rset_from_objs(self.req, objs, ('eid',), - 'Any X WHERE X is %s' % targettype) - - def key(self): - return Key(self.eid) - - def put(self, req=None): - if req is not None and self.req is None: - self.req = req - dbmodel = self.to_gae_model() - key = Put(dbmodel) - self.eid = str(key) - if self.req is not None and self.rset is None: - self.rset = rset_from_objs(self.req, dbmodel, ('eid',), - 'Any X WHERE X eid %(x)s', {'x': self.eid}) - self.row = self.col = 0 - return dbmodel - - @needrequest - def get(cls, req, keys): - # if check if this is a dict.key call - if isinstance(cls, Model) and keys in cls._attributes: - return super(Model, cls).get(keys) - rset = rset_from_objs(req, Get(keys), ('eid',), - 'Any X WHERE X eid IN %(x)s', {'x': keys}) - return list(rset.entities()) - - @needrequest - def get_by_id(cls, req, ids, parent=None): - if isinstance(parent, Model): - parent = parent.key() - ids, multiple = NormalizeAndTypeCheck(ids, (int, long)) - keys = [Key.from_path(cls.kind(), id, parent=parent) - for id in ids] - rset = rset_from_objs(req, Get(keys)) - return list(rset.entities()) - - @classmethod - def get_by_key_name(cls, req, key_names, parent=None): - if isinstance(parent, Model): - parent = parent.key() - key_names, multiple = NormalizeAndTypeCheck(key_names, basestring) - keys = [Key.from_path(cls.kind(), name, parent=parent) - for name in key_names] - rset = rset_from_objs(req, Get(keys)) - return list(rset.entities()) - - @classmethod - def get_or_insert(cls, req, key_name, **kwds): - def txn(): - entity = cls.get_by_key_name(key_name, parent=kwds.get('parent')) - if entity is None: - entity = cls(key_name=key_name, **kwds) - entity.put() - return entity - return RunInTransaction(txn) - - @classmethod - def all(cls, req): - rset = rset_from_objs(req, Query(cls.id).Run()) - return list(rset.entities()) - - @classmethod - def gql(cls, req, query_string, *args, **kwds): - raise NotImplementedError('use rql') - - @classmethod - def kind(cls): - return cls.id - - @classmethod - def properties(cls): - raise NotImplementedError('use eschema') - - def dynamic_properties(self): - raise NotImplementedError('use eschema') - - def cw_is_saved(self): - return self.has_eid() - - def parent(self): - parent = self._dbmodel.parent() - if not parent is None: - rset = rset_from_objs(self.req, (parent,), ('eid',), - 'Any X WHERE X eid %(x)s', {'x': parent.key()}) - parent = rset.get_entity(0, 0) - return parent - - def parent_key(self): - return self.parent().key() - - def to_xml(self): - return self._dbmodel.ToXml() - -# hijack AnyEntity class -entities.AnyEntity = Model - -BooleanProperty = db.BooleanProperty -URLProperty = db.URLProperty -DateProperty = db.DateProperty -DateTimeProperty = db.DateTimeProperty -TimeProperty = db.TimeProperty -StringProperty = db.StringProperty -TextProperty = db.TextProperty -BlobProperty = db.BlobProperty -IntegerProperty = db.IntegerProperty -FloatProperty = db.FloatProperty -ListProperty = db.ListProperty -SelfReferenceProperty = db.SelfReferenceProperty -UserProperty = db.UserProperty - - -class ReferencePropertyStub(object): - def __init__(self, cls, args, kwargs): - self.cls = cls - self.args = args - self.kwargs = kwargs - self.required = False - self.__dict__.update(kwargs) - self.creation_counter = db.Property.creation_counter - db.Property.creation_counter += 1 - - @property - def data_type(self): - class FakeDataType(object): - @staticmethod - def kind(): - return self.cls.__name__ - return FakeDataType - -def ReferenceProperty(cls, *args, **kwargs): - if issubclass(cls, db.Model): - cls = db.class_for_kind(cls.__name__) - return db.ReferenceProperty(cls, *args, **kwargs) - return ReferencePropertyStub(cls, args, kwargs) diff -r e3994fcc21c3 -r 1806148d6ce8 goa/dbinit.py --- a/goa/dbinit.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +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 . -"""some utility functions for datastore initialization. - -""" -__docformat__ = "restructuredtext en" - -from google.appengine.api.datastore import Key, Entity, Put, Get, Query -from google.appengine.api import datastore_errors - -_GROUP_CACHE = {} # XXX use memcache - -def _get_group(groupname): - try: - return _GROUP_CACHE[groupname] - except KeyError: - key = Key.from_path('CWGroup', 'key_' + groupname, parent=None) - try: - group = Get(key) - except datastore_errors.EntityNotFoundError: - raise Exception('can\'t find required group %s, is your instance ' - 'correctly initialized (eg did you run the ' - 'initialization script) ?' % groupname) - _GROUP_CACHE[groupname] = group - return group - - -def create_user(login, password, groups): - """create a cubicweb user""" - from cubicweb.server.utils import crypt_password - user = Entity('CWUser', name=login) - user['s_login'] = unicode(login) - user['s_upassword'] = crypt_password(password) - set_user_groups(user, groups) - Put(user) - return user - -def create_groups(): - """create initial cubicweb groups""" - for groupname in ('managers', 'users', 'guests'): - group = Entity('CWGroup', name='key_' + groupname) - group['s_name'] = unicode(groupname) - Put(group) - _GROUP_CACHE[groupname] = group - -def set_user_groups(user, groups): - """set user in the given groups (as string). The given user entity - (datastore.Entity) is not putted back to the repository, this is the caller - responsability. - """ - groups = [_get_group(g) for g in groups] - user['s_in_group'] = [g.key() for g in groups] or None - for group in groups: - try: - group['o_in_group'].append(user.key()) - except (KeyError, AttributeError): - group['o_in_group'] = [user.key()] - Put(group) - -def init_relations(gaeentity, eschema): - """set None for every subject relations which is not yet defined""" - for rschema in eschema.subject_relations(): - if rschema in ('identity', 'has_text'): - continue - dsrelation = 's_' + rschema.type - if not dsrelation in gaeentity: - gaeentity[dsrelation] = None - for rschema in eschema.object_relations(): - if rschema == 'identity': - continue - dsrelation = 'o_' + rschema.type - if not dsrelation in gaeentity: - gaeentity[dsrelation] = None - -def fix_entities(schema): - for etype in ('CWUser', 'CWGroup'): - eschema = schema.eschema(etype) - for gaeentity in Query(etype).Run(): - init_relations(gaeentity, eschema) - # XXX o_is on CWEType entity - gaeentity['s_is'] = Key.from_path('CWEType', 'key_' + etype, parent=None) - Put(gaeentity) - -def init_persistent_schema(ssession, schema): - execute = ssession.execute - rql = ('INSERT CWEType X: X name %(name)s, X description %(descr)s,' - 'X final FALSE') - eschema = schema.eschema('CWEType') - execute(rql, {'name': u'CWEType', 'descr': unicode(eschema.description)}) - for eschema in schema.entities(): - if eschema.final or eschema == 'CWEType': - continue - execute(rql, {'name': unicode(eschema), - 'descr': unicode(eschema.description)}) - -def insert_versions(ssession, config): - execute = ssession.execute - # insert versions - execute('INSERT CWProperty X: X pkey %(pk)s, X value%(v)s', - {'pk': u'system.version.cubicweb', - 'v': unicode(config.cubicweb_version())}) - for cube in config.cubes(): - execute('INSERT CWProperty X: X pkey %(pk)s, X value%(v)s', - {'pk': u'system.version.%s' % cube, - 'v': unicode(config.cube_version(cube))}) diff -r e3994fcc21c3 -r 1806148d6ce8 goa/dbmyams.py --- a/goa/dbmyams.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,223 +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 . -"""extends yams to be able to load google appengine's schemas - -MISSING FEATURES: - - ListProperty, StringList, EmailProperty, etc. (XXX) - - ReferenceProperty.verbose_name, collection_name, etc. (XXX) - -XXX proprify this knowing we'll use goa.db -""" - -from os.path import join -from datetime import datetime, date, time - -from google.appengine.ext import db -from google.appengine.api import datastore_types - -from yams.buildobjs import (String, Int, Float, Boolean, Date, Time, Datetime, - Bytes, SubjectRelation) -from yams.buildobjs import metadefinition, EntityType - -from cubicweb.schema import CubicWebSchemaLoader -from cubicweb.goa import db as goadb - -# db.Model -> yams ############################################################ - -DBM2Y_TYPESMAP = { - basestring: String, - datastore_types.Text: String, - int: Int, - float: Float, - bool: Boolean, - time: Time, - date: Date, - datetime: Datetime, - datastore_types.Blob: Bytes, - } - - -def dbm2y_default_factory(prop, **kwargs): - """just wraps the default types map to set - basic constraints like `required`, `default`, etc. - """ - yamstype = DBM2Y_TYPESMAP[prop.data_type] - if 'default' not in kwargs: - default = prop.default_value() - if default is not None: - kwargs['default'] = default - if prop.required: - kwargs['required'] = True - return yamstype(**kwargs) - -def dbm2y_string_factory(prop): - """like dbm2y_default_factory but also deals with `maxsize` and `vocabulary`""" - kwargs = {} - if prop.data_type is basestring: - kwargs['maxsize'] = 500 - if prop.choices is not None: - kwargs['vocabulary'] = prop.choices - return dbm2y_default_factory(prop, **kwargs) - -def dbm2y_date_factory(prop): - """like dbm2y_default_factory but also deals with today / now definition""" - kwargs = {} - if prop.auto_now_add: - if prop.data_type is datetime: - kwargs['default'] = 'now' - else: - kwargs['default'] = 'today' - # XXX no equivalent to Django's `auto_now` - return dbm2y_default_factory(prop, **kwargs) - - -def dbm2y_relation_factory(etype, prop, multiple=False): - """called if `prop` is a `db.ReferenceProperty`""" - if multiple: - cardinality = '**' - elif prop.required: - cardinality = '1*' - else: - cardinality = '?*' - # XXX deal with potential kwargs of ReferenceProperty.__init__() - try: - return SubjectRelation(prop.data_type.kind(), cardinality=cardinality) - except AttributeError, ex: - # hack, data_type is still _SELF_REFERENCE_MARKER - return SubjectRelation(etype, cardinality=cardinality) - - -DBM2Y_FACTORY = { - basestring: dbm2y_string_factory, - datastore_types.Text: dbm2y_string_factory, - int: dbm2y_default_factory, - float: dbm2y_default_factory, - bool: dbm2y_default_factory, - time: dbm2y_date_factory, - date: dbm2y_date_factory, - datetime: dbm2y_date_factory, - datastore_types.Blob: dbm2y_default_factory, - } - - -class GaeSchemaLoader(CubicWebSchemaLoader): - """Google appengine schema loader class""" - def __init__(self, *args, **kwargs): - self.use_gauthservice = kwargs.pop('use_gauthservice', False) - super(GaeSchemaLoader, self).__init__(*args, **kwargs) - self.defined = {} - self.created = [] - self.loaded_files = [] - self._instantiate_handlers() - - def finalize(self, register_base_types=False): - return self._build_schema('google-appengine', register_base_types) - - def load_dbmodel(self, name, props): - clsdict = {} - ordered_props = sorted(props.items(), - key=lambda x: x[1].creation_counter) - for pname, prop in ordered_props: - if isinstance(prop, db.ListProperty): - if not issubclass(prop.item_type, db.Model): - self.error('ignoring list property with %s item type' - % prop.item_type) - continue - rdef = dbm2y_relation_factory(name, prop, multiple=True) - else: - try: - if isinstance(prop, (db.ReferenceProperty, - goadb.ReferencePropertyStub)): - rdef = dbm2y_relation_factory(name, prop) - else: - rdef = DBM2Y_FACTORY[prop.data_type](prop) - except KeyError, ex: - import traceback - traceback.print_exc() - self.error('ignoring property %s (keyerror on %s)' % (pname, ex)) - continue - rdef.creation_rank = prop.creation_counter - clsdict[pname] = rdef - edef = metadefinition(name, (EntityType,), clsdict) - self.add_definition(self, edef()) - - def error(self, msg): - print 'ERROR:', msg - - def import_yams_schema(self, ertype, schemamod): - erdef = self.pyreader.import_erschema(ertype, schemamod) - - def import_yams_cube_schema(self, templpath): - for filepath in self.get_schema_files(templpath): - self.handle_file(filepath) - - @property - def pyreader(self): - return self._live_handlers['.py'] - -import os -from cubicweb import CW_SOFTWARE_ROOT - -def load_schema(config, schemaclasses=None, extrahook=None): - """high level method to load all the schema for a lax instance""" - # IMPORTANT NOTE: dbmodel schemas must be imported **BEFORE** - # the loader is instantiated because this is where the dbmodels - # are registered in the yams schema - for compname in config['included-cubes']: - __import__('%s.schema' % compname) - loader = GaeSchemaLoader(use_gauthservice=config['use-google-auth'], db=db) - if schemaclasses is not None: - for cls in schemaclasses: - loader.load_dbmodel(cls.__name__, goadb.extract_dbmodel(cls)) - elif config['schema-type'] == 'dbmodel': - import schema as appschema - for obj in vars(appschema).values(): - if isinstance(obj, type) and issubclass(obj, goadb.Model) and obj.__module__ == appschema.__name__: - loader.load_dbmodel(obj.__name__, goadb.extract_dbmodel(obj)) - for erschema in ('CWGroup', 'CWEType', 'CWRType', 'RQLExpression', - 'is_', 'is_instance_of', - 'read_permission', 'add_permission', - 'delete_permission', 'update_permission'): - loader.import_yams_schema(erschema, 'bootstrap') - loader.handle_file(join(CW_SOFTWARE_ROOT, 'schemas', 'base.py')) - cubes = config['included-yams-cubes'] - for cube in reversed(config.expand_cubes(cubes)): - config.info('loading cube %s', cube) - loader.import_yams_cube_schema(config.cube_dir(cube)) - if config['schema-type'] == 'yams': - loader.import_yams_cube_schema('.') - if extrahook is not None: - extrahook(loader) - if config['use-google-auth']: - loader.defined['CWUser'].remove_relation('upassword') - loader.defined['CWUser'].permissions['add'] = () - loader.defined['CWUser'].permissions['delete'] = () - for etype in ('CWGroup', 'RQLExpression'): - read_perm_rel = loader.defined[etype].get_relations('read_permission').next() - read_perm_rel.cardinality = '**' - # XXX not yet ready for CWUser workflow - loader.defined['CWUser'].remove_relation('in_state') - loader.defined['CWUser'].remove_relation('wf_info_for') - # remove RQLConstraint('NOT O name "owners"') on CWUser in_group CWGroup - # since "owners" group is not persistent with gae - loader.defined['CWUser'].get_relations('in_group').next().constraints = [] - # return the full schema including the cubes' schema - for ertype in loader.defined.values(): - if getattr(ertype, 'inlined', False): - ertype.inlined = False - return loader.finalize() diff -r e3994fcc21c3 -r 1806148d6ce8 goa/doc/FAQ.en.txt --- a/goa/doc/FAQ.en.txt Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -============================== -LAX Frequently Asked Questions -============================== - -[WRITE ME] \ No newline at end of file diff -r e3994fcc21c3 -r 1806148d6ce8 goa/doc/README_LAX.fr.txt --- a/goa/doc/README_LAX.fr.txt Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -Qu'est-ce que ``LAX`` ? -======================= - -``LAX`` (Logilab Application engine eXtension) est un framework -d'application web qui facilite les développements faits pour -``Google AppEngine``. - -``LAX`` est un portage de la partie web de la plate-forme -applicative développée par Logilab depuis 2001. Cette plate-forme -publie des données que la partie stockage tire de bases SQL, -d'annuaires LDAP et de systèmes de gestion de version. Depuis mai -2008, elle fonctionne sur le "datastore" de ``Google AppEngine``. - -``LAX`` est pour le moment en version alpha. - -Django/GAE vs. LAX/GAE -======================= - -NotImplementedError() - - -Téléchargement des sources -========================== - -- Les sources de ``Google AppEngine`` peuvent être obtenues à l'adresse - suivante : http://code.google.com/appengine/downloads.html - -- Les sources de ``LAX`` se trouvent à l'adresse suivante : - http://lax.logilab.org/ - - -Installation -============ - -Les sources de ``Google AppEngine`` doivent être décompressées et le -répertoire `google` qui s'y trouve doit être accessible par la variable -d'environnement ``PYTHONPATH``. Correctement définir le ``PYTHONPATH`` -n'est pas nécessaire pour le lancement de l'application elle-même mais -pour l'utilisation des scripts fournis par ``LAX`` ou pour l'exécution -des tests unitaires. - -Une fois décompactée, l'archive ``lax-0.1.0-alpha.tar.gz``, on obtient -l'arborescence suivante:: - - . - |-- app.yaml - |-- custom.py - |-- data - |-- cubicweb/ - |-- i18n/ - |-- logilab/ - |-- main.py - |-- mx/ - |-- rql/ - |-- schema.py - |-- simplejson/ - |-- tools/ - | |-- generate_schema_img.py - | `-- i18ncompile.py - |-- views.py - |-- yams/ - `-- yapps/ - - -On retrouve le squelette d'une application web de ``Google AppEngine`` -(fichiers ``app.yaml``, ``main.py``en particulier) avec les dépendances -supplémentaires nécessaires à l'utilisation du framework ``LAX`` - - -Lancement de l'application de base -================================== - -python /path/to/google_appengine/dev_appserver.py /path/to/lax - - diff -r e3994fcc21c3 -r 1806148d6ce8 goa/doc/devmanual_fr/advanced_notes.txt --- a/goa/doc/devmanual_fr/advanced_notes.txt Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ - -La différence entre la classe `AppRsetObject` et la classe `AppObject` est que -les instances de la premières sont séléctionnées pour une requête et un "result -set" et alors que les secondes ne sont séléctionnées qu'en fonction de leur -identifiant. diff -r e3994fcc21c3 -r 1806148d6ce8 goa/doc/devmanual_fr/archi_globale.dia Binary file goa/doc/devmanual_fr/archi_globale.dia has changed diff -r e3994fcc21c3 -r 1806148d6ce8 goa/doc/devmanual_fr/archi_globale.png Binary file goa/doc/devmanual_fr/archi_globale.png has changed diff -r e3994fcc21c3 -r 1806148d6ce8 goa/doc/devmanual_fr/chap_autres_composants_ui.txt --- a/goa/doc/devmanual_fr/chap_autres_composants_ui.txt Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -Autres composants de l'interface web -==================================== - -Actions -------- -XXXFILLME - -Component, VComponent ---------------------- -XXXFILLME - -CWProperty ---------- -XXXFILLME diff -r e3994fcc21c3 -r 1806148d6ce8 goa/doc/devmanual_fr/chap_bases_framework_erudi.txt --- a/goa/doc/devmanual_fr/chap_bases_framework_erudi.txt Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,226 +0,0 @@ -Fondements du framework CubicWeb -============================= - -Le moteur web d'cubicweb consiste en quelques classes gérant un ensemble d'objets -chargés dynamiquement au lancement d'cubicweb. Ce sont ces objets dynamiques, issus -du modèle ou de la librairie, qui construisent le site web final. Les différents -composants dynamiques sont par exemple : - -* coté client et serveur - - - les définitions d'entités, contenant la logique permettant la manipulation des - données de l'application - -* coté client - - - les *vues* , ou encore plus spécifiquement - - - les boites - - l'en-tête et le pied de page - - les formulaires - - les gabarits de pages - - - les *actions* - - les *controleurs* - -* coté serveur - - - les crochets de notification - - les vues de notification - -Les différents composants du moteur sont : - -* un frontal web (seul twisted disponible pour le moment), transparent du point - de vue des objets dynamiques -* un objet encapsulant la configuration -* un `vregistry` (`cubicweb.cwvreg`) contenant les objets chargés dynamiquements - - -Détail de la procédure d'enregistrement ---------------------------------------- -Au démarage le `vregistry` ou base de registres inspecte un certain nombre de -répertoires à la recherche de définition de classes "compatible". Après une -procédure d'enregistrement les objets sont affectés dans différents registres -afin d'être ensuite séléctionné dynamiquement pendant le fonctionnement de -l'application. - -La classe de base de tout ces objets est la classe `AppRsetObject` (module -`cubicweb.common.appobject`). - - -API Python/RQL --------------- - -Inspiré de la db-api standard, avec un object Connection possédant les méthodes -cursor, rollback et commit principalement. La méthode importante est la méthode -`execute` du curseur : - -`execute(rqlstring, args=None, eid_key=None, build_descr=True)` - -:rqlstring: la requête rql à éxécuter (unicode) -:args: si la requête contient des substitutions, un dictionnaire contenant les - valeurs à utiliser -:eid_key: - un détail d'implémentation du cache de requêtes RQL fait que si une substitution est - utilisée pour introduire un eid *levant des ambiguités dans la résolution de - type de la requête*, il faut spécifier par cet argument la clé correspondante - dans le dictionnaire - -C'est l'objet Connection qui possède les méthodes classiques `commit` et -`rollback`. Vous ne *devriez jamais avoir à les utiliser* lors du développement -d'interface web sur la base du framework CubicWeb étant donné que la fin de la -transaction est déterminée par celui-ci en fonction du succès d'éxécution de la -requête. - -NOTE : lors de l'éxécution de requêtes de modification (SET,INSERT,DELETE), si une -requête génère une erreur liée à la sécurité, un rollback est systématiquement -effectuée sur la transaction courante. - - -La classe `Request` (`cubicweb.web`) ---------------------------------- -Une instance de requête est créée lorsque une requête HTTP est transmise au -serveur web. Elle contient des informations telles que les paramètres de -formulaires, l'utilisateur connecté, etc. - -**De manière plus générale une requête représente une demande d'un utilisateur, -que se soit par HTTP ou non (on parle également de requête rql coté serveur par -exemple)** - -Une instance de la classe `Request` possède les attributs : - -* `user`, instance de`cubicweb.common.utils.User` correspondant à l'utilisateur - connecté -* `form`, dictionaire contenant les valeurs de formulaire web -* `encoding`, l'encodage de caractère à utiliser dans la réponse - -Mais encore : - -:Gestion des données de session: - * `session_data()`, retourne un dictionaire contenant l'intégralité des - données de la session - * `get_session_data(key, default=None)`, retourne la valeur associée à - la clé ou la valeur `default` si la clé n'est pas définie - * `set_session_data(key, value)`, associe une valeur à une clé - * `del_session_data(key)`, supprime la valeur associé à une clé - - -:Gestion de cookie: - * `get_cookie()`, retourne un dictionnaire contenant la valeur de l'entête - HTTP 'Cookie' - * `set_cookie(cookie, key, maxage=300)`, ajoute un en-tête HTTP `Set-Cookie`, - avec une durée de vie 5 minutes par défault (`maxage` = None donne un cooke - *de session"* expirant quand l'utilisateur ferme son navigateur - * `remove_cookie(cookie, key)`, fait expirer une valeur - -:Gestion d'URL: - * `url()`, retourne l'url complète de la requête HTTP - * `base_url()`, retourne l'url de la racine de l'application - * `relative_path()`, retourne chemin relatif de la requête - -:Et encore...: - * `set_content_type(content_type, filename=None)`, place l'en-tête HTTP - 'Content-Type' - * `get_header(header)`, retourne la valeur associé à un en-tête HTTP - arbitraire de la requête - * `set_header(header, value)`, ajoute un en-tête HTTP arbitraire dans la - réponse - * `cursor()` retourne un curseur RQL sur la session - * `execute(*args, **kwargs)`, raccourci vers .cursor().execute() - * `property_value(key)`, gestion des propriétés (`CWProperty`) - * le dictionaire `data` pour stocker des données pour partager de - l'information entre les composants *durant l'éxécution de la requête*. - -A noter que cette classe est en réalité abstraite et qu'une implémentation -concrète sera fournie par le *frontend* web utilisé (en l'occurent *twisted* -aujourd'hui). Enfin pour les vues ou autres qui sont éxécutés coté serveur, -la majeure partie de l'interface de `Request` est définie sur la session -associée au client. - - -La classe `AppObject` ---------------------- - -En général : - -* on n'hérite pas directement des cette classe mais plutôt d'une classe - plus spécifique comme par exemple `AnyEntity`, `EntityView`, `AnyRsetView`, - `Action`... - -* pour être enregistrable, un classe fille doit définir son registre (attribut - `__registry__`) et son identifiant (attribut `id`). Généralement on n'a pas à - s'occuper du registre, uniquement de l'identifiant `id` :) - -On trouve un certain nombre d'attributs et de méthodes définis dans cette classe -et donc commune à tous les objets de l'application : - -A l'enregistrement, les attributs suivants sont ajoutés dynamiquement aux -*classes* filles: - -* `vreg`, le `vregistry` de l'application -* `schema`, le schéma de l'application -* `config`, la configuration de l'application - -On trouve également sur les instances les attributs : - -* `req`, instance de `Request` -* `rset`, le "result set" associé à l'objet le cas échéant -* `cursor`, curseur rql sur la session - - -:Gestion d'URL: - * `build_url(method=None, **kwargs)`, retourne une URL absolue construites à - partir des arguments donnés. Le *controleur* devant gérer la réponse - peut-être spécifié via l'argument spécial `method` (le branchement est - théoriquement bien effectué automatiquement :). - - * `datadir_url()`, retourne l'url du répertoire de données de l'application - (contenant les fichiers statiques tels que les images, css, js...) - - * `base_url()`, raccourci sur `req.base_url()` - - * `url_quote(value)`, version *unicode safe* de de la fonction `urllib.quote` - -:Manipulation de données: - - * `etype_rset(etype, size=1)`, raccourci vers `vreg.etype_rset()` - - * `eid_rset(eid, rql=None, descr=True)`, retourne un objet result set pour - l'eid donné - * `entity(row, col=0)`, retourne l'entité correspondant à la position données - du "result set" associé à l'objet - - * `complete_entity(row, col=0, skip_bytes=True)`, équivalent à `entity` mais - appelle également la méthode `complete()` sur l'entité avant de la retourner - -:Formattage de données: - * `format_date(date, date_format=None, time=False)` - * `format_time(time)`, - -:Et encore...: - - * `external_resource(rid, default=_MARKER)`, accède à une valeur définie dans - le fichier de configuration `external_resource` - - * `tal_render(template, variables)`, - - -**NOTE IMPORTANTE** -Lorsqu'on hérite d'`AppObject` (même indirectement), il faut **toujours** -utiliser **super()** pour récupérer les méthodes et attributs des classes -parentes, et pas passer par l'identifiant de classe parente directement. -(sous peine de tomber sur des bugs bizarres lors du rechargement automatique -des vues). Par exemple, plutôt que d'écrire:: - - class Truc(PrimaryView): - def f(self, arg1): - PrimaryView.f(self, arg1) - -Il faut écrire:: - - class Truc(PrimaryView): - def f(self, arg1): - super(Truc, self).f(arg1) - - -XXX FILLME diagramme interaction application/controller/template/view diff -r e3994fcc21c3 -r 1806148d6ce8 goa/doc/devmanual_fr/chap_configuration_instance.txt --- a/goa/doc/devmanual_fr/chap_configuration_instance.txt Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -Configuration d'une instance -============================ - -À la création d'une instance, un fichier de configuration est généré dans :: - - $(CW_REGISTRY)//.conf - -par exemple :: - - /etc/cubicweb.d/jpl/all-in-one.conf - -C'est un simple fichier texte au format INI. Dans la description suivante, -chaque nom d'option est préfixé de sa section et suivi de sa valeur par défaut -le cas échéant, e.g. "`
.
) et appelle la vue `cell` pour chaque cellule - du résultat. Appelable sur n'importe quel result set. -:cell: - par défaut redirige sur la vue `final` si c'est une entité finale - ou sur la vue `outofcontext` sinon -:null: - vue toujours appelable et ne retournant rien diff -r e3994fcc21c3 -r 1806148d6ce8 goa/doc/quickstart.txt --- a/goa/doc/quickstart.txt Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -.. -*- coding: utf-8 -*- - -Introduction -============= - - -Concepts et vocabulaire ------------------------ - -*schéma* - le schéma définit le modèle de données d'une application sous forme - d'entités et de relations. C'est l'élément central d'une - application. - -*result set* - objet qui encaspule les résultats d'une requête adressée à l'entrepôt - de données et des informations sur cette requête. - -*vue* - une vue est une manière de représenter les données d'un `result set` - sous forme HTML, CSV, JSON, etc. - - - -Définition d'une application de Blog -==================================== - -La première chose à faire est de copier le squelette depuis le répertoire -``lax/skel`` vers un nouveau répertoire qui sera votre application -``Google AppEngine``:: - - $ cp -r lax/skel myapp - -Définition du schéma --------------------- - -Ouvrir le fichier ``myapp/schema.py`` afin de définir le schéma des -données manipulées. La syntaxe de la définition est la même que celle -proposée par `Google AppEngine`_ mais il faut remplacer la ligne -d'import:: - - from google.appengine.ext import db - -par celle-ci:: - - from cubicweb.goa import db - - -Un exemple de schéma de données pour un ``Blog`` pourrait être:: - - from cubicweb.goa import db - - class Blog(db.Model): - # un titre à donner à l'entrée - title = db.StringProperty(required=True) - # la date à laquelle le blog est créé - diem = db.DateProperty(required=True, auto_now_add=True) - # le contenu de l'entrée - content = db.TextProperty() - # une entrée peut en citer une autre - cites = db.SelfReferenceProperty() - - -Personnalisation des vues -------------------------- - -``LAX`` permet de générer directement, à partir de la définition -du schéma, des vues de consultation, d'ajout et de modification -pour tous les types de donées manipulés. Il est toutefois -généralement souhaitable de personnaliser les vues de consultations. - -Dans ``LAX``, les vues sont représentées par des classes Python. - -Une vue se caractérise par : - -- un identifiant (tous les objets dans ``LAX`` sont enregistrés - dans un registre et cet identifiant sert de clé pour y retrouver - la vue) - -- une description des types de données auxquels elle s'applique - -Il existe dans ``LAX`` des vues prédéfinies et utilisées par le moteur -d'affichage. Pour avoir une liste exhaustive de ces vues prédéfinies, -vous pouvez consulter cette page. (XXX mettre le lien vers la liste). -Par exemple, la vue ``primary`` est la vue utilisée pour générer la -page principale de consultation d'un objet. - -Par exemple, si on souhaite modifier la page principale d'une entrée de -blog, il faut surcharger la vue ``primary`` des objets ``Blog`` dans -le fichier ``myapp/views.py``:: - - from cubicweb.web.views import baseviews - - class BlogPrimaryView(baseviews.PrimaryView): - accepts = ('Blog',) - - def cell_call(self, row, col): - entity = self.rset.get_entity(row, col) - self.w(u'

%s

' % entity.title) - self.w(u'
%s
' entity.content) - - -Génération du graphique de schéma ---------------------------------- - -Il existe une vue ``schema`` qui permet d'afficher un graphique -représantant les différents types d'entités définis dans le schéma -ainsi que les relations entre ces types. Ce graphique doit être généré -statiquement. Le script à utiliser pour générer ce schéma est -dans ``myapp/tools``. Ce script nécessite d'avoir accès aux -bibliothèques fournies par le SDK de ``Google AppEngine``. Il faut -donc modifier son PYTHONPATH:: - - $ export PYTHONPATH=GAE_ROOT/google:GAE_ROOT/lib/yaml - $ python tools/generate_schema_img.py - - -Génération des fichiers de traduction -------------------------------------- - -Des catalogues de traduction se trouvent dans `myapp/i18n`. Il faut -pour l'instant les mettre à jour à la main (et/ou avec les outils -``GNU`` comme ``xgettext``) et ensuite les compiler grâce au script -``myapp/tools/i18ncompile.py``:: - - $ python tools/i18ncompile.py - -.. _`Google AppEngine` :: http://code.google.com/appengine/docs/datastore/overview.html diff -r e3994fcc21c3 -r 1806148d6ce8 goa/doc/tutorial-wine.txt --- a/goa/doc/tutorial-wine.txt Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -.. -*- coding: utf-8 -*- - -============= -LAX Tutorial -============= - -Introduction ------------- - -LAX is a web framework on top of the Google AppEngine datastore. - - -features: schema/data-model at core of app, selection/view mechanism, -reuseable components, very fast development - - -Since we are french, let us develop an example application that deals -with wine and will allow any wine enthusiast to track the content of -its cellar and share his tasting experiences. - -Schema ------- - -With LAX, the core of the application is the schema/datamodel. - -laxctl newapp ? XXX - -We will start by something simple and define three entities: WineMaker, -Wine and Bottle. - -:: - - class WineMaker(EntityType): - name = String(maxsize=50, required=True) - - class Wine(EntityType): - name = String(required=True, maxsize=100, fulltextindexed=True) - vintage = Int(required=True, constraints=[IntervalBoundConstraint(1850,2100)]) - grown_by = SubjectRelation('WineMaker', cardinality='?*', - description=_('Winemaker who grew the wine')) - - class Bottle(EntityType): - buy_date = Date(description=_('Date when the bottle was bought.'), - default='TODAY') - bottle_of = SubjectRelation('Wine', cardinality='?*') - -A WineMaker only has a name which is a string that is required and -must be less than 50 characters. - -A Wine has a name, which is a string that is required, must be less -than 100 characters and will be indexed in the full-text index XXX -fulltextindex marche pas encore. A Wine -also has a vintage year which is an integer that is required and must -be between 1850 and 2100. A Wine also has a relationship ``grown_by`` -that link it to a WineMaker. Cardinality ``?*`` means that a Wine can -have zero or one WineMaker (``?`` means `zero or one`) and that a -WineMaker can have any number of Wine entities (``*`` means `any number -including zero`). - -A Bottle has a buy_date attribute, which is a date with a default -value of TODAY, meaning that when a new bottle is created, it will -have its creation date as buy_date unless the user changes it to some -other date. A Bottle also has a relationship ``bottle_of`` that link -it to a Wine. The cardinality of that relationship implies that a -Bottle can be linked to zero or one Wine and that a Wine can by linked -to any number of Bottle entities. - - -Defining this simple schema is enough to get us started, launch the -application with the command:: - - laxctl start Winopedia - -and point your browser at localhost:8080 - -You will see the home page of your application. It lists the entity -types: WineMaker, Wine, Bottle. - -Let us create a few of these. Click on the [+] at the right of the -link WineMaker. Call this new WineMaker ``Domaine du château`` and -validate the form by clicking on ``button_ok``. - -Click on the logo at top left to get back to the home page, then -follow the WineMaker link. You should be seeing a list with a single -item ``Domaine du château``. Clicking on this item will get you to -its detailed description except that in this case, there is not much -to display besides the name. - -Now get back to the home page by clicking on the top-left logo, then -create a new WineMaker called ``Vallon de la Dame`` and get back to the -home page again to follow the WineMaker link for the second time. The -list now has two items. - -Get back to the home page and click on [+] at the right of the link -Wine. Call this new wine ``Cuvée du Roi`` and enter 2008 as vintage, -then click on ``button_ok``. You added a new wine without saying who -made it. There is a box on the left entitled "actions", click on the -menu item `modify`. You are back to the form to edit the wine entity -you just created, except that the form now has another section with a -combobox titled "add a relationship". Chose "grown_by" in this -menu and a second combobox appears where you pick ``Domaine du -château``. Validate the changes by clicking ``button_ok``. The entity -Wine that is displayed now includes a link to the entity WineMaker -named ``Domaine du château``. - -Exercise -~~~~~~~~ - -Create new entities Wine and Bottle. - -What we learned -~~~~~~~~~~~~~~~ - -Creating a simple schema was enough to set up a new application that -can store WineMaker, Wine, Bottle. - -What is next ? --------------- - -Althought the application is fully functionnal, its look is very -basic. We will now improve how information is displayed by writing -views. - - -Views -====== - -... - -Defining views with selection/views - -implementing interfaces, calendar for bottles bought and for tasting. -calendar with export icalput attribute drink_date on bottle - -add attribute wine color - -create view "bottle table" with color, buy_date, drink_date. - -in view wine, select Wine.bottles and apply view "bottle table" - -demo ajax with filter on bottle table - -Components -=========== - -... - - - -customize MainTemplate - -rss channel of new bottles or wines - -use URLRewriting for nice urls - -talk about security access rights - -talk about rql \ No newline at end of file diff -r e3994fcc21c3 -r 1806148d6ce8 goa/doc/tutorial.en.txt --- a/goa/doc/tutorial.en.txt Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,227 +0,0 @@ -.. -*- coding: utf-8 -*- - -============= -LAX Tutorial -============= - -Introduction -============ - -LAX stands for Logilab App engine eXtension. It is a web framework -running on top of the Google AppEngine datastore. - -Distinctive features include a data-model driven engine, a query -language, a selection/view mechanism for HTML/XML/text generation, -reuseable components, etc. It all sums up to very fast and efficient -development. - -This tutorial will guide you to build a blog application step by step -to discover the unique features of LAX. It assumes that you followed -the installation guidelines and that both the AppEngine SDK and the -LAX framework are setup on your computer. - -Creating a very simple application -================================== - -Creating a new application --------------------------- - -When you installed lax, you saw a directory named skel. Make a copy of -this directory and call it BlogDemo. - -Defining a schema ------------------ - -With LAX, the schema/datamodel is the core of the application. - -Let us start with something simple and improve on it later. First, we -make sure that in appconfig.py we have a line :: - - schema_type = 'yams' - -Then, in schema.py, we define two entities : ``Blog`` and ``BlogEntry``. - -:: - - class Blog(EntityType): - title = String(maxsize=50, required=True) - description = String() - - class BlogEntry(EntityType): - title = String(maxsize=100, required=True) - publish_date = Date(default='TODAY') - text = String(fulltextindexed=True) - category = String(vocabulary=('important','business')) - entry_of = SubjectRelation('Blog', cardinality='?*') - -A Blog has a title and a description. The title is a string that is -required and must be less than 50 characters. The description is a -string that is not constrained. - -A BlogEntry has a title, a publish_date and a text. The title is a -string that is required and must be less than 100 characters. The -publish_date is a Date with a default value of TODAY, meaning that -when a BlogEntry is created, its publish_date will be the current day -unless it is modified. The text is a string that will be indexed in -the full-text index and has no constraint. - -A BlogEntry also has a relationship ``entry_of`` that link it to a -Blog. The cardinality ``?*`` means that a BlogEntry can be part of -zero or one Blog (``?`` means `zero or one`) and that a Blog can -have any number of BlogEntry (``*`` means `any number including -zero`). For completeness, remember that ``+`` means `one or more`. - -:note: in lax-0.3.0, cardinality checking is not fully ported to -AppEngine, so cardinality limits are not enforced. This should be -fixed in lax-0.4.0 available at the beginning of June. - -Using the application ---------------------- - -Defining this simple schema is enough to get us started. Launch the -application with the command:: - - python dev_appserver.py BlogDemo - -and point your browser at localhost:8080 - -You will see the home page of your application. It lists the entity -types: Blog and BlogEntry. - -Let us create a few of these. Click on the [+] at the right of the -link Blog. Call this new Blog ``Tech-blog`` and type in -``everything about technology`` as the description, then validate the -form by clicking on ``button_ok``. - -Click on the logo at top left to get back to the home page, then -follow the Blog link. If this link reads ``blog_plural`` it is because -i18n is not working for you yet. Let us ignore this for a while. After -following the link, you should be seeing a list with a single item -``Tech-blog``. Clicking on this item will get you to its detailed -description except that in this case, there is not much to display -besides the name and the phrase ``everything about technology``. - -Now get back to the home page by clicking on the top-left logo, then -create a new Blog called ``MyLife`` and get back to the home page -again to follow the Blog link for the second time. The list now -has two items. - -Get back to the home page and click on [+] at the right of the link -BlogEntry. Call this new entry ``Hello World`` and type in some text -before clicking on ``button_ok``. You added a new blog entry without -saying to what blog it belongs. There is a box on the left entitled -``actions``, click on the menu item ``modify``. You are back to the form -to edit the blog entry you just created, except that the form now has -another section with a combobox titled ``add relation``. Chose -``entry_of`` in this menu and a second combobox appears where you pick -``MyLife``. Validate the changes by clicking -``button_ok``. The entity BlogEntry that is displayed now includes a link -to the entity Blog named ``MyLife``. - -Conclusion ----------- - -Exercise -~~~~~~~~ - -Create new blog entries in ``Tech-blog``. - -What we learned -~~~~~~~~~~~~~~~ - -Creating a simple schema was enough to set up a new application that -can store blogs and blog entries. - -What is next ? --------------- - -Althought the application is fully functionnal, its look is very -basic. We will now improve how information is displayed by writing -views. - - -Developing the user interface with Views -======================================== - -[WRITE ME] - -* Defining views with selection/views - -* implementing interfaces, calendar for blog entries. - -* show that a calendar view can export data to ical. - -* create view "blogentry table" with title, publish_date, category. - -* in view blog, select blogentries and apply view "blogentry table" - -* demo ajax by filtering blogentry table on category - -Components -=========== - -[WRITE ME] - -* explain the component architecture - -* add comments to the blog by importing the comments component - -Boxes -====== - -[WRITE ME] - -* explain how to build a box - -* add an blogentry archives box - -Preferences -============ - -[WRITE ME] - -* talk about the user preferences - -* add an example on how to hide / display / move a component or a box - -MainTemplate -============ - -[WRITE ME] - -* customize MainTemplate and show that everything in the user - interface can be changed - - -RSS Channel -=========== - -[WRITE ME] - -* show that the RSS view can be used to display an ordered selection - of blog entries, thus providing a RSS channel - -* show that a different selection (by category) means a different channel - -RQL -==== - -[WRITE ME] - -* talk about the Relation Query Language - -URL Rewriting -============= - -[WRITE ME] - -* show how urls are mapped to selections and views and explain URLRewriting - -Security -========= - -[WRITE ME] - -* talk about security access rights and show that security is defined - using RQL - diff -r e3994fcc21c3 -r 1806148d6ce8 goa/gaesource.py --- a/goa/gaesource.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,331 +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 . -"""Adapter for google appengine source. - -""" -__docformat__ = "restructuredtext en" - -from cubicweb import AuthenticationError, UnknownEid -from cubicweb.server.sources import AbstractSource, ConnectionWrapper -from cubicweb.server.pool import SingleOperation -from cubicweb.server.utils import crypt_password -from cubicweb.goa.dbinit import set_user_groups -from cubicweb.goa.rqlinterpreter import RQLInterpreter - -from google.appengine.api.datastore import Key, Entity, Put, Delete -from google.appengine.api import datastore_errors, users - -def _init_groups(guser, euser): - # set default groups - if guser is None: - groups = ['guests'] - else: - groups = ['users'] - if users.is_current_user_admin(): - groups.append('managers') - set_user_groups(euser, groups) - -def _clear_related_cache(session, gaesubject, rtype, gaeobject): - subject, object = str(gaesubject.key()), str(gaeobject.key()) - for eid, role in ((subject, 'subject'), (object, 'object')): - # clear related cache if necessary - try: - entity = session.entity_cache(eid) - except KeyError: - pass - else: - entity.cw_clear_relation_cache(rtype, role) - if gaesubject.kind() == 'CWUser': - for asession in session.repo._sessions.itervalues(): - if asession.user.eid == subject: - asession.user.cw_clear_relation_cache(rtype, 'subject') - if gaeobject.kind() == 'CWUser': - for asession in session.repo._sessions.itervalues(): - if asession.user.eid == object: - asession.user.cw_clear_relation_cache(rtype, 'object') - -def _mark_modified(session, gaeentity): - modified = session.transaction_data.setdefault('modifiedentities', {}) - modified[str(gaeentity.key())] = gaeentity - DatastorePutOp(session) - -def _rinfo(session, subject, rtype, object): - gaesubj = session.datastore_get(subject) - gaeobj = session.datastore_get(object) - rschema = session.vreg.schema.rschema(rtype) - cards = rschema.rproperty(gaesubj.kind(), gaeobj.kind(), 'cardinality') - return gaesubj, gaeobj, cards - -def _radd(session, gaeentity, targetkey, relation, card): - if card in '?1': - gaeentity[relation] = targetkey - else: - try: - related = gaeentity[relation] - except KeyError: - related = [] - else: - if related is None: - related = [] - related.append(targetkey) - gaeentity[relation] = related - _mark_modified(session, gaeentity) - -def _rdel(session, gaeentity, targetkey, relation, card): - if card in '?1': - gaeentity[relation] = None - else: - related = gaeentity[relation] - if related is not None: - related = [key for key in related if not key == targetkey] - gaeentity[relation] = related or None - _mark_modified(session, gaeentity) - - -class DatastorePutOp(SingleOperation): - """delayed put of entities to have less datastore write api calls - - * save all modified entities at precommit (should be the first operation - processed, hence the 0 returned by insert_index()) - - * in case others precommit operations modify some entities, resave modified - entities at commit. This suppose that no db changes will occurs during - commit event but it should be the case. - """ - def insert_index(self): - return 0 - - def _put_entities(self): - pending = self.session.transaction_data.get('pendingeids', ()) - modified = self.session.transaction_data.get('modifiedentities', {}) - for eid, gaeentity in modified.iteritems(): - assert not eid in pending - Put(gaeentity) - modified.clear() - - def postcommit_event(self): - self._put_entities() - - def precommit_event(self): - self._put_entities() - - -class GAESource(AbstractSource): - """adapter for a system source on top of google appengine datastore""" - - passwd_rql = "Any P WHERE X is CWUser, X login %(login)s, X upassword P" - auth_rql = "Any X WHERE X is CWUser, X login %(login)s, X upassword %(pwd)s" - _sols = ({'X': 'CWUser', 'P': 'Password'},) - - options = () - - def __init__(self, repo, appschema, source_config, *args, **kwargs): - AbstractSource.__init__(self, repo, appschema, source_config, - *args, **kwargs) - if repo.config['use-google-auth']: - self.info('using google authentication service') - self.authenticate = self.authenticate_gauth - else: - self.authenticate = self.authenticate_local - - def reset_caches(self): - """method called during test to reset potential source caches""" - pass - - def init_creating(self): - pass - - def init(self): - # XXX unregister unsupported hooks - from cubicweb.server.hooks import sync_owner_after_add_composite_relation - self.repo.hm.unregister_hook(sync_owner_after_add_composite_relation, - 'after_add_relation', '') - - def get_connection(self): - return ConnectionWrapper() - - # ISource interface ####################################################### - - def compile_rql(self, rql): - rqlst = self.repo.vreg.parse(rql) - rqlst.restricted_vars = () - rqlst.children[0].solutions = self._sols - return rqlst - - def set_schema(self, schema): - """set the instance'schema""" - self.interpreter = RQLInterpreter(schema) - self.schema = schema - if 'CWUser' in schema and not self.repo.config['use-google-auth']: - # rql syntax trees used to authenticate users - self._passwd_rqlst = self.compile_rql(self.passwd_rql) - self._auth_rqlst = self.compile_rql(self.auth_rql) - - def support_entity(self, etype, write=False): - """return true if the given entity's type is handled by this adapter - if write is true, return true only if it's a RW support - """ - return True - - def support_relation(self, rtype, write=False): - """return true if the given relation's type is handled by this adapter - if write is true, return true only if it's a RW support - """ - return True - - def authenticate_gauth(self, session, login, password): - guser = users.get_current_user() - # allowing or not anonymous connection should be done in the app.yaml - # file, suppose it's authorized if we are there - if guser is None: - login = u'anonymous' - else: - login = unicode(guser.nickname()) - # XXX http://code.google.com/appengine/docs/users/userobjects.html - # use a reference property to automatically work with email address - # changes after the propagation feature is implemented - key = Key.from_path('CWUser', 'key_' + login, parent=None) - try: - euser = session.datastore_get(key) - # XXX fix user. Required until we find a better way to fix broken records - if not euser.get('s_in_group'): - _init_groups(guser, euser) - Put(euser) - return str(key) - except datastore_errors.EntityNotFoundError: - # create a record for this user - euser = Entity('CWUser', name='key_' + login) - euser['s_login'] = login - _init_groups(guser, euser) - Put(euser) - return str(euser.key()) - - def authenticate_local(self, session, login, password): - """return CWUser eid for the given login/password if this account is - defined in this source, else raise `AuthenticationError` - - two queries are needed since passwords are stored crypted, so we have - to fetch the salt first - """ - args = {'login': login, 'pwd' : password} - if password is not None: - rset = self.syntax_tree_search(session, self._passwd_rqlst, args) - try: - pwd = rset[0][0] - except IndexError: - raise AuthenticationError('bad login') - # passwords are stored using the bytea type, so we get a StringIO - if pwd is not None: - args['pwd'] = crypt_password(password, pwd[:2]) - # get eid from login and (crypted) password - rset = self.syntax_tree_search(session, self._auth_rqlst, args) - try: - return rset[0][0] - except IndexError: - raise AuthenticationError('bad password') - - def syntax_tree_search(self, session, union, args=None, cachekey=None, - varmap=None): - """return result from this source for a rql query (actually from a rql - syntax tree and a solution dictionary mapping each used variable to a - possible type). If cachekey is given, the query necessary to fetch the - results (but not the results themselves) may be cached using this key. - """ - results, description = self.interpreter.interpret(union, args, - session.datastore_get) - return results # XXX description - - def flying_insert(self, table, session, union, args=None, varmap=None): - raise NotImplementedError - - def add_entity(self, session, entity): - """add a new entity to the source""" - # do not delay add_entity as other modifications, new created entity - # needs an eid - entity.put() - - def update_entity(self, session, entity): - """replace an entity in the source""" - gaeentity = entity.to_gae_model() - _mark_modified(session, entity.to_gae_model()) - if gaeentity.kind() == 'CWUser': - for asession in self.repo._sessions.itervalues(): - if asession.user.eid == entity.eid: - asession.user.update(dict(gaeentity)) - - def delete_entity(self, session, entity): - """delete an entity from the source""" - # do not delay delete_entity as other modifications to ensure - # consistency - eid = entity.eid - key = Key(eid) - Delete(key) - session.clear_datastore_cache(key) - session.drop_entity_cache(eid) - session.transaction_data.get('modifiedentities', {}).pop(eid, None) - - def add_relation(self, session, subject, rtype, object): - """add a relation to the source""" - gaesubj, gaeobj, cards = _rinfo(session, subject, rtype, object) - _radd(session, gaesubj, gaeobj.key(), 's_' + rtype, cards[0]) - _radd(session, gaeobj, gaesubj.key(), 'o_' + rtype, cards[1]) - _clear_related_cache(session, gaesubj, rtype, gaeobj) - - def delete_relation(self, session, subject, rtype, object): - """delete a relation from the source""" - gaesubj, gaeobj, cards = _rinfo(session, subject, rtype, object) - pending = session.transaction_data.setdefault('pendingeids', set()) - if not subject in pending: - _rdel(session, gaesubj, gaeobj.key(), 's_' + rtype, cards[0]) - if not object in pending: - _rdel(session, gaeobj, gaesubj.key(), 'o_' + rtype, cards[1]) - _clear_related_cache(session, gaesubj, rtype, gaeobj) - - # system source interface ################################################# - - def eid_type_source(self, session, eid): - """return a tuple (type, source, extid) for the entity with id """ - try: - key = Key(eid) - except datastore_errors.BadKeyError: - raise UnknownEid(eid) - return key.kind(), 'system', None - - def create_eid(self, session): - return None # let the datastore generating key - - def add_info(self, session, entity, source, extid=None): - """add type and source info for an eid into the system table""" - pass - - def delete_info(self, session, eid, etype, uri, extid): - """delete system information on deletion of an entity by transfering - record from the entities table to the deleted_entities table - """ - pass - - def fti_unindex_entity(self, session, eid): - """remove text content for entity with the given eid from the full text - index - """ - pass - - def fti_index_entity(self, session, entity): - """add text content of a created/modified entity to the full text index - """ - pass diff -r e3994fcc21c3 -r 1806148d6ce8 goa/goaconfig.py --- a/goa/goaconfig.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,179 +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 . -"""google appengine configuration - -""" -__docformat__ = "restructuredtext en" - -import os -from os.path import join - -from cubicweb import CW_SOFTWARE_ROOT -from cubicweb.cwconfig import CubicWebConfiguration -from cubicweb.web.webconfig import WebConfiguration, merge_options -from cubicweb.server.serverconfig import ServerConfiguration -from cubicweb.goa.dbmyams import load_schema - -UNSUPPORTED_OPTIONS = set(('connections-pool-size', - 'pyro-host', 'pyro-instance-id', - 'pyro-ns-host', 'pyro-ns-group', - 'https-url', 'host', 'pid-file', 'uid', 'base-url', 'log-file', - 'smtp-host', 'smtp-port', - 'embed-allowed', - )) - -# XXX fix: -# * default sender-name / sender-addr value -# * what about *session-time -# * check auth-mode=http + fix doc (eg require use-google-auth = False) - -class GAEConfiguration(ServerConfiguration, WebConfiguration): - """repository and web instance in Google AppEngine environment""" - name = 'app' - repo_method = 'inmemory' - options = merge_options(( - ('included-cubes', - {'type' : 'csv', - 'default': [], - 'help': 'list of db model based cubes used by the instance.', - 'group': 'main', 'level': 1, - }), - ('included-yams-cubes', - {'type' : 'csv', - 'default': [], - 'help': 'list of yams based cubes used by the instance.', - 'group': 'main', 'level': 1, - }), - ('use-google-auth', - {'type' : 'yn', - 'default': True, - 'help': 'does this instance rely on google authentication service or not.', - 'group': 'main', 'level': 1, - }), - ('schema-type', - {'type' : 'choice', 'choices': ('yams', 'dbmodel'), - 'default': 'yams', - 'help': 'does this instance is defining its schema using yams or db model.', - 'group': 'main', 'level': 1, - }), - # overriden options - ('query-log-file', - {'type' : 'string', - 'default': None, - 'help': 'web instance query log file: DON\'T SET A VALUE HERE WHEN ' - 'UPLOADING YOUR INSTANCE. This should only be used to analyse ' - 'queries issued by your instance in the development environment.', - 'group': 'main', 'level': 2, - }), - ('anonymous-user', - {'type' : 'string', - 'default': None, - 'help': 'login of the CubicWeb user account to use for anonymous user ' - '(if you want to allow anonymous). This option will be ignored if ' - 'use-google-auth option is set (in which case you should control ' - 'anonymous access using the app.yaml file)', - 'group': 'main', 'level': 1, - }), - - ) + WebConfiguration.options + ServerConfiguration.options) - options = [(optname, optdict) for optname, optdict in options - if not optname in UNSUPPORTED_OPTIONS] - - cubicweb_appobject_path = WebConfiguration.cubicweb_appobject_path | ServerConfiguration.cubicweb_appobject_path - cubicweb_appobject_path = list(cubicweb_appobject_path) + ['goa/appobjects'] - cube_appobject_path = WebConfiguration.cube_appobject_path | ServerConfiguration.cube_appobject_path - - # use file system schema - read_instance_schema = False - # schema is not persistent, don't load schema hooks (unavailable) - schema_hooks = False - # no user workflow for now - consider_user_state = False - - # deactivate some hooks during [pre|post]create scripts execution - # (unique values check, owned_by/created_by relations setup) - free_wheel = True - - if not os.environ.get('APYCOT_ROOT'): - CUBES_DIR = join(CW_SOFTWARE_ROOT, '../cubes') - - def __init__(self, appid, apphome=None): - if apphome is None: - apphome = 'data' - self._apphome = apphome - self._base_url = None - CubicWebConfiguration.__init__(self, appid) - - def __getitem__(self, key): - if key == 'connections-pool-size': - return 4 # > 1 to allow multiple user sessions in tests - if key == 'base-url': - return self._base_url - return super(GAEConfiguration, self).__getitem__(key) - - # overriden from cubicweb base configuration - - @property - def apphome(self): - return self._apphome - - def cubes(self): - """return the list of top level cubes used by this instance (eg - without dependencies) - """ - if self._cubes is None: - cubes = self['included-cubes'] + self['included-yams-cubes'] - cubes = self.expand_cubes(cubes) - return self.reorder_cubes(cubes) - return self._cubes - - def vc_config(self): - """return CubicWeb's engine and instance's cube versions number""" - return {} - - # overriden from cubicweb web configuration - - def instance_md5_version(self): - return '' - - def _init_base_url(self): - pass - - # overriden from cubicweb server configuration - - def sources(self): - return {'system': {'adapter': 'gae'}} - - def load_schema(self, schemaclasses=None, extrahook=None): - try: - return self._schema - except AttributeError: - self._schema = load_schema(self, schemaclasses, extrahook) - return self._schema - - # goa specific - def repo_session(self, sessionid): - return self.repository()._sessions[sessionid] - - def is_anonymous_user(self, login): - if self['use-google-auth']: - from google.appengine.api import users - return users.get_current_user() is None - else: - return login == self.anonymous_user()[0] - diff -r e3994fcc21c3 -r 1806148d6ce8 goa/goactl.py --- a/goa/goactl.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,252 +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 . -"""cubicweb on appengine plugins for cubicweb-ctl""" - -__docformat__ = "restructuredtext en" - -from os.path import exists, join, split, basename, normpath, abspath - -from cubicweb import CW_SOFTWARE_ROOT, BadCommandUsage -from cubicweb.cwctl import CWCTL -from cubicweb.toolsutils import (Command, copy_skeleton, create_symlink, - create_dir) -from cubicweb.cwconfig import CubicWebConfiguration - - -def slink_directories(): - import rql, yams, yapps, docutils, roman - try: - import json as simplejson - except ImportError: - import simplejson - from logilab import common as lgc - from logilab import constraint as lgcstr - from logilab import mtconverter as lgmtc - dirs = [ - (lgc.__path__[0], 'logilab/common'), - (lgmtc.__path__[0], 'logilab/mtconverter'), - (lgcstr.__path__[0], 'logilab/constraint'), - (rql.__path__[0], 'rql'), - (simplejson.__path__[0], 'simplejson'), - (yams.__path__[0], 'yams'), - (yapps.__path__[0], 'yapps'), - (docutils.__path__[0], 'docutils'), - (roman.__file__.replace('.pyc', '.py'), 'roman.py'), - - ('/usr/share/fckeditor/', 'fckeditor'), - - (join(CW_SOFTWARE_ROOT, 'web', 'data'), join('cubes', 'shared', 'data')), - (join(CW_SOFTWARE_ROOT, 'web', 'wdoc'), join('cubes', 'shared', 'wdoc')), - (join(CW_SOFTWARE_ROOT, 'i18n'), join('cubes', 'shared', 'i18n')), - (join(CW_SOFTWARE_ROOT, 'goa', 'tools'), 'tools'), - (join(CW_SOFTWARE_ROOT, 'goa', 'bin'), 'bin'), - ] - - try: - import dateutil - import vobject - dirs.extend([ (dateutil.__path__[0], 'dateutil'), - (vobject.__path__[0], 'vobject') ] ) - except ImportError: - pass - return dirs - -COPY_CW_FILES = ( - '__init__.py', - '__pkginfo__.py', - '_exceptions.py', - 'appobject.py', - 'dbapi.py', - 'cwvreg.py', - 'cwconfig.py', - 'entity.py', - 'interfaces.py', - 'i18n.py', - 'mail.py', - 'migration.py', - 'mixins.py', - 'mttransforms.py', - 'rqlrewrite.py', - 'rset.py', - 'schema.py', - 'schemaviewer.py', - 'selectors.py', - 'uilib.py', - 'utils.py', - 'vregistry.py', - 'view.py', - - 'ext/html4zope.py', - 'ext/rest.py', - - 'server/hookhelper.py', - 'server/hooksmanager.py', - 'server/hooks.py', - 'server/migractions.py', - 'server/pool.py', - 'server/querier.py', - 'server/repository.py', - 'server/securityhooks.py', - 'server/session.py', - 'server/serverconfig.py', - 'server/ssplanner.py', - 'server/utils.py', - 'server/sources/__init__.py', - - 'entities/__init__.py', - 'entities/authobjs.py', - 'entities/lib.py', - 'entities/schemaobjs.py', - 'entities/wfobjs.py', - - 'sobjects/__init__.py', - 'sobjects/notification.py', - -# XXX would be necessary for goa.testlib but require more stuff to be added -# such as server.serverconfig and so on (check devtools.__init__) -# 'devtools/__init__.py', -# 'devtools/fake.py', - - 'web/__init__.py', - 'web/_exceptions.py', - 'web/action.py', - 'web/application.py', - 'web/box.py', - 'web/component.py', - 'web/controller.py', - 'web/form.py', - 'web/htmlwidgets.py', - 'web/httpcache.py', - 'web/request.py', - 'web/webconfig.py', - - 'web/views/__init__.py', - 'web/views/actions.py', - 'web/views/basecomponents.py', - 'web/views/basecontrollers.py', - 'web/views/baseforms.py', - 'web/views/basetemplates.py', - 'web/views/baseviews.py', - 'web/views/boxes.py', - 'web/views/calendar.py', - 'web/views/error.py', - 'web/views/editcontroller.py', - 'web/views/ibreadcrumbs.py', - 'web/views/idownloadable.py', - 'web/views/magicsearch.py', - 'web/views/management.py', - 'web/views/navigation.py', - 'web/views/startup.py', - 'web/views/vcard.py', - 'web/views/wdoc.py', - 'web/views/urlpublishing.py', - 'web/views/urlrewrite.py', - 'web/views/xbel.py', - - 'wsgi/__init__.py', - 'wsgi/handler.py', - 'wsgi/request.py', - - 'goa/__init__.py', - 'goa/db.py', - 'goa/dbinit.py', - 'goa/dbmyams.py', - 'goa/goaconfig.py', - 'goa/goavreg.py', - 'goa/gaesource.py', - 'goa/rqlinterpreter.py', - 'goa/appobjects/__init__.py', - 'goa/appobjects/components.py', - 'goa/appobjects/dbmgmt.py', - 'goa/appobjects/gauthservice.py', - 'goa/appobjects/sessions.py', - - 'schemas/bootstrap.py', - 'schemas/base.py', - ) - -OVERRIDEN_FILES = ( - ('toolsutils.py', 'toolsutils.py'), - ('mttransforms.py', 'mttransforms.py'), - ('server__init__.py', 'server/__init__.py'), - ('rqlannotation.py', 'server/rqlannotation.py'), - ) - - -def create_init_file(pkgdir, pkgname): - open(join(pkgdir, '__init__.py'), 'w').write('"""%s pkg"""' % pkgname) - - -class NewGoogleAppCommand(Command): - """Create a new google appengine instance. - - - the path to the appengine instance directory - """ - name = 'newgapp' - arguments = '' - - def run(self, args): - if len(args) != 1: - raise BadCommandUsage("exactly one argument is expected") - appldir, = args - appldir = normpath(abspath(appldir)) - appid = basename(appldir) - context = {'appname': appid} - # goa instance'skeleton - copy_skeleton(join(CW_SOFTWARE_ROOT, 'goa', 'skel'), - appldir, context, askconfirm=True) - # cubicweb core dependencies - for directory, subdirectory in slink_directories(): - subdirectory = join(appldir, subdirectory) - if not exists(split(subdirectory)[0]): - create_dir(split(subdirectory)[0]) - create_symlink(directory, join(appldir, subdirectory)) - create_init_file(join(appldir, 'logilab'), 'logilab') - # copy supported part of cubicweb - create_dir(join(appldir, 'cubicweb')) - for fpath in COPY_CW_FILES: - target = join(appldir, 'cubicweb', fpath) - if not exists(split(target)[0]): - create_dir(split(target)[0]) - create_symlink(join(CW_SOFTWARE_ROOT, fpath), target) - # overriden files - for fpath, subfpath in OVERRIDEN_FILES: - create_symlink(join(CW_SOFTWARE_ROOT, 'goa', 'overrides', fpath), - join(appldir, 'cubicweb', subfpath)) - # link every supported components - packagesdir = join(appldir, 'cubes') - create_init_file(join(appldir, 'cubes'), 'cubes') - for include in ('addressbook','basket', 'blog','folder', - 'tag', 'comment', 'file', 'link', - 'mailinglist', 'person', 'task', 'zone', - ): - create_symlink(CubicWebConfiguration.cube_dir(include), - join(packagesdir, include)) - # generate sample config - from cubicweb.goa.goaconfig import GAEConfiguration - from cubicweb.migration import MigrationHelper - config = GAEConfiguration(appid, appldir) - if exists(config.main_config_file()): - mih = MigrationHelper(config) - mih.rewrite_configuration() - else: - config.save() - - -CWCTL.register(NewGoogleAppCommand) diff -r e3994fcc21c3 -r 1806148d6ce8 goa/goavreg.py --- a/goa/goavreg.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +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 . -"""goa specific registry - -""" -__docformat__ = "restructuredtext en" - -from os import listdir -from os.path import join, isdir - -from cubicweb import CW_SOFTWARE_ROOT -from cubicweb.cwvreg import CubicWebVRegistry - - -def _pkg_name(cube, module): - if cube is None: - return module - return 'cubes.%s.%s' % (cube, module) - -class GAEVRegistry(CubicWebVRegistry): - - def set_schema(self, schema): - """disable reload hooks of cubicweb registry set_schema method""" - self.schema = schema - - def load(self, applroot): - from cubicweb.goa import db - self.load_module(db) # AnyEntity class - # explicit loading, we don't want to load __init__.py - self.load_directory(join(CW_SOFTWARE_ROOT, 'entities'), - 'cubicweb.entities', skip=('__init__.py',)) - self.load_directory(join(CW_SOFTWARE_ROOT, 'web', 'views'), - 'cubicweb.web.views') - self.load_directory(join(CW_SOFTWARE_ROOT, 'goa', 'appobjects'), - 'cubicweb.goa.appobjects') - for cube in reversed(self.config.cubes()): - self.load_cube(cube) - self.load_instance(applroot) - - def load_directory(self, directory, cube, skip=()): - for filename in listdir(directory): - if filename[-3:] == '.py' and not filename in skip: - self._import('%s.%s' % (cube, filename[:-3])) - - def load_cube(self, cube): - self._auto_load(self.config.cube_dir(cube), - cube in self.config['included-cubes'], - cube) - - def load_instance(self, applroot): - self._auto_load(applroot, self.config['schema-type'] == 'dbmodel') - - def _import(self, modname): - obj = __import__(modname) - for attr in modname.split('.')[1:]: - obj = getattr(obj, attr) - self.load_module(obj) - - def _auto_load(self, path, loadschema, cube=None): - vobjpath = self.config.cube_appobject_path - for filename in listdir(path): - if filename[-3:] == '.py' and filename[:-3] in vobjpath: - self._import(_pkg_name(cube, filename[:-3])) - else: - abspath = join(path, filename) - if isdir(abspath) and filename in vobjpath: - self.load_directory(abspath, _pkg_name(cube, filename)) - if loadschema: - # when using db.Model defined schema, the defined class is used as - # entity class as well and so have to be registered - self._import(_pkg_name(cube, 'schema')) diff -r e3994fcc21c3 -r 1806148d6ce8 goa/overrides/__init__.py --- a/goa/overrides/__init__.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -# server.__init__ -# 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 . -""" - -""" diff -r e3994fcc21c3 -r 1806148d6ce8 goa/overrides/mttransforms.py --- a/goa/overrides/mttransforms.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +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 . -"""mime type transformation engine for cubicweb, based on mtconverter - -""" -__docformat__ = "restructuredtext en" - -from logilab import mtconverter - -from logilab.mtconverter.engine import TransformEngine -from logilab.mtconverter.transform import Transform -from cubicweb.uilib import rest_publish, html_publish, remove_html_tags - -HTML_MIMETYPES = ('text/html', 'text/xhtml', 'application/xhtml+xml') -# CubicWeb specific transformations - -class rest_to_html(Transform): - inputs = ('text/rest', 'text/x-rst') - output = 'text/html' - def _convert(self, trdata): - return rest_publish(trdata.appobject, trdata.decode()) - -class html_to_html(Transform): - inputs = HTML_MIMETYPES - output = 'text/html' - def _convert(self, trdata): - return html_publish(trdata.appobject, trdata.data) - - -# Instantiate and configure the transformation engine - -mtconverter.UNICODE_POLICY = 'replace' - -ENGINE = TransformEngine() -ENGINE.add_transform(rest_to_html()) -ENGINE.add_transform(html_to_html()) - -HAS_PIL_TRANSFORMS = False -HAS_PYGMENTS_TRANSFORMS = False - -class html_to_text(Transform): - inputs = HTML_MIMETYPES - output = 'text/plain' - def _convert(self, trdata): - return remove_html_tags(trdata.data) -ENGINE.add_transform(html_to_text()) diff -r e3994fcc21c3 -r 1806148d6ce8 goa/overrides/rqlannotation.py --- a/goa/overrides/rqlannotation.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +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 . -""" -""" -__docformat__ = "restructuredtext en" - -def set_qdata(getrschema, union, noinvariant): - pass - -class SQLGenAnnotator(object): - def __init__(self, schema): - self.schema = schema - self.nfdomain = frozenset(eschema.type for eschema in schema.entities() - if not eschema.final) - def annotate(self, rqlst): - rqlst.has_text_query = False - rqlst.need_distinct = False - - diff -r e3994fcc21c3 -r 1806148d6ce8 goa/overrides/server__init__.py --- a/goa/overrides/server__init__.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -# server debugging flag -# 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 . -""" - -""" -DEBUG = False - -# sqlite'stored procedures have to be registered at connexion opening time -SQL_CONNECT_HOOKS = {} - -# add to this set relations which should have their add security checking done -# *BEFORE* adding the actual relation (done after by default) -BEFORE_ADD_RELATIONS = set(('owned_by',)) - -# add to this set relations which should have their add security checking done -# *at COMMIT TIME* (done after by default) -ON_COMMIT_ADD_RELATIONS = set(()) - -# available sources registry -SOURCE_TYPES = {} diff -r e3994fcc21c3 -r 1806148d6ce8 goa/overrides/server_utils.py --- a/goa/overrides/server_utils.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +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 . -""" - -""" - -class RepoThread(object): - def __init__(self, *args): - pass # XXX raise - def start(self): - pass - def join(self): - pass - -class LoopTask(RepoThread): - def cancel(self): - pass diff -r e3994fcc21c3 -r 1806148d6ce8 goa/overrides/toolsutils.py --- a/goa/overrides/toolsutils.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +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 . -""" - -""" -import sys -from cubicweb import warning - -def lines(path, comments=None): - result = [] - for line in open(path, 'U'): - line = line.strip() - if line and (comments is None or not line.startswith(comments)): - result.append(line) - return result - -def read_config(config_file): - """read the instance configuration from a file and return it as a - dictionnary - - :type config_file: str - :param config_file: path to the configuration file - - :rtype: dict - :return: a dictionary with specified values associated to option names - """ - config = current = {} - try: - for line in lines(config_file, comments='#'): - try: - option, value = line.split('=', 1) - except ValueError: - option = line.strip().lower() - if option[0] == '[': - # start a section - section = option[1:-1] - assert not config.has_key(section), \ - 'Section %s is defined more than once' % section - config[section] = current = {} - continue - print >> sys.stderr, 'ignoring malformed line\n%r' % line - continue - option = option.strip().replace(' ', '_') - value = value.strip() - current[option] = value or None - except IOError, ex: - warning('missing or non readable configuration file %s (%s)', - config_file, ex) - return config - -def env_path(env_var, default, name): - return default - -def create_dir(*args): - raise RuntimeError() diff -r e3994fcc21c3 -r 1806148d6ce8 goa/rqlinterpreter.py --- a/goa/rqlinterpreter.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,684 +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 . -"""provide a minimal RQL support for google appengine dbmodel - -""" -__docformat__ = "restructuredtext en" - -from datetime import datetime - -from rql import RQLHelper, nodes - -from cubicweb import Binary -from cubicweb.rset import ResultSet -from cubicweb.server import SQL_CONNECT_HOOKS - -from google.appengine.api.datastore import Key, Get, Query, Entity -from google.appengine.api.datastore_types import Text, Blob -from google.appengine.api.datastore_errors import EntityNotFoundError, BadKeyError - - -def etype_from_key(key): - return Key(key).kind() - -def poss_var_types(myvar, ovar, kind, solutions): - return frozenset(etypes[myvar] for etypes in solutions - if etypes[ovar] == kind) - -def expand_result(results, result, myvar, values, dsget=None): - values = map(dsget, values) - if values: - result[myvar] = values.pop(0) - for value in values: - newresult = result.copy() - newresult[myvar] = value - results.append(newresult) - else: - results.remove(result) - -def _resolve(restrictions, solutions, fixed): - varname = restrictions[0].searched_var - objs = [] - for etype in frozenset(etypes[varname] for etypes in solutions): - gqlargs = {} - query = Query(etype) - for restriction in restrictions: - restriction.fill_query(fixed, query) - pobjs = query.Run() - if varname in fixed: - value = fixed[varname] - objs += (x for x in pobjs if x == value) - else: - objs += pobjs - if varname in fixed and not objs: - raise EidMismatch(varname, value) - return objs - -def _resolve_not(restrictions, solutions, fixed): - restr = restrictions[0] - constrvarname = restr.constraint_var - if len(restrictions) > 1 or not constrvarname in fixed: - raise NotImplementedError() - varname = restr.searched_var - objs = [] - for etype in frozenset(etypes[varname] for etypes in solutions): - gqlargs = {} - for operator in ('<', '>'): - query = Query(etype) - restr.fill_query(fixed, query, operator) - objs += query.Run() - return objs - -def _print_results(rlist): - return '[%s]' % ', '.join(_print_result(r) for r in rlist) - -def _print_result(rdict): - string = [] - for k, v in rdict.iteritems(): - if isinstance(v, Entity): - string.append('%s: %s' % (k, v.key()))#_print_result(v))) - elif isinstance(v, list): - string.append('%s: [%s]' % (k, ', '.join(str(i) for i in v))) - else: - string.append('%s: %s' % (k, v)) - return '{%s}' % ', '.join(string) - - -class EidMismatch(Exception): - def __init__(self, varname, value): - self.varname = varname - self.value = value - - -class Restriction(object): - supported_operators = ('=',) - def __init__(self, rel): - operator = rel.children[1].operator - if not operator in self.supported_operators: - raise NotImplementedError('unsupported operator') - self.rel = rel - self.operator = operator - self.rtype = rel.r_type - self.var = rel.children[0] - - def __repr__(self): - return '<%s for %s>' % (self.__class__.__name__, self.rel) - - @property - def rhs(self): - return self.rel.children[1].children[0] - - -class MultipleRestriction(object): - def __init__(self, restrictions): - self.restrictions = restrictions - - def resolve(self, solutions, fixed): - return _resolve(self.restrictions, solutions, fixed) - - -class VariableSelection(Restriction): - def __init__(self, rel, dsget, prefix='s'): - Restriction.__init__(self, rel) - self._dsget = dsget - self._not = self.rel.neged(strict=True) - self._prefix = prefix + '_' - - def __repr__(self): - return '<%s%s for %s>' % (self._prefix[0], self.__class__.__name__, self.rel) - - @property - def searched_var(self): - if self._prefix == 's_': - return self.var.name - return self.rhs.name - - @property - def constraint_var(self): - if self._prefix == 's_': - return self.rhs.name - return self.var.name - - def _possible_values(self, myvar, ovar, entity, solutions, dsprefix): - if self.rtype == 'identity': - return (entity.key(),) - value = entity.get(dsprefix + self.rtype) - if value is None: - return [] - if not isinstance(value, list): - value = [value] - vartypes = poss_var_types(myvar, ovar, entity.kind(), solutions) - return (v for v in value if v.kind() in vartypes) - - def complete_and_filter(self, solutions, results): - myvar = self.rhs.name - ovar = self.var.name - rtype = self.rtype - if self.schema.rschema(rtype).final: - # should be detected by rql.stcheck: "Any C WHERE NOT X attr C" doesn't make sense - #if self._not: - # raise NotImplementedError() - for result in results: - result[myvar] = result[ovar].get('s_'+rtype) - elif self.var.name in results[0]: - if self.rhs.name in results[0]: - self.filter(solutions, results) - else: - if self._not: - raise NotImplementedError() - for result in results[:]: - values = self._possible_values(myvar, ovar, result[ovar], - solutions, 's_') - expand_result(results, result, myvar, values, self._dsget) - else: - assert self.rhs.name in results[0] - self.object_complete_and_filter(solutions, results) - - def filter(self, solutions, results): - myvar = self.rhs.name - ovar = self.var.name - newsols = {} - for result in results[:]: - entity = result[ovar] - key = entity.key() - if not key in newsols: - values = self._possible_values(myvar, ovar, entity, solutions, 's_') - newsols[key] = frozenset(v for v in values) - if self._not: - if result[myvar].key() in newsols[key]: - results.remove(result) - elif not result[myvar].key() in newsols[key]: - results.remove(result) - - def object_complete_and_filter(self, solutions, results): - if self._not: - raise NotImplementedError() - myvar = self.var.name - ovar = self.rhs.name - for result in results[:]: - values = self._possible_values(myvar, ovar, result[ovar], - solutions, 'o_') - expand_result(results, result, myvar, values, self._dsget) - - -class EidRestriction(Restriction): - def __init__(self, rel, dsget): - Restriction.__init__(self, rel) - self._dsget = dsget - - def resolve(self, kwargs): - value = self.rel.children[1].children[0].eval(kwargs) - return self._dsget(value) - - -class RelationRestriction(VariableSelection): - - def _get_value(self, fixed): - return fixed[self.constraint_var].key() - - def fill_query(self, fixed, query, operator=None): - restr = '%s%s %s' % (self._prefix, self.rtype, operator or self.operator) - query[restr] = self._get_value(fixed) - - def resolve(self, solutions, fixed): - if self.rtype == 'identity': - if self._not: - raise NotImplementedError() - return [fixed[self.constraint_var]] - if self._not: - return _resolve_not([self], solutions, fixed) - return _resolve([self], solutions, fixed) - - -class NotRelationRestriction(RelationRestriction): - - def _get_value(self, fixed): - return None - - def resolve(self, solutions, fixed): - if self.rtype == 'identity': - raise NotImplementedError() - return _resolve([self], solutions, fixed) - - -class AttributeRestriction(RelationRestriction): - supported_operators = ('=', '>', '>=', '<', '<=', 'ILIKE') - def __init__(self, rel, kwargs): - RelationRestriction.__init__(self, rel, None) - value = self.rhs.eval(kwargs) - self.value = value - if self.operator == 'ILIKE': - if value.startswith('%'): - raise NotImplementedError('LIKE is only supported for prefix search') - if not value.endswith('%'): - raise NotImplementedError('LIKE is only supported for prefix search') - self.operator = '>' - self.value = value[:-1] - - def complete_and_filter(self, solutions, results): - # check lhs var first in case this is a restriction - assert self._not - myvar, rtype, value = self.var.name, self.rtype, self.value - for result in results[:]: - if result[myvar].get('s_'+rtype) == value: - results.remove(result) - - def _get_value(self, fixed): - return self.value - - -class DateAttributeRestriction(AttributeRestriction): - """just a thin layer on top af `AttributeRestriction` that - tries to convert date strings such as in : - Any X WHERE X creation_date >= '2008-03-04' - """ - def __init__(self, rel, kwargs): - super(DateAttributeRestriction, self).__init__(rel, kwargs) - if isinstance(self.value, basestring): -# try: - self.value = datetime.strptime(self.value, '%Y-%m-%d') -# except Exception, exc: -# from logging import error -# error('unable to parse date %s with format %%Y-%%m-%%d (exc=%s)', value, exc) - - -class AttributeInRestriction(AttributeRestriction): - def __init__(self, rel, kwargs): - RelationRestriction.__init__(self, rel, None) - values = [] - for c in self.rel.children[1].iget_nodes(nodes.Constant): - values.append(c.eval(kwargs)) - self.value = values - - @property - def operator(self): - return 'in' - - -class TypeRestriction(AttributeRestriction): - def __init__(self, var): - self.var = var - - def __repr__(self): - return '<%s for %s>' % (self.__class__.__name__, self.var) - - def resolve(self, solutions, fixed): - objs = [] - for etype in frozenset(etypes[self.var.name] for etypes in solutions): - objs += Query(etype).Run() - return objs - - -def append_result(res, descr, i, j, value, etype): - if value is not None: - if isinstance(value, Text): - value = unicode(value) - elif isinstance(value, Blob): - value = Binary(str(value)) - if j == 0: - res.append([value]) - descr.append([etype]) - else: - res[i].append(value) - descr[i].append(etype) - - -class ValueResolver(object): - def __init__(self, functions, args, term): - self.functions = functions - self.args = args - self.term = term - self._solution = self.term.stmt.solutions[0] - - def compute(self, result): - """return (entity type, value) to which self.term is evaluated according - to the given result dictionnary and to query arguments (self.args) - """ - return self.term.accept(self, result) - - def visit_function(self, node, result): - args = tuple(n.accept(self, result)[1] for n in node.children) - value = self.functions[node.name](*args) - return node.get_type(self._solution, self.args), value - - def visit_variableref(self, node, result): - value = result[node.name] - try: - etype = value.kind() - value = str(value.key()) - except AttributeError: - etype = self._solution[node.name] - return etype, value - - def visit_constant(self, node, result): - return node.get_type(kwargs=self.args), node.eval(self.args) - - -class RQLInterpreter(object): - """algorithm: - 1. visit the restriction clauses and collect restriction for each subject - of a relation. Different restriction types are: - * EidRestriction - * AttributeRestriction - * RelationRestriction - * VariableSelection (not really a restriction) - -> dictionary {: [restriction...], ...} - 2. resolve eid restrictions - 3. for each select in union: - for each solution in select'solutions: - 1. resolve variables which have attribute restriction - 2. resolve relation restriction - 3. resolve selection and add to global results - """ - def __init__(self, schema): - self.schema = schema - Restriction.schema = schema # yalta! - self.rqlhelper = RQLHelper(schema, {'eid': etype_from_key}) - self._stored_proc = {'LOWER': lambda x: x.lower(), - 'UPPER': lambda x: x.upper()} - for cb in SQL_CONNECT_HOOKS.get('sqlite', []): - cb(self) - - # emulate sqlite connection interface so we can reuse stored procedures - def create_function(self, name, nbargs, func): - self._stored_proc[name] = func - - def create_aggregate(self, name, nbargs, func): - self._stored_proc[name] = func - - - def execute(self, operation, parameters=None, eid_key=None, build_descr=True): - rqlst = self.rqlhelper.parse(operation, annotate=True) - try: - self.rqlhelper.compute_solutions(rqlst, kwargs=parameters) - except BadKeyError: - results, description = [], [] - else: - results, description = self.interpret(rqlst, parameters) - return ResultSet(results, operation, parameters, description, rqlst=rqlst) - - def interpret(self, node, kwargs, dsget=None): - if dsget is None: - self._dsget = Get - else: - self._dsget = dsget - try: - return node.accept(self, kwargs) - except NotImplementedError: - self.critical('support for query not implemented: %s', node) - raise - - def visit_union(self, node, kwargs): - results, description = [], [] - extra = {'kwargs': kwargs} - for child in node.children: - pres, pdescr = self.visit_select(child, extra) - results += pres - description += pdescr - return results, description - - def visit_select(self, node, extra): - constraints = {} - if node.where is not None: - node.where.accept(self, constraints, extra) - fixed, toresolve, postresolve, postfilters = {}, {}, {}, [] - # extract NOT filters - for vname, restrictions in constraints.items(): - for restr in restrictions[:]: - if isinstance(restr, AttributeRestriction) and restr._not: - postfilters.append(restr) - restrictions.remove(restr) - if not restrictions: - del constraints[vname] - # add TypeRestriction for variable which have no restrictions at all - for varname, var in node.defined_vars.iteritems(): - if not varname in constraints: - constraints[varname] = [TypeRestriction(var)] - #print node, constraints - # compute eid restrictions - kwargs = extra['kwargs'] - for varname, restrictions in constraints.iteritems(): - for restr in restrictions[:]: - if isinstance(restr, EidRestriction): - assert not varname in fixed - try: - value = restr.resolve(kwargs) - fixed[varname] = value - except EntityNotFoundError: - return [], [] - restrictions.remove(restr) - #print 'fixed', fixed.keys() - # combine remaining restrictions - for varname, restrictions in constraints.iteritems(): - for restr in restrictions: - if isinstance(restr, AttributeRestriction): - toresolve.setdefault(varname, []).append(restr) - elif isinstance(restr, NotRelationRestriction) or ( - isinstance(restr, RelationRestriction) and - not restr.searched_var in fixed and restr.constraint_var in fixed): - toresolve.setdefault(varname, []).append(restr) - else: - postresolve.setdefault(varname, []).append(restr) - try: - if len(toresolve[varname]) > 1: - toresolve[varname] = MultipleRestriction(toresolve[varname]) - else: - toresolve[varname] = toresolve[varname][0] - except KeyError: - pass - #print 'toresolve %s' % toresolve - #print 'postresolve %s' % postresolve - # resolve additional restrictions - if fixed: - partres = [fixed.copy()] - else: - partres = [] - for varname, restr in toresolve.iteritems(): - varpartres = partres[:] - try: - values = tuple(restr.resolve(node.solutions, fixed)) - except EidMismatch, ex: - varname = ex.varname - value = ex.value - partres = [res for res in partres if res[varname] != value] - if partres: - continue - # some join failed, no possible results - return [], [] - if not values: - # some join failed, no possible results - return [], [] - if not varpartres: - # init results - for value in values: - partres.append({varname: value}) - elif not varname in partres[0]: - # cartesian product - for res in partres: - res[varname] = values[0] - for res in partres[:]: - for value in values[1:]: - res = res.copy() - res[varname] = value - partres.append(res) - else: - # union - for res in varpartres: - for value in values: - res = res.copy() - res[varname] = value - partres.append(res) - #print 'partres', len(partres) - #print partres - # Note: don't check for empty partres since constant selection may still - # produce result at this point - # sort to get RelationRestriction before AttributeSelection - restrictions = sorted((restr for restrictions in postresolve.itervalues() - for restr in restrictions), - key=lambda x: not isinstance(x, RelationRestriction)) - # compute stuff not doable in the previous step using datastore queries - for restr in restrictions + postfilters: - restr.complete_and_filter(node.solutions, partres) - if not partres: - # some join failed, no possible results - return [], [] - if extra.pop('has_exists', False): - # remove potential duplicates introduced by exists - toremovevars = [v.name for v in node.defined_vars.itervalues() - if not v.scope is node] - if toremovevars: - newpartres = [] - for result in partres: - for var in toremovevars: - del result[var] - if not result in newpartres: - newpartres.append(result) - if not newpartres: - # some join failed, no possible results - return [], [] - partres = newpartres - if node.orderby: - for sortterm in reversed(node.orderby): - resolver = ValueResolver(self._stored_proc, kwargs, sortterm.term) - partres.sort(reverse=not sortterm.asc, - key=lambda x: resolver.compute(x)[1]) - if partres: - if node.offset: - partres = partres[node.offset:] - if node.limit: - partres = partres[:node.limit] - if not partres: - return [], [] - #print 'completed partres', _print_results(partres) - # compute results - res, descr = [], [] - for j, term in enumerate(node.selection): - resolver = ValueResolver(self._stored_proc, kwargs, term) - if not partres: - etype, value = resolver.compute({}) - # only constant selected - if not res: - res.append([]) - descr.append([]) - res[0].append(value) - descr[0].append(etype) - else: - for i, sol in enumerate(partres): - etype, value = resolver.compute(sol) - append_result(res, descr, i, j, value, etype) - #print '--------->', res - return res, descr - - def visit_and(self, node, constraints, extra): - for child in node.children: - child.accept(self, constraints, extra) - def visit_exists(self, node, constraints, extra): - extra['has_exists'] = True - self.visit_and(node, constraints, extra) - - def visit_not(self, node, constraints, extra): - for child in node.children: - child.accept(self, constraints, extra) - try: - extra.pop(node) - except KeyError: - raise NotImplementedError() - - def visit_relation(self, node, constraints, extra): - if node.is_types_restriction(): - return - rschema = self.schema.rschema(node.r_type) - neged = node.neged(strict=True) - if neged: - # ok, we *may* process this Not node (not implemented error will be - # raised later if we can't) - extra[node.parent] = True - if rschema.final: - self._visit_final_relation(rschema, node, constraints, extra) - elif neged: - self._visit_non_final_neged_relation(rschema, node, constraints) - else: - self._visit_non_final_relation(rschema, node, constraints) - - def _visit_non_final_relation(self, rschema, node, constraints, not_=False): - lhs, rhs = node.get_variable_parts() - for v1, v2, prefix in ((lhs, rhs, 's'), (rhs, lhs, 'o')): - #if not_: - nbrels = len(v2.variable.stinfo['relations']) - #else: - # nbrels = len(v2.variable.stinfo['relations']) - len(v2.variable.stinfo['uidrels']) - if nbrels > 1: - constraints.setdefault(v1.name, []).append( - RelationRestriction(node, self._dsget, prefix)) - # just init an empty list for v2 variable to avoid a - # TypeRestriction being added for it - constraints.setdefault(v2.name, []) - break - else: - constraints.setdefault(rhs.name, []).append( - VariableSelection(node, self._dsget, 's')) - - def _visit_non_final_neged_relation(self, rschema, node, constraints): - lhs, rhs = node.get_variable_parts() - for v1, v2, prefix in ((lhs, rhs, 's'), (rhs, lhs, 'o')): - stinfo = v2.variable.stinfo - if not stinfo['selected'] and len(stinfo['relations']) == 1: - constraints.setdefault(v1.name, []).append( - NotRelationRestriction(node, self._dsget, prefix)) - constraints.setdefault(v2.name, []) - break - else: - self._visit_non_final_relation(rschema, node, constraints, True) - - def _visit_final_relation(self, rschema, node, constraints, extra): - varname = node.children[0].name - if rschema.type == 'eid': - constraints.setdefault(varname, []).append( - EidRestriction(node, self._dsget)) - else: - rhs = node.children[1].children[0] - if isinstance(rhs, nodes.VariableRef): - constraints.setdefault(rhs.name, []).append( - VariableSelection(node, self._dsget)) - elif isinstance(rhs, nodes.Constant): - if rschema.objects()[0] in ('Datetime', 'Date'): # XXX - constraints.setdefault(varname, []).append( - DateAttributeRestriction(node, extra['kwargs'])) - else: - constraints.setdefault(varname, []).append( - AttributeRestriction(node, extra['kwargs'])) - elif isinstance(rhs, nodes.Function) and rhs.name == 'IN': - constraints.setdefault(varname, []).append( - AttributeInRestriction(node, extra['kwargs'])) - else: - raise NotImplementedError() - - def _not_implemented(self, *args, **kwargs): - raise NotImplementedError() - - visit_or = _not_implemented - # shouldn't occurs - visit_set = _not_implemented - visit_insert = _not_implemented - visit_delete = _not_implemented - - -from logging import getLogger -from cubicweb import set_log_methods -set_log_methods(RQLInterpreter, getLogger('cubicweb.goa.rqlinterpreter')) -set_log_methods(Restriction, getLogger('cubicweb.goa.rqlinterpreter')) diff -r e3994fcc21c3 -r 1806148d6ce8 goa/skel/app.yaml.tmpl --- a/goa/skel/app.yaml.tmpl Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -application: %(appname)s -version: 0-1 -runtime: python -api_version: 1 - -handlers: -- url: /admin/.* - script: $PYTHON_LIB/google/appengine/ext/admin - login: admin -- url: /data - static_dir: cubes/shared/data -- url: /fckeditor - static_dir: fckeditor -- url: /_load - script: loader.py - login: admin -- url: .* - script: main.py - # comment the line below to allow anonymous access or if you don't want to use - # google authentication service - login: required - -skip_files: | - ^(.*/)?( - (app\.yaml)| - (app\.yml)| - (index\.yaml)| - (index\.yml)| - (#.*#)| - (.*~)| - (.*\.py[co])| - (.*\.xcf)| - (.*\.asp)| - (.*\.aspx)| - (.*\.cfm)| - (.*\.po)| - (.*/RCS/.*)| - (\..*)| - (.*ChangeLog)| - (.*README)| - (.*TODO)| - (.*DEPENDS)| - (.*MANIFEST)| - (.*MANIFEST.in)| - (.*setup\.py)| - (.*,cover)| - (.*\.orig)| - (.*/test/.*)| - (.*/tests/.*)| - (.*/bin/.*)| - (.*/build/.*)| - (.*/debian/.*)| - (.*/doc/.*)| - (.*/skins/office2003/.*)| - (.*/editor/skins/silver/.*)| - (.*/editor/filemanager/.*)| - (.*/editor/plugins/.*)| - (.*/editor/images/smiley/.*)| - (.*/editor/.*spellerpages.*)| - (.*/docutils/writers/s5_html/.*)| - (.*/docutils/writers/latex2e/.*)| - (.*/docutils/writers/newlatex2e/.*)| - (.*/docutils/writers/pep_html/.*)| - (bin/.*)| - (tools/.*)| - (cubicweb.*/data/.*\.js)| - (cubicweb.*/data/.*\.css)| - (cubicweb.*/data/.*\.png)| - (cubicweb.*/data/.*\.gif)| - (cubicweb.*/data/.*\.gif)| - )$ - diff -r e3994fcc21c3 -r 1806148d6ce8 goa/skel/bootstrap_cubes diff -r e3994fcc21c3 -r 1806148d6ce8 goa/skel/custom.py --- a/goa/skel/custom.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +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 . -""" - -""" -def postinit(vreg): - """this callback is called at the end of initialization process - and can be used to load explicit modules (views or entities). - - For instance : - import someviews - vreg.load_module(someviws) - """ - # from migration import migrate - # migrate(vreg) diff -r e3994fcc21c3 -r 1806148d6ce8 goa/skel/cw-cubes/README.txt --- a/goa/skel/cw-cubes/README.txt Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -This directory is where you should put your lax components. - -For your application to actually use a component, you also -have to modify the ``INCLUDED_COMPONENTS`` variable in -the ``custom.py`` module. - - diff -r e3994fcc21c3 -r 1806148d6ce8 goa/skel/i18n/en.po --- a/goa/skel/i18n/en.po Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -# LAX application po file - -msgid "" -msgstr "" -"Project-Id-Version: erudi 2.48.2\n" -"PO-Revision-Date: 2008-03-28 18:14+0100\n" -"Last-Translator: Logilab Team \n" -"Language-Team: fr \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: ginco-devtools\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - diff -r e3994fcc21c3 -r 1806148d6ce8 goa/skel/i18n/fr.po --- a/goa/skel/i18n/fr.po Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -# LAX application po file - -msgid "" -msgstr "" -"Project-Id-Version: erudi 2.48.2\n" -"PO-Revision-Date: 2008-03-28 18:14+0100\n" -"Last-Translator: Logilab Team \n" -"Language-Team: fr \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: ginco-devtools\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - - diff -r e3994fcc21c3 -r 1806148d6ce8 goa/skel/loader.py --- a/goa/skel/loader.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +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 . -""" - -""" -if __name__ == '__main__': - - from os.path import dirname, abspath - from cubicweb import goa - from cubicweb.goa.goaconfig import GAEConfiguration - from cubicweb.goa.dbinit import create_user, create_groups - - # compute instance's root directory - APPLROOT = dirname(abspath(__file__)) - # apply monkey patches first - goa.do_monkey_patch() - # get instance's configuration (will be loaded from app.conf file) - GAEConfiguration.uiprops['JAVASCRIPTS'].append('DATADIR/goa.js') - config = GAEConfiguration('toto', APPLROOT) - # create default groups - create_groups() - if not config['use-google-auth']: - # create default admin - create_user('admin', 'admin', ('managers', 'users')) - # create anonymous user if specified - anonlogin = config['anonymous-user'] - if anonlogin: - create_user(anonlogin, config['anonymous-password'], ('guests',)) - print 'content initialized' diff -r e3994fcc21c3 -r 1806148d6ce8 goa/skel/main.py --- a/goa/skel/main.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +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 . -"""module defining the root handler for a lax instance. You should not have -to change anything here. - -""" -__docformat__ = "restructuredtext en" - -# compute instance's root directory -from os.path import dirname, abspath -APPLROOT = dirname(abspath(__file__)) - -# apply monkey patches first -from cubicweb import goa -goa.do_monkey_patch() - -# get instance's configuration (will be loaded from app.conf file) -from cubicweb.goa.goaconfig import GAEConfiguration -GAEConfiguration.uiprops['JAVASCRIPTS'].append('DATADIR/goa.js') -config = GAEConfiguration('toto', APPLROOT) - -# dynamic objects registry -from cubicweb.goa.goavreg import GAEVregistry -vreg = GAEVregistry(config, debug=goa.MODE == 'dev') - -# trigger automatic classes registration (metaclass magic), should be done -# before schema loading -import custom - -# load instance'schema -vreg.schema = config.load_schema() - -# load dynamic objects -vreg.load(APPLROOT) - -# call the postinit so custom get a chance to do instance specific stuff -custom.postinit(vreg) - -from cubicweb.wsgi.handler import CubicWebWSGIApplication -application = CubicWebWSGIApplication(config, vreg=vreg) - -# main function so this handler module is cached -def main(): - from wsgiref.handlers import CGIHandler - CGIHandler().run(application) - -if __name__ == "__main__": - main() diff -r e3994fcc21c3 -r 1806148d6ce8 goa/skel/schema.py --- a/goa/skel/schema.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +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 . -""" - -""" - -class Blog(EntityType): - title = String(maxsize=50, required=True) - description = String() - -class BlogEntry(EntityType): - title = String(maxsize=100, required=True) - publish_date = Date(default='TODAY') - text = RichString(fulltextindexed=True) - category = String(vocabulary=('important','business')) - entry_of = SubjectRelation('Blog', cardinality='?*') diff -r e3994fcc21c3 -r 1806148d6ce8 goa/skel/views.py --- a/goa/skel/views.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -# custom application views -# 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 . -""" - -""" -from datetime import date - -from logilab.common.date import last_day - -from cubicweb.web.views import baseviews, boxes, calendar -from cubicweb.web.htmlwidgets import BoxLink, BoxWidget - -_ = unicode - - -class BlogEntryPrimaryView(baseviews.PrimaryView): - accepts = ('BlogEntry',) - - def cell_call(self, row, col): - entity = self.rset.get_entity(row, col) - self.w(u'

%s

' % entity.dc_title()) - entity.view('metadata', w=self.w) - self.w(entity.printable_value('text')) - - -class BlogArchiveBox(boxes.BoxTemplate): - """side box usually displaying some related entities in a primary view""" - id = 'blog_archives_box' - title = _('blog archives') - - def call(self, **kwargs): - """display a list of entities by calling their view - """ - _ = self.req._ - rset = self.req.execute('Any CD ORDERBY CD DESC WHERE B is Blog, B creation_date CD') - blogmonths = [] - for (blogdate,) in rset: - year, month = blogdate.year, blogdate.month - if (year, month) not in blogmonths: - blogmonths.append( (year, month) ) - box = BoxWidget(_('Blog archives'), id=self.id) - for year, month in blogmonths: - firstday = date(year, month, 1) - lastday = last_day(firstday) - rql = ('Any B WHERE B is BlogEntry, B creation_date >= "%s", B creation_date <= "%s"' - % (firstday.strftime('%Y-%m-%d'), lastday.strftime('%Y-%m-%d'))) - url = self.build_url(rql=rql) - label = u'%s %s' % (_(calendar.MONTHNAMES[month-1]), year) - box.append( BoxLink(url, label) ) - box.render(self.w) - - - - diff -r e3994fcc21c3 -r 1806148d6ce8 goa/test/data/__init__.py --- a/goa/test/data/__init__.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +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 . -"""zou - -""" diff -r e3994fcc21c3 -r 1806148d6ce8 goa/test/data/bootstrap_cubes diff -r e3994fcc21c3 -r 1806148d6ce8 goa/test/data/schema.py --- a/goa/test/data/schema.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +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 . -""" - -""" - - -class YamsEntity(EntityType): - if 'Blog' in defined_types and 'Article' in defined_types: - ambiguous_relation = SubjectRelation(('Blog', 'Article')) - if 'Blog' in defined_types: - inlined_relation = SubjectRelation('Blog', cardinality='?*') - -class inlined_relation(RelationType): - inlined = True - diff -r e3994fcc21c3 -r 1806148d6ce8 goa/test/data/settings.py --- a/goa/test/data/settings.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +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 . -""" - -""" -TEMPLATE_DEBUG = False diff -r e3994fcc21c3 -r 1806148d6ce8 goa/test/data/views.py --- a/goa/test/data/views.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -# -*- coding: utf-8 -*- -# 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 . -""" - -""" -import os -os.environ["DJANGO_SETTINGS_MODULE"] = 'data.settings' - -from django import template - - -def encode_output(self, output): - # Check type so that we don't run str() on a Unicode object - if not isinstance(output, basestring): - return unicode(output) - return output - -template.VariableNode.encode_output = encode_output - -from cubicweb.view import StartupView - -INDEX_TEMPLATE = template.Template(u''' -

hellô {{ user.login }}

-''') - -class MyIndex(StartupView): - id = 'index' - - def call(self): - ctx = template.Context({'user': self.req.user}) - return INDEX_TEMPLATE.render(ctx) diff -r e3994fcc21c3 -r 1806148d6ce8 goa/test/unittest_db.py --- a/goa/test/unittest_db.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -# -*- coding: utf-8 -*- -# 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 . -""" - -""" -from cubicweb.goa.testlib import * - -from cubicweb import Binary -from cubicweb.goa.goaconfig import GAEConfiguration -from cubicweb.server.utils import crypt_password - -from google.appengine.api.datastore_types import Text, Blob - - -class Blog(db.Model): - data = db.BlobProperty() - -class DBTest(GAEBasedTC): - config = GAEConfiguration('toto') - config.global_set_option('use-google-auth', False) - - MODEL_CLASSES = (Blog,) - - def test_set_none_relation(self): - eprop = self.add_entity('CWProperty', pkey=u'ui.language', value=u'en') - self.failUnless('s_for_user' in eprop._dbmodel) - self.assertEquals(eprop._dbmodel['s_for_user'], None) - - def test_euser_key(self): - euser = self.add_entity('CWUser', login=u'toto', upassword='toto') - self.assertEquals(euser.key().name(), 'key_toto') - - def test_egroup_key(self): - egroup = self.add_entity('CWGroup', name=u'toto') - self.assertEquals(egroup.key().name(), 'key_toto') - - def test_password_encryption(self): - euser = self.add_entity('CWUser', login=u'toto', upassword='toto') - self.failUnless(euser.upassword != 'toto', euser.upassword) - self.assertEquals(crypt_password('toto', euser.upassword[:2]), euser.upassword) - - def test_long_text(self): - # datastore string type is limited to 500 bytes - text = u'e'*501 - entity = self.add_entity('State', name=u'test', description=text) - self.assertIsInstance(entity.description, unicode) - self.failIf(isinstance(entity.description, Text)) - self.assertEquals(entity.description, text) - - def test_long_accentued_text(self): - # datastore string type is limited to 500 bytes - text = u'é'*500 - entity = self.add_entity('State', name=u'test', description=text) - self.assertIsInstance(entity.description, unicode) - self.failIf(isinstance(entity.description, Text)) - self.assertEquals(entity.description, text) - - def test_blob(self): - data = 'e'*501 - entity = self.add_entity('Blog', data=data) - self.assertIsInstance(entity.data, Binary) - value = entity.data.getvalue() - self.failIf(isinstance(value, Blob)) - self.assertEquals(value, data) - - -if __name__ == '__main__': - from logilab.common.testlib import unittest_main - unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 goa/test/unittest_editcontroller.py --- a/goa/test/unittest_editcontroller.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,430 +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 . -""" - -""" -from cubicweb.goa.testlib import * - -from urllib import unquote - -from cubicweb import ValidationError -from cubicweb.uilib import rql_for_eid - -from cubicweb.web import INTERNAL_FIELD_VALUE, Redirect - -from cubicweb.goa.goaconfig import GAEConfiguration -from cubicweb.entities.authobjs import CWUser - - -class EditControllerTC(GAEBasedTC): - - config = GAEConfiguration('toto') - config.global_set_option('use-google-auth', False) - config.global_set_option('schema-type', 'yams') - config.global_set_option('included-cubes', ()) - config.global_set_option('included-yams-cubes', ('blog',)) - - MODEL_CLASSES = () - from cubicweb.web.views import editcontroller - from cubicweb.entities import lib - LOAD_APP_MODULES = (editcontroller, lib) - - def setUp(self): - GAEBasedTC.setUp(self) - self.req = self.request() - self.ctrl = self.get_ctrl(self.req) - - def get_ctrl(self, req): - return self.vreg.select('controllers', 'edit', req=req, appli=self) - - def publish(self, req): - assert req is self.ctrl.req - try: - result = self.ctrl.publish() - req.cnx.commit() - except Redirect: - req.cnx.commit() - raise - except: - req.cnx.rollback() - raise - return result - - def expect_redirect_publish(self, req=None): - if req is not None: - self.ctrl = self.get_ctrl(req) - else: - req = self.req - try: - res = self.publish(req) - except Redirect, ex: - try: - path, params = ex.location.split('?', 1) - except: - path, params = ex.location, "" - req._url = path - cleanup = lambda p: (p[0], unquote(p[1])) - params = dict(cleanup(p.split('=', 1)) for p in params.split('&') if p) - return req.relative_path(False), params # path.rsplit('/', 1)[-1], params - else: - self.fail('expected a Redirect exception') - - def test_noparam_edit(self): - """check behaviour of this controller without any form parameter""" - self.req.form = {} - self.assertRaises(ValidationError, self.publish, self.req) - - def test_validation_unique(self): - """test creation of two linked entities""" - user = self.user - self.req.form = {'eid': 'X', '__type:X': 'CWUser', - 'login:X': self.user.login, 'edits-login:X': u'', - 'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'', - } - self.assertRaises(ValidationError, self.publish, self.req) - - - def test_user_editing_itself(self): - """checking that a manager user can edit itself""" - self.skip('missing actual gae support, retry latter') - user = self.user - basegroups = [str(eid) for eid, in self.req.execute('CWGroup G WHERE X in_group G, X eid %(x)s', {'x': user.eid})] - groupeids = [eid for eid, in self.req.execute('CWGroup G WHERE G name in ("managers", "users")')] - groups = [str(eid) for eid in groupeids] - stateeid = [eid for eid, in self.req.execute('State S WHERE S name "activated"')][0] - self.req.form = { - 'eid': user.eid, - '__type:'+user.eid: 'CWUser', - 'login:'+user.eid: unicode(user.login), - 'firstname:'+user.eid: u'Th\xe9nault', - 'surname:'+user.eid: u'Sylvain', - 'in_group:'+user.eid: groups, - 'in_state:'+user.eid: stateeid, - # - 'edits-login:'+user.eid: unicode(user.login), - 'edits-firstname:'+user.eid: u'', - 'edits-surname:'+user.eid: u'', - 'edits-in_group:'+user.eid: basegroups, - 'edits-in_state:'+user.eid: stateeid, - } - path, params = self.expect_redirect_publish() - e = self.req.execute('Any X WHERE X eid %(x)s', {'x': user.eid}, 'x').get_entity(0, 0) - self.assertEquals(e.firstname, u'Th\xe9nault') - self.assertEquals(e.surname, u'Sylvain') - self.assertEquals(e.login, user.login) - self.assertEquals([g.eid for g in e.in_group], groupeids) - self.assertEquals(e.in_state[0].eid, stateeid) - - def test_user_can_change_its_password(self): - user = self.create_user('user') - cnx = self.login('user') - req = self.request() - #self.assertEquals(self.ctrl.schema['CWUser']._groups['read'], - # ('managers', 'users')) - req.form = { - 'eid': user.eid, '__type:'+user.eid: 'CWUser', - '__maineid' : str(user.eid), - 'upassword:'+user.eid: 'tournicoton', - 'upassword-confirm:'+user.eid: 'tournicoton', - 'edits-upassword:'+user.eid: '', - } - path, params = self.expect_redirect_publish(req) - cnx.commit() # commit to check we don't get late validation error for instance - self.assertEquals(path, 'euser/user') - self.failIf('vid' in params) - - def test_user_editing_itself_no_relation(self): - """checking we can edit an entity without specifying some required - relations (meaning no changes) - """ - user = self.user - groupeids = [eid for eid, in self.req.execute('CWGroup G WHERE X in_group G, X eid %(x)s', {'x': user.eid})] - self.req.form = { - 'eid': user.eid, - '__type:'+user.eid: 'CWUser', - 'login:'+user.eid: unicode(user.login), - 'firstname:'+user.eid: u'Th\xe9nault', - 'surname:'+user.eid: u'Sylvain', - # - 'edits-login:'+user.eid: unicode(user.login), - 'edits-firstname:'+user.eid: u'', - 'edits-surname:'+user.eid: u'', - } - path, params = self.expect_redirect_publish() - self.req.drop_entity_cache(user.eid) - e = self.req.execute('Any X WHERE X eid %(x)s', {'x': user.eid}, 'x').get_entity(0, 0) - self.assertEquals(e.login, user.login) - self.assertEquals(e.firstname, u'Th\xe9nault') - self.assertEquals(e.surname, u'Sylvain') - self.assertUnorderedIterableEquals([g.eid for g in e.in_group], groupeids) - #stateeids = [eid for eid, in self.req.execute('State S WHERE S name "activated"')] - #self.assertEquals([s.eid for s in e.in_state], stateeids) - - - def test_create_multiple_linked(self): - gueid = self.req.execute('CWGroup G WHERE G name "users"')[0][0] - self.req.form = {'eid': ['X', 'Y'], - - '__type:X': 'CWUser', - '__maineid' : 'X', - 'login:X': u'adim', 'edits-login:X': u'', - 'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'', - 'surname:X': u'Di Mascio', 'edits-surname:X': '', - - 'in_group:X': gueid, 'edits-in_group:X': INTERNAL_FIELD_VALUE, - - '__type:Y': 'EmailAddress', - 'address:Y': u'dima@logilab.fr', 'edits-address:Y': '', - 'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE, - } - path, params = self.expect_redirect_publish() - # should be redirected on the created person - self.assertEquals(path, 'euser/adim') - e = self.req.execute('Any P WHERE P surname "Di Mascio"').get_entity(0, 0) - self.assertEquals(e.surname, 'Di Mascio') - email = e.use_email[0] - self.assertEquals(email.address, 'dima@logilab.fr') - - def test_edit_multiple_linked(self): - peid = self.create_user('adim').eid - self.req.form = {'eid': [peid, 'Y'], - '__type:%s'%peid: 'CWUser', - 'surname:%s'%peid: u'Di Masci', 'edits-surname:%s'%peid: '', - - '__type:Y': 'EmailAddress', - 'address:Y': u'dima@logilab.fr', 'edits-address:Y': '', - 'use_email:%s'%peid: 'Y', 'edits-use_email:%s'%peid: INTERNAL_FIELD_VALUE, - - '__redirectrql': 'Any X WHERE X eid %s'%peid, - } - path, params = self.expect_redirect_publish() - # should be redirected on the created person - eid = params['rql'].split()[-1] - e = self.req.execute('Any X WHERE X eid %(x)s', {'x': eid}, 'x').get_entity(0, 0) - self.assertEquals(e.surname, 'Di Masci') - email = e.use_email[0] - self.assertEquals(email.address, 'dima@logilab.fr') - - emaileid = email.eid - self.req.form = {'eid': [peid, emaileid], - '__type:%s'%peid: 'CWUser', - 'surname:%s'%peid: u'Di Masci', 'edits-surname:%s'%peid: 'Di Masci', - '__type:%s'%emaileid: 'EmailAddress', - 'address:%s'%emaileid: u'adim@logilab.fr', 'edits-address:%s'%emaileid: 'dima@logilab.fr', - 'use_email:%s'%peid: emaileid, 'edits-use_email:%s'%peid: emaileid, - '__redirectrql': 'Any X WHERE X eid %s'%peid, - } - path, params = self.expect_redirect_publish() - # should be redirected on the created person - eid = params['rql'].split()[-1] - # XXX this should not be necessary, it isn't with regular cubicweb - self.req._eid_cache = {} - e = self.req.execute('Any X WHERE X eid %(x)s', {'x': eid}, 'x').get_entity(0, 0) - self.assertEquals(e.surname, 'Di Masci') - email = e.use_email[0] - self.assertEquals(email.address, 'adim@logilab.fr') - - - def test_password_confirm(self): - """test creation of two linked entities - """ - user = self.user - self.req.form = {'__cloned_eid:X': user.eid, - 'eid': 'X', '__type:X': 'CWUser', - 'login:X': u'toto', 'edits-login:X': u'', - 'upassword:X': u'toto', 'edits-upassword:X': u'', - } - self.assertRaises(ValidationError, self.publish, self.req) - self.req.form = {'__cloned_eid:X': user.eid, - 'eid': 'X', '__type:X': 'CWUser', - 'login:X': u'toto', 'edits-login:X': u'', - 'upassword:X': u'toto', 'upassword-confirm:X': u'tutu', 'edits-upassword:X': u'', - } - self.assertRaises(ValidationError, self.publish, self.req) - - - def test_req_pending_insert(self): - """make sure req's pending insertions are taken into account""" - tmpgroup = self.add_entity('CWGroup', name=u"test") - user = self.user - self.req.set_session_data('pending_insert', set([(user.eid, 'in_group', tmpgroup.eid)])) - path, params = self.expect_redirect_publish() - usergroups = [gname for gname, in - self.req.execute('Any N WHERE G name N, U in_group G, U eid %(u)s', {'u': user.eid})] - self.assertUnorderedIterableEquals(usergroups, ['managers', 'users', 'test']) - self.assertEquals(self.req.get_pending_inserts(), []) - - - def test_req_pending_delete(self): - """make sure req's pending deletions are taken into account""" - user = self.user - groupeid = self.req.execute('INSERT CWGroup G: G name "test", U in_group G WHERE U eid %(x)s', - {'x': user.eid})[0][0] - usergroups = [gname for gname, in - self.req.execute('Any N WHERE G name N, U in_group G, U eid %(u)s', {'u': user.eid})] - # just make sure everything was set correctly - self.assertUnorderedIterableEquals(usergroups, ['managers', 'users', 'test']) - # now try to delete the relation - self.req.set_session_data('pending_delete', set([(user.eid, 'in_group', groupeid)])) - path, params = self.expect_redirect_publish() - usergroups = [gname for gname, in - self.req.execute('Any N WHERE G name N, U in_group G, U eid %(u)s', {'u': user.eid})] - self.assertUnorderedIterableEquals(usergroups, ['managers', 'users']) - #self.assertUnorderedIterableEquals(usergroups, ['managers']) - self.assertEquals(self.req.get_pending_deletes(), []) - - def test_custom_attribute_handler(self): - def custom_login_edit(self, formparams, value, relations): - formparams['login'] = value.upper() - relations.append('X login %(login)s') - CWUser.custom_login_edit = custom_login_edit - try: - user = self.user - eid = repr(user.eid) - self.req.form = { - 'eid': eid, - '__type:'+eid: 'CWUser', - 'login:'+eid: u'foo', - 'edits-login:'+eid: unicode(user.login), - } - path, params = self.expect_redirect_publish() - rset = self.req.execute('Any L WHERE X eid %(x)s, X login L', {'x': user.eid}, 'x') - self.assertEquals(rset[0][0], 'FOO') - finally: - del CWUser.custom_login_edit - - def test_redirect_apply_button(self): - redirectrql = rql_for_eid(4012) # whatever - self.req.form = { - 'eid': 'A', '__type:A': 'BlogEntry', - '__maineid' : 'A', - 'content:A': u'"13:03:43"', 'edits-content:A': '', - 'title:A': u'huuu', 'edits-title:A': '', - '__redirectrql': redirectrql, - '__redirectvid': 'primary', - '__redirectparams': 'toto=tutu&tata=titi', - '__form_id': 'edition', - '__action_apply': '', - } - path, params = self.expect_redirect_publish() - self.failUnless(path.startswith('blogentry/')) - eid = path.split('/')[1] - self.assertEquals(params['vid'], 'edition') - self.assertNotEquals(eid, '4012') - self.assertEquals(params['__redirectrql'], redirectrql) - self.assertEquals(params['__redirectvid'], 'primary') - self.assertEquals(params['__redirectparams'], 'toto=tutu&tata=titi') - - def test_redirect_ok_button(self): - redirectrql = rql_for_eid(4012) # whatever - self.req.form = { - 'eid': 'A', '__type:A': 'BlogEntry', - '__maineid' : 'A', - 'content:A': u'"13:03:43"', 'edits-content:A': '', - 'title:A': u'huuu', 'edits-title:A': '', - '__redirectrql': redirectrql, - '__redirectvid': 'primary', - '__redirectparams': 'toto=tutu&tata=titi', - '__form_id': 'edition', - } - path, params = self.expect_redirect_publish() - self.assertEquals(path, 'view') - self.assertEquals(params['rql'], redirectrql) - self.assertEquals(params['vid'], 'primary') - self.assertEquals(params['tata'], 'titi') - self.assertEquals(params['toto'], 'tutu') - - def test_redirect_delete_button(self): - eid = self.add_entity('BlogEntry', title=u'hop', content=u'hop').eid - self.req.form = {'eid': str(eid), '__type:%s'%eid: 'BlogEntry', - '__action_delete': ''} - path, params = self.expect_redirect_publish() - self.assertEquals(path, 'blogentry') - self.assertEquals(params, {u'__message': u'entity deleted'}) - eid = self.add_entity('EmailAddress', address=u'hop@logilab.fr').eid - self.req.execute('SET X use_email E WHERE E eid %(e)s, X eid %(x)s', - {'x': self.user.eid, 'e': eid}, 'x') - self.commit() - self.req.form = {'eid': str(eid), '__type:%s'%eid: 'EmailAddress', - '__action_delete': ''} - path, params = self.expect_redirect_publish() - self.assertEquals(unquote(path), 'euser/'+self.user.login) - self.assertEquals(params, {u'__message': u'entity deleted'}) - eid1 = self.add_entity('BlogEntry', title=u'hop', content=u'hop').eid - eid2 = self.add_entity('EmailAddress', address=u'hop@logilab.fr').eid - self.req.form = {'eid': [str(eid1), str(eid2)], - '__type:%s'%eid1: 'BlogEntry', - '__type:%s'%eid2: 'EmailAddress', - '__action_delete': ''} - path, params = self.expect_redirect_publish() - self.assertEquals(path, 'view') - self.assertEquals(params, {u'__message': u'entities deleted'}) - - - def test_nonregr_multiple_empty_email_addr(self): - gueid = self.req.execute('CWGroup G WHERE G name "users"')[0][0] - self.req.form = {'eid': ['X', 'Y'], - - '__type:X': 'CWUser', - 'login:X': u'adim', 'edits-login:X': u'', - 'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'', - 'in_group:X': gueid, 'edits-in_group:X': INTERNAL_FIELD_VALUE, - - '__type:Y': 'EmailAddress', - 'address:Y': u'', 'edits-address:Y': '', - 'alias:Y': u'', 'edits-alias:Y': '', - 'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE, - } - self.assertRaises(ValidationError, self.publish, self.req) - - - def test_nonregr_rollback_on_validation_error(self): - self.skip('lax fix me') - p = self.create_user("doe") - # do not try to skip 'primary_email' for this test - old_skips = p.__class__.skip_copy_for - p.__class__.skip_copy_for = () - try: - e = self.add_entity('EmailAddress', address=u'doe@doe.com') - self.req.execute('SET P use_email E, P primary_email E WHERE P eid %(p)s, E eid %(e)s', - {'p' : p.eid, 'e' : e.eid}) - self.req.form = {'__cloned_eid:X': p.eid, - 'eid': 'X', '__type:X': 'CWUser', - 'login': u'dodo', 'edits-login': u'dodo', - 'surname:X': u'Boom', 'edits-surname:X': u'', - '__errorurl' : "whatever but required", - } - # try to emulate what really happens in the web application - # 1/ validate form => EditController.publish raises a ValidationError - # which fires a Redirect - # 2/ When re-publishing the copy form, the publisher implicitly commits - try: - self.app.publish('edit', self.req) - except Redirect: - self.req.form['rql'] = 'Any X WHERE X eid %s' % p.eid - self.req.form['vid'] = 'copy' - self.app.publish('view', self.req) - rset = self.req.execute('CWUser P WHERE P surname "Boom"') - self.assertEquals(len(rset), 0) - finally: - p.__class__.skip_copy_for = old_skips - - -if __name__ == '__main__': - from logilab.common.testlib import unittest_main - unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 goa/test/unittest_metadata.py --- a/goa/test/unittest_metadata.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +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 . -""" - -""" -from cubicweb.goa.testlib import * - -import time -from mx.DateTime import DateTimeType -from datetime import datetime -from cubicweb.goa import db - -from google.appengine.api import datastore - -class Article(db.Model): - content = db.TextProperty() - synopsis = db.StringProperty(default='hello') - -class Blog(db.Model): - diem = db.DateProperty(required=True, auto_now_add=True) - title = db.StringProperty(required=True) - content = db.TextProperty() - talks_about = db.ReferenceProperty(Article) - cites = db.SelfReferenceProperty() - - -class MetaDataTC(GAEBasedTC): - MODEL_CLASSES = (Article, Blog) - - def setUp(self): - GAEBasedTC.setUp(self) - self.req = self.request() - self.a = self.add_entity('Article') - self.p = self.add_entity('CWProperty', pkey=u'ui.language', value=u'en') - self.session.commit() - - def _test_timestamp(self, entity, attr, sleep=0.1): - timestamp = getattr(entity, attr) - self.failUnless(timestamp) - self.assertIsInstance(timestamp, DateTimeType) - self.assertIsInstance(entity.to_gae_model()['s_'+attr], datetime) - time.sleep(sleep) - if entity.id == 'Article': - entity.set_attributes(content=u'zou') - else: - entity.set_attributes(value=u'en') - self.session.commit() - return timestamp - - def test_creation_date_dbmodel(self): - cdate = self._test_timestamp(self.a, 'creation_date') - self.assertEquals(cdate, self.a.creation_date) - - def test_creation_date_yams(self): - cdate = self._test_timestamp(self.p, 'creation_date') - self.assertEquals(cdate, self.p.creation_date) - - def test_modification_date_dbmodel(self): - mdate = self._test_timestamp(self.a, 'modification_date', sleep=1) - a = self.execute('Any X WHERE X eid %(x)s', {'x': self.a.eid}, 'x').get_entity(0, 0) - self.failUnless(mdate < a.modification_date, (mdate, a.modification_date)) - - def test_modification_date_yams(self): - mdate = self._test_timestamp(self.p, 'modification_date', sleep=1) - p = self.execute('Any X WHERE X eid %(x)s', {'x': self.p.eid}, 'x').get_entity(0, 0) - self.failUnless(mdate < p.modification_date, (mdate, p.modification_date)) - - def _test_owned_by(self, entity): - self.assertEquals(len(entity.owned_by), 1) - owner = entity.owned_by[0] - self.assertIsInstance(owner, db.Model) - dbmodel = entity.to_gae_model() - self.assertEquals(len(dbmodel['s_owned_by']), 1) - self.assertIsInstance(dbmodel['s_owned_by'][0], datastore.Key) - - def test_owned_by_dbmodel(self): - self._test_owned_by(self.a) - - def test_owned_by_yams(self): - self._test_owned_by(self.p) - - def _test_created_by(self, entity): - self.assertEquals(len(entity.created_by), 1) - creator = entity.created_by[0] - self.assertIsInstance(creator, db.Model) - self.assertIsInstance(entity.to_gae_model()['s_created_by'], datastore.Key) - - def test_created_by_dbmodel(self): - self._test_created_by(self.a) - - def test_created_by_dbmodel(self): - self._test_created_by(self.p) - - def test_user_owns_dbmodel(self): - self.failUnless(self.req.user.owns(self.a.eid)) - - def test_user_owns_yams(self): - self.failUnless(self.req.user.owns(self.p.eid)) - - def test_is_relation(self): - en = self.execute('Any EN WHERE E name EN, X is E, X eid %(x)s', {'x': self.a.eid}, 'x')[0][0] - self.assertEquals(en, 'Article') - en = self.execute('Any EN WHERE E name EN, X is E, X eid %(x)s', {'x': self.p.eid}, 'x')[0][0] - self.assertEquals(en, 'CWProperty') - en = self.execute('Any EN WHERE E name EN, X is E, X eid %(x)s', {'x': self.req.user.eid}, 'x')[0][0] - self.assertEquals(en, 'CWUser') - - -if __name__ == '__main__': - from logilab.common.testlib import unittest_main - unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 goa/test/unittest_rql.py --- a/goa/test/unittest_rql.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,625 +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 . -from cubicweb.goa.testlib import * - -from cubicweb import Binary - -from logilab.common.testlib import unittest_main -from mx.DateTime import now, today, DateTimeType -import rql - -from google.appengine.api.datastore_types import Blob, Text - -# stored procedure definition ################################################# - -from rql.utils import register_function, FunctionDescr - -class itemtype_sort_value(FunctionDescr): - supported_backends = ('sqlite',) - rtype = 'Int' - -try: - register_function(itemtype_sort_value) -except AssertionError: - pass - -def init_sqlite_connexion(cnx): - def itemtype_sort_value(text): - return {"personal":2, "business":1}[text] - cnx.create_function("ITEMTYPE_SORT_VALUE", 1, itemtype_sort_value) - -from cubicweb.server import SQL_CONNECT_HOOKS -sqlite_hooks = SQL_CONNECT_HOOKS.setdefault('sqlite', []) -sqlite_hooks.append(init_sqlite_connexion) - -# end stored procedure definition ############################################# - -class Article(db.Model): - content = db.TextProperty() - synopsis = db.StringProperty(default=u'hello') - -class Blog(db.Model): - diem = db.DateProperty(required=True, auto_now_add=True) - content = db.TextProperty() - itemtype = db.StringProperty(required=True, choices=(u'personal', u'business')) - talks_about = db.ReferenceProperty(Article) - cites = db.SelfReferenceProperty() - data = db.BlobProperty() - - -class RQLTest(GAEBasedTC): - MODEL_CLASSES = (Article, Blog) - - def setUp(self): - GAEBasedTC.setUp(self) - # hack to make talks_about cardinality to ** instead of ?* - self.schema.rschema('talks_about').set_rproperty('Blog', 'Article', - 'cardinality', '**') - self.req = self.request() - self.article = self.add_entity('Article', content=u'very interesting') - self.blog = self.add_entity('Blog', itemtype=u'personal', content=u'hop') - self.execute('SET X talks_about Y WHERE X eid %(x)s, Y eid %(y)s', - {'x': self.blog.eid, 'y': self.article.eid}) - self.commit() - - def _check_rset_size(self, rset, row, col): - self.assertEquals(len(rset), row) - self.assertEquals(len(rset[0]), col) - self.assertEquals(len(rset.description), row) - self.assertEquals(len(rset.description[0]), col) - - def _check_blog_rset(self, rset): - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset.description[0][0], 'Blog') - self.assertEquals(rset[0][0], self.blog.eid) - self.assertEquals(rset.get_entity(0, 0).eid, self.blog.eid) - - def test_0_const(self): - rset = self.req.execute('Any 1') - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset[0][0], 1) - self.assertEquals(rset.description[0][0], 'Int') - - def test_0_now_const(self): - rset = self.req.execute('Any NOW') - self._check_rset_size(rset, 1, 1) - self.assertIsInstance(rset[0][0], DateTimeType) - self.assertEquals(rset.description[0][0], 'Datetime') - - def test_0_today_const(self): - rset = self.req.execute('Any TODAY') - self._check_rset_size(rset, 1, 1) - self.assertIsInstance(rset[0][0], DateTimeType) - self.assertEquals(rset[0][0], today()) - self.assertEquals(rset.description[0][0], 'Date') - - - def test_1_eid(self): - rset = self.req.execute('Any X WHERE X eid %(x)s', {'x': self.blog.eid}) - self._check_blog_rset(rset) - rset = self.req.execute('Any X WHERE X eid "%s"' % self.blog.eid) - self._check_blog_rset(rset) - - def test_1_eid_eid(self): - rset = self.req.execute('Any X,Y WHERE X eid %(x)s, Y eid %(y)s', {'x': self.blog.eid, - 'y': self.article.eid}) - self._check_rset_size(rset, 1, 2) - self.assertEquals(rset.description[0], ('Blog', 'Article')) - self.assertEquals(rset[0][0], self.blog.eid) - self.assertEquals(rset[0][1], self.article.eid) - - def test_1_eid_with_is(self): - self.assertRaises(rql.TypeResolverException, - self.req.execute, 'Any X WHERE X eid %(x)s, X is Article', {'x': self.blog.eid}) - rset = self.req.execute('Any X WHERE X eid %(x)s, X is Blog', {'x': self.blog.eid}) - self._check_blog_rset(rset) - - def test_1_is(self): - rset = self.req.execute('Any X WHERE X is Blog') - self._check_blog_rset(rset) - blog2 = Blog(itemtype=u'personal', content=u'hop') - blog2.put() - rset = self.req.execute('Any X WHERE X is Blog') - self.assertEquals(len(rset), 2) - self.assertEquals(rset.description, [('Blog',), ('Blog',)]) - - - def test_2_attribute_selection_1(self): - rset = self.req.execute('Any X,D,C WHERE X is Blog, X diem D, X content C') - self._check_rset_size(rset, 1, 3) - self.assertEquals(rset[0], [self.blog.eid, today(), u'hop']) - self.assertEquals(rset.description[0], ('Blog', 'Date', 'String')) - self.assertIsInstance(rset[0][1], DateTimeType) - - def test_2_attribute_selection_2(self): - rset = self.req.execute('Any D,C WHERE X is Blog, X diem D, X content C') - self._check_rset_size(rset, 1, 2) - self.assertEquals(rset[0], [today(), u'hop']) - self.assertEquals(rset.description[0], ('Date', 'String')) - - def test_2_attribute_selection_binary(self): - rset = self.req.execute('Any D WHERE X is Blog, X data D') - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset[0], [None]) - self.assertEquals(rset.description[0], ('Bytes',)) - self.blog['data'] = Binary('raw data') - self.blog.put() - rset = self.req.execute('Any D WHERE X is Blog, X data D') - self._check_rset_size(rset, 1, 1) - self.assertIsInstance(rset[0][0], Binary) - value = rset[0][0].getvalue() - self.assertIsInstance(value, str) - self.failIf(isinstance(value, Blob)) - self.assertEquals(value, 'raw data') - self.assertEquals(rset.description[0], ('Bytes',)) - - def test_2_attribute_selection_long_text(self): - self.blog['content'] = text = 'a'*501 - self.blog.put() - rset = self.req.execute('Any C WHERE X is Blog, X content C') - self._check_rset_size(rset, 1, 1) - self.assertIsInstance(rset[0][0], unicode) - self.failIf(isinstance(rset[0][0], Text)) - self.assertEquals(rset[0][0], text) - - def test_2_attribute_selection_transformation(self): - rset = self.req.execute('Any X,UPPER(C) WHERE X is Blog, X content C') - self._check_rset_size(rset, 1, 2) - self.assertEquals(rset[0], [self.blog.eid, u'HOP']) - self.assertEquals(rset.description[0], ('Blog', 'String',)) - - - def test_3_attribute_restriction(self): - rset = self.req.execute('Any X WHERE X itemtype "personal"') - self._check_blog_rset(rset) - rset = self.req.execute('Any X WHERE X itemtype "business"') - self.assertEquals(len(rset), 0) - - def test_3_ambigous_attribute_restriction_1(self): - rset = self.req.execute('Any X WHERE X content "hello"') - self.assertEquals(len(rset), 0) - - def test_3_ambigous_attribute_restriction_2(self): - rset = self.req.execute('Any X WHERE X content "hop"') - self._check_blog_rset(rset) - - def test_3_ambigous_attribute_restriction_3(self): - article = Article(content=u'hop') - article.put() - rset = self.req.execute('Any X WHERE X content "hop"') - self._check_rset_size(rset, 2, 1) - self.assertUnorderedIterableEquals([r[0] for r in rset], [self.blog.eid, article.eid]) - self.assertUnorderedIterableEquals([r[0] for r in rset.description], ['Blog', 'Article']) - - def test_3_incoherant_attribute_restriction(self): - rset = self.req.execute('Any X WHERE X eid %(x)s, X content "hola"', - {'x': self.blog.eid}) - self.assertEquals(len(rset), 0) - - def test_3_multiple_attribute_restriction(self): - rset = self.req.execute('Any X WHERE X content "hop", X itemtype "personal"') - self._check_blog_rset(rset) - - def test_3_incoherant_multiple_attribute_restriction(self): - rset = self.req.execute('Any X WHERE X content "hip", X itemtype "personal"') - self.assertEquals(len(rset), 0) - - def test_3_today_attribute_restriction(self): - rset = self.req.execute('Any X WHERE X diem < TODAY') - self.assertEquals(len(rset), 0) - rset = self.req.execute('Any X WHERE X diem <= TODAY') - self._check_blog_rset(rset) - rset = self.req.execute('Any X WHERE X diem > TODAY') - self.assertEquals(len(rset), 0) - rset = self.req.execute('Any X WHERE X diem >= TODAY') - self._check_blog_rset(rset) - - def test_3_now_attribute_restriction(self): - rset = self.req.execute('Any X WHERE X diem < NOW') - self._check_blog_rset(rset) - rset = self.req.execute('Any X WHERE X diem <= NOW') - self._check_blog_rset(rset) - rset = self.req.execute('Any X WHERE X diem > NOW') - self.assertEquals(len(rset), 0) - rset = self.req.execute('Any X WHERE X diem >= NOW') - self.assertEquals(len(rset), 0) - - def test_3_in_attribute_restriction(self): - self.skip('missing actual gae support, retry latter') - article2 = Article(content=u'hip') - rset = self.req.execute('Any X WHERE X content IN ("hop", "hip")') - self._check_rset_size(rset, 2, 1) - self.assertUnorderedIterableEquals([r[0] for r in rset], [self.blog.eid, article.eid]) - self.assertUnorderedIterableEquals([r[0] for r in rset.description], ['Blog', 'Article']) - - def test_3_like(self): - repo = self.config.repository() - versions = repo.get_versions() - self.assertEquals(versions.keys(), ['cubicweb']) - - def _setup_relation_description(self): - self.article2 = self.add_entity('Article', content=u'hop') - self.blog2 = self.add_entity('Blog', itemtype=u'personal', content=u'hip') - self.execute('SET X talks_about Y WHERE X eid %(x)s, Y eid %(y)s', - {'x': self.blog2.eid, 'y': self.article2.eid}) - self.blog3 = self.add_entity('Blog', itemtype=u'business', content=u'hep') - self.commit() - - def test_4_relation_restriction_1(self): - self._setup_relation_description() - rset = self.req.execute('Any X WHERE X talks_about Y') - self._check_rset_size(rset, 2, 1) - self.assertUnorderedIterableEquals([r[0] for r in rset], - [self.blog.eid, self.blog2.eid]) - self.assertUnorderedIterableEquals([r[0] for r in rset.description], ['Blog', 'Blog']) - - def test_4_relation_restriction_2(self): - self._setup_relation_description() - rset = self.req.execute('Any Y WHERE X talks_about Y') - self._check_rset_size(rset, 2, 1) - self.assertUnorderedIterableEquals([r[0] for r in rset], - [self.article.eid, self.article2.eid]) - self.assertUnorderedIterableEquals([r[0] for r in rset.description], - ['Article', 'Article']) - - def test_4_relation_restriction_3(self): - self._setup_relation_description() - rset = self.req.execute('Any X,Y WHERE X talks_about Y') - self._check_rset_size(rset, 2, 2) - self.assertUnorderedIterableEquals([tuple(r) for r in rset], - [(self.blog.eid, self.article.eid), - (self.blog2.eid, self.article2.eid)]) - self.assertUnorderedIterableEquals([tuple(r) for r in rset.description], - [('Blog', 'Article'), - ('Blog', 'Article')]) - - def test_4_relation_restriction_4(self): - self._setup_relation_description() - rset = self.req.execute('Any X,Y WHERE X talks_about Y, X eid %(x)s', - {'x': self.blog.eid}) - self._check_rset_size(rset, 1, 2) - self.assertEquals(rset[0], [self.blog.eid, self.article.eid]) - self.assertUnorderedIterableEquals(rset.description[0], ['Blog', 'Article']) - - def test_4_relation_restriction_5(self): - self._setup_relation_description() - rset = self.req.execute('Any X,Y WHERE X talks_about Y, Y eid %(x)s', - {'x': self.article.eid}) - self._check_rset_size(rset, 1, 2) - self.assertEquals(rset[0], [self.blog.eid, self.article.eid]) - self.assertUnorderedIterableEquals(rset.description[0], ['Blog', 'Article']) - - def test_4_relation_subject_restriction(self): - self._setup_relation_description() - rset = self.req.execute('Any X,Y WHERE X talks_about Y, X content %(c)s', - {'c': 'hop'}) - self._check_rset_size(rset, 1, 2) - self.assertEquals(rset[0], [self.blog.eid, self.article.eid]) - self.assertUnorderedIterableEquals(rset.description[0], ['Blog', 'Article']) - - def test_4_relation_object_restriction(self): - self._setup_relation_description() - rset = self.req.execute('Any X WHERE X is Blog, X talks_about Y, Y content %(c)s', - {'c': 'very interesting'}) - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset[0], [self.blog.eid]) - self.assertUnorderedIterableEquals(rset.description[0], ['Blog']) - - def test_4_relation_subject_object_restriction(self): - article2 = self.add_entity('Article', content=u'very interesting') - rset = self.req.execute('Any X,XC WHERE X is Blog, X content XC, X content %(xc)s, ' - 'X talks_about Y, Y content %(c)s', - {'xc': 'hop', 'c': 'very interesting'}) - self._check_rset_size(rset, 1, 2) - self.assertEquals(rset[0], [self.blog.eid, self.blog.content]) - self.assertUnorderedIterableEquals(rset.description[0], ['Blog', 'String']) - - def test_4_relation_subject_object_restriction_no_res(self): - article2 = self.add_entity('Article', content=u'very interesting') - rset = self.req.execute('Any X,XC WHERE X is Blog, X content XC, X content %(xc)s, ' - 'X talks_about Y, Y content %(c)s', - {'xc': 'hip', 'c': 'very interesting'}) - self.assertEquals(len(rset), 0) - - def test_4_relation_subject_object_restriction_no_res_2(self): - rset = self.req.execute('Any X,XC WHERE X is Blog, X content XC, X content %(xc)s, ' - 'X talks_about Y, Y content %(c)s', - {'xc': 'hop', 'c': 'not interesting'}) - self.assertEquals(len(rset), 0) - - def test_4_relation_restriction_7(self): - self._setup_relation_description() - rset = self.req.execute('Any XC,XD,YC WHERE X talks_about Y, Y eid %(x)s,' - 'X content XC, X diem XD, Y content YC', - {'x': self.article.eid}) - self._check_rset_size(rset, 1, 3) - self.assertEquals(rset[0], [self.blog.content, self.blog.diem, self.article.content]) - self.assertUnorderedIterableEquals(rset.description[0], ['String', 'Date', 'String']) - - def test_4_relation_restriction_8(self): - self._setup_relation_description() - rset = self.req.execute('Any X,Y WHERE X cites Y, Y eid %(x)s', {'x': self.blog.eid}) - self.assertEquals(len(rset), 0) - - def test_4_relation_restriction_9(self): - article2 = self.add_entity('Article', content=u'hop') - self.req.execute('SET X talks_about Y WHERE X eid %(x)s, Y eid %(y)s', - {'x': self.blog.eid, 'y': article2.eid}) - rset = self.req.execute('Any X,Y WHERE X talks_about Y, X eid %(x)s, Y eid %(y)s', - {'x': self.blog.eid, 'y': article2.eid}) - self._check_rset_size(rset, 1, 2) - - def test_4_ambiguous_subject_relation(self): - ye = self.add_entity('YamsEntity') - self.req.execute('SET X ambiguous_relation Y WHERE X eid %(x)s, Y eid %(y)s', - {'x': ye.eid, 'y': self.blog.eid}) - self.req.execute('SET X ambiguous_relation Y WHERE X eid %(x)s, Y eid %(y)s', - {'x': ye.eid, 'y': self.article.eid}) - self.commit() - #ye = self.vreg.etype_class('YamsEntity ')(req, None) - #ye.to_gae_model()['s_ambiguous_relation'] = [self.blog.key(), self.article.key()] - #ye.put() - rset = self.req.execute('Any X WHERE Y ambiguous_relation X') - self._check_rset_size(rset, 2, 1) - self.assertUnorderedIterableEquals([r[0] for r in rset], [self.blog.eid, self.article.eid]) - self.assertUnorderedIterableEquals([r[0] for r in rset.description], ['Blog', 'Article']) - rset = self.req.execute('Any X WHERE Y ambiguous_relation X, Y eid %(x)s', {'x': ye.eid}) - self._check_rset_size(rset, 2, 1) - self.assertUnorderedIterableEquals([r[0] for r in rset], [self.blog.eid, self.article.eid]) - self.assertUnorderedIterableEquals([r[0] for r in rset.description], ['Blog', 'Article']) - - def test_4_relation_selection(self): - req = self.request() - rset = req.execute('Any N WHERE G content N, U talks_about G, U eid %(u)s', {'u': self.blog.eid}) - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset[0][0], 'very interesting') - - - def test_5_orderby(self): - self._setup_relation_description() - rset = self.req.execute('Any X,XC ORDERBY XC WHERE X is Blog, X content XC') - self._check_rset_size(rset, 3, 2) - self.assertEquals(rset.rows, - [[self.blog3.eid, 'hep'], - [self.blog2.eid, 'hip'], - [self.blog.eid, 'hop']]) - - def test_5_orderby_desc(self): - self._setup_relation_description() - rset = self.req.execute('Any X,XC ORDERBY XC DESC WHERE X is Blog, X content XC') - self._check_rset_size(rset, 3, 2) - self.assertEquals(rset.rows, - [[self.blog.eid, 'hop'], - [self.blog2.eid, 'hip'], - [self.blog3.eid, 'hep']]) - - def test_5_orderby_several_terms(self): - self._setup_relation_description() - rset = self.req.execute('Any X,XC,XI ORDERBY XI,XC WHERE X is Blog, X content XC, X itemtype XI') - self._check_rset_size(rset, 3, 3) - self.assertEquals(rset.rows, - [[self.blog3.eid, 'hep', 'business'], - [self.blog2.eid, 'hip', 'personal'], - [self.blog.eid, 'hop', 'personal']]) - - def test_5_orderby_several_terms_mixed_implicit(self): - self._setup_relation_description() - rset = self.req.execute('Any X,XC,XI ORDERBY XI,XC DESC WHERE X is Blog, X content XC, X itemtype XI') - self._check_rset_size(rset, 3, 3) - self.assertEquals(rset.rows, - [[self.blog3.eid, 'hep', 'business'], - [self.blog.eid, 'hop', 'personal'], - [self.blog2.eid, 'hip', 'personal']]) - - def test_5_orderby_several_terms_explicit_order(self): - self._setup_relation_description() - rset = self.req.execute('Any X,XC,XI ORDERBY XI DESC,XC DESC WHERE X is Blog, X content XC, X itemtype XI') - self._check_rset_size(rset, 3, 3) - self.assertEquals(rset.rows, - [[self.blog.eid, 'hop', 'personal'], - [self.blog2.eid, 'hip', 'personal'], - [self.blog3.eid, 'hep', 'business']]) - - def test_5_orderby_several_terms_mixed_order(self): - self._setup_relation_description() - rset = self.req.execute('Any X,XC,XI ORDERBY XI ASC,XC DESC WHERE X is Blog, X content XC, X itemtype XI') - self._check_rset_size(rset, 3, 3) - self.assertEquals(rset.rows, - [[self.blog3.eid, 'hep', 'business'], - [self.blog.eid, 'hop', 'personal'], - [self.blog2.eid, 'hip', 'personal']]) - - - def test_5_orderby_lower(self): - blog2 = self.add_entity('Blog', itemtype=u'business', content=u'Hup') - rset = self.req.execute('Any X ORDERBY LOWER(XC) ' - 'WHERE X is Blog, X content XC') - self._check_rset_size(rset, 2, 1) - self.assertEquals(rset.rows, [[self.blog.eid], [blog2.eid]]) - rset = self.req.execute('Any X ORDERBY LOWER(XC) DESC' - 'WHERE X is Blog, X content XC') - self._check_rset_size(rset, 2, 1) - self.assertEquals(rset.rows, [[blog2.eid], [self.blog.eid]]) - - def test_5_orderby_stored_proc(self): - blog2 = self.add_entity('Blog', itemtype=u'business', content=u'hop') - rset = self.req.execute('Any X ORDERBY ITEMTYPE_SORT_VALUE(XIT) ' - 'WHERE X is Blog, X itemtype XIT') - self._check_rset_size(rset, 2, 1) - self.assertEquals(rset.rows, [[blog2.eid], [self.blog.eid]]) - rset = self.req.execute('Any X ORDERBY ITEMTYPE_SORT_VALUE(XIT) DESC' - 'WHERE X is Blog, X itemtype XIT') - self._check_rset_size(rset, 2, 1) - self.assertEquals(rset.rows, [[self.blog.eid], [blog2.eid]]) - - - def test_6_limit(self): - self._setup_relation_description() - rset = self.req.execute('Any X LIMIT 2 WHERE X is Blog') - self._check_rset_size(rset, 2, 1) - - def test_6_offset(self): - self._setup_relation_description() - rset = self.req.execute('Any XC ORDERBY XC DESC OFFSET 1 WHERE X is Blog, X content XC') - self._check_rset_size(rset, 2, 1) - self.assertEquals(rset.rows, [['hip'], ['hep']]) - - def test_6_limit_and_orderby(self): - self._setup_relation_description() - rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 WHERE X is Blog, X content XC') - self._check_rset_size(rset, 2, 1) - self.assertEquals(rset.rows, [['hep'], ['hip']]) - - def test_6_limit_offset_and_orderby(self): - self._setup_relation_description() - rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 OFFSET 0 WHERE X is Blog, X content XC') - self._check_rset_size(rset, 2, 1) - self.assertEquals(rset.rows, [['hep'], ['hip']]) - rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 OFFSET 1 WHERE X is Blog, X content XC') - self._check_rset_size(rset, 2, 1) - self.assertEquals(rset.rows, [['hip'], ['hop']]) - rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 OFFSET 2 WHERE X is Blog, X content XC') - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset.rows, [['hop']]) - rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 OFFSET 3 WHERE X is Blog, X content XC') - self.failIf(rset) - - - def test_7_simple_datetimecast(self): - self._setup_relation_description() - _today = today() - _tomorrow = _today + 1 - rset = self.req.execute('Any X WHERE X is Blog, X creation_date >= "%s"' - % _tomorrow.strftime('%Y-%m-%d')) - self.failUnless(len(rset) == 0) - rset = self.req.execute('Any X WHERE X is Blog, X creation_date >= "%s"' - % _today.strftime('%Y-%m-%d')) - self._check_rset_size(rset, 3, 1) - rset = self.req.execute('Any X WHERE X is Blog, X creation_date <= "%s"' - % _tomorrow.strftime('%Y-%m-%d')) - self._check_rset_size(rset, 3, 1) - - def test_7_identity_relation(self): - rset = self.req.execute('Any X WHERE X identity Y, X eid %(x)s, Y eid %(y)s', - {'x': self.user.eid, 'y': self.user.eid}) - self._check_rset_size(rset, 1, 1) - rset = self.req.execute('Any Y WHERE X identity Y, X eid %(x)s', - {'x': self.user.eid}) - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset.rows, [[self.user.eid]]) - blog2 = self.add_entity('Blog', itemtype=u'personal', content=u'hip') - rset = self.req.execute('Any X WHERE X identity Y, X eid %(x)s, Y eid %(y)s', - {'x': self.blog.eid, 'y': blog2.eid}) - self.failIf(rset) - - def test_8_not_relation_1(self): - rset = self.req.execute('Any X WHERE X identity U, NOT U in_group G, ' - 'G name "guests", X eid %(x)s, U eid %(u)s', - {'x': self.user.eid, 'u': self.user.eid}) - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset.rows, [[self.user.eid]]) - - def test_8_not_relation_linked_subject(self): - rset = self.req.execute('Any X WHERE NOT X talks_about Y, Y eid %(y)s', - {'y': self.article.eid}) - self.failIf(rset) - blog2 = self.add_entity('Blog', content=u'hop', itemtype=u'personal') - self.commit() - rset = self.req.execute('Any X WHERE NOT X talks_about Y, Y eid %(y)s', - {'y': self.article.eid}) - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset.rows, [[blog2.eid]]) - - def test_8_not_relation_linked_object(self): - rset = self.req.execute('Any Y WHERE NOT X talks_about Y, X eid %(x)s', - {'x': self.blog.eid}) - self.failIf(rset) - article2 = self.add_entity('Article', content=u'hop') - self.commit() - rset = self.req.execute('Any Y WHERE NOT X talks_about Y, X eid %(x)s', - {'x': self.blog.eid}) - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset.rows, [[article2.eid]]) - - def test_8_not_relation_linked_attr(self): - self.skip('not yet implemented') - # TODO: this should generated - # Query(X)[s_talks_about] > "hop" || Query(X)[s_talks_about] < "hop" - article2 = self.add_entity('Article', content=u'hop') - self.req.execute('SET X talks_about Y WHERE X eid %(x)s, Y eid %(y)s', - {'x': self.blog.eid, 'y': article2.eid}) - self.commit() - rset = self.req.execute('Any X WHERE NOT X talks_about Y, Y content "hop"') - self._check_rset_size(rset, 1, 2) - self.assertEquals(rset.rows, [[self.blog.eid, self.article.eid]]) - - def test_8_not_relation_unlinked_subject(self): - blog2 = self.add_entity('Blog', content=u'hop', itemtype=u'personal') - self.commit() - rset = self.req.execute('Any X WHERE NOT X talks_about Y') - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset.rows, [[blog2.eid]]) - - def test_8_not_relation_unlinked_object(self): - article2 = self.add_entity('Article', content=u'hop') - self.commit() - rset = self.req.execute('Any Y WHERE NOT X talks_about Y') - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset.rows, [[article2.eid]]) - - def test_8_not_relation_final_1(self): - rset = self.req.execute('Any G WHERE G is CWGroup, NOT G name "guests"') - self._check_rset_size(rset, 2, 1) - self.assertUnorderedIterableEquals([g.name for g in rset.entities()], - ['users', 'managers']) - - def test_8_not_relation_final_2(self): - rset = self.req.execute('Any GN WHERE G is CWGroup, NOT G name "guests", G name GN') - self._check_rset_size(rset, 2, 1) - self.assertUnorderedIterableEquals([gn for gn, in rset.rows], - ['users', 'managers']) - - - def test_9_exists(self): - blog2 = self.add_entity('Article', content=u'hop') - article2 = self.add_entity('Article', content=u'hop') - self.req.execute('SET X talks_about Y WHERE X eid %(x)s, Y eid %(y)s', - {'x': self.blog.eid, 'y': article2.eid}) - self.commit() - rset = self.req.execute('Any X WHERE X is Blog, EXISTS(X talks_about Y)') - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset.rows, [[self.blog.eid]]) - - - def test_error_unknown_eid(self): - rset = self.req.execute('Any X WHERE X eid %(x)s', {'x': '1234'}) - self.assertEquals(len(rset), 0) - self.blog.cw_delete() - rset = self.req.execute('Any X WHERE X eid %(x)s', {'x': self.blog.eid}) - self.assertEquals(len(rset), 0) - - def test_nonregr_inlined_relation(self): - eid = self.execute('INSERT YamsEntity X: X inlined_relation Y WHERE Y eid %(y)s', - {'y': self.blog.eid})[0][0] - self.commit() - rset = self.execute('Any X WHERE Y inlined_relation X, Y eid %(y)s', {'y': eid}) - self._check_rset_size(rset, 1, 1) - self.assertEquals(rset[0][0], self.blog.eid) - -if __name__ == '__main__': - unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 goa/test/unittest_schema.py --- a/goa/test/unittest_schema.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +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 . -""" - -""" -from cubicweb.goa.testlib import * - -class Article(db.Model): - content = db.TextProperty() - synopsis = db.StringProperty(default='hello') - -class Blog(db.Model): - diem = db.DateProperty(required=True, auto_now_add=True) - title = db.StringProperty(required=True) - content = db.TextProperty() - talks_about = db.ReferenceProperty(Article) - cites = db.SelfReferenceProperty() - - -class SomeViewsTC(GAEBasedTC): - MODEL_CLASSES = (Article, Blog) - - def test_entities_and_relation(self): - schema = self.schema - self.assertSetEquals(set(str(e) for e in schema.entities()), - set(('Boolean', 'Bytes', 'Date', 'Datetime', 'Float', - 'Decimal', - 'Int', 'Interval', 'Password', 'String', 'Time', - 'CWEType', 'CWGroup', 'CWPermission', 'CWProperty', 'CWRType', - 'CWUser', 'EmailAddress', - 'RQLExpression', 'State', 'Transition', 'TrInfo', - 'Article', 'Blog', 'YamsEntity'))) - self.assertSetEquals(set(str(e) for e in schema.relations()), - set(('add_permission', 'address', 'alias', 'allowed_transition', - 'ambiguous_relation', 'canonical', 'cites', - 'comment', 'comment_format', 'condition', 'content', - 'created_by', 'creation_date', 'delete_permission', - 'description', 'description_format', 'destination_state', - 'diem', 'eid', 'expression', 'exprtype', 'final', 'firstname', - 'for_user', 'from_state', 'fulltext_container', 'has_text', - 'identical_to', 'identity', 'in_group', 'initial_state', - 'inlined', 'inlined_relation', 'is', 'is_instance_of', - 'label', 'last_login_time', 'login', - 'mainvars', 'meta', 'modification_date', 'name', 'owned_by', 'pkey', 'primary_email', - 'read_permission', 'require_group', 'state_of', 'surname', 'symmetric', - 'synopsis', 'talks_about', 'title', 'to_state', 'transition_of', - 'update_permission', 'use_email', 'value'))) - - def test_dbmodel_imported(self): - eschema = self.schema['Blog'] - orels = [str(e) for e in eschema.ordered_relations()] - # only relations defined in the class are actually ordered - orels, others = orels[:5], orels[5:] - self.assertEquals(orels, - ['diem', 'title', 'content', 'talks_about', 'cites']) - self.assertUnorderedIterableEquals(others, - ['eid', 'identity', 'owned_by', 'modification_date', - 'created_by', 'creation_date', 'is', 'is_instance_of']) - self.assertUnorderedIterableEquals((str(e) for e in eschema.object_relations()), - ('ambiguous_relation', 'cites', 'identity', 'inlined_relation')) - eschema = self.schema['Article'] - orels = [str(e) for e in eschema.ordered_relations()] - # only relations defined in the class are actually ordered - orels, others = orels[:2], orels[2:] - self.assertEquals(orels, - ['content', 'synopsis']) - self.assertUnorderedIterableEquals(others, - ['eid', 'identity', 'owned_by', 'modification_date', - 'created_by', 'creation_date', 'is', 'is_instance_of']) - self.assertUnorderedIterableEquals((str(e) for e in eschema.object_relations()), - ('ambiguous_relation', 'talks_about', 'identity')) - - def test_yams_imported(self): - eschema = self.schema['CWProperty'] - # only relations defined in the class are actually ordered - orels = [str(e) for e in eschema.ordered_relations()] - orels, others = orels[:3], orels[3:] - self.assertEquals(orels, - ['pkey', 'value', 'for_user']) - self.assertEquals(others, - ['created_by', 'creation_date', 'eid', 'identity', - 'is', 'is_instance_of', 'modification_date', 'owned_by']) - self.assertUnorderedIterableEquals((str(e) for e in eschema.object_relations()), - ('identity',)) - - def test_yams_ambiguous_relation(self): - rschema = self.schema['ambiguous_relation'] - # only relations defined in the class are actually ordered - self.assertUnorderedIterableEquals((str(e) for e in rschema.subjects()), - ('YamsEntity',)) - self.assertUnorderedIterableEquals((str(e) for e in rschema.objects()), - ('Blog', 'Article')) - - def test_euser(self): - eschema = self.schema['CWUser'] - # XXX pretend to have some relations it has not - self.assertEquals([str(e) for e in eschema.ordered_relations()], - ['login', 'firstname', 'surname', 'last_login_time', - 'primary_email', 'use_email', 'in_group', 'created_by', - 'creation_date', 'eid', 'has_text', 'identity', - 'is', 'is_instance_of', 'modification_date', - 'owned_by']) - self.assertUnorderedIterableEquals((str(e) for e in eschema.object_relations()), - ('owned_by', 'created_by', 'identity', 'for_user')) - - def test_eid(self): - rschema = self.schema['eid'] - self.assertEquals(rschema.objects(), ('Bytes',)) - self.assertEquals(rschema.rproperty('Blog', 'Bytes', 'cardinality'), '?1') - - -if __name__ == '__main__': - from logilab.common.testlib import unittest_main - unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 goa/test/unittest_views.py --- a/goa/test/unittest_views.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +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 . -""" - -""" -from cubicweb.goa.testlib import * - -from cubicweb.interfaces import ICalendarable - - -class Blog(db.Model): - diem = db.DateProperty(required=True, auto_now_add=True) - title = db.StringProperty(required=True) - content = db.TextProperty() - - __implements__ = (ICalendarable,) - - @property - def start(self): - return self.diem - - @property - def stop(self): - return self.diem - - def matching_dates(self, begin, end): - """calendar views interface""" - mydate = self.diem - if mydate: - return [mydate] - return [] - - -class SomeViewsTC(GAEBasedTC): - MODEL_CLASSES = (Blog, ) - from cubicweb.web.views import basecontrollers, baseviews, navigation, boxes, calendar - from data import views - LOAD_APP_MODULES = (basecontrollers, baseviews, navigation, boxes, calendar, views) - - def setUp(self): - GAEBasedTC.setUp(self) - self.req = self.request() - self.blog = Blog(title=u'a blog', content=u'hop') - self.blog.put(self.req) - - def test_hcal(self): - self.vreg['views'].render('hcal', self.req, rset=self.blog.rset) - - def test_django_index(self): - self.vreg['views'].render('index', self.req, rset=None) - -for vid in ('primary', 'oneline', 'incontext', 'outofcontext', 'text'): - setattr(SomeViewsTC, 'test_%s'%vid, lambda self, vid=vid: self.blog.view(vid)) - -if __name__ == '__main__': - from logilab.common.testlib import unittest_main - unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 goa/testlib.py --- a/goa/testlib.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,198 +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 . -""" -""" -__docformat__ = "restructuredtext en" - -from logilab.common.testlib import TestCase, TestSkipped -try: - import google.appengine -except ImportError: - raise TestSkipped('Can not import google.appengine. Skip this module') - -import os, os.path as osp -import time -from shutil import copy - -# additional monkey patches necessary in regular cubicweb environment -from cubicweb.server import rqlannotation -from cubicweb.goa.overrides import rqlannotation as goarqlannotation -rqlannotation.SQLGenAnnotator = goarqlannotation.SQLGenAnnotator -rqlannotation.set_qdata = goarqlannotation.set_qdata - -from google.appengine.api import apiproxy_stub_map -from google.appengine.api import datastore_file_stub -from google.appengine.ext import db as gdb - -from cubicweb.devtools.fake import FakeRequest - -from cubicweb.goa import db, do_monkey_patch -from cubicweb.goa.goavreg import GAEVRegistry -from cubicweb.goa.goaconfig import GAEConfiguration -from cubicweb.goa.dbinit import (create_user, create_groups, fix_entities, - init_persistent_schema, insert_versions) - -import logging -logger = logging.getLogger() -logger.setLevel(logging.CRITICAL) - -do_monkey_patch() - -class GAEBasedTC(TestCase): - APP_ID = u'test_app' - AUTH_DOMAIN = 'gmail.com' - LOGGED_IN_USER = u't...@example.com' # set to '' for no logged in user - MODEL_CLASSES = None - LOAD_APP_MODULES = None - config = None - _DS_TEMPL_FILE = 'tmpdb-template' - - def load_schema_hook(self, loader): - loader.import_yams_cube_schema('data') - - @property - def DS_FILE(self): - return self.DS_TEMPL_FILE.replace('-template', '') - - @property - def DS_TEMPL_FILE(self): - return self._DS_TEMPL_FILE + '_'.join(sorted(cls.__name__ for cls in self.MODEL_CLASSES)) - - def _set_ds_file(self, dsfile): - # Start with a fresh api proxy. - apiproxy_stub_map.apiproxy = apiproxy_stub_map.APIProxyStubMap() - # Use a fresh stub datastore. - stub = datastore_file_stub.DatastoreFileStub(self.APP_ID, dsfile, - dsfile+'.history') - apiproxy_stub_map.apiproxy.RegisterStub('datastore_v3', stub) - - def setUp(self): - # Ensure we're in UTC. - os.environ['TZ'] = 'UTC' - time.tzset() - if osp.exists(self.DS_TEMPL_FILE): - copy(self.DS_TEMPL_FILE, self.DS_FILE) - need_ds_init = False - self._set_ds_file(self.DS_FILE) - else: - need_ds_init = True - self._set_ds_file(self.DS_TEMPL_FILE) -# from google.appengine.api import mail_stub -# from google3.apphosting.api import urlfetch_stub -# from google3.apphosting.api import user_service_stub -# # Use a fresh stub UserService. -# apiproxy_stub_map.apiproxy.RegisterStub( -# 'user', user_service_stub.UserServiceStub()) - os.environ['AUTH_DOMAIN'] = self.AUTH_DOMAIN - os.environ['USER_EMAIL'] = self.LOGGED_IN_USER -# # Use a fresh urlfetch stub. -# apiproxy_stub_map.apiproxy.RegisterStub( -# 'urlfetch', urlfetch_stub.URLFetchServiceStub()) -# # Use a fresh mail stub. -# apiproxy_stub_map.apiproxy.RegisterStub( -# 'mail', mail_stub.MailServiceStub()) - if self.MODEL_CLASSES is None: - raise Exception('GAEBasedTC should set MODEL_CLASSES class attribute') - gdb._kind_map = {} - self.config = self.config or GAEConfiguration('toto') - self.config.init_log(logging.CRITICAL) - self.schema = self.config.load_schema(self.MODEL_CLASSES, - self.load_schema_hook) - self.vreg = GAEVregistry(self.config) - self.vreg.schema = self.schema - self.vreg.load_module(db) - from cubicweb.goa.appobjects import sessions - self.vreg.load_module(sessions) - from cubicweb.entities import authobjs, schemaobjs - self.vreg.load_module(authobjs) - self.vreg.load_module(schemaobjs) - if self.config['use-google-auth']: - from cubicweb.goa.appobjects import gauthservice - self.vreg.load_module(gauthservice) - if self.LOAD_APP_MODULES is not None: - for module in self.LOAD_APP_MODULES: - self.vreg.load_module(module) - for cls in self.MODEL_CLASSES: - self.vreg.register(cls) - self.session_manager = self.vreg.select('components', 'sessionmanager') - if need_ds_init: - # create default groups and create entities according to the schema - create_groups() - if not self.config['use-google-auth']: - create_user(self.LOGGED_IN_USER, 'toto', ('users', 'managers')) - self.session = self.login(self.LOGGED_IN_USER, 'toto') - else: - req = FakeRequest(vreg=self.vreg) - self.session = self.session_manager.open_session(req) - self.user = self.session.user() - ssession = self.config.repo_session(self.session.sessionid) - ssession.set_pool() - init_persistent_schema(ssession, self.schema) - insert_versions(ssession, self.config) - ssession.commit() - fix_entities(self.schema) - copy(self.DS_TEMPL_FILE, self.DS_FILE) - self._set_ds_file(self.DS_FILE) - else: - if not self.config['use-google-auth']: - self.session = self.login(self.LOGGED_IN_USER, 'toto') - else: - req = FakeRequest(vreg=self.vreg) - self.session = self.session_manager.open_session(req) - self.user = self.session.user() - - def tearDown(self): - self.session.close() - - def request(self): - req = FakeRequest(vreg=self.vreg) - req.set_connection(self.session, self.user) - return req - - def add_entity(self, etype, **kwargs): - cu = self.session.cursor() - rql = 'INSERT %s X' % etype - if kwargs: - rql += ': %s' % ', '.join('X %s %%(%s)s' % (key, key) for key in kwargs) - rset = cu.execute(rql, kwargs) - return rset.get_entity(0, 0) - - def execute(self, *args): - return self.session.cursor().execute(*args) - - def commit(self): - self.session.commit() - - def rollback(self): - self.session.rollback() - - def create_user(self, login, groups=('users',), req=None): - assert not self.config['use-google-auth'] - user = self.add_entity('CWUser', upassword=str(login), login=unicode(login)) - cu = self.session.cursor() - cu.execute('SET X in_group G WHERE X eid %%(x)s, G name IN(%s)' - % ','.join(repr(g) for g in groups), - {'x': user.eid}, 'x') - return user - - def login(self, login, password=None): - assert not self.config['use-google-auth'] - req = FakeRequest(vreg=self.vreg) - req.form['__login'] = login - req.form['__password'] = password or login - return self.session_manager.open_session(req) diff -r e3994fcc21c3 -r 1806148d6ce8 goa/tools/__init__.py --- a/goa/tools/__init__.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +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 . -"""lax tools cube - -""" diff -r e3994fcc21c3 -r 1806148d6ce8 goa/tools/generate_schema_img.py --- a/goa/tools/generate_schema_img.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +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 . -""" - -""" -import sys -from os.path import dirname, abspath, join -from yams import schema2dot -from cubicweb.web.views.schema import SKIP_TYPES - -APPLROOT = abspath(join(dirname(abspath(__file__)), '..')) - -try: - import custom -except ImportError: - sys.path.insert(0, APPLROOT) - import custom - - -schema = custom.SCHEMA -skip_rels = ('owned_by', 'created_by', 'identity', 'is', 'is_instance_of') -path = join(APPLROOT, 'data', 'schema.png') -schema2dot.schema2dot(schema, path, #size=size, - skiptypes=SKIP_TYPES) -print 'generated', path -path = join(APPLROOT, 'data', 'metaschema.png') -schema2dot.schema2dot(schema, path) -print 'generated', path diff -r e3994fcc21c3 -r 1806148d6ce8 goa/tools/laxctl.py --- a/goa/tools/laxctl.py Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,269 +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 . -"""provides all lax instances management commands into a single utility script - -""" -__docformat__ = "restructuredtext en" - -import sys -import os -import os.path as osp -import time -import re -import urllib2 -from urllib import urlencode -from Cookie import SimpleCookie - -from logilab.common.clcommands import Command, register_commands, main_run - -from cubicweb.uilib import remove_html_tags -from cubicweb.web.views.schema import SKIP_TYPES - -APPLROOT = osp.abspath(osp.join(osp.dirname(osp.abspath(__file__)), '..')) - - -def initialize_vregistry(applroot): - # apply monkey patches first - from cubicweb.goa import do_monkey_patch - do_monkey_patch() - from cubicweb.goa.goavreg import GAEVregistry - from cubicweb.goa.goaconfig import GAEConfiguration - #WebConfiguration.uiprops['JAVASCRIPTS'].append('DATADIR/goa.js') - config = GAEConfiguration('toto', applroot) - vreg = GAEVregistry(config) - vreg.set_schema(config.load_schema()) - return vreg - -def alistdir(directory): - return [osp.join(directory, f) for f in os.listdir(directory)] - - -class LaxCommand(Command): - """base command class for all lax commands - creates vreg, schema and calls - """ - min_args = max_args = 0 - - def run(self, args): - self.vreg = initialize_vregistry(APPLROOT) - self._run(args) - - -class GenerateSchemaCommand(LaxCommand): - """generates the schema's png file""" - name = 'genschema' - - def _run(self, args): - assert not args, 'no argument expected' - from yams import schema2dot - schema = self.vreg.schema - path = osp.join(APPLROOT, 'data', 'schema.png') - schema2dot.schema2dot(schema, path, #size=size, - skiptypes=SKIP_TYPES) - print 'generated', path - path = osp.join(APPLROOT, 'data', 'metaschema.png') - schema2dot.schema2dot(schema, path) - print 'generated', path - - -class PopulateDataDirCommand(LaxCommand): - """populate instance's data directory according to used cubes""" - name = 'populatedata' - - def _run(self, args): - assert not args, 'no argument expected' - # first clean everything which is a symlink from the data directory - datadir = osp.join(APPLROOT, 'data') - if not osp.exists(datadir): - print 'created data directory' - os.mkdir(datadir) - for filepath in alistdir(datadir): - if osp.islink(filepath): - print 'removing', filepath - os.remove(filepath) - cubes = list(self.vreg.config.cubes()) + ['shared'] - for templ in cubes: - templpath = self.vreg.config.cube_dir(templ) - templdatadir = osp.join(templpath, 'data') - if not osp.exists(templdatadir): - print 'no data provided by', templ - continue - for resource in os.listdir(templdatadir): - if resource == 'external_resources': - continue - if not osp.exists(osp.join(datadir, resource)): - print 'symlinked %s from %s' % (resource, templ) - os.symlink(osp.join(templdatadir, resource), - osp.join(datadir, resource)) - - -class NoRedirectHandler(urllib2.HTTPRedirectHandler): - def http_error_302(self, req, fp, code, msg, headers): - raise urllib2.HTTPError(req.get_full_url(), code, msg, headers, fp) - http_error_301 = http_error_303 = http_error_307 = http_error_302 - - -class GetSessionIdHandler(urllib2.HTTPRedirectHandler): - def __init__(self, config): - self.config = config - - def http_error_303(self, req, fp, code, msg, headers): - cookie = SimpleCookie(headers['Set-Cookie']) - sessionid = cookie['__session'].value - print 'session id', sessionid - setattr(self.config, 'cookie', '__session=' + sessionid) - return 1 # on exception should be raised - - -class URLCommand(LaxCommand): - """abstract class for commands doing stuff by accessing the web instance - """ - min_args = max_args = 1 - arguments = '' - - options = ( - ('cookie', - {'short': 'C', 'type' : 'string', 'metavar': 'key=value', - 'default': None, - 'help': 'session/authentication cookie.'}), - ('user', - {'short': 'u', 'type' : 'string', 'metavar': 'login', - 'default': None, - 'help': 'user login instead of giving raw cookie string (require lax ' - 'based authentication).'}), - ('password', - {'short': 'p', 'type' : 'string', 'metavar': 'password', - 'default': None, - 'help': 'user password instead of giving raw cookie string (require ' - 'lax based authentication).'}), - ) - - def _run(self, args): - baseurl = args[0] - if not baseurl.startswith('http'): - baseurl = 'http://' + baseurl - if not baseurl.endswith('/'): - baseurl += '/' - self.base_url = baseurl - if not self.config.cookie and self.config.user: - # no cookie specified but a user is. Try to open a session using - # given authentication info - print 'opening session for', self.config.user - opener = urllib2.build_opener(GetSessionIdHandler(self.config)) - urllib2.install_opener(opener) - data = urlencode(dict(__login=self.config.user, - __password=self.config.password)) - self.open_url(urllib2.Request(baseurl, data)) - opener = urllib2.build_opener(NoRedirectHandler()) - urllib2.install_opener(opener) - self.do_base_url(baseurl) - - def build_req(self, url): - req = urllib2.Request(url) - if self.config.cookie: - req.headers['Cookie'] = self.config.cookie - return req - - def open_url(self, req): - try: - return urllib2.urlopen(req) - except urllib2.HTTPError, ex: - if ex.code == 302: - self.error_302(req, ex) - elif ex.code == 500: - self.error_500(req, ex) - else: - raise - - def error_302(self, req, ex): - print 'authentication required' - print ('visit %s?vid=authinfo with your browser to get ' - 'authentication info' % self.base_url) - sys.exit(1) - - def error_500(self, req, ex): - print 'an unexpected error occured on the server' - print ('you may get more information by visiting ' - '%s' % req.get_full_url()) - sys.exit(1) - - def extract_message(self, data): - match = re.search(r'
(.*?)
', data.read(), re.M|re.S) - if match: - msg = remove_html_tags(match.group(1)) - print msg - return msg - - def do_base_url(self, baseurl): - raise NotImplementedError() - - -class DSInitCommand(URLCommand): - """initialize the datastore""" - name = 'db-init' - - options = URLCommand.options + ( - ('sleep', - {'short': 's', 'type' : 'int', 'metavar': 'nb seconds', - 'default': None, - 'help': 'number of seconds to wait between each request to avoid ' - 'going out of quota.'}), - ) - - def do_base_url(self, baseurl): - req = self.build_req(baseurl + '?vid=contentinit') - while True: - try: - data = self.open_url(req) - except urllib2.HTTPError, ex: - if ex.code == 303: # redirect - print 'process completed' - break - raise - msg = self.extract_message(data) - if msg and msg.startswith('error: '): - print ('you may to cleanup datastore by visiting ' - '%s?vid=contentclear (ALL ENTITIES WILL BE DELETED)' - % baseurl) - break - if self.config.sleep: - time.sleep(self.config.sleep) - - -class CleanSessionsCommand(URLCommand): - """cleanup sessions on the server. This command should usually be called - regularly by a cron job or equivalent. - """ - name = "cleansessions" - def do_base_url(self, baseurl): - req = self.build_req(baseurl + '?vid=cleansessions') - data = self.open_url(req) - self.extract_message(data) - - -register_commands([GenerateSchemaCommand, - PopulateDataDirCommand, - DSInitCommand, - CleanSessionsCommand, - ]) - -def run(): - main_run(sys.argv[1:]) - -if __name__ == '__main__': - run() diff -r e3994fcc21c3 -r 1806148d6ce8 hooks/test/unittest_hooks.py --- a/hooks/test/unittest_hooks.py Thu Sep 23 23:28:58 2010 +0200 +++ b/hooks/test/unittest_hooks.py Wed Sep 29 16:16:32 2010 +0200 @@ -49,7 +49,7 @@ self.commit() def test_delete_required_relations_object(self): - self.skip('no sample in the schema ! YAGNI ? Kermaat ?') + self.skipTest('no sample in the schema ! YAGNI ? Kermaat ?') def test_static_vocabulary_check(self): self.assertRaises(ValidationError, @@ -63,14 +63,14 @@ self.commit) def test_inlined(self): - self.assertEquals(self.repo.schema['sender'].inlined, True) + self.assertEqual(self.repo.schema['sender'].inlined, True) self.execute('INSERT EmailAddress X: X address "toto@logilab.fr", X alias "hop"') self.execute('INSERT EmailPart X: X content_format "text/plain", X ordernum 1, X content "this is a test"') eeid = self.execute('INSERT Email X: X messageid "<1234>", X subject "test", X sender Y, X recipients Y, X parts P ' 'WHERE Y is EmailAddress, P is EmailPart')[0][0] self.execute('SET X sender Y WHERE X is Email, Y is EmailAddress') rset = self.execute('Any S WHERE X sender S, X eid %s' % eeid) - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) def test_composite_1(self): self.execute('INSERT EmailAddress X: X address "toto@logilab.fr", X alias "hop"') @@ -81,10 +81,10 @@ self.commit() self.execute('DELETE Email X') rset = self.execute('Any X WHERE X is EmailPart') - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) self.commit() rset = self.execute('Any X WHERE X is EmailPart') - self.assertEquals(len(rset), 0) + self.assertEqual(len(rset), 0) def test_composite_2(self): self.execute('INSERT EmailAddress X: X address "toto@logilab.fr", X alias "hop"') @@ -96,7 +96,7 @@ self.execute('DELETE EmailPart X') self.commit() rset = self.execute('Any X WHERE X is EmailPart') - self.assertEquals(len(rset), 0) + self.assertEqual(len(rset), 0) def test_composite_redirection(self): self.execute('INSERT EmailAddress X: X address "toto@logilab.fr", X alias "hop"') @@ -110,74 +110,73 @@ self.execute('SET X parts Y WHERE X messageid "<2345>"') self.commit() rset = self.execute('Any X WHERE X is EmailPart') - self.assertEquals(len(rset), 1) - self.assertEquals(rset.get_entity(0, 0).reverse_parts[0].messageid, '<2345>') + self.assertEqual(len(rset), 1) + self.assertEqual(rset.get_entity(0, 0).reverse_parts[0].messageid, '<2345>') def test_unsatisfied_constraints(self): releid = self.execute('SET U in_group G WHERE G name "owners", U login "admin"')[0][0] ex = self.assertRaises(ValidationError, self.commit) - self.assertEquals(ex.errors, + self.assertEqual(ex.errors, {'in_group-object': u'RQLConstraint NOT O name "owners" failed'}) def test_html_tidy_hook(self): req = self.request() entity = req.create_entity('Workflow', name=u'wf1', description_format=u'text/html', description=u'yo') - self.assertEquals(entity.description, u'yo') + self.assertEqual(entity.description, u'yo') entity = req.create_entity('Workflow', name=u'wf2', description_format=u'text/html', description=u'yo') - self.assertEquals(entity.description, u'yo') + self.assertEqual(entity.description, u'yo') entity = req.create_entity('Workflow', name=u'wf3', description_format=u'text/html', description=u'yo') - self.assertEquals(entity.description, u'yo') + self.assertEqual(entity.description, u'yo') entity = req.create_entity('Workflow', name=u'wf4', description_format=u'text/html', description=u'R&D') - self.assertEquals(entity.description, u'R&D') + self.assertEqual(entity.description, u'R&D') entity = req.create_entity('Workflow', name=u'wf5', description_format=u'text/html', description=u"
c'est l'été") - self.assertEquals(entity.description, u"
c'est l'été
") + self.assertEqual(entity.description, u"
c'est l'été
") def test_nonregr_html_tidy_hook_no_update(self): entity = self.request().create_entity('Workflow', name=u'wf1', description_format=u'text/html', description=u'yo') entity.set_attributes(name=u'wf2') - self.assertEquals(entity.description, u'yo') + self.assertEqual(entity.description, u'yo') entity.set_attributes(description=u'R&D

yo') entity.cw_attr_cache.pop('description') - self.assertEquals(entity.description, u'R&D

yo

') - + self.assertEqual(entity.description, u'R&D

yo

') def test_metadata_cwuri(self): entity = self.request().create_entity('Workflow', name=u'wf1') - self.assertEquals(entity.cwuri, self.repo.config['base-url'] + 'eid/%s' % entity.eid) + self.assertEqual(entity.cwuri, self.repo.config['base-url'] + 'eid/%s' % entity.eid) def test_metadata_creation_modification_date(self): _now = datetime.now() entity = self.request().create_entity('Workflow', name=u'wf1') - self.assertEquals((entity.creation_date - _now).seconds, 0) - self.assertEquals((entity.modification_date - _now).seconds, 0) + self.assertEqual((entity.creation_date - _now).seconds, 0) + self.assertEqual((entity.modification_date - _now).seconds, 0) def test_metadata_created_by(self): entity = self.request().create_entity('Bookmark', title=u'wf1', path=u'/view') self.commit() # fire operations - self.assertEquals(len(entity.created_by), 1) # make sure we have only one creator - self.assertEquals(entity.created_by[0].eid, self.session.user.eid) + self.assertEqual(len(entity.created_by), 1) # make sure we have only one creator + self.assertEqual(entity.created_by[0].eid, self.session.user.eid) def test_metadata_owned_by(self): entity = self.request().create_entity('Bookmark', title=u'wf1', path=u'/view') self.commit() # fire operations - self.assertEquals(len(entity.owned_by), 1) # make sure we have only one owner - self.assertEquals(entity.owned_by[0].eid, self.session.user.eid) + self.assertEqual(len(entity.owned_by), 1) # make sure we have only one owner + self.assertEqual(entity.owned_by[0].eid, self.session.user.eid) def test_user_login_stripped(self): u = self.create_user(' joe ') tname = self.execute('Any L WHERE E login L, E eid %(e)s', {'e': u.eid})[0][0] - self.assertEquals(tname, 'joe') + self.assertEqual(tname, 'joe') self.execute('SET X login " jijoe " WHERE X eid %(x)s', {'x': u.eid}) tname = self.execute('Any L WHERE E login L, E eid %(e)s', {'e': u.eid})[0][0] - self.assertEquals(tname, 'jijoe') + self.assertEqual(tname, 'jijoe') @@ -198,15 +197,15 @@ def test_user_group_synchronization(self): user = self.session.user - self.assertEquals(user.groups, set(('managers',))) + self.assertEqual(user.groups, set(('managers',))) self.execute('SET X in_group G WHERE X eid %s, G name "guests"' % user.eid) - self.assertEquals(user.groups, set(('managers',))) + self.assertEqual(user.groups, set(('managers',))) self.commit() - self.assertEquals(user.groups, set(('managers', 'guests'))) + self.assertEqual(user.groups, set(('managers', 'guests'))) self.execute('DELETE X in_group G WHERE X eid %s, G name "guests"' % user.eid) - self.assertEquals(user.groups, set(('managers', 'guests'))) + self.assertEqual(user.groups, set(('managers', 'guests'))) self.commit() - self.assertEquals(user.groups, set(('managers',))) + self.assertEqual(user.groups, set(('managers',))) def test_user_composite_owner(self): ueid = self.create_user('toto').eid @@ -214,7 +213,7 @@ self.execute('INSERT EmailAddress X: X address "toto@logilab.fr", U use_email X ' 'WHERE U login "toto"') self.commit() - self.assertEquals(self.execute('Any A WHERE X owned_by U, U use_email X,' + self.assertEqual(self.execute('Any A WHERE X owned_by U, U use_email X,' 'U login "toto", X address A')[0][0], 'toto@logilab.fr') @@ -230,23 +229,23 @@ def test_unexistant_eproperty(self): ex = self.assertRaises(ValidationError, self.execute, 'INSERT CWProperty X: X pkey "bla.bla", X value "hop", X for_user U') - self.assertEquals(ex.errors, {'pkey-subject': 'unknown property key'}) + self.assertEqual(ex.errors, {'pkey-subject': 'unknown property key'}) ex = self.assertRaises(ValidationError, self.execute, 'INSERT CWProperty X: X pkey "bla.bla", X value "hop"') - self.assertEquals(ex.errors, {'pkey-subject': 'unknown property key'}) + self.assertEqual(ex.errors, {'pkey-subject': 'unknown property key'}) def test_site_wide_eproperty(self): ex = self.assertRaises(ValidationError, self.execute, 'INSERT CWProperty X: X pkey "ui.site-title", X value "hop", X for_user U') - self.assertEquals(ex.errors, {'for_user-subject': "site-wide property can't be set for user"}) + self.assertEqual(ex.errors, {'for_user-subject': "site-wide property can't be set for user"}) def test_bad_type_eproperty(self): ex = self.assertRaises(ValidationError, self.execute, 'INSERT CWProperty X: X pkey "ui.language", X value "hop", X for_user U') - self.assertEquals(ex.errors, {'value-subject': u'unauthorized value'}) + self.assertEqual(ex.errors, {'value-subject': u'unauthorized value'}) ex = self.assertRaises(ValidationError, self.execute, 'INSERT CWProperty X: X pkey "ui.language", X value "hop"') - self.assertEquals(ex.errors, {'value-subject': u'unauthorized value'}) + self.assertEqual(ex.errors, {'value-subject': u'unauthorized value'}) class SchemaHooksTC(CubicWebTC): @@ -266,7 +265,7 @@ self.execute('INSERT CWUser X: X login "admin"') except ValidationError, ex: self.assertIsInstance(ex.entity, int) - self.assertEquals(ex.errors, {'login-subject': 'the value "admin" is already used, use another one'}) + self.assertEqual(ex.errors, {'login-subject': 'the value "admin" is already used, use another one'}) if __name__ == '__main__': diff -r e3994fcc21c3 -r 1806148d6ce8 hooks/test/unittest_syncschema.py --- a/hooks/test/unittest_syncschema.py Thu Sep 23 23:28:58 2010 +0200 +++ b/hooks/test/unittest_syncschema.py Wed Sep 29 16:16:32 2010 +0200 @@ -98,7 +98,7 @@ self.execute('Societe2 X WHERE X name "logilab"') self.execute('SET X concerne2 X WHERE X name "logilab"') rset = self.execute('Any X WHERE X concerne2 Y') - self.assertEquals(rset.rows, [[s2eid]]) + self.assertEqual(rset.rows, [[s2eid]]) # check that when a relation definition is deleted, existing relations are deleted rdefeid = self.execute('INSERT CWRelation X: X cardinality "**", X relation_type RT, ' ' X from_entity E, X to_entity E ' @@ -125,9 +125,9 @@ def test_is_instance_of_insertions(self): seid = self.execute('INSERT Transition T: T name "subdiv"')[0][0] is_etypes = [etype for etype, in self.execute('Any ETN WHERE X eid %s, X is ET, ET name ETN' % seid)] - self.assertEquals(is_etypes, ['Transition']) + self.assertEqual(is_etypes, ['Transition']) instanceof_etypes = [etype for etype, in self.execute('Any ETN WHERE X eid %s, X is_instance_of ET, ET name ETN' % seid)] - self.assertEquals(sorted(instanceof_etypes), ['BaseTransition', 'Transition']) + self.assertEqual(sorted(instanceof_etypes), ['BaseTransition', 'Transition']) snames = [name for name, in self.execute('Any N WHERE S is BaseTransition, S name N')] self.failIf('subdiv' in snames) snames = [name for name, in self.execute('Any N WHERE S is_instance_of BaseTransition, S name N')] @@ -136,27 +136,27 @@ def test_perms_synchronization_1(self): schema = self.repo.schema - self.assertEquals(schema['CWUser'].get_groups('read'), set(('managers', 'users'))) + self.assertEqual(schema['CWUser'].get_groups('read'), set(('managers', 'users'))) self.failUnless(self.execute('Any X, Y WHERE X is CWEType, X name "CWUser", Y is CWGroup, Y name "users"')[0]) self.execute('DELETE X read_permission Y WHERE X is CWEType, X name "CWUser", Y name "users"') - self.assertEquals(schema['CWUser'].get_groups('read'), set(('managers', 'users', ))) + self.assertEqual(schema['CWUser'].get_groups('read'), set(('managers', 'users', ))) self.commit() - self.assertEquals(schema['CWUser'].get_groups('read'), set(('managers',))) + self.assertEqual(schema['CWUser'].get_groups('read'), set(('managers',))) self.execute('SET X read_permission Y WHERE X is CWEType, X name "CWUser", Y name "users"') self.commit() - self.assertEquals(schema['CWUser'].get_groups('read'), set(('managers', 'users',))) + self.assertEqual(schema['CWUser'].get_groups('read'), set(('managers', 'users',))) def test_perms_synchronization_2(self): schema = self.repo.schema['in_group'].rdefs[('CWUser', 'CWGroup')] - self.assertEquals(schema.get_groups('read'), set(('managers', 'users', 'guests'))) + self.assertEqual(schema.get_groups('read'), set(('managers', 'users', 'guests'))) self.execute('DELETE X read_permission Y WHERE X relation_type RT, RT name "in_group", Y name "guests"') - self.assertEquals(schema.get_groups('read'), set(('managers', 'users', 'guests'))) + self.assertEqual(schema.get_groups('read'), set(('managers', 'users', 'guests'))) self.commit() - self.assertEquals(schema.get_groups('read'), set(('managers', 'users'))) + self.assertEqual(schema.get_groups('read'), set(('managers', 'users'))) self.execute('SET X read_permission Y WHERE X relation_type RT, RT name "in_group", Y name "guests"') - self.assertEquals(schema.get_groups('read'), set(('managers', 'users'))) + self.assertEqual(schema.get_groups('read'), set(('managers', 'users'))) self.commit() - self.assertEquals(schema.get_groups('read'), set(('managers', 'users', 'guests'))) + self.assertEqual(schema.get_groups('read'), set(('managers', 'users', 'guests'))) def test_nonregr_user_edit_itself(self): ueid = self.session.user.eid @@ -187,7 +187,7 @@ self.failIf(self.schema['state_of'].inlined) self.failIf(self.index_exists('State', 'state_of')) rset = self.execute('Any X, Y WHERE X state_of Y') - self.assertEquals(len(rset), 2) # user states + self.assertEqual(len(rset), 2) # user states except: import traceback traceback.print_exc() @@ -198,7 +198,7 @@ self.failUnless(self.schema['state_of'].inlined) self.failUnless(self.index_exists('State', 'state_of')) rset = self.execute('Any X, Y WHERE X state_of Y') - self.assertEquals(len(rset), 2) + self.assertEqual(len(rset), 2) def test_indexed_change(self): self.session.set_pool() @@ -317,7 +317,7 @@ rdef = self.schema['Transition'].rdef('type') cstr = rdef.constraint_by_type('StaticVocabularyConstraint') if not getattr(cstr, 'eid', None): - self.skip('start me alone') # bug in schema reloading, constraint's eid not restored + self.skipTest('start me alone') # bug in schema reloading, constraint's eid not restored self.execute('SET X value %(v)s WHERE X eid %(x)s', {'x': cstr.eid, 'v': u"u'normal', u'auto', u'new'"}) self.execute('INSERT CWConstraint X: X value %(value)s, X cstrtype CT, EDEF constrained_by X ' @@ -325,7 +325,7 @@ {'ct': 'SizeConstraint', 'value': u'max=10', 'x': rdef.eid}) self.commit() cstr = rdef.constraint_by_type('StaticVocabularyConstraint') - self.assertEquals(cstr.values, (u'normal', u'auto', u'new')) + self.assertEqual(cstr.values, (u'normal', u'auto', u'new')) self.execute('INSERT Transition T: T name "hop", T type "new"') if __name__ == '__main__': diff -r e3994fcc21c3 -r 1806148d6ce8 i18n.py --- a/i18n.py Thu Sep 23 23:28:58 2010 +0200 +++ b/i18n.py Wed Sep 29 16:16:32 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 i18n/gettext utilities. +"""Some i18n/gettext utilities.""" -""" __docformat__ = "restructuredtext en" import re diff -r e3994fcc21c3 -r 1806148d6ce8 i18n/en.po --- a/i18n/en.po Thu Sep 23 23:28:58 2010 +0200 +++ b/i18n/en.po Wed Sep 29 16:16:32 2010 +0200 @@ -956,9 +956,6 @@ msgid "add a new permission" msgstr "" -msgid "add_perm" -msgstr "add permission" - # subject and object forms for each relation type # (no object form for final relation types) msgid "add_permission" @@ -1857,9 +1854,6 @@ msgid "delete this relation" msgstr "" -msgid "delete_perm" -msgstr "delete permission" - msgid "delete_permission" msgstr "can be deleted by" @@ -3087,9 +3081,6 @@ msgid "read" msgstr "" -msgid "read_perm" -msgstr "read permission" - msgid "read_permission" msgstr "can be read by" @@ -3785,9 +3776,6 @@ msgid "update" msgstr "" -msgid "update_perm" -msgstr "update permission" - msgid "update_permission" msgstr "can be updated by" @@ -4057,3 +4045,15 @@ msgid "you should probably delete that property" msgstr "" + +#~ msgid "add_perm" +#~ msgstr "add permission" + +#~ msgid "delete_perm" +#~ msgstr "delete permission" + +#~ msgid "read_perm" +#~ msgstr "read permission" + +#~ msgid "update_perm" +#~ msgstr "update permission" diff -r e3994fcc21c3 -r 1806148d6ce8 i18n/es.po --- a/i18n/es.po Thu Sep 23 23:28:58 2010 +0200 +++ b/i18n/es.po Wed Sep 29 16:16:32 2010 +0200 @@ -998,9 +998,6 @@ msgid "add a new permission" msgstr "Agregar una autorización" -msgid "add_perm" -msgstr "Agregado" - # subject and object forms for each relation type # (no object form for final relation types) msgid "add_permission" @@ -1932,9 +1929,6 @@ msgid "delete this relation" msgstr "Eliminar esta relación" -msgid "delete_perm" -msgstr "Eliminar" - msgid "delete_permission" msgstr "Permiso de eliminar" @@ -3202,9 +3196,6 @@ msgid "read" msgstr "Lectura" -msgid "read_perm" -msgstr "Lectura" - msgid "read_permission" msgstr "Permiso de lectura" @@ -3913,9 +3904,6 @@ msgid "update" msgstr "Modificación" -msgid "update_perm" -msgstr "Permiso de Modificar" - msgid "update_permission" msgstr "Puede ser modificado por" @@ -4198,6 +4186,12 @@ msgid "you should probably delete that property" msgstr "Debería probablamente suprimir esta propriedad" +#~ msgid "add_perm" +#~ msgstr "Agregado" + +#~ msgid "delete_perm" +#~ msgstr "Eliminar" + #~ msgid "edition" #~ msgstr "Edición" @@ -4206,3 +4200,9 @@ #~ msgid "personnal informations" #~ msgstr "Información personal" + +#~ msgid "read_perm" +#~ msgstr "Lectura" + +#~ msgid "update_perm" +#~ msgstr "Permiso de Modificar" diff -r e3994fcc21c3 -r 1806148d6ce8 i18n/fr.po --- a/i18n/fr.po Thu Sep 23 23:28:58 2010 +0200 +++ b/i18n/fr.po Wed Sep 29 16:16:32 2010 +0200 @@ -996,9 +996,6 @@ msgid "add a new permission" msgstr "ajouter une permission" -msgid "add_perm" -msgstr "ajout" - # subject and object forms for each relation type # (no object form for final relation types) msgid "add_permission" @@ -1930,9 +1927,6 @@ msgid "delete this relation" msgstr "supprimer cette relation" -msgid "delete_perm" -msgstr "suppression" - msgid "delete_permission" msgstr "permission de supprimer" @@ -3202,9 +3196,6 @@ msgid "read" msgstr "lecture" -msgid "read_perm" -msgstr "lecture" - msgid "read_permission" msgstr "permission de lire" @@ -3914,9 +3905,6 @@ msgid "update" msgstr "modification" -msgid "update_perm" -msgstr "modification" - msgid "update_permission" msgstr "permission de modification" @@ -4198,6 +4186,12 @@ msgid "you should probably delete that property" msgstr "vous devriez probablement supprimer cette propriété" +#~ msgid "add_perm" +#~ msgstr "ajout" + +#~ msgid "delete_perm" +#~ msgstr "suppression" + #~ msgid "edition" #~ msgstr "édition" @@ -4207,5 +4201,11 @@ #~ msgid "personnal informations" #~ msgstr "informations personnelles" +#~ msgid "read_perm" +#~ msgstr "lecture" + +#~ msgid "update_perm" +#~ msgstr "modification" + #~ msgid "yams type, rdf type or mime type of the object" #~ msgstr "type yams, vocabulaire rdf ou type mime de l'objet" diff -r e3994fcc21c3 -r 1806148d6ce8 i18n/static-messages.pot --- a/i18n/static-messages.pot Thu Sep 23 23:28:58 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -msgid "read_perm" -msgstr "" - -msgid "add_perm" -msgstr "" - -msgid "update_perm" -msgstr "" - -msgid "delete_perm" -msgstr "" diff -r e3994fcc21c3 -r 1806148d6ce8 migration.py --- a/migration.py Thu Sep 23 23:28:58 2010 +0200 +++ b/migration.py Wed Sep 29 16:16:32 2010 +0200 @@ -129,7 +129,8 @@ return object.__getattribute__(self, name) except AttributeError: cmd = 'cmd_%s' % name - if hasattr(self, cmd): + # search self.__class__ to avoid infinite recursion + if hasattr(self.__class__, cmd): meth = getattr(self, cmd) return lambda *args, **kwargs: self.interact(args, kwargs, meth=meth) diff -r e3994fcc21c3 -r 1806148d6ce8 selectors.py --- a/selectors.py Thu Sep 23 23:28:58 2010 +0200 +++ b/selectors.py Wed Sep 29 16:16:32 2010 +0200 @@ -194,6 +194,7 @@ import logging from warnings import warn +from operator import eq from logilab.common.deprecation import class_renamed from logilab.common.compat import all, any @@ -530,17 +531,26 @@ class multi_lines_rset(Selector): - """If `nb` is specified, return 1 if the result set has exactly `nb` row of - result. Else (`nb` is None), return 1 if the result set contains *at least* + """Return 1 if the operator expression matches between `num` elements + in the result set and the `expected` value if defined. + + By default, multi_lines_rset(expected) matches equality expression: + `nb` row(s) in result set equals to expected value + But, you can perform richer comparisons by overriding default operator: + multi_lines_rset(expected, operator.gt) + + If `expected` is None, return 1 if the result set contains *at least* two rows. + If rset is None, return 0. """ - def __init__(self, nb=None): - self.expected = nb + def __init__(self, expected=None, operator=eq): + self.expected = expected + self.operator = operator def match_expected(self, num): if self.expected is None: return num > 1 - return num == self.expected + return self.operator(num, self.expected) @lltrace def __call__(self, cls, req, rset=None, **kwargs): @@ -1039,12 +1049,12 @@ return self.score_entity(kwargs['entity']) if rset is None: return 0 - user = req.user - action = self.action if row is None: score = 0 need_local_check = [] geteschema = req.vreg.schema.eschema + user = req.user + action = self.action for etype in rset.column_types(0): if etype in BASE_TYPES: return 0 @@ -1061,9 +1071,11 @@ if need_local_check: # check local role for entities of necessary types for i, row in enumerate(rset): - if not rset.description[i][0] in need_local_check: + if not rset.description[i][col] in need_local_check: continue - if not self.score(req, rset, i, col): + # micro-optimisation instead of calling self.score(req, + # rset, i, col): rset may be large + if not rset.get_entity(i, col).cw_has_perm(action): return 0 score += 1 return score diff -r e3994fcc21c3 -r 1806148d6ce8 server/hook.py --- a/server/hook.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/hook.py Wed Sep 29 16:16:32 2010 +0200 @@ -60,6 +60,11 @@ .. _`database trigger`: http://en.wikipedia.org/wiki/Database_trigger +.. hint:: + + It is a good practice to write unit tests for each hook. See an example in + :ref:`hook_test` + Operations ~~~~~~~~~~ @@ -402,7 +407,7 @@ class MyHook(Hook): __regid__ = 'whatever' - __select__ = Hook.__select__ & implements('Person') + __select__ = Hook.__select__ & is_instance('Person') else your hooks will be called madly, whatever the event. """ @@ -490,6 +495,8 @@ This hook ensure that when one of the watched relation is added, the `main_rtype` relation is added to the target entity of the relation. + Notice there are no default behaviour defined when a watched relation is + deleted, you'll have to handle this by yourself. You usually want to use the :class:`match_rtype_sets` selector on concret classes. diff -r e3994fcc21c3 -r 1806148d6ce8 server/querier.py --- a/server/querier.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/querier.py Wed Sep 29 16:16:32 2010 +0200 @@ -32,8 +32,8 @@ from rql.nodes import (Relation, VariableRef, Constant, SubQuery, Function, Exists, Not) -from cubicweb import Unauthorized, QueryError, UnknownEid, typed_eid -from cubicweb import server +from cubicweb import ValidationError, Unauthorized, QueryError, UnknownEid +from cubicweb import server, typed_eid from cubicweb.rset import ResultSet from cubicweb.server.utils import cleanup_solutions @@ -702,15 +702,9 @@ # execute the plan try: results = plan.execute() - except Unauthorized: - # XXX this could be done in security's after_add_relation hooks - # since it's actually realy only needed there (other relations - # security is done *before* actual changes, and add/update entity - # security is done after changes but in an operation, and exception - # generated in operation's events properly generate a rollback on - # the session). Even though, this is done here for a better - # consistency: getting an Unauthorized exception means the - # transaction has been rollbacked + except (Unauthorized, ValidationError): + # getting an Unauthorized/ValidationError exception means the + # transaction must been rollbacked # # notes: # * we should not reset the pool here, since we don't want the diff -r e3994fcc21c3 -r 1806148d6ce8 server/serverctl.py --- a/server/serverctl.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/serverctl.py Wed Sep 29 16:16:32 2010 +0200 @@ -501,7 +501,7 @@ passwdmsg='new password for %s' % adminlogin) try: cursor.execute("UPDATE cw_CWUser SET cw_upassword=%(p)s WHERE cw_login=%(l)s", - {'p': crypt_password(passwd), 'l': adminlogin}) + {'p': buffer(crypt_password(passwd)), 'l': adminlogin}) sconfig = Configuration(options=USER_OPTIONS) sconfig['login'] = adminlogin sconfig['password'] = passwd diff -r e3994fcc21c3 -r 1806148d6ce8 server/sources/native.py --- a/server/sources/native.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/sources/native.py Wed Sep 29 16:16:32 2010 +0200 @@ -142,7 +142,11 @@ """return backend type and a boolean flag if NULL values should be allowed for a given relation definition """ - coltype = y2sql.type_from_constraints(dbhelper, rdef.object, + if rdef.object.final: + ttype = rdef.object + else: + ttype = 'Int' # eid type + coltype = y2sql.type_from_constraints(dbhelper, ttype, rdef.constraints, creating=False) allownull = rdef.cardinality[0] != '1' return coltype, allownull diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_fti.py --- a/server/test/unittest_fti.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_fti.py Wed Sep 29 16:16:32 2010 +0200 @@ -12,7 +12,7 @@ def setUp(self): if not socket.gethostname().endswith('.logilab.fr'): - self.skip('XXX require logilab configuration') + self.skipTest('XXX require logilab configuration') super(PostgresFTITC, self).setUp() def test_occurence_count(self): @@ -24,7 +24,7 @@ c3 = req.create_entity('Card', title=u'c2', content=u'cubicweb cubicweb') self.commit() - self.assertEquals(req.execute('Card X ORDERBY FTIRANK(X) DESC WHERE X has_text "cubicweb"').rows, + self.assertEqual(req.execute('Card X ORDERBY FTIRANK(X) DESC WHERE X has_text "cubicweb"').rows, [[c1.eid], [c3.eid], [c2.eid]]) @@ -41,7 +41,7 @@ c3 = req.create_entity('Card', title=u'cubicweb', content=u'autre chose') self.commit() - self.assertEquals(req.execute('Card X ORDERBY FTIRANK(X) DESC WHERE X has_text "cubicweb"').rows, + self.assertEqual(req.execute('Card X ORDERBY FTIRANK(X) DESC WHERE X has_text "cubicweb"').rows, [[c3.eid], [c1.eid], [c2.eid]]) @@ -55,5 +55,5 @@ c2 = req.create_entity('Comment', content=u'cubicweb cubicweb', comments=c1) c3 = req.create_entity('Comment', content=u'cubicweb cubicweb cubicweb', comments=c1) self.commit() - self.assertEquals(req.execute('Any X ORDERBY FTIRANK(X) DESC WHERE X has_text "cubicweb"').rows, + self.assertEqual(req.execute('Any X ORDERBY FTIRANK(X) DESC WHERE X has_text "cubicweb"').rows, [[c1.eid], [c3.eid], [c2.eid]]) diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_hook.py --- a/server/test/unittest_hook.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_hook.py Wed Sep 29 16:16:32 2010 +0200 @@ -47,7 +47,7 @@ l1 = hook.LateOperation(session) l2 = hook.LateOperation(session) l3 = hook.Operation(session) - self.assertEquals(session.pending_operations, [l3, l1, l2]) + self.assertEqual(session.pending_operations, [l3, l1, l2]) @clean_session_ops def test_single_last_operation(self): @@ -56,9 +56,9 @@ l1 = hook.LateOperation(session) l2 = hook.LateOperation(session) l3 = hook.Operation(session) - self.assertEquals(session.pending_operations, [l3, l1, l2, l0]) + self.assertEqual(session.pending_operations, [l3, l1, l2, l0]) l4 = hook.SingleLastOperation(session) - self.assertEquals(session.pending_operations, [l3, l1, l2, l4]) + self.assertEqual(session.pending_operations, [l3, l1, l2, l4]) @clean_session_ops def test_global_operation_order(self): @@ -70,7 +70,7 @@ op3 = syncschema.MemSchemaNotifyChanges(session) op4 = integrity._DelayedDeleteOp(session) op5 = integrity._CheckORelationOp(session) - self.assertEquals(session.pending_operations, [op1, op2, op4, op5, op3]) + self.assertEqual(session.pending_operations, [op1, op2, op4, op5, op3]) class HookCalled(Exception): pass @@ -102,19 +102,19 @@ class _Hook(hook.Hook): events = ('before_add_entiti',) ex = self.assertRaises(Exception, self.o.register, _Hook) - self.assertEquals(str(ex), 'bad event before_add_entiti on %s._Hook' % __name__) + self.assertEqual(str(ex), 'bad event before_add_entiti on %s._Hook' % __name__) def test_register_bad_hook2(self): class _Hook(hook.Hook): events = None ex = self.assertRaises(Exception, self.o.register, _Hook) - self.assertEquals(str(ex), 'bad .events attribute None on %s._Hook' % __name__) + self.assertEqual(str(ex), 'bad .events attribute None on %s._Hook' % __name__) def test_register_bad_hook3(self): class _Hook(hook.Hook): events = 'before_add_entity' ex = self.assertRaises(Exception, self.o.register, _Hook) - self.assertEquals(str(ex), 'bad event b on %s._Hook' % __name__) + self.assertEqual(str(ex), 'bad event b on %s._Hook' % __name__) def test_call_hook(self): self.o.register(AddAnyHook) @@ -138,17 +138,17 @@ def test_startup_shutdown(self): import hooks # cubicweb/server/test/data/hooks.py - self.assertEquals(hooks.CALLED_EVENTS['server_startup'], True) + self.assertEqual(hooks.CALLED_EVENTS['server_startup'], True) # don't actually call repository.shutdown ! self.repo.hm.call_hooks('server_shutdown', repo=self.repo) - self.assertEquals(hooks.CALLED_EVENTS['server_shutdown'], True) + self.assertEqual(hooks.CALLED_EVENTS['server_shutdown'], True) def test_session_open_close(self): import hooks # cubicweb/server/test/data/hooks.py cnx = self.login('anon') - self.assertEquals(hooks.CALLED_EVENTS['session_open'], 'anon') + self.assertEqual(hooks.CALLED_EVENTS['session_open'], 'anon') cnx.close() - self.assertEquals(hooks.CALLED_EVENTS['session_close'], 'anon') + self.assertEqual(hooks.CALLED_EVENTS['session_close'], 'anon') # class RelationHookTC(TestCase): @@ -162,30 +162,30 @@ # """make sure before_xxx_relation hooks are called directly""" # self.o.register(self._before_relation_hook, # 'before_add_relation', 'concerne') -# self.assertEquals(self.called, []) +# self.assertEqual(self.called, []) # self.o.call_hooks('before_add_relation', 'concerne', 'USER', # 1, 'concerne', 2) -# self.assertEquals(self.called, [(1, 'concerne', 2)]) +# self.assertEqual(self.called, [(1, 'concerne', 2)]) # def test_after_add_relation(self): # """make sure after_xxx_relation hooks are deferred""" # self.o.register(self._after_relation_hook, # 'after_add_relation', 'concerne') -# self.assertEquals(self.called, []) +# self.assertEqual(self.called, []) # self.o.call_hooks('after_add_relation', 'concerne', 'USER', # 1, 'concerne', 2) # self.o.call_hooks('after_add_relation', 'concerne', 'USER', # 3, 'concerne', 4) -# self.assertEquals(self.called, [(1, 'concerne', 2), (3, 'concerne', 4)]) +# self.assertEqual(self.called, [(1, 'concerne', 2), (3, 'concerne', 4)]) # def test_before_delete_relation(self): # """make sure before_xxx_relation hooks are called directly""" # self.o.register(self._before_relation_hook, # 'before_delete_relation', 'concerne') -# self.assertEquals(self.called, []) +# self.assertEqual(self.called, []) # self.o.call_hooks('before_delete_relation', 'concerne', 'USER', # 1, 'concerne', 2) -# self.assertEquals(self.called, [(1, 'concerne', 2)]) +# self.assertEqual(self.called, [(1, 'concerne', 2)]) # def test_after_delete_relation(self): # """make sure after_xxx_relation hooks are deferred""" @@ -195,7 +195,7 @@ # 1, 'concerne', 2) # self.o.call_hooks('after_delete_relation', 'concerne', 'USER', # 3, 'concerne', 4) -# self.assertEquals(self.called, [(1, 'concerne', 2), (3, 'concerne', 4)]) +# self.assertEqual(self.called, [(1, 'concerne', 2), (3, 'concerne', 4)]) # def _before_relation_hook(self, pool, subject, r_type, object): diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_ldapuser.py --- a/server/test/unittest_ldapuser.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_ldapuser.py Wed Sep 29 16:16:32 2010 +0200 @@ -92,19 +92,19 @@ def test_base(self): # check a known one e = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT}).get_entity(0, 0) - self.assertEquals(e.login, SYT) + self.assertEqual(e.login, SYT) e.complete() - self.assertEquals(e.creation_date, None) - self.assertEquals(e.modification_date, None) - self.assertEquals(e.firstname, None) - self.assertEquals(e.surname, None) - self.assertEquals(e.in_group[0].name, 'users') - self.assertEquals(e.owned_by[0].login, SYT) - self.assertEquals(e.created_by, ()) - self.assertEquals(e.primary_email[0].address, 'Sylvain Thenault') + self.assertEqual(e.creation_date, None) + self.assertEqual(e.modification_date, None) + self.assertEqual(e.firstname, None) + self.assertEqual(e.surname, None) + self.assertEqual(e.in_group[0].name, 'users') + self.assertEqual(e.owned_by[0].login, SYT) + self.assertEqual(e.created_by, ()) + self.assertEqual(e.primary_email[0].address, 'Sylvain Thenault') # email content should be indexed on the user rset = self.sexecute('CWUser X WHERE X has_text "thenault"') - self.assertEquals(rset.rows, [[e.eid]]) + self.assertEqual(rset.rows, [[e.eid]]) def test_not(self): eid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT})[0][0] @@ -117,16 +117,16 @@ aeid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': ADIM})[0][0] rset = self.sexecute('CWUser X, Y WHERE X login %(syt)s, Y login %(adim)s', {'syt': SYT, 'adim': ADIM}) - self.assertEquals(rset.rows, [[seid, aeid]]) + self.assertEqual(rset.rows, [[seid, aeid]]) rset = self.sexecute('Any X,Y,L WHERE X login L, X login %(syt)s, Y login %(adim)s', {'syt': SYT, 'adim': ADIM}) - self.assertEquals(rset.rows, [[seid, aeid, SYT]]) + self.assertEqual(rset.rows, [[seid, aeid, SYT]]) def test_in(self): seid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT})[0][0] aeid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': ADIM})[0][0] rset = self.sexecute('Any X,L ORDERBY L WHERE X login IN("%s", "%s"), X login L' % (SYT, ADIM)) - self.assertEquals(rset.rows, [[aeid, ADIM], [seid, SYT]]) + self.assertEqual(rset.rows, [[aeid, ADIM], [seid, SYT]]) def test_relations(self): eid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT})[0][0] @@ -144,28 +144,28 @@ def test_upper(self): eid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT})[0][0] rset = self.sexecute('Any UPPER(L) WHERE X eid %s, X login L' % eid) - self.assertEquals(rset[0][0], SYT.upper()) + self.assertEqual(rset[0][0], SYT.upper()) def test_unknown_attr(self): eid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT})[0][0] rset = self.sexecute('Any L,C,M WHERE X eid %s, X login L, ' 'X creation_date C, X modification_date M' % eid) - self.assertEquals(rset[0][0], SYT) - self.assertEquals(rset[0][1], None) - self.assertEquals(rset[0][2], None) + self.assertEqual(rset[0][0], SYT) + self.assertEqual(rset[0][1], None) + self.assertEqual(rset[0][2], None) def test_sort(self): logins = [l for l, in self.sexecute('Any L ORDERBY L WHERE X login L')] - self.assertEquals(logins, sorted(logins)) + self.assertEqual(logins, sorted(logins)) def test_lower_sort(self): logins = [l for l, in self.sexecute('Any L ORDERBY lower(L) WHERE X login L')] - self.assertEquals(logins, sorted(logins)) + self.assertEqual(logins, sorted(logins)) def test_or(self): rset = self.sexecute('DISTINCT Any X WHERE X login %(login)s OR (X in_group G, G name "managers")', {'login': SYT}) - self.assertEquals(len(rset), 2, rset.rows) # syt + admin + self.assertEqual(len(rset), 2, rset.rows) # syt + admin def test_nonregr_set_owned_by(self): # test that when a user coming from ldap is triggering a transition @@ -173,7 +173,7 @@ self.sexecute('SET X in_group G WHERE X login %(syt)s, G name "managers"', {'syt': SYT}) self.commit() syt = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT}).get_entity(0, 0) - self.assertEquals([g.name for g in syt.in_group], ['managers', 'users']) + self.assertEqual([g.name for g in syt.in_group], ['managers', 'users']) self.patch_authenticate() cnx = self.login(SYT, password='dummypassword') cu = cnx.cursor() @@ -183,15 +183,15 @@ try: cnx.commit() adim.clear_all_caches() - self.assertEquals(adim.in_state[0].name, 'deactivated') + self.assertEqual(adim.in_state[0].name, 'deactivated') trinfo = iworkflowable.latest_trinfo() - self.assertEquals(trinfo.owned_by[0].login, SYT) + self.assertEqual(trinfo.owned_by[0].login, SYT) # select from_state to skip the user's creation TrInfo rset = self.sexecute('Any U ORDERBY D DESC WHERE WF wf_info_for X,' 'WF creation_date D, WF from_state FS,' 'WF owned_by U?, X eid %(x)s', {'x': adim.eid}) - self.assertEquals(rset.rows, [[syt.eid]]) + self.assertEqual(rset.rows, [[syt.eid]]) finally: # restore db state self.restore_connection() @@ -213,14 +213,14 @@ self.sexecute('SET U in_group G WHERE G name ~= "bougloup%", U login "admin"') self.sexecute('SET U in_group G WHERE G name = "bougloup1", U login %(syt)s', {'syt': SYT}) rset = self.sexecute('Any L,SN ORDERBY L WHERE X in_state S, S name SN, X login L, EXISTS(X in_group G, G name ~= "bougloup%")') - self.assertEquals(rset.rows, [['admin', 'activated'], [SYT, 'activated']]) + self.assertEqual(rset.rows, [['admin', 'activated'], [SYT, 'activated']]) def test_exists2(self): self.create_user('comme') self.create_user('cochon') self.sexecute('SET X copain Y WHERE X login "comme", Y login "cochon"') rset = self.sexecute('Any GN ORDERBY GN WHERE X in_group G, G name GN, (G name "managers" OR EXISTS(X copain T, T login in ("comme", "cochon")))') - self.assertEquals(rset.rows, [['managers'], ['users']]) + self.assertEqual(rset.rows, [['managers'], ['users']]) def test_exists3(self): self.create_user('comme') @@ -230,7 +230,7 @@ self.sexecute('SET X copain Y WHERE X login %(syt)s, Y login "cochon"', {'syt': SYT}) self.failUnless(self.sexecute('Any X, Y WHERE X copain Y, X login %(syt)s, Y login "cochon"', {'syt': SYT})) rset = self.sexecute('Any GN,L WHERE X in_group G, X login L, G name GN, G name "managers" OR EXISTS(X copain T, T login in ("comme", "cochon"))') - self.assertEquals(sorted(rset.rows), [['managers', 'admin'], ['users', 'comme'], ['users', SYT]]) + self.assertEqual(sorted(rset.rows), [['managers', 'admin'], ['users', 'comme'], ['users', SYT]]) def test_exists4(self): self.create_user('comme') @@ -252,7 +252,7 @@ all = self.sexecute('Any GN, L WHERE X in_group G, X login L, G name GN') all.rows.remove(['users', 'comme']) all.rows.remove(['users', SYT]) - self.assertEquals(sorted(rset.rows), sorted(all.rows)) + self.assertEqual(sorted(rset.rows), sorted(all.rows)) def test_exists5(self): self.create_user('comme') @@ -265,25 +265,25 @@ rset= self.sexecute('Any L WHERE X login L, ' 'EXISTS(X copain T, T login in ("comme", "cochon")) AND ' 'NOT EXISTS(X copain T2, T2 login "billy")') - self.assertEquals(sorted(rset.rows), [['cochon'], [SYT]]) + self.assertEqual(sorted(rset.rows), [['cochon'], [SYT]]) rset= self.sexecute('Any GN,L WHERE X in_group G, X login L, G name GN, ' 'EXISTS(X copain T, T login in ("comme", "cochon")) AND ' 'NOT EXISTS(X copain T2, T2 login "billy")') - self.assertEquals(sorted(rset.rows), [['guests', 'cochon'], + self.assertEqual(sorted(rset.rows), [['guests', 'cochon'], ['users', 'cochon'], ['users', SYT]]) def test_cd_restriction(self): rset = self.sexecute('CWUser X WHERE X creation_date > "2009-02-01"') # admin/anon but no ldap user since it doesn't support creation_date - self.assertEquals(sorted(e.login for e in rset.entities()), + self.assertEqual(sorted(e.login for e in rset.entities()), ['admin', 'anon']) def test_union(self): afeids = self.sexecute('State X') ueids = self.sexecute('CWUser X') rset = self.sexecute('(Any X WHERE X is State) UNION (Any X WHERE X is CWUser)') - self.assertEquals(sorted(r[0] for r in rset.rows), + self.assertEqual(sorted(r[0] for r in rset.rows), sorted(r[0] for r in afeids + ueids)) def _init_security_test(self): @@ -294,23 +294,23 @@ def test_security1(self): cu = self._init_security_test() rset = cu.execute('CWUser X WHERE X login %(login)s', {'login': SYT}) - self.assertEquals(rset.rows, []) + self.assertEqual(rset.rows, []) rset = cu.execute('Any X WHERE X login "iaminguestsgrouponly"') - self.assertEquals(len(rset.rows), 1) + self.assertEqual(len(rset.rows), 1) def test_security2(self): cu = self._init_security_test() rset = cu.execute('Any X WHERE X has_text %(syt)s', {'syt': SYT}) - self.assertEquals(rset.rows, []) + self.assertEqual(rset.rows, []) rset = cu.execute('Any X WHERE X has_text "iaminguestsgrouponly"') - self.assertEquals(len(rset.rows), 1) + self.assertEqual(len(rset.rows), 1) def test_security3(self): cu = self._init_security_test() rset = cu.execute('Any F WHERE X has_text %(syt)s, X firstname F', {'syt': SYT}) - self.assertEquals(rset.rows, []) + self.assertEqual(rset.rows, []) rset = cu.execute('Any F WHERE X has_text "iaminguestsgrouponly", X firstname F') - self.assertEquals(rset.rows, [[None]]) + self.assertEqual(rset.rows, [[None]]) def test_nonregr1(self): self.sexecute('Any X,AA ORDERBY AA DESC WHERE E eid %(x)s, E owned_by X, ' @@ -351,34 +351,34 @@ def test_count(self): trfunc = GlobTrFunc('count', 0) res = trfunc.apply([[1], [2], [3], [4]]) - self.assertEquals(res, [[4]]) + self.assertEqual(res, [[4]]) trfunc = GlobTrFunc('count', 1) res = trfunc.apply([[1, 2], [2, 4], [3, 6], [1, 5]]) - self.assertEquals(res, [[1, 2], [2, 1], [3, 1]]) + self.assertEqual(res, [[1, 2], [2, 1], [3, 1]]) def test_sum(self): trfunc = GlobTrFunc('sum', 0) res = trfunc.apply([[1], [2], [3], [4]]) - self.assertEquals(res, [[10]]) + self.assertEqual(res, [[10]]) trfunc = GlobTrFunc('sum', 1) res = trfunc.apply([[1, 2], [2, 4], [3, 6], [1, 5]]) - self.assertEquals(res, [[1, 7], [2, 4], [3, 6]]) + self.assertEqual(res, [[1, 7], [2, 4], [3, 6]]) def test_min(self): trfunc = GlobTrFunc('min', 0) res = trfunc.apply([[1], [2], [3], [4]]) - self.assertEquals(res, [[1]]) + self.assertEqual(res, [[1]]) trfunc = GlobTrFunc('min', 1) res = trfunc.apply([[1, 2], [2, 4], [3, 6], [1, 5]]) - self.assertEquals(res, [[1, 2], [2, 4], [3, 6]]) + self.assertEqual(res, [[1, 2], [2, 4], [3, 6]]) def test_max(self): trfunc = GlobTrFunc('max', 0) res = trfunc.apply([[1], [2], [3], [4]]) - self.assertEquals(res, [[4]]) + self.assertEqual(res, [[4]]) trfunc = GlobTrFunc('max', 1) res = trfunc.apply([[1, 2], [2, 4], [3, 6], [1, 5]]) - self.assertEquals(res, [[1, 5], [2, 4], [3, 6]]) + self.assertEqual(res, [[1, 5], [2, 4], [3, 6]]) # XXX LDAPUserSourceTC._init_repo() @@ -405,13 +405,13 @@ def test_base(self): rqlst = self._prepare('CWUser X WHERE X login "toto"').children[0] - self.assertEquals(self.o.generate(rqlst, 'X')[1], + self.assertEqual(self.o.generate(rqlst, 'X')[1], '(&(objectClass=top)(objectClass=posixAccount)(uid=toto))') def test_kwargs(self): rqlst = self._prepare('CWUser X WHERE X login %(x)s').children[0] self.o._args = {'x': "toto"} - self.assertEquals(self.o.generate(rqlst, 'X')[1], + self.assertEqual(self.o.generate(rqlst, 'X')[1], '(&(objectClass=top)(objectClass=posixAccount)(uid=toto))') def test_get_attr(self): diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_migractions.py --- a/server/test/unittest_migractions.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_migractions.py Wed Sep 29 16:16:32 2010 +0200 @@ -84,11 +84,11 @@ 'RDEF relation_type RT, RDEF ordernum O, RT name RTN')) self.mh.cmd_add_attribute('Note', 'whatever') self.failUnless('whatever' in self.schema) - self.assertEquals(self.schema['whatever'].subjects(), ('Note',)) - self.assertEquals(self.schema['whatever'].objects(), ('Int',)) - self.assertEquals(self.schema['Note'].default('whatever'), 2) + self.assertEqual(self.schema['whatever'].subjects(), ('Note',)) + self.assertEqual(self.schema['whatever'].objects(), ('Int',)) + self.assertEqual(self.schema['Note'].default('whatever'), 2) note = self.execute('Note X').get_entity(0, 0) - self.assertEquals(note.whatever, 2) + self.assertEqual(note.whatever, 2) orderdict2 = dict(self.mh.rqlexec('Any RTN, O WHERE X name "Note", RDEF from_entity X, ' 'RDEF relation_type RT, RDEF ordernum O, RT name RTN')) whateverorder = migrschema['whatever'].rdef('Note', 'Int').order @@ -97,7 +97,7 @@ orderdict[k] = v+1 orderdict['whatever'] = whateverorder self.assertDictEquals(orderdict, orderdict2) - #self.assertEquals([r.type for r in self.schema['Note'].ordered_relations()], + #self.assertEqual([r.type for r in self.schema['Note'].ordered_relations()], # ['modification_date', 'creation_date', 'owned_by', # 'eid', 'ecrit_par', 'inline1', 'date', 'type', # 'whatever', 'date', 'in_basket']) @@ -110,12 +110,12 @@ self.failIf('shortpara' in self.schema) self.mh.cmd_add_attribute('Note', 'shortpara') self.failUnless('shortpara' in self.schema) - self.assertEquals(self.schema['shortpara'].subjects(), ('Note', )) - self.assertEquals(self.schema['shortpara'].objects(), ('String', )) + self.assertEqual(self.schema['shortpara'].subjects(), ('Note', )) + self.assertEqual(self.schema['shortpara'].objects(), ('String', )) # test created column is actually a varchar(64) notesql = self.mh.sqlexec("SELECT sql FROM sqlite_master WHERE type='table' and name='%sNote'" % SQL_PREFIX)[0][0] fields = dict(x.strip().split()[:2] for x in notesql.split('(', 1)[1].rsplit(')', 1)[0].split(',')) - self.assertEquals(fields['%sshortpara' % SQL_PREFIX], 'varchar(64)') + self.assertEqual(fields['%sshortpara' % SQL_PREFIX], 'varchar(64)') self.mh.rollback() def test_add_datetime_with_default_value_attribute(self): @@ -123,15 +123,15 @@ self.failIf('shortpara' in self.schema) self.mh.cmd_add_attribute('Note', 'mydate') self.failUnless('mydate' in self.schema) - self.assertEquals(self.schema['mydate'].subjects(), ('Note', )) - self.assertEquals(self.schema['mydate'].objects(), ('Date', )) + self.assertEqual(self.schema['mydate'].subjects(), ('Note', )) + self.assertEqual(self.schema['mydate'].objects(), ('Date', )) testdate = date(2005, 12, 13) eid1 = self.mh.rqlexec('INSERT Note N')[0][0] eid2 = self.mh.rqlexec('INSERT Note N: N mydate %(mydate)s', {'mydate' : testdate})[0][0] d1 = self.mh.rqlexec('Any D WHERE X eid %(x)s, X mydate D', {'x': eid1})[0][0] d2 = self.mh.rqlexec('Any D WHERE X eid %(x)s, X mydate D', {'x': eid2})[0][0] - self.assertEquals(d1, date.today()) - self.assertEquals(d2, testdate) + self.assertEqual(d1, date.today()) + self.assertEqual(d2, testdate) self.mh.rollback() def test_drop_chosen_constraints_ctxmanager(self): @@ -175,10 +175,10 @@ for etype in ('Personne', 'Email'): s1 = self.mh.rqlexec('Any N WHERE WF workflow_of ET, ET name "%s", WF name N' % etype)[0][0] - self.assertEquals(s1, "foo") + self.assertEqual(s1, "foo") s1 = self.mh.rqlexec('Any N WHERE ET default_workflow WF, ET name "%s", WF name N' % etype)[0][0] - self.assertEquals(s1, "foo") + self.assertEqual(s1, "foo") def test_add_entity_type(self): self.failIf('Folder2' in self.schema) @@ -189,18 +189,18 @@ self.failUnless('filed_under2' in self.schema) self.failUnless(self.execute('CWRType X WHERE X name "filed_under2"')) self.schema.rebuild_infered_relations() - self.assertEquals(sorted(str(rs) for rs in self.schema['Folder2'].subject_relations()), + self.assertEqual(sorted(str(rs) for rs in self.schema['Folder2'].subject_relations()), ['created_by', 'creation_date', 'cwuri', 'description', 'description_format', 'eid', 'filed_under2', 'has_text', 'identity', 'in_basket', 'is', 'is_instance_of', 'modification_date', 'name', 'owned_by']) - self.assertEquals([str(rs) for rs in self.schema['Folder2'].object_relations()], + self.assertEqual([str(rs) for rs in self.schema['Folder2'].object_relations()], ['filed_under2', 'identity']) - self.assertEquals(sorted(str(e) for e in self.schema['filed_under2'].subjects()), + self.assertEqual(sorted(str(e) for e in self.schema['filed_under2'].subjects()), sorted(str(e) for e in self.schema.entities() if not e.final)) - self.assertEquals(self.schema['filed_under2'].objects(), ('Folder2',)) + self.assertEqual(self.schema['filed_under2'].objects(), ('Folder2',)) eschema = self.schema.eschema('Folder2') for cstr in eschema.rdef('name').constraints: self.failUnless(hasattr(cstr, 'eid')) @@ -227,22 +227,22 @@ self.mh.cmd_add_relation_type('filed_under2') self.schema.rebuild_infered_relations() self.failUnless('filed_under2' in self.schema) - self.assertEquals(sorted(str(e) for e in self.schema['filed_under2'].subjects()), + self.assertEqual(sorted(str(e) for e in self.schema['filed_under2'].subjects()), sorted(str(e) for e in self.schema.entities() if not e.final)) - self.assertEquals(self.schema['filed_under2'].objects(), ('Folder2',)) + self.assertEqual(self.schema['filed_under2'].objects(), ('Folder2',)) self.mh.cmd_drop_relation_type('filed_under2') self.failIf('filed_under2' in self.schema) def test_add_relation_definition_nortype(self): self.mh.cmd_add_relation_definition('Personne', 'concerne2', 'Affaire') - self.assertEquals(self.schema['concerne2'].subjects(), + self.assertEqual(self.schema['concerne2'].subjects(), ('Personne',)) - self.assertEquals(self.schema['concerne2'].objects(), + self.assertEqual(self.schema['concerne2'].objects(), ('Affaire', )) - self.assertEquals(self.schema['concerne2'].rdef('Personne', 'Affaire').cardinality, + self.assertEqual(self.schema['concerne2'].rdef('Personne', 'Affaire').cardinality, '1*') self.mh.cmd_add_relation_definition('Personne', 'concerne2', 'Note') - self.assertEquals(sorted(self.schema['concerne2'].objects()), ['Affaire', 'Note']) + self.assertEqual(sorted(self.schema['concerne2'].objects()), ['Affaire', 'Note']) self.mh.create_entity('Personne', nom=u'tot') self.mh.create_entity('Affaire') self.mh.rqlexec('SET X concerne2 Y WHERE X is Personne, Y is Affaire') @@ -253,59 +253,59 @@ self.failIf('concerne2' in self.schema) def test_drop_relation_definition_existant_rtype(self): - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].subjects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()), ['Affaire', 'Personne']) - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()), ['Affaire', 'Division', 'Note', 'Societe', 'SubDivision']) self.mh.cmd_drop_relation_definition('Personne', 'concerne', 'Affaire') - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].subjects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()), ['Affaire']) - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()), ['Division', 'Note', 'Societe', 'SubDivision']) self.mh.cmd_add_relation_definition('Personne', 'concerne', 'Affaire') - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].subjects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()), ['Affaire', 'Personne']) - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()), ['Affaire', 'Division', 'Note', 'Societe', 'SubDivision']) # trick: overwrite self.maxeid to avoid deletion of just reintroduced types self.maxeid = self.execute('Any MAX(X)')[0][0] def test_drop_relation_definition_with_specialization(self): - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].subjects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()), ['Affaire', 'Personne']) - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()), ['Affaire', 'Division', 'Note', 'Societe', 'SubDivision']) self.mh.cmd_drop_relation_definition('Affaire', 'concerne', 'Societe') - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].subjects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()), ['Affaire', 'Personne']) - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()), ['Affaire', 'Division', 'Note', 'SubDivision']) self.schema.rebuild_infered_relations() # need to be explicitly called once everything is in place - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()), ['Affaire', 'Note']) self.mh.cmd_add_relation_definition('Affaire', 'concerne', 'Societe') - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].subjects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()), ['Affaire', 'Personne']) - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()), ['Affaire', 'Note', 'Societe']) self.schema.rebuild_infered_relations() # need to be explicitly called once everything is in place - self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()), + self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()), ['Affaire', 'Division', 'Note', 'Societe', 'SubDivision']) # trick: overwrite self.maxeid to avoid deletion of just reintroduced types self.maxeid = self.execute('Any MAX(X)')[0][0] def test_rename_relation(self): - self.skip('implement me') + self.skipTest('implement me') def test_change_relation_props_non_final(self): rschema = self.schema['concerne'] card = rschema.rdef('Affaire', 'Societe').cardinality - self.assertEquals(card, '**') + self.assertEqual(card, '**') try: self.mh.cmd_change_relation_props('Affaire', 'concerne', 'Societe', cardinality='?*') card = rschema.rdef('Affaire', 'Societe').cardinality - self.assertEquals(card, '?*') + self.assertEqual(card, '?*') finally: self.mh.cmd_change_relation_props('Affaire', 'concerne', 'Societe', cardinality='**') @@ -313,12 +313,12 @@ def test_change_relation_props_final(self): rschema = self.schema['adel'] card = rschema.rdef('Personne', 'String').fulltextindexed - self.assertEquals(card, False) + self.assertEqual(card, False) try: self.mh.cmd_change_relation_props('Personne', 'adel', 'String', fulltextindexed=True) card = rschema.rdef('Personne', 'String').fulltextindexed - self.assertEquals(card, True) + self.assertEqual(card, True) finally: self.mh.cmd_change_relation_props('Personne', 'adel', 'String', fulltextindexed=False) @@ -338,11 +338,11 @@ self.mh.cmd_sync_schema_props_perms(commit=False) - self.assertEquals(cursor.execute('Any D WHERE X name "Personne", X description D')[0][0], + self.assertEqual(cursor.execute('Any D WHERE X name "Personne", X description D')[0][0], 'blabla bla') - self.assertEquals(cursor.execute('Any D WHERE X name "titre", X description D')[0][0], + self.assertEqual(cursor.execute('Any D WHERE X name "titre", X description D')[0][0], 'usually a title') - self.assertEquals(cursor.execute('Any D WHERE X relation_type RT, RT name "titre",' + self.assertEqual(cursor.execute('Any D WHERE X relation_type RT, RT name "titre",' 'X from_entity FE, FE name "Personne",' 'X description D')[0][0], 'title for this person') @@ -353,29 +353,29 @@ expected = [u'nom', u'prenom', u'sexe', u'promo', u'ass', u'adel', u'titre', u'web', u'tel', u'fax', u'datenaiss', u'test', 'description', u'firstname', u'creation_date', 'cwuri', u'modification_date'] - self.assertEquals(rinorder, expected) + self.assertEqual(rinorder, expected) # test permissions synchronization #################################### # new rql expr to add note entity eexpr = self._erqlexpr_entity('add', 'Note') - self.assertEquals(eexpr.expression, + self.assertEqual(eexpr.expression, 'X ecrit_part PE, U in_group G, ' 'PE require_permission P, P name "add_note", P require_group G') - self.assertEquals([et.name for et in eexpr.reverse_add_permission], ['Note']) - self.assertEquals(eexpr.reverse_read_permission, ()) - self.assertEquals(eexpr.reverse_delete_permission, ()) - self.assertEquals(eexpr.reverse_update_permission, ()) + self.assertEqual([et.name for et in eexpr.reverse_add_permission], ['Note']) + self.assertEqual(eexpr.reverse_read_permission, ()) + self.assertEqual(eexpr.reverse_delete_permission, ()) + self.assertEqual(eexpr.reverse_update_permission, ()) # no more rqlexpr to delete and add para attribute self.failIf(self._rrqlexpr_rset('add', 'para')) self.failIf(self._rrqlexpr_rset('delete', 'para')) # new rql expr to add ecrit_par relation rexpr = self._rrqlexpr_entity('add', 'ecrit_par') - self.assertEquals(rexpr.expression, + self.assertEqual(rexpr.expression, 'O require_permission P, P name "add_note", ' 'U in_group G, P require_group G') - self.assertEquals([rdef.rtype.name for rdef in rexpr.reverse_add_permission], ['ecrit_par']) - self.assertEquals(rexpr.reverse_read_permission, ()) - self.assertEquals(rexpr.reverse_delete_permission, ()) + self.assertEqual([rdef.rtype.name for rdef in rexpr.reverse_add_permission], ['ecrit_par']) + self.assertEqual(rexpr.reverse_read_permission, ()) + self.assertEqual(rexpr.reverse_delete_permission, ()) # no more rqlexpr to delete and add travaille relation self.failIf(self._rrqlexpr_rset('add', 'travaille')) self.failIf(self._rrqlexpr_rset('delete', 'travaille')) @@ -386,13 +386,13 @@ self.failIf(self._erqlexpr_rset('read', 'Affaire')) # rqlexpr to update Affaire entity has been updated eexpr = self._erqlexpr_entity('update', 'Affaire') - self.assertEquals(eexpr.expression, 'X concerne S, S owned_by U') + self.assertEqual(eexpr.expression, 'X concerne S, S owned_by U') # no change for rqlexpr to add and delete Affaire entity - self.assertEquals(len(self._erqlexpr_rset('delete', 'Affaire')), 1) - self.assertEquals(len(self._erqlexpr_rset('add', 'Affaire')), 1) + self.assertEqual(len(self._erqlexpr_rset('delete', 'Affaire')), 1) + self.assertEqual(len(self._erqlexpr_rset('add', 'Affaire')), 1) # no change for rqlexpr to add and delete concerne relation - self.assertEquals(len(self._rrqlexpr_rset('delete', 'concerne')), len(delete_concerne_rqlexpr)) - self.assertEquals(len(self._rrqlexpr_rset('add', 'concerne')), len(add_concerne_rqlexpr)) + self.assertEqual(len(self._rrqlexpr_rset('delete', 'concerne')), len(delete_concerne_rqlexpr)) + self.assertEqual(len(self._rrqlexpr_rset('add', 'concerne')), len(add_concerne_rqlexpr)) # * migrschema involve: # * 7 rqlexprs deletion (2 in (Affaire read + Societe + travaille) + 1 # in para attribute) @@ -400,36 +400,36 @@ # * 2 new (Note add, ecrit_par add) # * 2 implicit new for attributes update_permission (Note.para, Personne.test) # remaining orphan rql expr which should be deleted at commit (composite relation) - self.assertEquals(cursor.execute('Any COUNT(X) WHERE X is RQLExpression, ' + self.assertEqual(cursor.execute('Any COUNT(X) WHERE X is RQLExpression, ' 'NOT ET1 read_permission X, NOT ET2 add_permission X, ' 'NOT ET3 delete_permission X, NOT ET4 update_permission X')[0][0], 7+1) # finally - self.assertEquals(cursor.execute('Any COUNT(X) WHERE X is RQLExpression')[0][0], + self.assertEqual(cursor.execute('Any COUNT(X) WHERE X is RQLExpression')[0][0], nbrqlexpr_start + 1 + 2 + 2) self.mh.commit() # unique_together test self.assertEqual(len(self.schema.eschema('Personne')._unique_together), 1) - self.assertUnorderedIterableEquals(self.schema.eschema('Personne')._unique_together[0], + self.assertItemsEqual(self.schema.eschema('Personne')._unique_together[0], ('nom', 'prenom', 'datenaiss')) rset = cursor.execute('Any C WHERE C is CWUniqueTogetherConstraint') - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) relations = [r.rtype.name for r in rset.get_entity(0,0).relations] - self.assertUnorderedIterableEquals(relations, ('nom', 'prenom', 'datenaiss')) + self.assertItemsEqual(relations, ('nom', 'prenom', 'datenaiss')) def _erqlexpr_rset(self, action, ertype): rql = 'RQLExpression X WHERE ET is CWEType, ET %s_permission X, ET name %%(name)s' % action return self.mh.session.execute(rql, {'name': ertype}) def _erqlexpr_entity(self, action, ertype): rset = self._erqlexpr_rset(action, ertype) - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) return rset.get_entity(0, 0) def _rrqlexpr_rset(self, action, ertype): rql = 'RQLExpression X WHERE RT is CWRType, RDEF %s_permission X, RT name %%(name)s, RDEF relation_type RT' % action return self.mh.session.execute(rql, {'name': ertype}) def _rrqlexpr_entity(self, action, ertype): rset = self._rrqlexpr_rset(action, ertype) - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) return rset.get_entity(0, 0) def test_set_size_constraint(self): @@ -447,7 +447,7 @@ def test_add_remove_cube_and_deps(self): cubes = set(self.config.cubes()) schema = self.repo.schema - self.assertEquals(sorted((str(s), str(o)) for s, o in schema['see_also'].rdefs.keys()), + self.assertEqual(sorted((str(s), str(o)) for s, o in schema['see_also'].rdefs.keys()), sorted([('EmailThread', 'EmailThread'), ('Folder', 'Folder'), ('Bookmark', 'Bookmark'), ('Bookmark', 'Note'), ('Note', 'Note'), ('Note', 'Bookmark')])) @@ -462,16 +462,16 @@ for ertype in ('Email', 'EmailThread', 'EmailPart', 'File', 'sender', 'in_thread', 'reply_to', 'data_format'): self.failIf(ertype in schema, ertype) - self.assertEquals(sorted(schema['see_also'].rdefs.keys()), + self.assertEqual(sorted(schema['see_also'].rdefs.keys()), sorted([('Folder', 'Folder'), ('Bookmark', 'Bookmark'), ('Bookmark', 'Note'), ('Note', 'Note'), ('Note', 'Bookmark')])) - self.assertEquals(sorted(schema['see_also'].subjects()), ['Bookmark', 'Folder', 'Note']) - self.assertEquals(sorted(schema['see_also'].objects()), ['Bookmark', 'Folder', 'Note']) - self.assertEquals(self.execute('Any X WHERE X pkey "system.version.email"').rowcount, 0) - self.assertEquals(self.execute('Any X WHERE X pkey "system.version.file"').rowcount, 0) + self.assertEqual(sorted(schema['see_also'].subjects()), ['Bookmark', 'Folder', 'Note']) + self.assertEqual(sorted(schema['see_also'].objects()), ['Bookmark', 'Folder', 'Note']) + self.assertEqual(self.execute('Any X WHERE X pkey "system.version.email"').rowcount, 0) + self.assertEqual(self.execute('Any X WHERE X pkey "system.version.file"').rowcount, 0) except : import traceback traceback.print_exc() @@ -485,19 +485,19 @@ for ertype in ('Email', 'EmailThread', 'EmailPart', 'File', 'sender', 'in_thread', 'reply_to', 'data_format'): self.failUnless(ertype in schema, ertype) - self.assertEquals(sorted(schema['see_also'].rdefs.keys()), + self.assertEqual(sorted(schema['see_also'].rdefs.keys()), sorted([('EmailThread', 'EmailThread'), ('Folder', 'Folder'), ('Bookmark', 'Bookmark'), ('Bookmark', 'Note'), ('Note', 'Note'), ('Note', 'Bookmark')])) - self.assertEquals(sorted(schema['see_also'].subjects()), ['Bookmark', 'EmailThread', 'Folder', 'Note']) - self.assertEquals(sorted(schema['see_also'].objects()), ['Bookmark', 'EmailThread', 'Folder', 'Note']) + self.assertEqual(sorted(schema['see_also'].subjects()), ['Bookmark', 'EmailThread', 'Folder', 'Note']) + self.assertEqual(sorted(schema['see_also'].objects()), ['Bookmark', 'EmailThread', 'Folder', 'Note']) from cubes.email.__pkginfo__ import version as email_version from cubes.file.__pkginfo__ import version as file_version - self.assertEquals(self.execute('Any V WHERE X value V, X pkey "system.version.email"')[0][0], + self.assertEqual(self.execute('Any V WHERE X value V, X pkey "system.version.email"')[0][0], email_version) - self.assertEquals(self.execute('Any V WHERE X value V, X pkey "system.version.file"')[0][0], + self.assertEqual(self.execute('Any V WHERE X value V, X pkey "system.version.file"')[0][0], file_version) # trick: overwrite self.maxeid to avoid deletion of just reintroduced # types (and their associated tables!) @@ -535,19 +535,19 @@ def test_remove_dep_cube(self): ex = self.assertRaises(ConfigurationError, self.mh.cmd_remove_cube, 'file') - self.assertEquals(str(ex), "can't remove cube file, used as a dependency") + self.assertEqual(str(ex), "can't remove cube file, used as a dependency") def test_introduce_base_class(self): self.mh.cmd_add_entity_type('Para') self.mh.repo.schema.rebuild_infered_relations() - self.assertEquals(sorted(et.type for et in self.schema['Para'].specialized_by()), + self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()), ['Note']) - self.assertEquals(self.schema['Note'].specializes().type, 'Para') + self.assertEqual(self.schema['Note'].specializes().type, 'Para') self.mh.cmd_add_entity_type('Text') self.mh.repo.schema.rebuild_infered_relations() - self.assertEquals(sorted(et.type for et in self.schema['Para'].specialized_by()), + self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()), ['Note', 'Text']) - self.assertEquals(self.schema['Text'].specializes().type, 'Para') + self.assertEqual(self.schema['Text'].specializes().type, 'Para') # test columns have been actually added text = self.execute('INSERT Text X: X para "hip", X summary "hop", X newattr "momo"').get_entity(0, 0) note = self.execute('INSERT Note X: X para "hip", X shortpara "hop", X newattr "momo", X unique_id "x"').get_entity(0, 0) @@ -574,10 +574,10 @@ self.commit() finally: self.session.data['rebuild-infered'] = False - self.assertEquals(sorted(et.type for et in self.schema['Para'].specialized_by()), + self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()), []) - self.assertEquals(self.schema['Note'].specializes(), None) - self.assertEquals(self.schema['Text'].specializes(), None) + self.assertEqual(self.schema['Note'].specializes(), None) + self.assertEqual(self.schema['Text'].specializes(), None) def test_add_symmetric_relation_type(self): diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_msplanner.py --- a/server/test/unittest_msplanner.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_msplanner.py Wed Sep 29 16:16:32 2010 +0200 @@ -141,8 +141,8 @@ for var in sourcevars.keys(): solindices = sourcevars.pop(var) sourcevars[var._ms_table_key()] = solindices - self.assertEquals(ppi._sourcesterms, sourcesterms) - self.assertEquals(ppi.needsplit, needsplit) + self.assertEqual(ppi._sourcesterms, sourcesterms) + self.assertEqual(ppi.needsplit, needsplit) def test_simple_system_only(self): @@ -2032,7 +2032,7 @@ # identity relation. BUT I think it's better to leave it as is and to # explain constraint propagation rules, and so why this should be # wrapped in exists() if used in multi-source - self.skip('take a look at me if you wish') + self.skipTest('take a look at me if you wish') self._test('Any B,U,UL GROUPBY B,U,UL WHERE B created_by U?, B is File ' 'WITH U,UL BEING (Any U,UL WHERE ME eid %(x)s, (U identity ME ' 'OR (EXISTS(U in_group G, G name IN("managers", "staff")))) ' diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_multisources.py --- a/server/test/unittest_multisources.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_multisources.py Wed Sep 29 16:16:32 2010 +0200 @@ -101,34 +101,34 @@ def test_eid_comp(self): rset = self.sexecute('Card X WHERE X eid > 1') - self.assertEquals(len(rset), 4) + self.assertEqual(len(rset), 4) rset = self.sexecute('Any X,T WHERE X title T, X eid > 1') - self.assertEquals(len(rset), 4) + self.assertEqual(len(rset), 4) def test_metainformation(self): rset = self.sexecute('Card X ORDERBY T WHERE X title T') # 2 added to the system source, 2 added to the external source - self.assertEquals(len(rset), 4) + self.assertEqual(len(rset), 4) # since they are orderd by eid, we know the 3 first one is coming from the system source # and the others from external source - self.assertEquals(rset.get_entity(0, 0).cw_metainformation(), + self.assertEqual(rset.get_entity(0, 0).cw_metainformation(), {'source': {'adapter': 'native', 'uri': 'system'}, 'type': u'Card', 'extid': None}) externent = rset.get_entity(3, 0) metainf = externent.cw_metainformation() - self.assertEquals(metainf['source'], {'adapter': 'pyrorql', 'base-url': 'http://extern.org/', 'uri': 'extern'}) - self.assertEquals(metainf['type'], 'Card') + self.assertEqual(metainf['source'], {'adapter': 'pyrorql', 'base-url': 'http://extern.org/', 'uri': 'extern'}) + self.assertEqual(metainf['type'], 'Card') self.assert_(metainf['extid']) etype = self.sexecute('Any ETN WHERE X is ET, ET name ETN, X eid %(x)s', {'x': externent.eid})[0][0] - self.assertEquals(etype, 'Card') + self.assertEqual(etype, 'Card') def test_order_limit_offset(self): rsetbase = self.sexecute('Any W,X ORDERBY W,X WHERE X wikiid W') - self.assertEquals(len(rsetbase), 4) - self.assertEquals(sorted(rsetbase.rows), rsetbase.rows) + self.assertEqual(len(rsetbase), 4) + self.assertEqual(sorted(rsetbase.rows), rsetbase.rows) rset = self.sexecute('Any W,X ORDERBY W,X LIMIT 2 OFFSET 2 WHERE X wikiid W') - self.assertEquals(rset.rows, rsetbase.rows[2:4]) + self.assertEqual(rset.rows, rsetbase.rows[2:4]) def test_has_text(self): self.repo.sources_by_uri['extern'].synchronize(MTIME) # in case fti_update has been run before @@ -148,9 +148,9 @@ cu = cnx.cursor() rset = cu.execute('Any X WHERE X has_text "card"') # 5: 4 card + 1 readable affaire - self.assertEquals(len(rset), 5, zip(rset.rows, rset.description)) + self.assertEqual(len(rset), 5, zip(rset.rows, rset.description)) rset = cu.execute('Any X ORDERBY FTIRANK(X) WHERE X has_text "card"') - self.assertEquals(len(rset), 5, zip(rset.rows, rset.description)) + self.assertEqual(len(rset), 5, zip(rset.rows, rset.description)) Connection_close(cnx.cnx) # cnx is a TestCaseConnectionProxy def test_synchronization(self): @@ -178,14 +178,14 @@ affeid = self.sexecute('Affaire X WHERE X ref "AFFREF"')[0][0] rset = self.sexecute('Any X,AA,AB WHERE E eid %(x)s, E in_state X, X name AA, X modification_date AB', {'x': affeid}) - self.assertEquals(len(rset), 1) - self.assertEquals(rset[0][1], "pitetre") + self.assertEqual(len(rset), 1) + self.assertEqual(rset[0][1], "pitetre") def test_simplifiable_var_2(self): affeid = self.sexecute('Affaire X WHERE X ref "AFFREF"')[0][0] rset = self.sexecute('Any E WHERE E eid %(x)s, E in_state S, NOT S name "moved"', {'x': affeid, 'u': self.session.user.eid}) - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) def test_sort_func(self): self.sexecute('Affaire X ORDERBY DUMB_SORT(RF) WHERE X ref RF') @@ -197,31 +197,31 @@ iec1 = self.repo.extid2eid(self.repo.sources_by_uri['extern'], str(self.ec1), 'Card', self.session) rset = self.sexecute('Any X WHERE X eid IN (%s, %s)' % (iec1, self.ic1)) - self.assertEquals(sorted(r[0] for r in rset.rows), sorted([iec1, self.ic1])) + self.assertEqual(sorted(r[0] for r in rset.rows), sorted([iec1, self.ic1])) def test_greater_eid(self): rset = self.sexecute('Any X WHERE X eid > %s' % (self.ic1 - 1)) - self.assertEquals(len(rset.rows), 2) # self.ic1 and self.ic2 + self.assertEqual(len(rset.rows), 2) # self.ic1 and self.ic2 cu = cnx2.cursor() ec2 = cu.execute('INSERT Card X: X title "glup"')[0][0] cnx2.commit() # 'X eid > something' should not trigger discovery rset = self.sexecute('Any X WHERE X eid > %s' % (self.ic1 - 1)) - self.assertEquals(len(rset.rows), 2) + self.assertEqual(len(rset.rows), 2) # trigger discovery using another query crset = self.sexecute('Card X WHERE X title "glup"') - self.assertEquals(len(crset.rows), 1) + self.assertEqual(len(crset.rows), 1) rset = self.sexecute('Any X WHERE X eid > %s' % (self.ic1 - 1)) - self.assertEquals(len(rset.rows), 3) + self.assertEqual(len(rset.rows), 3) rset = self.sexecute('Any MAX(X)') - self.assertEquals(len(rset.rows), 1) - self.assertEquals(rset.rows[0][0], crset[0][0]) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(rset.rows[0][0], crset[0][0]) def test_attr_unification_1(self): n1 = self.sexecute('INSERT Note X: X type "AFFREF"')[0][0] n2 = self.sexecute('INSERT Note X: X type "AFFREU"')[0][0] rset = self.sexecute('Any X,Y WHERE X is Note, Y is Affaire, X type T, Y ref T') - self.assertEquals(len(rset), 1, rset.rows) + self.assertEqual(len(rset), 1, rset.rows) def test_attr_unification_2(self): cu = cnx2.cursor() @@ -230,7 +230,7 @@ try: c1 = self.sexecute('INSERT Card C: C title "AFFREF"')[0][0] rset = self.sexecute('Any X,Y WHERE X is Card, Y is Affaire, X title T, Y ref T') - self.assertEquals(len(rset), 2, rset.rows) + self.assertEqual(len(rset), 2, rset.rows) finally: cu.execute('DELETE Card X WHERE X eid %(x)s', {'x': ec2}) cnx2.commit() @@ -247,26 +247,26 @@ afeids = self.sexecute('Affaire X') ueids = self.sexecute('CWUser X') rset = self.sexecute('(Any X WHERE X is Affaire) UNION (Any X WHERE X is CWUser)') - self.assertEquals(sorted(r[0] for r in rset.rows), + self.assertEqual(sorted(r[0] for r in rset.rows), sorted(r[0] for r in afeids + ueids)) def test_subquery1(self): rsetbase = self.sexecute('Any W,X WITH W,X BEING (Any W,X ORDERBY W,X WHERE X wikiid W)') - self.assertEquals(len(rsetbase), 4) - self.assertEquals(sorted(rsetbase.rows), rsetbase.rows) + self.assertEqual(len(rsetbase), 4) + self.assertEqual(sorted(rsetbase.rows), rsetbase.rows) rset = self.sexecute('Any W,X LIMIT 2 OFFSET 2 WITH W,X BEING (Any W,X ORDERBY W,X WHERE X wikiid W)') - self.assertEquals(rset.rows, rsetbase.rows[2:4]) + self.assertEqual(rset.rows, rsetbase.rows[2:4]) rset = self.sexecute('Any W,X ORDERBY W,X LIMIT 2 OFFSET 2 WITH W,X BEING (Any W,X WHERE X wikiid W)') - self.assertEquals(rset.rows, rsetbase.rows[2:4]) + self.assertEqual(rset.rows, rsetbase.rows[2:4]) rset = self.sexecute('Any W,X WITH W,X BEING (Any W,X ORDERBY W,X LIMIT 2 OFFSET 2 WHERE X wikiid W)') - self.assertEquals(rset.rows, rsetbase.rows[2:4]) + self.assertEqual(rset.rows, rsetbase.rows[2:4]) def test_subquery2(self): affeid = self.sexecute('Affaire X WHERE X ref "AFFREF"')[0][0] rset = self.sexecute('Any X,AA,AB WITH X,AA,AB BEING (Any X,AA,AB WHERE E eid %(x)s, E in_state X, X name AA, X modification_date AB)', {'x': affeid}) - self.assertEquals(len(rset), 1) - self.assertEquals(rset[0][1], "pitetre") + self.assertEqual(len(rset), 1) + self.assertEqual(rset[0][1], "pitetre") def test_not_relation(self): states = set(tuple(x) for x in self.sexecute('Any S,SN WHERE S is State, S name SN')) @@ -275,22 +275,22 @@ states.remove((userstate.eid, userstate.name)) notstates = set(tuple(x) for x in self.sexecute('Any S,SN WHERE S is State, S name SN, NOT X in_state S, X eid %(x)s', {'x': self.session.user.eid})) - self.assertSetEquals(notstates, states) + self.assertSetEqual(notstates, states) aff1 = self.sexecute('Any X WHERE X is Affaire, X ref "AFFREF"')[0][0] aff1stateeid, aff1statename = self.sexecute('Any S,SN WHERE X eid %(x)s, X in_state S, S name SN', {'x': aff1})[0] - self.assertEquals(aff1statename, 'pitetre') + self.assertEqual(aff1statename, 'pitetre') states.add((userstate.eid, userstate.name)) states.remove((aff1stateeid, aff1statename)) notstates = set(tuple(x) for x in self.sexecute('Any S,SN WHERE S is State, S name SN, NOT X in_state S, X eid %(x)s', {'x': aff1})) - self.assertSetEquals(notstates, states) + self.assertSetEqual(notstates, states) def test_absolute_url_base_url(self): cu = cnx2.cursor() ceid = cu.execute('INSERT Card X: X title "without wikiid to get eid based url"')[0][0] cnx2.commit() lc = self.sexecute('Card X WHERE X title "without wikiid to get eid based url"').get_entity(0, 0) - self.assertEquals(lc.absolute_url(), 'http://extern.org/card/eid/%s' % ceid) + self.assertEqual(lc.absolute_url(), 'http://extern.org/card/eid/%s' % ceid) cu.execute('DELETE Card X WHERE X eid %(x)s', {'x':ceid}) cnx2.commit() @@ -299,7 +299,7 @@ ceid = cu.execute('INSERT Card X: X title "without wikiid to get eid based url"')[0][0] cnx3.commit() lc = self.sexecute('Card X WHERE X title "without wikiid to get eid based url"').get_entity(0, 0) - self.assertEquals(lc.absolute_url(), 'http://testing.fr/cubicweb/card/eid/%s' % lc.eid) + self.assertEqual(lc.absolute_url(), 'http://testing.fr/cubicweb/card/eid/%s' % lc.eid) cu.execute('DELETE Card X WHERE X eid %(x)s', {'x':ceid}) cnx3.commit() @@ -315,8 +315,8 @@ treid = iworkflowable.latest_trinfo().eid rset = self.sexecute('Any X ORDERBY D DESC WHERE E eid %(x)s, E wf_info_for X, X modification_date D', {'x': treid}) - self.assertEquals(len(rset), 1) - self.assertEquals(rset.rows[0], [self.session.user.eid]) + self.assertEqual(len(rset), 1) + self.assertEqual(rset.rows[0], [self.session.user.eid]) def test_nonregr3(self): self.sexecute('DELETE Card X WHERE X eid %(x)s, NOT X multisource_inlined_rel Y', {'x': self.ic1}) diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_querier.py --- a/server/test/unittest_querier.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_querier.py Wed Sep 29 16:16:32 2010 +0200 @@ -57,7 +57,7 @@ class MakeSchemaTC(TestCase): def test_known_values(self): solution = {'A': 'String', 'B': 'CWUser'} - self.assertEquals(make_schema((Variable('A'), Variable('B')), solution, + self.assertEqual(make_schema((Variable('A'), Variable('B')), solution, 'table0', TYPEMAP), ('C0 text,C1 integer', {'A': 'table0.C0', 'B': 'table0.C1'})) @@ -84,7 +84,7 @@ def test_preprocess_1(self): reid = self.execute('Any X WHERE X is CWRType, X name "owned_by"')[0][0] rqlst = self._prepare('Any COUNT(RDEF) WHERE RDEF relation_type X, X eid %(x)s', {'x': reid}) - self.assertEquals(rqlst.solutions, [{'RDEF': 'CWAttribute'}, {'RDEF': 'CWRelation'}]) + self.assertEqual(rqlst.solutions, [{'RDEF': 'CWAttribute'}, {'RDEF': 'CWRelation'}]) def test_preprocess_2(self): teid = self.execute("INSERT Tag X: X name 'tag'")[0][0] @@ -94,7 +94,7 @@ rqlst = self._prepare('Any X WHERE E eid %(x)s, E tags X', {'x': teid}) # the query may be optimized, should keep only one solution # (any one, etype will be discarded) - self.assertEquals(len(rqlst.solutions), 1) + self.assertEqual(len(rqlst.solutions), 1) def test_preprocess_security(self): plan = self._prepare_plan('Any ETN,COUNT(X) GROUPBY ETN ' @@ -102,24 +102,24 @@ plan.session = self.user_groups_session('users') union = plan.rqlst plan.preprocess(union) - self.assertEquals(len(union.children), 1) - self.assertEquals(len(union.children[0].with_), 1) + self.assertEqual(len(union.children), 1) + self.assertEqual(len(union.children[0].with_), 1) subq = union.children[0].with_[0].query - self.assertEquals(len(subq.children), 3) - self.assertEquals([t.as_string() for t in union.children[0].selection], + self.assertEqual(len(subq.children), 3) + self.assertEqual([t.as_string() for t in union.children[0].selection], ['ETN','COUNT(X)']) - self.assertEquals([t.as_string() for t in union.children[0].groupby], + self.assertEqual([t.as_string() for t in union.children[0].groupby], ['ETN']) partrqls = sorted(((rqlst.as_string(), rqlst.solutions) for rqlst in subq.children)) rql, solutions = partrqls[0] - self.assertEquals(rql, + self.assertEqual(rql, 'Any ETN,X WHERE X is ET, ET name ETN, (EXISTS(X owned_by %(B)s))' ' OR ((((EXISTS(D concerne C?, C owned_by %(B)s, X identity D, C is Division, D is Affaire))' ' OR (EXISTS(H concerne G?, G owned_by %(B)s, G is SubDivision, X identity H, H is Affaire)))' ' OR (EXISTS(I concerne F?, F owned_by %(B)s, F is Societe, X identity I, I is Affaire)))' ' OR (EXISTS(J concerne E?, E owned_by %(B)s, E is Note, X identity J, J is Affaire)))' ', ET is CWEType, X is Affaire') - self.assertEquals(solutions, [{'C': 'Division', + self.assertEqual(solutions, [{'C': 'Division', 'D': 'Affaire', 'E': 'Note', 'F': 'Societe', @@ -130,8 +130,8 @@ 'X': 'Affaire', 'ET': 'CWEType', 'ETN': 'String'}]) rql, solutions = partrqls[1] - self.assertEquals(rql, 'Any ETN,X WHERE X is ET, ET name ETN, ET is CWEType, X is IN(BaseTransition, Bookmark, CWAttribute, CWCache, CWConstraint, CWConstraintType, CWEType, CWGroup, CWPermission, CWProperty, CWRType, CWRelation, CWUniqueTogetherConstraint, CWUser, Card, Comment, Division, Email, EmailAddress, EmailPart, EmailThread, ExternalUri, File, Folder, Note, Personne, RQLExpression, Societe, State, SubDivision, SubWorkflowExitPoint, Tag, TrInfo, Transition, Workflow, WorkflowTransition)') - self.assertListEquals(sorted(solutions), + self.assertEqual(rql, 'Any ETN,X WHERE X is ET, ET name ETN, ET is CWEType, X is IN(BaseTransition, Bookmark, CWAttribute, CWCache, CWConstraint, CWConstraintType, CWEType, CWGroup, CWPermission, CWProperty, CWRType, CWRelation, CWUniqueTogetherConstraint, CWUser, Card, Comment, Division, Email, EmailAddress, EmailPart, EmailThread, ExternalUri, File, Folder, Note, Personne, RQLExpression, Societe, State, SubDivision, SubWorkflowExitPoint, Tag, TrInfo, Transition, Workflow, WorkflowTransition)') + self.assertListEqual(sorted(solutions), sorted([{'X': 'BaseTransition', 'ETN': 'String', 'ET': 'CWEType'}, {'X': 'Bookmark', 'ETN': 'String', 'ET': 'CWEType'}, {'X': 'Card', 'ETN': 'String', 'ET': 'CWEType'}, @@ -169,10 +169,10 @@ {'X': 'Workflow', 'ETN': 'String', 'ET': 'CWEType'}, {'X': 'WorkflowTransition', 'ETN': 'String', 'ET': 'CWEType'}])) rql, solutions = partrqls[2] - self.assertEquals(rql, + self.assertEqual(rql, 'Any ETN,X WHERE X is ET, ET name ETN, EXISTS(X owned_by %(C)s), ' 'ET is CWEType, X is Basket') - self.assertEquals(solutions, [{'ET': 'CWEType', + self.assertEqual(solutions, [{'ET': 'CWEType', 'X': 'Basket', 'ETN': 'String', }]) @@ -182,45 +182,45 @@ plan.session = self.user_groups_session('users') union = plan.rqlst plan.preprocess(union) - self.assertEquals(len(union.children), 1) - self.assertEquals(len(union.children[0].with_), 1) + self.assertEqual(len(union.children), 1) + self.assertEqual(len(union.children[0].with_), 1) subq = union.children[0].with_[0].query - self.assertEquals(len(subq.children), 3) - self.assertEquals([t.as_string() for t in union.children[0].selection], + self.assertEqual(len(subq.children), 3) + self.assertEqual([t.as_string() for t in union.children[0].selection], ['MAX(X)']) def test_preprocess_nonregr(self): rqlst = self._prepare('Any S ORDERBY SI WHERE NOT S ecrit_par O, S para SI') - self.assertEquals(len(rqlst.solutions), 1) + self.assertEqual(len(rqlst.solutions), 1) def test_build_description(self): # should return an empty result set rset = self.execute('Any X WHERE X eid %(x)s', {'x': self.session.user.eid}) - self.assertEquals(rset.description[0][0], 'CWUser') + self.assertEqual(rset.description[0][0], 'CWUser') rset = self.execute('Any 1') - self.assertEquals(rset.description[0][0], 'Int') + self.assertEqual(rset.description[0][0], 'Int') rset = self.execute('Any TRUE') - self.assertEquals(rset.description[0][0], 'Boolean') + self.assertEqual(rset.description[0][0], 'Boolean') rset = self.execute('Any "hop"') - self.assertEquals(rset.description[0][0], 'String') + self.assertEqual(rset.description[0][0], 'String') rset = self.execute('Any TODAY') - self.assertEquals(rset.description[0][0], 'Date') + self.assertEqual(rset.description[0][0], 'Date') rset = self.execute('Any NOW') - self.assertEquals(rset.description[0][0], 'Datetime') + self.assertEqual(rset.description[0][0], 'Datetime') rset = self.execute('Any %(x)s', {'x': 1}) - self.assertEquals(rset.description[0][0], 'Int') + self.assertEqual(rset.description[0][0], 'Int') rset = self.execute('Any %(x)s', {'x': 1L}) - self.assertEquals(rset.description[0][0], 'Int') + self.assertEqual(rset.description[0][0], 'Int') rset = self.execute('Any %(x)s', {'x': True}) - self.assertEquals(rset.description[0][0], 'Boolean') + self.assertEqual(rset.description[0][0], 'Boolean') rset = self.execute('Any %(x)s', {'x': 1.0}) - self.assertEquals(rset.description[0][0], 'Float') + self.assertEqual(rset.description[0][0], 'Float') rset = self.execute('Any %(x)s', {'x': datetime.now()}) - self.assertEquals(rset.description[0][0], 'Datetime') + self.assertEqual(rset.description[0][0], 'Datetime') rset = self.execute('Any %(x)s', {'x': 'str'}) - self.assertEquals(rset.description[0][0], 'String') + self.assertEqual(rset.description[0][0], 'String') rset = self.execute('Any %(x)s', {'x': u'str'}) - self.assertEquals(rset.description[0][0], 'String') + self.assertEqual(rset.description[0][0], 'String') class QuerierTC(BaseQuerierTC): @@ -244,46 +244,46 @@ {'data': Binary("xxx")})[0][0] fdata = self.execute('Any D WHERE X data D, X eid %(x)s', {'x': feid})[0][0] self.assertIsInstance(fdata, Binary) - self.assertEquals(fdata.getvalue(), 'xxx') + self.assertEqual(fdata.getvalue(), 'xxx') # selection queries tests ################################################# def test_select_1(self): rset = self.execute('Any X ORDERBY X WHERE X is CWGroup') result, descr = rset.rows, rset.description - self.assertEquals(tuplify(result), [(1,), (2,), (3,), (4,)]) - self.assertEquals(descr, [('CWGroup',), ('CWGroup',), ('CWGroup',), ('CWGroup',)]) + self.assertEqual(tuplify(result), [(1,), (2,), (3,), (4,)]) + self.assertEqual(descr, [('CWGroup',), ('CWGroup',), ('CWGroup',), ('CWGroup',)]) def test_select_2(self): rset = self.execute('Any X ORDERBY N WHERE X is CWGroup, X name N') - self.assertEquals(tuplify(rset.rows), [(1,), (2,), (3,), (4,)]) - self.assertEquals(rset.description, [('CWGroup',), ('CWGroup',), ('CWGroup',), ('CWGroup',)]) + self.assertEqual(tuplify(rset.rows), [(1,), (2,), (3,), (4,)]) + self.assertEqual(rset.description, [('CWGroup',), ('CWGroup',), ('CWGroup',), ('CWGroup',)]) rset = self.execute('Any X ORDERBY N DESC WHERE X is CWGroup, X name N') - self.assertEquals(tuplify(rset.rows), [(4,), (3,), (2,), (1,)]) + self.assertEqual(tuplify(rset.rows), [(4,), (3,), (2,), (1,)]) def test_select_3(self): rset = self.execute('Any N GROUPBY N WHERE X is CWGroup, X name N') result, descr = rset.rows, rset.description result.sort() - self.assertEquals(tuplify(result), [('guests',), ('managers',), ('owners',), ('users',)]) - self.assertEquals(descr, [('String',), ('String',), ('String',), ('String',)]) + self.assertEqual(tuplify(result), [('guests',), ('managers',), ('owners',), ('users',)]) + self.assertEqual(descr, [('String',), ('String',), ('String',), ('String',)]) def test_select_is(self): rset = self.execute('Any X, TN ORDERBY TN LIMIT 10 WHERE X is T, T name TN') result, descr = rset.rows, rset.description - self.assertEquals(result[0][1], descr[0][0]) + self.assertEqual(result[0][1], descr[0][0]) def test_select_is_aggr(self): rset = self.execute('Any TN, COUNT(X) GROUPBY TN ORDERBY 2 DESC WHERE X is T, T name TN') result, descr = rset.rows, rset.description - self.assertEquals(descr[0][0], 'String') - self.assertEquals(descr[0][1], 'Int') - self.assertEquals(result[0][0], 'CWRelation') # XXX may change as schema evolve + self.assertEqual(descr[0][0], 'String') + self.assertEqual(descr[0][1], 'Int') + self.assertEqual(result[0][0], 'CWRelation') # XXX may change as schema evolve def test_select_groupby_orderby(self): rset = self.execute('Any N GROUPBY N ORDERBY N WHERE X is CWGroup, X name N') - self.assertEquals(tuplify(rset.rows), [('guests',), ('managers',), ('owners',), ('users',)]) - self.assertEquals(rset.description, [('String',), ('String',), ('String',), ('String',)]) + self.assertEqual(tuplify(rset.rows), [('guests',), ('managers',), ('owners',), ('users',)]) + self.assertEqual(rset.description, [('String',), ('String',), ('String',), ('String',)]) def test_select_complex_groupby(self): rset = self.execute('Any N GROUPBY N WHERE X name N') @@ -295,20 +295,20 @@ def test_select_complex_orderby(self): rset1 = self.execute('Any N ORDERBY N WHERE X name N') - self.assertEquals(sorted(rset1.rows), rset1.rows) + self.assertEqual(sorted(rset1.rows), rset1.rows) rset = self.execute('Any N ORDERBY N LIMIT 5 OFFSET 1 WHERE X name N') - self.assertEquals(rset.rows[0][0], rset1.rows[1][0]) - self.assertEquals(len(rset), 5) + self.assertEqual(rset.rows[0][0], rset1.rows[1][0]) + self.assertEqual(len(rset), 5) def test_select_5(self): rset = self.execute('Any X, TMP ORDERBY TMP WHERE X name TMP, X is CWGroup') - self.assertEquals(tuplify(rset.rows), [(1, 'guests',), (2, 'managers',), (3, 'owners',), (4, 'users',)]) - self.assertEquals(rset.description, [('CWGroup', 'String',), ('CWGroup', 'String',), ('CWGroup', 'String',), ('CWGroup', 'String',)]) + self.assertEqual(tuplify(rset.rows), [(1, 'guests',), (2, 'managers',), (3, 'owners',), (4, 'users',)]) + self.assertEqual(rset.description, [('CWGroup', 'String',), ('CWGroup', 'String',), ('CWGroup', 'String',), ('CWGroup', 'String',)]) def test_select_6(self): self.execute("INSERT Personne X: X nom 'bidule'")[0] rset = self.execute('Any Y where X name TMP, Y nom in (TMP, "bidule")') - #self.assertEquals(rset.description, [('Personne',), ('Personne',)]) + #self.assertEqual(rset.description, [('Personne',), ('Personne',)]) self.assert_(('Personne',) in rset.description) rset = self.execute('DISTINCT Any Y where X name TMP, Y nom in (TMP, "bidule")') self.assert_(('Personne',) in rset.description) @@ -317,17 +317,17 @@ peid = self.execute("INSERT Personne X: X nom 'bidule'")[0][0] seid = self.execute("INSERT Societe X: X nom 'chouette'")[0][0] rset = self.execute('Personne X WHERE NOT X nom "bidule"') - self.assertEquals(len(rset.rows), 0, rset.rows) + self.assertEqual(len(rset.rows), 0, rset.rows) rset = self.execute('Personne X WHERE NOT X nom "bid"') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) self.execute("SET P travaille S WHERE P nom 'bidule', S nom 'chouette'") rset = self.execute('Personne X WHERE NOT X travaille S') - self.assertEquals(len(rset.rows), 0, rset.rows) + self.assertEqual(len(rset.rows), 0, rset.rows) def test_select_is_in(self): self.execute("INSERT Personne X: X nom 'bidule'") self.execute("INSERT Societe X: X nom 'chouette'") - self.assertEquals(len(self.execute("Any X WHERE X is IN (Personne, Societe)")), + self.assertEqual(len(self.execute("Any X WHERE X is IN (Personne, Societe)")), 2) def test_select_not_rel(self): @@ -336,9 +336,9 @@ self.execute("INSERT Personne X: X nom 'autre'") self.execute("SET P travaille S WHERE P nom 'bidule', S nom 'chouette'") rset = self.execute('Personne X WHERE NOT X travaille S') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) rset = self.execute('Personne X WHERE NOT X travaille S, S nom "chouette"') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) def test_select_nonregr_inlined(self): self.execute("INSERT Note X: X para 'bidule'") @@ -347,15 +347,15 @@ self.execute("SET X ecrit_par P WHERE X para 'bidule', P nom 'chouette'") rset = self.execute('Any U,T ORDERBY T DESC WHERE U is CWUser, ' 'N ecrit_par U, N type T')#, {'x': self.ueid}) - self.assertEquals(len(rset.rows), 0) + self.assertEqual(len(rset.rows), 0) def test_select_nonregr_edition_not(self): groupeids = set((1, 2, 3)) groupreadperms = set(r[0] for r in self.execute('Any Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), X read_permission Y')) rset = self.execute('DISTINCT Any Y WHERE X is CWEType, X name "CWGroup", Y eid IN(1, 2, 3), NOT X read_permission Y') - self.assertEquals(sorted(r[0] for r in rset.rows), sorted(groupeids - groupreadperms)) + self.assertEqual(sorted(r[0] for r in rset.rows), sorted(groupeids - groupreadperms)) rset = self.execute('DISTINCT Any Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), NOT X read_permission Y') - self.assertEquals(sorted(r[0] for r in rset.rows), sorted(groupeids - groupreadperms)) + self.assertEqual(sorted(r[0] for r in rset.rows), sorted(groupeids - groupreadperms)) def test_select_outer_join(self): peid1 = self.execute("INSERT Personne X: X nom 'bidule'")[0][0] @@ -363,27 +363,27 @@ seid1 = self.execute("INSERT Societe X: X nom 'chouette'")[0][0] seid2 = self.execute("INSERT Societe X: X nom 'chouetos'")[0][0] rset = self.execute('Any X,S ORDERBY X WHERE X travaille S?') - self.assertEquals(rset.rows, [[peid1, None], [peid2, None]]) + self.assertEqual(rset.rows, [[peid1, None], [peid2, None]]) self.execute("SET P travaille S WHERE P nom 'bidule', S nom 'chouette'") rset = self.execute('Any X,S ORDERBY X WHERE X travaille S?') - self.assertEquals(rset.rows, [[peid1, seid1], [peid2, None]]) + self.assertEqual(rset.rows, [[peid1, seid1], [peid2, None]]) rset = self.execute('Any S,X ORDERBY S WHERE X? travaille S') - self.assertEquals(rset.rows, [[seid1, peid1], [seid2, None]]) + self.assertEqual(rset.rows, [[seid1, peid1], [seid2, None]]) def test_select_outer_join_optimized(self): peid1 = self.execute("INSERT Personne X: X nom 'bidule'")[0][0] rset = self.execute('Any X WHERE X eid %(x)s, P? connait X', {'x':peid1}) - self.assertEquals(rset.rows, [[peid1]]) + self.assertEqual(rset.rows, [[peid1]]) rset = self.execute('Any X WHERE X eid %(x)s, X require_permission P?', {'x':peid1}) - self.assertEquals(rset.rows, [[peid1]]) + self.assertEqual(rset.rows, [[peid1]]) def test_select_left_outer_join(self): rset = self.execute('DISTINCT Any G WHERE U? in_group G') - self.assertEquals(len(rset), 4) + self.assertEqual(len(rset), 4) rset = self.execute('DISTINCT Any G WHERE U? in_group G, U eid %(x)s', {'x': self.session.user.eid}) - self.assertEquals(len(rset), 4) + self.assertEqual(len(rset), 4) def test_select_ambigous_outer_join(self): teid = self.execute("INSERT Tag X: X name 'tag'")[0][0] @@ -395,7 +395,7 @@ self.failUnless(['users', 'tag'] in rset.rows) self.failUnless(['activated', None] in rset.rows) rset = self.execute("Any GN,TN ORDERBY GN WHERE T tags G?, T name TN, G name GN") - self.assertEquals(rset.rows, [[None, 'tagbis'], ['users', 'tag']]) + self.assertEqual(rset.rows, [[None, 'tagbis'], ['users', 'tag']]) def test_select_not_inline_rel(self): self.execute("INSERT Personne X: X nom 'bidule'") @@ -403,7 +403,7 @@ self.execute("INSERT Note X: X type 'b'") self.execute("SET X ecrit_par Y WHERE X type 'a', Y nom 'bidule'") rset = self.execute('Note X WHERE NOT X ecrit_par P') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) def test_select_not_unlinked_multiple_solutions(self): self.execute("INSERT Personne X: X nom 'bidule'") @@ -411,7 +411,7 @@ self.execute("INSERT Note X: X type 'b'") self.execute("SET Y evaluee X WHERE X type 'a', Y nom 'bidule'") rset = self.execute('Note X WHERE NOT Y evaluee X') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) def test_select_date_extraction(self): self.execute("INSERT Personne X: X nom 'foo', X datenaiss %(d)s", @@ -421,41 +421,41 @@ for funcname, result in test_data: rset = self.execute('Any %s(D) WHERE X is Personne, X datenaiss D' % funcname) - self.assertEquals(len(rset.rows), 1) - self.assertEquals(rset.rows[0][0], result) - self.assertEquals(rset.description, [('Int',)]) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(rset.rows[0][0], result) + self.assertEqual(rset.description, [('Int',)]) def test_select_aggregat_count(self): rset = self.execute('Any COUNT(X)') - self.assertEquals(len(rset.rows), 1) - self.assertEquals(len(rset.rows[0]), 1) - self.assertEquals(rset.description, [('Int',)]) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(len(rset.rows[0]), 1) + self.assertEqual(rset.description, [('Int',)]) def test_select_aggregat_sum(self): rset = self.execute('Any SUM(O) WHERE X ordernum O') - self.assertEquals(len(rset.rows), 1) - self.assertEquals(len(rset.rows[0]), 1) - self.assertEquals(rset.description, [('Int',)]) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(len(rset.rows[0]), 1) + self.assertEqual(rset.description, [('Int',)]) def test_select_aggregat_min(self): rset = self.execute('Any MIN(X) WHERE X is Personne') - self.assertEquals(len(rset.rows), 1) - self.assertEquals(len(rset.rows[0]), 1) - self.assertEquals(rset.description, [('Personne',)]) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(len(rset.rows[0]), 1) + self.assertEqual(rset.description, [('Personne',)]) rset = self.execute('Any MIN(O) WHERE X ordernum O') - self.assertEquals(len(rset.rows), 1) - self.assertEquals(len(rset.rows[0]), 1) - self.assertEquals(rset.description, [('Int',)]) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(len(rset.rows[0]), 1) + self.assertEqual(rset.description, [('Int',)]) def test_select_aggregat_max(self): rset = self.execute('Any MAX(X) WHERE X is Personne') - self.assertEquals(len(rset.rows), 1) - self.assertEquals(len(rset.rows[0]), 1) - self.assertEquals(rset.description, [('Personne',)]) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(len(rset.rows[0]), 1) + self.assertEqual(rset.description, [('Personne',)]) rset = self.execute('Any MAX(O) WHERE X ordernum O') - self.assertEquals(len(rset.rows), 1) - self.assertEquals(len(rset.rows[0]), 1) - self.assertEquals(rset.description, [('Int',)]) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(len(rset.rows[0]), 1) + self.assertEqual(rset.description, [('Int',)]) def test_select_custom_aggregat_concat_string(self): rset = self.execute('Any GROUP_CONCAT(N) WHERE X is CWGroup, X name N') @@ -482,15 +482,15 @@ def test_select_aggregat_sort(self): rset = self.execute('Any G, COUNT(U) GROUPBY G ORDERBY 2 WHERE U in_group G') - self.assertEquals(len(rset.rows), 2) - self.assertEquals(len(rset.rows[0]), 2) - self.assertEquals(rset.description[0], ('CWGroup', 'Int',)) + self.assertEqual(len(rset.rows), 2) + self.assertEqual(len(rset.rows[0]), 2) + self.assertEqual(rset.description[0], ('CWGroup', 'Int',)) def test_select_aggregat_having(self): rset = self.execute('Any N,COUNT(RDEF) GROUPBY N ORDERBY 2,N ' 'WHERE RT name N, RDEF relation_type RT ' 'HAVING COUNT(RDEF) > 10') - self.assertListEquals(rset.rows, + self.assertListEqual(rset.rows, [[u'description_format', 12], [u'description', 13], [u'name', 14], @@ -508,13 +508,13 @@ rset = self.execute('Any U,COUNT(X) GROUPBY U ' 'WHERE U eid %(x)s, X owned_by U ' 'HAVING COUNT(X) > 10', {'x': self.ueid}) - self.assertEquals(len(rset.rows), 1) - self.assertEquals(rset.rows[0][0], self.ueid) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(rset.rows[0][0], self.ueid) def test_select_having_non_aggregat_1(self): rset = self.execute('Any L WHERE X login L, X creation_date CD ' 'HAVING YEAR(CD) = %s' % date.today().year) - self.assertListEquals(rset.rows, + self.assertListEqual(rset.rows, [[u'admin'], [u'anon']]) @@ -522,7 +522,7 @@ rset = self.execute('Any L GROUPBY L WHERE X login L, X in_group G, ' 'X creation_date CD HAVING YEAR(CD) = %s OR COUNT(G) > 1' % date.today().year) - self.assertListEquals(rset.rows, + self.assertListEqual(rset.rows, [[u'admin'], [u'anon']]) @@ -531,39 +531,46 @@ rset = self.execute('Any X ORDERBY X,D LIMIT 5 WHERE X creation_date D') result = rset.rows result.sort() - self.assertEquals(tuplify(result), [(1,), (2,), (3,), (4,), (5,)]) + self.assertEqual(tuplify(result), [(1,), (2,), (3,), (4,), (5,)]) def test_select_upper(self): rset = self.execute('Any X, UPPER(L) ORDERBY L WHERE X is CWUser, X login L') - self.assertEquals(len(rset.rows), 2) - self.assertEquals(rset.rows[0][1], 'ADMIN') - self.assertEquals(rset.description[0], ('CWUser', 'String',)) - self.assertEquals(rset.rows[1][1], 'ANON') - self.assertEquals(rset.description[1], ('CWUser', 'String',)) + self.assertEqual(len(rset.rows), 2) + self.assertEqual(rset.rows[0][1], 'ADMIN') + self.assertEqual(rset.description[0], ('CWUser', 'String',)) + self.assertEqual(rset.rows[1][1], 'ANON') + self.assertEqual(rset.description[1], ('CWUser', 'String',)) eid = rset.rows[0][0] rset = self.execute('Any UPPER(L) WHERE X eid %s, X login L'%eid) - self.assertEquals(rset.rows[0][0], 'ADMIN') - self.assertEquals(rset.description, [('String',)]) + self.assertEqual(rset.rows[0][0], 'ADMIN') + self.assertEqual(rset.description, [('String',)]) def test_select_float_abs(self): # test positive number eid = self.execute('INSERT Affaire A: A invoiced %(i)s', {'i': 1.2})[0][0] rset = self.execute('Any ABS(I) WHERE X eid %(x)s, X invoiced I', {'x': eid}) - self.assertEquals(rset.rows[0][0], 1.2) + self.assertEqual(rset.rows[0][0], 1.2) # test negative number eid = self.execute('INSERT Affaire A: A invoiced %(i)s', {'i': -1.2})[0][0] rset = self.execute('Any ABS(I) WHERE X eid %(x)s, X invoiced I', {'x': eid}) - self.assertEquals(rset.rows[0][0], 1.2) + self.assertEqual(rset.rows[0][0], 1.2) def test_select_int_abs(self): # test positive number eid = self.execute('INSERT Affaire A: A duration %(d)s', {'d': 12})[0][0] rset = self.execute('Any ABS(D) WHERE X eid %(x)s, X duration D', {'x': eid}) - self.assertEquals(rset.rows[0][0], 12) + self.assertEqual(rset.rows[0][0], 12) # test negative number eid = self.execute('INSERT Affaire A: A duration %(d)s', {'d': -12})[0][0] rset = self.execute('Any ABS(D) WHERE X eid %(x)s, X duration D', {'x': eid}) - self.assertEquals(rset.rows[0][0], 12) + self.assertEqual(rset.rows[0][0], 12) + +## def test_select_simplified(self): +## ueid = self.session.user.eid +## rset = self.execute('Any L WHERE %s login L'%ueid) +## self.assertEqual(rset.rows[0][0], 'admin') +## rset = self.execute('Any L WHERE %(x)s login L', {'x':ueid}) +## self.assertEqual(rset.rows[0][0], 'admin') def test_select_searchable_text_1(self): rset = self.execute(u"INSERT Personne X: X nom 'bidüle'") @@ -571,9 +578,9 @@ rset = self.execute("INSERT Societe X: X nom 'chouette'") self.commit() rset = self.execute('Any X where X has_text %(text)s', {'text': u'bidüle'}) - self.assertEquals(len(rset.rows), 2, rset.rows) + self.assertEqual(len(rset.rows), 2, rset.rows) rset = self.execute(u'Any N where N has_text "bidüle"') - self.assertEquals(len(rset.rows), 2, rset.rows) + self.assertEqual(len(rset.rows), 2, rset.rows) biduleeids = [r[0] for r in rset.rows] rset = self.execute(u'Any N where NOT N has_text "bidüle"') self.failIf([r[0] for r in rset.rows if r[0] in biduleeids]) @@ -586,7 +593,7 @@ rset = self.execute("INSERT Societe X: X nom 'bidule'") self.commit() rset = self.execute('Personne N where N has_text "bidule"') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) def test_select_searchable_text_3(self): rset = self.execute("INSERT Personne X: X nom 'bidule', X sexe 'M'") @@ -594,7 +601,7 @@ rset = self.execute("INSERT Societe X: X nom 'bidule'") self.commit() rset = self.execute('Any X where X has_text "bidule" and X sexe "M"') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) def test_select_multiple_searchable_text(self): self.execute(u"INSERT Personne X: X nom 'bidüle'") @@ -605,20 +612,20 @@ {'text': u'bidüle', 'text2': u'chouette',} ) - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) def test_select_no_descr(self): rset = self.execute('Any X WHERE X is CWGroup', build_descr=0) rset.rows.sort() - self.assertEquals(tuplify(rset.rows), [(1,), (2,), (3,), (4,)]) - self.assertEquals(rset.description, ()) + self.assertEqual(tuplify(rset.rows), [(1,), (2,), (3,), (4,)]) + self.assertEqual(rset.description, ()) def test_select_limit_offset(self): rset = self.execute('CWGroup X ORDERBY N LIMIT 2 WHERE X name N') - self.assertEquals(tuplify(rset.rows), [(1,), (2,)]) - self.assertEquals(rset.description, [('CWGroup',), ('CWGroup',)]) + self.assertEqual(tuplify(rset.rows), [(1,), (2,)]) + self.assertEqual(rset.description, [('CWGroup',), ('CWGroup',)]) rset = self.execute('CWGroup X ORDERBY N LIMIT 2 OFFSET 2 WHERE X name N') - self.assertEquals(tuplify(rset.rows), [(3,), (4,)]) + self.assertEqual(tuplify(rset.rows), [(3,), (4,)]) def test_select_symmetric(self): self.execute("INSERT Personne X: X nom 'machin'") @@ -628,24 +635,24 @@ self.execute("SET X connait Y WHERE X nom 'chouette', Y nom 'bidule'") self.execute("SET X connait Y WHERE X nom 'machin', Y nom 'chouette'") rset = self.execute('Any P where P connait P2') - self.assertEquals(len(rset.rows), 3, rset.rows) + self.assertEqual(len(rset.rows), 3, rset.rows) rset = self.execute('Any P where NOT P connait P2') - self.assertEquals(len(rset.rows), 1, rset.rows) # trucmuche + self.assertEqual(len(rset.rows), 1, rset.rows) # trucmuche rset = self.execute('Any P where P connait P2, P2 nom "bidule"') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) rset = self.execute('Any P where P2 connait P, P2 nom "bidule"') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) rset = self.execute('Any P where P connait P2, P2 nom "chouette"') - self.assertEquals(len(rset.rows), 2, rset.rows) + self.assertEqual(len(rset.rows), 2, rset.rows) rset = self.execute('Any P where P2 connait P, P2 nom "chouette"') - self.assertEquals(len(rset.rows), 2, rset.rows) + self.assertEqual(len(rset.rows), 2, rset.rows) def test_select_inline(self): self.execute("INSERT Personne X: X nom 'bidule'") self.execute("INSERT Note X: X type 'a'") self.execute("SET X ecrit_par Y WHERE X type 'a', Y nom 'bidule'") rset = self.execute('Any N where N ecrit_par X, X nom "bidule"') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) def test_select_creation_date(self): self.execute("INSERT Personne X: X nom 'bidule'") @@ -715,13 +722,13 @@ def test_select_explicit_eid(self): rset = self.execute('Any X,E WHERE X owned_by U, X eid E, U eid %(u)s', {'u': self.session.user.eid}) self.failUnless(rset) - self.assertEquals(rset.description[0][1], 'Int') + self.assertEqual(rset.description[0][1], 'Int') # def test_select_rewritten_optional(self): # eid = self.execute("INSERT Affaire X: X sujet 'cool'")[0][0] # rset = self.execute('Any X WHERE X eid %(x)s, EXISTS(X owned_by U) OR EXISTS(X concerne S?, S owned_by U)', # {'x': eid}, 'x') -# self.assertEquals(rset.rows, [[eid]]) +# self.assertEqual(rset.rows, [[eid]]) def test_today_bug(self): self.execute("INSERT Tag X: X name 'bidule', X creation_date NOW") @@ -742,14 +749,14 @@ def test_select_boolean(self): rset = self.execute('Any N WHERE X is CWEType, X name N, X final %(val)s', {'val': True}) - self.assertEquals(sorted(r[0] for r in rset.rows), ['Boolean', 'Bytes', + self.assertEqual(sorted(r[0] for r in rset.rows), ['Boolean', 'Bytes', 'Date', 'Datetime', 'Decimal', 'Float', 'Int', 'Interval', 'Password', 'String', 'Time']) rset = self.execute('Any N WHERE X is CWEType, X name N, X final TRUE') - self.assertEquals(sorted(r[0] for r in rset.rows), ['Boolean', 'Bytes', + self.assertEqual(sorted(r[0] for r in rset.rows), ['Boolean', 'Bytes', 'Date', 'Datetime', 'Decimal', 'Float', 'Int', 'Interval', @@ -758,17 +765,17 @@ def test_select_constant(self): rset = self.execute('Any X, "toto" ORDERBY X WHERE X is CWGroup') - self.assertEquals(rset.rows, + self.assertEqual(rset.rows, map(list, zip((1,2,3,4), ('toto','toto','toto','toto',)))) self.assertIsInstance(rset[0][1], unicode) - self.assertEquals(rset.description, + self.assertEqual(rset.description, zip(('CWGroup', 'CWGroup', 'CWGroup', 'CWGroup'), ('String', 'String', 'String', 'String',))) rset = self.execute('Any X, %(value)s ORDERBY X WHERE X is CWGroup', {'value': 'toto'}) - self.assertEquals(rset.rows, + self.assertEqual(rset.rows, map(list, zip((1,2,3,4), ('toto','toto','toto','toto',)))) self.assertIsInstance(rset[0][1], unicode) - self.assertEquals(rset.description, + self.assertEqual(rset.description, zip(('CWGroup', 'CWGroup', 'CWGroup', 'CWGroup'), ('String', 'String', 'String', 'String',))) rset = self.execute('Any X,GN WHERE X is CWUser, G is CWGroup, X login "syt", X in_group G, G name GN') @@ -779,9 +786,9 @@ ' UNION ' '(Any X,N WHERE X name N, X state_of WF, WF workflow_of E, E name %(name)s))', {'name': 'CWUser'}) - self.assertEquals([x[1] for x in rset.rows], + self.assertEqual([x[1] for x in rset.rows], ['activate', 'activated', 'deactivate', 'deactivated']) - self.assertEquals(rset.description, + self.assertEqual(rset.description, [('Transition', 'String'), ('State', 'String'), ('Transition', 'String'), ('State', 'String')]) @@ -801,13 +808,13 @@ '((Any N,COUNT(X) GROUPBY N WHERE X name N, X is State HAVING COUNT(X)>1)' ' UNION ' '(Any N,COUNT(X) GROUPBY N WHERE X name N, X is Transition HAVING COUNT(X)>1))') - self.assertEquals(rset.rows, [[u'hop', 2], [u'hop', 2]]) + self.assertEqual(rset.rows, [[u'hop', 2], [u'hop', 2]]) def test_select_union_selection_with_diff_variables(self): rset = self.execute('(Any N WHERE X name N, X is State)' ' UNION ' '(Any NN WHERE XX name NN, XX is Transition)') - self.assertEquals(sorted(r[0] for r in rset.rows), + self.assertEqual(sorted(r[0] for r in rset.rows), ['abort', 'activate', 'activated', 'ben non', 'deactivate', 'deactivated', 'done', 'en cours', 'end', 'finie', 'markasdone', 'pitetre', 'redoit', @@ -820,7 +827,7 @@ ' UNION ' '(Any Y WHERE Y eid %(y)s)', {'x': eid1, 'y': eid2}) - self.assertEquals(rset.description[:], [('CWGroup',), ('CWUser',)]) + self.assertEqual(rset.description[:], [('CWGroup',), ('CWUser',)]) def test_exists(self): geid = self.execute("INSERT CWGroup X: X name 'lulufanclub'")[0][0] @@ -828,15 +835,15 @@ peid = self.execute("INSERT Personne X: X prenom 'lulu', X nom 'petit'")[0][0] rset = self.execute("Any X WHERE X prenom 'lulu'," "EXISTS (U in_group G, G name 'lulufanclub' OR G name 'managers');") - self.assertEquals(rset.rows, [[peid]]) + self.assertEqual(rset.rows, [[peid]]) def test_identity(self): eid = self.execute('Any X WHERE X identity Y, Y eid 1')[0][0] - self.assertEquals(eid, 1) + self.assertEqual(eid, 1) eid = self.execute('Any X WHERE Y identity X, Y eid 1')[0][0] - self.assertEquals(eid, 1) + self.assertEqual(eid, 1) login = self.execute('Any L WHERE X login "admin", X identity Y, Y login L')[0][0] - self.assertEquals(login, 'admin') + self.assertEqual(login, 'admin') def test_select_date_mathexp(self): rset = self.execute('Any X, TODAY - CD WHERE X is CWUser, X creation_date CD') @@ -852,8 +859,8 @@ rset = self.execute('Any GN, COUNT(X)*100/T GROUPBY GN ORDERBY 2,1' ' WHERE G name GN, X in_group G' ' WITH T BEING (Any COUNT(U) WHERE U is CWUser)') - self.assertEquals(rset.rows, [[u'guests', 50], [u'managers', 50], [u'users', 100]]) - self.assertEquals(rset.description, [('String', 'Int'), ('String', 'Int'), ('String', 'Int')]) + self.assertEqual(rset.rows, [[u'guests', 50], [u'managers', 50], [u'users', 100]]) + self.assertEqual(rset.description, [('String', 'Int'), ('String', 'Int'), ('String', 'Int')]) def test_select_subquery_aggregat_2(self): expected = self.execute('Any X, 0, COUNT(T) GROUPBY X ' @@ -864,55 +871,55 @@ T? transition_of P, T type "auto"), P2,E BEING (Any P,COUNT(T) GROUPBY P WHERE P is Workflow, T is Transition, T? transition_of P, T type "normal")''') - self.assertEquals(sorted(rset.rows), sorted(expected)) + self.assertEqual(sorted(rset.rows), sorted(expected)) def test_select_subquery_const(self): rset = self.execute('Any X WITH X BEING ((Any NULL) UNION (Any "toto"))') - self.assertEquals(rset.rows, [[None], ['toto']]) - self.assertEquals(rset.description, [(None,), ('String',)]) + self.assertEqual(rset.rows, [[None], ['toto']]) + self.assertEqual(rset.description, [(None,), ('String',)]) # insertion queries tests ################################################# def test_insert_is(self): eid, = self.execute("INSERT Personne X: X nom 'bidule'")[0] etype, = self.execute("Any TN WHERE X is T, X eid %s, T name TN" % eid)[0] - self.assertEquals(etype, 'Personne') + self.assertEqual(etype, 'Personne') self.execute("INSERT Personne X: X nom 'managers'") def test_insert_1(self): rset = self.execute("INSERT Personne X: X nom 'bidule'") - self.assertEquals(len(rset.rows), 1) - self.assertEquals(rset.description, [('Personne',)]) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(rset.description, [('Personne',)]) rset = self.execute('Personne X WHERE X nom "bidule"') self.assert_(rset.rows) - self.assertEquals(rset.description, [('Personne',)]) + self.assertEqual(rset.description, [('Personne',)]) def test_insert_1_multiple(self): self.execute("INSERT Personne X: X nom 'bidule'") self.execute("INSERT Personne X: X nom 'chouette'") rset = self.execute("INSERT Societe Y: Y nom N, P travaille Y WHERE P nom N") - self.assertEquals(len(rset.rows), 2) - self.assertEquals(rset.description, [('Societe',), ('Societe',)]) + self.assertEqual(len(rset.rows), 2) + self.assertEqual(rset.description, [('Societe',), ('Societe',)]) def test_insert_2(self): rset = self.execute("INSERT Personne X, Personne Y: X nom 'bidule', Y nom 'tutu'") - self.assertEquals(rset.description, [('Personne', 'Personne')]) + self.assertEqual(rset.description, [('Personne', 'Personne')]) rset = self.execute('Personne X WHERE X nom "bidule" or X nom "tutu"') self.assert_(rset.rows) - self.assertEquals(rset.description, [('Personne',), ('Personne',)]) + self.assertEqual(rset.description, [('Personne',), ('Personne',)]) def test_insert_3(self): self.execute("INSERT Personne X: X nom Y WHERE U login 'admin', U login Y") rset = self.execute('Personne X WHERE X nom "admin"') self.assert_(rset.rows) - self.assertEquals(rset.description, [('Personne',)]) + self.assertEqual(rset.description, [('Personne',)]) def test_insert_4(self): self.execute("INSERT Societe Y: Y nom 'toto'") self.execute("INSERT Personne X: X nom 'bidule', X travaille Y WHERE Y nom 'toto'") rset = self.execute('Any X, Y WHERE X nom "bidule", Y nom "toto", X travaille Y') self.assert_(rset.rows) - self.assertEquals(rset.description, [('Personne', 'Societe',)]) + self.assertEqual(rset.description, [('Personne', 'Societe',)]) def test_insert_4bis(self): peid = self.execute("INSERT Personne X: X nom 'bidule'")[0][0] @@ -937,7 +944,7 @@ self.execute("INSERT Societe Y: Y nom 'toto', X travaille Y WHERE X nom 'bidule'") rset = self.execute('Any X, Y WHERE X nom "bidule", Y nom "toto", X travaille Y') self.assert_(rset.rows) - self.assertEquals(rset.description, [('Personne', 'Societe',)]) + self.assertEqual(rset.description, [('Personne', 'Societe',)]) def test_insert_5bis(self): peid = self.execute("INSERT Personne X: X nom 'bidule'")[0][0] @@ -945,45 +952,45 @@ {'x': peid}) rset = self.execute('Any X, Y WHERE X nom "bidule", Y nom "toto", X travaille Y') self.assert_(rset.rows) - self.assertEquals(rset.description, [('Personne', 'Societe',)]) + self.assertEqual(rset.description, [('Personne', 'Societe',)]) def test_insert_6(self): self.execute("INSERT Personne X, Societe Y: X nom 'bidule', Y nom 'toto', X travaille Y") rset = self.execute('Any X, Y WHERE X nom "bidule", Y nom "toto", X travaille Y') self.assert_(rset.rows) - self.assertEquals(rset.description, [('Personne', 'Societe',)]) + self.assertEqual(rset.description, [('Personne', 'Societe',)]) def test_insert_7(self): self.execute("INSERT Personne X, Societe Y: X nom N, Y nom 'toto', X travaille Y WHERE U login 'admin', U login N") rset = self.execute('Any X, Y WHERE X nom "admin", Y nom "toto", X travaille Y') self.assert_(rset.rows) - self.assertEquals(rset.description, [('Personne', 'Societe',)]) + self.assertEqual(rset.description, [('Personne', 'Societe',)]) def test_insert_7_2(self): self.execute("INSERT Personne X, Societe Y: X nom N, Y nom 'toto', X travaille Y WHERE U login N") rset = self.execute('Any X, Y WHERE Y nom "toto", X travaille Y') - self.assertEquals(len(rset), 2) - self.assertEquals(rset.description, [('Personne', 'Societe',), + self.assertEqual(len(rset), 2) + self.assertEqual(rset.description, [('Personne', 'Societe',), ('Personne', 'Societe',)]) def test_insert_8(self): self.execute("INSERT Societe Y, Personne X: Y nom N, X nom 'toto', X travaille Y WHERE U login 'admin', U login N") rset = self.execute('Any X, Y WHERE X nom "toto", Y nom "admin", X travaille Y') self.assert_(rset.rows) - self.assertEquals(rset.description, [('Personne', 'Societe',)]) + self.assertEqual(rset.description, [('Personne', 'Societe',)]) def test_insert_9(self): self.execute("INSERT Societe X: X nom 'Lo'") self.execute("INSERT Societe X: X nom 'Gi'") self.execute("INSERT SubDivision X: X nom 'Lab'") rset = self.execute("INSERT Personne X: X nom N, X travaille Y, X travaille_subdivision Z WHERE Y is Societe, Z is SubDivision, Y nom N") - self.assertEquals(len(rset), 2) - self.assertEquals(rset.description, [('Personne',), ('Personne',)]) - # self.assertSetEquals(set(x.nom for x in rset.entities()), + self.assertEqual(len(rset), 2) + self.assertEqual(rset.description, [('Personne',), ('Personne',)]) + # self.assertSetEqual(set(x.nom for x in rset.entities()), # ['Lo', 'Gi']) - # self.assertSetEquals(set(y.nom for x in rset.entities() for y in x.travaille), + # self.assertSetEqual(set(y.nom for x in rset.entities() for y in x.travaille), # ['Lo', 'Gi']) - # self.assertEquals([y.nom for x in rset.entities() for y in x.travaille_subdivision], + # self.assertEqual([y.nom for x in rset.entities() for y in x.travaille_subdivision], # ['Lab', 'Lab']) def test_insert_query_error(self): @@ -1005,7 +1012,7 @@ rset = self.execute('INSERT CWUser E, EmailAddress EM: E login "X", E upassword "X", ' 'E primary_email EM, EM address "X", E in_group G ' 'WHERE G name "managers"') - self.assertEquals(list(rset.description[0]), ['CWUser', 'EmailAddress']) + self.assertEqual(list(rset.description[0]), ['CWUser', 'EmailAddress']) # deletion queries tests ################################################## @@ -1020,10 +1027,10 @@ def test_delete_2(self): rset = self.execute("INSERT Personne X, Personne Y, Societe Z : X nom 'syt', Y nom 'adim', Z nom 'Logilab', X travaille Z, Y travaille Z") - self.assertEquals(len(rset), 1) - self.assertEquals(len(rset[0]), 3) - self.assertEquals(rset.description[0], ('Personne', 'Personne', 'Societe')) - self.assertEquals(self.execute('Any N WHERE X nom N, X eid %s'% rset[0][0])[0][0], 'syt') + self.assertEqual(len(rset), 1) + self.assertEqual(len(rset[0]), 3) + self.assertEqual(rset.description[0], ('Personne', 'Personne', 'Societe')) + self.assertEqual(self.execute('Any N WHERE X nom N, X eid %s'% rset[0][0])[0][0], 'syt') rset = self.execute('Personne X WHERE X travaille Y, Y nom "Logilab"') self.assertEqual(len(rset.rows), 2, rset.rows) self.execute("DELETE X travaille Y WHERE X is Personne, Y nom 'Logilabo'") @@ -1049,16 +1056,16 @@ teid2 = self.execute("INSERT Folder T: T name 'tutu'")[0][0] self.execute('SET X see_also Y WHERE X eid %s, Y eid %s' % (teid1, teid2)) rset = self.execute('Any X,Y WHERE X see_also Y') - self.assertEquals(len(rset) , 2, rset.rows) + self.assertEqual(len(rset) , 2, rset.rows) self.execute('DELETE X see_also Y WHERE X eid %s, Y eid %s' % (teid1, teid2)) rset = self.execute('Any X,Y WHERE X see_also Y') - self.assertEquals(len(rset) , 0) + self.assertEqual(len(rset) , 0) self.execute('SET X see_also Y WHERE X eid %s, Y eid %s' % (teid1, teid2)) rset = self.execute('Any X,Y WHERE X see_also Y') - self.assertEquals(len(rset) , 2) + self.assertEqual(len(rset) , 2) self.execute('DELETE X see_also Y WHERE X eid %s, Y eid %s' % (teid2, teid1)) rset = self.execute('Any X,Y WHERE X see_also Y') - self.assertEquals(len(rset) , 0) + self.assertEqual(len(rset) , 0) def test_nonregr_delete_cache(self): """test that relations are properly cleaned when an entity is deleted @@ -1073,9 +1080,9 @@ self.o.execute(s, "DELETE Email X") sqlc = s.pool['system'] sqlc.execute('SELECT * FROM recipients_relation') - self.assertEquals(len(sqlc.fetchall()), 0) + self.assertEqual(len(sqlc.fetchall()), 0) sqlc.execute('SELECT * FROM owned_by_relation WHERE eid_from=%s'%eeid) - self.assertEquals(len(sqlc.fetchall()), 0) + self.assertEqual(len(sqlc.fetchall()), 0) def test_nonregr_delete_cache2(self): eid = self.execute("INSERT Folder T: T name 'toto'")[0][0] @@ -1088,13 +1095,13 @@ self.execute("DELETE Folder T WHERE T eid %s" % eid) self.commit() rset = self.execute("Any X WHERE X eid %(x)s", {'x': eid}) - self.assertEquals(rset.rows, []) + self.assertEqual(rset.rows, []) rset = self.execute("Any X WHERE X eid %s" % eid) - self.assertEquals(rset.rows, []) + self.assertEqual(rset.rows, []) rset = self.execute("Folder X WHERE X eid %(x)s", {'x': eid}) - self.assertEquals(rset.rows, []) + self.assertEqual(rset.rows, []) rset = self.execute("Folder X WHERE X eid %s" %eid) - self.assertEquals(rset.rows, []) + self.assertEqual(rset.rows, []) # update queries tests #################################################### @@ -1110,7 +1117,7 @@ def test_update_2(self): peid, seid = self.execute("INSERT Personne X, Societe Y: X nom 'bidule', Y nom 'toto'")[0] rset = self.execute("SET X travaille Y WHERE X nom 'bidule', Y nom 'toto'") - self.assertEquals(tuplify(rset.rows), [(peid, seid)]) + self.assertEqual(tuplify(rset.rows), [(peid, seid)]) rset = self.execute('Any X, Y WHERE X travaille Y') self.assertEqual(len(rset.rows), 1) @@ -1138,8 +1145,8 @@ peid1 = self.execute("INSERT Personne Y: Y nom 'tutu'")[0][0] peid2 = self.execute("INSERT Personne Y: Y nom 'toto'")[0][0] self.execute("SET X nom 'tutu', Y nom 'toto' WHERE X nom 'toto', Y nom 'tutu'") - self.assertEquals(self.execute('Any X WHERE X nom "toto"').rows, [[peid1]]) - self.assertEquals(self.execute('Any X WHERE X nom "tutu"').rows, [[peid2]]) + self.assertEqual(self.execute('Any X WHERE X nom "toto"').rows, [[peid1]]) + self.assertEqual(self.execute('Any X WHERE X nom "tutu"').rows, [[peid2]]) def test_update_multiple2(self): ueid = self.execute("INSERT CWUser X: X login 'bob', X upassword 'toto'")[0][0] @@ -1162,13 +1169,13 @@ {'order': orders[splitidx]}) orders2 = [r[0] for r in self.execute('Any O ORDERBY O WHERE ST name "Personne", X from_entity ST, X ordernum O')] orders = orders[:splitidx] + [o+1 for o in orders[splitidx:]] - self.assertEquals(orders2, orders) + self.assertEqual(orders2, orders) def test_update_string_concat(self): beid = self.execute("INSERT Bookmark Y: Y title 'toto', Y path '/view'")[0][0] self.execute('SET X title XN + %(suffix)s WHERE X is Bookmark, X title XN', {'suffix': u'-moved'}) newname = self.execute('Any XN WHERE X eid %(x)s, X title XN', {'x': beid})[0][0] - self.assertEquals(newname, 'toto-moved') + self.assertEqual(newname, 'toto-moved') def test_update_query_error(self): self.execute("INSERT Personne Y: Y nom 'toto'") @@ -1176,39 +1183,38 @@ self.assertRaises(QueryError, self.execute, "SET X nom 'toto', X has_text 'tutu' WHERE X is Personne") self.assertRaises(QueryError, self.execute, "SET X login 'tutu', X eid %s" % cnx.user(self.session).eid) - # upassword encryption tests ################################################# def test_insert_upassword(self): rset = self.execute("INSERT CWUser X: X login 'bob', X upassword 'toto'") - self.assertEquals(len(rset.rows), 1) - self.assertEquals(rset.description, [('CWUser',)]) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(rset.description, [('CWUser',)]) self.assertRaises(Unauthorized, self.execute, "Any P WHERE X is CWUser, X login 'bob', X upassword P") cursor = self.pool['system'] cursor.execute("SELECT %supassword from %sCWUser WHERE %slogin='bob'" % (SQL_PREFIX, SQL_PREFIX, SQL_PREFIX)) passwd = str(cursor.fetchone()[0]) - self.assertEquals(passwd, crypt_password('toto', passwd[:2])) + self.assertEqual(passwd, crypt_password('toto', passwd[:2])) rset = self.execute("Any X WHERE X is CWUser, X login 'bob', X upassword %(pwd)s", {'pwd': Binary(passwd)}) - self.assertEquals(len(rset.rows), 1) - self.assertEquals(rset.description, [('CWUser',)]) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(rset.description, [('CWUser',)]) def test_update_upassword(self): cursor = self.pool['system'] rset = self.execute("INSERT CWUser X: X login 'bob', X upassword %(pwd)s", {'pwd': 'toto'}) - self.assertEquals(rset.description[0][0], 'CWUser') + self.assertEqual(rset.description[0][0], 'CWUser') rset = self.execute("SET X upassword %(pwd)s WHERE X is CWUser, X login 'bob'", {'pwd': 'tutu'}) cursor.execute("SELECT %supassword from %sCWUser WHERE %slogin='bob'" % (SQL_PREFIX, SQL_PREFIX, SQL_PREFIX)) passwd = str(cursor.fetchone()[0]) - self.assertEquals(passwd, crypt_password('tutu', passwd[:2])) + self.assertEqual(passwd, crypt_password('tutu', passwd[:2])) rset = self.execute("Any X WHERE X is CWUser, X login 'bob', X upassword %(pwd)s", {'pwd': Binary(passwd)}) - self.assertEquals(len(rset.rows), 1) - self.assertEquals(rset.description, [('CWUser',)]) + self.assertEqual(len(rset.rows), 1) + self.assertEqual(rset.description, [('CWUser',)]) # non regression tests #################################################### @@ -1216,11 +1222,11 @@ teid = self.execute("INSERT Tag X: X name 'tag'")[0][0] self.execute("SET X tags Y WHERE X name 'tag', Y is State, Y name 'activated'") rset = self.execute('Any X WHERE T tags X') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) rset = self.execute('Any T WHERE T tags X, X is State') - self.assertEquals(rset.rows, [[teid]]) + self.assertEqual(rset.rows, [[teid]]) rset = self.execute('Any T WHERE T tags X') - self.assertEquals(rset.rows, [[teid]]) + self.assertEqual(rset.rows, [[teid]]) def test_nonregr_2(self): teid = self.execute("INSERT Tag X: X name 'tag'")[0][0] @@ -1229,7 +1235,7 @@ {'g': geid, 't': teid}) rset = self.execute('Any X WHERE E eid %(x)s, E tags X', {'x': teid}) - self.assertEquals(rset.rows, [[geid]]) + self.assertEqual(rset.rows, [[geid]]) def test_nonregr_3(self): """bad sql generated on the second query (destination_state is not @@ -1237,7 +1243,7 @@ """ rset = self.execute('Any S,ES,T WHERE S state_of WF, WF workflow_of ET, ET name "CWUser",' 'ES allowed_transition T, T destination_state S') - self.assertEquals(len(rset.rows), 2) + self.assertEqual(len(rset.rows), 2) def test_nonregr_4(self): # fix variables'type, else we get (nb of entity types with a 'name' attribute)**3 @@ -1245,7 +1251,7 @@ # by the server (or client lib) rset = self.execute('Any ER,SE,OE WHERE SE name "Comment", ER name "comments", OE name "Comment",' 'ER is CWRType, SE is CWEType, OE is CWEType') - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) def test_nonregr_5(self): # jpl #15505: equivalent queries returning different result sets @@ -1265,9 +1271,9 @@ rset4 = self.execute('Any N,U WHERE N todo_by U, T eid %s,' 'N filed_under T, W concerne N,' 'W filed_under A, A eid %s' % (teid1, teid2)) - self.assertEquals(rset1.rows, rset2.rows) - self.assertEquals(rset1.rows, rset3.rows) - self.assertEquals(rset1.rows, rset4.rows) + self.assertEqual(rset1.rows, rset2.rows) + self.assertEqual(rset1.rows, rset3.rows) + self.assertEqual(rset1.rows, rset4.rows) def test_nonregr_6(self): self.execute('Any N,COUNT(S) GROUPBY N ORDERBY COUNT(N) WHERE S name N, S is State') @@ -1285,7 +1291,7 @@ rset = self.execute('Any lower(N) ORDERBY LOWER(N) WHERE X is Tag, X name N,' 'X owned_by U, U eid %(x)s', {'x':self.session.user.eid}) - self.assertEquals(rset.rows, [[u'\xe9name0']]) + self.assertEqual(rset.rows, [[u'\xe9name0']]) def test_nonregr_description(self): @@ -1299,8 +1305,8 @@ self.execute("SET X in_basket B WHERE X is Personne") self.execute("SET X in_basket B WHERE X is Societe") rset = self.execute('Any X WHERE X in_basket B, B eid %s' % beid) - self.assertEquals(len(rset), 2) - self.assertEquals(rset.description, [('Personne',), ('Societe',)]) + self.assertEqual(len(rset), 2) + self.assertEqual(rset.description, [('Personne',), ('Societe',)]) def test_nonregr_cache_1(self): @@ -1310,19 +1316,19 @@ {'y': beid}) rset = self.execute("Any X WHERE X in_basket B, B eid %(x)s", {'x': beid}) - self.assertEquals(rset.rows, [[peid]]) + self.assertEqual(rset.rows, [[peid]]) rset = self.execute("Any X WHERE X in_basket B, B eid %(x)s", {'x': beid}) - self.assertEquals(rset.rows, [[peid]]) + self.assertEqual(rset.rows, [[peid]]) def test_nonregr_has_text_cache(self): eid1 = self.execute("INSERT Personne X: X nom 'bidule'")[0][0] eid2 = self.execute("INSERT Personne X: X nom 'tag'")[0][0] self.commit() rset = self.execute("Any X WHERE X has_text %(text)s", {'text': 'bidule'}) - self.assertEquals(rset.rows, [[eid1]]) + self.assertEqual(rset.rows, [[eid1]]) rset = self.execute("Any X WHERE X has_text %(text)s", {'text': 'tag'}) - self.assertEquals(rset.rows, [[eid2]]) + self.assertEqual(rset.rows, [[eid2]]) def test_nonregr_sortterm_management(self): """Error: Variable has no attribute 'sql' in rql2sql.py (visit_variable) @@ -1347,16 +1353,16 @@ self.execute("SET X todo_by Y WHERE X is Note, Y eid %s" % ueid) rset = self.execute('Any N WHERE N todo_by U, N is Note, U eid %s, N filed_under T, T eid %s' % (ueid, teid1)) - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) def test_nonregr_XXX(self): teid = self.execute('Transition S WHERE S name "deactivate"')[0][0] rset = self.execute('Any O WHERE O is State, ' 'S eid %(x)s, S transition_of ET, O state_of ET', {'x': teid}) - self.assertEquals(len(rset), 2) + self.assertEqual(len(rset), 2) rset = self.execute('Any O WHERE O is State, NOT S destination_state O, ' 'S eid %(x)s, S transition_of ET, O state_of ET', {'x': teid}) - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) def test_nonregr_set_datetime(self): @@ -1373,9 +1379,9 @@ ueid = self.execute("INSERT CWUser X: X login 'bob', X upassword 'toto', X in_group G " "WHERE G name 'users'")[0][0] rset = self.execute("CWUser U") - self.assertEquals(len(rset), 3) # bob + admin + anon + self.assertEqual(len(rset), 3) # bob + admin + anon rset = self.execute("Any U WHERE NOT U owned_by U") - self.assertEquals(len(rset), 0) # even admin created at repo initialization time should belong to itself + self.assertEqual(len(rset), 0) # even admin created at repo initialization time should belong to itself def test_nonreg_update_index(self): # this is the kind of queries generated by "cubicweb-ctl db-check -ry" @@ -1390,11 +1396,11 @@ self.execute('Any X,S, MAX(T) GROUPBY X,S ORDERBY S WHERE X is CWUser, T tags X, S eid IN(%s), X in_state S' % seid) def test_nonregr_solution_cache(self): - self.skip('XXX should be fixed or documented') # (doesn't occur if cache key is provided.) + self.skipTest('XXX should be fixed or documented') # (doesn't occur if cache key is provided.) rset = self.execute('Any X WHERE X is CWUser, X eid %(x)s', {'x':self.ueid}) - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) rset = self.execute('Any X WHERE X is CWUser, X eid %(x)s', {'x':12345}) - self.assertEquals(len(rset), 0) + self.assertEqual(len(rset), 0) def test_nonregr_final_norestr(self): self.assertRaises(BadRQLQuery, self.execute, 'Date X') diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_repository.py --- a/server/test/unittest_repository.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_repository.py Wed Sep 29 16:16:32 2010 +0200 @@ -32,7 +32,7 @@ from yams.constraints import UniqueConstraint from cubicweb import (BadConnectionId, RepositoryError, ValidationError, - UnknownEid, AuthenticationError) + UnknownEid, AuthenticationError, Unauthorized) from cubicweb.selectors import is_instance from cubicweb.schema import CubicWebSchema, RQLConstraint from cubicweb.dbapi import connect, multiple_connections_unfix @@ -65,10 +65,10 @@ self.session.set_pool() cu = self.session.system_sql('SELECT %s FROM %s WHERE %s is NULL' % ( namecol, table, finalcol)) - self.assertEquals(cu.fetchall(), []) + self.assertEqual(cu.fetchall(), []) cu = self.session.system_sql('SELECT %s FROM %s WHERE %s=%%(final)s ORDER BY %s' % (namecol, table, finalcol, namecol), {'final': 'TRUE'}) - self.assertEquals(cu.fetchall(), [(u'Boolean',), (u'Bytes',), + self.assertEqual(cu.fetchall(), [(u'Boolean',), (u'Bytes',), (u'Date',), (u'Datetime',), (u'Decimal',),(u'Float',), (u'Int',), @@ -84,15 +84,15 @@ ";") cu = self.session.system_sql(sql) rows = cu.fetchall() - self.assertEquals(len(rows), 3) + self.assertEqual(len(rows), 3) self.test_unique_together() finally: self.repo.set_schema(origshema) def test_unique_together(self): person = self.repo.schema.eschema('Personne') - self.assertEquals(len(person._unique_together), 1) - self.assertUnorderedIterableEquals(person._unique_together[0], + self.assertEqual(len(person._unique_together), 1) + self.assertItemsEqual(person._unique_together[0], ('nom', 'prenom', 'inline2')) def test_schema_has_owner(self): @@ -136,15 +136,39 @@ repo.close(cnxid) self.assert_(repo.connect(u"barnabé", password=u"héhéhé".encode('UTF8'))) - def test_invalid_entity_rollback(self): + def test_rollback_on_commit_error(self): cnxid = self.repo.connect(self.admlogin, password=self.admpassword) - # no group self.repo.execute(cnxid, 'INSERT CWUser X: X login %(login)s, X upassword %(passwd)s', {'login': u"tutetute", 'passwd': 'tutetute'}) self.assertRaises(ValidationError, self.repo.commit, cnxid) self.failIf(self.repo.execute(cnxid, 'CWUser X WHERE X login "tutetute"')) + def test_rollback_on_execute_validation_error(self): + class ValidationErrorAfterHook(Hook): + __regid__ = 'valerror-after-hook' + __select__ = Hook.__select__ & is_instance('CWGroup') + events = ('after_update_entity',) + def __call__(self): + raise ValidationError(self.entity.eid, {}) + with self.temporary_appobjects(ValidationErrorAfterHook): + self.assertRaises(ValidationError, + self.execute, 'SET X name "toto" WHERE X is CWGroup, X name "guests"') + self.failIf(self.execute('Any X WHERE X is CWGroup, X name "toto"')) + + def test_rollback_on_execute_unauthorized(self): + class UnauthorizedAfterHook(Hook): + __regid__ = 'unauthorized-after-hook' + __select__ = Hook.__select__ & is_instance('CWGroup') + events = ('after_update_entity',) + def __call__(self): + raise Unauthorized() + with self.temporary_appobjects(UnauthorizedAfterHook): + self.assertRaises(Unauthorized, + self.execute, 'SET X name "toto" WHERE X is CWGroup, X name "guests"') + self.failIf(self.execute('Any X WHERE X is CWGroup, X name "toto"')) + + def test_close(self): repo = self.repo cnxid = repo.connect(self.admlogin, password=self.admpassword) @@ -161,14 +185,14 @@ cnxid = repo.connect(self.admlogin, password=self.admpassword) repo.set_shared_data(cnxid, 'data', 4) cnxid2 = repo.connect(self.admlogin, password=self.admpassword) - self.assertEquals(repo.get_shared_data(cnxid, 'data'), 4) - self.assertEquals(repo.get_shared_data(cnxid2, 'data'), None) + self.assertEqual(repo.get_shared_data(cnxid, 'data'), 4) + self.assertEqual(repo.get_shared_data(cnxid2, 'data'), None) repo.set_shared_data(cnxid2, 'data', 5) - self.assertEquals(repo.get_shared_data(cnxid, 'data'), 4) - self.assertEquals(repo.get_shared_data(cnxid2, 'data'), 5) + self.assertEqual(repo.get_shared_data(cnxid, 'data'), 4) + self.assertEqual(repo.get_shared_data(cnxid2, 'data'), 5) repo.get_shared_data(cnxid2, 'data', pop=True) - self.assertEquals(repo.get_shared_data(cnxid, 'data'), 4) - self.assertEquals(repo.get_shared_data(cnxid2, 'data'), None) + self.assertEqual(repo.get_shared_data(cnxid, 'data'), 4) + self.assertEqual(repo.get_shared_data(cnxid2, 'data'), None) repo.close(cnxid) repo.close(cnxid2) self.assertRaises(BadConnectionId, repo.get_shared_data, cnxid, 'data') @@ -188,19 +212,19 @@ cnxid = repo.connect(self.admlogin, password=self.admpassword) # check db state result = repo.execute(cnxid, 'Personne X') - self.assertEquals(result.rowcount, 0) + self.assertEqual(result.rowcount, 0) # rollback entity insertion repo.execute(cnxid, "INSERT Personne X: X nom 'bidule'") result = repo.execute(cnxid, 'Personne X') - self.assertEquals(result.rowcount, 1) + self.assertEqual(result.rowcount, 1) repo.rollback(cnxid) result = repo.execute(cnxid, 'Personne X') - self.assertEquals(result.rowcount, 0, result.rows) + self.assertEqual(result.rowcount, 0, result.rows) # commit repo.execute(cnxid, "INSERT Personne X: X nom 'bidule'") repo.commit(cnxid) result = repo.execute(cnxid, 'Personne X') - self.assertEquals(result.rowcount, 1) + self.assertEqual(result.rowcount, 1) def test_transaction_base2(self): repo = self.repo @@ -208,10 +232,10 @@ # rollback relation insertion repo.execute(cnxid, "SET U in_group G WHERE U login 'admin', G name 'guests'") result = repo.execute(cnxid, "Any U WHERE U in_group G, U login 'admin', G name 'guests'") - self.assertEquals(result.rowcount, 1) + self.assertEqual(result.rowcount, 1) repo.rollback(cnxid) result = repo.execute(cnxid, "Any U WHERE U in_group G, U login 'admin', G name 'guests'") - self.assertEquals(result.rowcount, 0, result.rows) + self.assertEqual(result.rowcount, 0, result.rows) def test_transaction_base3(self): repo = self.repo @@ -222,13 +246,13 @@ user = session.user user.cw_adapt_to('IWorkflowable').fire_transition('deactivate') rset = repo.execute(cnxid, 'TrInfo T WHERE T wf_info_for X, X eid %(x)s', {'x': user.eid}) - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) repo.rollback(cnxid) rset = repo.execute(cnxid, 'TrInfo T WHERE T wf_info_for X, X eid %(x)s', {'x': user.eid}) - self.assertEquals(len(rset), 0) + self.assertEqual(len(rset), 0) def test_transaction_interleaved(self): - self.skip('implement me') + self.skipTest('implement me') def test_close_kill_processing_request(self): repo = self.repo @@ -246,14 +270,14 @@ repo.commit(cnxid) try: ex = self.assertRaises(Exception, run_transaction) - self.assertEquals(str(ex), 'try to access pool on a closed session') + self.assertEqual(str(ex), 'try to access pool on a closed session') finally: t.join() def test_initial_schema(self): schema = self.repo.schema # check order of attributes is respected - self.assertListEquals([r.type for r in schema.eschema('CWAttribute').ordered_relations() + self.assertListEqual([r.type for r in schema.eschema('CWAttribute').ordered_relations() if not r.type in ('eid', 'is', 'is_instance_of', 'identity', 'creation_date', 'modification_date', 'cwuri', 'owned_by', 'created_by', @@ -266,11 +290,11 @@ 'indexed', 'fulltextindexed', 'internationalizable', 'defaultval', 'description', 'description_format']) - self.assertEquals(schema.eschema('CWEType').main_attribute(), 'name') - self.assertEquals(schema.eschema('State').main_attribute(), 'name') + self.assertEqual(schema.eschema('CWEType').main_attribute(), 'name') + self.assertEqual(schema.eschema('State').main_attribute(), 'name') constraints = schema.rschema('name').rdef('CWEType', 'String').constraints - self.assertEquals(len(constraints), 2) + self.assertEqual(len(constraints), 2) for cstr in constraints[:]: if isinstance(cstr, UniqueConstraint): constraints.remove(cstr) @@ -278,17 +302,17 @@ else: self.fail('unique constraint not found') sizeconstraint = constraints[0] - self.assertEquals(sizeconstraint.min, None) - self.assertEquals(sizeconstraint.max, 64) + self.assertEqual(sizeconstraint.min, None) + self.assertEqual(sizeconstraint.max, 64) constraints = schema.rschema('relation_type').rdef('CWAttribute', 'CWRType').constraints - self.assertEquals(len(constraints), 1) + self.assertEqual(len(constraints), 1) cstr = constraints[0] self.assert_(isinstance(cstr, RQLConstraint)) - self.assertEquals(cstr.restriction, 'O final TRUE') + self.assertEqual(cstr.restriction, 'O final TRUE') ownedby = schema.rschema('owned_by') - self.assertEquals(ownedby.objects('CWEType'), ('CWUser',)) + self.assertEqual(ownedby.objects('CWEType'), ('CWUser',)) def test_pyro(self): import Pyro @@ -319,7 +343,7 @@ schema = cnx.get_schema() self.failUnless(cnx.vreg) self.failUnless('etypes'in cnx.vreg) - self.assertEquals(schema.__hashmode__, None) + self.assertEqual(schema.__hashmode__, None) cu = cnx.cursor() rset = cu.execute('Any U,G WHERE U in_group G') user = iter(rset.entities()).next() @@ -337,25 +361,25 @@ repo = self.repo cnxid = repo.connect(self.admlogin, password=self.admpassword) session = repo._get_session(cnxid, setpool=True) - self.assertEquals(repo.type_and_source_from_eid(1, session), + self.assertEqual(repo.type_and_source_from_eid(1, session), ('CWGroup', 'system', None)) - self.assertEquals(repo.type_from_eid(1, session), 'CWGroup') - self.assertEquals(repo.source_from_eid(1, session).uri, 'system') - self.assertEquals(repo.eid2extid(repo.system_source, 1, session), None) + self.assertEqual(repo.type_from_eid(1, session), 'CWGroup') + self.assertEqual(repo.source_from_eid(1, session).uri, 'system') + self.assertEqual(repo.eid2extid(repo.system_source, 1, session), None) class dummysource: uri = 'toto' self.assertRaises(UnknownEid, repo.eid2extid, dummysource, 1, session) def test_public_api(self): - self.assertEquals(self.repo.get_schema(), self.repo.schema) - self.assertEquals(self.repo.source_defs(), {'system': {'adapter': 'native', 'uri': 'system'}}) + self.assertEqual(self.repo.get_schema(), self.repo.schema) + self.assertEqual(self.repo.source_defs(), {'system': {'adapter': 'native', 'uri': 'system'}}) # .properties() return a result set - self.assertEquals(self.repo.properties().rql, 'Any K,V WHERE P is CWProperty,P pkey K, P value V, NOT P for_user U') + self.assertEqual(self.repo.properties().rql, 'Any K,V WHERE P is CWProperty,P pkey K, P value V, NOT P for_user U') def test_session_api(self): repo = self.repo cnxid = repo.connect(self.admlogin, password=self.admpassword) - self.assertEquals(repo.user_info(cnxid), (5, 'admin', set([u'managers']), {})) - self.assertEquals(repo.describe(cnxid, 1), (u'CWGroup', u'system', None)) + self.assertEqual(repo.user_info(cnxid), (5, 'admin', set([u'managers']), {})) + self.assertEqual(repo.describe(cnxid, 1), (u'CWGroup', u'system', None)) repo.close(cnxid) self.assertRaises(BadConnectionId, repo.user_info, cnxid) self.assertRaises(BadConnectionId, repo.describe, cnxid, 1) @@ -363,12 +387,12 @@ def test_shared_data_api(self): repo = self.repo cnxid = repo.connect(self.admlogin, password=self.admpassword) - self.assertEquals(repo.get_shared_data(cnxid, 'data'), None) + self.assertEqual(repo.get_shared_data(cnxid, 'data'), None) repo.set_shared_data(cnxid, 'data', 4) - self.assertEquals(repo.get_shared_data(cnxid, 'data'), 4) + self.assertEqual(repo.get_shared_data(cnxid, 'data'), 4) repo.get_shared_data(cnxid, 'data', pop=True) repo.get_shared_data(cnxid, 'whatever', pop=True) - self.assertEquals(repo.get_shared_data(cnxid, 'data'), None) + self.assertEqual(repo.get_shared_data(cnxid, 'data'), None) repo.close(cnxid) self.assertRaises(BadConnectionId, repo.set_shared_data, cnxid, 'data', 0) self.assertRaises(BadConnectionId, repo.get_shared_data, cnxid, 'data') @@ -394,14 +418,14 @@ {'x': note.eid, 'p': p1.eid}) rset = self.execute('Any P WHERE A todo_by P, A eid %(x)s', {'x': note.eid}) - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) p2 = self.request().create_entity('Personne', nom=u'tutu') self.execute('SET A todo_by P WHERE A eid %(x)s, P eid %(p)s', {'x': note.eid, 'p': p2.eid}) rset = self.execute('Any P WHERE A todo_by P, A eid %(x)s', {'x': note.eid}) - self.assertEquals(len(rset), 1) - self.assertEquals(rset.rows[0][0], p2.eid) + self.assertEqual(len(rset), 1) + self.assertEqual(rset.rows[0][0], p2.eid) def test_delete_if_object_inlined_singlecard(self): req = self.request() @@ -409,7 +433,7 @@ req.create_entity('Personne', nom=u'Vincent', fiche=c) req.create_entity('Personne', nom=u'Florent', fiche=c) self.commit() - self.assertEquals(len(c.reverse_fiche), 1) + self.assertEqual(len(c.reverse_fiche), 1) def test_set_attributes_in_before_update(self): # local hook @@ -430,7 +454,7 @@ addr.set_attributes(address=u'a@b.com') rset = self.execute('Any A,AA WHERE X eid %(x)s, X address A, X alias AA', {'x': addr.eid}) - self.assertEquals(rset.rows, [[u'a@b.com', u'foo']]) + self.assertEqual(rset.rows, [[u'a@b.com', u'foo']]) def test_set_attributes_in_before_add(self): # local hook @@ -477,7 +501,7 @@ def test_source_from_eid(self): self.session.set_pool() - self.assertEquals(self.repo.source_from_eid(1, self.session), + self.assertEqual(self.repo.source_from_eid(1, self.session), self.repo.sources_by_uri['system']) def test_source_from_eid_raise(self): @@ -486,7 +510,7 @@ def test_type_from_eid(self): self.session.set_pool() - self.assertEquals(self.repo.type_from_eid(1, self.session), 'CWGroup') + self.assertEqual(self.repo.type_from_eid(1, self.session), 'CWGroup') def test_type_from_eid_raise(self): self.session.set_pool() @@ -503,12 +527,12 @@ self.assertIsInstance(data[0][3], datetime) data[0] = list(data[0]) data[0][3] = None - self.assertEquals(tuplify(data), [(-1, 'Personne', 'system', None, None)]) + self.assertEqual(tuplify(data), [(-1, 'Personne', 'system', None, None)]) self.repo.delete_info(self.session, entity, 'system', None) #self.repo.commit() cu = self.session.system_sql('SELECT * FROM entities WHERE eid = -1') data = cu.fetchall() - self.assertEquals(data, []) + self.assertEqual(data, []) class FTITC(CubicWebTC): @@ -518,7 +542,7 @@ eidp = self.execute('INSERT Personne X: X nom "toto", X prenom "tutu"')[0][0] self.commit() ts = datetime.now() - self.assertEquals(len(self.execute('Personne X WHERE X has_text "tutu"')), 1) + self.assertEqual(len(self.execute('Personne X WHERE X has_text "tutu"')), 1) self.session.set_pool() cu = self.session.system_sql('SELECT mtime, eid FROM entities WHERE eid = %s' % eidp) omtime = cu.fetchone()[0] @@ -527,23 +551,23 @@ time.sleep(1 - (ts.second - int(ts.second))) self.execute('SET X nom "tata" WHERE X eid %(x)s', {'x': eidp}) self.commit() - self.assertEquals(len(self.execute('Personne X WHERE X has_text "tutu"')), 1) + self.assertEqual(len(self.execute('Personne X WHERE X has_text "tutu"')), 1) self.session.set_pool() cu = self.session.system_sql('SELECT mtime FROM entities WHERE eid = %s' % eidp) mtime = cu.fetchone()[0] self.failUnless(omtime < mtime) self.commit() date, modified, deleted = self.repo.entities_modified_since(('Personne',), omtime) - self.assertEquals(modified, [('Personne', eidp)]) - self.assertEquals(deleted, []) + self.assertEqual(modified, [('Personne', eidp)]) + self.assertEqual(deleted, []) date, modified, deleted = self.repo.entities_modified_since(('Personne',), mtime) - self.assertEquals(modified, []) - self.assertEquals(deleted, []) + self.assertEqual(modified, []) + self.assertEqual(deleted, []) self.execute('DELETE Personne X WHERE X eid %(x)s', {'x': eidp}) self.commit() date, modified, deleted = self.repo.entities_modified_since(('Personne',), omtime) - self.assertEquals(modified, []) - self.assertEquals(deleted, [('Personne', eidp)]) + self.assertEqual(modified, []) + self.assertEqual(deleted, [('Personne', eidp)]) def test_fulltext_container_entity(self): assert self.schema.rschema('use_email').fulltext_container == 'subject' @@ -551,27 +575,27 @@ toto = req.create_entity('EmailAddress', address=u'toto@logilab.fr') self.commit() rset = req.execute('Any X WHERE X has_text %(t)s', {'t': 'toto'}) - self.assertEquals(rset.rows, []) + self.assertEqual(rset.rows, []) req.user.set_relations(use_email=toto) self.commit() rset = req.execute('Any X WHERE X has_text %(t)s', {'t': 'toto'}) - self.assertEquals(rset.rows, [[req.user.eid]]) + self.assertEqual(rset.rows, [[req.user.eid]]) req.execute('DELETE X use_email Y WHERE X login "admin", Y eid %(y)s', {'y': toto.eid}) self.commit() rset = req.execute('Any X WHERE X has_text %(t)s', {'t': 'toto'}) - self.assertEquals(rset.rows, []) + self.assertEqual(rset.rows, []) tutu = req.create_entity('EmailAddress', address=u'tutu@logilab.fr') req.user.set_relations(use_email=tutu) self.commit() rset = req.execute('Any X WHERE X has_text %(t)s', {'t': 'tutu'}) - self.assertEquals(rset.rows, [[req.user.eid]]) + self.assertEqual(rset.rows, [[req.user.eid]]) tutu.set_attributes(address=u'hip@logilab.fr') self.commit() rset = req.execute('Any X WHERE X has_text %(t)s', {'t': 'tutu'}) - self.assertEquals(rset.rows, []) + self.assertEqual(rset.rows, []) rset = req.execute('Any X WHERE X has_text %(t)s', {'t': 'hip'}) - self.assertEquals(rset.rows, [[req.user.eid]]) + self.assertEqual(rset.rows, [[req.user.eid]]) def test_no_uncessary_ftiindex_op(self): req = self.request() @@ -584,7 +608,7 @@ def test_versions_inserted(self): inserted = [r[0] for r in self.execute('Any K ORDERBY K WHERE P pkey K, P pkey ~= "system.version.%"')] - self.assertEquals(inserted, + self.assertEqual(inserted, [u'system.version.basket', u'system.version.card', u'system.version.comment', u'system.version.cubicweb', u'system.version.email', u'system.version.file', u'system.version.folder', @@ -616,15 +640,15 @@ eidp = self.execute('INSERT Personne X: X nom "toto"')[0][0] eidn = self.execute('INSERT Note X: X type "T"')[0][0] self.execute('SET N ecrit_par Y WHERE N type "T", Y nom "toto"') - self.assertEquals(CALLED, [('before_add_relation', eidn, 'ecrit_par', eidp), + self.assertEqual(CALLED, [('before_add_relation', eidn, 'ecrit_par', eidp), ('after_add_relation', eidn, 'ecrit_par', eidp)]) CALLED[:] = () self.execute('DELETE N ecrit_par Y WHERE N type "T", Y nom "toto"') - self.assertEquals(CALLED, [('before_delete_relation', eidn, 'ecrit_par', eidp), + self.assertEqual(CALLED, [('before_delete_relation', eidn, 'ecrit_par', eidp), ('after_delete_relation', eidn, 'ecrit_par', eidp)]) CALLED[:] = () eidn = self.execute('INSERT Note N: N ecrit_par P WHERE P nom "toto"')[0][0] - self.assertEquals(CALLED, [('before_add_relation', eidn, 'ecrit_par', eidp), + self.assertEqual(CALLED, [('before_add_relation', eidn, 'ecrit_par', eidp), ('after_add_relation', eidn, 'ecrit_par', eidp)]) def test_unique_contraint(self): @@ -638,7 +662,7 @@ req = self.request() req.create_entity('Note', type=u'todo', inline1=a01) ex = self.assertRaises(ValidationError, req.cnx.commit) - self.assertEquals(ex.errors, {'inline1-subject': u'RQLUniqueConstraint S type T, S inline1 A1, A1 todo_by C, Y type T, Y inline1 A2, A2 todo_by C failed'}) + self.assertEqual(ex.errors, {'inline1-subject': u'RQLUniqueConstraint S type T, S inline1 A1, A1 todo_by C, Y type T, Y inline1 A2, A2 todo_by C failed'}) if __name__ == '__main__': unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_rql2sql.py --- a/server/test/unittest_rql2sql.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_rql2sql.py Wed Sep 29 16:16:32 2010 +0200 @@ -1096,12 +1096,15 @@ for sol in delete.solutions: s.add(sol.get(var)) return s - self.assertEquals(var_sols('FROM_ENTITYOBJECT'), set(('CWAttribute', 'CWRelation'))) - self.assertEquals(var_sols('FROM_ENTITYOBJECT'), delete.defined_vars['FROM_ENTITYOBJECT'].stinfo['possibletypes']) - self.assertEquals(var_sols('ISOBJECT'), + self.assertEqual(var_sols('FROM_ENTITYOBJECT'), set(('CWAttribute', 'CWRelation'))) + self.assertEqual(var_sols('FROM_ENTITYOBJECT'), delete.defined_vars['FROM_ENTITYOBJECT'].stinfo['possibletypes']) + self.assertEqual(var_sols('ISOBJECT'), set(x.type for x in self.schema.entities() if not x.final)) - self.assertEquals(var_sols('ISOBJECT'), delete.defined_vars['ISOBJECT'].stinfo['possibletypes']) + self.assertEqual(var_sols('ISOBJECT'), delete.defined_vars['ISOBJECT'].stinfo['possibletypes']) + +def strip(text): + return '\n'.join(l.strip() for l in text.strip().splitlines()) class PostgresSQLGeneratorTC(RQLGeneratorTC): schema = schema @@ -1118,7 +1121,7 @@ r, nargs, cbs = self.o.generate(union, args, varmap=varmap) args.update(nargs) - self.assertLinesEquals((r % args).strip(), self._norm_sql(sql), striplines=True) + self.assertMultiLineEqual(strip(r % args), self._norm_sql(sql)) except Exception, ex: if 'r' in locals(): try: @@ -1200,7 +1203,7 @@ def test_is_null_transform(self): union = self._prepare('Any X WHERE X login %(login)s') r, args, cbs = self.o.generate(union, {'login': None}) - self.assertLinesEquals((r % args).strip(), + self.assertMultiLineEqual((r % args).strip(), '''SELECT _X.cw_eid FROM cw_CWUser AS _X WHERE _X.cw_login IS NULL''') @@ -1454,8 +1457,8 @@ try: union = self._prepare('Any R WHERE X ref R') r, nargs, cbs = self.o.generate(union, args={}) - self.assertLinesEquals(r.strip(), 'SELECT _X.cw_ref\nFROM cw_Affaire AS _X') - self.assertEquals(cbs, {0: [cb]}) + self.assertMultiLineEqual(r.strip(), 'SELECT _X.cw_ref\nFROM cw_Affaire AS _X') + self.assertEqual(cbs, {0: [cb]}) finally: self.o.attr_map.clear() @@ -1712,7 +1715,7 @@ rqlst = mock_object(defined_vars={}) rqlst.defined_vars['A'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=True) rqlst.defined_vars['B'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=False) - self.assertEquals(remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'}, + self.assertEqual(remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'}, {'A': 'FootGroup', 'B': 'FootTeam'}], {}, None), ([{'A': 'RugbyGroup', 'B': 'RugbyTeam'}, {'A': 'FootGroup', 'B': 'FootTeam'}], @@ -1723,7 +1726,7 @@ rqlst = mock_object(defined_vars={}) rqlst.defined_vars['A'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=True) rqlst.defined_vars['B'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=False) - self.assertEquals(remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'}, + self.assertEqual(remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'}, {'A': 'FootGroup', 'B': 'RugbyTeam'}], {}, None), ([{'A': 'RugbyGroup', 'B': 'RugbyTeam'}], {}, set()) ) diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_rqlannotation.py --- a/server/test/unittest_rqlannotation.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_rqlannotation.py Wed Sep 29 16:16:32 2010 +0200 @@ -41,256 +41,256 @@ def test_0_1(self): rqlst = self._prepare('Any SEN,RN,OEN WHERE X from_entity SE, SE eid 44, X relation_type R, R eid 139, X to_entity OE, OE eid 42, R name RN, SE name SEN, OE name OEN') - self.assertEquals(rqlst.defined_vars['SE']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['OE']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['R']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['SE'].stinfo['attrvar'], None) - self.assertEquals(rqlst.defined_vars['OE'].stinfo['attrvar'], None) - self.assertEquals(rqlst.defined_vars['R'].stinfo['attrvar'], None) + self.assertEqual(rqlst.defined_vars['SE']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['OE']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['R']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['SE'].stinfo['attrvar'], None) + self.assertEqual(rqlst.defined_vars['OE'].stinfo['attrvar'], None) + self.assertEqual(rqlst.defined_vars['R'].stinfo['attrvar'], None) def test_0_2(self): rqlst = self._prepare('Any O WHERE NOT S ecrit_par O, S eid 1, S inline1 P, O inline2 P') - self.assertEquals(rqlst.defined_vars['P']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['O'].stinfo['attrvar'], None) + self.assertEqual(rqlst.defined_vars['P']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['O'].stinfo['attrvar'], None) def test_0_4(self): rqlst = self._prepare('Any A,B,C WHERE A eid 12,A comment B, A ?wf_info_for C') - self.assertEquals(rqlst.defined_vars['A']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['A']._q_invariant, False) self.assert_(rqlst.defined_vars['B'].stinfo['attrvar']) - self.assertEquals(rqlst.defined_vars['C']._q_invariant, False) - self.assertEquals(rqlst.solutions, [{'A': 'TrInfo', 'B': 'String', 'C': 'Affaire'}, + self.assertEqual(rqlst.defined_vars['C']._q_invariant, False) + self.assertEqual(rqlst.solutions, [{'A': 'TrInfo', 'B': 'String', 'C': 'Affaire'}, {'A': 'TrInfo', 'B': 'String', 'C': 'CWUser'}, {'A': 'TrInfo', 'B': 'String', 'C': 'Note'}]) def test_0_5(self): rqlst = self._prepare('Any P WHERE N ecrit_par P, N eid 0') - self.assertEquals(rqlst.defined_vars['N']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['P']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['N']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['P']._q_invariant, True) def test_0_6(self): rqlst = self._prepare('Any P WHERE NOT N ecrit_par P, N eid 512') - self.assertEquals(rqlst.defined_vars['P']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['P']._q_invariant, False) def test_0_7(self): rqlst = self._prepare('Personne X,Y where X nom NX, Y nom NX, X eid XE, not Y eid XE') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False) self.assert_(rqlst.defined_vars['XE'].stinfo['attrvar']) def test_0_8(self): rqlst = self._prepare('Any P WHERE X eid 0, NOT X connait P') - self.assertEquals(rqlst.defined_vars['P']._q_invariant, False) - #self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) - self.assertEquals(len(rqlst.solutions), 1, rqlst.solutions) + self.assertEqual(rqlst.defined_vars['P']._q_invariant, False) + #self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(len(rqlst.solutions), 1, rqlst.solutions) def test_0_10(self): rqlst = self._prepare('Any X WHERE X concerne Y, Y is Note') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False) def test_0_11(self): rqlst = self._prepare('Any X WHERE X todo_by Y, X is Affaire') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, True) def test_0_12(self): rqlst = self._prepare('Personne P WHERE P concerne A, A concerne S, S nom "Logilab"') - self.assertEquals(rqlst.defined_vars['P']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['A']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['S']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['P']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['A']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['S']._q_invariant, False) def test_1_0(self): rqlst = self._prepare('Any X,Y WHERE X created_by Y, X eid 5, NOT Y eid 6') - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, True) def test_1_1(self): rqlst = self._prepare('Any X,Y WHERE X created_by Y, X eid 5, NOT Y eid IN (6,7)') - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, True) def test_2(self): rqlst = self._prepare('Any X WHERE X identity Y, Y eid 1') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) def test_7(self): rqlst = self._prepare('Personne X,Y where X nom NX, Y nom NX, X eid XE, not Y eid XE') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False) def test_8(self): # DISTINCT Any P WHERE P require_group %(g)s, NOT %(u)s has_group_permission P, P is CWPermission rqlst = self._prepare('DISTINCT Any X WHERE A concerne X, NOT N migrated_from X, ' 'X is Note, N eid 1') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) def test_diff_scope_identity_deamb(self): rqlst = self._prepare('Any X WHERE X concerne Y, Y is Note, EXISTS(Y identity Z, Z migrated_from N)') - self.assertEquals(rqlst.defined_vars['Z']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['Z']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, True) def test_optional_inlined(self): rqlst = self._prepare('Any X,S where X from_state S?') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['S']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['S']._q_invariant, True) def test_optional_inlined_2(self): rqlst = self._prepare('Any N,A WHERE N? inline1 A') - self.assertEquals(rqlst.defined_vars['N']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['A']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['N']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['A']._q_invariant, False) def test_optional_1(self): rqlst = self._prepare('Any X,S WHERE X travaille S?') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['S']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['S']._q_invariant, True) def test_greater_eid(self): rqlst = self._prepare('Any X WHERE X eid > 5') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) def test_greater_eid_typed(self): rqlst = self._prepare('Any X WHERE X eid > 5, X is Note') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) def test_max_eid(self): rqlst = self._prepare('Any MAX(X)') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) def test_max_eid_typed(self): rqlst = self._prepare('Any MAX(X) WHERE X is Note') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) def test_all_entities(self): rqlst = self._prepare('Any X') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) def test_all_typed_entity(self): rqlst = self._prepare('Any X WHERE X is Note') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) def test_has_text_1(self): rqlst = self._prepare('Any X WHERE X has_text "toto tata"') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'has_text') + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'has_text') def test_has_text_2(self): rqlst = self._prepare('Any X WHERE X is Personne, X has_text "coucou"') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'has_text') + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'has_text') def test_not_relation_1(self): # P can't be invariant since deambiguification caused by "NOT X require_permission P" # is not considered by generated sql (NOT EXISTS(...)) rqlst = self._prepare('Any P,G WHERE P require_group G, NOT X require_permission P') - self.assertEquals(rqlst.defined_vars['P']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['G']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['P']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['G']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) def test_not_relation_2(self): rqlst = self._prepare('TrInfo X WHERE X eid 2, NOT X from_state Y, Y is State') - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) def test_not_relation_3(self): rqlst = self._prepare('Any X, Y WHERE X eid 1, Y eid in (2, 3)') - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False) def test_not_relation_4_1(self): rqlst = self._prepare('Note X WHERE NOT Y evaluee X') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, True) def test_not_relation_4_2(self): rqlst = self._prepare('Any X WHERE NOT Y evaluee X') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, True) def test_not_relation_4_3(self): rqlst = self._prepare('Any Y WHERE NOT Y evaluee X') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False) def test_not_relation_4_4(self): rqlst = self._prepare('Any X WHERE NOT Y evaluee X, Y is CWUser') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False) def test_not_relation_4_5(self): rqlst = self._prepare('Any X WHERE NOT Y evaluee X, Y eid %s, X is Note' % self.ueid) - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.solutions, [{'X': 'Note'}]) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.solutions, [{'X': 'Note'}]) def test_not_relation_5_1(self): rqlst = self._prepare('Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), NOT X read_permission Y') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False) def test_not_relation_5_2(self): rqlst = self._prepare('DISTINCT Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), NOT X read_permission Y') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False) def test_not_relation_6(self): rqlst = self._prepare('Personne P where NOT P concerne A') - self.assertEquals(rqlst.defined_vars['P']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['A']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['P']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['A']._q_invariant, True) def test_not_relation_7(self): rqlst = self._prepare('Any K,V WHERE P is CWProperty, P pkey K, P value V, NOT P for_user U') - self.assertEquals(rqlst.defined_vars['P']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['U']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['P']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['U']._q_invariant, True) def test_exists_1(self): rqlst = self._prepare('Any U WHERE U eid IN (1,2), EXISTS(X owned_by U)') - self.assertEquals(rqlst.defined_vars['U']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['U']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) def test_exists_2(self): rqlst = self._prepare('Any U WHERE EXISTS(U eid IN (1,2), X owned_by U)') - self.assertEquals(rqlst.defined_vars['U']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['U']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) def test_exists_3(self): rqlst = self._prepare('Any U WHERE EXISTS(X owned_by U, X bookmarked_by U)') - self.assertEquals(rqlst.defined_vars['U']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['U']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) def test_exists_4(self): rqlst = self._prepare('Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), EXISTS(X read_permission Y)') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False) def test_exists_5(self): rqlst = self._prepare('DISTINCT Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), EXISTS(X read_permission Y)') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, True) def test_not_exists_1(self): rqlst = self._prepare('Any U WHERE NOT EXISTS(X owned_by U, X bookmarked_by U)') - self.assertEquals(rqlst.defined_vars['U']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['U']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) def test_not_exists_2(self): rqlst = self._prepare('Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), NOT EXISTS(X read_permission Y)') - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False) def test_not_exists_distinct_1(self): rqlst = self._prepare('DISTINCT Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), NOT EXISTS(X read_permission Y)') - self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False) def test_or_1(self): rqlst = self._prepare('Any X WHERE X concerne B OR C concerne X, B eid 12, C eid 13') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, False) def test_or_2(self): rqlst = self._prepare('Any X WHERE X created_by U, X concerne B OR C concerne X, B eid 12, C eid 13') - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['U']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'created_by') + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['U']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'created_by') def test_or_3(self): rqlst = self._prepare('Any N WHERE A evaluee N or EXISTS(N todo_by U)') - self.assertEquals(rqlst.defined_vars['N']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['A']._q_invariant, True) - self.assertEquals(rqlst.defined_vars['U']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['N']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['A']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['U']._q_invariant, True) def test_or_exists_1(self): # query generated by security rewriting @@ -300,30 +300,30 @@ 'OR (EXISTS(I concerne H?, H owned_by D, H is Societe, A identity I, I is Affaire))) ' 'OR (EXISTS(J concerne G?, G owned_by D, G is SubDivision, A identity J, J is Affaire))) ' 'OR (EXISTS(K concerne F?, F owned_by D, F is Division, A identity K, K is Affaire)))') - self.assertEquals(rqlst.defined_vars['A']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['S']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['A']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['S']._q_invariant, False) def test_or_exists_2(self): rqlst = self._prepare('Any U WHERE EXISTS(U in_group G, G name "managers") OR EXISTS(X owned_by U, X bookmarked_by U)') - self.assertEquals(rqlst.defined_vars['U']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['G']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['X']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['U']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['G']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['X']._q_invariant, True) def test_or_exists_3(self): rqlst = self._prepare('Any COUNT(S),CS GROUPBY CS ORDERBY 1 DESC LIMIT 10 ' 'WHERE C is Societe, S concerne C, C nom CS, ' '(EXISTS(S owned_by D)) OR (EXISTS(S documented_by N, N title "published"))') - self.assertEquals(rqlst.defined_vars['S']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['S']._q_invariant, True) rqlst = self._prepare('Any COUNT(S),CS GROUPBY CS ORDERBY 1 DESC LIMIT 10 ' 'WHERE S is Affaire, C is Societe, S concerne C, C nom CS, ' '(EXISTS(S owned_by D)) OR (EXISTS(S documented_by N, N title "published"))') - self.assertEquals(rqlst.defined_vars['S']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['S']._q_invariant, True) def test_nonregr_ambiguity(self): rqlst = self._prepare('Note N WHERE N attachment F') # N may be an image as well, not invariant - self.assertEquals(rqlst.defined_vars['N']._q_invariant, False) - self.assertEquals(rqlst.defined_vars['F']._q_invariant, True) + self.assertEqual(rqlst.defined_vars['N']._q_invariant, False) + self.assertEqual(rqlst.defined_vars['F']._q_invariant, True) if __name__ == '__main__': from logilab.common.testlib import unittest_main diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_schemaserial.py --- a/server/test/unittest_schemaserial.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_schemaserial.py Wed Sep 29 16:16:32 2010 +0200 @@ -47,7 +47,7 @@ class Schema2RQLTC(TestCase): def test_eschema2rql1(self): - self.assertListEquals(list(eschema2rql(schema.eschema('CWAttribute'))), + self.assertListEqual(list(eschema2rql(schema.eschema('CWAttribute'))), [ ('INSERT CWEType X: X description %(description)s,X final %(final)s,X name %(name)s', {'description': u'define a final relation: link a final relation type from a non final entity to a final entity type. used to build the instance schema', @@ -55,13 +55,13 @@ ]) def test_eschema2rql2(self): - self.assertListEquals(list(eschema2rql(schema.eschema('String'))), [ + self.assertListEqual(list(eschema2rql(schema.eschema('String'))), [ ('INSERT CWEType X: X description %(description)s,X final %(final)s,X name %(name)s', {'description': u'', 'final': True, 'name': u'String'})]) def test_eschema2rql_specialization(self): # x: None since eschema.eid are None - self.assertListEquals(sorted(specialize2rql(schema)), + self.assertListEqual(sorted(specialize2rql(schema)), [('SET X specializes ET WHERE X eid %(x)s, ET eid %(et)s', {'et': None, 'x': None}), ('SET X specializes ET WHERE X eid %(x)s, ET eid %(et)s', @@ -72,7 +72,7 @@ {'et': None, 'x': None})]) def test_rschema2rql1(self): - self.assertListEquals(list(rschema2rql(schema.rschema('relation_type'), cstrtypemap)), + self.assertListEqual(list(rschema2rql(schema.rschema('relation_type'), cstrtypemap)), [ ('INSERT CWRType X: X description %(description)s,X final %(final)s,X fulltext_container %(fulltext_container)s,X inlined %(inlined)s,X name %(name)s,X symmetric %(symmetric)s', {'description': u'link a relation definition to its relation type', 'symmetric': False, 'name': u'relation_type', 'final' : False, 'fulltext_container': None, 'inlined': True}), @@ -93,7 +93,7 @@ ]) def test_rschema2rql2(self): - self.assertListEquals(list(rschema2rql(schema.rschema('add_permission'), cstrtypemap)), + self.assertListEqual(list(rschema2rql(schema.rschema('add_permission'), cstrtypemap)), [ ('INSERT CWRType X: X description %(description)s,X final %(final)s,X fulltext_container %(fulltext_container)s,X inlined %(inlined)s,X name %(name)s,X symmetric %(symmetric)s', {'description': u'', 'symmetric': False, 'name': u'add_permission', 'final': False, 'fulltext_container': None, 'inlined': False}), @@ -113,7 +113,7 @@ ]) def test_rschema2rql3(self): - self.assertListEquals(list(rschema2rql(schema.rschema('cardinality'), cstrtypemap)), + self.assertListEqual(list(rschema2rql(schema.rschema('cardinality'), cstrtypemap)), [ ('INSERT CWRType X: X description %(description)s,X final %(final)s,X fulltext_container %(fulltext_container)s,X inlined %(inlined)s,X name %(name)s,X symmetric %(symmetric)s', {'description': u'', 'symmetric': False, 'name': u'cardinality', 'final': True, 'fulltext_container': None, 'inlined': False}), @@ -136,7 +136,7 @@ ]) def test_rdef2rql(self): - self.assertListEquals(list(rdef2rql(schema['description_format'].rdefs[('CWRType', 'String')], cstrtypemap)), + self.assertListEqual(list(rdef2rql(schema['description_format'].rdefs[('CWRType', 'String')], cstrtypemap)), [ ('INSERT CWAttribute X: X cardinality %(cardinality)s,X defaultval %(defaultval)s,X description %(description)s,X fulltextindexed %(fulltextindexed)s,X indexed %(indexed)s,X internationalizable %(internationalizable)s,X ordernum %(ordernum)s,X relation_type ER,X from_entity SE,X to_entity OE WHERE SE eid %(se)s,ER eid %(rt)s,OE eid %(oe)s', {'se': None, 'rt': None, 'oe': None, @@ -148,19 +148,19 @@ def test_updateeschema2rql1(self): - self.assertListEquals(list(updateeschema2rql(schema.eschema('CWAttribute'), 1)), + self.assertListEqual(list(updateeschema2rql(schema.eschema('CWAttribute'), 1)), [('SET X description %(description)s,X final %(final)s,X name %(name)s WHERE X eid %(x)s', {'description': u'define a final relation: link a final relation type from a non final entity to a final entity type. used to build the instance schema', 'x': 1, 'final': False, 'name': u'CWAttribute'}), ]) def test_updateeschema2rql2(self): - self.assertListEquals(list(updateeschema2rql(schema.eschema('String'), 1)), + self.assertListEqual(list(updateeschema2rql(schema.eschema('String'), 1)), [('SET X description %(description)s,X final %(final)s,X name %(name)s WHERE X eid %(x)s', {'description': u'', 'x': 1, 'final': True, 'name': u'String'}) ]) def test_updaterschema2rql1(self): - self.assertListEquals(list(updaterschema2rql(schema.rschema('relation_type'), 1)), + self.assertListEqual(list(updaterschema2rql(schema.rschema('relation_type'), 1)), [ ('SET X description %(description)s,X final %(final)s,X fulltext_container %(fulltext_container)s,X inlined %(inlined)s,X name %(name)s,X symmetric %(symmetric)s WHERE X eid %(x)s', {'x': 1, 'symmetric': False, @@ -176,7 +176,7 @@ 'inlined': False, 'name': u'add_permission'}) ] for i, (rql, args) in enumerate(updaterschema2rql(schema.rschema('add_permission'), 1)): - yield self.assertEquals, (rql, args), expected[i] + yield self.assertEqual, (rql, args), expected[i] class Perms2RQLTC(TestCase): GROUP_MAPPING = { @@ -187,7 +187,7 @@ } def test_eperms2rql1(self): - self.assertListEquals([(rql, kwargs) for rql, kwargs in erperms2rql(schema.eschema('CWEType'), self.GROUP_MAPPING)], + self.assertListEqual([(rql, kwargs) for rql, kwargs in erperms2rql(schema.eschema('CWEType'), self.GROUP_MAPPING)], [('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 0}), ('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 1}), ('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 2}), @@ -197,7 +197,7 @@ ]) def test_rperms2rql2(self): - self.assertListEquals([(rql, kwargs) for rql, kwargs in erperms2rql(schema.rschema('read_permission').rdef('CWEType', 'CWGroup'), self.GROUP_MAPPING)], + self.assertListEqual([(rql, kwargs) for rql, kwargs in erperms2rql(schema.rschema('read_permission').rdef('CWEType', 'CWGroup'), self.GROUP_MAPPING)], [('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 0}), ('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 1}), ('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 2}), @@ -206,7 +206,7 @@ ]) def test_rperms2rql3(self): - self.assertListEquals([(rql, kwargs) for rql, kwargs in erperms2rql(schema.rschema('name').rdef('CWEType', 'String'), self.GROUP_MAPPING)], + self.assertListEqual([(rql, kwargs) for rql, kwargs in erperms2rql(schema.rschema('name').rdef('CWEType', 'String'), self.GROUP_MAPPING)], [('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 0}), ('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 1}), ('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 2}), @@ -214,7 +214,7 @@ ]) #def test_perms2rql(self): - # self.assertListEquals(perms2rql(schema, self.GROUP_MAPPING), + # self.assertListEqual(perms2rql(schema, self.GROUP_MAPPING), # ['INSERT CWEType X: X name 'Societe', X final FALSE']) diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_security.py --- a/server/test/unittest_security.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_security.py Wed Sep 29 16:16:32 2010 +0200 @@ -81,10 +81,10 @@ cnx = self.login('iaminusersgrouponly') self.hijack_source_execute() self.execute('Any U WHERE NOT A todo_by U, A is Affaire') - self.assertEquals(self.query[0][1].as_string(), + self.assertEqual(self.query[0][1].as_string(), 'Any U WHERE NOT EXISTS(A todo_by U), A is Affaire') self.execute('Any U WHERE NOT EXISTS(A todo_by U), A is Affaire') - self.assertEquals(self.query[0][1].as_string(), + self.assertEqual(self.query[0][1].as_string(), 'Any U WHERE NOT EXISTS(A todo_by U), A is Affaire') class SecurityTC(BaseSecurityTC): @@ -103,7 +103,7 @@ cu = cnx.cursor() cu.execute("INSERT Personne X: X nom 'bidule'") self.assertRaises(Unauthorized, cnx.commit) - self.assertEquals(cu.execute('Personne X').rowcount, 1) + self.assertEqual(cu.execute('Personne X').rowcount, 1) def test_insert_rql_permission(self): # test user can only add une affaire related to a societe he owns @@ -113,7 +113,7 @@ self.assertRaises(Unauthorized, cnx.commit) # test nothing has actually been inserted self.restore_connection() - self.assertEquals(self.execute('Affaire X').rowcount, 1) + self.assertEqual(self.execute('Affaire X').rowcount, 1) cnx = self.login('iaminusersgrouponly') cu = cnx.cursor() cu.execute("INSERT Affaire X: X sujet 'cool'") @@ -128,7 +128,7 @@ cu.execute( "SET X nom 'bidulechouette' WHERE X is Personne") self.assertRaises(Unauthorized, cnx.commit) self.restore_connection() - self.assertEquals(self.execute('Personne X WHERE X nom "bidulechouette"').rowcount, 0) + self.assertEqual(self.execute('Personne X WHERE X nom "bidulechouette"').rowcount, 0) def test_update_security_2(self): cnx = self.login('anon') @@ -139,7 +139,7 @@ #self.assertRaises(Unauthorized, cnx.commit) # test nothing has actually been inserted self.restore_connection() - self.assertEquals(self.execute('Personne X WHERE X nom "bidulechouette"').rowcount, 0) + self.assertEqual(self.execute('Personne X WHERE X nom "bidulechouette"').rowcount, 0) def test_update_security_3(self): cnx = self.login('iaminusersgrouponly') @@ -210,14 +210,14 @@ cnx.commit() # to actually get Unauthorized exception, try to insert a relation were we can read both entities rset = cu.execute('Personne P') - self.assertEquals(len(rset), 1) + self.assertEqual(len(rset), 1) ent = rset.get_entity(0, 0) session.set_pool() # necessary self.assertRaises(Unauthorized, ent.cw_check_perm, 'update') self.assertRaises(Unauthorized, cu.execute, "SET P travaille S WHERE P is Personne, S is Societe") # test nothing has actually been inserted: - self.assertEquals(cu.execute('Any P,S WHERE P travaille S,P is Personne, S is Societe').rowcount, 0) + self.assertEqual(cu.execute('Any P,S WHERE P travaille S,P is Personne, S is Societe').rowcount, 0) cu.execute("INSERT Societe X: X nom 'chouette'") cu.execute("SET A concerne S WHERE A is Affaire, S nom 'chouette'") cnx.commit() @@ -278,7 +278,7 @@ cnx = self.login('iaminusersgrouponly') cu = cnx.cursor() rset = cu.execute('Affaire X') - self.assertEquals(rset.rows, []) + self.assertEqual(rset.rows, []) self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x': eid}) # cache test self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x': eid}) @@ -287,12 +287,12 @@ cu.execute("SET A concerne S WHERE A is Affaire, S is Societe") cnx.commit() rset = cu.execute('Any X WHERE X eid %(x)s', {'x': aff2}) - self.assertEquals(rset.rows, [[aff2]]) + self.assertEqual(rset.rows, [[aff2]]) # more cache test w/ NOT eid rset = cu.execute('Affaire X WHERE NOT X eid %(x)s', {'x': eid}) - self.assertEquals(rset.rows, [[aff2]]) + self.assertEqual(rset.rows, [[aff2]]) rset = cu.execute('Affaire X WHERE NOT X eid %(x)s', {'x': aff2}) - self.assertEquals(rset.rows, []) + self.assertEqual(rset.rows, []) # test can't update an attribute of an entity that can't be readen self.assertRaises(Unauthorized, cu.execute, 'SET X sujet "hacked" WHERE X eid %(x)s', {'x': eid}) @@ -309,7 +309,7 @@ self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':aff2})) # XXX would be nice if it worked rset = cu.execute("Affaire X WHERE X sujet 'cool'") - self.assertEquals(len(rset), 0) + self.assertEqual(len(rset), 0) finally: affschema.set_action_permissions('read', origperms) cnx.close() @@ -329,7 +329,7 @@ self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':aff2})) self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':card1})) rset = cu.execute("Any X WHERE X has_text 'cool'") - self.assertEquals(sorted(eid for eid, in rset.rows), + self.assertEqual(sorted(eid for eid, in rset.rows), [card1, aff2]) def test_read_erqlexpr_has_text2(self): @@ -340,9 +340,9 @@ cnx = self.login('iaminusersgrouponly') cu = cnx.cursor() rset = cu.execute('Any N WHERE N has_text "bidule"') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) rset = cu.execute('Any N WITH N BEING (Any N WHERE N has_text "bidule")') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) def test_read_erqlexpr_optional_rel(self): self.execute("INSERT Personne X: X nom 'bidule'") @@ -352,7 +352,7 @@ cnx = self.login('anon') cu = cnx.cursor() rset = cu.execute('Any N,U WHERE N has_text "bidule", N owned_by U?') - self.assertEquals(len(rset.rows), 1, rset.rows) + self.assertEqual(len(rset.rows), 1, rset.rows) def test_read_erqlexpr_aggregat(self): self.execute("INSERT Affaire X: X sujet 'cool'")[0][0] @@ -360,22 +360,22 @@ cnx = self.login('iaminusersgrouponly') cu = cnx.cursor() rset = cu.execute('Any COUNT(X) WHERE X is Affaire') - self.assertEquals(rset.rows, [[0]]) + self.assertEqual(rset.rows, [[0]]) aff2 = cu.execute("INSERT Affaire X: X sujet 'cool'")[0][0] soc1 = cu.execute("INSERT Societe X: X nom 'chouette'")[0][0] cu.execute("SET A concerne S WHERE A is Affaire, S is Societe") cnx.commit() rset = cu.execute('Any COUNT(X) WHERE X is Affaire') - self.assertEquals(rset.rows, [[1]]) + self.assertEqual(rset.rows, [[1]]) rset = cu.execute('Any ETN, COUNT(X) GROUPBY ETN WHERE X is ET, ET name ETN') values = dict(rset) - self.assertEquals(values['Affaire'], 1) - self.assertEquals(values['Societe'], 2) + self.assertEqual(values['Affaire'], 1) + self.assertEqual(values['Societe'], 2) rset = cu.execute('Any ETN, COUNT(X) GROUPBY ETN WHERE X is ET, ET name ETN WITH X BEING ((Affaire X) UNION (Societe X))') - self.assertEquals(len(rset), 2) + self.assertEqual(len(rset), 2) values = dict(rset) - self.assertEquals(values['Affaire'], 1) - self.assertEquals(values['Societe'], 2) + self.assertEqual(values['Affaire'], 1) + self.assertEqual(values['Societe'], 2) def test_attribute_security(self): @@ -415,7 +415,7 @@ cnx.commit() note2.cw_adapt_to('IWorkflowable').fire_transition('markasdone') cnx.commit() - self.assertEquals(len(cu.execute('Any X WHERE X in_state S, S name "todo", X eid %(x)s', {'x': note2.eid})), + self.assertEqual(len(cu.execute('Any X WHERE X in_state S, S name "todo", X eid %(x)s', {'x': note2.eid})), 0) cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': note2.eid}) self.assertRaises(Unauthorized, cnx.commit) @@ -433,11 +433,11 @@ rset = cu.execute('CWUser X') self.failUnless(rset) x = rset.get_entity(0, 0) - self.assertEquals(x.login, None) + self.assertEqual(x.login, None) self.failUnless(x.creation_date) x = rset.get_entity(1, 0) x.complete() - self.assertEquals(x.login, None) + self.assertEqual(x.login, None) self.failUnless(x.creation_date) cnx.rollback() @@ -456,9 +456,9 @@ affaire = self.execute('Any X WHERE X ref "ARCT01"').get_entity(0, 0) affaire.cw_adapt_to('IWorkflowable').fire_transition('abort') self.commit() - self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01"')), + self.assertEqual(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01"')), 1) - self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01",' + self.assertEqual(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01",' 'X owned_by U, U login "admin"')), 1) # TrInfo at the above state change cnx = self.login('iaminusersgrouponly') @@ -473,9 +473,9 @@ cu = cnx.cursor() # anonymous user can only read itself rset = cu.execute('Any L WHERE X owned_by U, U login L') - self.assertEquals(rset.rows, [['anon']]) + self.assertEqual(rset.rows, [['anon']]) rset = cu.execute('CWUser X') - self.assertEquals(rset.rows, [[anon.eid]]) + self.assertEqual(rset.rows, [[anon.eid]]) # anonymous user can read groups (necessary to check allowed transitions for instance) self.assert_(cu.execute('CWGroup X')) # should only be able to read the anonymous user, not another one @@ -488,7 +488,7 @@ # {'x': self.user.eid}) rset = cu.execute('CWUser X WHERE X eid %(x)s', {'x': anon.eid}) - self.assertEquals(rset.rows, [[anon.eid]]) + self.assertEqual(rset.rows, [[anon.eid]]) # but can't modify it cu.execute('SET X login "toto" WHERE X eid %(x)s', {'x': anon.eid}) self.assertRaises(Unauthorized, cnx.commit) @@ -516,14 +516,14 @@ cnx = self.login('anon') cu = cnx.cursor() anoneid = self.session.user.eid - self.assertEquals(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,' + self.assertEqual(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,' 'B bookmarked_by U, U eid %s' % anoneid).rows, [['index', '?vid=index']]) - self.assertEquals(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,' + self.assertEqual(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,' 'B bookmarked_by U, U eid %(x)s', {'x': anoneid}).rows, [['index', '?vid=index']]) # can read others bookmarks as well - self.assertEquals(cu.execute('Any B where B is Bookmark, NOT B bookmarked_by U').rows, + self.assertEqual(cu.execute('Any B where B is Bookmark, NOT B bookmarked_by U').rows, [[beid1]]) self.assertRaises(Unauthorized, cu.execute,'DELETE B bookmarked_by U') self.assertRaises(Unauthorized, @@ -535,7 +535,7 @@ cnx = self.login('anon') cu = cnx.cursor() names = [t for t, in cu.execute('Any N ORDERBY lower(N) WHERE X name N')] - self.assertEquals(names, sorted(names, key=lambda x: x.lower())) + self.assertEqual(names, sorted(names, key=lambda x: x.lower())) def test_in_state_without_update_perm(self): """check a user change in_state without having update permission on the @@ -582,7 +582,7 @@ self.commit() aff.cw_clear_relation_cache('wf_info_for', 'object') trinfo = iworkflowable.latest_trinfo() - self.assertEquals(trinfo.comment, 'bouh!') + self.assertEqual(trinfo.comment, 'bouh!') # but not from_state/to_state aff.cw_clear_relation_cache('wf_info_for', role='object') self.assertRaises(Unauthorized, diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_session.py --- a/server/test/unittest_session.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_session.py Wed Sep 29 16:16:32 2010 +0200 @@ -43,7 +43,7 @@ class MakeDescriptionTC(TestCase): def test_known_values(self): solution = {'A': 'Int', 'B': 'CWUser'} - self.assertEquals(_make_description((Function('max', 'A'), Variable('B')), {}, solution), + self.assertEqual(_make_description((Function('max', 'A'), Variable('B')), {}, solution), ['Int','CWUser']) class InternalSessionTC(CubicWebTC): diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_sqlutils.py --- a/server/test/unittest_sqlutils.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_sqlutils.py Wed Sep 29 16:16:32 2010 +0200 @@ -36,13 +36,13 @@ def test_init(self): o = SQLAdapterMixIn(BASE_CONFIG) - self.assertEquals(o.dbhelper.dbencoding, 'UTF-8') + self.assertEqual(o.dbhelper.dbencoding, 'UTF-8') def test_init_encoding(self): config = BASE_CONFIG.copy() config['db-encoding'] = 'ISO-8859-1' o = SQLAdapterMixIn(config) - self.assertEquals(o.dbhelper.dbencoding, 'ISO-8859-1') + self.assertEqual(o.dbhelper.dbencoding, 'ISO-8859-1') if __name__ == '__main__': unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_storage.py --- a/server/test/unittest_storage.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_storage.py Wed Sep 29 16:16:32 2010 +0200 @@ -78,15 +78,15 @@ expected_filepath = osp.join(self.tempdir, '%s_data_%s' % (f1.eid, f1.data_name)) self.failUnless(osp.isfile(expected_filepath)) - self.assertEquals(file(expected_filepath).read(), 'the-data') + self.assertEqual(file(expected_filepath).read(), 'the-data') self.rollback() self.failIf(osp.isfile(expected_filepath)) f1 = self.create_file() self.commit() - self.assertEquals(file(expected_filepath).read(), 'the-data') + self.assertEqual(file(expected_filepath).read(), 'the-data') f1.set_attributes(data=Binary('the new data')) self.rollback() - self.assertEquals(file(expected_filepath).read(), 'the-data') + self.assertEqual(file(expected_filepath).read(), 'the-data') f1.cw_delete() self.failUnless(osp.isfile(expected_filepath)) self.rollback() @@ -98,14 +98,14 @@ def test_bfss_sqlite_fspath(self): f1 = self.create_file() expected_filepath = osp.join(self.tempdir, '%s_data_%s' % (f1.eid, f1.data_name)) - self.assertEquals(self.fspath(f1), expected_filepath) + self.assertEqual(self.fspath(f1), expected_filepath) def test_bfss_fs_importing_doesnt_touch_path(self): self.session.transaction_data['fs_importing'] = True filepath = osp.abspath(__file__) f1 = self.session.create_entity('File', data=Binary(filepath), data_format=u'text/plain', data_name=u'foo') - self.assertEquals(self.fspath(f1), filepath) + self.assertEqual(self.fspath(f1), filepath) def test_source_storage_transparency(self): with self.temporary_appobjects(DummyBeforeHook, DummyAfterHook): @@ -114,11 +114,11 @@ def test_source_mapped_attribute_error_cases(self): ex = self.assertRaises(QueryError, self.execute, 'Any X WHERE X data ~= "hop", X is File') - self.assertEquals(str(ex), 'can\'t use File.data (X data ILIKE "hop") in restriction') + self.assertEqual(str(ex), 'can\'t use File.data (X data ILIKE "hop") in restriction') ex = self.assertRaises(QueryError, self.execute, 'Any X, Y WHERE X data D, Y data D, ' 'NOT X identity Y, X is File, Y is File') - self.assertEquals(str(ex), "can't use D as a restriction variable") + self.assertEqual(str(ex), "can't use D as a restriction variable") # query returning mix of mapped / regular attributes (only file.data # mapped, not image.data for instance) ex = self.assertRaises(QueryError, self.execute, @@ -127,19 +127,19 @@ ' UNION ' ' (Any D WHERE X data D, X is File)' ')') - self.assertEquals(str(ex), 'query fetch some source mapped attribute, some not') + self.assertEqual(str(ex), 'query fetch some source mapped attribute, some not') ex = self.assertRaises(QueryError, self.execute, '(Any D WHERE X data D, X is File)' ' UNION ' '(Any D WHERE X title D, X is Bookmark)') - self.assertEquals(str(ex), 'query fetch some source mapped attribute, some not') + self.assertEqual(str(ex), 'query fetch some source mapped attribute, some not') storages.set_attribute_storage(self.repo, 'State', 'name', storages.BytesFileSystemStorage(self.tempdir)) try: ex = self.assertRaises(QueryError, self.execute, 'Any D WHERE X name D, X is IN (State, Transition)') - self.assertEquals(str(ex), 'query fetch some source mapped attribute, some not') + self.assertEqual(str(ex), 'query fetch some source mapped attribute, some not') finally: storages.unset_attribute_storage(self.repo, 'State', 'name') @@ -150,30 +150,30 @@ ' UNION ' ' (Any D, X WHERE X eid %(x)s, X data D)' ')', {'x': f1.eid}) - self.assertEquals(len(rset), 2) - self.assertEquals(rset[0][0], f1.eid) - self.assertEquals(rset[1][0], f1.eid) - self.assertEquals(rset[0][1].getvalue(), 'the-data') - self.assertEquals(rset[1][1].getvalue(), 'the-data') + self.assertEqual(len(rset), 2) + self.assertEqual(rset[0][0], f1.eid) + self.assertEqual(rset[1][0], f1.eid) + self.assertEqual(rset[0][1].getvalue(), 'the-data') + self.assertEqual(rset[1][1].getvalue(), 'the-data') rset = self.execute('Any X,LENGTH(D) WHERE X eid %(x)s, X data D', {'x': f1.eid}) - self.assertEquals(len(rset), 1) - self.assertEquals(rset[0][0], f1.eid) - self.assertEquals(rset[0][1], len('the-data')) + self.assertEqual(len(rset), 1) + self.assertEqual(rset[0][0], f1.eid) + self.assertEqual(rset[0][1], len('the-data')) rset = self.execute('Any X,LENGTH(D) WITH D,X BEING (' ' (Any D, X WHERE X eid %(x)s, X data D)' ' UNION ' ' (Any D, X WHERE X eid %(x)s, X data D)' ')', {'x': f1.eid}) - self.assertEquals(len(rset), 2) - self.assertEquals(rset[0][0], f1.eid) - self.assertEquals(rset[1][0], f1.eid) - self.assertEquals(rset[0][1], len('the-data')) - self.assertEquals(rset[1][1], len('the-data')) + self.assertEqual(len(rset), 2) + self.assertEqual(rset[0][0], f1.eid) + self.assertEqual(rset[1][0], f1.eid) + self.assertEqual(rset[0][1], len('the-data')) + self.assertEqual(rset[1][1], len('the-data')) ex = self.assertRaises(QueryError, self.execute, 'Any X,UPPER(D) WHERE X eid %(x)s, X data D', {'x': f1.eid}) - self.assertEquals(str(ex), 'UPPER can not be called on mapped attribute') + self.assertEqual(str(ex), 'UPPER can not be called on mapped attribute') def test_bfss_fs_importing_transparency(self): @@ -181,7 +181,7 @@ filepath = osp.abspath(__file__) f1 = self.session.create_entity('File', data=Binary(filepath), data_format=u'text/plain', data_name=u'foo') - self.assertEquals(f1.data.getvalue(), file(filepath).read(), + self.assertEqual(f1.data.getvalue(), file(filepath).read(), 'files content differ') @tag('Storage', 'BFSS', 'update') @@ -193,10 +193,10 @@ # update f1's local dict. We want the pure rql version to work self.execute('SET F data %(d)s WHERE F eid %(f)s', {'d': Binary('some other data'), 'f': f1.eid}) - self.assertEquals(f1.data.getvalue(), 'some other data') + self.assertEqual(f1.data.getvalue(), 'some other data') self.commit() f2 = self.execute('Any F WHERE F eid %(f)s, F is File', {'f': f1.eid}).get_entity(0, 0) - self.assertEquals(f2.data.getvalue(), 'some other data') + self.assertEqual(f2.data.getvalue(), 'some other data') @tag('Storage', 'BFSS', 'update', 'extension', 'commit') def test_bfss_update_with_different_extension_commited(self): @@ -208,7 +208,7 @@ self.commit() old_path = self.fspath(f1) self.failUnless(osp.isfile(old_path)) - self.assertEquals(osp.splitext(old_path)[1], '.txt') + self.assertEqual(osp.splitext(old_path)[1], '.txt') self.execute('SET F data %(d)s, F data_name %(dn)s, F data_format %(df)s WHERE F eid %(f)s', {'d': Binary('some other data'), 'f': f1.eid, 'dn': u'bar.jpg', 'df': u'image/jpeg'}) self.commit() @@ -218,7 +218,7 @@ new_path = self.fspath(f2) self.failIf(osp.isfile(old_path)) self.failUnless(osp.isfile(new_path)) - self.assertEquals(osp.splitext(new_path)[1], '.jpg') + self.assertEqual(osp.splitext(new_path)[1], '.jpg') @tag('Storage', 'BFSS', 'update', 'extension', 'rollback') def test_bfss_update_with_different_extension_rollbacked(self): @@ -231,7 +231,7 @@ old_path = self.fspath(f1) old_data = f1.data.getvalue() self.failUnless(osp.isfile(old_path)) - self.assertEquals(osp.splitext(old_path)[1], '.txt') + self.assertEqual(osp.splitext(old_path)[1], '.txt') self.execute('SET F data %(d)s, F data_name %(dn)s, F data_format %(df)s WHERE F eid %(f)s', {'d': Binary('some other data'), 'f': f1.eid, 'dn': u'bar.jpg', 'df': u'image/jpeg'}) self.rollback() @@ -241,9 +241,9 @@ new_path = self.fspath(f2) new_data = f2.data.getvalue() self.failUnless(osp.isfile(new_path)) - self.assertEquals(osp.splitext(new_path)[1], '.txt') - self.assertEquals(old_path, new_path) - self.assertEquals(old_data, new_data) + self.assertEqual(osp.splitext(new_path)[1], '.txt') + self.assertEqual(old_path, new_path) + self.assertEqual(old_data, new_data) def test_bfss_update_with_fs_importing(self): # use self.session to use server-side cache @@ -256,8 +256,8 @@ self.execute('SET F data %(d)s WHERE F eid %(f)s', {'d': Binary(new_fspath), 'f': f1.eid}) self.commit() - self.assertEquals(f1.data.getvalue(), 'the new data') - self.assertEquals(self.fspath(f1), new_fspath) + self.assertEqual(f1.data.getvalue(), 'the new data') + self.assertEqual(self.fspath(f1), new_fspath) self.failIf(osp.isfile(old_fspath)) diff -r e3994fcc21c3 -r 1806148d6ce8 server/test/unittest_undo.py --- a/server/test/unittest_undo.py Thu Sep 23 23:28:58 2010 +0200 +++ b/server/test/unittest_undo.py Wed Sep 29 16:16:32 2010 +0200 @@ -54,36 +54,36 @@ self.cnx.undo_transaction, 'hop') txinfo = self.cnx.transaction_info(self.txuuid) self.failUnless(txinfo.datetime) - self.assertEquals(txinfo.user_eid, self.session.user.eid) - self.assertEquals(txinfo.user().login, 'admin') + self.assertEqual(txinfo.user_eid, self.session.user.eid) + self.assertEqual(txinfo.user().login, 'admin') actions = txinfo.actions_list() - self.assertEquals(len(actions), 2) + self.assertEqual(len(actions), 2) actions = txinfo.actions_list(public=False) - self.assertEquals(len(actions), 6) + self.assertEqual(len(actions), 6) a1 = actions[0] - self.assertEquals(a1.action, 'C') - self.assertEquals(a1.eid, self.toto.eid) - self.assertEquals(a1.etype,'CWUser') - self.assertEquals(a1.changes, None) - self.assertEquals(a1.public, True) - self.assertEquals(a1.order, 1) + self.assertEqual(a1.action, 'C') + self.assertEqual(a1.eid, self.toto.eid) + self.assertEqual(a1.etype,'CWUser') + self.assertEqual(a1.changes, None) + self.assertEqual(a1.public, True) + self.assertEqual(a1.order, 1) a4 = actions[3] - self.assertEquals(a4.action, 'A') - self.assertEquals(a4.rtype, 'in_group') - self.assertEquals(a4.eid_from, self.toto.eid) - self.assertEquals(a4.eid_to, self.toto.in_group[0].eid) - self.assertEquals(a4.order, 4) + self.assertEqual(a4.action, 'A') + self.assertEqual(a4.rtype, 'in_group') + self.assertEqual(a4.eid_from, self.toto.eid) + self.assertEqual(a4.eid_to, self.toto.in_group[0].eid) + self.assertEqual(a4.order, 4) for i, rtype in ((1, 'owned_by'), (2, 'owned_by'), (4, 'in_state'), (5, 'created_by')): a = actions[i] - self.assertEquals(a.action, 'A') - self.assertEquals(a.eid_from, self.toto.eid) - self.assertEquals(a.rtype, rtype) - self.assertEquals(a.order, i+1) + self.assertEqual(a.action, 'A') + self.assertEqual(a.eid_from, self.toto.eid) + self.assertEqual(a.rtype, rtype) + self.assertEqual(a.order, i+1) # test undoable_transactions txs = self.cnx.undoable_transactions() - self.assertEquals(len(txs), 1) - self.assertEquals(txs[0].uuid, self.txuuid) + self.assertEqual(len(txs), 1) + self.assertEqual(txs[0].uuid, self.txuuid) # test transaction_info / undoable_transactions security cnx = self.login('anon') self.assertRaises(NoSuchTransaction, @@ -93,7 +93,7 @@ self.assertRaises(NoSuchTransaction, cnx.undo_transaction, self.txuuid) txs = cnx.undoable_transactions() - self.assertEquals(len(txs), 0) + self.assertEqual(len(txs), 0) def test_undoable_transactions(self): toto = self.toto @@ -105,31 +105,31 @@ txuuid2 = self.commit() undoable_transactions = self.cnx.undoable_transactions txs = undoable_transactions(action='D') - self.assertEquals(len(txs), 1, txs) - self.assertEquals(txs[0].uuid, txuuid2) + self.assertEqual(len(txs), 1, txs) + self.assertEqual(txs[0].uuid, txuuid2) txs = undoable_transactions(action='C') - self.assertEquals(len(txs), 2, txs) - self.assertEquals(txs[0].uuid, txuuid1) - self.assertEquals(txs[1].uuid, self.txuuid) + self.assertEqual(len(txs), 2, txs) + self.assertEqual(txs[0].uuid, txuuid1) + self.assertEqual(txs[1].uuid, self.txuuid) txs = undoable_transactions(eid=toto.eid) - self.assertEquals(len(txs), 3) - self.assertEquals(txs[0].uuid, txuuid2) - self.assertEquals(txs[1].uuid, txuuid1) - self.assertEquals(txs[2].uuid, self.txuuid) + self.assertEqual(len(txs), 3) + self.assertEqual(txs[0].uuid, txuuid2) + self.assertEqual(txs[1].uuid, txuuid1) + self.assertEqual(txs[2].uuid, self.txuuid) txs = undoable_transactions(etype='CWUser') - self.assertEquals(len(txs), 2) + self.assertEqual(len(txs), 2) txs = undoable_transactions(etype='CWUser', action='C') - self.assertEquals(len(txs), 1) - self.assertEquals(txs[0].uuid, self.txuuid) + self.assertEqual(len(txs), 1) + self.assertEqual(txs[0].uuid, self.txuuid) txs = undoable_transactions(etype='EmailAddress', action='D') - self.assertEquals(len(txs), 0) + self.assertEqual(len(txs), 0) txs = undoable_transactions(etype='EmailAddress', action='D', public=False) - self.assertEquals(len(txs), 1) - self.assertEquals(txs[0].uuid, txuuid2) + self.assertEqual(len(txs), 1) + self.assertEqual(txs[0].uuid, txuuid2) txs = undoable_transactions(eid=toto.eid, action='R', public=False) - self.assertEquals(len(txs), 1) - self.assertEquals(txs[0].uuid, txuuid2) + self.assertEqual(len(txs), 1) + self.assertEqual(txs[0].uuid, txuuid2) def test_undo_deletion_base(self): toto = self.toto @@ -143,34 +143,34 @@ for_user=toto) self.commit() txs = self.cnx.undoable_transactions() - self.assertEquals(len(txs), 2) + self.assertEqual(len(txs), 2) toto.cw_delete() txuuid = self.commit() actions = self.cnx.transaction_info(txuuid).actions_list() - self.assertEquals(len(actions), 1) + self.assertEqual(len(actions), 1) toto.clear_all_caches() e.clear_all_caches() errors = self.cnx.undo_transaction(txuuid) undotxuuid = self.commit() - self.assertEquals(undotxuuid, None) # undo not undoable - self.assertEquals(errors, []) + self.assertEqual(undotxuuid, None) # undo not undoable + self.assertEqual(errors, []) self.failUnless(self.execute('Any X WHERE X eid %(x)s', {'x': toto.eid})) self.failUnless(self.execute('Any X WHERE X eid %(x)s', {'x': e.eid})) self.failUnless(self.execute('Any X WHERE X has_text "toto@logilab"')) - self.assertEquals(toto.cw_adapt_to('IWorkflowable').state, 'activated') - self.assertEquals(toto.cw_adapt_to('IEmailable').get_email(), 'toto@logilab.org') - self.assertEquals([(p.pkey, p.value) for p in toto.reverse_for_user], + self.assertEqual(toto.cw_adapt_to('IWorkflowable').state, 'activated') + self.assertEqual(toto.cw_adapt_to('IEmailable').get_email(), 'toto@logilab.org') + self.assertEqual([(p.pkey, p.value) for p in toto.reverse_for_user], [('ui.default-text-format', 'text/rest')]) - self.assertEquals([g.name for g in toto.in_group], + self.assertEqual([g.name for g in toto.in_group], ['users']) - self.assertEquals([et.name for et in toto.related('is', entities=True)], + self.assertEqual([et.name for et in toto.related('is', entities=True)], ['CWUser']) - self.assertEquals([et.name for et in toto.is_instance_of], + self.assertEqual([et.name for et in toto.is_instance_of], ['CWUser']) # undoing shouldn't be visble in undoable transaction, and the undoed # transaction should be removed txs = self.cnx.undoable_transactions() - self.assertEquals(len(txs), 2) + self.assertEqual(len(txs), 2) self.assertRaises(NoSuchTransaction, self.cnx.transaction_info, txuuid) self.check_transaction_deleted(txuuid) @@ -191,9 +191,9 @@ errors = self.cnx.undo_transaction(txuuid) self.commit() p.clear_all_caches() - self.assertEquals(p.fiche[0].eid, c2.eid) - self.assertEquals(len(errors), 1) - self.assertEquals(errors[0], + self.assertEqual(p.fiche[0].eid, c2.eid) + self.assertEqual(len(errors), 1) + self.assertEqual(errors[0], "Can't restore object relation fiche to entity " "%s which is already linked using this relation." % p.eid) @@ -209,12 +209,12 @@ g.cw_delete() self.commit() errors = self.cnx.undo_transaction(txuuid) - self.assertEquals(errors, + self.assertEqual(errors, [u"Can't restore relation in_group, object entity " "%s doesn't exist anymore." % g.eid]) ex = self.assertRaises(ValidationError, self.commit) - self.assertEquals(ex.entity, self.toto.eid) - self.assertEquals(ex.errors, + self.assertEqual(ex.entity, self.toto.eid) + self.assertEqual(ex.errors, {'in_group-subject': u'at least one relation in_group is ' 'required on CWUser (%s)' % self.toto.eid}) @@ -254,8 +254,8 @@ self.commit() ex = self.assertRaises(ValidationError, self.cnx.undo_transaction, txuuid) - self.assertEquals(ex.entity, tutu.eid) - self.assertEquals(ex.errors, + self.assertEqual(ex.entity, tutu.eid) + self.assertEqual(ex.errors, {None: 'some later transaction(s) touch entity, undo them first'}) def test_undo_creation_integrity_2(self): @@ -267,15 +267,15 @@ self.commit() ex = self.assertRaises(ValidationError, self.cnx.undo_transaction, txuuid) - self.assertEquals(ex.entity, g.eid) - self.assertEquals(ex.errors, + self.assertEqual(ex.entity, g.eid) + self.assertEqual(ex.errors, {None: 'some later transaction(s) touch entity, undo them first'}) - # self.assertEquals(errors, + # self.assertEqual(errors, # [u"Can't restore relation in_group, object entity " # "%s doesn't exist anymore." % g.eid]) # ex = self.assertRaises(ValidationError, self.commit) - # self.assertEquals(ex.entity, self.toto.eid) - # self.assertEquals(ex.errors, + # self.assertEqual(ex.entity, self.toto.eid) + # self.assertEqual(ex.errors, # {'in_group-subject': u'at least one relation in_group is ' # 'required on CWUser (%s)' % self.toto.eid}) diff -r e3994fcc21c3 -r 1806148d6ce8 sobjects/test/unittest_email.py --- a/sobjects/test/unittest_email.py Thu Sep 23 23:28:58 2010 +0200 +++ b/sobjects/test/unittest_email.py Wed Sep 29 16:16:32 2010 +0200 @@ -26,23 +26,23 @@ def test_use_email_set_primary_email(self): self.execute('INSERT EmailAddress X: X address "admin@logilab.fr", U use_email X WHERE U login "admin"') - self.assertEquals(self.execute('Any A WHERE U primary_email X, U login "admin", X address A').rows, + self.assertEqual(self.execute('Any A WHERE U primary_email X, U login "admin", X address A').rows, []) self.commit() - self.assertEquals(self.execute('Any A WHERE U primary_email X, U login "admin", X address A')[0][0], + self.assertEqual(self.execute('Any A WHERE U primary_email X, U login "admin", X address A')[0][0], 'admin@logilab.fr') # having another email should'nt change anything self.execute('INSERT EmailAddress X: X address "a@logilab.fr", U use_email X WHERE U login "admin"') self.commit() - self.assertEquals(self.execute('Any A WHERE U primary_email X, U login "admin", X address A')[0][0], + self.assertEqual(self.execute('Any A WHERE U primary_email X, U login "admin", X address A')[0][0], 'admin@logilab.fr') def test_primary_email_set_use_email(self): self.execute('INSERT EmailAddress X: X address "admin@logilab.fr", U primary_email X WHERE U login "admin"') - self.assertEquals(self.execute('Any A WHERE U use_email X, U login "admin", X address A').rows, + self.assertEqual(self.execute('Any A WHERE U use_email X, U login "admin", X address A').rows, []) self.commit() - self.assertEquals(self.execute('Any A WHERE U use_email X, U login "admin", X address A')[0][0], + self.assertEqual(self.execute('Any A WHERE U use_email X, U login "admin", X address A')[0][0], 'admin@logilab.fr') def test_cardinality_check(self): diff -r e3994fcc21c3 -r 1806148d6ce8 sobjects/test/unittest_notification.py --- a/sobjects/test/unittest_notification.py Thu Sep 23 23:28:58 2010 +0200 +++ b/sobjects/test/unittest_notification.py Wed Sep 29 16:16:32 2010 +0200 @@ -72,12 +72,12 @@ finder = self.vreg['components'].select('recipients_finder', self.request(), rset=urset) self.set_option('default-recipients-mode', 'none') - self.assertEquals(finder.recipients(), []) + self.assertEqual(finder.recipients(), []) self.set_option('default-recipients-mode', 'users') - self.assertEquals(finder.recipients(), [(u'admin@logilab.fr', 'fr')]) + self.assertEqual(finder.recipients(), [(u'admin@logilab.fr', 'fr')]) self.set_option('default-recipients-mode', 'default-dest-addrs') self.set_option('default-dest-addrs', 'abcd@logilab.fr, efgh@logilab.fr') - self.assertEquals(finder.recipients(), [('abcd@logilab.fr', 'en'), ('efgh@logilab.fr', 'en')]) + self.assertEqual(finder.recipients(), [('abcd@logilab.fr', 'en'), ('efgh@logilab.fr', 'en')]) class StatusChangeViewsTC(CubicWebTC): @@ -88,9 +88,9 @@ u.cw_adapt_to('IWorkflowable').fire_transition('deactivate', comment=u'yeah') self.failIf(MAILBOX) self.commit() - self.assertEquals(len(MAILBOX), 1) + self.assertEqual(len(MAILBOX), 1) email = MAILBOX[0] - self.assertEquals(email.content, + self.assertEqual(email.content, ''' admin changed status from to for entity 'toto' @@ -99,7 +99,7 @@ url: http://testing.fr/cubicweb/cwuser/toto ''') - self.assertEquals(email.subject, 'status changed cwuser #%s (admin)' % u.eid) + self.assertEqual(email.subject, 'status changed cwuser #%s (admin)' % u.eid) if __name__ == '__main__': unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 sobjects/test/unittest_supervising.py --- a/sobjects/test/unittest_supervising.py Thu Sep 23 23:28:58 2010 +0200 +++ b/sobjects/test/unittest_supervising.py Wed Sep 29 16:16:32 2010 +0200 @@ -52,16 +52,16 @@ session = self.session sentops = [op for op in session.pending_operations if isinstance(op, SupervisionMailOp)] - self.assertEquals(len(sentops), 1) + self.assertEqual(len(sentops), 1) # check view content op = sentops[0] view = sentops[0]._get_view() - self.assertEquals(view.recipients(), ['test@logilab.fr']) - self.assertEquals(view.subject(), '[data supervision] changes summary') + self.assertEqual(view.recipients(), ['test@logilab.fr']) + self.assertEqual(view.subject(), '[data supervision] changes summary') data = view.render(changes=session.transaction_data.get('pendingchanges')).strip() data = re.sub('#\d+', '#EID', data) data = re.sub('/\d+', '/EID', data) - self.assertTextEquals('''user admin has made the following change(s): + self.assertMultiLineEqual('''user admin has made the following change(s): * added cwuser #EID (toto) http://testing.fr/cubicweb/cwuser/toto @@ -79,22 +79,22 @@ data) # check prepared email op._prepare_email() - self.assertEquals(len(op.to_send), 1) + self.assertEqual(len(op.to_send), 1) self.assert_(op.to_send[0][0]) - self.assertEquals(op.to_send[0][1], ['test@logilab.fr']) + self.assertEqual(op.to_send[0][1], ['test@logilab.fr']) self.commit() # some other changes ####### user.cw_adapt_to('IWorkflowable').fire_transition('deactivate') sentops = [op for op in session.pending_operations if isinstance(op, SupervisionMailOp)] - self.assertEquals(len(sentops), 1) + self.assertEqual(len(sentops), 1) # check view content op = sentops[0] view = sentops[0]._get_view() data = view.render(changes=session.transaction_data.get('pendingchanges')).strip() data = re.sub('#\d+', '#EID', data) data = re.sub('/\d+', '/EID', data) - self.assertTextEquals('''user admin has made the following change(s): + self.assertMultiLineEqual('''user admin has made the following change(s): * changed state of cwuser #EID (toto) from state activated to state deactivated diff -r e3994fcc21c3 -r 1806148d6ce8 test/data/cubes/email/entities.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/data/cubes/email/entities.py Wed Sep 29 16:16:32 2010 +0200 @@ -0,0 +1,1 @@ +"test" diff -r e3994fcc21c3 -r 1806148d6ce8 test/data/cubes/email/hooks.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/data/cubes/email/hooks.py Wed Sep 29 16:16:32 2010 +0200 @@ -0,0 +1,1 @@ +"test" diff -r e3994fcc21c3 -r 1806148d6ce8 test/data/cubes/email/views/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/data/cubes/email/views/__init__.py Wed Sep 29 16:16:32 2010 +0200 @@ -0,0 +1,1 @@ +"test" diff -r e3994fcc21c3 -r 1806148d6ce8 test/data/cubes/file/entities/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/data/cubes/file/entities/__init__.py Wed Sep 29 16:16:32 2010 +0200 @@ -0,0 +1,1 @@ +"test" diff -r e3994fcc21c3 -r 1806148d6ce8 test/data/cubes/file/hooks/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/data/cubes/file/hooks/__init__.py Wed Sep 29 16:16:32 2010 +0200 @@ -0,0 +1,1 @@ +"test" diff -r e3994fcc21c3 -r 1806148d6ce8 test/data/cubes/file/views.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/data/cubes/file/views.py Wed Sep 29 16:16:32 2010 +0200 @@ -0,0 +1,1 @@ +"test" diff -r e3994fcc21c3 -r 1806148d6ce8 test/data/rewrite/bootstrap_cubes --- a/test/data/rewrite/bootstrap_cubes Thu Sep 23 23:28:58 2010 +0200 +++ b/test/data/rewrite/bootstrap_cubes Wed Sep 29 16:16:32 2010 +0200 @@ -1,1 +1,1 @@ -card, person +card diff -r e3994fcc21c3 -r 1806148d6ce8 test/data/rewrite/schema.py --- a/test/data/rewrite/schema.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/data/rewrite/schema.py Wed Sep 29 16:16:32 2010 +0200 @@ -49,7 +49,7 @@ class require_permission(RelationDefinition): - subject = ('Card', 'Note', 'Person') + subject = ('Card', 'Note') object = 'CWPermission' diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_cwconfig.py --- a/test/unittest_cwconfig.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_cwconfig.py Wed Sep 29 16:16:32 2010 +0200 @@ -54,17 +54,17 @@ self.config.adjust_sys_path() # forge depends on email and file and comment # email depends on file - self.assertEquals(self.config.reorder_cubes(['file', 'email', 'forge']), + self.assertEqual(self.config.reorder_cubes(['file', 'email', 'forge']), ('forge', 'email', 'file')) - self.assertEquals(self.config.reorder_cubes(['email', 'file', 'forge']), + self.assertEqual(self.config.reorder_cubes(['email', 'file', 'forge']), ('forge', 'email', 'file')) - self.assertEquals(self.config.reorder_cubes(['email', 'forge', 'file']), + self.assertEqual(self.config.reorder_cubes(['email', 'forge', 'file']), ('forge', 'email', 'file')) - self.assertEquals(self.config.reorder_cubes(['file', 'forge', 'email']), + self.assertEqual(self.config.reorder_cubes(['file', 'forge', 'email']), ('forge', 'email', 'file')) - self.assertEquals(self.config.reorder_cubes(['forge', 'file', 'email']), + self.assertEqual(self.config.reorder_cubes(['forge', 'file', 'email']), ('forge', 'email', 'file')) - self.assertEquals(self.config.reorder_cubes(('forge', 'email', 'file')), + self.assertEqual(self.config.reorder_cubes(('forge', 'email', 'file')), ('forge', 'email', 'file')) def test_reorder_cubes_recommends(self): @@ -75,13 +75,13 @@ try: # email recommends comment # comment recommends file - self.assertEquals(self.config.reorder_cubes(('forge', 'email', 'file', 'comment')), + self.assertEqual(self.config.reorder_cubes(('forge', 'email', 'file', 'comment')), ('forge', 'email', 'comment', 'file')) - self.assertEquals(self.config.reorder_cubes(('forge', 'email', 'comment', 'file')), + self.assertEqual(self.config.reorder_cubes(('forge', 'email', 'comment', 'file')), ('forge', 'email', 'comment', 'file')) - self.assertEquals(self.config.reorder_cubes(('forge', 'comment', 'email', 'file')), + self.assertEqual(self.config.reorder_cubes(('forge', 'comment', 'email', 'file')), ('forge', 'email', 'comment', 'file')) - self.assertEquals(self.config.reorder_cubes(('comment', 'forge', 'email', 'file')), + self.assertEqual(self.config.reorder_cubes(('comment', 'forge', 'email', 'file')), ('forge', 'email', 'comment', 'file')) finally: comment_pkginfo.__recommends_cubes__ = {} @@ -90,19 +90,23 @@ # def test_vc_config(self): # vcconf = self.config.vc_config() # self.assertIsInstance(vcconf['EEMAIL'], Version) -# self.assertEquals(vcconf['EEMAIL'], (0, 3, 1)) -# self.assertEquals(vcconf['CW'], (2, 31, 2)) +# self.assertEqual(vcconf['EEMAIL'], (0, 3, 1)) +# self.assertEqual(vcconf['CW'], (2, 31, 2)) # self.assertRaises(KeyError, vcconf.__getitem__, 'CW_VERSION') # self.assertRaises(KeyError, vcconf.__getitem__, 'CRM') def test_expand_cubes(self): - self.assertEquals(self.config.expand_cubes(('email', 'blog')), + self.config.__class__.CUBES_PATH = [CUSTOM_CUBES_DIR] + self.config.adjust_sys_path() + self.assertEqual(self.config.expand_cubes(('email', 'blog')), ['email', 'blog', 'file']) def test_vregistry_path(self): - self.assertEquals([unabsolutize(p) for p in self.config.vregistry_path()], + self.config.__class__.CUBES_PATH = [CUSTOM_CUBES_DIR] + self.config.adjust_sys_path() + self.assertEqual([unabsolutize(p) for p in self.config.vregistry_path()], ['entities', 'web/views', 'sobjects', 'hooks', - 'file/entities.py', 'file/views', 'file/hooks.py', + 'file/entities', 'file/views.py', 'file/hooks', 'email/entities.py', 'email/views', 'email/hooks.py', 'test/data/entities.py', 'test/data/views.py']) @@ -111,27 +115,27 @@ import email self.assertNotEquals(dirname(email.__file__), self.config.CUBES_DIR) self.config.__class__.CUBES_PATH = [CUSTOM_CUBES_DIR] - self.assertEquals(self.config.cubes_search_path(), + self.assertEqual(self.config.cubes_search_path(), [CUSTOM_CUBES_DIR, self.config.CUBES_DIR]) self.config.__class__.CUBES_PATH = [CUSTOM_CUBES_DIR, self.config.CUBES_DIR, 'unexistant'] # filter out unexistant and duplicates - self.assertEquals(self.config.cubes_search_path(), + self.assertEqual(self.config.cubes_search_path(), [CUSTOM_CUBES_DIR, self.config.CUBES_DIR]) self.failUnless('mycube' in self.config.available_cubes()) # test cubes python path self.config.adjust_sys_path() import cubes - self.assertEquals(cubes.__path__, self.config.cubes_search_path()) + self.assertEqual(cubes.__path__, self.config.cubes_search_path()) # this import should succeed once path is adjusted from cubes import mycube - self.assertEquals(mycube.__path__, [join(CUSTOM_CUBES_DIR, 'mycube')]) + self.assertEqual(mycube.__path__, [join(CUSTOM_CUBES_DIR, 'mycube')]) # file cube should be overriden by the one found in data/cubes sys.modules.pop('cubes.file', None) del cubes.file from cubes import file - self.assertEquals(file.__path__, [join(CUSTOM_CUBES_DIR, 'file')]) + self.assertEqual(file.__path__, [join(CUSTOM_CUBES_DIR, 'file')]) class FindPrefixTC(TestCase): @@ -153,35 +157,35 @@ def test_samedir(self): prefix = tempfile.tempdir self.make_dirs('share', 'cubicweb') - self.assertEquals(_find_prefix(prefix), prefix) + self.assertEqual(_find_prefix(prefix), prefix) @with_tempdir def test_samedir_filepath(self): prefix = tempfile.tempdir self.make_dirs('share', 'cubicweb') file_path = self.make_file('bob.py') - self.assertEquals(_find_prefix(file_path), prefix) + self.assertEqual(_find_prefix(file_path), prefix) @with_tempdir def test_dir_inside_prefix(self): prefix = tempfile.tempdir self.make_dirs('share', 'cubicweb') dir_path = self.make_dirs('bob') - self.assertEquals(_find_prefix(dir_path), prefix) + self.assertEqual(_find_prefix(dir_path), prefix) @with_tempdir def test_file_in_dir_inside_prefix(self): prefix = tempfile.tempdir self.make_dirs('share', 'cubicweb') file_path = self.make_file('bob', 'toto.py') - self.assertEquals(_find_prefix(file_path), prefix) + self.assertEqual(_find_prefix(file_path), prefix) @with_tempdir def test_file_in_deeper_dir_inside_prefix(self): prefix = tempfile.tempdir self.make_dirs('share', 'cubicweb') file_path = self.make_file('bob', 'pyves', 'alain', 'adim', 'syt', 'toto.py') - self.assertEquals(_find_prefix(file_path), prefix) + self.assertEqual(_find_prefix(file_path), prefix) @with_tempdir def test_multiple_candidate_prefix(self): @@ -189,7 +193,7 @@ prefix = self.make_dirs('bob') self.make_dirs('bob', 'share', 'cubicweb') file_path = self.make_file('bob', 'pyves', 'alain', 'adim', 'syt', 'toto.py') - self.assertEquals(_find_prefix(file_path), prefix) + self.assertEqual(_find_prefix(file_path), prefix) @with_tempdir def test_sister_candidate_prefix(self): @@ -197,7 +201,7 @@ self.make_dirs('share', 'cubicweb') self.make_dirs('bob', 'share', 'cubicweb') file_path = self.make_file('bell', 'toto.py') - self.assertEquals(_find_prefix(file_path), prefix) + self.assertEqual(_find_prefix(file_path), prefix) @with_tempdir def test_multiple_parent_candidate_prefix(self): @@ -205,7 +209,7 @@ prefix = self.make_dirs('share', 'cubicweb', 'bob') self.make_dirs('share', 'cubicweb', 'bob', 'share', 'cubicweb') file_path = self.make_file('share', 'cubicweb', 'bob', 'pyves', 'alain', 'adim', 'syt', 'toto.py') - self.assertEquals(_find_prefix(file_path), prefix) + self.assertEqual(_find_prefix(file_path), prefix) @with_tempdir def test_upper_candidate_prefix(self): @@ -213,12 +217,12 @@ self.make_dirs('share', 'cubicweb') self.make_dirs('bell','bob', 'share', 'cubicweb') file_path = self.make_file('bell', 'toto.py') - self.assertEquals(_find_prefix(file_path), prefix) + self.assertEqual(_find_prefix(file_path), prefix) @with_tempdir def test_no_prefix(self): prefix = tempfile.tempdir - self.assertEquals(_find_prefix(prefix), sys.prefix) + self.assertEqual(_find_prefix(prefix), sys.prefix) if __name__ == '__main__': unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_dbapi.py --- a/test/unittest_dbapi.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_dbapi.py Wed Sep 29 16:16:32 2010 +0200 @@ -29,40 +29,40 @@ def test_public_repo_api(self): cnx = self.login('anon') - self.assertEquals(cnx.get_schema(), self.repo.schema) - self.assertEquals(cnx.source_defs(), {'system': {'adapter': 'native', 'uri': 'system'}}) + self.assertEqual(cnx.get_schema(), self.repo.schema) + self.assertEqual(cnx.source_defs(), {'system': {'adapter': 'native', 'uri': 'system'}}) self.restore_connection() # proper way to close cnx self.assertRaises(ProgrammingError, cnx.get_schema) self.assertRaises(ProgrammingError, cnx.source_defs) def test_db_api(self): cnx = self.login('anon') - self.assertEquals(cnx.rollback(), None) - self.assertEquals(cnx.commit(), None) + self.assertEqual(cnx.rollback(), None) + self.assertEqual(cnx.commit(), None) self.restore_connection() # proper way to close cnx - #self.assertEquals(cnx.close(), None) + #self.assertEqual(cnx.close(), None) self.assertRaises(ProgrammingError, cnx.rollback) self.assertRaises(ProgrammingError, cnx.commit) self.assertRaises(ProgrammingError, cnx.close) def test_api(self): cnx = self.login('anon') - self.assertEquals(cnx.user(None).login, 'anon') - self.assertEquals(cnx.describe(1), (u'CWGroup', u'system', None)) + self.assertEqual(cnx.user(None).login, 'anon') + self.assertEqual(cnx.describe(1), (u'CWGroup', u'system', None)) self.restore_connection() # proper way to close cnx self.assertRaises(ProgrammingError, cnx.user, None) self.assertRaises(ProgrammingError, cnx.describe, 1) def test_shared_data_api(self): cnx = self.login('anon') - self.assertEquals(cnx.get_shared_data('data'), None) + self.assertEqual(cnx.get_shared_data('data'), None) cnx.set_shared_data('data', 4) - self.assertEquals(cnx.get_shared_data('data'), 4) + self.assertEqual(cnx.get_shared_data('data'), 4) cnx.get_shared_data('data', pop=True) cnx.get_shared_data('whatever', pop=True) - self.assertEquals(cnx.get_shared_data('data'), None) + self.assertEqual(cnx.get_shared_data('data'), None) cnx.set_shared_data('data', 4) - self.assertEquals(cnx.get_shared_data('data'), 4) + self.assertEqual(cnx.get_shared_data('data'), 4) self.restore_connection() # proper way to close cnx self.assertRaises(ProgrammingError, cnx.check) self.assertRaises(ProgrammingError, cnx.set_shared_data, 'data', 0) diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_entity.py --- a/test/unittest_entity.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_entity.py Wed Sep 29 16:16:32 2010 +0200 @@ -40,14 +40,14 @@ def test_has_eid(self): e = self.vreg['etypes'].etype_class('CWUser')(self.request()) - self.assertEquals(e.eid, None) - self.assertEquals(e.has_eid(), False) + self.assertEqual(e.eid, None) + self.assertEqual(e.has_eid(), False) e.eid = 'X' - self.assertEquals(e.has_eid(), False) + self.assertEqual(e.has_eid(), False) e.eid = 0 - self.assertEquals(e.has_eid(), True) + self.assertEqual(e.has_eid(), True) e.eid = 2 - self.assertEquals(e.has_eid(), True) + self.assertEqual(e.has_eid(), True) def test_copy(self): req = self.request() @@ -59,11 +59,11 @@ self.execute('SET TAG tags X WHERE X eid %(x)s', {'x': oe.eid}) e = req.create_entity('Note', type=u'z') e.copy_relations(oe.eid) - self.assertEquals(len(e.ecrit_par), 1) - self.assertEquals(e.ecrit_par[0].eid, p.eid) - self.assertEquals(len(e.reverse_tags), 1) + self.assertEqual(len(e.ecrit_par), 1) + self.assertEqual(e.ecrit_par[0].eid, p.eid) + self.assertEqual(len(e.reverse_tags), 1) # check meta-relations are not copied, set on commit - self.assertEquals(len(e.created_by), 0) + self.assertEqual(len(e.created_by), 0) def test_copy_with_nonmeta_composite_inlined(self): req = self.request() @@ -81,8 +81,8 @@ user = self.user() adeleid = self.execute('INSERT EmailAddress X: X address "toto@logilab.org", U use_email X WHERE U login "admin"')[0][0] e = self.execute('Any X WHERE X eid %(x)s', {'x': user.eid}).get_entity(0, 0) - self.assertEquals(e.use_email[0].address, "toto@logilab.org") - self.assertEquals(e.use_email[0].eid, adeleid) + self.assertEqual(e.use_email[0].address, "toto@logilab.org") + self.assertEqual(e.use_email[0].eid, adeleid) usereid = self.execute('INSERT CWUser X: X login "toto", X upassword "toto", X in_group G ' 'WHERE G name "users"')[0][0] e = self.execute('Any X WHERE X eid %(x)s', {'x': usereid}).get_entity(0, 0) @@ -102,18 +102,18 @@ e.copy_relations(user.eid) self.commit() e.cw_clear_relation_cache('in_state', 'subject') - self.assertEquals(e.cw_adapt_to('IWorkflowable').state, 'activated') + self.assertEqual(e.cw_adapt_to('IWorkflowable').state, 'activated') def test_related_cache_both(self): user = self.execute('Any X WHERE X eid %(x)s', {'x':self.user().eid}).get_entity(0, 0) adeleid = self.execute('INSERT EmailAddress X: X address "toto@logilab.org", U use_email X WHERE U login "admin"')[0][0] self.commit() - self.assertEquals(user._cw_related_cache, {}) + self.assertEqual(user._cw_related_cache, {}) email = user.primary_email[0] - self.assertEquals(sorted(user._cw_related_cache), ['primary_email_subject']) - self.assertEquals(email._cw_related_cache.keys(), ['primary_email_object']) + self.assertEqual(sorted(user._cw_related_cache), ['primary_email_subject']) + self.assertEqual(email._cw_related_cache.keys(), ['primary_email_object']) groups = user.in_group - self.assertEquals(sorted(user._cw_related_cache), ['in_group_subject', 'primary_email_subject']) + self.assertEqual(sorted(user._cw_related_cache), ['in_group_subject', 'primary_email_subject']) for group in groups: self.failIf('in_group_subject' in group._cw_related_cache, group._cw_related_cache.keys()) @@ -123,8 +123,8 @@ for tag in u'abcd': req.create_entity('Tag', name=tag) self.execute('SET X tags Y WHERE X is Tag, Y is Personne') - self.assertEquals(len(p.related('tags', 'object', limit=2)), 2) - self.assertEquals(len(p.related('tags', 'object')), 4) + self.assertEqual(len(p.related('tags', 'object', limit=2)), 2) + self.assertEqual(len(p.related('tags', 'object')), 4) def test_fetch_rql(self): @@ -139,7 +139,7 @@ peschema.subjrels['evaluee'].rdef(peschema, Note.e_schema).cardinality = '1*' seschema.subjrels['evaluee'].rdef(seschema, Note.e_schema).cardinality = '1*' # testing basic fetch_attrs attribute - self.assertEquals(Personne.fetch_rql(user), + self.assertEqual(Personne.fetch_rql(user), 'Any X,AA,AB,AC ORDERBY AA ASC ' 'WHERE X is Personne, X nom AA, X prenom AB, X modification_date AC') pfetch_attrs = Personne.fetch_attrs @@ -147,39 +147,39 @@ try: # testing unknown attributes Personne.fetch_attrs = ('bloug', 'beep') - self.assertEquals(Personne.fetch_rql(user), 'Any X WHERE X is Personne') + self.assertEqual(Personne.fetch_rql(user), 'Any X WHERE X is Personne') # testing one non final relation Personne.fetch_attrs = ('nom', 'prenom', 'travaille') - self.assertEquals(Personne.fetch_rql(user), + self.assertEqual(Personne.fetch_rql(user), 'Any X,AA,AB,AC,AD ORDERBY AA ASC ' 'WHERE X is Personne, X nom AA, X prenom AB, X travaille AC?, AC nom AD') # testing two non final relations Personne.fetch_attrs = ('nom', 'prenom', 'travaille', 'evaluee') - self.assertEquals(Personne.fetch_rql(user), + self.assertEqual(Personne.fetch_rql(user), 'Any X,AA,AB,AC,AD,AE,AF ORDERBY AA ASC,AF DESC ' 'WHERE X is Personne, X nom AA, X prenom AB, X travaille AC?, AC nom AD, ' 'X evaluee AE?, AE modification_date AF') # testing one non final relation with recursion Personne.fetch_attrs = ('nom', 'prenom', 'travaille') Societe.fetch_attrs = ('nom', 'evaluee') - self.assertEquals(Personne.fetch_rql(user), + self.assertEqual(Personne.fetch_rql(user), 'Any X,AA,AB,AC,AD,AE,AF ORDERBY AA ASC,AF DESC ' 'WHERE X is Personne, X nom AA, X prenom AB, X travaille AC?, AC nom AD, ' 'AC evaluee AE?, AE modification_date AF' ) # testing symmetric relation Personne.fetch_attrs = ('nom', 'connait') - self.assertEquals(Personne.fetch_rql(user), 'Any X,AA,AB ORDERBY AA ASC ' + self.assertEqual(Personne.fetch_rql(user), 'Any X,AA,AB ORDERBY AA ASC ' 'WHERE X is Personne, X nom AA, X connait AB?') # testing optional relation peschema.subjrels['travaille'].rdef(peschema, seschema).cardinality = '?*' Personne.fetch_attrs = ('nom', 'prenom', 'travaille') Societe.fetch_attrs = ('nom',) - self.assertEquals(Personne.fetch_rql(user), + self.assertEqual(Personne.fetch_rql(user), 'Any X,AA,AB,AC,AD ORDERBY AA ASC WHERE X is Personne, X nom AA, X prenom AB, X travaille AC?, AC nom AD') # testing relation with cardinality > 1 peschema.subjrels['travaille'].rdef(peschema, seschema).cardinality = '**' - self.assertEquals(Personne.fetch_rql(user), + self.assertEqual(Personne.fetch_rql(user), 'Any X,AA,AB ORDERBY AA ASC WHERE X is Personne, X nom AA, X prenom AB') # XXX test unauthorized attribute finally: @@ -195,20 +195,20 @@ Note.fetch_attrs, Note.fetch_order = fetch_config(('type',)) SubNote.fetch_attrs, SubNote.fetch_order = fetch_config(('type',)) p = self.request().create_entity('Personne', nom=u'pouet') - self.assertEquals(p.cw_related_rql('evaluee'), + self.assertEqual(p.cw_related_rql('evaluee'), 'Any X,AA,AB ORDERBY AA ASC WHERE E eid %(x)s, E evaluee X, ' 'X type AA, X modification_date AB') Personne.fetch_attrs, Personne.fetch_order = fetch_config(('nom', )) # XXX - self.assertEquals(p.cw_related_rql('evaluee'), + self.assertEqual(p.cw_related_rql('evaluee'), 'Any X,AA ORDERBY AA DESC ' 'WHERE E eid %(x)s, E evaluee X, X modification_date AA') tag = self.vreg['etypes'].etype_class('Tag')(self.request()) - self.assertEquals(tag.cw_related_rql('tags', 'subject'), + self.assertEqual(tag.cw_related_rql('tags', 'subject'), 'Any X,AA ORDERBY AA DESC ' 'WHERE E eid %(x)s, E tags X, X modification_date AA') - self.assertEquals(tag.cw_related_rql('tags', 'subject', ('Personne',)), + self.assertEqual(tag.cw_related_rql('tags', 'subject', ('Personne',)), 'Any X,AA,AB ORDERBY AA ASC ' 'WHERE E eid %(x)s, E tags X, X is IN (Personne), X nom AA, ' 'X modification_date AB') @@ -217,20 +217,20 @@ tag = self.vreg['etypes'].etype_class('Tag')(self.request()) for ttype in self.schema['tags'].objects(): self.vreg['etypes'].etype_class(ttype).fetch_attrs = ('modification_date',) - self.assertEquals(tag.cw_related_rql('tags', 'subject'), + self.assertEqual(tag.cw_related_rql('tags', 'subject'), 'Any X,AA ORDERBY AA DESC ' 'WHERE E eid %(x)s, E tags X, X modification_date AA') def test_unrelated_rql_security_1(self): user = self.request().user rql = user.cw_unrelated_rql('use_email', 'EmailAddress', 'subject')[0] - self.assertEquals(rql, 'Any O,AA,AB,AC ORDERBY AC DESC ' + self.assertEqual(rql, 'Any O,AA,AB,AC ORDERBY AC DESC ' 'WHERE NOT S use_email O, S eid %(x)s, O is EmailAddress, O address AA, O alias AB, O modification_date AC') self.create_user('toto') self.login('toto') user = self.request().user rql = user.cw_unrelated_rql('use_email', 'EmailAddress', 'subject')[0] - self.assertEquals(rql, 'Any O,AA,AB,AC ORDERBY AC DESC ' + self.assertEqual(rql, 'Any O,AA,AB,AC ORDERBY AC DESC ' 'WHERE NOT S use_email O, S eid %(x)s, O is EmailAddress, O address AA, O alias AB, O modification_date AC') user = self.execute('Any X WHERE X login "admin"').get_entity(0, 0) self.assertRaises(Unauthorized, user.cw_unrelated_rql, 'use_email', 'EmailAddress', 'subject') @@ -241,24 +241,24 @@ def test_unrelated_rql_security_2(self): email = self.execute('INSERT EmailAddress X: X address "hop"').get_entity(0, 0) rql = email.cw_unrelated_rql('use_email', 'CWUser', 'object')[0] - self.assertEquals(rql, 'Any S,AA,AB,AC,AD ORDERBY AA ASC ' + self.assertEqual(rql, 'Any S,AA,AB,AC,AD ORDERBY AA ASC ' 'WHERE NOT S use_email O, O eid %(x)s, S is CWUser, S login AA, S firstname AB, S surname AC, S modification_date AD') #rql = email.cw_unrelated_rql('use_email', 'Person', 'object')[0] - #self.assertEquals(rql, '') + #self.assertEqual(rql, '') self.login('anon') email = self.execute('Any X WHERE X eid %(x)s', {'x': email.eid}).get_entity(0, 0) rql = email.cw_unrelated_rql('use_email', 'CWUser', 'object')[0] - self.assertEquals(rql, 'Any S,AA,AB,AC,AD ORDERBY AA ' + self.assertEqual(rql, 'Any S,AA,AB,AC,AD ORDERBY AA ' 'WHERE NOT EXISTS(S use_email O), O eid %(x)s, S is CWUser, S login AA, S firstname AB, S surname AC, S modification_date AD, ' 'A eid %(B)s, EXISTS(S identity A, NOT A in_group C, C name "guests", C is CWGroup)') #rql = email.cw_unrelated_rql('use_email', 'Person', 'object')[0] - #self.assertEquals(rql, '') + #self.assertEqual(rql, '') def test_unrelated_rql_security_nonexistant(self): self.login('anon') email = self.vreg['etypes'].etype_class('EmailAddress')(self.request()) rql = email.cw_unrelated_rql('use_email', 'CWUser', 'object')[0] - self.assertEquals(rql, 'Any S,AA,AB,AC,AD ORDERBY AA ' + self.assertEqual(rql, 'Any S,AA,AB,AC,AD ORDERBY AA ' 'WHERE S is CWUser, S login AA, S firstname AB, S surname AC, S modification_date AD, ' 'A eid %(B)s, EXISTS(S identity A, NOT A in_group C, C name "guests", C is CWGroup)') @@ -280,53 +280,53 @@ e = req.create_entity('Tag', name=u'x') req.create_entity('Personne', nom=u'di mascio', prenom=u'adrien') req.create_entity('Personne', nom=u'thenault', prenom=u'sylvain') - self.assertEquals(len(e.unrelated('tags', 'Personne', 'subject', limit=1)), + self.assertEqual(len(e.unrelated('tags', 'Personne', 'subject', limit=1)), 1) def test_unrelated_security(self): email = self.execute('INSERT EmailAddress X: X address "hop"').get_entity(0, 0) rset = email.unrelated('use_email', 'CWUser', 'object') - self.assertEquals([x.login for x in rset.entities()], [u'admin', u'anon']) + self.assertEqual([x.login for x in rset.entities()], [u'admin', u'anon']) user = self.request().user rset = user.unrelated('use_email', 'EmailAddress', 'subject') - self.assertEquals([x.address for x in rset.entities()], [u'hop']) + self.assertEqual([x.address for x in rset.entities()], [u'hop']) self.create_user('toto') self.login('toto') email = self.execute('Any X WHERE X eid %(x)s', {'x': email.eid}).get_entity(0, 0) rset = email.unrelated('use_email', 'CWUser', 'object') - self.assertEquals([x.login for x in rset.entities()], ['toto']) + self.assertEqual([x.login for x in rset.entities()], ['toto']) user = self.request().user rset = user.unrelated('use_email', 'EmailAddress', 'subject') - self.assertEquals([x.address for x in rset.entities()], ['hop']) + self.assertEqual([x.address for x in rset.entities()], ['hop']) user = self.execute('Any X WHERE X login "admin"').get_entity(0, 0) rset = user.unrelated('use_email', 'EmailAddress', 'subject') - self.assertEquals([x.address for x in rset.entities()], []) + self.assertEqual([x.address for x in rset.entities()], []) self.login('anon') email = self.execute('Any X WHERE X eid %(x)s', {'x': email.eid}).get_entity(0, 0) rset = email.unrelated('use_email', 'CWUser', 'object') - self.assertEquals([x.login for x in rset.entities()], []) + self.assertEqual([x.login for x in rset.entities()], []) user = self.request().user rset = user.unrelated('use_email', 'EmailAddress', 'subject') - self.assertEquals([x.address for x in rset.entities()], []) + self.assertEqual([x.address for x in rset.entities()], []) def test_unrelated_new_entity(self): e = self.vreg['etypes'].etype_class('CWUser')(self.request()) unrelated = [r[0] for r in e.unrelated('in_group', 'CWGroup', 'subject')] # should be default groups but owners, i.e. managers, users, guests - self.assertEquals(len(unrelated), 3) + self.assertEqual(len(unrelated), 3) def test_printable_value_string(self): e = self.request().create_entity('Card', title=u'rest test', content=u'du :eid:`1:*ReST*`', content_format=u'text/rest') - self.assertEquals(e.printable_value('content'), + self.assertEqual(e.printable_value('content'), '

du *ReST*

\n') e.cw_attr_cache['content'] = 'du html users' e.cw_attr_cache['content_format'] = 'text/html' - self.assertEquals(e.printable_value('content'), + self.assertEqual(e.printable_value('content'), 'du html users') e.cw_attr_cache['content'] = 'du *texte*' e.cw_attr_cache['content_format'] = 'text/plain' - self.assertEquals(e.printable_value('content'), + self.assertEqual(e.printable_value('content'), '

\ndu *texte*
\n

') e.cw_attr_cache['title'] = 'zou' e.cw_attr_cache['content'] = '''\ @@ -334,17 +334,16 @@ ======= du :eid:`1:*ReST*`''' e.cw_attr_cache['content_format'] = 'text/rest' - self.assertEquals(e.printable_value('content', format='text/plain'), + self.assertEqual(e.printable_value('content', format='text/plain'), e.cw_attr_cache['content']) e.cw_attr_cache['content'] = u'yo (zou éà ;)' e.cw_attr_cache['content_format'] = 'text/html' - self.assertEquals(e.printable_value('content', format='text/plain').strip(), - u'**yo (zou éà ;)**') + self.assertEqual(e.printable_value('content', format='text/plain').strip(), if HAS_TAL: e.cw_attr_cache['content'] = '

titre

' e.cw_attr_cache['content_format'] = 'text/cubicweb-page-template' - self.assertEquals(e.printable_value('content'), + self.assertEqual(e.printable_value('content'), '

zou

') @@ -356,17 +355,17 @@ if mttransforms.HAS_PYGMENTS_TRANSFORMS: import pygments if tuple(int(i) for i in pygments.__version__.split('.')[:2]) >= (1, 3): - self.assertEquals(e.printable_value('data'), + self.assertEqual(e.printable_value('data'), '''
lambda x: 1
 
''') else: - self.assertEquals(e.printable_value('data'), + self.assertEqual(e.printable_value('data'), '''
lambda x: 1
 
''') else: - self.assertEquals(e.printable_value('data'), + self.assertEqual(e.printable_value('data'), '''
 lambda x: 1
 
@@ -374,7 +373,7 @@ e = req.create_entity('File', data=Binary('*héhéhé*'), data_format=u'text/rest', data_encoding=u'utf-8', data_name=u'toto.txt') - self.assertEquals(e.printable_value('data'), + self.assertEqual(e.printable_value('data'), u'

héhéhé

\n') def test_printable_value_bad_html(self): @@ -383,42 +382,43 @@ e = req.create_entity('Card', title=u'bad html', content=u'
R&D
', content_format=u'text/html') tidy = lambda x: x.replace('\n', '') - self.assertEquals(tidy(e.printable_value('content')), + self.assertEqual(tidy(e.printable_value('content')), '
R&D
') e.cw_attr_cache['content'] = u'yo !! R&D
pas fermé' - self.assertEquals(tidy(e.printable_value('content')), + self.assertEqual(tidy(e.printable_value('content')), u'yo !! R&D
pas fermé
') e.cw_attr_cache['content'] = u'R&D' - self.assertEquals(tidy(e.printable_value('content')), u'R&D') + self.assertEqual(tidy(e.printable_value('content')), u'R&D') e.cw_attr_cache['content'] = u'R&D;' - self.assertEquals(tidy(e.printable_value('content')), u'R&D;') + self.assertEqual(tidy(e.printable_value('content')), u'R&D;') e.cw_attr_cache['content'] = u'yo !! R&D
pas fermé' - self.assertEquals(tidy(e.printable_value('content')), + self.assertEqual(tidy(e.printable_value('content')), u'yo !! R&D
pas fermé
') e.cw_attr_cache['content'] = u'été
été' - self.assertEquals(tidy(e.printable_value('content')), - u'été
été
') + self.assertEqual(tidy(e.printable_value('content')), e.cw_attr_cache['content'] = u'C'est un exemple sérieux' - self.assertEquals(tidy(e.printable_value('content')), + self.assertEqual(tidy(e.printable_value('content')), + e['content'] = u'C'est un exemple sérieux' + self.assertEqual(tidy(e.printable_value('content')), u"C'est un exemple sérieux") # make sure valid xhtml is left untouched e.cw_attr_cache['content'] = u'
R&D
' - self.assertEquals(e.printable_value('content'), e.cw_attr_cache['content']) + self.assertEqual(e.printable_value('content'), e.cw_attr_cache['content']) e.cw_attr_cache['content'] = u'
été
' - self.assertEquals(e.printable_value('content'), e.cw_attr_cache['content']) + self.assertEqual(e.printable_value('content'), e.cw_attr_cache['content']) e.cw_attr_cache['content'] = u'été' - self.assertEquals(e.printable_value('content'), e.cw_attr_cache['content']) + self.assertEqual(e.printable_value('content'), e.cw_attr_cache['content']) e.cw_attr_cache['content'] = u'hop\r\nhop\nhip\rmomo' - self.assertEquals(e.printable_value('content'), u'hop\nhop\nhip\nmomo') + self.assertEqual(e.printable_value('content'), u'hop\nhop\nhip\nmomo') def test_printable_value_bad_html_ms(self): - self.skip('fix soup2xhtml to handle this test') + self.skipTest('fix soup2xhtml to handle this test') req = self.request() e = req.create_entity('Card', title=u'bad html', content=u'
R&D
', content_format=u'text/html') tidy = lambda x: x.replace('\n', '') e.cw_attr_cache['content'] = u'
ms orifice produces weird html
' - self.assertEquals(tidy(e.printable_value('content')), + self.assertEqual(tidy(e.printable_value('content')), u'
ms orifice produces weird html
') import tidy as tidymod # apt-get install python-tidy tidy = lambda x: str(tidymod.parseString(x.encode('utf-8'), @@ -427,7 +427,7 @@ 'show_body_only' : True, 'quote-nbsp' : False, 'char_encoding' : 'utf8'})).decode('utf-8').strip() - self.assertEquals(tidy(e.printable_value('content')), + self.assertEqual(tidy(e.printable_value('content')), u'
ms orifice produces weird html
') @@ -440,7 +440,7 @@ e.cw_attr_cache['data_format'] = 'text/html' e.cw_attr_cache['data_encoding'] = 'ascii' e._cw.transaction_data = {} # XXX req should be a session - self.assertEquals(e.cw_adapt_to('IFTIndexable').get_words(), + self.assertEqual(e.cw_adapt_to('IFTIndexable').get_words(), {'C': [u'du', u'html', 'an', 'html', 'file', u'some', u'data']}) @@ -449,7 +449,7 @@ p1 = req.create_entity('Personne', nom=u'di mascio', prenom=u'adrien') p2 = req.create_entity('Personne', nom=u'toto') self.execute('SET X evaluee Y WHERE X nom "di mascio", Y nom "toto"') - self.assertEquals(p1.evaluee[0].nom, "toto") + self.assertEqual(p1.evaluee[0].nom, "toto") self.failUnless(not p1.reverse_evaluee) def test_complete_relation(self): @@ -463,7 +463,7 @@ self.failUnless(trinfo.cw_relation_cached('from_state', 'subject')) self.failUnless(trinfo.cw_relation_cached('to_state', 'subject')) self.failUnless(trinfo.cw_relation_cached('wf_info_for', 'subject')) - self.assertEquals(trinfo.by_transition, ()) + self.assertEqual(trinfo.by_transition, ()) def test_request_cache(self): req = self.request() @@ -475,55 +475,55 @@ def test_rest_path(self): req = self.request() note = req.create_entity('Note', type=u'z') - self.assertEquals(note.rest_path(), 'note/%s' % note.eid) + self.assertEqual(note.rest_path(), 'note/%s' % note.eid) # unique attr tag = req.create_entity('Tag', name=u'x') - self.assertEquals(tag.rest_path(), 'tag/x') + self.assertEqual(tag.rest_path(), 'tag/x') # test explicit rest_attr person = req.create_entity('Personne', prenom=u'john', nom=u'doe') - self.assertEquals(person.rest_path(), 'personne/doe') + self.assertEqual(person.rest_path(), 'personne/doe') # ambiguity test person2 = req.create_entity('Personne', prenom=u'remi', nom=u'doe') person.clear_all_caches() - self.assertEquals(person.rest_path(), 'personne/eid/%s' % person.eid) - self.assertEquals(person2.rest_path(), 'personne/eid/%s' % person2.eid) + self.assertEqual(person.rest_path(), 'personne/eid/%s' % person.eid) + self.assertEqual(person2.rest_path(), 'personne/eid/%s' % person2.eid) # unique attr with None value (wikiid in this case) card1 = req.create_entity('Card', title=u'hop') - self.assertEquals(card1.rest_path(), 'card/eid/%s' % card1.eid) + self.assertEqual(card1.rest_path(), 'card/eid/%s' % card1.eid) # don't use rest if we have /, ? or & in the path (breaks mod_proxy) card2 = req.create_entity('Card', title=u'pod', wikiid=u'zo/bi') - self.assertEquals(card2.rest_path(), 'card/eid/%d' % card2.eid) + self.assertEqual(card2.rest_path(), 'card/eid/%d' % card2.eid) card3 = req.create_entity('Card', title=u'pod', wikiid=u'zo&bi') - self.assertEquals(card3.rest_path(), 'card/eid/%d' % card3.eid) + self.assertEqual(card3.rest_path(), 'card/eid/%d' % card3.eid) card4 = req.create_entity('Card', title=u'pod', wikiid=u'zo?bi') - self.assertEquals(card4.rest_path(), 'card/eid/%d' % card4.eid) + self.assertEqual(card4.rest_path(), 'card/eid/%d' % card4.eid) def test_set_attributes(self): req = self.request() person = req.create_entity('Personne', nom=u'di mascio', prenom=u'adrien') - self.assertEquals(person.prenom, u'adrien') - self.assertEquals(person.nom, u'di mascio') + self.assertEqual(person.prenom, u'adrien') + self.assertEqual(person.nom, u'di mascio') person.set_attributes(prenom=u'sylvain', nom=u'thénault') person = self.execute('Personne P').get_entity(0, 0) # XXX retreival needed ? - self.assertEquals(person.prenom, u'sylvain') - self.assertEquals(person.nom, u'thénault') + self.assertEqual(person.prenom, u'sylvain') + self.assertEqual(person.nom, u'thénault') def test_metainformation_and_external_absolute_url(self): req = self.request() note = req.create_entity('Note', type=u'z') metainf = note.cw_metainformation() - self.assertEquals(metainf, {'source': {'adapter': 'native', 'uri': 'system'}, 'type': u'Note', 'extid': None}) - self.assertEquals(note.absolute_url(), 'http://testing.fr/cubicweb/note/%s' % note.eid) + self.assertEqual(metainf, {'source': {'adapter': 'native', 'uri': 'system'}, 'type': u'Note', 'extid': None}) + self.assertEqual(note.absolute_url(), 'http://testing.fr/cubicweb/note/%s' % note.eid) metainf['source'] = metainf['source'].copy() metainf['source']['base-url'] = 'http://cubicweb2.com/' metainf['extid'] = 1234 - self.assertEquals(note.absolute_url(), 'http://cubicweb2.com/note/1234') + self.assertEqual(note.absolute_url(), 'http://cubicweb2.com/note/1234') def test_absolute_url_empty_field(self): req = self.request() card = req.create_entity('Card', wikiid=u'', title=u'test') - self.assertEquals(card.absolute_url(), + self.assertEqual(card.absolute_url(), 'http://testing.fr/cubicweb/card/eid/%s' % card.eid) def test_create_entity(self): @@ -535,10 +535,10 @@ p = req.create_entity('Personne', nom=u'di mascio', prenom=u'adrien', connait=p1, evaluee=[p1, p2], reverse_ecrit_par=note) - self.assertEquals(p.nom, 'di mascio') - self.assertEquals([c.nom for c in p.connait], ['fayolle']) - self.assertEquals(sorted([c.nom for c in p.evaluee]), ['campeas', 'fayolle']) - self.assertEquals([c.type for c in p.reverse_ecrit_par], ['z']) + self.assertEqual(p.nom, 'di mascio') + self.assertEqual([c.nom for c in p.connait], ['fayolle']) + self.assertEqual(sorted([c.nom for c in p.evaluee]), ['campeas', 'fayolle']) + self.assertEqual([c.type for c in p.reverse_ecrit_par], ['z']) diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_mail.py --- a/test/unittest_mail.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_mail.py Wed Sep 29 16:16:32 2010 +0200 @@ -51,7 +51,7 @@ mail = format_mail({'name': 'oim', 'email': 'oim@logilab.fr'}, ['test@logilab.fr'], u'un petit cöucou', u'bïjour', config=self.config) - self.assertLinesEquals(mail.as_string(), """\ + self.assertMultiLineEqual(mail.as_string(), """\ MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 @@ -64,17 +64,17 @@ dW4gcGV0aXQgY8O2dWNvdQ== """) msg = message_from_string(mail.as_string()) - self.assertEquals(msg.get('subject'), u'bïjour') - self.assertEquals(msg.get('from'), u'oim ') - self.assertEquals(msg.get('to'), u'test@logilab.fr') - self.assertEquals(msg.get('reply-to'), u'oim , BimBam ') - self.assertEquals(msg.get_payload(decode=True), u'un petit cöucou') + self.assertEqual(msg.get('subject'), u'bïjour') + self.assertEqual(msg.get('from'), u'oim ') + self.assertEqual(msg.get('to'), u'test@logilab.fr') + self.assertEqual(msg.get('reply-to'), u'oim , BimBam ') + self.assertEqual(msg.get_payload(decode=True), u'un petit cöucou') def test_format_mail_euro(self): mail = format_mail({'name': u'oîm', 'email': u'oim@logilab.fr'}, ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €') - self.assertLinesEquals(mail.as_string(), """\ + self.assertMultiLineEqual(mail.as_string(), """\ MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 @@ -86,11 +86,11 @@ dW4gcGV0aXQgY8O2dWNvdSDigqw= """) msg = message_from_string(mail.as_string()) - self.assertEquals(msg.get('subject'), u'bïjour €') - self.assertEquals(msg.get('from'), u'oîm ') - self.assertEquals(msg.get('to'), u'test@logilab.fr') - self.assertEquals(msg.get('reply-to'), u'oîm ') - self.assertEquals(msg.get_payload(decode=True), u'un petit cöucou €') + self.assertEqual(msg.get('subject'), u'bïjour €') + self.assertEqual(msg.get('from'), u'oîm ') + self.assertEqual(msg.get('to'), u'test@logilab.fr') + self.assertEqual(msg.get('reply-to'), u'oîm ') + self.assertEqual(msg.get_payload(decode=True), u'un petit cöucou €') def test_format_mail_from_reply_to(self): @@ -100,19 +100,19 @@ msg = format_mail({'name': u'', 'email': u''}, ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €', config=self.config) - self.assertEquals(msg.get('from'), u'') - self.assertEquals(msg.get('reply-to'), None) + self.assertEqual(msg.get('from'), u'') + self.assertEqual(msg.get('reply-to'), None) msg = format_mail({'name': u'tutu', 'email': u'tutu@logilab.fr'}, ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €', config=self.config) msg = message_from_string(msg.as_string()) - self.assertEquals(msg.get('from'), u'tutu ') - self.assertEquals(msg.get('reply-to'), u'tutu ') + self.assertEqual(msg.get('from'), u'tutu ') + self.assertEqual(msg.get('reply-to'), u'tutu ') msg = format_mail({'name': u'tutu', 'email': u'tutu@logilab.fr'}, ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €') msg = message_from_string(msg.as_string()) - self.assertEquals(msg.get('from'), u'tutu ') - self.assertEquals(msg.get('reply-to'), u'tutu ') + self.assertEqual(msg.get('from'), u'tutu ') + self.assertEqual(msg.get('reply-to'), u'tutu ') # set sender name and address as expected self.set_option('sender-name', 'cubicweb-test') self.set_option('sender-addr', 'cubicweb-test@logilab.fr') @@ -121,22 +121,22 @@ ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €', config=self.config) msg = message_from_string(msg.as_string()) - self.assertEquals(msg.get('from'), u'cubicweb-test ') - self.assertEquals(msg.get('reply-to'), u'cubicweb-test ') + self.assertEqual(msg.get('from'), u'cubicweb-test ') + self.assertEqual(msg.get('reply-to'), u'cubicweb-test ') # anonymous notification: only email specified msg = format_mail({'email': u'tutu@logilab.fr'}, ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €', config=self.config) msg = message_from_string(msg.as_string()) - self.assertEquals(msg.get('from'), u'cubicweb-test ') - self.assertEquals(msg.get('reply-to'), u'cubicweb-test , cubicweb-test ') + self.assertEqual(msg.get('from'), u'cubicweb-test ') + self.assertEqual(msg.get('reply-to'), u'cubicweb-test , cubicweb-test ') # anonymous notification: only name specified msg = format_mail({'name': u'tutu'}, ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €', config=self.config) msg = message_from_string(msg.as_string()) - self.assertEquals(msg.get('from'), u'tutu ') - self.assertEquals(msg.get('reply-to'), u'tutu ') + self.assertEqual(msg.get('from'), u'tutu ') + self.assertEqual(msg.get('reply-to'), u'tutu ') diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_migration.py --- a/test/unittest_migration.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_migration.py Wed Sep 29 16:16:32 2010 +0200 @@ -52,26 +52,26 @@ self.config.__class__.cube_appobject_path = frozenset() def test_filter_scripts_base(self): - self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,3,0), (2,4,0)), + self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,3,0), (2,4,0)), []) - self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,4,0), (2,5,0)), + self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,4,0), (2,5,0)), [((2, 5, 0), SMIGRDIR+'2.5.0_Any.sql')]) - self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,5,0), (2,6,0)), + self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,5,0), (2,6,0)), [((2, 6, 0), SMIGRDIR+'2.6.0_Any.sql')]) - self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,4,0), (2,6,0)), + self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,4,0), (2,6,0)), [((2, 5, 0), SMIGRDIR+'2.5.0_Any.sql'), ((2, 6, 0), SMIGRDIR+'2.6.0_Any.sql')]) - self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,5,0), (2,5,1)), + self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,5,0), (2,5,1)), []) - self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,5,0), (2,10,2)), + self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,5,0), (2,10,2)), [((2, 6, 0), SMIGRDIR+'2.6.0_Any.sql'), ((2, 10, 2), SMIGRDIR+'2.10.2_Any.sql')]) - self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,5,1), (2,6,0)), + self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,5,1), (2,6,0)), [((2, 6, 0), SMIGRDIR+'2.6.0_Any.sql')]) - self.assertListEquals(filter_scripts(self.config, TMIGRDIR, (0,0,2), (0,0,3)), + self.assertListEqual(filter_scripts(self.config, TMIGRDIR, (0,0,2), (0,0,3)), [((0, 0, 3), TMIGRDIR+'0.0.3_Any.py')]) - self.assertListEquals(filter_scripts(self.config, TMIGRDIR, (0,0,2), (0,0,4)), + self.assertListEqual(filter_scripts(self.config, TMIGRDIR, (0,0,2), (0,0,4)), [((0, 0, 3), TMIGRDIR+'0.0.3_Any.py'), ((0, 0, 4), TMIGRDIR+'0.0.4_Any.py')]) @@ -82,16 +82,16 @@ self.assertIsInstance(config.migration_handler(), MigrationHelper) config = self.config config.__class__.name = 'twisted' - self.assertListEquals(filter_scripts(config, TMIGRDIR, (0,0,4), (0,1,0)), + self.assertListEqual(filter_scripts(config, TMIGRDIR, (0,0,4), (0,1,0)), [((0, 1 ,0), TMIGRDIR+'0.1.0_common.py'), ((0, 1 ,0), TMIGRDIR+'0.1.0_web.py')]) config.__class__.name = 'repository' - self.assertListEquals(filter_scripts(config, TMIGRDIR, (0,0,4), (0,1,0)), + self.assertListEqual(filter_scripts(config, TMIGRDIR, (0,0,4), (0,1,0)), [((0, 1 ,0), TMIGRDIR+'0.1.0_Any.py'), ((0, 1 ,0), TMIGRDIR+'0.1.0_common.py'), ((0, 1 ,0), TMIGRDIR+'0.1.0_repository.py')]) config.__class__.name = 'all-in-one' - self.assertListEquals(filter_scripts(config, TMIGRDIR, (0,0,4), (0,1,0)), + self.assertListEqual(filter_scripts(config, TMIGRDIR, (0,0,4), (0,1,0)), [((0, 1 ,0), TMIGRDIR+'0.1.0_Any.py'), ((0, 1 ,0), TMIGRDIR+'0.1.0_common.py'), ((0, 1 ,0), TMIGRDIR+'0.1.0_repository.py'), @@ -107,7 +107,7 @@ """make sure database can be created""" config = ApptestConfiguration('data') source = config.sources()['system'] - self.assertEquals(source['db-driver'], 'sqlite') + self.assertEqual(source['db-driver'], 'sqlite') cleanup_sqlite(source['db-name'], removetemplate=True) init_test_database(config=config) diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_req.py --- a/test/unittest_req.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_req.py Wed Sep 29 16:16:32 2010 +0200 @@ -23,11 +23,11 @@ class RebuildURLTC(TestCase): def test_rebuild_url(self): rebuild_url = RequestSessionBase(None).rebuild_url - self.assertEquals(rebuild_url('http://logilab.fr?__message=pouet', __message='hop'), + self.assertEqual(rebuild_url('http://logilab.fr?__message=pouet', __message='hop'), 'http://logilab.fr?__message=hop') - self.assertEquals(rebuild_url('http://logilab.fr', __message='hop'), + self.assertEqual(rebuild_url('http://logilab.fr', __message='hop'), 'http://logilab.fr?__message=hop') - self.assertEquals(rebuild_url('http://logilab.fr?vid=index', __message='hop'), + self.assertEqual(rebuild_url('http://logilab.fr?vid=index', __message='hop'), 'http://logilab.fr?__message=hop&vid=index') def test_build_url(self): diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_rqlrewrite.py --- a/test/unittest_rqlrewrite.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_rqlrewrite.py Wed Sep 29 16:16:32 2010 +0200 @@ -15,9 +15,7 @@ # # You should have received a copy of the GNU Lesser General Public License along # with CubicWeb. If not, see . -""" -""" from logilab.common.testlib import unittest_main, TestCase from logilab.common.testlib import mock_object from yams import BadSchemaDefinition @@ -109,7 +107,7 @@ rqlst = parse('Any S WHERE S documented_by C, C eid %(u)s') rewrite(rqlst, {('C', 'X'): (card_constraint,), ('S', 'X'): affaire_constraints}, kwargs) - self.assertTextEquals(rqlst.as_string(), + self.assertMultiLineEqual(rqlst.as_string(), "Any S WHERE S documented_by C, C eid %(u)s, B eid %(D)s, " "EXISTS(C in_state A, B in_group E, F require_state A, " "F name 'read', F require_group E, A is State, E is CWGroup, F is CWPermission), " @@ -272,7 +270,7 @@ "EXISTS(U in_group B, B name 'managers', B is CWGroup), T is TrInfo") def test_unsupported_constraint_3(self): - self.skip('raise unauthorized for now') + self.skipTest('raise unauthorized for now') trinfo_constraint = ('X wf_info_for Y, Y require_permission P, P name "read"') rqlst = parse('Any T WHERE T wf_info_for X') rewrite(rqlst, {('T', 'X'): (trinfo_constraint, 'X in_group G, G name "managers"')}, {}) diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_rset.py --- a/test/unittest_rset.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_rset.py Wed Sep 29 16:16:32 2010 +0200 @@ -16,9 +16,7 @@ # # You should have received a copy of the GNU Lesser General Public License along # with CubicWeb. If not, see . -"""unit tests for module cubicweb.utils - -""" +"""unit tests for module cubicweb.utils""" from urlparse import urlsplit import pickle @@ -52,7 +50,7 @@ } for rql, relations in queries.items(): result = list(attr_desc_iterator(parse(rql).children[0])) - self.assertEquals((rql, result), (rql, relations)) + self.assertEqual((rql, result), (rql, relations)) def test_relations_description_indexed(self): """tests relations_description() function""" @@ -63,7 +61,7 @@ for rql, results in queries.items(): for var_index, relations in results.items(): result = list(attr_desc_iterator(parse(rql).children[0], var_index)) - self.assertEquals(result, relations) + self.assertEqual(result, relations) @@ -79,15 +77,15 @@ def compare_urls(self, url1, url2): info1 = urlsplit(url1) info2 = urlsplit(url2) - self.assertEquals(info1[:3], info2[:3]) + self.assertEqual(info1[:3], info2[:3]) if info1[3] != info2[3]: params1 = dict(pair.split('=') for pair in info1[3].split('&')) params2 = dict(pair.split('=') for pair in info1[3].split('&')) - self.assertDictEquals(params1, params2) + self.assertDictEqual(params1, params2) def test_pickle(self): del self.rset.req - self.assertEquals(len(pickle.dumps(self.rset)), 392) + self.assertEqual(len(pickle.dumps(self.rset)), 392) def test_build_url(self): req = self.request() @@ -105,9 +103,9 @@ def test_resultset_build(self): """test basic build of a ResultSet""" rs = ResultSet([1,2,3], 'CWGroup X', description=['CWGroup', 'CWGroup', 'CWGroup']) - self.assertEquals(rs.rowcount, 3) - self.assertEquals(rs.rows, [1,2,3]) - self.assertEquals(rs.description, ['CWGroup', 'CWGroup', 'CWGroup']) + self.assertEqual(rs.rowcount, 3) + self.assertEqual(rs.rows, [1,2,3]) + self.assertEqual(rs.description, ['CWGroup', 'CWGroup', 'CWGroup']) def test_resultset_limit(self): @@ -117,12 +115,12 @@ rs.req = self.request() rs.vreg = self.vreg - self.assertEquals(rs.limit(2).rows, [[12000, 'adim'], [13000, 'syt']]) + self.assertEqual(rs.limit(2).rows, [[12000, 'adim'], [13000, 'syt']]) rs2 = rs.limit(2, offset=1) - self.assertEquals(rs2.rows, [[13000, 'syt'], [14000, 'nico']]) - self.assertEquals(rs2.get_entity(0, 0).cw_row, 0) - self.assertEquals(rs.limit(2, offset=2).rows, [[14000, 'nico']]) - self.assertEquals(rs.limit(2, offset=3).rows, []) + self.assertEqual(rs2.rows, [[13000, 'syt'], [14000, 'nico']]) + self.assertEqual(rs2.get_entity(0, 0).cw_row, 0) + self.assertEqual(rs.limit(2, offset=2).rows, [[14000, 'nico']]) + self.assertEqual(rs.limit(2, offset=3).rows, []) def test_resultset_filter(self): @@ -135,8 +133,8 @@ return entity.login != 'nico' rs2 = rs.filtered_rset(test_filter) - self.assertEquals(len(rs2), 2) - self.assertEquals([login for _, login in rs2], ['adim', 'syt']) + self.assertEqual(len(rs2), 2) + self.assertEqual([login for _, login in rs2], ['adim', 'syt']) def test_resultset_transform(self): rs = ResultSet([[12, 'adim'], [13, 'syt'], [14, 'nico']], @@ -147,8 +145,8 @@ return row[1:], desc[1:] rs2 = rs.transformed_rset(test_transform) - self.assertEquals(len(rs2), 3) - self.assertEquals(list(rs2), [['adim'],['syt'],['nico']]) + self.assertEqual(len(rs2), 3) + self.assertEqual(list(rs2), [['adim'],['syt'],['nico']]) def test_resultset_sort(self): rs = ResultSet([[12000, 'adim'], [13000, 'syt'], [14000, 'nico']], @@ -157,23 +155,35 @@ rs.req = self.request() rs.vreg = self.vreg +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py rs2 = rs.sorted_rset(lambda e:e.cw_attr_cache['login']) self.assertEquals(len(rs2), 3) self.assertEquals([login for _, login in rs2], ['adim', 'nico', 'syt']) +======= + rs2 = rs.sorted_rset(lambda e:e['login']) + self.assertEqual(len(rs2), 3) + self.assertEqual([login for _, login in rs2], ['adim', 'nico', 'syt']) +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp # make sure rs is unchanged - self.assertEquals([login for _, login in rs], ['adim', 'syt', 'nico']) + self.assertEqual([login for _, login in rs], ['adim', 'syt', 'nico']) +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py rs2 = rs.sorted_rset(lambda e:e.cw_attr_cache['login'], reverse=True) self.assertEquals(len(rs2), 3) self.assertEquals([login for _, login in rs2], ['syt', 'nico', 'adim']) +======= + rs2 = rs.sorted_rset(lambda e:e['login'], reverse=True) + self.assertEqual(len(rs2), 3) + self.assertEqual([login for _, login in rs2], ['syt', 'nico', 'adim']) +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp # make sure rs is unchanged - self.assertEquals([login for _, login in rs], ['adim', 'syt', 'nico']) + self.assertEqual([login for _, login in rs], ['adim', 'syt', 'nico']) rs3 = rs.sorted_rset(lambda row: row[1], col=-1) - self.assertEquals(len(rs3), 3) - self.assertEquals([login for _, login in rs3], ['adim', 'nico', 'syt']) + self.assertEqual(len(rs3), 3) + self.assertEqual([login for _, login in rs3], ['adim', 'nico', 'syt']) # make sure rs is unchanged - self.assertEquals([login for _, login in rs], ['adim', 'syt', 'nico']) + self.assertEqual([login for _, login in rs], ['adim', 'syt', 'nico']) def test_resultset_split(self): rs = ResultSet([[12000, 'adim', u'Adim chez les pinguins'], @@ -187,33 +197,49 @@ rs.req = self.request() rs.vreg = self.vreg +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py rsets = rs.split_rset(lambda e:e.cw_attr_cache['login']) self.assertEquals(len(rsets), 3) self.assertEquals([login for _, login,_ in rsets[0]], ['adim', 'adim']) self.assertEquals([login for _, login,_ in rsets[1]], ['syt']) self.assertEquals([login for _, login,_ in rsets[2]], ['nico', 'nico']) +======= + rsets = rs.split_rset(lambda e:e['login']) + self.assertEqual(len(rsets), 3) + self.assertEqual([login for _, login,_ in rsets[0]], ['adim', 'adim']) + self.assertEqual([login for _, login,_ in rsets[1]], ['syt']) + self.assertEqual([login for _, login,_ in rsets[2]], ['nico', 'nico']) +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp # make sure rs is unchanged - self.assertEquals([login for _, login,_ in rs], ['adim', 'adim', 'syt', 'nico', 'nico']) + self.assertEqual([login for _, login,_ in rs], ['adim', 'adim', 'syt', 'nico', 'nico']) +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py rsets = rs.split_rset(lambda e:e.cw_attr_cache['login'], return_dict=True) self.assertEquals(len(rsets), 3) self.assertEquals([login for _, login,_ in rsets['nico']], ['nico', 'nico']) self.assertEquals([login for _, login,_ in rsets['adim']], ['adim', 'adim']) self.assertEquals([login for _, login,_ in rsets['syt']], ['syt']) +======= + rsets = rs.split_rset(lambda e:e['login'], return_dict=True) + self.assertEqual(len(rsets), 3) + self.assertEqual([login for _, login,_ in rsets['nico']], ['nico', 'nico']) + self.assertEqual([login for _, login,_ in rsets['adim']], ['adim', 'adim']) + self.assertEqual([login for _, login,_ in rsets['syt']], ['syt']) +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp # make sure rs is unchanged - self.assertEquals([login for _, login,_ in rs], ['adim', 'adim', 'syt', 'nico', 'nico']) + self.assertEqual([login for _, login,_ in rs], ['adim', 'adim', 'syt', 'nico', 'nico']) rsets = rs.split_rset(lambda s: s.count('d'), col=2) - self.assertEquals(len(rsets), 2) - self.assertEquals([title for _, _, title in rsets[0]], + self.assertEqual(len(rsets), 2) + self.assertEqual([title for _, _, title in rsets[0]], [u"Adim chez les pinguins", u"Jardiner facile", u"L'épluchage du castor commun",]) - self.assertEquals([title for _, _, title in rsets[1]], + self.assertEqual([title for _, _, title in rsets[1]], [u"Le carrelage en 42 leçons", u"La tarte tatin en 15 minutes",]) # make sure rs is unchanged - self.assertEquals([title for _, _, title in rs], + self.assertEqual([title for _, _, title in rs], [u'Adim chez les pinguins', u'Jardiner facile', u'Le carrelage en 42 leçons', @@ -228,15 +254,27 @@ def test_get_entity_simple(self): self.request().create_entity('CWUser', login=u'adim', upassword='adim', - surname=u'di mascio', firstname=u'adrien') + surname=u'di mascio', firstname=u'adrien') e = self.execute('Any X,T WHERE X login "adim", X surname T').get_entity(0, 0) +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py self.assertEquals(e.cw_attr_cache['surname'], 'di mascio') self.assertRaises(KeyError, e.cw_attr_cache.__getitem__, 'firstname') self.assertRaises(KeyError, e.cw_attr_cache.__getitem__, 'creation_date') self.assertEquals(pprelcachedict(e._cw_related_cache), []) +======= + self.assertEqual(e['surname'], 'di mascio') + self.assertRaises(KeyError, e.__getitem__, 'firstname') + self.assertRaises(KeyError, e.__getitem__, 'creation_date') + self.assertEqual(pprelcachedict(e._cw_related_cache), []) +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp e.complete() +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py self.assertEquals(e.cw_attr_cache['firstname'], 'adrien') self.assertEquals(pprelcachedict(e._cw_related_cache), []) +======= + self.assertEqual(e['firstname'], 'adrien') + self.assertEqual(pprelcachedict(e._cw_related_cache), []) +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp def test_get_entity_advanced(self): self.request().create_entity('Bookmark', title=u'zou', path=u'/view') @@ -244,24 +282,47 @@ rset = self.execute('Any X,Y,XT,YN WHERE X bookmarked_by Y, X title XT, Y login YN') e = rset.get_entity(0, 0) +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py self.assertEquals(e.cw_row, 0) self.assertEquals(e.cw_col, 0) self.assertEquals(e.cw_attr_cache['title'], 'zou') self.assertRaises(KeyError, e.cw_attr_cache.__getitem__, 'path') self.assertEquals(e.view('text'), 'zou') self.assertEquals(pprelcachedict(e._cw_related_cache), []) +======= + self.assertEqual(e.cw_row, 0) + self.assertEqual(e.cw_col, 0) + self.assertEqual(e['title'], 'zou') + self.assertRaises(KeyError, e.__getitem__, 'path') + self.assertEqual(e.view('text'), 'zou') + self.assertEqual(pprelcachedict(e._cw_related_cache), []) +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp e = rset.get_entity(0, 1) +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py self.assertEquals(e.cw_row, 0) self.assertEquals(e.cw_col, 1) self.assertEquals(e.cw_attr_cache['login'], 'anon') self.assertRaises(KeyError, e.cw_attr_cache.__getitem__, 'firstname') self.assertEquals(pprelcachedict(e._cw_related_cache), +======= + self.assertEqual(e.cw_row, 0) + self.assertEqual(e.cw_col, 1) + self.assertEqual(e['login'], 'anon') + self.assertRaises(KeyError, e.__getitem__, 'firstname') + self.assertEqual(pprelcachedict(e._cw_related_cache), +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp []) e.complete() +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py self.assertEquals(e.cw_attr_cache['firstname'], None) self.assertEquals(e.view('text'), 'anon') self.assertEquals(pprelcachedict(e._cw_related_cache), +======= + self.assertEqual(e['firstname'], None) + self.assertEqual(e.view('text'), 'anon') + self.assertEqual(pprelcachedict(e._cw_related_cache), +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp []) self.assertRaises(NotAnEntity, rset.get_entity, 0, 2) @@ -273,7 +334,7 @@ seid = self.execute('State X WHERE X name "activated"')[0][0] # for_user / in_group are prefetched in CWUser __init__, in_state should # be filed from our query rset - self.assertEquals(pprelcachedict(e._cw_related_cache), + self.assertEqual(pprelcachedict(e._cw_related_cache), [('in_state_subject', [seid])]) def test_get_entity_advanced_prefilled_cache(self): @@ -282,17 +343,32 @@ rset = self.execute('Any X,U,S,XT,UL,SN WHERE X created_by U, U in_state S, ' 'X title XT, S name SN, U login UL, X eid %s' % e.eid) e = rset.get_entity(0, 0) +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py self.assertEquals(e.cw_attr_cache['title'], 'zou') self.assertEquals(pprelcachedict(e._cw_related_cache), +======= + self.assertEqual(e['title'], 'zou') + self.assertEqual(pprelcachedict(e._cw_related_cache), +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp [('created_by_subject', [5])]) # first level of recursion u = e.created_by[0] +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py self.assertEquals(u.cw_attr_cache['login'], 'admin') self.assertRaises(KeyError, u.cw_attr_cache.__getitem__, 'firstname') +======= + self.assertEqual(u['login'], 'admin') + self.assertRaises(KeyError, u.__getitem__, 'firstname') +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp # second level of recursion s = u.in_state[0] +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py self.assertEquals(s.cw_attr_cache['name'], 'activated') self.assertRaises(KeyError, s.cw_attr_cache.__getitem__, 'description') +======= + self.assertEqual(s['name'], 'activated') + self.assertRaises(KeyError, s.__getitem__, 'description') +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp def test_get_entity_cache_with_left_outer_join(self): @@ -302,11 +378,11 @@ e = rset.get_entity(0, 0) # if any of the assertion below fails with a KeyError, the relation is not cached # related entities should be an empty list - self.assertEquals(e._cw_relation_cache('primary_email', 'subject', True), ()) + self.assertEqual(e._cw_relation_cache('primary_email', 'subject', True), ()) # related rset should be an empty rset cached = e._cw_relation_cache('primary_email', 'subject', False) self.assertIsInstance(cached, ResultSet) - self.assertEquals(cached.rowcount, 0) + self.assertEqual(cached.rowcount, 0) def test_get_entity_union(self): @@ -320,16 +396,20 @@ ('CWGroup', 'users')) for entity in rset.entities(): # test get_entity for each row actually etype, n = expected[entity.cw_row] - self.assertEquals(entity.__regid__, etype) + self.assertEqual(entity.__regid__, etype) attr = etype == 'Bookmark' and 'title' or 'name' +<<<<<<< /home/syt/src/fcubicweb/cubicweb/test/unittest_rset.py self.assertEquals(entity.cw_attr_cache[attr], n) +======= + self.assertEqual(entity[attr], n) +>>>>>>> /tmp/unittest_rset.py~other.4ZXPmp def test_related_entity_optional(self): e = self.request().create_entity('Bookmark', title=u'aaaa', path=u'path') rset = self.execute('Any B,U,L WHERE B bookmarked_by U?, U login L') entity, rtype = rset.related_entity(0, 2) - self.assertEquals(entity, None) - self.assertEquals(rtype, None) + self.assertEqual(entity, None) + self.assertEqual(rtype, None) def test_related_entity_union_subquery(self): e = self.request().create_entity('Bookmark', title=u'aaaa', path=u'path') @@ -338,27 +418,27 @@ ' UNION ' ' (Any X,N WHERE X is Bookmark, X title N))') entity, rtype = rset.related_entity(0, 1) - self.assertEquals(entity.eid, e.eid) - self.assertEquals(rtype, 'title') + self.assertEqual(entity.eid, e.eid) + self.assertEqual(rtype, 'title') entity, rtype = rset.related_entity(1, 1) - self.assertEquals(entity.__regid__, 'CWGroup') - self.assertEquals(rtype, 'name') + self.assertEqual(entity.__regid__, 'CWGroup') + self.assertEqual(rtype, 'name') # rset = self.execute('Any X,N ORDERBY N WHERE X is Bookmark WITH X,N BEING ' '((Any X,N WHERE X is CWGroup, X name N)' ' UNION ' ' (Any X,N WHERE X is Bookmark, X title N))') entity, rtype = rset.related_entity(0, 1) - self.assertEquals(entity.eid, e.eid) - self.assertEquals(rtype, 'title') + self.assertEqual(entity.eid, e.eid) + self.assertEqual(rtype, 'title') # rset = self.execute('Any X,N ORDERBY N WITH N,X BEING ' '((Any N,X WHERE X is CWGroup, X name N)' ' UNION ' ' (Any N,X WHERE X is Bookmark, X title N))') entity, rtype = rset.related_entity(0, 1) - self.assertEquals(entity.eid, e.eid) - self.assertEquals(rtype, 'title') + self.assertEqual(entity.eid, e.eid) + self.assertEqual(rtype, 'title') def test_related_entity_trap_subquery(self): req = self.request() @@ -372,7 +452,7 @@ rset = self.execute('Any X,S,L WHERE X in_state S ' 'WITH X, L BEING (Any X,MAX(L) GROUPBY X ' 'WHERE X is CWUser, T? wf_info_for X, T creation_date L)') - self.assertEquals(len(rset), 2) + self.assertEqual(len(rset), 2) rset.related_entity(0, 1) rset.related_entity(0, 2) @@ -380,28 +460,28 @@ rset = self.execute('Any U,G WHERE U in_group G') # make sure we have at least one element self.failUnless(rset) - self.assertEquals(set(e.e_schema.type for e in rset.entities(0)), + self.assertEqual(set(e.e_schema.type for e in rset.entities(0)), set(['CWUser',])) - self.assertEquals(set(e.e_schema.type for e in rset.entities(1)), + self.assertEqual(set(e.e_schema.type for e in rset.entities(1)), set(['CWGroup',])) def test_printable_rql(self): rset = self.execute(u'CWEType X WHERE X final FALSE') - self.assertEquals(rset.printable_rql(), + self.assertEqual(rset.printable_rql(), 'Any X WHERE X final FALSE, X is CWEType') def test_searched_text(self): rset = self.execute(u'Any X WHERE X has_text "foobar"') - self.assertEquals(rset.searched_text(), 'foobar') + self.assertEqual(rset.searched_text(), 'foobar') rset = self.execute(u'Any X WHERE X has_text %(text)s', {'text' : 'foo'}) - self.assertEquals(rset.searched_text(), 'foo') + self.assertEqual(rset.searched_text(), 'foo') def test_union_limited_rql(self): rset = self.execute('(Any X,N WHERE X is Bookmark, X title N)' ' UNION ' '(Any X,N WHERE X is CWGroup, X name N)') rset.limit(2, 10, inplace=True) - self.assertEquals(rset.limited_rql(), + self.assertEqual(rset.limited_rql(), 'Any A,B LIMIT 2 OFFSET 10 ' 'WITH A,B BEING (' '(Any X,N WHERE X is Bookmark, X title N) ' @@ -411,12 +491,12 @@ def test_count_users_by_date(self): rset = self.execute('Any D, COUNT(U) GROUPBY D WHERE U is CWUser, U creation_date D') - self.assertEquals(rset.related_entity(0,0), (None, None)) + self.assertEqual(rset.related_entity(0,0), (None, None)) def test_str(self): rset = self.execute('(Any X,N WHERE X is CWGroup, X name N)') self.assertIsInstance(str(rset), basestring) - self.assertEquals(len(str(rset).splitlines()), 1) + self.assertEqual(len(str(rset).splitlines()), 1) def test_repr(self): rset = self.execute('(Any X,N WHERE X is CWGroup, X name N)') @@ -425,7 +505,7 @@ rset = self.execute('(Any X WHERE X is CWGroup, X name "managers")') self.assertIsInstance(str(rset), basestring) - self.assertEquals(len(str(rset).splitlines()), 1) + self.assertEqual(len(str(rset).splitlines()), 1) if __name__ == '__main__': unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_rtags.py --- a/test/unittest_rtags.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_rtags.py Wed Sep 29 16:16:32 2010 +0200 @@ -28,25 +28,25 @@ rtags.tag_subject_of(('Societe', 'travaille', '*'), 'primary') rtags.tag_subject_of(('*', 'evaluee', '*'), 'secondary') rtags.tag_object_of(('*', 'tags', '*'), 'generated') - self.assertEquals(rtags.get('Note', 'evaluee', '*', 'subject'), + self.assertEqual(rtags.get('Note', 'evaluee', '*', 'subject'), 'secondary') - self.assertEquals(rtags.get('Societe', 'travaille', '*', 'subject'), + self.assertEqual(rtags.get('Societe', 'travaille', '*', 'subject'), 'primary') - self.assertEquals(rtags.get('Note', 'travaille', '*', 'subject'), + self.assertEqual(rtags.get('Note', 'travaille', '*', 'subject'), None) - self.assertEquals(rtags.get('Note', 'tags', '*', 'subject'), + self.assertEqual(rtags.get('Note', 'tags', '*', 'subject'), None) - self.assertEquals(rtags.get('*', 'tags', 'Note', 'object'), + self.assertEqual(rtags.get('*', 'tags', 'Note', 'object'), 'generated') - self.assertEquals(rtags.get('Tag', 'tags', '*', 'object'), + self.assertEqual(rtags.get('Tag', 'tags', '*', 'object'), 'generated') -# self.assertEquals(rtags.rtag('evaluee', 'Note', 'subject'), set(('secondary', 'link'))) -# self.assertEquals(rtags.is_inlined('evaluee', 'Note', 'subject'), False) -# self.assertEquals(rtags.rtag('evaluee', 'Personne', 'subject'), set(('secondary', 'link'))) -# self.assertEquals(rtags.is_inlined('evaluee', 'Personne', 'subject'), False) -# self.assertEquals(rtags.rtag('ecrit_par', 'Note', 'object'), set(('inlineview', 'link'))) -# self.assertEquals(rtags.is_inlined('ecrit_par', 'Note', 'object'), True) +# self.assertEqual(rtags.rtag('evaluee', 'Note', 'subject'), set(('secondary', 'link'))) +# self.assertEqual(rtags.is_inlined('evaluee', 'Note', 'subject'), False) +# self.assertEqual(rtags.rtag('evaluee', 'Personne', 'subject'), set(('secondary', 'link'))) +# self.assertEqual(rtags.is_inlined('evaluee', 'Personne', 'subject'), False) +# self.assertEqual(rtags.rtag('ecrit_par', 'Note', 'object'), set(('inlineview', 'link'))) +# self.assertEqual(rtags.is_inlined('ecrit_par', 'Note', 'object'), True) # class Personne2(Personne): # id = 'Personne' # __rtags__ = { @@ -54,21 +54,21 @@ # } # self.vreg.register(Personne2) # rtags = Personne2.rtags -# self.assertEquals(rtags.rtag('evaluee', 'Note', 'subject'), set(('inlineview', 'link'))) -# self.assertEquals(rtags.is_inlined('evaluee', 'Note', 'subject'), True) -# self.assertEquals(rtags.rtag('evaluee', 'Personne', 'subject'), set(('secondary', 'link'))) -# self.assertEquals(rtags.is_inlined('evaluee', 'Personne', 'subject'), False) +# self.assertEqual(rtags.rtag('evaluee', 'Note', 'subject'), set(('inlineview', 'link'))) +# self.assertEqual(rtags.is_inlined('evaluee', 'Note', 'subject'), True) +# self.assertEqual(rtags.rtag('evaluee', 'Personne', 'subject'), set(('secondary', 'link'))) +# self.assertEqual(rtags.is_inlined('evaluee', 'Personne', 'subject'), False) def test_rtagset_expansion(self): rtags = RelationTagsSet() rtags.tag_subject_of(('Societe', 'travaille', '*'), 'primary') rtags.tag_subject_of(('*', 'travaille', '*'), 'secondary') - self.assertEquals(rtags.get('Societe', 'travaille', '*', 'subject'), + self.assertEqual(rtags.get('Societe', 'travaille', '*', 'subject'), set(('primary', 'secondary'))) - self.assertEquals(rtags.get('Note', 'travaille', '*', 'subject'), + self.assertEqual(rtags.get('Note', 'travaille', '*', 'subject'), set(('secondary',))) - self.assertEquals(rtags.get('Note', 'tags', "*", 'subject'), + self.assertEqual(rtags.get('Note', 'tags', "*", 'subject'), set()) def test_rtagdict_expansion(self): @@ -79,16 +79,16 @@ {'key1': 'val0', 'key3': 'val0'}) rtags.tag_subject_of(('Societe', 'travaille', '*'), {'key2': 'val2'}) - self.assertEquals(rtags.get('Societe', 'travaille', '*', 'subject'), + self.assertEqual(rtags.get('Societe', 'travaille', '*', 'subject'), {'key1': 'val1', 'key2': 'val2', 'key3': 'val0'}) - self.assertEquals(rtags.get('Note', 'travaille', '*', 'subject'), + self.assertEqual(rtags.get('Note', 'travaille', '*', 'subject'), {'key1': 'val0', 'key3': 'val0'}) - self.assertEquals(rtags.get('Note', 'tags', "*", 'subject'), + self.assertEqual(rtags.get('Note', 'tags', "*", 'subject'), {}) rtags.setdefault(('Societe', 'travaille', '*', 'subject'), 'key1', 'val4') rtags.setdefault(('Societe', 'travaille', '*', 'subject'), 'key4', 'val4') - self.assertEquals(rtags.get('Societe', 'travaille', '*', 'subject'), + self.assertEqual(rtags.get('Societe', 'travaille', '*', 'subject'), {'key1': 'val1', 'key2': 'val2', 'key3': 'val0', 'key4': 'val4'}) if __name__ == '__main__': diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_schema.py --- a/test/unittest_schema.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_schema.py Wed Sep 29 16:16:32 2010 +0200 @@ -142,13 +142,13 @@ def test_erqlexpression(self): self.assertRaises(RQLSyntaxError, ERQLExpression, '1') expr = ERQLExpression('X travaille S, S owned_by U') - self.assertEquals(str(expr), 'Any X WHERE X travaille S, S owned_by U, X eid %(x)s, U eid %(u)s') + self.assertEqual(str(expr), 'Any X WHERE X travaille S, S owned_by U, X eid %(x)s, U eid %(u)s') def test_rrqlexpression(self): self.assertRaises(Exception, RRQLExpression, '1') self.assertRaises(RQLSyntaxError, RRQLExpression, 'O X Y') expr = RRQLExpression('U has_update_permission O') - self.assertEquals(str(expr), 'Any O,U WHERE U has_update_permission O, O eid %(o)s, U eid %(u)s') + self.assertEqual(str(expr), 'Any O,U WHERE U has_update_permission O, O eid %(o)s, U eid %(u)s') loader = CubicWebSchemaLoader() config = TestConfiguration('data') @@ -158,15 +158,15 @@ def test_order_eschemas(self): schema = loader.load(config) - self.assertEquals(order_eschemas([schema['Note'], schema['SubNote']]), + self.assertEqual(order_eschemas([schema['Note'], schema['SubNote']]), [schema['Note'], schema['SubNote']]) - self.assertEquals(order_eschemas([schema['SubNote'], schema['Note']]), + self.assertEqual(order_eschemas([schema['SubNote'], schema['Note']]), [schema['Note'], schema['SubNote']]) def test_knownValues_load_schema(self): schema = loader.load(config) self.assert_(isinstance(schema, CubicWebSchema)) - self.assertEquals(schema.name, 'data') + self.assertEqual(schema.name, 'data') entities = [str(e) for e in schema.entities()] entities.sort() expected_entities = ['BaseTransition', 'Bookmark', 'Boolean', 'Bytes', 'Card', @@ -181,7 +181,7 @@ 'Societe', 'State', 'String', 'SubNote', 'SubWorkflowExitPoint', 'Tag', 'Time', 'Transition', 'TrInfo', 'Workflow', 'WorkflowTransition'] - self.assertListEquals(entities, sorted(expected_entities)) + self.assertListEqual(entities, sorted(expected_entities)) relations = [str(r) for r in schema.relations()] relations.sort() expected_relations = ['add_permission', 'address', 'alias', 'allowed_transition', @@ -227,11 +227,11 @@ 'wf_info_for', 'wikiid', 'workflow_of'] - self.assertListEquals(relations, expected_relations) + self.assertListEqual(relations, expected_relations) eschema = schema.eschema('CWUser') rels = sorted(str(r) for r in eschema.subject_relations()) - self.assertListEquals(rels, ['created_by', 'creation_date', 'custom_workflow', 'cwuri', 'eid', + self.assertListEqual(rels, ['created_by', 'creation_date', 'custom_workflow', 'cwuri', 'eid', 'evaluee', 'firstname', 'has_text', 'identity', 'in_group', 'in_state', 'is', 'is_instance_of', 'last_login_time', @@ -239,11 +239,11 @@ 'primary_email', 'surname', 'upassword', 'use_email']) rels = sorted(r.type for r in eschema.object_relations()) - self.assertListEquals(rels, ['bookmarked_by', 'created_by', 'for_user', + self.assertListEqual(rels, ['bookmarked_by', 'created_by', 'for_user', 'identity', 'owned_by', 'wf_info_for']) rschema = schema.rschema('relation_type') properties = rschema.rdef('CWAttribute', 'CWRType') - self.assertEquals(properties.cardinality, '1*') + self.assertEqual(properties.cardinality, '1*') constraints = properties.constraints self.failUnlessEqual(len(constraints), 1, constraints) constraint = constraints[0] @@ -258,13 +258,13 @@ def test_permission_settings(self): schema = loader.load(config) aschema = schema['TrInfo'].rdef('comment') - self.assertEquals(aschema.get_groups('read'), + self.assertEqual(aschema.get_groups('read'), set(('managers', 'users', 'guests'))) - self.assertEquals(aschema.get_rqlexprs('read'), + self.assertEqual(aschema.get_rqlexprs('read'), ()) - self.assertEquals(aschema.get_groups('update'), + self.assertEqual(aschema.get_groups('update'), set(('managers',))) - self.assertEquals([x.expression for x in aschema.get_rqlexprs('update')], + self.assertEqual([x.expression for x in aschema.get_rqlexprs('update')], ['U has_update_permission X']) class BadSchemaRQLExprTC(TestCase): @@ -279,7 +279,7 @@ self.loader.handle_file(join(DATADIR, schemafile)) ex = self.assertRaises(BadSchemaDefinition, self.loader._build_schema, 'toto', False) - self.assertEquals(str(ex), msg) + self.assertEqual(str(ex), msg) def test_rrqlexpr_on_etype(self): self._test('rrqlexpr_on_eetype.py', @@ -301,12 +301,12 @@ class NormalizeExpressionTC(TestCase): def test(self): - self.assertEquals(normalize_expression('X bla Y,Y blur Z , Z zigoulou X '), + self.assertEqual(normalize_expression('X bla Y,Y blur Z , Z zigoulou X '), 'X bla Y, Y blur Z, Z zigoulou X') class RQLExpressionTC(TestCase): def test_comparison(self): - self.assertEquals(ERQLExpression('X is CWUser', 'X', 0), + self.assertEqual(ERQLExpression('X is CWUser', 'X', 0), ERQLExpression('X is CWUser', 'X', 0)) self.assertNotEquals(ERQLExpression('X is CWUser', 'X', 0), ERQLExpression('X is CWGroup', 'X', 0)) @@ -314,7 +314,7 @@ class GuessRrqlExprMainVarsTC(TestCase): def test_exists(self): mainvars = guess_rrqlexpr_mainvars(normalize_expression('NOT EXISTS(O team_competition C, C level < 3)')) - self.assertEquals(mainvars, 'O') + self.assertEqual(mainvars, 'O') if __name__ == '__main__': diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_selectors.py --- a/test/unittest_selectors.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_selectors.py Wed Sep 29 16:16:32 2010 +0200 @@ -17,12 +17,14 @@ # with CubicWeb. If not, see . """unit tests for selectors mechanism""" +from operator import eq, lt, le, gt from logilab.common.testlib import TestCase, unittest_main from cubicweb import Binary from cubicweb.devtools.testlib import CubicWebTC from cubicweb.appobject import Selector, AndSelector, OrSelector -from cubicweb.selectors import is_instance, adaptable, match_user_groups +from cubicweb.selectors import (is_instance, adaptable, match_user_groups, + multi_lines_rset) from cubicweb.interfaces import IDownloadable from cubicweb.web import action @@ -41,55 +43,55 @@ class SelectorsTC(TestCase): def test_basic_and(self): selector = _1_() & _1_() - self.assertEquals(selector(None), 2) + self.assertEqual(selector(None), 2) selector = _1_() & _0_() - self.assertEquals(selector(None), 0) + self.assertEqual(selector(None), 0) selector = _0_() & _1_() - self.assertEquals(selector(None), 0) + self.assertEqual(selector(None), 0) def test_basic_or(self): selector = _1_() | _1_() - self.assertEquals(selector(None), 1) + self.assertEqual(selector(None), 1) selector = _1_() | _0_() - self.assertEquals(selector(None), 1) + self.assertEqual(selector(None), 1) selector = _0_() | _1_() - self.assertEquals(selector(None), 1) + self.assertEqual(selector(None), 1) selector = _0_() | _0_() - self.assertEquals(selector(None), 0) + self.assertEqual(selector(None), 0) def test_selector_and_function(self): selector = _1_() & _2_ - self.assertEquals(selector(None), 3) + self.assertEqual(selector(None), 3) selector = _2_ & _1_() - self.assertEquals(selector(None), 3) + self.assertEqual(selector(None), 3) def test_three_and(self): selector = _1_() & _1_() & _1_() - self.assertEquals(selector(None), 3) + self.assertEqual(selector(None), 3) selector = _1_() & _0_() & _1_() - self.assertEquals(selector(None), 0) + self.assertEqual(selector(None), 0) selector = _0_() & _1_() & _1_() - self.assertEquals(selector(None), 0) + self.assertEqual(selector(None), 0) def test_three_or(self): selector = _1_() | _1_() | _1_() - self.assertEquals(selector(None), 1) + self.assertEqual(selector(None), 1) selector = _1_() | _0_() | _1_() - self.assertEquals(selector(None), 1) + self.assertEqual(selector(None), 1) selector = _0_() | _1_() | _1_() - self.assertEquals(selector(None), 1) + self.assertEqual(selector(None), 1) selector = _0_() | _0_() | _0_() - self.assertEquals(selector(None), 0) + self.assertEqual(selector(None), 0) def test_composition(self): selector = (_1_() & _1_()) & (_1_() & _1_()) self.failUnless(isinstance(selector, AndSelector)) - self.assertEquals(len(selector.selectors), 4) - self.assertEquals(selector(None), 4) + self.assertEqual(len(selector.selectors), 4) + self.assertEqual(selector(None), 4) selector = (_1_() & _0_()) | (_1_() & _1_()) self.failUnless(isinstance(selector, OrSelector)) - self.assertEquals(len(selector.selectors), 2) - self.assertEquals(selector(None), 2) + self.assertEqual(len(selector.selectors), 2) + self.assertEqual(selector(None), 2) def test_search_selectors(self): sel = is_instance('something') @@ -103,37 +105,37 @@ selector = _1_() selector &= _1_() selector &= _1_() - self.assertEquals(selector(None), 3) + self.assertEqual(selector(None), 3) selector = _1_() selector &= _0_() selector &= _1_() - self.assertEquals(selector(None), 0) + self.assertEqual(selector(None), 0) selector = _0_() selector &= _1_() selector &= _1_() - self.assertEquals(selector(None), 0) + self.assertEqual(selector(None), 0) selector = _0_() selector &= _0_() selector &= _0_() - self.assertEquals(selector(None), 0) + self.assertEqual(selector(None), 0) def test_inplace_or(self): selector = _1_() selector |= _1_() selector |= _1_() - self.assertEquals(selector(None), 1) + self.assertEqual(selector(None), 1) selector = _1_() selector |= _0_() selector |= _1_() - self.assertEquals(selector(None), 1) + self.assertEqual(selector(None), 1) selector = _0_() selector |= _1_() selector |= _1_() - self.assertEquals(selector(None), 1) + self.assertEqual(selector(None), 1) selector = _0_() selector |= _0_() selector |= _0_() - self.assertEquals(selector(None), 0) + self.assertEqual(selector(None), 0) class ImplementsSelectorTC(CubicWebTC): @@ -153,7 +155,7 @@ def test_yams_inheritance(self): cls = self.vreg['etypes'].etype_class('Transition') - self.assertEquals(is_instance('BaseTransition').score_class(cls, self.request()), + self.assertEqual(is_instance('BaseTransition').score_class(cls, self.request()), 3) @@ -190,6 +192,59 @@ finally: del self.vreg[SomeAction.__registry__][SomeAction.__regid__] + +class MultiLinesRsetSelectorTC(CubicWebTC): + def setUp(self): + super(MultiLinesRsetSelectorTC, self).setUp() + self.req = self.request() + self.req.execute('INSERT CWGroup G: G name "group1"') + self.req.execute('INSERT CWGroup G: G name "group2"') + self.commit() + self.rset = self.req.execute('Any G WHERE G is CWGroup') + + def test_default_op_in_selector(self): + expected = len(self.rset) + selector = multi_lines_rset(expected) + self.assertEqual(selector(None, self.req, self.rset), 1) + self.assertEqual(selector(None, self.req, None), 0) + selector = multi_lines_rset(expected + 1) + self.assertEqual(selector(None, self.req, self.rset), 0) + self.assertEqual(selector(None, self.req, None), 0) + selector = multi_lines_rset(expected - 1) + self.assertEqual(selector(None, self.req, self.rset), 0) + self.assertEqual(selector(None, self.req, None), 0) + + def test_without_rset(self): + expected = len(self.rset) + selector = multi_lines_rset(expected) + self.assertEqual(selector(None, self.req, None), 0) + selector = multi_lines_rset(expected + 1) + self.assertEqual(selector(None, self.req, None), 0) + selector = multi_lines_rset(expected - 1) + self.assertEqual(selector(None, self.req, None), 0) + + def test_with_operators(self): + expected = len(self.rset) + + # Format 'expected', 'operator', 'assert' + testdata = (( expected, eq, 1), + ( expected+1, eq, 0), + ( expected-1, eq, 0), + ( expected, le, 1), + ( expected+1, le, 1), + ( expected-1, le, 0), + ( expected-1, gt, 1), + ( expected, gt, 0), + ( expected+1, gt, 0), + ( expected+1, lt, 1), + ( expected, lt, 0), + ( expected-1, lt, 0)) + + for (expected, operator, assertion) in testdata: + selector = multi_lines_rset(expected, operator) + yield self.assertEqual, selector(None, self.req, self.rset), assertion + + if __name__ == '__main__': unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_spa2rql.py --- a/test/unittest_spa2rql.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_spa2rql.py Wed Sep 29 16:16:32 2010 +0200 @@ -37,7 +37,7 @@ def _test(self, sparql, rql, args={}): qi = self.tr.translate(sparql) - self.assertEquals(qi.finalize(), (rql, args)) + self.assertEqual(qi.finalize(), (rql, args)) def XXX_test_base_01(self): self._test('SELECT * WHERE { }', 'Any X') diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_uilib.py --- a/test/unittest_uilib.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_uilib.py Wed Sep 29 16:16:32 2010 +0200 @@ -36,22 +36,22 @@ ] for text, expected in data: got = uilib.remove_html_tags(text) - self.assertEquals(got, expected) + self.assertEqual(got, expected) def test_fallback_safe_cut(self): - self.assertEquals(uilib.fallback_safe_cut(u'ab cd', 4), u'ab c...') - self.assertEquals(uilib.fallback_safe_cut(u'ab cd', 5), u'ab cd') - self.assertEquals(uilib.fallback_safe_cut(u'ab &d', 4), u'ab &...') - self.assertEquals(uilib.fallback_safe_cut(u'ab &d ef', 5), u'ab &d...') - self.assertEquals(uilib.fallback_safe_cut(u'ab ìd', 4), u'ab ì...') - self.assertEquals(uilib.fallback_safe_cut(u'& &d ef', 4), u'& &d...') + self.assertEqual(uilib.fallback_safe_cut(u'ab cd', 4), u'ab c...') + self.assertEqual(uilib.fallback_safe_cut(u'ab cd', 5), u'ab cd') + self.assertEqual(uilib.fallback_safe_cut(u'ab &d', 4), u'ab &...') + self.assertEqual(uilib.fallback_safe_cut(u'ab &d ef', 5), u'ab &d...') + self.assertEqual(uilib.fallback_safe_cut(u'ab ìd', 4), u'ab ì...') + self.assertEqual(uilib.fallback_safe_cut(u'& &d ef', 4), u'& &d...') def test_lxml_safe_cut(self): - self.assertEquals(uilib.safe_cut(u'aaa
aaad
ef', 4), u'

aaa

a...
') - self.assertEquals(uilib.safe_cut(u'aaa
aaad
ef', 7), u'

aaa

aaad
...') - self.assertEquals(uilib.safe_cut(u'aaa
aaad
', 7), u'

aaa

aaad
') + self.assertEqual(uilib.safe_cut(u'aaa
aaad
ef', 4), u'

aaa

a...
') + self.assertEqual(uilib.safe_cut(u'aaa
aaad
ef', 7), u'

aaa

aaad
...') + self.assertEqual(uilib.safe_cut(u'aaa
aaad
', 7), u'

aaa

aaad
') # Missing ellipsis due to space management but we don't care - self.assertEquals(uilib.safe_cut(u'ab &d', 4), u'

ab &...

') + self.assertEqual(uilib.safe_cut(u'ab &d', 4), u'

ab &...

') def test_cut(self): """tests uilib.cut() behaviour""" @@ -62,7 +62,7 @@ ] for text, expected in data: got = uilib.cut(text, 8) - self.assertEquals(got, expected) + self.assertEqual(got, expected) def test_text_cut(self): """tests uilib.text_cut() behaviour with no text""" @@ -89,62 +89,62 @@ ] for text, expected in data: got = uilib.text_cut(text, 30) - self.assertEquals(got, expected) + self.assertEqual(got, expected) def test_soup2xhtml_1_1(self): - self.assertEquals(uilib.soup2xhtml('hop
', 'ascii'), + self.assertEqual(uilib.soup2xhtml('hop
', 'ascii'), 'hop
') - self.assertEquals(uilib.soup2xhtml('
hop', 'ascii'), + self.assertEqual(uilib.soup2xhtml('
hop', 'ascii'), '
hop
') - self.assertEquals(uilib.soup2xhtml('hop
hop', 'ascii'), + self.assertEqual(uilib.soup2xhtml('hop
hop', 'ascii'), 'hop
hop
') def test_soup2xhtml_1_2(self): - self.assertEquals(uilib.soup2xhtml('hop
', 'ascii'), + self.assertEqual(uilib.soup2xhtml('hop
', 'ascii'), 'hop ') - self.assertEquals(uilib.soup2xhtml('
hop', 'ascii'), + self.assertEqual(uilib.soup2xhtml('
hop', 'ascii'), '
hop') - self.assertEquals(uilib.soup2xhtml('hop
hop', 'ascii'), + self.assertEqual(uilib.soup2xhtml('hop
hop', 'ascii'), '
hop
hop') def test_soup2xhtml_2_1(self): - self.assertEquals(uilib.soup2xhtml('hop ', 'ascii'), + self.assertEqual(uilib.soup2xhtml('hop ', 'ascii'), 'hop ') - self.assertEquals(uilib.soup2xhtml(' hop', 'ascii'), + self.assertEqual(uilib.soup2xhtml(' hop', 'ascii'), ' hop') - self.assertEquals(uilib.soup2xhtml('hop hop', 'ascii'), + self.assertEqual(uilib.soup2xhtml('hop hop', 'ascii'), 'hop hop') def test_soup2xhtml_2_2(self): - self.assertEquals(uilib.soup2xhtml('hop ', 'ascii'), + self.assertEqual(uilib.soup2xhtml('hop ', 'ascii'), 'hop ') - self.assertEquals(uilib.soup2xhtml(' hop', 'ascii'), + self.assertEqual(uilib.soup2xhtml(' hop', 'ascii'), ' hop') - self.assertEquals(uilib.soup2xhtml('hop hop', 'ascii'), + self.assertEqual(uilib.soup2xhtml('hop hop', 'ascii'), 'hop hop') def test_soup2xhtml_3_1(self): - self.assertEquals(uilib.soup2xhtml('hop ', 'ascii'), + self.assertEqual(uilib.soup2xhtml('hop ', 'ascii'), 'hop ') - self.assertEquals(uilib.soup2xhtml(' hop', 'ascii'), + self.assertEqual(uilib.soup2xhtml(' hop', 'ascii'), ' hop') - self.assertEquals(uilib.soup2xhtml('hop hop', 'ascii'), + self.assertEqual(uilib.soup2xhtml('hop hop', 'ascii'), 'hop hop') def test_soup2xhtml_3_2(self): - self.assertEquals(uilib.soup2xhtml('hop ', 'ascii'), + self.assertEqual(uilib.soup2xhtml('hop ', 'ascii'), 'hop ') - self.assertEquals(uilib.soup2xhtml(' hop', 'ascii'), + self.assertEqual(uilib.soup2xhtml(' hop', 'ascii'), ' hop') - self.assertEquals(uilib.soup2xhtml('hop hop', 'ascii'), + self.assertEqual(uilib.soup2xhtml('hop hop', 'ascii'), 'hop hop') def test_js(self): - self.assertEquals(str(uilib.js.pouet(1, "2")), + self.assertEqual(str(uilib.js.pouet(1, "2")), 'pouet(1,"2")') - self.assertEquals(str(uilib.js.cw.pouet(1, "2")), + self.assertEqual(str(uilib.js.cw.pouet(1, "2")), 'cw.pouet(1,"2")') - self.assertEquals(str(uilib.js.cw.pouet(1, "2").pouet(None)), + self.assertEqual(str(uilib.js.cw.pouet(1, "2").pouet(None)), 'cw.pouet(1,"2").pouet(null)') if __name__ == '__main__': diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_utils.py --- a/test/unittest_utils.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_utils.py Wed Sep 29 16:16:32 2010 +0200 @@ -57,47 +57,47 @@ def test_base(self): l = RepeatList(3, (1, 3)) - self.assertEquals(l[0], (1, 3)) - self.assertEquals(l[2], (1, 3)) - self.assertEquals(l[-1], (1, 3)) - self.assertEquals(len(l), 3) + self.assertEqual(l[0], (1, 3)) + self.assertEqual(l[2], (1, 3)) + self.assertEqual(l[-1], (1, 3)) + self.assertEqual(len(l), 3) # XXX - self.assertEquals(l[4], (1, 3)) + self.assertEqual(l[4], (1, 3)) self.failIf(RepeatList(0, None)) def test_slice(self): l = RepeatList(3, (1, 3)) - self.assertEquals(l[0:1], [(1, 3)]) - self.assertEquals(l[0:4], [(1, 3)]*3) - self.assertEquals(l[:], [(1, 3)]*3) + self.assertEqual(l[0:1], [(1, 3)]) + self.assertEqual(l[0:4], [(1, 3)]*3) + self.assertEqual(l[:], [(1, 3)]*3) def test_iter(self): - self.assertEquals(list(RepeatList(3, (1, 3))), + self.assertEqual(list(RepeatList(3, (1, 3))), [(1, 3)]*3) def test_add(self): l = RepeatList(3, (1, 3)) - self.assertEquals(l + [(1, 4)], [(1, 3)]*3 + [(1, 4)]) - self.assertEquals([(1, 4)] + l, [(1, 4)] + [(1, 3)]*3) - self.assertEquals(l + RepeatList(2, (2, 3)), [(1, 3)]*3 + [(2, 3)]*2) + self.assertEqual(l + [(1, 4)], [(1, 3)]*3 + [(1, 4)]) + self.assertEqual([(1, 4)] + l, [(1, 4)] + [(1, 3)]*3) + self.assertEqual(l + RepeatList(2, (2, 3)), [(1, 3)]*3 + [(2, 3)]*2) x = l + RepeatList(2, (1, 3)) self.assertIsInstance(x, RepeatList) - self.assertEquals(len(x), 5) - self.assertEquals(x[0], (1, 3)) + self.assertEqual(len(x), 5) + self.assertEqual(x[0], (1, 3)) x = l + [(1, 3)] * 2 - self.assertEquals(x, [(1, 3)] * 5) + self.assertEqual(x, [(1, 3)] * 5) def test_eq(self): - self.assertEquals(RepeatList(3, (1, 3)), + self.assertEqual(RepeatList(3, (1, 3)), [(1, 3)]*3) def test_pop(self): l = RepeatList(3, (1, 3)) l.pop(2) - self.assertEquals(l, [(1, 3)]*2) + self.assertEqual(l, [(1, 3)]*2) class SizeConstrainedListTC(TestCase): @@ -106,7 +106,7 @@ l = SizeConstrainedList(10) for i in xrange(12): l.append(i) - self.assertEquals(l, range(2, 12)) + self.assertEqual(l, range(2, 12)) def test_extend(self): testdata = [(range(5), range(5)), @@ -116,44 +116,44 @@ for extension, expected in testdata: l = SizeConstrainedList(10) l.extend(extension) - yield self.assertEquals, l, expected + yield self.assertEqual, l, expected class JSONEncoderTC(TestCase): def setUp(self): if json is None: - self.skip('json not available') + self.skipTest('json not available') def encode(self, value): return json.dumps(value, cls=CubicWebJsonEncoder) def test_encoding_dates(self): - self.assertEquals(self.encode(datetime.datetime(2009, 9, 9, 20, 30)), + self.assertEqual(self.encode(datetime.datetime(2009, 9, 9, 20, 30)), '"2009/09/09 20:30:00"') - self.assertEquals(self.encode(datetime.date(2009, 9, 9)), + self.assertEqual(self.encode(datetime.date(2009, 9, 9)), '"2009/09/09"') - self.assertEquals(self.encode(datetime.time(20, 30)), + self.assertEqual(self.encode(datetime.time(20, 30)), '"20:30:00"') def test_encoding_decimal(self): - self.assertEquals(self.encode(decimal.Decimal('1.2')), '1.2') + self.assertEqual(self.encode(decimal.Decimal('1.2')), '1.2') def test_encoding_bare_entity(self): e = Entity(None) e.cw_attr_cache['pouet'] = 'hop' e.eid = 2 - self.assertEquals(json.loads(self.encode(e)), + self.assertEqual(json.loads(self.encode(e)), {'pouet': 'hop', 'eid': 2}) def test_encoding_entity_in_list(self): e = Entity(None) e.cw_attr_cache['pouet'] = 'hop' e.eid = 2 - self.assertEquals(json.loads(self.encode([e])), + self.assertEqual(json.loads(self.encode([e])), [{'pouet': 'hop', 'eid': 2}]) def test_encoding_unknown_stuff(self): - self.assertEquals(self.encode(TestCase), 'null') + self.assertEqual(self.encode(TestCase), 'null') if __name__ == '__main__': diff -r e3994fcc21c3 -r 1806148d6ce8 test/unittest_vregistry.py --- a/test/unittest_vregistry.py Thu Sep 23 23:28:58 2010 +0200 +++ b/test/unittest_vregistry.py Wed Sep 29 16:16:32 2010 +0200 @@ -48,9 +48,9 @@ self.vreg.load_file(join(BASE, 'entities', '__init__.py'), 'cubicweb.entities.__init__') self.vreg.load_file(join(WEBVIEWSDIR, 'idownloadable.py'), 'cubicweb.web.views.idownloadable') self.vreg.load_file(join(WEBVIEWSDIR, 'primary.py'), 'cubicweb.web.views.primary') - self.assertEquals(len(self.vreg['views']['primary']), 2) + self.assertEqual(len(self.vreg['views']['primary']), 2) self.vreg.initialization_completed() - self.assertEquals(len(self.vreg['views']['primary']), 1) + self.assertEqual(len(self.vreg['views']['primary']), 1) def test_load_subinterface_based_appobjects(self): @@ -70,7 +70,7 @@ self.vreg.register(CardIProgressAdapter) self.vreg.initialization_completed() # check progressbar isn't kicked - self.assertEquals(len(self.vreg['views']['progressbar']), 1) + self.assertEqual(len(self.vreg['views']['progressbar']), 1) def test_properties(self): self.vreg.reset() @@ -84,7 +84,7 @@ def test_property_default_overriding(self): # see data/views.py from cubicweb.web.views.xmlrss import RSSIconBox - self.assertEquals(self.vreg.property_info(RSSIconBox._cwpropkey('visible'))['default'], True) + self.assertEqual(self.vreg.property_info(RSSIconBox._cwpropkey('visible'))['default'], True) if __name__ == '__main__': unittest_main() diff -r e3994fcc21c3 -r 1806148d6ce8 vregistry.py --- a/vregistry.py Thu Sep 23 23:28:58 2010 +0200 +++ b/vregistry.py Wed Sep 29 16:16:32 2010 +0200 @@ -46,6 +46,7 @@ from cubicweb import RegistryNotFound, ObjectNotFound, NoSelectableObject from cubicweb.appobject import AppObject, class_regid + def _toload_info(path, extrapath, _toload=None): """return a dictionary of : and an ordered list of (file, module name) to load @@ -221,17 +222,14 @@ elif appobjectscore > 0 and appobjectscore == score: winners.append(appobject) if winners is None: - raise NoSelectableObject('args: %s\nkwargs: %s %s' - % (args, kwargs.keys(), - [repr(v) for v in appobjects])) + raise NoSelectableObject(args, kwargs, appobjects) if len(winners) > 1: # log in production environement / test, error while debugging + msg = 'select ambiguity: %s\n(args: %s, kwargs: %s)' if self.config.debugmode or self.config.mode == 'test': - raise Exception('select ambiguity, args: %s\nkwargs: %s %s' - % (args, kwargs.keys(), - [repr(v) for v in winners])) - self.error('select ambiguity, args: %s\nkwargs: %s %s', - args, kwargs.keys(), [repr(v) for v in winners]) + # raise bare exception in debug mode + raise Exception(msg % (winners, self.args, self.kwargs.keys())) + self.error(msg, winners, self.args, self.kwargs.keys()) # return the result of calling the appobject return winners[0](*args, **kwargs) diff -r e3994fcc21c3 -r 1806148d6ce8 web/data/cubicweb.css --- a/web/data/cubicweb.css Thu Sep 23 23:28:58 2010 +0200 +++ b/web/data/cubicweb.css Wed Sep 29 16:16:32 2010 +0200 @@ -201,6 +201,18 @@ display: inline; } +.caption { + font-weight: bold; +} + +.legend{ + font-style: italic; +} + +.align-center{ + text-align: center; +} + /***************************************/ /* LAYOUT */ /***************************************/ diff -r e3994fcc21c3 -r 1806148d6ce8 web/data/cubicweb.old.css --- a/web/data/cubicweb.old.css Thu Sep 23 23:28:58 2010 +0200 +++ b/web/data/cubicweb.old.css Wed Sep 29 16:16:32 2010 +0200 @@ -208,6 +208,17 @@ display: inline; } +.caption { + font-weight: bold; +} + +.legend{ + font-style: italic; +} + +.align-center{ + text-align: center; +} /***************************************/ /* LAYOUT */ diff -r e3994fcc21c3 -r 1806148d6ce8 web/facet.py --- a/web/facet.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/facet.py Wed Sep 29 16:16:32 2010 +0200 @@ -64,6 +64,14 @@ from cubicweb.appobject import AppObject from cubicweb.web.htmlwidgets import HTMLWidget + +def rtype_facet_title(facet): + ptypes = facet.cw_rset.column_types(0) + if len(ptypes) == 1: + return display_name(facet._cw, facet.rtype, form=facet.role, + context=iter(ptypes).next()) + return display_name(facet._cw, facet.rtype, form=facet.role) + ## rqlst manipulation functions used by facets ################################ def prepare_facets_rqlst(rqlst, args=None): @@ -511,9 +519,7 @@ # internal purpose _select_target_entity = True - @property - def title(self): - return display_name(self._cw, self.rtype, form=self.role) + title = property(rtype_facet_title) @property def rql_sort(self): @@ -888,9 +894,7 @@ rtype = None # override me in subclass role = 'subject' # role of filtered entity in the relation - @property - def title(self): - return display_name(self._cw, self.rtype, self.role) + title = property(rtype_facet_title) def support_and(self): return False diff -r e3994fcc21c3 -r 1806148d6ce8 web/request.py --- a/web/request.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/request.py Wed Sep 29 16:16:32 2010 +0200 @@ -531,7 +531,7 @@ """set output content type for this request. An optional filename may be given """ - if content_type.startswith('text/'): + if content_type.startswith('text/') and ';charset=' not in content_type: content_type += ';charset=' + (encoding or self.encoding) self.set_header('content-type', content_type) if filename: diff -r e3994fcc21c3 -r 1806148d6ce8 web/test/test_views.py --- a/web/test/test_views.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/test/test_views.py Wed Sep 29 16:16:32 2010 +0200 @@ -66,7 +66,7 @@ self.vreg.register(SomeView) rset = self.execute('CWUser X') source = self.view('someview', rset).source - self.assertEquals(source.count('spam.js'), 1) + self.assertEqual(source.count('spam.js'), 1) diff -r e3994fcc21c3 -r 1806148d6ce8 web/test/unittest_application.py --- a/web/test/unittest_application.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/test/unittest_application.py Wed Sep 29 16:16:32 2010 +0200 @@ -69,32 +69,32 @@ def test_list_arg(self): """tests the list_arg() function""" list_arg = self._cw.list_form_param - self.assertEquals(list_arg('arg3', {}), []) + self.assertEqual(list_arg('arg3', {}), []) d = {'arg1' : "value1", 'arg2' : ('foo', INTERNAL_FIELD_VALUE,), 'arg3' : ['bar']} - self.assertEquals(list_arg('arg1', d, True), ['value1']) - self.assertEquals(d, {'arg2' : ('foo', INTERNAL_FIELD_VALUE), 'arg3' : ['bar'],}) - self.assertEquals(list_arg('arg2', d, True), ['foo']) - self.assertEquals({'arg3' : ['bar'],}, d) - self.assertEquals(list_arg('arg3', d), ['bar',]) - self.assertEquals({'arg3' : ['bar'],}, d) + self.assertEqual(list_arg('arg1', d, True), ['value1']) + self.assertEqual(d, {'arg2' : ('foo', INTERNAL_FIELD_VALUE), 'arg3' : ['bar'],}) + self.assertEqual(list_arg('arg2', d, True), ['foo']) + self.assertEqual({'arg3' : ['bar'],}, d) + self.assertEqual(list_arg('arg3', d), ['bar',]) + self.assertEqual({'arg3' : ['bar'],}, d) def test_from_controller(self): self._cw.vreg['controllers'] = {'view': 1, 'login': 1} - self.assertEquals(self._cw.from_controller(), 'view') + self.assertEqual(self._cw.from_controller(), 'view') req = FakeRequest(url='project?vid=list') req.vreg['controllers'] = {'view': 1, 'login': 1} # this assertion is just to make sure that relative_path can be # correctly computed as it is used in from_controller() - self.assertEquals(req.relative_path(False), 'project') - self.assertEquals(req.from_controller(), 'view') + self.assertEqual(req.relative_path(False), 'project') + self.assertEqual(req.from_controller(), 'view') # test on a valid non-view controller req = FakeRequest(url='login?x=1&y=2') req.vreg['controllers'] = {'view': 1, 'login': 1} - self.assertEquals(req.relative_path(False), 'login') - self.assertEquals(req.from_controller(), 'login') + self.assertEqual(req.relative_path(False), 'login') + self.assertEqual(req.from_controller(), 'login') class UtilsTC(TestCase): @@ -107,22 +107,22 @@ # """tests which mapping is used (application or core)""" # init_mapping() # from cubicweb.common import mapping - # self.assertEquals(mapping.MAPPING_USED, 'core') + # self.assertEqual(mapping.MAPPING_USED, 'core') # sys.modules['mapping'] = FakeMapping() # init_mapping() - # self.assertEquals(mapping.MAPPING_USED, 'application') + # self.assertEqual(mapping.MAPPING_USED, 'application') # del sys.modules['mapping'] def test_execute_linkto(self): """tests the execute_linkto() function""" - self.assertEquals(self.ctrl.execute_linkto(), None) - self.assertEquals(self.ctrl._cursor.executed, + self.assertEqual(self.ctrl.execute_linkto(), None) + self.assertEqual(self.ctrl._cursor.executed, []) self.ctrl.set_form({'__linkto' : 'works_for:12_13_14:object', 'eid': 8}) self.ctrl.execute_linkto() - self.assertEquals(self.ctrl._cursor.executed, + self.assertEqual(self.ctrl._cursor.executed, ['SET Y works_for X WHERE X eid 8, Y eid %s' % i for i in (12, 13, 14)]) @@ -130,7 +130,7 @@ self.ctrl.set_form({'__linkto' : 'works_for:12_13_14:subject', 'eid': 8}) self.ctrl.execute_linkto() - self.assertEquals(self.ctrl._cursor.executed, + self.assertEqual(self.ctrl._cursor.executed, ['SET X works_for Y WHERE X eid 8, Y eid %s' % i for i in (12, 13, 14)]) @@ -138,14 +138,14 @@ self.ctrl.new_cursor() self.ctrl._cw.form = {'__linkto' : 'works_for:12_13_14:object'} self.ctrl.execute_linkto(eid=8) - self.assertEquals(self.ctrl._cursor.executed, + self.assertEqual(self.ctrl._cursor.executed, ['SET Y works_for X WHERE X eid 8, Y eid %s' % i for i in (12, 13, 14)]) self.ctrl.new_cursor() self.ctrl.set_form({'__linkto' : 'works_for:12_13_14:subject'}) self.ctrl.execute_linkto(eid=8) - self.assertEquals(self.ctrl._cursor.executed, + self.assertEqual(self.ctrl._cursor.executed, ['SET X works_for Y WHERE X eid 8, Y eid %s' % i for i in (12, 13, 14)]) @@ -159,13 +159,13 @@ def test_cnx_user_groups_sync(self): user = self.user() - self.assertEquals(user.groups, set(('managers',))) + self.assertEqual(user.groups, set(('managers',))) self.execute('SET X in_group G WHERE X eid %s, G name "guests"' % user.eid) user = self.user() - self.assertEquals(user.groups, set(('managers',))) + self.assertEqual(user.groups, set(('managers',))) self.commit() user = self.user() - self.assertEquals(user.groups, set(('managers', 'guests'))) + self.assertEqual(user.groups, set(('managers', 'guests'))) # cleanup self.execute('DELETE X in_group G WHERE X eid %s, G name "guests"' % user.eid) self.commit() @@ -193,13 +193,13 @@ path, params = self.expect_redirect(lambda x: self.app_publish(x, 'edit'), req) forminfo = req.session.data['view?vid=edition...'] eidmap = forminfo['eidmap'] - self.assertEquals(eidmap, {}) + self.assertEqual(eidmap, {}) values = forminfo['values'] - self.assertEquals(values['login-subject:'+eid], '') - self.assertEquals(values['eid'], eid) + self.assertEqual(values['login-subject:'+eid], '') + self.assertEqual(values['eid'], eid) error = forminfo['error'] - self.assertEquals(error.entity, user.eid) - self.assertEquals(error.errors['login-subject'], 'required field') + self.assertEqual(error.entity, user.eid) + self.assertEqual(error.errors['login-subject'], 'required field') def test_validation_error_dont_loose_subentity_data_ctrl(self): @@ -222,13 +222,13 @@ } path, params = self.expect_redirect(lambda x: self.app_publish(x, 'edit'), req) forminfo = req.session.data['view?vid=edition...'] - self.assertEquals(set(forminfo['eidmap']), set('XY')) - self.assertEquals(forminfo['eidmap']['X'], None) + self.assertEqual(set(forminfo['eidmap']), set('XY')) + self.assertEqual(forminfo['eidmap']['X'], None) self.assertIsInstance(forminfo['eidmap']['Y'], int) - self.assertEquals(forminfo['error'].entity, 'X') - self.assertEquals(forminfo['error'].errors, + self.assertEqual(forminfo['error'].entity, 'X') + self.assertEqual(forminfo['error'].errors, {'login-subject': 'required field'}) - self.assertEquals(forminfo['values'], req.form) + self.assertEqual(forminfo['values'], req.form) def test_validation_error_dont_loose_subentity_data_repo(self): @@ -251,13 +251,13 @@ } path, params = self.expect_redirect(lambda x: self.app_publish(x, 'edit'), req) forminfo = req.session.data['view?vid=edition...'] - self.assertEquals(set(forminfo['eidmap']), set('XY')) + self.assertEqual(set(forminfo['eidmap']), set('XY')) self.assertIsInstance(forminfo['eidmap']['X'], int) self.assertIsInstance(forminfo['eidmap']['Y'], int) - self.assertEquals(forminfo['error'].entity, forminfo['eidmap']['X']) - self.assertEquals(forminfo['error'].errors, + self.assertEqual(forminfo['error'].entity, forminfo['eidmap']['X']) + self.assertEqual(forminfo['error'].errors, {'login-subject': u'the value "admin" is already used, use another one'}) - self.assertEquals(forminfo['values'], req.form) + self.assertEqual(forminfo['values'], req.form) def _test_cleaned(self, kwargs, injected, cleaned): @@ -282,24 +282,24 @@ # protocol vreg = self.app.vreg # default value - self.assertEquals(vreg.property_value('ui.language'), 'en') + self.assertEqual(vreg.property_value('ui.language'), 'en') self.execute('INSERT CWProperty X: X value "fr", X pkey "ui.language"') - self.assertEquals(vreg.property_value('ui.language'), 'en') + self.assertEqual(vreg.property_value('ui.language'), 'en') self.commit() - self.assertEquals(vreg.property_value('ui.language'), 'fr') + self.assertEqual(vreg.property_value('ui.language'), 'fr') self.execute('SET X value "de" WHERE X pkey "ui.language"') - self.assertEquals(vreg.property_value('ui.language'), 'fr') + self.assertEqual(vreg.property_value('ui.language'), 'fr') self.commit() - self.assertEquals(vreg.property_value('ui.language'), 'de') + self.assertEqual(vreg.property_value('ui.language'), 'de') self.execute('DELETE CWProperty X WHERE X pkey "ui.language"') - self.assertEquals(vreg.property_value('ui.language'), 'de') + self.assertEqual(vreg.property_value('ui.language'), 'de') self.commit() - self.assertEquals(vreg.property_value('ui.language'), 'en') + self.assertEqual(vreg.property_value('ui.language'), 'en') def test_login_not_available_to_authenticated(self): req = self.request() ex = self.assertRaises(Unauthorized, self.app_publish, req, 'login') - self.assertEquals(str(ex), 'log out first') + self.assertEqual(str(ex), 'log out first') def test_fb_login_concept(self): """see data/views.py""" @@ -311,7 +311,7 @@ req.form['__fblogin'] = u'turlututu' page = self.app_publish(req) self.failIf(req.cnx is origcnx) - self.assertEquals(req.user.login, 'turlututu') + self.assertEqual(req.user.login, 'turlututu') self.failUnless('turlututu' in page, page) # authentication tests #################################################### @@ -320,13 +320,13 @@ req, origsession = self.init_authentication('http') self.assertAuthFailure(req) self.assertRaises(AuthenticationError, self.app_publish, req, 'login') - self.assertEquals(req.cnx, None) + self.assertEqual(req.cnx, None) authstr = base64.encodestring('%s:%s' % (origsession.login, origsession.authinfo['password'])) req._headers['Authorization'] = 'basic %s' % authstr self.assertAuthSuccess(req, origsession) - self.assertEquals(req.session.authinfo, {'password': origsession.authinfo['password']}) + self.assertEqual(req.session.authinfo, {'password': origsession.authinfo['password']}) self.assertRaises(LogOut, self.app_publish, req, 'logout') - self.assertEquals(len(self.open_sessions), 0) + self.assertEqual(len(self.open_sessions), 0) def test_cookie_auth_no_anon(self): req, origsession = self.init_authentication('cookie') @@ -334,13 +334,13 @@ form = self.app_publish(req, 'login') self.failUnless('__login' in form) self.failUnless('__password' in form) - self.assertEquals(req.cnx, None) + self.assertEqual(req.cnx, None) req.form['__login'] = origsession.login req.form['__password'] = origsession.authinfo['password'] self.assertAuthSuccess(req, origsession) - self.assertEquals(req.session.authinfo, {'password': origsession.authinfo['password']}) + self.assertEqual(req.session.authinfo, {'password': origsession.authinfo['password']}) self.assertRaises(LogOut, self.app_publish, req, 'logout') - self.assertEquals(len(self.open_sessions), 0) + self.assertEqual(len(self.open_sessions), 0) def test_login_by_email(self): login = self.request().user.login @@ -359,9 +359,9 @@ req.form['__login'] = address req.form['__password'] = origsession.authinfo['password'] self.assertAuthSuccess(req, origsession) - self.assertEquals(req.session.authinfo, {'password': origsession.authinfo['password']}) + self.assertEqual(req.session.authinfo, {'password': origsession.authinfo['password']}) self.assertRaises(LogOut, self.app_publish, req, 'logout') - self.assertEquals(len(self.open_sessions), 0) + self.assertEqual(len(self.open_sessions), 0) def _reset_cookie(self, req): # preparing the suite of the test @@ -376,18 +376,18 @@ def _test_auth_anon(self, req): self.app.connect(req) asession = req.session - self.assertEquals(len(self.open_sessions), 1) - self.assertEquals(asession.login, 'anon') - self.assertEquals(asession.authinfo['password'], 'anon') + self.assertEqual(len(self.open_sessions), 1) + self.assertEqual(asession.login, 'anon') + self.assertEqual(asession.authinfo['password'], 'anon') self.failUnless(asession.anonymous_session) self._reset_cookie(req) def _test_anon_auth_fail(self, req): - self.assertEquals(len(self.open_sessions), 1) + self.assertEqual(len(self.open_sessions), 1) self.app.connect(req) - self.assertEquals(req.message, 'authentication failure') - self.assertEquals(req.session.anonymous_session, True) - self.assertEquals(len(self.open_sessions), 1) + self.assertEqual(req.message, 'authentication failure') + self.assertEqual(req.session.anonymous_session, True) + self.assertEqual(len(self.open_sessions), 1) self._reset_cookie(req) def test_http_auth_anon_allowed(self): @@ -399,9 +399,9 @@ authstr = base64.encodestring('%s:%s' % (origsession.login, origsession.authinfo['password'])) req._headers['Authorization'] = 'basic %s' % authstr self.assertAuthSuccess(req, origsession) - self.assertEquals(req.session.authinfo, {'password': origsession.authinfo['password']}) + self.assertEqual(req.session.authinfo, {'password': origsession.authinfo['password']}) self.assertRaises(LogOut, self.app_publish, req, 'logout') - self.assertEquals(len(self.open_sessions), 0) + self.assertEqual(len(self.open_sessions), 0) def test_cookie_auth_anon_allowed(self): req, origsession = self.init_authentication('cookie', 'anon') @@ -412,10 +412,10 @@ req.form['__login'] = origsession.login req.form['__password'] = origsession.authinfo['password'] self.assertAuthSuccess(req, origsession) - self.assertEquals(req.session.authinfo, + self.assertEqual(req.session.authinfo, {'password': origsession.authinfo['password']}) self.assertRaises(LogOut, self.app_publish, req, 'logout') - self.assertEquals(len(self.open_sessions), 0) + self.assertEqual(len(self.open_sessions), 0) def test_non_regr_optional_first_var(self): req = self.request() diff -r e3994fcc21c3 -r 1806148d6ce8 web/test/unittest_breadcrumbs.py --- a/web/test/unittest_breadcrumbs.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/test/unittest_breadcrumbs.py Wed Sep 29 16:16:32 2010 +0200 @@ -28,11 +28,11 @@ self.execute('SET F2 filed_under F1 WHERE F1 eid %(f1)s, F2 eid %(f2)s', {'f1' : f1.eid, 'f2' : f2.eid}) self.commit() - self.assertEquals(f2.view('breadcrumbs'), + self.assertEqual(f2.view('breadcrumbs'), 'chi&ld' % f2.eid) childrset = f2.as_rset() ibc = self.vreg['components'].select('breadcrumbs', self.request(), rset=childrset) - self.assertEquals(ibc.render(), + self.assertEqual(ibc.render(), """ > folder_plural > par&ent >  chi&ld""" % (f1.eid, f2.eid)) diff -r e3994fcc21c3 -r 1806148d6ce8 web/test/unittest_facet.py --- a/web/test/unittest_facet.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/test/unittest_facet.py Wed Sep 29 16:16:32 2010 +0200 @@ -9,12 +9,12 @@ rqlst = rset.syntax_tree().copy() req.vreg.rqlhelper.annotate(rqlst) mainvar, baserql = facet.prepare_facets_rqlst(rqlst, rset.args) - self.assertEquals(mainvar.name, 'X') - self.assertEquals(baserql, 'Any X WHERE X is CWUser') - self.assertEquals(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') + self.assertEqual(mainvar.name, 'X') + self.assertEqual(baserql, 'Any X WHERE X is CWUser') + self.assertEqual(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') return req, rset, rqlst, mainvar - def test_relation(self): + def test_relation_simple(self): req, rset, rqlst, mainvar = self.prepare_rqlst() f = facet.RelationFacet(req, rset=rset, rqlst=rqlst.children[0], @@ -24,22 +24,55 @@ f.target_attr = 'name' guests, managers = [eid for eid, in self.execute('CWGroup G ORDERBY GN ' 'WHERE G name GN, G name IN ("guests", "managers")')] - self.assertEquals(f.vocabulary(), + self.assertEqual(f.vocabulary(), [(u'guests', guests), (u'managers', managers)]) # ensure rqlst is left unmodified - self.assertEquals(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') + self.assertEqual(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') #rqlst = rset.syntax_tree() - self.assertEquals(f.possible_values(), + self.assertEqual(f.possible_values(), [str(guests), str(managers)]) # ensure rqlst is left unmodified - self.assertEquals(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') + self.assertEqual(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') req.form[f.__regid__] = str(guests) f.add_rql_restrictions() # selection is cluttered because rqlst has been prepared for facet (it # is not in real life) - self.assertEquals(f.rqlst.as_string(), + self.assertEqual(f.rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser, X in_group D, D eid %s' % guests) + def test_relation_optional_rel(self): + req = self.request() + rset = self.execute('Any X,GROUP_CONCAT(GN) GROUPBY X ' + 'WHERE X in_group G?, G name GN, NOT G name "users"') + rqlst = rset.syntax_tree().copy() + req.vreg.rqlhelper.annotate(rqlst) + mainvar, baserql = facet.prepare_facets_rqlst(rqlst, rset.args) + + f = facet.RelationFacet(req, rset=rset, + rqlst=rqlst.children[0], + filtered_variable=mainvar) + f.rtype = 'in_group' + f.role = 'subject' + f.target_attr = 'name' + guests, managers = [eid for eid, in self.execute('CWGroup G ORDERBY GN ' + 'WHERE G name GN, G name IN ("guests", "managers")')] + self.assertEqual(f.vocabulary(), + [(u'guests', guests), (u'managers', managers)]) + # ensure rqlst is left unmodified + self.assertEqual(rqlst.as_string(), 'DISTINCT Any GROUPBY X WHERE X in_group G?, G name GN, NOT G name "users"') + #rqlst = rset.syntax_tree() + self.assertEqual(sorted(f.possible_values()), + [str(guests), str(managers)]) + # ensure rqlst is left unmodified + self.assertEqual(rqlst.as_string(), 'DISTINCT Any GROUPBY X WHERE X in_group G?, G name GN, NOT G name "users"') + req.form[f.__regid__] = str(guests) + f.add_rql_restrictions() + # selection is cluttered because rqlst has been prepared for facet (it + # is not in real life) + self.assertEqual(f.rqlst.as_string(), + 'DISTINCT Any GROUPBY X WHERE X in_group G?, G name GN, NOT G name "users", X in_group D, D eid %s' % guests) + + def test_relationattribute(self): req, rset, rqlst, mainvar = self.prepare_rqlst() f = facet.RelationAttributeFacet(req, rset=rset, @@ -48,20 +81,20 @@ f.rtype = 'in_group' f.role = 'subject' f.target_attr = 'name' - self.assertEquals(f.vocabulary(), + self.assertEqual(f.vocabulary(), [(u'guests', u'guests'), (u'managers', u'managers')]) # ensure rqlst is left unmodified - self.assertEquals(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') + self.assertEqual(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') #rqlst = rset.syntax_tree() - self.assertEquals(f.possible_values(), + self.assertEqual(f.possible_values(), ['guests', 'managers']) # ensure rqlst is left unmodified - self.assertEquals(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') + self.assertEqual(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') req.form[f.__regid__] = 'guests' f.add_rql_restrictions() # selection is cluttered because rqlst has been prepared for facet (it # is not in real life) - self.assertEquals(f.rqlst.as_string(), + self.assertEqual(f.rqlst.as_string(), "DISTINCT Any WHERE X is CWUser, X in_group E, E name 'guests'") @@ -71,18 +104,18 @@ rqlst=rqlst.children[0], filtered_variable=mainvar) f.rtype = 'login' - self.assertEquals(f.vocabulary(), + self.assertEqual(f.vocabulary(), [(u'admin', u'admin'), (u'anon', u'anon')]) # ensure rqlst is left unmodified - self.assertEquals(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') + self.assertEqual(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') #rqlst = rset.syntax_tree() - self.assertEquals(f.possible_values(), + self.assertEqual(f.possible_values(), ['admin', 'anon']) # ensure rqlst is left unmodified - self.assertEquals(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') + self.assertEqual(rqlst.as_string(), 'DISTINCT Any WHERE X is CWUser') req.form[f.__regid__] = 'admin' f.add_rql_restrictions() # selection is cluttered because rqlst has been prepared for facet (it # is not in real life) - self.assertEquals(f.rqlst.as_string(), + self.assertEqual(f.rqlst.as_string(), "DISTINCT Any WHERE X is CWUser, X login 'admin'") diff -r e3994fcc21c3 -r 1806148d6ce8 web/test/unittest_form.py --- a/web/test/unittest_form.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/test/unittest_form.py Wed Sep 29 16:16:32 2010 +0200 @@ -36,10 +36,10 @@ def test_form_field_format(self): form = FieldsForm(self.request(), None) - self.assertEquals(StringField().format(form), 'text/html') + self.assertEqual(StringField().format(form), 'text/html') self.execute('INSERT CWProperty X: X pkey "ui.default-text-format", X value "text/rest", X for_user U WHERE U login "admin"') self.commit() - self.assertEquals(StringField().format(form), 'text/rest') + self.assertEqual(StringField().format(form), 'text/rest') class EntityFieldsFormTC(CubicWebTC): @@ -70,7 +70,7 @@ form = self.vreg['forms'].select('edition', self.req, entity=e) unrelated = [rview for rview, reid in form.field_by_name('in_group', 'subject').choices(form)] # should be default groups but owners, i.e. managers, users, guests - self.assertEquals(unrelated, [u'guests', u'managers', u'users']) + self.assertEqual(unrelated, [u'guests', u'managers', u'users']) def test_consider_req_form_params(self): e = self.vreg['etypes'].etype_class('CWUser')(self.request()) @@ -79,7 +79,7 @@ field = StringField(name='login', role='subject', eidparam=True) form.append_field(field) form.build_context({}) - self.assertEquals(field.widget.values(form, field), (u'toto',)) + self.assertEqual(field.widget.values(form, field), (u'toto',)) def test_linkto_field_duplication(self): @@ -144,7 +144,7 @@ form = RTFForm(self.req, redirect_path='perdu.com', entity=state) # make it think it can use fck editor anyway form.field_by_name('description', 'subject').format = lambda x: 'text/html' - self.assertTextEquals(self._render_entity_field('description', form), + self.assertMultiLineEqual(self._render_entity_field('description', form), expected % {'eid': state.eid}) @@ -174,7 +174,7 @@ file = self.req.create_entity('File', data_name=u"pouet.txt", data_encoding=u'UTF-8', data=Binary('new widgets system')) form = FFForm(self.req, redirect_path='perdu.com', entity=file) - self.assertTextEquals(self._render_entity_field('data', form), + self.assertMultiLineEqual(self._render_entity_field('data', form), ''' show advanced fields
-detach attached file -''' % {'eid': file.eid}) +detach attached file''' % {'eid': file.eid}) def test_editablefilefield(self): @@ -198,7 +197,7 @@ file = self.req.create_entity('File', data_name=u"pouet.txt", data_encoding=u'UTF-8', data=Binary('new widgets system')) form = EFFForm(self.req, redirect_path='perdu.com', entity=file) - self.assertTextEquals(self._render_entity_field('data', form), + self.assertMultiLineEqual(self._render_entity_field('data', form), ''' show advanced fields
+ self.assertEqual(content.strip(), '''
@@ -35,7 +35,7 @@ view = self.vreg['views'].select('pyvallist', self.request(), pyvalue=[1, 'a']) content = view.render(pyvalue=[1, 'a']) - self.assertEquals(content.strip(), '''
    + self.assertEqual(content.strip(), '''
    • 1
    • a
    ''') diff -r e3994fcc21c3 -r 1806148d6ce8 web/test/unittest_views_searchrestriction.py --- a/web/test/unittest_views_searchrestriction.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/test/unittest_views_searchrestriction.py Wed Sep 29 16:16:32 2010 +0200 @@ -46,32 +46,32 @@ 'B in_group P, P name "managers"') def test_1(self): - self.assertEquals(self._generate(self.select, 'in_state', 'subject', 'name'), + self.assertEqual(self._generate(self.select, 'in_state', 'subject', 'name'), "DISTINCT Any A,C ORDERBY C WHERE B in_group P, P name 'managers', " "B in_state A, B is CWUser, A name C") def test_2(self): - self.assertEquals(self._generate(self.select, 'tags', 'object', 'name'), + self.assertEqual(self._generate(self.select, 'tags', 'object', 'name'), "DISTINCT Any A,C ORDERBY C WHERE B in_group P, P name 'managers', " "A tags B, B is CWUser, A name C") def test_3(self): - self.assertEquals(self._generate(self.select, 'created_by', 'subject', 'login'), + self.assertEqual(self._generate(self.select, 'created_by', 'subject', 'login'), "DISTINCT Any A,C ORDERBY C WHERE B in_group P, P name 'managers', " "B created_by A, B is CWUser, A login C") def test_4(self): - self.assertEquals(self._generate(self.parse('Any X WHERE X is CWUser'), 'created_by', 'subject', 'login'), + self.assertEqual(self._generate(self.parse('Any X WHERE X is CWUser'), 'created_by', 'subject', 'login'), "DISTINCT Any A,B ORDERBY B WHERE X is CWUser, X created_by A, A login B") def test_5(self): - self.assertEquals(self._generate(self.parse('Any X,L WHERE X is CWUser, X login L'), 'created_by', 'subject', 'login'), + self.assertEqual(self._generate(self.parse('Any X,L WHERE X is CWUser, X login L'), 'created_by', 'subject', 'login'), "DISTINCT Any A,B ORDERBY B WHERE X is CWUser, X created_by A, A login B") def test_nonregr1(self): select = self.parse('Any T,V WHERE T bookmarked_by V?, ' 'V in_state VS, VS name "published", T created_by U') - self.assertEquals(self._generate(select, 'created_by', 'subject', 'login'), + self.assertEqual(self._generate(select, 'created_by', 'subject', 'login'), "DISTINCT Any A,B ORDERBY B WHERE T created_by U, " "T created_by A, T is Bookmark, A login B") @@ -83,7 +83,7 @@ for rdefs in rschema.rdefs.values(): rdefs.cardinality = '++' try: - self.assertEquals(self._generate(select, 'in_state', 'subject', 'name'), + self.assertEqual(self._generate(select, 'in_state', 'subject', 'name'), "DISTINCT Any A,B ORDERBY B WHERE V is CWUser, " "NOT EXISTS(V in_state VS), VS name 'published', " "V in_state A, A name B") @@ -94,7 +94,7 @@ def test_nonregr3(self): #'DISTINCT Any X,TMP,N WHERE P name TMP, X version_of P, P is Project, X is Version, not X in_state S,S name "published", X num N ORDERBY TMP,N' select = self.parse('DISTINCT Any X, MAX(Y) GROUPBY X WHERE X is CWUser, Y is Bookmark, X in_group A') - self.assertEquals(self._generate(select, 'in_group', 'subject', 'name'), + self.assertEqual(self._generate(select, 'in_group', 'subject', 'name'), "DISTINCT Any B,C ORDERBY C WHERE X is CWUser, X in_group B, B name C") diff -r e3994fcc21c3 -r 1806148d6ce8 web/test/unittest_viewselector.py --- a/web/test/unittest_viewselector.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/test/unittest_viewselector.py Wed Sep 29 16:16:32 2010 +0200 @@ -65,7 +65,7 @@ except AttributeError: return if registry == 'hooks': - self.assertEquals(len(content), expected, content) + self.assertEqual(len(content), expected, content) return try: self.assertSetEqual(content.keys(), expected) @@ -467,19 +467,36 @@ def test_properties(self): +<<<<<<< /home/syt/src/fcubicweb/cubicweb/web/test/unittest_viewselector.py self.assertEquals(sorted(k for k in self.vreg['propertydefs'].keys() if k.startswith('ctxcomponents.edit_box')), ['ctxcomponents.edit_box.context', 'ctxcomponents.edit_box.order', 'ctxcomponents.edit_box.visible']) self.assertEquals([k for k in self.vreg['propertyvalues'].keys() +======= + self.assertEqual(sorted(k for k in self.vreg['propertydefs'].keys() + if k.startswith('boxes.edit_box')), + ['boxes.edit_box.context', + 'boxes.edit_box.order', + 'boxes.edit_box.visible']) + self.assertEqual([k for k in self.vreg['propertyvalues'].keys() +>>>>>>> /tmp/unittest_viewselector.py~other.F5zfDM if not k.startswith('system.version')], []) +<<<<<<< /home/syt/src/fcubicweb/cubicweb/web/test/unittest_viewselector.py self.assertEquals(self.vreg.property_value('ctxcomponents.edit_box.visible'), True) self.assertEquals(self.vreg.property_value('ctxcomponents.edit_box.order'), 2) self.assertEquals(self.vreg.property_value('ctxcomponents.possible_views_box.visible'), False) self.assertEquals(self.vreg.property_value('ctxcomponents.possible_views_box.order'), 10) self.assertRaises(UnknownProperty, self.vreg.property_value, 'ctxcomponents.actions_box') +======= + self.assertEqual(self.vreg.property_value('boxes.edit_box.visible'), True) + self.assertEqual(self.vreg.property_value('boxes.edit_box.order'), 2) + self.assertEqual(self.vreg.property_value('boxes.possible_views_box.visible'), False) + self.assertEqual(self.vreg.property_value('boxes.possible_views_box.order'), 10) + self.assertRaises(UnknownProperty, self.vreg.property_value, 'boxes.actions_box') +>>>>>>> /tmp/unittest_viewselector.py~other.F5zfDM diff -r e3994fcc21c3 -r 1806148d6ce8 web/test/unittest_web.py --- a/web/test/unittest_web.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/test/unittest_web.py Wed Sep 29 16:16:32 2010 +0200 @@ -25,9 +25,9 @@ req = FakeRequest() arurl = req.ajax_replace_url # NOTE: for the simplest use cases, we could use doctest - self.assertEquals(arurl('foo', rql='Person P', vid='list'), + self.assertEqual(arurl('foo', rql='Person P', vid='list'), """javascript: $('#foo').loadxhtml("http://testing.fr/cubicweb/json?rql=Person%20P&fname=view&vid=list",null,"get","replace"); noop()""") - self.assertEquals(arurl('foo', rql='Person P', vid='oneline', name='bar', age=12), + self.assertEqual(arurl('foo', rql='Person P', vid='oneline', name='bar', age=12), """javascript: $('#foo').loadxhtml("http://testing.fr/cubicweb/json?name=bar&age=12&rql=Person%20P&fname=view&vid=oneline",null,"get","replace"); noop()""") diff -r e3994fcc21c3 -r 1806148d6ce8 web/uicfg.py diff -r e3994fcc21c3 -r 1806148d6ce8 web/views/actions.py --- a/web/views/actions.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/views/actions.py Wed Sep 29 16:16:32 2010 +0200 @@ -57,8 +57,7 @@ 'optional argument', DeprecationWarning) editableattrs = form.editable_attributes() for rschema, role in editableattrs: - if not rschema.final: - return 1 + return 1 return 0 @objectify_selector @@ -142,8 +141,8 @@ class ModifyAction(action.Action): __regid__ = 'edit' - __select__ = (action.Action.__select__ & one_line_rset() & - (has_permission('update') | has_editable_relation('add'))) + __select__ = (action.Action.__select__ + & one_line_rset() & has_editable_relation('add')) title = _('modify') category = 'mainactions' diff -r e3994fcc21c3 -r 1806148d6ce8 web/views/basecontrollers.py --- a/web/views/basecontrollers.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/views/basecontrollers.py Wed Sep 29 16:16:32 2010 +0200 @@ -154,7 +154,6 @@ else: req.set_message(req._("You have no access to this view or it can not " "be used to display the current data.")) - self.warning("the view %s can not be applied to this query", vid) vid = req.form.get('fallbackvid') or vid_from_rset(req, rset, req.vreg.schema) view = req.vreg['views'].select(vid, req, rset=rset) return view, rset diff -r e3994fcc21c3 -r 1806148d6ce8 web/views/cwuser.py --- a/web/views/cwuser.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/views/cwuser.py Wed Sep 29 16:16:32 2010 +0200 @@ -85,7 +85,8 @@ % xml_escape(entity.firstname)) emailaddr = entity.cw_adapt_to('IEmailable').get_email() if emailaddr: - self.w(u'%s\n' % hashlib.sha1(emailaddr).hexdigest()) + self.w(u'%s\n' + % hashlib.sha1(emailaddr.encode('utf-8')).hexdigest()) self.w(u'\n') diff -r e3994fcc21c3 -r 1806148d6ce8 web/views/formrenderers.py --- a/web/views/formrenderers.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/views/formrenderers.py Wed Sep 29 16:16:32 2010 +0200 @@ -342,8 +342,14 @@ def render_fields(self, w, form, values): if form.parent_form is None: w(u'
numchar
1a
2b
') - subfields = [field for field in form.forms[0].fields - if field.is_visible()] + # get fields from the first subform with something to display (we + # may have subforms with nothing editable that will simply be + # skipped later) + for subform in form.forms: + subfields = [field for field in subform.fields + if field.is_visible()] + if subfields: + break if subfields: # main form, display table headers w(u'') diff -r e3994fcc21c3 -r 1806148d6ce8 web/views/primary.py --- a/web/views/primary.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/views/primary.py Wed Sep 29 16:16:32 2010 +0200 @@ -145,18 +145,23 @@ for rschema, role, dispctrl, value in display_attributes: if support_args(self._render_attribute, 'label'): label = self._rel_label(entity, rschema, role, dispctrl) - self._render_attribute(label, value, table=True) + self.render_attribute(label, value, table=True) elif support_args(self._render_attribute, 'dispctrl'): - warn('[3.10] _render_attribute prototype has changed, please' - ' update %s' % self.__class___, DeprecationWarning) + warn('[3.9] _render_attribute prototype has changed and ' + 'renamed to render_attribute, please update %s' + % self.__class___, DeprecationWarning) self._render_attribute(dispctrl, rschema, value, role=role, table=True) else: - warn('[3.6] _render_attribute prototype has changed, please' - ' update %s' % self.__class___, DeprecationWarning) self._render_attribute(rschema, value, role=role, table=True) + warn('[3.6] _render_attribute prototype has changed and ' + 'renamed to render_attribute, please update %s' + % self.__class___, DeprecationWarning) self.w(u'
') + def render_attribute(self, label, value, table=False): + self.field(label, value, tr=False, table=table) + def render_entity_relations(self, entity): for rschema, tschemas, role, dispctrl in self._section_def(entity, 'relations'): if rschema.final or dispctrl.get('rtypevid'): @@ -164,31 +169,45 @@ try: rview = self._cw.vreg['views'].select( vid, self._cw, rset=entity.cw_rset, row=entity.cw_row, - col=entity.cw_col, dispctrl=dispctrl, rtype=rschema, role=role) + col=entity.cw_col, dispctrl=dispctrl, + rtype=rschema, role=role) except NoSelectableObject: continue - self.w(u'
') - label = self._rel_label(entity, rschema, role, dispctrl) - if label: - self.w(u'

%s

' % label) - rview.render(row=entity.cw_row, col=entity.cw_col, w=self.w, - rtype=rschema.type, role=role) - self.w(u'
') - continue - rset = self._relation_rset(entity, rschema, role, dispctrl) - if rset: - if support_args(self._render_relation, 'label'): - label = self._rel_label(entity, rschema, role, dispctrl) - self._render_relation(label, dispctrl, rset, 'autolimited') - elif not support_args(self._render_relation, 'showlabel'): - warn('[3.10] _render_relation prototype has changed, ' - 'please update %s' % self.__class__, DeprecationWarning) - self._render_relation(dispctrl, rset, 'autolimited') - else: - warn('[3.6] _render_relation prototype has changed, ' - 'please update %s' % self.__class__, DeprecationWarning) - self._render_relation(rset, dispctrl, 'autolimited', - self.show_rel_label) + value = rview.render(row=entity.cw_row, col=entity.cw_col, + rtype=rschema.type, role=role) + else: + rset = self._relation_rset(entity, rschema, role, dispctrl) + if not rset: + continue + if hasattr(self, '_render_relation'): + if not support_args(self._render_relation, 'showlabel'): + self._render_relation(dispctrl, rset, 'autolimited') + warn('[3.9] _render_relation prototype has changed and has ' + 'been renamed to render_relation, please update %s' + % self.__class__, DeprecationWarning) + else: + self._render_relation(rset, dispctrl, 'autolimited', + self.show_rel_label) + warn('[3.6] _render_relation prototype has changed and has ' + 'been renamed to render_relation, please update %s' + % self.__class__, DeprecationWarning) + continue + vid = dispctrl.get('vid', 'autolimited') + try: + rview = self._cw.vreg['views'].select( + vid, self._cw, rset=rset, dispctrl=dispctrl) + except NoSelectableObject: + continue + value = rview.render() + label = self._rel_label(entity, rschema, role, dispctrl) + self.render_relation(label, value) + + def render_relation(self, label, value): + self.w(u'
') + if label: + self.w(u'

%s

' % label) + self.w(value) + self.w(u'
') def render_side_boxes(self, boxes): """display side related relations: @@ -266,17 +285,6 @@ rset = dispctrl['filter'](rset) return rset - def _render_relation(self, label, dispctrl, rset, defaultvid): - self.w(u'
') - if label: - self.w(u'

%s

' % label) - self.wview(dispctrl.get('vid', defaultvid), rset, - initargs={'dispctrl': dispctrl}) - self.w(u'
') - - def _render_attribute(self, label, value, table=False): - self.field(label, value, tr=False, table=table) - def _rel_label(self, entity, rschema, role, dispctrl): if rschema.final: showlabel = dispctrl.get('showlabel', self.show_attr_label) diff -r e3994fcc21c3 -r 1806148d6ce8 web/views/workflow.py --- a/web/views/workflow.py Thu Sep 23 23:28:58 2010 +0200 +++ b/web/views/workflow.py Wed Sep 29 16:16:32 2010 +0200 @@ -164,7 +164,7 @@ class WFHistoryVComponent(component.CtxComponent): """display the workflow history for entities supporting it""" __regid__ = 'wfhistory' - __select__ = WFHistoryView.__select__ & component.EntityVComponent.__select__ + __select__ = component.EntityVComponent.__select__ & WFHistoryView.__select__ context = 'navcontentbottom' title = _('Workflow history')