Edgewall Software

Ticket #4378: mysql_unicode.patch

File mysql_unicode.patch, 3.7 kB (added by jonas, 2 months ago)

Implements str->conversion in mysql_backend.py instead of relying on python-mysql

  • trac/db/mysql_backend.py

     
    2626 
    2727try: 
    2828    import MySQLdb 
     29    import MySQLdb.cursors 
    2930    has_mysqldb = True 
     31     
     32    class MySQLUnicodeCursor(MySQLdb.cursors.Cursor): 
     33        def _convert_row(self, row): 
     34            return tuple([(isinstance(v, str) and [v.decode('utf-8')] or [v])[0] 
     35                          for v in row]) 
     36        def fetchone(self): 
     37            row = super(MySQLUnicodeCursor, self).fetchone() 
     38            return row and self._convert_row(row) or None 
     39        def fetchmany(self, num): 
     40            rows = super(MySQLUnicodeCursor, self).fetchmany(num) 
     41            return rows != None and [self._convert_row(row) 
     42                                     for row in rows] or [] 
     43        def fetchall(self): 
     44            rows = super(MySQLUnicodeCursor, self).fetchall() 
     45            return rows != None and [self._convert_row(row) 
     46                                     for row in rows] or [] 
    3047except ImportError: 
    3148    has_mysqldb = False 
    3249 
     
    131148 
    132149    poolable = True 
    133150 
    134     def _mysqldb_gt_or_eq(self, v): 
    135         """This function checks whether the version of python-mysqldb 
    136         is greater than or equal to the version that's passed to it. 
    137         Note that the tuple only checks the major, minor, and sub versions; 
    138         the sub-sub version is weird, so we only check for 'final' versions. 
    139         """ 
    140         ver = MySQLdb.version_info 
    141         if ver[0] < v[0] or ver[1] < v[1] or ver[2] < v[2]: 
    142             return False 
    143         if ver[3] != 'final': 
    144             return False 
    145         return True 
    146  
    147     def _set_character_set(self, cnx, charset): 
    148         vers = tuple([ int(n) for n in cnx.get_server_info().split('.')[:2] ]) 
    149         if vers < (4, 1): 
    150             raise TracError(_('MySQL servers older than 4.1 are not ' 
    151                               'supported!')) 
    152         cnx.query('SET NAMES %s' % charset) 
    153         cnx.store_result() 
    154         cnx.charset = charset 
    155  
    156151    def __init__(self, path, user=None, password=None, host=None, 
    157152                 port=None, params={}): 
    158153        if path.startswith('/'): 
     
    161156            password = '' 
    162157        if port == None: 
    163158            port = 3306 
    164  
    165         # python-mysqldb 1.2.1 added a 'charset' arg that is required for 
    166         # unicode stuff.  We hack around that here for older versions; at 
    167         # some point, this hack should be removed, and a strict requirement 
    168         # on 1.2.1 made.  -dilinger 
    169         if (self._mysqldb_gt_or_eq((1, 2, 1))): 
    170             cnx = MySQLdb.connect(db=path, user=user, passwd=password, 
    171                                   host=host, port=port, charset='utf8') 
    172         else: 
    173             cnx = MySQLdb.connect(db=path, user=user, passwd=password, 
    174                                   host=host, port=port, use_unicode=True) 
    175             self._set_character_set(cnx, 'utf8') 
     159        cnx = MySQLdb.connect(db=path, user=user, passwd=password, 
     160                              host=host, port=port, charset='utf8') 
    176161        ConnectionWrapper.__init__(self, cnx) 
    177162        self._is_closed = False 
    178163 
     
    197182 
    198183    def rollback(self): 
    199184        self.cnx.ping() 
    200         self._set_character_set(self.cnx, 'utf8') 
    201185        try: 
    202186            self.cnx.rollback() 
    203187        except MySQLdb.ProgrammingError: 
     
    210194            except MySQLdb.ProgrammingError: 
    211195                pass # this error would mean it's already closed.  So, ignore 
    212196            self._is_closed = True 
     197 
     198    def cursor(self): 
     199        return MySQLUnicodeCursor(self.cnx) 
     200         
     201 No newline at end of file