Edgewall Software

Ticket #9352: 9352-pysqlite-1.patch

File 9352-pysqlite-1.patch, 5.7 KB (added by rblank, 21 months ago)

Restore pysqlite-1.1.7 compatibility in 0.12-stable.

  • trac/db/sqlite_backend.py

    diff --git a/trac/db/sqlite_backend.py b/trac/db/sqlite_backend.py
    a b  
    3535        import sqlite3 as sqlite 
    3636        have_pysqlite = 2 
    3737    except ImportError: 
    38         have_pysqlite = 0 
     38        try: 
     39            import sqlite 
     40            have_pysqlite = 1 
     41        except ImportError: 
     42            have_pysqlite = 0 
    3943 
    4044if have_pysqlite == 2: 
    4145    # Force values to integers because PySQLite 2.2.0 had (2, 2, '0') 
     
    102106            return result 
    103107 
    104108 
     109elif have_pysqlite == 1: 
     110    sqlite_version = sqlite._sqlite.sqlite_version_info() 
     111    sqlite_version_string = '%d.%d.%d' % sqlite_version 
     112 
     113    class SQLiteUnicodeCursor(sqlite.Cursor): 
     114        def _convert_row(self, row): 
     115            return tuple([(isinstance(v, str) and [v.decode('utf-8')] or [v])[0] 
     116                          for v in row]) 
     117        def fetchone(self): 
     118            row = sqlite.Cursor.fetchone(self) 
     119            return row and self._convert_row(row) or None 
     120        def fetchmany(self, num): 
     121            rows = sqlite.Cursor.fetchmany(self, num) 
     122            return rows != None and [self._convert_row(row) 
     123                                     for row in rows] or [] 
     124        def fetchall(self): 
     125            rows = sqlite.Cursor.fetchall(self) 
     126            return rows != None and [self._convert_row(row) 
     127                                     for row in rows] or [] 
     128 
     129 
    105130# Mapping from "abstract" SQL types to DB-specific types 
    106131_type_map = { 
    107132    'int': 'integer', 
     
    152177    def get_supported_schemes(self): 
    153178        if not have_pysqlite: 
    154179            self.error = _("Cannot load Python bindings for SQLite") 
    155         elif sqlite_version >= (3, 3, 3): 
    156             if sqlite.version_info < (1, 1, 7): 
    157                 self.error = _("Need at least PySqlite %(version)s or higher", 
    158                                version='1.1.7') 
    159             elif sqlite.version_info[0] == 2 and \ 
     180        elif sqlite.version_info < (1, 1, 7): 
     181            self.error = _("Need at least PySqlite %(version)s or higher", 
     182                           version='1.1.7') 
     183        elif sqlite_version >= (3, 3, 3) and sqlite.version_info[0] == 2 and \ 
    160184                    sqlite.version_info < (2, 0, 7): 
    161                 self.error = _("Need at least PySqlite %(version)s or higher", 
    162                                version='2.0.7') 
     185            self.error = _("Need at least PySqlite %(version)s or higher", 
     186                           version='2.0.7') 
    163187        yield ('sqlite', self.error and -1 or 1) 
    164188 
    165189    def get_connection(self, path, log=None, params={}): 
     
    254278                      'and the directory it is located in.', 
    255279                      user=getuser(), path=path)) 
    256280 
    257         self._active_cursors = weakref.WeakKeyDictionary() 
    258         timeout = int(params.get('timeout', 10.0)) 
    259         self._eager = params.get('cursor', 'eager') == 'eager' 
    260         # eager is default, can be turned off by specifying ?cursor= 
    261         if isinstance(path, unicode): # needed with 2.4.0 
    262             path = path.encode('utf-8') 
    263         cnx = sqlite.connect(path, detect_types=sqlite.PARSE_DECLTYPES, 
    264                              check_same_thread=sqlite_version < (3, 3, 1), 
    265                              timeout=timeout) 
     281        if have_pysqlite == 2: 
     282            self._active_cursors = weakref.WeakKeyDictionary() 
     283            timeout = int(params.get('timeout', 10.0)) 
     284            self._eager = params.get('cursor', 'eager') == 'eager' 
     285            # eager is default, can be turned off by specifying ?cursor= 
     286            if isinstance(path, unicode): # needed with 2.4.0 
     287                path = path.encode('utf-8') 
     288            cnx = sqlite.connect(path, detect_types=sqlite.PARSE_DECLTYPES, 
     289                                 check_same_thread=sqlite_version < (3, 3, 1), 
     290                                 timeout=timeout) 
     291        else: 
     292            timeout = int(params.get('timeout', 10000)) 
     293            cnx = sqlite.connect(path, timeout=timeout, encoding='utf-8') 
     294             
    266295        # load extensions 
    267296        extensions = params.get('extensions', []) 
    268297        if len(extensions) > 0: 
     
    273302        
    274303        ConnectionWrapper.__init__(self, cnx, log) 
    275304 
    276     def cursor(self): 
    277         cursor = self.cnx.cursor((PyFormatCursor, EagerCursor)[self._eager]) 
    278         self._active_cursors[cursor] = True 
    279         cursor.cnx = self 
    280         return IterableCursor(cursor, self.log) 
     305    if have_pysqlite == 2: 
     306        def cursor(self): 
     307            cursor = self.cnx.cursor((PyFormatCursor, EagerCursor)[self._eager]) 
     308            self._active_cursors[cursor] = True 
     309            cursor.cnx = self 
     310            return IterableCursor(cursor, self.log) 
    281311 
    282     def rollback(self): 
    283         for cursor in self._active_cursors.keys(): 
    284             cursor.close() 
    285         self.cnx.rollback() 
     312        def rollback(self): 
     313            for cursor in self._active_cursors.keys(): 
     314                cursor.close() 
     315            self.cnx.rollback() 
     316 
     317    else: 
     318        def cursor(self): 
     319            self.cnx._checkNotClosed("cursor") 
     320            cursor = SQLiteUnicodeCursor(self.cnx, self.cnx.rowclass) 
     321            return IterableCursor(cursor, self.log) 
    286322 
    287323    def cast(self, column, type): 
    288324        if sqlite_version >= (3, 2, 3): 
     
    313349        """Return the quoted identifier.""" 
    314350        return "`%s`" % identifier 
    315351 
    316     def get_last_id(self, cursor, table, column='id'): 
    317         return cursor.lastrowid 
     352    if have_pysqlite == 2: 
     353        def get_last_id(self, cursor, table, column='id'): 
     354            return cursor.lastrowid 
     355    else: 
     356        def get_last_id(self, cursor, table, column='id'): 
     357            return self.cnx.db.sqlite_last_insert_rowid()