get actual exception class instead of 'unicode' in the error view
"""Test tools for cubicweb:organization: Logilab:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr"""__docformat__="restructuredtext en"importosimportloggingfromos.pathimport(abspath,join,exists,basename,dirname,normpath,split,isfile,isabs)frommx.DateTimeimportstrptime,DateTimeDeltafromcubicwebimportCW_SOFTWARE_ROOT,ConfigurationErrorfromcubicweb.toolsutilsimportread_configfromcubicweb.cwconfigimportCubicWebConfiguration,merge_optionsfromcubicweb.server.serverconfigimportServerConfigurationfromcubicweb.etwist.twconfigimportTwistedConfiguration# validators are used to validate (XML, DTD, whatever) view's content# validators availables are :# 'dtd' : validates XML + declared DTD# 'xml' : guarantees XML is well formed# None : do not try to validate anythingVIEW_VALIDATORS={}BASE_URL='http://testing.fr/cubicweb/'DEFAULT_SOURCES={'system':{'adapter':'native','db-encoding':'UTF-8',#'ISO-8859-1','db-user':u'admin','db-password':'gingkow','db-name':'tmpdb','db-driver':'sqlite','db-host':None,},'admin':{'login':u'admin','password':u'gingkow',},}classTestServerConfiguration(ServerConfiguration):mode='test'set_language=Falseread_application_schema=Falsebootstrap_schema=Falseinit_repository=Trueoptions=merge_options(ServerConfiguration.options+(('anonymous-user',{'type':'string','default':None,'help':'login of the CubicWeb user account to use for anonymous user (if you want to allow anonymous)','group':'main','inputlevel':1,}),('anonymous-password',{'type':'string','default':None,'help':'password of the CubicWeb user account matching login','group':'main','inputlevel':1,}),))ifnotos.environ.get('APYCOT_ROOT'):REGISTRY_DIR=normpath(join(CW_SOFTWARE_ROOT,'../cubes'))def__init__(self,appid,log_threshold=logging.CRITICAL+10):ServerConfiguration.__init__(self,appid)self.global_set_option('log-file',None)self.init_log(log_threshold,force=True)# need this, usually triggered by cubicweb-ctlself.load_cwctl_plugins()anonymous_user=TwistedConfiguration.anonymous_user.im_func@propertydefapphome(self):ifexists(self.appid):returnabspath(self.appid)# application cube testreturnabspath('..')appdatahome=apphomedefmain_config_file(self):"""return application's control configuration file"""returnjoin(self.apphome,'%s.conf'%self.name)definstance_md5_version(self):return''defbootstrap_cubes(self):try:super(TestServerConfiguration,self).bootstrap_cubes()exceptIOError:# no cubesself.init_cubes(())sourcefile=Nonedefsources_file(self):"""define in subclasses self.sourcefile if necessary"""ifself.sourcefile:print'Reading sources from',self.sourcefilesourcefile=self.sourcefileifnotisabs(sourcefile):sourcefile=join(self.apphome,sourcefile)else:sourcefile=super(TestServerConfiguration,self).sources_file()returnsourcefiledefsources(self):"""By default, we run tests with the sqlite DB backend. One may use its own configuration by just creating a 'sources' file in the test directory from wich tests are launched or by specifying an alternative sources file using self.sourcefile. """sources=super(TestServerConfiguration,self).sources()ifnotsources:sources=DEFAULT_SOURCESreturnsourcesdefload_defaults(self):super(TestServerConfiguration,self).load_defaults()# note: don't call global set option here, OptionManager may not yet be initialized# add anonymous userself.set_option('anonymous-user','anon')self.set_option('anonymous-password','anon')# uncomment the line below if you want rql queries to be logged#self.set_option('query-log-file', '/tmp/test_rql_log.' + `os.getpid()`)self.set_option('sender-name','cubicweb-test')self.set_option('sender-addr','cubicweb-test@logilab.fr')try:send_to='%s@logilab.fr'%os.getlogin()exceptOSError:send_to='%s@logilab.fr'%(os.environ.get('USER')oros.environ.get('USERNAME')oros.environ.get('LOGNAME'))self.set_option('sender-addr',send_to)self.set_option('default-dest-addrs',send_to)self.set_option('base-url',BASE_URL)classBaseApptestConfiguration(TestServerConfiguration,TwistedConfiguration):repo_method='inmemory'options=merge_options(TestServerConfiguration.options+TwistedConfiguration.options)cubicweb_vobject_path=TestServerConfiguration.cubicweb_vobject_path|TwistedConfiguration.cubicweb_vobject_pathcube_vobject_path=TestServerConfiguration.cube_vobject_path|TwistedConfiguration.cube_vobject_pathdefavailable_languages(self,*args):return('en','fr','de')defext_resources_file(self):"""return application's external resources file"""returnjoin(self.apphome,'data','external_resources')defpyro_enabled(self):# but export PYRO_MULTITHREAD=0 or you get problems with sqlite and threadsreturnTrueclassApptestConfiguration(BaseApptestConfiguration):def__init__(self,appid,log_threshold=logging.CRITICAL,sourcefile=None):BaseApptestConfiguration.__init__(self,appid,log_threshold=log_threshold)self.init_repository=sourcefileisNoneself.sourcefile=sourcefileimportreself.global_set_option('embed-allowed',re.compile('.*'))classRealDatabaseConfiguration(ApptestConfiguration):init_repository=Falsesourcesdef={'system':{'adapter':'native','db-encoding':'UTF-8',#'ISO-8859-1','db-user':u'admin','db-password':'gingkow','db-name':'seotest','db-driver':'postgres','db-host':None,},'admin':{'login':u'admin','password':u'gingkow',},}def__init__(self,appid,log_threshold=logging.CRITICAL,sourcefile=None):ApptestConfiguration.__init__(self,appid)self.init_repository=Falsedefsources(self):""" By default, we run tests with the sqlite DB backend. One may use its own configuration by just creating a 'sources' file in the test directory from wich tests are launched. """self._sources=self.sourcesdefreturnself._sourcesdefbuildconfig(dbuser,dbpassword,dbname,adminuser,adminpassword,dbhost=None):"""convenience function that builds a real-db configuration class"""sourcesdef={'system':{'adapter':'native','db-encoding':'UTF-8',#'ISO-8859-1','db-user':dbuser,'db-password':dbpassword,'db-name':dbname,'db-driver':'postgres','db-host':dbhost,},'admin':{'login':adminuser,'password':adminpassword,},}returntype('MyRealDBConfig',(RealDatabaseConfiguration,),{'sourcesdef':sourcesdef})defloadconfig(filename):"""convenience function that builds a real-db configuration class from a file """returntype('MyRealDBConfig',(RealDatabaseConfiguration,),{'sourcesdef':read_config(filename)})classLivetestConfiguration(BaseApptestConfiguration):init_repository=Falsedef__init__(self,cube=None,sourcefile=None,pyro_name=None,log_threshold=logging.CRITICAL):TestServerConfiguration.__init__(self,cube,log_threshold=log_threshold)self.appid=pyro_nameorcube# don't change this, else some symlink problems may arise in some# environment (e.g. mine (syt) ;o)# XXX I'm afraid this test will prevent to run test from a production# environmentself._sources=None# application cube testifcubeisnotNone:self.apphome=self.cube_dir(cube)elif'web'inos.getcwd().split(os.sep):# web testself.apphome=join(normpath(join(dirname(__file__),'..')),'web')else:# application cube testself.apphome=abspath('..')self.sourcefile=sourcefileself.global_set_option('realm','')self.use_pyro=pyro_nameisnotNonedefpyro_enabled(self):ifself.use_pyro:returnTrueelse:returnFalseCubicWebConfiguration.cls_adjust_sys_path()definstall_sqlite_path(querier):"""This patch hotfixes the following sqlite bug : - http://www.sqlite.org/cvstrac/tktview?tn=1327,33 (some dates are returned as strings rather thant date objects) """defwrap_execute(base_execute):defnew_execute(*args,**kwargs):rset=base_execute(*args,**kwargs)ifrset.description:found_date=Falseforrow,rowdescinzip(rset,rset.description):forcellindex,(value,vtype)inenumerate(zip(row,rowdesc)):ifvtypein('Date','Datetime')andtype(value)isunicode:found_date=Truetry:row[cellindex]=strptime(value,'%Y-%m-%d %H:%M:%S')except:row[cellindex]=strptime(value,'%Y-%m-%d')ifvtype=='Time'andtype(value)isunicode:found_date=Truetry:row[cellindex]=strptime(value,'%H:%M:%S')except:# DateTime used as Time?row[cellindex]=strptime(value,'%Y-%m-%d %H:%M:%S')ifvtype=='Interval'andtype(value)isint:found_date=Truerow[cellindex]=DateTimeDelta(0,0,0,value)ifnotfound_date:breakreturnrsetreturnnew_executequerier.__class__.execute=wrap_execute(querier.__class__.execute)definit_test_database(driver='sqlite',configdir='data',config=None,vreg=None):"""init a test database for a specific driver"""fromcubicweb.dbapiimportin_memory_cnxifvregandnotconfig:config=vreg.configconfig=configorTestServerConfiguration(configdir)source=config.sources()ifdriver=='sqlite':init_test_database_sqlite(config,source)elifdriver=='postgres':init_test_database_postgres(config,source)else:raiseValueError('no initialization function for driver %r'%driver)config._cubes=None# avoid assertion errorrepo,cnx=in_memory_cnx(vregorconfig,unicode(source['admin']['login']),source['admin']['password']or'xxx')ifdriver=='sqlite':install_sqlite_path(repo.querier)returnrepo,cnxdefinit_test_database_postgres(config,source,vreg=None):"""initialize a fresh sqlite databse used for testing purpose"""ifconfig.init_repository:fromcubicweb.serverimportinit_repositoryinit_repository(config,interactive=False,drop=True,vreg=vreg)defcleanup_sqlite(dbfile,removecube=False):try:os.remove(dbfile)os.remove('%s-journal'%dbfile)exceptOSError:passifremovecube:try:os.remove('%s-cube'%dbfile)exceptOSError:passdefinit_test_database_sqlite(config,source,vreg=None):"""initialize a fresh sqlite databse used for testing purpose"""importshutil# remove database file if it exists (actually I know driver == 'sqlite' :)dbfile=source['system']['db-name']cleanup_sqlite(dbfile)cube='%s-cube'%dbfileifexists(cube):shutil.copy(cube,dbfile)else:# initialize the databasefromcubicweb.serverimportinit_repositoryinit_repository(config,interactive=False,vreg=vreg)shutil.copy(dbfile,cube)