More on this problem... I was able to overcome the "cannot duplicate a singleton" error by explicitly closing each db on the tests' tearDown: -------------
db.close(action=None) ------------- I needed to include action=None, otherwise I'd get the following error: ------------- Traceback (most recent call last): File "/stuff/web2py/applications/me_app/tests/controllers/__init__.py", line 21, in tearDown db.close() File "/stuff/web2py/gluon/dal.py", line 7148, in close adapter.close() File "/stuff/web2py/gluon/dal.py", line 505, in close getattr(self, action)() File "/stuff/web2py/gluon/dal.py", line 1643, in commit return self.connection.commit() AttributeError: 'NoneType' object has no attribute 'commit' ------------- However, I still have the "invalid tablename" exception. Best regards On Tuesday, October 2, 2012 12:54:52 PM UTC+1, João Saraiva wrote: > > Hello, > > I am having problems with the new Singleton DAL feature and a web-app that > I had already working correctly with web2py. > > Although the web-app itself runs ok (I can navigate the browser to it, and > the app runs without issues when used from the browser), it crashes when I > run unit-tests on it (by means of web2py.test-runner). More specifically, > each test crashes with the following stack trace: > ------------- > Traceback (most recent call last): > File "/stuff/web2py/gluon/restricted.py", line 209, in restricted > exec ccode in environment > File "/stuff/web2py/applications/me_app/models/00_app_config.py", line > 61, in <module> > initialize = Initialization(settings, T, request, response, session, > cache) > File "/stuff/web2py/applications/me_app/modules/model_logic/config.py", > line 53, in __init__ > (db, archival_db, scheduler_db) = self.__init_db() > File "/stuff/web2py/applications/me_app/modules/model_logic/config.py", > line 88, in __init_db > check_reserved=check_reserved) > File "/stuff/web2py/gluon/dal.py", line 6595, in __new__ > raise RuntimeError, 'Cannot duplicate a Singleton' > RuntimeError: Cannot duplicate a Singleton > ------------- > > The statement that makes this crash is: > ------------- > db = DAL( > settings.db_uri if not request.is_testing else > 'sqlite:memory:', > migrate_enabled=settings.migrate or request.is_testing, > lazy_tables=True, > #bigint_id=True, # TODO > check_reserved=check_reserved) > ------------- > I also create other databases after db that, in testing mode, also point > to 'sqlite:memory'. If I comment those other databases out, the first test > passes ok, but the other ones still crash. > > If I try to comment the lines that originate this error ( > http://code.google.com/p/web2py/source/browse/gluon/dal.py#6594 and > http://code.google.com/p/web2py/source/browse/gluon/dal.py#6595), then I > get an error when creating the first table in my db: > ------------- > Traceback (most recent call last): > File "/stuff/web2py/gluon/restricted.py", line 209, in restricted > exec ccode in environment > File "/stuff/web2py/applications/me_app/models/08_domain.py", line 14, > in <module> > current.domain = domain = domain_model.define_domain() > File > "/stuff/web2py/applications/me_app/modules/model_logic/domain_model.py", > line 334, in define_domain > domain=domain) > File > "/stuff/web2py/applications/me_app/modules/model_logic/domain_model.py", > line 665, in __define_core > on_define=init_domain__country, > File "/stuff/web2py/gluon/dal.py", line 7034, in define_table > raise SyntaxError, 'invalid table name: %s' % tablename > SyntaxError: invalid table name: country > ------------- > which appears to be the same error message that has been reported by > others ( > https://groups.google.com/d/msg/web2py-developers/CWxEhcWxiGM/-Aw_fhQQY4EJ > ). > > When I revert to r4184, everything runs peachy. > > Looking at the code for DAL, I am led to believe that this may have > something to do with threading. Is there any way to disable the Singleton > DAL feature selectively (at least for unit-testing, which does not use > threading in the same manner as web containers do)? > > Best regards, > JS > > > On Tuesday, October 2, 2012 3:32:16 AM UTC+1, Massimo Di Pierro wrote: >> >> There is a big change in DAL. >> >> a = DAL(uri) >> b = DAL(uri) >> >> now "a is b" because DAL is a singleton (almost). It is a thread local >> singleton as long a uri is specified. >> What does this mean in practice? >> >> It means that unless you have lazy virtual fields, Row and Rows objects >> can be serialized (pickled), properly cached, and stored in session. >> For example: >> >> session.rows = session.rows or db(db.mytable).select() >> >> and you can still do: >> >> session.rows.first().update_record(....) >> >> has many practical implications in the way you program and there is even >> more we could do. In the future we may be able to serialize every DAL >> expression. >> >> This is a big change in the source and the internal logic is complex. >> It may have some unforeseen side effects. >> PLEASE TEST THAT TRUNK DOES NOT BREAK YOUR CODE before this makes it into >> stable. >> >> massimo >> >> >> >> >> >> --