--- a/devtools/testlib.py Wed Feb 24 12:49:55 2010 +0100
+++ b/devtools/testlib.py Wed Feb 24 15:08:13 2010 +0100
@@ -66,24 +66,7 @@
return set(schema.entities()) - protected_entities
-def get_versions(self, checkversions=False):
- """return the a dictionary containing cubes used by this instance
- as key with their version as value, including cubicweb version. This is a
- public method, not requiring a session id.
-
- replace Repository.get_versions by this method if you want to get versions
- from code instead of from the database
- """
- vcconf = {'cubicweb': self.config.cubicweb_version()}
- self.config.bootstrap_cubes()
- for pk in self.config.cubes():
- version = self.config.cube_version(pk)
- vcconf[pk] = version
- self.config._cubes = None
- return vcconf
-
-
-def refresh_repo(repo):
+def refresh_repo(repo, resetschema=False, resetvreg=False):
devtools.reset_test_database(repo.config)
for pool in repo.pools:
pool.reconnect()
@@ -92,6 +75,8 @@
repo.querier._rql_cache = {}
for source in repo.sources:
source.reset_caches()
+ if resetschema:
+ repo.set_schema(repo.config.load_schema(), resetvreg=resetvreg)
# email handling, to test emails sent by an application ########################
@@ -160,6 +145,7 @@
"""
appid = 'data'
configcls = devtools.ApptestConfiguration
+ reset_schema = reset_vreg = False # reset schema / vreg between tests
@classproperty
def config(cls):
@@ -230,7 +216,7 @@
@classmethod
def _refresh_repo(cls):
- refresh_repo(cls.repo)
+ refresh_repo(cls.repo, cls.reset_schema, cls.reset_vreg)
# global resources accessors ###############################################
--- a/embedded/README Wed Feb 24 12:49:55 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-This directory contains extra libraries which are needed
-to make cubicweb work.
-
-The mx.DateTime python implementation is directly taken from
-the mx.DateTime distribution. The only modification is the
-strptime function which has been mocked using the standard
-``datetime`` module. (as provided by the python2.5's stdlib)
--- a/goa/goactl.py Wed Feb 24 12:49:55 2010 +0100
+++ b/goa/goactl.py Wed Feb 24 15:08:13 2010 +0100
@@ -31,7 +31,6 @@
(docutils.__path__[0], 'docutils'),
(roman.__file__.replace('.pyc', '.py'), 'roman.py'),
- (join(CW_SOFTWARE_ROOT, 'embedded', 'mx'), 'mx'),
('/usr/share/fckeditor/', 'fckeditor'),
(join(CW_SOFTWARE_ROOT, 'web', 'data'), join('cubes', 'shared', 'data')),
--- a/goa/test/pytestconf.py Wed Feb 24 12:49:55 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-"""this pytestconf automatically adds the mx's python version in the PYTHONPATH
-:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
-"""
-import sys
-import os.path as osp
-
-import cubicweb
-# remove 'mx' modules imported by cubicweb
-for modname in sys.modules.keys():
- if modname.startswith('mx'):
- sys.modules.pop(modname)
-
-# this is where mx should get imported from
-mxpath = osp.abspath(osp.join(osp.dirname(cubicweb.__file__), 'embedded'))
-sys.path.insert(1, mxpath)
-
-# make sure the correct mx is imported
-import mx
-assert osp.dirname(mx.__file__) == osp.join(mxpath, 'mx'), '%s != %s' % (osp.dirname(mx.__file__), mxpath)
--- a/hooks/test/unittest_hooks.py Wed Feb 24 12:49:55 2010 +0100
+++ b/hooks/test/unittest_hooks.py Wed Feb 24 15:08:13 2010 +0100
@@ -9,22 +9,8 @@
from datetime import datetime
-from cubicweb import (ConnectionError, ValidationError, AuthenticationError,
- BadConnectionId)
-from cubicweb.devtools.testlib import CubicWebTC, get_versions
-
-from cubicweb.server.sqlutils import SQL_PREFIX
-from cubicweb.server.repository import Repository
-
-orig_get_versions = Repository.get_versions
-
-def setup_module(*args):
- Repository.get_versions = get_versions
-
-def teardown_module(*args):
- Repository.get_versions = orig_get_versions
-
-
+from cubicweb import ValidationError, AuthenticationError, BadConnectionId
+from cubicweb.devtools.testlib import CubicWebTC
class CoreHooksTC(CubicWebTC):
--- a/hooks/test/unittest_syncschema.py Wed Feb 24 12:49:55 2010 +0100
+++ b/hooks/test/unittest_syncschema.py Wed Feb 24 15:08:13 2010 +0100
@@ -1,38 +1,43 @@
from logilab.common.testlib import TestCase, unittest_main
-from cubicweb.devtools.testlib import CubicWebTC
-#################
-# <required ?> #
-#################
+from cubicweb import ValidationError
+from cubicweb.devtools.testlib import CubicWebTC
+from cubicweb.server.sqlutils import SQL_PREFIX
-from datetime import datetime
-
-from cubicweb import (ConnectionError, ValidationError, AuthenticationError,
- BadConnectionId)
-from cubicweb.devtools.testlib import get_versions
-
-from cubicweb.server.sqlutils import SQL_PREFIX
-from cubicweb.server.repository import Repository
-
-orig_get_versions = Repository.get_versions
-#################
-# </required ?> #
-#################
-
-def setup_module(*args):
- Repository.get_versions = get_versions
-
-def teardown_module(*args):
- Repository.get_versions = orig_get_versions
-
+SCHEMA_EIDS = {}
class SchemaModificationHooksTC(CubicWebTC):
+ reset_schema = True
@classmethod
def init_config(cls, config):
super(SchemaModificationHooksTC, cls).init_config(config)
+ # we have to read schema from the database to get eid for schema entities
config._cubes = None
cls.repo.fill_schema()
+ # remember them so we can reread it from the fs instead of the db (too
+ # costly) between tests
+ for x in cls.repo.schema.entities():
+ SCHEMA_EIDS[x] = x.eid
+ for x in cls.repo.schema.relations():
+ SCHEMA_EIDS[x] = x.eid
+ for rdef in x.rdefs.itervalues():
+ SCHEMA_EIDS[(rdef.subject, rdef.rtype, rdef.object)] = rdef.eid
+
+ @classmethod
+ def _refresh_repo(cls):
+ super(SchemaModificationHooksTC, cls)._refresh_repo()
+ # rebuild schema eid index
+ schema = cls.repo.schema
+ for x in schema.entities():
+ x.eid = SCHEMA_EIDS[x]
+ schema._eid_index[x.eid] = x
+ for x in cls.repo.schema.relations():
+ x.eid = SCHEMA_EIDS[x]
+ schema._eid_index[x.eid] = x
+ for rdef in x.rdefs.itervalues():
+ rdef.eid = SCHEMA_EIDS[(rdef.subject, rdef.rtype, rdef.object)]
+ schema._eid_index[rdef.eid] = rdef
def index_exists(self, etype, attr, unique=False):
self.session.set_pool()
--- a/server/checkintegrity.py Wed Feb 24 12:49:55 2010 +0100
+++ b/server/checkintegrity.py Wed Feb 24 15:08:13 2010 +0100
@@ -111,6 +111,8 @@
pb.update()
# restore Entity.check
Entity.check = _check
+ repo.config.disabled_hooks_categories.remove('metadata')
+ repo.config.disabled_hooks_categories.remove('integrity')
def check_schema(schema, session, eids, fix=1):
--- a/server/migractions.py Wed Feb 24 12:49:55 2010 +0100
+++ b/server/migractions.py Wed Feb 24 15:08:13 2010 +0100
@@ -973,7 +973,7 @@
you usually want to use sync_schema_props_perms instead.
"""
oldvalue = None
- for constr in self.repo.schema.eschema(etype).constraints(rtype):
+ for constr in self.repo.schema.eschema(etype).rdef(rtype).constraints:
if isinstance(constr, SizeConstraint):
oldvalue = constr.max
if oldvalue == size:
--- a/server/repository.py Wed Feb 24 12:49:55 2010 +0100
+++ b/server/repository.py Wed Feb 24 15:08:13 2010 +0100
@@ -102,10 +102,11 @@
hooks order hazardness
"""
# XXX now that rql in migraction default to unsafe_execute we don't want to
- # skip that anymore. Also we should imo rely on the orm to first fetch
- # existing entity if any then delete it
- #if session.is_super_session:
- # return
+ # skip that for super session (though we can still skip it for internal
+ # sessions). Also we should imo rely on the orm to first fetch existing
+ # entity if any then delete it.
+ if session.is_internal_session:
+ return
card = session.schema_rproperty(rtype, eidfrom, eidto, 'cardinality')
# one may be tented to check for neweids but this may cause more than one
# relation even with '1?' cardinality if thoses relations are added in the
@@ -114,16 +115,27 @@
# not expected for this). So: don't do it, we pretend to ensure repository
# consistency.
#
- # also, we must not use unsafe_execute since we want the delete permission
- # to be checked when some existing relation is deleted
+ # XXX we don't want read permissions to be applied but we want delete
+ # permission to be checked
+ rschema = session.repo.schema.rschema(rtype)
if card[0] in '1?':
- rschema = session.repo.schema.rschema(rtype)
if not rschema.inlined: # inlined relations will be implicitly deleted
- session.execute('DELETE X %s Y WHERE X eid %%(x)s, NOT Y eid %%(y)s' % rtype,
- {'x': eidfrom, 'y': eidto}, 'x')
+ rset = session.unsafe_execute('Any X,Y WHERE X %s Y, X eid %%(x)s, '
+ 'NOT Y eid %%(y)s' % rtype,
+ {'x': eidfrom, 'y': eidto}, 'x')
+ if rset:
+ safe_delete_relation(session, rschema, *rset[0])
if card[1] in '1?':
- session.execute('DELETE X %s Y WHERE NOT X eid %%(x)s, Y eid %%(y)s' % rtype,
- {'x': eidfrom, 'y': eidto}, 'y')
+ rset = session.unsafe_execute('Any X,Y WHERE X %s Y, Y eid %%(y)s, '
+ 'NOT X eid %%(x)s' % rtype,
+ {'x': eidfrom, 'y': eidto}, 'y')
+ if rset:
+ safe_delete_relation(session, rschema, *rset[0])
+
+def safe_delete_relation(session, rschema, subject, object):
+ if not rschema.has_perm(session, 'delete', fromeid=subject, toeid=object):
+ raise Unauthorized()
+ session.repo.glob_delete_relation(session, subject, rschema.type, object)
class Repository(object):
@@ -435,7 +447,8 @@
public method, not requiring a session id.
"""
versions = self.get_versions(not (self.config.creating
- or self.config.repairing))
+ or self.config.repairing
+ or self.config.mode == 'test'))
cubes = list(versions)
cubes.remove('cubicweb')
return cubes
--- a/server/sources/native.py Wed Feb 24 12:49:55 2010 +0100
+++ b/server/sources/native.py Wed Feb 24 15:08:13 2010 +0100
@@ -429,7 +429,8 @@
if rollback:
try:
session.pool.connection(self.uri).rollback()
- self.critical('transaction has been rollbacked')
+ if self.repo.config.mode != 'test':
+ self.critical('transaction has been rollbacked')
except:
pass
raise
@@ -453,7 +454,8 @@
query, args, ex.args[0])
try:
session.pool.connection(self.uri).rollback()
- self.critical('transaction has been rollbacked')
+ if self.repo.config.mode != 'test':
+ self.critical('transaction has been rollbacked')
except:
pass
raise
--- a/server/test/unittest_migractions.py Wed Feb 24 12:49:55 2010 +0100
+++ b/server/test/unittest_migractions.py Wed Feb 24 15:08:13 2010 +0100
@@ -9,20 +9,11 @@
from logilab.common.testlib import TestCase, unittest_main
from cubicweb import ConfigurationError
-from cubicweb.devtools.testlib import CubicWebTC, get_versions
+from cubicweb.devtools.testlib import CubicWebTC
from cubicweb.schema import CubicWebSchemaLoader
from cubicweb.server.sqlutils import SQL_PREFIX
-from cubicweb.server.repository import Repository
from cubicweb.server.migractions import *
-orig_get_versions = Repository.get_versions
-
-def setup_module(*args):
- Repository.get_versions = get_versions
-
-def teardown_module(*args):
- Repository.get_versions = orig_get_versions
-
class MigrationCommandsTC(CubicWebTC):
@@ -43,7 +34,7 @@
@classmethod
def _refresh_repo(cls):
super(MigrationCommandsTC, cls)._refresh_repo()
- cls.repo.schema = cls.vreg.schema = deepcopy(cls.origschema)
+ cls.repo.set_schema(deepcopy(cls.origschema), resetvreg=False)
def setUp(self):
CubicWebTC.setUp(self)
--- a/server/test/unittest_msplanner.py Wed Feb 24 12:49:55 2010 +0100
+++ b/server/test/unittest_msplanner.py Wed Feb 24 15:08:13 2010 +0100
@@ -5,7 +5,6 @@
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
"""
-from logilab.common.decorators import clear_cache
from cubicweb.devtools import init_test_database
from cubicweb.devtools.repotest import BasePlannerTC, test_plan
@@ -78,12 +77,12 @@
self.prevrqlexpr_affaire = affreadperms[-1]
# add access to type attribute so S can't be invariant
affreadperms[-1] = ERQLExpression('X concerne S?, S owned_by U, S type "X"')
- self.schema['Affaire'].permissions['read'] = tuple(affreadperms)
+ self.schema['Affaire'].set_action_permissions('read', affreadperms)
# hijack CWUser security
userreadperms = list(self.schema['CWUser'].permissions['read'])
self.prevrqlexpr_user = userreadperms[-1]
userreadperms[-1] = ERQLExpression('X owned_by U')
- self.schema['CWUser'].permissions['read'] = tuple(userreadperms)
+ self.schema['CWUser'].set_action_permissions('read', userreadperms)
self.add_source(FakeUserROSource, 'ldap')
self.add_source(FakeCardSource, 'cards')
@@ -96,9 +95,7 @@
def restore_orig_affaire_security(self):
affreadperms = list(self.schema['Affaire'].permissions['read'])
affreadperms[-1] = self.prevrqlexpr_affaire
- self.schema['Affaire'].permissions['read'] = tuple(affreadperms)
- clear_cache(self.schema['Affaire'], 'get_rqlexprs')
- #clear_cache(self.schema['Affaire'], 'get_groups')
+ self.schema['Affaire'].set_action_permissions('read', affreadperms)
def restore_orig_cwuser_security(self):
if hasattr(self, '_orig_cwuser_security_restored'):
@@ -106,9 +103,7 @@
self._orig_cwuser_security_restored = True
userreadperms = list(self.schema['CWUser'].permissions['read'])
userreadperms[-1] = self.prevrqlexpr_user
- self.schema['CWUser'].permissions['read'] = tuple(userreadperms)
- clear_cache(self.schema['CWUser'], 'get_rqlexprs')
- #clear_cache(self.schema['CWUser'], 'get_groups')
+ self.schema['CWUser'].set_action_permissions('read', userreadperms)
class PartPlanInformationTC(BaseMSPlannerTC):
--- a/server/test/unittest_multisources.py Wed Feb 24 12:49:55 2010 +0100
+++ b/server/test/unittest_multisources.py Wed Feb 24 15:08:13 2010 +0100
@@ -30,13 +30,25 @@
repo2, cnx2 = init_test_database(config=ExternalSource1Configuration('data'))
repo3, cnx3 = init_test_database(config=ExternalSource2Configuration('data'))
-# XXX, access existing connection, no pyro connection
+# hi-jacking
from cubicweb.server.sources.pyrorql import PyroRQLSource
-PyroRQLSource.get_connection = lambda x: x.uri == 'extern-multi' and cnx3 or cnx2
-# necessary since the repository is closing its initial connections pool though
-# we want to keep cnx2 valid
from cubicweb.dbapi import Connection
-Connection.close = lambda x: None
+
+PyroRQLSource_get_connection = PyroRQLSource.get_connection
+Connection_close = Connection.close
+
+def setup_module(*args):
+ # hi-jack PyroRQLSource.get_connection to access existing connection (no
+ # pyro connection)
+ PyroRQLSource.get_connection = lambda x: x.uri == 'extern-multi' and cnx3 or cnx2
+ # also necessary since the repository is closing its initial connections
+ # pool though we want to keep cnx2 valid
+ Connection.close = lambda x: None
+
+def teardown_module(*args):
+ PyroRQLSource.get_connection = PyroRQLSource_get_connection
+ Connection.close = Connection_close
+
class TwoSourcesTC(CubicWebTC):
config = TwoSourcesConfiguration('data')
--- a/server/test/unittest_security.py Wed Feb 24 12:49:55 2010 +0100
+++ b/server/test/unittest_security.py Wed Feb 24 15:08:13 2010 +0100
@@ -494,12 +494,13 @@
# needed to avoid check_perm error
session.set_pool()
# needed to remove rql expr granting update perm to the user
+ affaire_perms = self.schema['Affaire'].permissions.copy()
self.schema['Affaire'].set_action_permissions('update', self.schema['Affaire'].get_groups('update'))
- self.assertRaises(Unauthorized,
- self.schema['Affaire'].check_perm, session, 'update', eid=eid)
- cu = cnx.cursor()
- self.schema['Affaire'].set_action_permissions('read', ('users',))
try:
+ self.assertRaises(Unauthorized,
+ self.schema['Affaire'].check_perm, session, 'update', eid=eid)
+ cu = cnx.cursor()
+ self.schema['Affaire'].set_action_permissions('read', ('users',))
aff = cu.execute('Any X WHERE X ref "ARCT01"').get_entity(0, 0)
aff.fire_transition('abort')
cnx.commit()
@@ -510,7 +511,9 @@
# from the current state but Unauthorized if it exists but user can't pass it
self.assertRaises(ValidationError, user.fire_transition, 'deactivate')
finally:
- self.schema['Affaire'].set_action_permissions('read', ('managers',))
+ # restore orig perms
+ for action, perms in affaire_perms.iteritems():
+ self.schema['Affaire'].set_action_permissions(action, perms)
def test_trinfo_security(self):
aff = self.execute('INSERT Affaire X: X ref "ARCT01"').get_entity(0, 0)
--- a/test/unittest_cwconfig.py Wed Feb 24 12:49:55 2010 +0100
+++ b/test/unittest_cwconfig.py Wed Feb 24 15:08:13 2010 +0100
@@ -9,6 +9,7 @@
import os
from os.path import dirname, join, abspath
+from logilab.common.modutils import cleanup_sys_modules
from logilab.common.testlib import TestCase, unittest_main
from logilab.common.changelog import Version
@@ -26,6 +27,7 @@
class CubicWebConfigurationTC(TestCase):
def setUp(self):
+ cleanup_sys_modules([CUSTOM_CUBES_DIR, ApptestConfiguration.CUBES_DIR])
self.config = ApptestConfiguration('data')
self.config._cubes = ('email', 'file')
--- a/test/unittest_entity.py Wed Feb 24 12:49:55 2010 +0100
+++ b/test/unittest_entity.py Wed Feb 24 15:08:13 2010 +0100
@@ -178,9 +178,11 @@
def test_related_rql_base(self):
Personne = self.vreg['etypes'].etype_class('Personne')
Note = self.vreg['etypes'].etype_class('Note')
+ SubNote = self.vreg['etypes'].etype_class('SubNote')
self.failUnless(issubclass(self.vreg['etypes'].etype_class('SubNote'), Note))
Personne.fetch_attrs, Personne.fetch_order = fetch_config(('nom', 'type'))
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.related_rql('evaluee'),
'Any X,AA,AB ORDERBY AA ASC WHERE E eid %(x)s, E evaluee X, '
--- a/test/unittest_utils.py Wed Feb 24 12:49:55 2010 +0100
+++ b/test/unittest_utils.py Wed Feb 24 15:08:13 2010 +0100
@@ -6,14 +6,18 @@
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
"""
-from logilab.common.testlib import TestCase, unittest_main
-
-import simplejson
+import re
import decimal
import datetime
-from cubicweb.utils import make_uid, UStringIO, SizeConstrainedList, CubicWebJsonEncoder
+from logilab.common.testlib import TestCase, unittest_main
+from cubicweb.utils import make_uid, UStringIO, SizeConstrainedList
+try:
+ import simplejson
+ from cubicweb.utils import CubicWebJsonEncoder
+except ImportError:
+ simplejson = None
class MakeUidTC(TestCase):
def test_1(self):
@@ -26,6 +30,9 @@
uid = make_uid('xyz')
if uid in d:
self.fail(len(d))
+ if re.match('\d', uid):
+ self.fail('make_uid must not return something begining with '
+ 'some numeric character, got %s' % uid)
d.add(uid)
@@ -53,6 +60,9 @@
yield self.assertEquals, l, expected
class JSONEncoerTests(TestCase):
+ def setUp(self):
+ if simplejson is None:
+ self.skip('simplejson not available')
def encode(self, value):
return simplejson.dumps(value, cls=CubicWebJsonEncoder)
--- a/utils.py Wed Feb 24 12:49:55 2010 +0100
+++ b/utils.py Wed Feb 24 15:08:13 2010 +0100
@@ -26,9 +26,11 @@
def make_uid(key):
"""forge a unique identifier
- not that unique on win32"""
- msg = str(key) + "%.10f" % time() + str(randint(0, 1000000))
- return md5(msg).hexdigest()
+ XXX not that unique on win32
+ """
+ key = str(key)
+ msg = key + "%.10f" % time() + str(randint(0, 1000000))
+ return key + md5(msg).hexdigest()
else: