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
>>
>>
>>
>>
>>
>>
--