From 1fd4be59013b812e2049784cae1bbecd21221099 Mon Sep 17 00:00:00 2001 From: abi Date: Thu, 25 Dec 2014 21:40:41 +0100 Subject: [PATCH] sqlite3: make it possible to set text_factory upon initialization, including tests --- bottle_sqlite.py | 12 +++++++++++- test.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/bottle_sqlite.py b/bottle_sqlite.py index 7f4c3ae..8d2005c 100755 --- a/bottle_sqlite.py +++ b/bottle_sqlite.py @@ -52,12 +52,19 @@ class SQLitePlugin(object): name = 'sqlite' api = 2 + ''' python3 moves unicode to str ''' + try: + unicode + except NameError: + unicode = str + def __init__(self, dbfile=':memory:', autocommit=True, dictrows=True, - keyword='db'): + keyword='db', text_factory=unicode): self.dbfile = dbfile self.autocommit = autocommit self.dictrows = dictrows self.keyword = keyword + self.text_factory = text_factory def setup(self, app): ''' Make sure that other installed plugins don't affect the same @@ -91,6 +98,7 @@ class SQLitePlugin(object): autocommit = g('autocommit', self.autocommit) dictrows = g('dictrows', self.dictrows) keyword = g('keyword', self.keyword) + text_factory = g('keyword', self.text_factory) # Test if the original callback accepts a 'db' keyword. # Ignore it if it does not need a database handle. @@ -101,6 +109,8 @@ class SQLitePlugin(object): def wrapper(*args, **kwargs): # Connect to the database db = sqlite3.connect(dbfile) + # set text factory + db.text_factory = text_factory # This enables column access by name: row['column_name'] if dictrows: db.row_factory = sqlite3.Row diff --git a/test.py b/test.py index 07a210c..681a79e 100644 --- a/test.py +++ b/test.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- import os import unittest import sqlite3 @@ -6,6 +7,12 @@ import tempfile import bottle from bottle.ext import sqlite +''' python3 moves unicode to str ''' +try: + unicode +except NameError: + unicode = str + class SQLiteTest(unittest.TestCase): @@ -48,6 +55,35 @@ class SQLiteTest(unittest.TestCase): # I have two plugins working with different names self._request('/') + def test_text_factory(self): + # set text factory to str, unicode (default) would cause + # PrammingError: You must not use 8-bit bytestrings .. exception + self.app.install(sqlite.Plugin(keyword='db2',text_factory=str)) + + @self.app.get('/') + def test(db, db2): + char = 'ööö' + db2.execute("CREATE TABLE todo (id INTEGER PRIMARY KEY, task char(100) NOT NULL)") + db2.execute("INSERT INTO todo (id,task) VALUES ('1',:TEST)", { "TEST": char }) + count = len(db2.execute("SELECT * FROM todo").fetchall()) + self.assertEqual(count, 1) + + self._request('/') + + def test_text_factory_fail(self): + self.app.install(sqlite.Plugin(keyword='db3',text_factory=unicode)) + + @self.app.get('/') + def test(db, db3): + char = 'ööö' + db3.execute("CREATE TABLE todo (id INTEGER PRIMARY KEY, task char(100) NOT NULL)") + try: + db3.execute("INSERT INTO todo (id,task) VALUES ('1',:TEST)", { "TEST": char }) + except sqlite3.ProgrammingError as e: + pass + + self._request('/') + def test_raise_sqlite_integrity_error(self): @self.app.get('/') def test(db):