Webpy 0.23 #208

Open
wants to merge 29 commits into
from
Commits
+531 −176
Split
View
@@ -0,0 +1,27 @@
+# web.py unit tests
+
+## Setup
+
+All databases expect a database with name `webpy` with username `scott` and password `tiger`.
+
+## Running all tests
+
+To run all tests:
+
+ $ python test/alltests.py
+
+## Running individual tests
+
+To run all tests in a file:
+
+ $ python test/db.py
+
+To run all tests in a class:
+
+ $ python test/db.py SqliteTest
+
+To run a single test:
+
+ $ python test/db.py SqliteTest.testUnicode
+
+
File renamed without changes.
File renamed without changes.
@@ -5,7 +5,7 @@
from distutils.core import setup
setup(name='web.py',
- version='0.22',
+ version='0.23',
description='web.py: makes web apps',
author='Aaron Swartz',
author_email='me@aaronsw.com',
View
No changes.
View
@@ -0,0 +1,8 @@
+import webtest
+
+def suite():
+ modules = ["doctests", "db", "form"]
+ return webtest.suite(modules)
+
+if __name__ == "__main__":
+ webtest.main()
View
@@ -0,0 +1,90 @@
+"""DB test"""
+import webtest
+import web
+
+class DBTest(webtest.TestCase):
+ dbname = 'postgres'
+
+ def setUp(self):
+ webtest.setup_database(self.dbname)
+ web.query("CREATE TABLE person (name text, email text)")
+
+ def tearDown(self):
+ # there might be some error with the current connection, delete from a new connection
+ webtest.setup_database(self.dbname)
+ web.query('DROP TABLE person')
+
+ def testUnicode(self):
+ """Bug#177265: unicode queries throw errors"""
+ web.select('person', where='name=$name', vars={'name': u'\xf4'})
+
+ def testWrongQuery(self):
+ # It should be possible to run a correct query after getting an error from a wrong query.
+ try:
+ web.select('wrong_table')
+ except:
+ pass
+ web.select('person')
+
+ def assertRows(self, n):
+ result = web.select('person')
+ self.assertEquals(len(list(result)), n)
+
+ def testCommit(self):
+ web.transact()
+ web.insert('person', False, name='user1')
+ web.commit()
+
+ web.transact()
+ web.insert('person', False, name='user2')
+ web.insert('person', False, name='user3')
+ web.commit()
+ self.assertRows(3)
+
+ def testRollback(self):
+ web.transact()
+ web.insert('person', False, name='user1')
+ web.insert('person', False, name='user2')
+ web.insert('person', False, name='user3')
+ web.rollback()
+ self.assertRows(0)
+
+ def testNestedTransactions(self):
+ web.transact()
+ web.insert('person', False, name='user1')
+ self.assertRows(1)
+
+ web.transact()
+ web.insert('person', False, name='user2')
+ self.assertRows(2)
+ web.rollback()
+ self.assertRows(1)
+
+ web.transact()
+ web.insert('person', False, name='user3')
+ web.commit()
+
+ self.assertRows(2)
+ web.commit()
+
+
+
+
+class SqliteTest(DBTest):
+ dbname = "sqlite"
+
+ def testNestedTransactions(self):
+ # nested transactions are not supported in sqlite
+ pass
+
+class MySQLTest(DBTest):
+ dbname = "mysql"
+
+ def setUp(self):
+ web.config._hasPooling = False
+ webtest.setup_database(self.dbname)
+ # In mysql, transactions are supported only with INNODB engine.
+ web.query("CREATE TABLE person (name text, email text) ENGINE InnoDB")
+
+if __name__ == '__main__':
+ webtest.main()
View
@@ -0,0 +1,10 @@
+"""Run all doctests in web.py.
+"""
+import webtest
+
+def suite():
+ modules = ["web.utils", "web.db", "web.net", "web.wsgi", "web.http", "web.webapi", "web.request", "web.template"]
+ return webtest.doctest_suite(modules)
+
+if __name__ == "__main__":
+ webtest.main()
View
@@ -0,0 +1,16 @@
+import webtest
+from web import form
+
+class FormTest(webtest.TestCase):
+ def testUnicode(self):
+ t = form.Textbox('first_name', maxlength='255', description=u'\u1234', value=u'\u1234')
+ f = form.Form(t)
+ f.render() # this fails if unicode is not supported.
+
+ t = form.Textbox('first_name', maxlength='255', description=u'\u1234', value=u'\u1234')
+ t.note = u'\u1234'
+ f = form.Form(t)
+ f.render() # this fails if unicode is not supported.
+
+if __name__ == "__main__":
+ webtest.main()
View
@@ -0,0 +1,58 @@
+"""webtest: test utilities.
+"""
+import unittest
+from unittest import TestCase
+import sys, os
+
+# adding current directory to path to make sure local copy of web module is used.
+sys.path.insert(0, '.')
+
+import web
+
+def runTests(suite):
+ runner = unittest.TextTestRunner()
+ return runner.run(suite)
+
+def main(suite=None):
+ if not suite:
+ main_module = __import__('__main__')
+ suite = module_suite(main_module, sys.argv[1:] or None)
+
+ result = runTests(suite)
+ sys.exit(not result.wasSuccessful())
+
+def load_modules(names):
+ return [__import__(name, None, None, "x") for name in names]
+
+def module_suite(module, classnames=None):
+ """Makes a suite from a module."""
+ if hasattr(module, 'suite'):
+ return module.suite()
+ elif classnames:
+ return unittest.TestLoader().loadTestsFromNames(classnames, module)
+ else:
+ return unittest.TestLoader().loadTestsFromModule(module)
+
+def doctest_suite(module_names):
+ """Makes a test suite from doctests."""
+ import doctest
+ suite = unittest.TestSuite()
+ for mod in load_modules(module_names):
+ suite.addTest(doctest.DocTestSuite(mod))
+ return suite
+
+def suite(module_names):
+ """Creates a suite from multiple modules."""
+ suite = unittest.TestSuite()
+ for mod in load_modules(module_names):
+ suite.addTest(module_suite(mod))
+ return suite
+
+def setup_database(dbname):
+ if dbname == 'sqlite':
+ web.config.db_parameters = dict(dbn=dbname, db='webpy.db')
+ else:
+ web.config.db_parameters = dict(dbn=dbname, db='webpy', user='scott', pw='tiger')
+
+ #web.config.db_printing=True
+ web.load()
File renamed without changes.
File renamed without changes.
View
@@ -1,58 +0,0 @@
-"""
-web.py test suite.
-"""
-
-import sys
-import web
-import unittest
-
-def commit(value):
- web.transact()
- web.insert("test", seqname=False, value=value)
- web.commit()
-
-def rollback(value):
- web.transact()
- web.insert("test", seqname=False, value=value)
- web.rollback()
-
-def getrow(value):
- d = web.select('test', where='value=$value', vars=locals())
- a = (d and d[0].value) or None
- return a
-
-def assert_presence(*values):
- for v in values:
- assert getrow(v) is not None
-
-def assert_absence(*values):
- for v in values:
- assert getrow(v) is None
-
-class PostgresTest(unittest.TestCase):
- parameters = dict(dbn="postgres", db="webtest", user="postgres", pw="")
-
- def setUp(self):
- web.config.db_parameters = self.parameters
- #web.config.db_printing = True
- web.load()
- web.delete("test", where="1=1")
-
- def tearDown(self):
- sys.stdout.flush()
- sys.stderr.flush()
-
- def testCommit(self):
- commit(1)
- assert_presence(1)
-
- def testRollback(self):
- rollback(1)
- assert_absence(1)
-
-class MySQLTest(PostgresTest):
- parameters = dict(dbn="mysql", db="webtest", user="webpy", pw="")
-
-if __name__ == "__main__":
- unittest.main()
-
@@ -2,7 +2,7 @@
from __future__ import generators
"""web.py: makes web apps (http://webpy.org)"""
-__version__ = "0.22"
+__version__ = "0.23"
__revision__ = "$Rev$"
__author__ = "Aaron Swartz <me@aaronsw.com>"
__license__ = "public domain"
File renamed without changes.
@@ -147,6 +147,8 @@ def reparam(string_, dictionary):
>>> reparam("s = $s", dict(s=True))
<sql: "s = 't'">
"""
+ # making a copy of dictionary because eval mangles it
+ dictionary = dictionary.copy()
vals = []
result = []
for live, chunk in _interpolate(string_):
@@ -258,6 +260,10 @@ def connect(dbn, **keywords):
if dbn == "postgres":
try:
import psycopg2 as db
+
+ # fix for Bug#177265
+ import psycopg2.extensions
+ psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
except ImportError:
try:
import psycopg as db
@@ -322,7 +328,19 @@ def db_cursor():
globals()['db'] = _PooledDB(db, keywords)
web.ctx.db = globals()['db'].connection()
else:
- web.ctx.db = db.connect(**keywords)
+ web.ctx.db = db.connect(**keywords)
+
+ # fix for Bug#177265
+ if web.ctx.get('db_name') == "postgres":
+ try:
+ if web.config._hasPooling:
+ # hack to call a function in actual db connection
+ web.ctx.db._con._con.set_client_encoding('UTF8')
+ else:
+ web.ctx.db.set_client_encoding('UTF8')
+ except Exception, e:
+ print >> web.debug, 'Error in setting utf-8 encoding:', str(e), '(ignored)'
+
return web.ctx.db.cursor()
web.ctx.db_cursor = db_cursor
@@ -340,7 +358,7 @@ def db_execute(cur, sql_query, dorollback=True):
except:
if web.config.get('db_printing'):
print >> web.debug, 'ERR:', str(sql_query)
- if dorollback: rollback(care=False)
+ if dorollback and not web.ctx.db_transaction: web.ctx.db.rollback()
raise
if web.config.get('db_printing'):
@@ -360,11 +378,13 @@ class transaction:
end.
"""
def __enter__(self):
+ self.db_transaction = web.ctx.db_transaction
transact()
def __exit__(self, exctype, excvalue, traceback):
if exctype is not None:
- rollback()
+ while self.db_transaction < web.ctx.db_transaction:
+ rollback()
else:
commit()
@@ -398,7 +418,7 @@ def rollback(care=True):
"""Rolls back a transaction."""
web.ctx.db_transaction -= 1
if web.ctx.db_transaction < 0:
- web.db_transaction = 0
+ web.ctx.db_transaction = 0
if care:
raise TransactionError, "not in a transaction"
else:
@@ -460,11 +480,12 @@ def sqllist(lst):
>>> sqllist(['a', 'b'])
'a, b'
- >>> sqllist('a')
- 'a'
-
+ >>> sqllist('foo')
+ 'foo'
+ >>> sqllist(u'foo')
+ u'foo'
"""
- if isinstance(lst, str):
+ if isinstance(lst, (str, unicode)):
return lst
else:
return ', '.join(lst)
Oops, something went wrong.