MySQLdb1 icon indicating copy to clipboard operation
MySQLdb1 copied to clipboard

Installable under Python 3.3

Open okin opened this issue 10 years ago • 6 comments

This are some fixes that should make it possible to at least install this projekt under Python 3.3. Running the tests under Python 3.3 fails with an segmentation fault.

okin avatar Jan 10 '14 09:01 okin

:+1:

This passes for me on py26 and py27 and crashes with a segfault on py33, as you said.

$ tox -e py26,py27,py33
...
  py26: commands succeeded
  py27: commands succeeded
ERROR:   py33: commands failed

$ .tox/py33/bin/nosetests -w tests -v
test_BLOB (test_MySQLdb_capabilities.test_MySQLdb) ... [4]    309 segmentation fault  .tox/py33/bin/nosetests -w tests -v

I have some minor suggestions, but otherwise this is good to merge I think.

msabramo avatar Apr 15 '14 19:04 msabramo

Trying to figure out what's wrong by looking at core dump. In case this is useful for someone with more knowledge of CPython and more recent experience with C:

$ ulimit -c unlimited 
$ .tox/py33/bin/nosetests -w tests -v
test_BLOB (test_MySQLdb_capabilities.test_MySQLdb) ... [4]    1578 segmentation fault (core dumped)  .tox/py33/bin/nosetests -w tests -v
$ lldb -c /cores/core.939
error: core.939 is a corrupt mach-o file: load command 185 LC_SEGMENT_64 has a fileoff + filesize (0x17e56000) that extends beyond the end of the file (0x17e55000), the segment will be truncated
error: core.939 is a corrupt mach-o file: load command 186 LC_SEGMENT_64 has a fileoff (0x17e56000) that extends beyond the end of the file (0x17e55000)
Core file '/cores/core.939' (x86_64) was loaded.
Process 0 stopped
* thread #1: tid = 0x0000, 0x00000001000639ec Python`PyObject_Malloc + 92, stop reason = signal SIGSTOP
    frame #0: 0x00000001000639ec Python`PyObject_Malloc + 92
Python`PyObject_Malloc + 92:
-> 0x1000639ec:  movq   (%rsi), %rax
   0x1000639ef:  movq   %rax, 8(%rcx)
   0x1000639f3:  movq   %rsi, %rdx
   0x1000639f6:  testq  %rax, %rax
(lldb) bt 10
* thread #1: tid = 0x0000, 0x00000001000639ec Python`PyObject_Malloc + 92, stop reason = signal SIGSTOP
    frame #0: 0x00000001000639ec Python`PyObject_Malloc + 92
    frame #1: 0x000000010008396f Python`PyUnicode_New + 175
    frame #2: 0x000000010009af5d Python`_PyUnicode_FromASCII + 109
    frame #3: 0x000000010015b22e Python`_textiowrapper_readline + 1678
    frame #4: 0x000000010015b3ac Python`textiowrapper_iternext + 236
    frame #5: 0x0000000100042997 Python`listextend + 199
    frame #6: 0x000000010000d5a8 Python`PyObject_Call + 104
    frame #7: 0x000000010000dca6 Python`callmethod + 134
    frame #8: 0x000000010000f217 Python`_PyObject_CallMethodId_SizeT + 183
    frame #9: 0x000000010014e2f9 Python`iobase_readlines + 233

msabramo avatar Apr 15 '14 19:04 msabramo

diff --git a/MySQLdb/connections.py b/MySQLdb/connections.py
index 13e55c4..6c7c03a 100644
--- a/MySQLdb/connections.py
+++ b/MySQLdb/connections.py
@@ -10,8 +10,12 @@
 from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \
      DatabaseError, OperationalError, IntegrityError, InternalError, \
      NotSupportedError, ProgrammingError
-import types, _mysql
+import _mysql
 import re
+import sys
+
+if sys.version_info[0] == 3:
+    unicode = str


 def defaulterrorhandler(connection, cursor, errorclass, errorvalue):
@@ -233,8 +237,8 @@ def string_decoder(s):
             self.converter[FIELD_TYPE.VARCHAR].append((None, string_decoder))
             self.converter[FIELD_TYPE.BLOB].append((None, string_decoder))

-        self.encoders[types.StringType] = string_literal
-        self.encoders[types.UnicodeType] = unicode_literal
+        self.encoders[bytes] = string_literal
+        self.encoders[unicode] = unicode_literal
         self._transactional = self.server_capabilities & CLIENT.TRANSACTIONS
         if self._transactional:
             if autocommit is not None:
diff --git a/MySQLdb/cursors.py b/MySQLdb/cursors.py
index b45ddaf..4c884a3 100644
--- a/MySQLdb/cursors.py
+++ b/MySQLdb/cursors.py
@@ -7,15 +7,11 @@

 import re
 import sys
-try:
-    from types import ListType, TupleType, UnicodeType
-except ImportError:
-    # Python 3
-    ListType = list
-    TupleType = tuple
-    UnicodeType = str
-
-restr = r"""
+
+if sys.version_info[0] == 3:
+    unicode = str
+
+restr = rb"""
     \s
     values
     \s*
@@ -305,7 +301,7 @@ def callproc(self, procname, args=()):
         q = "CALL %s(%s)" % (procname,
                              ','.join(['@_%s_%d' % (procname, i)
                                        for i in range(len(args))]))
-        if type(q) is UnicodeType:
+        if type(q) is unicode:
             q = q.encode(db.unicode_literal.charset)
         self._query(q)
         self._executed = q
diff --git a/tests/capabilities.py b/tests/capabilities.py
index 076361c..e1760a7 100644
--- a/tests/capabilities.py
+++ b/tests/capabilities.py
@@ -9,7 +9,10 @@
 import array
 import unittest
 from configdb import connection_factory
+import sys

+if sys.version_info[0] == 3:
+    unichr = chr

 class DatabaseTest(unittest.TestCase):

methane avatar Apr 16 '14 00:04 methane

@msabramo I've fixed one memory corruption on #61. Could you try it?

methane avatar Apr 16 '14 14:04 methane

@methane: #61 seemed to stop the segfault on Python 3.3 but it segfaults on Python 2.6 and 2.7 -- both locally and on Travis CI: https://travis-ci.org/farcepest/MySQLdb1/builds/23126432

msabramo avatar Apr 16 '14 15:04 msabramo

I made the changes suggested by @msabramo regarding the use of SafeConfigParser from setup_common.py.

okin avatar Apr 17 '14 09:04 okin