Hello community,

here is the log from the commit of package python3-PyMySQL for openSUSE:Factory 
checked in at 2016-09-14 23:35:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python3-PyMySQL (Old)
 and      /work/SRC/openSUSE:Factory/.python3-PyMySQL.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python3-PyMySQL"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python3-PyMySQL/python3-PyMySQL.changes  
2016-07-28 23:46:30.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python3-PyMySQL.new/python3-PyMySQL.changes     
2016-09-14 23:35:10.000000000 +0200
@@ -1,0 +2,22 @@
+Mon Sep 12 19:38:20 UTC 2016 - [email protected]
+
+- update to version 0.7.9:
+  * Fix PyMySQL stop reading rows when first column is empty string
+    (#513) Reverts DEPRECATE_EOF introduced in 0.7.7.
+
+- changes from version 0.7.8:
+  * Revert error message change in 0.7.7.  (SQLAlchemy parses error
+    message, #507)
+
+- changes from version 0.7.7:
+  * Add new unicode collation (#498)
+  * Fix conv option is not used for encoding objects.
+  * Experimental support for DEPRECATE_EOF protocol.
+
+- changes from version 0.7.6:
+  * Fix SELECT JSON type cause UnicodeError
+  * Avoid float convertion while parsing microseconds
+  * Warning has number
+  * SSCursor supports warnings
+
+-------------------------------------------------------------------

Old:
----
  PyMySQL-0.7.5.tar.gz

New:
----
  PyMySQL-0.7.9.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python3-PyMySQL.spec ++++++
--- /var/tmp/diff_new_pack.I45z1z/_old  2016-09-14 23:35:11.000000000 +0200
+++ /var/tmp/diff_new_pack.I45z1z/_new  2016-09-14 23:35:11.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           python3-PyMySQL
-Version:        0.7.5
+Version:        0.7.9
 Release:        0
 Summary:        Pure Python MySQL Driver
 License:        MIT

++++++ PyMySQL-0.7.5.tar.gz -> PyMySQL-0.7.9.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/CHANGELOG new/PyMySQL-0.7.9/CHANGELOG
--- old/PyMySQL-0.7.5/CHANGELOG 2016-06-28 14:18:40.000000000 +0200
+++ new/PyMySQL-0.7.9/CHANGELOG 2016-09-03 21:13:57.000000000 +0200
@@ -1,5 +1,36 @@
 # Changes
 
+## 0.7.9
+
+Release date: 2016-09-03
+
+* Fix PyMySQL stop reading rows when first column is empty string (#513)
+  Reverts DEPRECATE_EOF introduced in 0.7.7.
+
+## 0.7.8
+
+Release date: 2016-09-01
+
+* Revert error message change in 0.7.7.
+  (SQLAlchemy parses error message, #507)
+
+## 0.7.7
+
+Release date: 2016-08-30
+
+* Add new unicode collation (#498)
+* Fix conv option is not used for encoding objects.
+* Experimental support for DEPRECATE_EOF protocol.
+
+## 0.7.6
+
+Release date: 2016-07-29
+
+* Fix SELECT JSON type cause UnicodeError
+* Avoid float convertion while parsing microseconds
+* Warning has number
+* SSCursor supports warnings
+
 ## 0.7.5
 
 Release date: 2016-06-28
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/PKG-INFO new/PyMySQL-0.7.9/PKG-INFO
--- old/PyMySQL-0.7.5/PKG-INFO  2016-06-28 14:18:51.000000000 +0200
+++ new/PyMySQL-0.7.9/PKG-INFO  2016-09-03 21:14:48.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: PyMySQL
-Version: 0.7.5
+Version: 0.7.9
 Summary: Pure Python MySQL Driver
 Home-page: https://github.com/PyMySQL/PyMySQL/
 Author: INADA Naoki
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/PyMySQL.egg-info/PKG-INFO 
new/PyMySQL-0.7.9/PyMySQL.egg-info/PKG-INFO
--- old/PyMySQL-0.7.5/PyMySQL.egg-info/PKG-INFO 2016-06-28 14:18:50.000000000 
+0200
+++ new/PyMySQL-0.7.9/PyMySQL.egg-info/PKG-INFO 2016-09-03 21:14:48.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: PyMySQL
-Version: 0.7.5
+Version: 0.7.9
 Summary: Pure Python MySQL Driver
 Home-page: https://github.com/PyMySQL/PyMySQL/
 Author: INADA Naoki
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/PyMySQL.egg-info/SOURCES.txt 
new/PyMySQL-0.7.9/PyMySQL.egg-info/SOURCES.txt
--- old/PyMySQL-0.7.5/PyMySQL.egg-info/SOURCES.txt      2016-06-28 
14:18:51.000000000 +0200
+++ new/PyMySQL-0.7.9/PyMySQL.egg-info/SOURCES.txt      2016-09-03 
21:14:48.000000000 +0200
@@ -10,7 +10,6 @@
 PyMySQL.egg-info/PKG-INFO
 PyMySQL.egg-info/SOURCES.txt
 PyMySQL.egg-info/dependency_links.txt
-PyMySQL.egg-info/pbr.json
 PyMySQL.egg-info/top_level.txt
 pymysql/__init__.py
 pymysql/_compat.py
@@ -39,6 +38,7 @@
 pymysql/tests/test_connection.py
 pymysql/tests/test_converters.py
 pymysql/tests/test_cursor.py
+pymysql/tests/test_err.py
 pymysql/tests/test_issues.py
 pymysql/tests/test_load_local.py
 pymysql/tests/test_nextset.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/PyMySQL.egg-info/pbr.json 
new/PyMySQL-0.7.9/PyMySQL.egg-info/pbr.json
--- old/PyMySQL-0.7.5/PyMySQL.egg-info/pbr.json 2015-02-25 10:09:23.000000000 
+0100
+++ new/PyMySQL-0.7.9/PyMySQL.egg-info/pbr.json 1970-01-01 01:00:00.000000000 
+0100
@@ -1 +0,0 @@
-{"is_release": false, "git_version": "08bac52"}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/README.rst new/PyMySQL-0.7.9/README.rst
--- old/PyMySQL-0.7.5/README.rst        2016-05-24 10:05:28.000000000 +0200
+++ new/PyMySQL-0.7.9/README.rst        2016-08-27 19:59:17.000000000 +0200
@@ -15,7 +15,8 @@
 PyMySQL
 =======
 
-.. contents::
+.. contents:: Table of Contents
+   :local:
 
 This package contains a pure-Python MySQL client library. The goal of PyMySQL
 is to be a drop-in replacement for MySQLdb and work on CPython, PyPy and 
IronPython.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/__init__.py 
new/PyMySQL-0.7.9/pymysql/__init__.py
--- old/PyMySQL-0.7.5/pymysql/__init__.py       2016-06-28 14:18:40.000000000 
+0200
+++ new/PyMySQL-0.7.9/pymysql/__init__.py       2016-09-03 21:12:20.000000000 
+0200
@@ -26,14 +26,16 @@
 from ._compat import PY2
 from .constants import FIELD_TYPE
 from .converters import escape_dict, escape_sequence, escape_string
-from .err import Warning, Error, InterfaceError, DataError, \
-     DatabaseError, OperationalError, IntegrityError, InternalError, \
-     NotSupportedError, ProgrammingError, MySQLError
-from .times import Date, Time, Timestamp, \
-    DateFromTicks, TimeFromTicks, TimestampFromTicks
+from .err import (
+    Warning, Error, InterfaceError, DataError,
+    DatabaseError, OperationalError, IntegrityError, InternalError,
+    NotSupportedError, ProgrammingError, MySQLError)
+from .times import (
+    Date, Time, Timestamp,
+    DateFromTicks, TimeFromTicks, TimestampFromTicks)
 
 
-VERSION = (0, 7, 5, None)
+VERSION = (0, 7, 9, None)
 threadsafety = 1
 apilevel = "2.0"
 paramstyle = "pyformat"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/charset.py 
new/PyMySQL-0.7.9/pymysql/charset.py
--- old/PyMySQL-0.7.5/pymysql/charset.py        2014-08-29 13:32:54.000000000 
+0200
+++ new/PyMySQL-0.7.9/pymysql/charset.py        2016-08-27 19:59:17.000000000 
+0200
@@ -11,6 +11,10 @@
         self.id, self.name, self.collation = id, name, collation
         self.is_default = is_default == 'Yes'
 
+    def __repr__(self):
+        return "Charset(id=%s, name=%r, collation=%r)" % (
+                self.id, self.name, self.collation)
+
     @property
     def encoding(self):
         name = self.name
@@ -249,6 +253,10 @@
 _charsets.add(Charset(241, 'utf8mb4', 'utf8mb4_esperanto_ci', ''))
 _charsets.add(Charset(242, 'utf8mb4', 'utf8mb4_hungarian_ci', ''))
 _charsets.add(Charset(243, 'utf8mb4', 'utf8mb4_sinhala_ci', ''))
+_charsets.add(Charset(244, 'utf8mb4', 'utf8mb4_german2_ci', ''))
+_charsets.add(Charset(245, 'utf8mb4', 'utf8mb4_croatian_ci', ''))
+_charsets.add(Charset(246, 'utf8mb4', 'utf8mb4_unicode_520_ci', ''))
+_charsets.add(Charset(247, 'utf8mb4', 'utf8mb4_vietnamese_ci', ''))
 
 
 charset_by_name = _charsets.by_name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/connections.py 
new/PyMySQL-0.7.9/pymysql/connections.py
--- old/PyMySQL-0.7.5/pymysql/connections.py    2016-06-28 13:27:57.000000000 
+0200
+++ new/PyMySQL-0.7.9/pymysql/connections.py    2016-09-03 21:04:12.000000000 
+0200
@@ -88,7 +88,6 @@
     FIELD_TYPE.BLOB,
     FIELD_TYPE.LONG_BLOB,
     FIELD_TYPE.MEDIUM_BLOB,
-    FIELD_TYPE.JSON,
     FIELD_TYPE.STRING,
     FIELD_TYPE.TINY_BLOB,
     FIELD_TYPE.VAR_STRING,
@@ -118,20 +117,18 @@
 
     try:
         print("packet length:", len(data))
-        print("method call[1]:", sys._getframe(1).f_code.co_name)
-        print("method call[2]:", sys._getframe(2).f_code.co_name)
-        print("method call[3]:", sys._getframe(3).f_code.co_name)
-        print("method call[4]:", sys._getframe(4).f_code.co_name)
-        print("method call[5]:", sys._getframe(5).f_code.co_name)
-        print("-" * 88)
+        for i in range(1, 6):
+            f = sys._getframe(i)
+            print("call[%d]: %s (line %d)" % (i, f.f_code.co_name, f.f_lineno))
+        print("-" * 66)
     except ValueError:
         pass
     dump_data = [data[i:i+16] for i in range_type(0, min(len(data), 256), 16)]
     for d in dump_data:
         print(' '.join(map(lambda x: "{:02X}".format(byte2int(x)), d)) +
               '   ' * (16 - len(d)) + ' ' * 2 +
-              ' '.join(map(lambda x: "{}".format(is_ascii(x)), d)))
-    print("-" * 88)
+              ''.join(map(lambda x: "{}".format(is_ascii(x)), d)))
+    print("-" * 66)
     print()
 
 
@@ -364,17 +361,18 @@
         return result
 
     def is_ok_packet(self):
-        return self._data[0:1] == b'\0'
-
-    def is_auth_switch_request(self):
-        # 
http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest
-        return self._data[0:1] == b'\xfe'
+        # https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html
+        return self._data[0:1] == b'\0' and len(self._data) >= 7
 
     def is_eof_packet(self):
         # 
http://dev.mysql.com/doc/internals/en/generic-response-packets.html#packet-EOF_Packet
         # Caution: \xFE may be LengthEncodedInteger.
         # If \xFE is LengthEncodedInteger header, 8bytes followed.
-        return len(self._data) < 9 and self._data[0:1] == b'\xfe'
+        return self._data[0:1] == b'\xfe' and len(self._data) < 9
+
+    def is_auth_switch_request(self):
+        # 
http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest
+        return self._data[0:1] == b'\xfe'
 
     def is_resultset_packet(self):
         field_count = ord(self._data[0:1])
@@ -407,9 +405,9 @@
 
     def __init__(self, data, encoding):
         MysqlPacket.__init__(self, data, encoding)
-        self.__parse_field_descriptor(encoding)
+        self._parse_field_descriptor(encoding)
 
-    def __parse_field_descriptor(self, encoding):
+    def _parse_field_descriptor(self, encoding):
         """Parse the 'Field Descriptor' (Metadata) packet.
 
         This is compatible with MySQL 4.1+ (not compatible with MySQL 4.0).
@@ -660,7 +658,7 @@
 
         self.encoding = charset_by_name(self.charset).encoding
 
-        client_flag |= CLIENT.CAPABILITIES | CLIENT.MULTI_STATEMENTS
+        client_flag |= CLIENT.CAPABILITIES
         if self.db:
             client_flag |= CLIENT.CONNECT_WITH_DB
         self.client_flag = client_flag
@@ -1357,12 +1355,16 @@
         self._read_ok_packet(ok_packet)
 
     def _check_packet_is_eof(self, packet):
-        if packet.is_eof_packet():
-            eof_packet = EOFPacketWrapper(packet)
-            self.warning_count = eof_packet.warning_count
-            self.has_next = eof_packet.has_next
-            return True
-        return False
+        if not packet.is_eof_packet():
+            return False
+        #TODO: Support CLIENT.DEPRECATE_EOF
+        # 1) Add DEPRECATE_EOF to CAPABILITIES
+        # 2) Mask CAPABILITIES with server_capabilities
+        # 3) if server_capabilities & CLIENT.DEPRECATE_EOF: use 
OKPacketWrapper instead of EOFPacketWrapper
+        wp = EOFPacketWrapper(packet)
+        self.warning_count = wp.warning_count
+        self.has_next = wp.has_next
+        return True
 
     def _read_result_packet(self, first_packet):
         self.field_count = first_packet.read_length_encoded_integer()
@@ -1433,21 +1435,30 @@
         self.fields = []
         self.converters = []
         use_unicode = self.connection.use_unicode
+        conn_encoding = self.connection.encoding
         description = []
+
         for i in range_type(self.field_count):
             field = self.connection._read_packet(FieldDescriptorPacket)
             self.fields.append(field)
             description.append(field.description())
             field_type = field.type_code
             if use_unicode:
-                if field_type in TEXT_TYPES:
-                    charset = charset_by_id(field.charsetnr)
-                    if charset.is_binary:
+                if field_type == FIELD_TYPE.JSON:
+                    # When SELECT from JSON column: charset = binary
+                    # When SELECT CAST(... AS JSON): charset = connection 
encoding
+                    # This behavior is different from TEXT / BLOB.
+                    # We should decode result by connection encoding 
regardless charsetnr.
+                    # See https://github.com/PyMySQL/PyMySQL/issues/488
+                    encoding = conn_encoding  # SELECT CAST(... AS JSON) 
+                elif field_type in TEXT_TYPES:
+                    if field.charsetnr == 63:  # binary
                         # TEXTs with charset=binary means BINARY types.
                         encoding = None
                     else:
-                        encoding = charset.encoding
+                        encoding = conn_encoding
                 else:
+                    # Integers, Dates and Times, and other basic data is 
encoded in ascii
                     encoding = 'ascii'
             else:
                 encoding = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/constants/CLIENT.py 
new/PyMySQL-0.7.9/pymysql/constants/CLIENT.py
--- old/PyMySQL-0.7.5/pymysql/constants/CLIENT.py       2016-05-18 
11:03:00.000000000 +0200
+++ new/PyMySQL-0.7.9/pymysql/constants/CLIENT.py       2016-09-03 
21:04:12.000000000 +0200
@@ -19,11 +19,13 @@
 PS_MULTI_RESULTS = 1 << 18
 PLUGIN_AUTH = 1 << 19
 PLUGIN_AUTH_LENENC_CLIENT_DATA = 1 << 21
-CAPABILITIES = (LONG_PASSWORD | LONG_FLAG | TRANSACTIONS |
-                PROTOCOL_41 | SECURE_CONNECTION | PLUGIN_AUTH |
-                PLUGIN_AUTH_LENENC_CLIENT_DATA)
+CAPABILITIES = (
+    LONG_PASSWORD | LONG_FLAG | PROTOCOL_41 | TRANSACTIONS
+    | SECURE_CONNECTION | MULTI_STATEMENTS | MULTI_RESULTS
+    | PLUGIN_AUTH | PLUGIN_AUTH_LENENC_CLIENT_DATA)
+
 # Not done yet
 CONNECT_ATTRS = 1 << 20
 HANDLE_EXPIRED_PASSWORDS = 1 << 22
 SESSION_TRACK = 1 << 23
-CLIENT_DEPRECATE_EOF = 1 << 24
+DEPRECATE_EOF = 1 << 24
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/constants/CR.py 
new/PyMySQL-0.7.9/pymysql/constants/CR.py
--- old/PyMySQL-0.7.5/pymysql/constants/CR.py   2016-05-18 11:03:00.000000000 
+0200
+++ new/PyMySQL-0.7.9/pymysql/constants/CR.py   2016-08-29 18:14:43.000000000 
+0200
@@ -1,3 +1,4 @@
+# flake8: noqa
 # errmsg.h
 CR_ERROR_FIRST         = 2000
 CR_UNKNOWN_ERROR       = 2000
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/converters.py 
new/PyMySQL-0.7.9/pymysql/converters.py
--- old/PyMySQL-0.7.5/pymysql/converters.py     2016-05-24 09:22:27.000000000 
+0200
+++ new/PyMySQL-0.7.9/pymysql/converters.py     2016-08-27 19:59:17.000000000 
+0200
@@ -2,6 +2,7 @@
 
 import datetime
 from decimal import Decimal
+import re
 import time
 
 from .constants import FIELD_TYPE, FLAG
@@ -145,6 +146,16 @@
 def escape_struct_time(obj, mapping=None):
     return escape_datetime(datetime.datetime(*obj[:6]))
 
+def _convert_second_fraction(s):
+    if not s:
+        return 0
+    # Pad zeros to ensure the fraction length in microseconds
+    s = s.ljust(6, '0')
+    return int(s[:6])
+
+DATETIME_RE = re.compile(r"(\d{1,4})-(\d{1,2})-(\d{1,2})[T 
](\d{1,2}):(\d{1,2}):(\d{1,2})(?:.(\d{1,6}))?")
+
+
 def convert_datetime(obj):
     """Returns a DATETIME or TIMESTAMP column value as a datetime object:
 
@@ -163,23 +174,20 @@
     """
     if not PY2 and isinstance(obj, (bytes, bytearray)):
         obj = obj.decode('ascii')
-    if ' ' in obj:
-        sep = ' '
-    elif 'T' in obj:
-        sep = 'T'
-    else:
+
+    m = DATETIME_RE.match(obj)
+    if not m:
         return convert_date(obj)
 
     try:
-        ymd, hms = obj.split(sep, 1)
-        usecs = '0'
-        if '.' in hms:
-            hms, usecs = hms.split('.')
-        usecs = float('0.' + usecs) * 1e6
-        return datetime.datetime(*[ int(x) for x in 
ymd.split('-')+hms.split(':')+[usecs] ])
+        groups = list(m.groups())
+        groups[-1] = _convert_second_fraction(groups[-1])
+        return datetime.datetime(*[ int(x) for x in groups ])
     except ValueError:
         return convert_date(obj)
 
+TIMEDELTA_RE = re.compile(r"(-)?(\d{1,3}):(\d{1,2}):(\d{1,2})(?:.(\d{1,6}))?")
+
 
 def convert_timedelta(obj):
     """Returns a TIME column as a timedelta object:
@@ -200,16 +208,17 @@
     """
     if not PY2 and isinstance(obj, (bytes, bytearray)):
         obj = obj.decode('ascii')
+
+    m = TIMEDELTA_RE.match(obj)
+    if not m:
+        return None
+
     try:
-        microseconds = 0
-        if "." in obj:
-            (obj, tail) = obj.split('.')
-            microseconds = float('0.' + tail) * 1e6
-        hours, minutes, seconds = obj.split(':')
-        negate = 1
-        if hours.startswith("-"):
-            hours = hours[1:]
-            negate = -1
+        groups = list(m.groups())
+        groups[-1] = _convert_second_fraction(groups[-1])
+        negate = -1 if groups[0] else 1
+        hours, minutes, seconds, microseconds = groups[1:]
+
         tdelta = datetime.timedelta(
             hours = int(hours),
             minutes = int(minutes),
@@ -220,6 +229,9 @@
     except ValueError:
         return None
 
+TIME_RE = re.compile(r"(\d{1,2}):(\d{1,2}):(\d{1,2})(?:.(\d{1,6}))?")
+
+
 def convert_time(obj):
     """Returns a TIME column as a time object:
 
@@ -244,17 +256,21 @@
     """
     if not PY2 and isinstance(obj, (bytes, bytearray)):
         obj = obj.decode('ascii')
+
+    m = TIME_RE.match(obj)
+    if not m:
+        return None
+
     try:
-        microseconds = 0
-        if "." in obj:
-            (obj, tail) = obj.split('.')
-            microseconds = float('0.' + tail) * 1e6
-        hours, minutes, seconds = obj.split(':')
+        groups = list(m.groups())
+        groups[-1] = _convert_second_fraction(groups[-1])
+        hours, minutes, seconds, microseconds = groups
         return datetime.time(hour=int(hours), minute=int(minutes),
                              second=int(seconds), 
microsecond=int(microseconds))
     except ValueError:
         return None
 
+
 def convert_date(obj):
     """Returns a DATE column as a date object:
 
@@ -324,7 +340,7 @@
 #def convert_bit(b):
 #    b = "\x00" * (8 - len(b)) + b # pad w/ zeroes
 #    return struct.unpack(">Q", b)[0]
-#    
+#
 #     the snippet above is right, but MySQLdb doesn't process bits,
 #     so we shouldn't either
 convert_bit = through
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/cursors.py 
new/PyMySQL-0.7.9/pymysql/cursors.py
--- old/PyMySQL-0.7.5/pymysql/cursors.py        2016-06-28 13:27:57.000000000 
+0200
+++ new/PyMySQL-0.7.9/pymysql/cursors.py        2016-08-29 18:14:36.000000000 
+0200
@@ -5,7 +5,6 @@
 import warnings
 
 from ._compat import range_type, text_type, PY2
-
 from . import err
 
 
@@ -20,9 +19,9 @@
 
 
 class Cursor(object):
-    '''
+    """
     This is the object you use to interact with the database.
-    '''
+    """
 
     #: Max stetement size which :meth:`executemany` generates.
     #:
@@ -30,11 +29,13 @@
     #: Default value of max_allowed_packet is 1048576.
     max_stmt_length = 1024000
 
+    _defer_warnings = False
+
     def __init__(self, connection):
-        '''
+        """
         Do not create an instance of a Cursor yourself. Call
         connections.Connection.cursor().
-        '''
+        """
         self.connection = connection
         self.description = None
         self.rownumber = 0
@@ -43,11 +44,12 @@
         self._executed = None
         self._result = None
         self._rows = None
+        self._warnings_handled = False
 
     def close(self):
-        '''
+        """
         Closing a cursor just exhausts all remaining data.
-        '''
+        """
         conn = self.connection
         if conn is None:
             return
@@ -86,6 +88,9 @@
         """Get the next query set"""
         conn = self._get_db()
         current_result = self._result
+        # for unbuffered queries warnings are only available once whole result 
has been read
+        if unbuffered:
+            self._show_warnings()
         if current_result is None or current_result is not conn._result:
             return None
         if not current_result.has_next:
@@ -110,12 +115,12 @@
         if isinstance(args, (tuple, list)):
             if PY2:
                 args = tuple(map(ensure_bytes, args))
-            return tuple(conn.escape(arg) for arg in args)
+            return tuple(conn.literal(arg) for arg in args)
         elif isinstance(args, dict):
             if PY2:
                 args = dict((ensure_bytes(key), ensure_bytes(val)) for
                             (key, val) in args.items())
-            return dict((key, conn.escape(val)) for (key, val) in args.items())
+            return dict((key, conn.literal(val)) for (key, val) in 
args.items())
         else:
             # If it's not a dictionary let's try escaping it anyways.
             # Worst case it will throw a Value error
@@ -268,7 +273,7 @@
         return args
 
     def fetchone(self):
-        ''' Fetch the next row '''
+        """Fetch the next row"""
         self._check_executed()
         if self._rows is None or self.rownumber >= len(self._rows):
             return None
@@ -277,7 +282,7 @@
         return result
 
     def fetchmany(self, size=None):
-        ''' Fetch several rows '''
+        """Fetch several rows"""
         self._check_executed()
         if self._rows is None:
             return ()
@@ -287,7 +292,7 @@
         return result
 
     def fetchall(self):
-        ''' Fetch all the rows '''
+        """Fetch all the rows"""
         self._check_executed()
         if self._rows is None:
             return ()
@@ -328,14 +333,18 @@
         self.description = result.description
         self.lastrowid = result.insert_id
         self._rows = result.rows
+        self._warnings_handled = False
 
-        if result.warning_count > 0:
-            self._show_warnings(conn)
+        if not self._defer_warnings:
+            self._show_warnings()
 
-    def _show_warnings(self, conn):
-        if self._result and self._result.has_next:
+    def _show_warnings(self):
+        if self._warnings_handled:
             return
-        ws = conn.show_warnings()
+        self._warnings_handled = True
+        if self._result and (self._result.has_next or not 
self._result.warning_count):
+            return
+        ws = self._get_db().show_warnings()
         if ws is None:
             return
         for w in ws:
@@ -343,7 +352,7 @@
             if PY2:
                 if isinstance(msg, unicode):
                     msg = msg.encode('utf-8', 'replace')
-            warnings.warn(str(msg), err.Warning, 4)
+            warnings.warn(err.Warning(*w[1:3]), stacklevel=4)
 
     def __iter__(self):
         return iter(self.fetchone, None)
@@ -404,6 +413,8 @@
     possible to scroll backwards, as only the current row is held in memory.
     """
 
+    _defer_warnings = True
+
     def _conv_row(self, row):
         return row
 
@@ -432,14 +443,15 @@
         return self._nextset(unbuffered=True)
 
     def read_next(self):
-        """ Read next row """
+        """Read next row"""
         return self._conv_row(self._result._read_rowdata_packet_unbuffered())
 
     def fetchone(self):
-        """ Fetch next row """
+        """Fetch next row"""
         self._check_executed()
         row = self.read_next()
         if row is None:
+            self._show_warnings()
             return None
         self.rownumber += 1
         return row
@@ -464,7 +476,7 @@
         return self.fetchall_unbuffered()
 
     def fetchmany(self, size=None):
-        """ Fetch many """
+        """Fetch many"""
         self._check_executed()
         if size is None:
             size = self.arraysize
@@ -473,6 +485,7 @@
         for i in range_type(size):
             row = self.read_next()
             if row is None:
+                self._show_warnings()
                 break
             rows.append(row)
             self.rownumber += 1
@@ -503,4 +516,4 @@
 
 
 class SSDictCursor(DictCursorMixin, SSCursor):
-    """ An unbuffered cursor, which returns results as a dictionary """
+    """An unbuffered cursor, which returns results as a dictionary"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/err.py 
new/PyMySQL-0.7.9/pymysql/err.py
--- old/PyMySQL-0.7.5/pymysql/err.py    2015-02-05 09:45:43.000000000 +0100
+++ new/PyMySQL-0.7.9/pymysql/err.py    2016-09-03 21:04:12.000000000 +0200
@@ -68,10 +68,12 @@
 
 error_map = {}
 
+
 def _map_error(exc, *errors):
     for error in errors:
         error_map[error] = exc
 
+
 _map_error(ProgrammingError, ER.DB_CREATE_EXISTS, ER.SYNTAX_ERROR,
            ER.PARSE_ERROR, ER.NO_SUCH_TABLE, ER.WRONG_DB_NAME,
            ER.WRONG_TABLE_NAME, ER.FIELD_SPECIFIED_TWICE,
@@ -89,32 +91,17 @@
            ER.CON_COUNT_ERROR, ER.TABLEACCESS_DENIED_ERROR,
            ER.COLUMNACCESS_DENIED_ERROR)
 
+
 del _map_error, ER
 
 
-def _get_error_info(data):
+def raise_mysql_exception(data):
     errno = struct.unpack('<h', data[1:3])[0]
     is_41 = data[3:4] == b"#"
     if is_41:
-        # version 4.1
-        sqlstate = data[4:9].decode("utf8", 'replace')
-        errorvalue = data[9:].decode("utf8", 'replace')
-        return (errno, sqlstate, errorvalue)
+        # client protocol 4.1
+        errval = data[9:].decode('utf-8', 'replace')
     else:
-        # version 4.0
-        return (errno, None, data[3:].decode("utf8", 'replace'))
-
-
-def _check_mysql_exception(errinfo):
-    errno, sqlstate, errorvalue = errinfo
-    errorclass = error_map.get(errno, None)
-    if errorclass:
-        raise errorclass(errno, errorvalue)
-
-    # couldn't find the right error number
-    raise InternalError(errno, errorvalue)
-
-
-def raise_mysql_exception(data):
-    errinfo = _get_error_info(data)
-    _check_mysql_exception(errinfo)
+        errval = data[3:].decode('utf-8', 'replace')
+    errorclass = error_map.get(errno, InternalError)
+    raise errorclass(errno, errval)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/tests/__init__.py 
new/PyMySQL-0.7.9/pymysql/tests/__init__.py
--- old/PyMySQL-0.7.5/pymysql/tests/__init__.py 2016-06-14 10:59:53.000000000 
+0200
+++ new/PyMySQL-0.7.9/pymysql/tests/__init__.py 2016-09-03 21:04:12.000000000 
+0200
@@ -5,6 +5,7 @@
 from pymysql.tests.test_connection import *
 from pymysql.tests.test_converters import *
 from pymysql.tests.test_cursor import *
+from pymysql.tests.test_err import *
 from pymysql.tests.test_issues import *
 from pymysql.tests.test_load_local import *
 from pymysql.tests.test_nextset import *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/tests/test_DictCursor.py 
new/PyMySQL-0.7.9/pymysql/tests/test_DictCursor.py
--- old/PyMySQL-0.7.5/pymysql/tests/test_DictCursor.py  2015-02-04 
18:10:29.000000000 +0100
+++ new/PyMySQL-0.7.9/pymysql/tests/test_DictCursor.py  2016-08-27 
19:59:17.000000000 +0200
@@ -21,7 +21,9 @@
         with warnings.catch_warnings():
             warnings.filterwarnings("ignore")
             c.execute("drop table if exists dictcursor")
-        c.execute("""CREATE TABLE dictcursor (name char(20), age int , DOB 
datetime)""")
+            # include in filterwarnings since for unbuffered dict cursor 
warning for lack of table
+            # will only be propagated at start of next execute() call
+            c.execute("""CREATE TABLE dictcursor (name char(20), age int , DOB 
datetime)""")
         data = [("bob", 21, "1990-02-06 23:04:56"),
                 ("jim", 56, "1955-05-09 13:12:45"),
                 ("fred", 100, "1911-09-12 01:01:01")]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/tests/test_basic.py 
new/PyMySQL-0.7.9/pymysql/tests/test_basic.py
--- old/PyMySQL-0.7.5/pymysql/tests/test_basic.py       2016-05-24 
09:22:27.000000000 +0200
+++ new/PyMySQL-0.7.9/pymysql/tests/test_basic.py       2016-08-29 
18:14:43.000000000 +0200
@@ -1,15 +1,16 @@
-import pymysql.cursors
-
-from pymysql.tests import base
-from pymysql import util
-from pymysql.err import ProgrammingError
-
-import time
+# coding: utf-8
 import datetime
+import json
+import time
 import warnings
 
 from unittest2 import SkipTest
 
+from pymysql import util
+import pymysql.cursors
+from pymysql.tests import base
+from pymysql.err import ProgrammingError
+
 
 __all__ = ["TestConversion", "TestCursor", "TestBulkInserts"]
 
@@ -238,6 +239,31 @@
         self.assertEqual([(1,)], list(c.fetchall()))
         c.close()
 
+    def test_json(self):
+        args = self.databases[0].copy()
+        args["charset"] = "utf8mb4"
+        conn = pymysql.connect(**args)
+        if not self.mysql_server_is(conn, (5, 7, 0)):
+            raise SkipTest("JSON type is not supported on MySQL <= 5.6")
+
+        self.safe_create_table(conn, "test_json", """\
+create table test_json (
+    id int not null,
+    json JSON not null,
+    primary key (id)
+);""")
+        cur = conn.cursor()
+
+        json_str = u'{"hello": "こんにちは"}'
+        cur.execute("INSERT INTO test_json (id, `json`) values (42, %s)", 
(json_str,))
+        cur.execute("SELECT `json` from `test_json` WHERE `id`=42")
+        res = cur.fetchone()[0]
+        self.assertEqual(json.loads(res), json.loads(json_str))
+
+        cur.execute("SELECT CAST(%s AS JSON) AS x", (json_str,))
+        res = cur.fetchone()[0]
+        self.assertEqual(json.loads(res), json.loads(json_str))
+
 
 class TestBulkInserts(base.PyMySQLTestCase):
 
@@ -349,4 +375,5 @@
             cur.execute("drop table if exists no_exists_table")
         self.assertEqual(len(ws), 1)
         self.assertEqual(ws[0].category, pymysql.Warning)
-        self.assertTrue(u"no_exists_table" in str(ws[0].message))
+        if u"no_exists_table" not in str(ws[0].message):
+            self.fail("'no_exists_table' not in %s" % (str(ws[0].message),))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/tests/test_converters.py 
new/PyMySQL-0.7.9/pymysql/tests/test_converters.py
--- old/PyMySQL-0.7.5/pymysql/tests/test_converters.py  2016-05-18 
11:03:00.000000000 +0200
+++ new/PyMySQL-0.7.9/pymysql/tests/test_converters.py  2016-08-27 
19:59:17.000000000 +0200
@@ -1,3 +1,4 @@
+import datetime
 from unittest import TestCase
 
 from pymysql._compat import PY2
@@ -21,3 +22,46 @@
                 converters.escape_string(b"foo\nbar"),
                 b"foo\\nbar"
             )
+
+    def test_convert_datetime(self):
+        expected = datetime.datetime(2007, 2, 24, 23, 6, 20)
+        dt = converters.convert_datetime('2007-02-24 23:06:20')
+        self.assertEqual(dt, expected)
+
+    def test_convert_datetime_with_fsp(self):
+        expected = datetime.datetime(2007, 2, 24, 23, 6, 20, 511581)
+        dt = converters.convert_datetime('2007-02-24 23:06:20.511581')
+        self.assertEqual(dt, expected)
+
+    def _test_convert_timedelta(self, with_negate=False, with_fsp=False):
+        d = {'hours': 789, 'minutes': 12, 'seconds': 34}
+        s = '%(hours)s:%(minutes)s:%(seconds)s' % d
+        if with_fsp:
+            d['microseconds'] = 511581
+            s += '.%(microseconds)s' % d
+
+        expected = datetime.timedelta(**d)
+        if with_negate:
+            expected = -expected
+            s = '-' + s
+
+        tdelta = converters.convert_timedelta(s)
+        self.assertEqual(tdelta, expected)
+
+    def test_convert_timedelta(self):
+        self._test_convert_timedelta(with_negate=False, with_fsp=False)
+        self._test_convert_timedelta(with_negate=True, with_fsp=False)
+
+    def test_convert_timedelta_with_fsp(self):
+        self._test_convert_timedelta(with_negate=False, with_fsp=True)
+        self._test_convert_timedelta(with_negate=False, with_fsp=True)
+
+    def test_convert_time(self):
+        expected = datetime.time(23, 6, 20)
+        time_obj = converters.convert_time('23:06:20')
+        self.assertEqual(time_obj, expected)
+
+    def test_convert_time_with_fsp(self):
+        expected = datetime.time(23, 6, 20, 511581)
+        time_obj = converters.convert_time('23:06:20.511581')
+        self.assertEqual(time_obj, expected)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/tests/test_err.py 
new/PyMySQL-0.7.9/pymysql/tests/test_err.py
--- old/PyMySQL-0.7.5/pymysql/tests/test_err.py 1970-01-01 01:00:00.000000000 
+0100
+++ new/PyMySQL-0.7.9/pymysql/tests/test_err.py 2016-09-03 21:04:12.000000000 
+0200
@@ -0,0 +1,21 @@
+import unittest2
+
+from pymysql import err
+
+
+__all__ = ["TestRaiseException"]
+
+
+class TestRaiseException(unittest2.TestCase):
+
+    def test_raise_mysql_exception(self):
+        data = b"\xff\x15\x04Access denied"
+        with self.assertRaises(err.OperationalError) as cm:
+            err.raise_mysql_exception(data)
+        self.assertEqual(cm.exception.args, (1045, 'Access denied'))
+
+    def test_raise_mysql_exception_client_protocol_41(self):
+        data = b"\xff\x15\x04#28000Access denied"
+        with self.assertRaises(err.OperationalError) as cm:
+            err.raise_mysql_exception(data)
+        self.assertEqual(cm.exception.args, (1045, 'Access denied'))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/tests/test_issues.py 
new/PyMySQL-0.7.9/pymysql/tests/test_issues.py
--- old/PyMySQL-0.7.5/pymysql/tests/test_issues.py      2016-06-28 
13:58:08.000000000 +0200
+++ new/PyMySQL-0.7.9/pymysql/tests/test_issues.py      2016-08-27 
19:59:17.000000000 +0200
@@ -4,6 +4,8 @@
 import sys
 
 import pymysql
+from pymysql import cursors
+from pymysql._compat import text_type
 from pymysql.tests import base
 import unittest2
 
@@ -467,7 +469,7 @@
 
         # select WKB
         query = "SELECT AsBinary(geom) FROM issue363"
-        if sys.version_info[0:2] >= (3,2) and self.mysql_server_is(conn, (5, 
7, 0)):
+        if self.mysql_server_is(conn, (5, 7, 0)):
             with self.assertWarns(pymysql.err.Warning) as cm:
                 cur.execute(query)
         else:
@@ -486,3 +488,28 @@
         # don't assert the exact internal binary value, as it could
         # vary across implementations
         self.assertTrue(isinstance(row[0], bytes))
+
+    def test_issue_491(self):
+        """ Test warning propagation """
+        conn = pymysql.connect(charset="utf8", **self.databases[0])
+
+        with warnings.catch_warnings():
+            # Ignore all warnings other than pymysql generated ones
+            warnings.simplefilter("ignore")
+            warnings.simplefilter("error", category=pymysql.Warning)
+
+            # verify for both buffered and unbuffered cursor types
+            for cursor_class in (cursors.Cursor, cursors.SSCursor):
+                c = conn.cursor(cursor_class)
+                try:
+                    c.execute("SELECT CAST('124b' AS SIGNED)")
+                    c.fetchall()
+                except pymysql.Warning as e:
+                    # Warnings should have errorcode and string message, just 
like exceptions
+                    self.assertEqual(len(e.args), 2)
+                    self.assertEqual(e.args[0], 1292)
+                    self.assertTrue(isinstance(e.args[1], text_type))
+                else:
+                    self.fail("Should raise Warning")
+                finally:
+                    c.close()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/tests/test_load_local.py 
new/PyMySQL-0.7.9/pymysql/tests/test_load_local.py
--- old/PyMySQL-0.7.5/pymysql/tests/test_load_local.py  2016-06-14 
10:59:53.000000000 +0200
+++ new/PyMySQL-0.7.9/pymysql/tests/test_load_local.py  2016-08-29 
18:14:43.000000000 +0200
@@ -80,7 +80,9 @@
                      "test_load_local FIELDS TERMINATED BY 
','").format(filename)
                 )
                 self.assertEqual(w[0].category, Warning)
-                self.assertTrue("Incorrect integer value" in 
str(w[-1].message))
+                expected_message = "Incorrect integer value"
+                if expected_message not in str(w[-1].message):
+                    self.fail("%r not in %r" % (expected_message, 
w[-1].message))
         finally:
             c.execute("DROP TABLE test_load_local")
             c.close()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/times.py 
new/PyMySQL-0.7.9/pymysql/times.py
--- old/PyMySQL-0.7.5/pymysql/times.py  2014-08-29 13:32:54.000000000 +0200
+++ new/PyMySQL-0.7.9/pymysql/times.py  2016-08-29 18:14:43.000000000 +0200
@@ -1,16 +1,20 @@
 from time import localtime
 from datetime import date, datetime, time, timedelta
 
+
 Date = date
 Time = time
 TimeDelta = timedelta
 Timestamp = datetime
 
+
 def DateFromTicks(ticks):
     return date(*localtime(ticks)[:3])
 
+
 def TimeFromTicks(ticks):
     return time(*localtime(ticks)[3:6])
 
+
 def TimestampFromTicks(ticks):
     return datetime(*localtime(ticks)[:6])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/pymysql/util.py 
new/PyMySQL-0.7.9/pymysql/util.py
--- old/PyMySQL-0.7.5/pymysql/util.py   2016-05-18 11:03:00.000000000 +0200
+++ new/PyMySQL-0.7.9/pymysql/util.py   2016-08-29 18:14:43.000000000 +0200
@@ -1,14 +1,17 @@
 import struct
 
+
 def byte2int(b):
     if isinstance(b, int):
         return b
     else:
         return struct.unpack("!B", b)[0]
 
+
 def int2byte(i):
     return struct.pack("!B", i)
 
+
 def join_bytes(bs):
     if len(bs) == 0:
         return ""
@@ -17,4 +20,3 @@
         for b in bs[1:]:
             rv += b
         return rv
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.5/setup.cfg new/PyMySQL-0.7.9/setup.cfg
--- old/PyMySQL-0.7.5/setup.cfg 2016-06-28 14:18:51.000000000 +0200
+++ new/PyMySQL-0.7.9/setup.cfg 2016-09-03 21:14:48.000000000 +0200
@@ -1,6 +1,3 @@
-[wheel]
-universal = 1
-
 [flake8]
 ignore = E226,E301,E701
 exclude = tests,build


Reply via email to