Hello community,

here is the log from the commit of package python3-PyMySQL for openSUSE:Factory 
checked in at 2016-07-28 23:46:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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-05-25 21:23:12.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python3-PyMySQL.new/python3-PyMySQL.changes     
2016-07-28 23:46:30.000000000 +0200
@@ -1,0 +2,28 @@
+Sat Jul 23 17:32:11 UTC 2016 - a...@gmx.de
+
+- specfile:
+  *updated url
+
+- update to version 0.7.5:
+  * Fix exception raised while importing when getpwuid() fails (#472)
+  * SSCursor supports LOAD DATA LOCAL INFILE (#473)
+  * Fix encoding error happen for JSON type (#477)
+  * Fix test fail on Python 2.7 and MySQL 5.7 (#478)
+
+- changes from version 0.7.4:
+  * Fix AttributeError may happen while Connection.__del__ (#463)
+  * Fix SyntaxError in test_cursor. (#464)
+  * frozenset support for query value. (#461)
+  * Start using readthedocs.io
+
+- changes from version 0.7.3:
+  * Add read_timeout and write_timeout option.
+  * Support serialization customization by `conv` option.
+  * Unknown type is converted by `str()`, for MySQLdb compatibility.
+  * Support '%%' in `Cursor.executemany()`
+  * Support REPLACE statement in `Cursor.executemany()`
+  * Fix handling incomplete row caused by 'SHOW SLAVE HOSTS'.
+  * Fix decode error when use_unicode=False on PY3
+  * Fix port option in my.cnf file is ignored.
+
+-------------------------------------------------------------------
@@ -6 +33,0 @@
-

Old:
----
  PyMySQL-0.7.2.tar.gz

New:
----
  PyMySQL-0.7.5.tar.gz

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

Other differences:
------------------
++++++ python3-PyMySQL.spec ++++++
--- /var/tmp/diff_new_pack.ZQWNB7/_old  2016-07-28 23:46:32.000000000 +0200
+++ /var/tmp/diff_new_pack.ZQWNB7/_new  2016-07-28 23:46:32.000000000 +0200
@@ -17,12 +17,12 @@
 
 
 Name:           python3-PyMySQL
-Version:        0.7.2
+Version:        0.7.5
 Release:        0
 Summary:        Pure Python MySQL Driver
 License:        MIT
 Group:          Development/Languages/Python
-Url:            http://code.google.com/p/pymysql
+Url:            https://github.com/PyMySQL/PyMySQL
 Source:         
https://files.pythonhosted.org/packages/source/P/PyMySQL/PyMySQL-%{version}.tar.gz
 BuildRequires:  python3-devel
 BuildRequires:  python3-setuptools

++++++ PyMySQL-0.7.2.tar.gz -> PyMySQL-0.7.5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/CHANGELOG new/PyMySQL-0.7.5/CHANGELOG
--- old/PyMySQL-0.7.2/CHANGELOG 2016-02-24 11:38:43.000000000 +0100
+++ new/PyMySQL-0.7.5/CHANGELOG 2016-06-28 14:18:40.000000000 +0200
@@ -1,5 +1,37 @@
 # Changes
 
+## 0.7.5
+
+Release date: 2016-06-28
+
+* Fix exception raised while importing when getpwuid() fails (#472)
+* SSCursor supports LOAD DATA LOCAL INFILE (#473)
+* Fix encoding error happen for JSON type (#477)
+* Fix test fail on Python 2.7 and MySQL 5.7 (#478)
+
+## 0.7.4
+
+Release date: 2016-05-26
+
+* Fix AttributeError may happen while Connection.__del__ (#463)
+* Fix SyntaxError in test_cursor. (#464)
+* frozenset support for query value. (#461)
+* Start using readthedocs.io
+
+## 0.7.3
+
+Release date: 2016-05-19
+
+* Add read_timeout and write_timeout option.
+* Support serialization customization by `conv` option.
+* Unknown type is converted by `str()`, for MySQLdb compatibility.
+* Support '%%' in `Cursor.executemany()`
+* Support REPLACE statement in `Cursor.executemany()`
+* Fix handling incomplete row caused by 'SHOW SLAVE HOSTS'.
+* Fix decode error when use_unicode=False on PY3
+* Fix port option in my.cnf file is ignored.
+
+
 ## 0.7.2
 
 Release date: 2016-02-24
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/PKG-INFO new/PyMySQL-0.7.5/PKG-INFO
--- old/PyMySQL-0.7.2/PKG-INFO  2016-02-24 11:40:57.000000000 +0100
+++ new/PyMySQL-0.7.5/PKG-INFO  2016-06-28 14:18:51.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: PyMySQL
-Version: 0.7.2
+Version: 0.7.5
 Summary: Pure Python MySQL Driver
 Home-page: https://github.com/PyMySQL/PyMySQL/
 Author: INADA Naoki
@@ -8,15 +8,14 @@
 License: MIT
 Description: UNKNOWN
 Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
 Classifier: Programming Language :: Python :: 2
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
-Classifier: Development Status :: 4 - Beta
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Topic :: Database
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/PyMySQL.egg-info/PKG-INFO 
new/PyMySQL-0.7.5/PyMySQL.egg-info/PKG-INFO
--- old/PyMySQL-0.7.2/PyMySQL.egg-info/PKG-INFO 2016-02-24 11:40:56.000000000 
+0100
+++ new/PyMySQL-0.7.5/PyMySQL.egg-info/PKG-INFO 2016-06-28 14:18:50.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: PyMySQL
-Version: 0.7.2
+Version: 0.7.5
 Summary: Pure Python MySQL Driver
 Home-page: https://github.com/PyMySQL/PyMySQL/
 Author: INADA Naoki
@@ -8,15 +8,14 @@
 License: MIT
 Description: UNKNOWN
 Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
 Classifier: Programming Language :: Python :: 2
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
-Classifier: Development Status :: 4 - Beta
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Topic :: Database
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/PyMySQL.egg-info/SOURCES.txt 
new/PyMySQL-0.7.5/PyMySQL.egg-info/SOURCES.txt
--- old/PyMySQL-0.7.2/PyMySQL.egg-info/SOURCES.txt      2016-02-24 
11:40:57.000000000 +0100
+++ new/PyMySQL-0.7.5/PyMySQL.egg-info/SOURCES.txt      2016-06-28 
14:18:51.000000000 +0200
@@ -39,7 +39,6 @@
 pymysql/tests/test_connection.py
 pymysql/tests/test_converters.py
 pymysql/tests/test_cursor.py
-pymysql/tests/test_example.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.2/README.rst new/PyMySQL-0.7.5/README.rst
--- old/PyMySQL-0.7.2/README.rst        2016-02-24 11:30:58.000000000 +0100
+++ new/PyMySQL-0.7.5/README.rst        2016-05-24 10:05:28.000000000 +0200
@@ -1,18 +1,30 @@
-=======
-PyMySQL
-=======
+.. image:: https://readthedocs.org/projects/pymysql/badge/?version=latest
+    :target: http://pymysql.readthedocs.io/en/latest/?badge=latest
+    :alt: Documentation Status
 
 .. image:: https://travis-ci.org/PyMySQL/PyMySQL.svg?branch=master
-   :target: https://travis-ci.org/PyMySQL/PyMySQL
+    :target: https://travis-ci.org/PyMySQL/PyMySQL
 
 .. image:: 
https://coveralls.io/repos/PyMySQL/PyMySQL/badge.svg?branch=master&service=github
-   :target: https://coveralls.io/github/PyMySQL/PyMySQL?branch=master
+    :target: https://coveralls.io/github/PyMySQL/PyMySQL?branch=master
+
+.. image:: https://img.shields.io/badge/license-MIT-blue.svg
+    :target: https://github.com/PyMySQL/PyMySQL/blob/master/LICENSE
+
+
+PyMySQL
+=======
 
 .. contents::
 
 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.
 
+NOTE: PyMySQL doesn't support low level APIs `_mysql` provides like 
`data_seek`,
+`store_result`, and `use_result`. You should use high level APIs defined in 
PEP 294.
+But some APIs like `autocommit` and `ping` are supported because PEP 294 
doesn't cover
+their usecase.
+
 
 Requirements
 -------------
@@ -42,38 +54,14 @@
 
     $ pip install PyMySQL
 
-Alternatively (e.g. if ``pip`` is not available), a tarball can be downloaded
-from GitHub and installed with Setuptools::
 
-    $ # X.X is the desired PyMySQL version (e.g. 0.5 or 0.6).
-    $ curl -L https://github.com/PyMySQL/PyMySQL/tarball/pymysql-X.X | tar xz
-    $ cd PyMySQL*
-    $ python setup.py install
-    $ # The folder PyMySQL* can be safely removed now.
-
-Test Suite
-----------
-
-If you would like to run the test suite, create database for test like this::
-
-    mysql -e 'create database test_pymysql  DEFAULT CHARACTER SET utf8 DEFAULT 
COLLATE utf8_general_ci;'
-    mysql -e 'create database test_pymysql2 DEFAULT CHARACTER SET utf8 DEFAULT 
COLLATE utf8_general_ci;'
-
-Then, copy the file ``.travis.databases.json`` to 
``pymysql/tests/databases.json``
-and edit the new file to match your MySQL configuration::
-
-    $ cp .travis.databases.json pymysql/tests/databases.json
-    $ $EDITOR pymysql/tests/databases.json
-
-To run all the tests, execute the script ``runtests.py``::
-
-    $ python runtests.py
-
-A ``tox.ini`` file is also provided for conveniently running tests on multiple
-Python versions::
+Documentation
+-------------
 
-    $ tox
+Documentation is available online: http://pymysql.readthedocs.io/
 
+For support, please refer to the `StackOverflow
+<http://stackoverflow.com/questions/tagged/pymysql>`_.
 
 Example
 -------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/pymysql/__init__.py 
new/PyMySQL-0.7.5/pymysql/__init__.py
--- old/PyMySQL-0.7.2/pymysql/__init__.py       2016-02-24 11:39:11.000000000 
+0100
+++ new/PyMySQL-0.7.5/pymysql/__init__.py       2016-06-28 14:18:40.000000000 
+0200
@@ -33,7 +33,7 @@
     DateFromTicks, TimeFromTicks, TimestampFromTicks
 
 
-VERSION = (0, 7, 2, None)
+VERSION = (0, 7, 5, None)
 threadsafety = 1
 apilevel = "2.0"
 paramstyle = "pyformat"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/pymysql/connections.py 
new/PyMySQL-0.7.5/pymysql/connections.py
--- old/PyMySQL-0.7.2/pymysql/connections.py    2016-02-24 11:30:58.000000000 
+0100
+++ new/PyMySQL-0.7.5/pymysql/connections.py    2016-06-28 13:27:57.000000000 
+0200
@@ -18,8 +18,7 @@
 
 from .charset import MBLENGTH, charset_by_name, charset_by_id
 from .constants import CLIENT, COMMAND, FIELD_TYPE, SERVER_STATUS
-from .converters import (
-    escape_item, encoders, decoders, escape_string, through)
+from .converters import escape_item, escape_string, through, conversions as 
_conv
 from .cursors import Cursor
 from .optionfile import Parser
 from .util import byte2int, int2byte
@@ -36,7 +35,8 @@
     import getpass
     DEFAULT_USER = getpass.getuser()
     del getpass
-except ImportError:
+except (ImportError, KeyError):
+    # KeyError occurs when there's no entry in OS database for a current user.
     DEFAULT_USER = None
 
 
@@ -88,6 +88,7 @@
     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,
@@ -523,19 +524,19 @@
     connect().
     """
 
-    socket = None
+    _sock = None
     _auth_plugin_name = ''
 
     def __init__(self, host=None, user=None, password="",
-                 database=None, port=3306, unix_socket=None,
+                 database=None, port=0, unix_socket=None,
                  charset='', sql_mode=None,
-                 read_default_file=None, conv=decoders, use_unicode=None,
+                 read_default_file=None, conv=None, use_unicode=None,
                  client_flag=0, cursorclass=Cursor, init_command=None,
                  connect_timeout=None, ssl=None, read_default_group=None,
                  compress=None, named_pipe=None, no_delay=None,
                  autocommit=False, db=None, passwd=None, local_infile=False,
                  max_allowed_packet=16*1024*1024, defer_connect=False,
-                 auth_plugin_map={}):
+                 auth_plugin_map={}, read_timeout=None, write_timeout=None):
         """
         Establish a connection to the MySQL database. Accepts several
         arguments:
@@ -544,15 +545,16 @@
         user: Username to log in as
         password: Password to use.
         database: Database to use, None to not use a particular one.
-        port: MySQL port to use, default is usually OK.
+        port: MySQL port to use, default is usually OK. (default: 3306)
         unix_socket: Optionally, you can use a unix socket rather than TCP/IP.
         charset: Charset you want to use.
         sql_mode: Default SQL_MODE to use.
         read_default_file:
             Specifies  my.cnf file to read these parameters from under the 
[client] section.
         conv:
-            Decoders dictionary to use instead of the default one.
-            This is used to provide custom marshalling of types. See 
converters.
+            Conversion dictionary to use instead of the default one.
+            This is used to provide custom marshalling and unmarshaling of 
types.
+            See converters.
         use_unicode:
             Whether or not to default to unicode strings.
             This option defaults to true for Py3k.
@@ -635,11 +637,17 @@
             charset = _config("default-character-set", charset)
 
         self.host = host or "localhost"
-        self.port = port
+        self.port = port or 3306
         self.user = user or DEFAULT_USER
         self.password = password or ""
         self.db = database
         self.unix_socket = unix_socket
+        if read_timeout is not None and read_timeout <= 0:
+            raise ValueError("read_timeout should be >= 0")
+        self._read_timeout = read_timeout
+        if write_timeout is not None and write_timeout <= 0:
+            raise ValueError("write_timeout should be >= 0")
+        self._write_timeout = write_timeout
         if charset:
             self.charset = charset
             self.use_unicode = True
@@ -667,14 +675,17 @@
         #: specified autocommit mode. None means use server default.
         self.autocommit_mode = autocommit
 
-        self.encoders = encoders  # Need for MySQLdb compatibility.
-        self.decoders = conv
+        if conv is None:
+            conv = _conv
+        # Need for MySQLdb compatibility.
+        self.encoders = dict([(k, v) for (k, v) in conv.items() if type(k) is 
not int])
+        self.decoders = dict([(k, v) for (k, v) in conv.items() if type(k) is 
int])
         self.sql_mode = sql_mode
         self.init_command = init_command
         self.max_allowed_packet = max_allowed_packet
         self._auth_plugin_map = auth_plugin_map
         if defer_connect:
-            self.socket = None
+            self._sock = None
         else:
             self.connect()
 
@@ -697,7 +708,7 @@
 
     def close(self):
         """Send the quit message and close the socket"""
-        if self.socket is None:
+        if self._sock is None:
             raise err.Error("Already closed")
         send_data = struct.pack('<iB', 1, COMMAND.COM_QUIT)
         try:
@@ -705,22 +716,22 @@
         except Exception:
             pass
         finally:
-            sock = self.socket
-            self.socket = None
+            sock = self._sock
+            self._sock = None
             self._rfile = None
             sock.close()
 
     @property
     def open(self):
-        return self.socket is not None
+        return self._sock is not None
 
     def __del__(self):
-        if self.socket:
+        if self._sock:
             try:
-                self.socket.close()
+                self._sock.close()
             except:
                 pass
-        self.socket = None
+        self._sock = None
         self._rfile = None
 
     def autocommit(self, value):
@@ -770,19 +781,25 @@
         return result.rows
 
     def select_db(self, db):
-        '''Set current db'''
+        """Set current db"""
         self._execute_command(COMMAND.COM_INIT_DB, db)
         self._read_ok_packet()
 
     def escape(self, obj, mapping=None):
-        """Escape whatever value you pass to it"""
+        """Escape whatever value you pass to it.
+        
+        Non-standard, for internal use; do not use this in your applications.
+        """
         if isinstance(obj, str_type):
             return "'" + self.escape_string(obj) + "'"
         return escape_item(obj, self.charset, mapping=mapping)
 
     def literal(self, obj):
-        '''Alias for escape()'''
-        return self.escape(obj)
+        """Alias for escape()
+        
+        Non-standard, for internal use; do not use this in your applications.
+        """
+        return self.escape(obj, self.encoders)
 
     def escape_string(self, s):
         if (self.server_status &
@@ -834,7 +851,7 @@
 
     def ping(self, reconnect=True):
         """Check if the server is alive"""
-        if self.socket is None:
+        if self._sock is None:
             if reconnect:
                 self.connect()
                 reconnect = False
@@ -883,7 +900,7 @@
                     sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
                 sock.settimeout(None)
                 sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
-            self.socket = sock
+            self._sock = sock
             self._rfile = _makefile(sock, 'rb')
             self._next_seq_id = 0
 
@@ -967,6 +984,7 @@
         return packet
 
     def _read_bytes(self, num_bytes):
+        self._sock.settimeout(self._read_timeout)
         while True:
             try:
                 data = self._rfile.read(num_bytes)
@@ -983,8 +1001,9 @@
         return data
 
     def _write_bytes(self, data):
+        self._sock.settimeout(self._write_timeout)
         try:
-            self.socket.sendall(data)
+            self._sock.sendall(data)
         except IOError as e:
             raise err.OperationalError(2006, "MySQL server has gone away (%r)" 
% (e,))
 
@@ -1012,7 +1031,7 @@
             return 0
 
     def _execute_command(self, command, sql):
-        if not self.socket:
+        if not self._sock:
             raise err.InterfaceError("(0, '')")
 
         # If the last query was unbuffered, make sure it finishes before
@@ -1066,8 +1085,8 @@
         if self.ssl and self.server_capabilities & CLIENT.SSL:
             self.write_packet(data_init)
 
-            self.socket = self.ctx.wrap_socket(self.socket, 
server_hostname=self.host)
-            self._rfile = _makefile(self.socket, 'rb')
+            self._sock = self.ctx.wrap_socket(self._sock, 
server_hostname=self.host)
+            self._rfile = _makefile(self._sock, 'rb')
 
         data = data_init + self.user + b'\0'
 
@@ -1301,6 +1320,10 @@
             self._read_ok_packet(first_packet)
             self.unbuffered_active = False
             self.connection = None
+        elif first_packet.is_load_local_packet():
+            self._read_load_local_packet(first_packet)
+            self.unbuffered_active = False
+            self.connection = None
         else:
             self.field_count = first_packet.read_length_encoded_integer()
             self._get_descriptions()
@@ -1390,7 +1413,12 @@
     def _read_row_from_packet(self, packet):
         row = []
         for encoding, converter in self.converters:
-            data = packet.read_length_coded_string()
+            try:
+                data = packet.read_length_coded_string()
+            except IndexError:
+                # No more columns in this row
+                # See https://github.com/PyMySQL/PyMySQL/pull/434
+                break
             if data is not None:
                 if encoding is not None:
                     data = data.decode(encoding)
@@ -1441,7 +1469,7 @@
 
     def send_data(self):
         """Send data packets from the local file to the server"""
-        if not self.connection.socket:
+        if not self.connection._sock:
             raise err.InterfaceError("(0, '')")
         conn = self.connection
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/pymysql/constants/FIELD_TYPE.py 
new/PyMySQL-0.7.5/pymysql/constants/FIELD_TYPE.py
--- old/PyMySQL-0.7.2/pymysql/constants/FIELD_TYPE.py   2014-08-29 
13:32:54.000000000 +0200
+++ new/PyMySQL-0.7.5/pymysql/constants/FIELD_TYPE.py   2016-06-28 
13:27:57.000000000 +0200
@@ -17,6 +17,7 @@
 NEWDATE = 14
 VARCHAR = 15
 BIT = 16
+JSON = 245
 NEWDECIMAL = 246
 ENUM = 247
 SET = 248
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/pymysql/converters.py 
new/PyMySQL-0.7.5/pymysql/converters.py
--- old/PyMySQL-0.7.2/pymysql/converters.py     2016-02-24 11:30:58.000000000 
+0100
+++ new/PyMySQL-0.7.5/pymysql/converters.py     2016-05-24 09:22:27.000000000 
+0200
@@ -109,7 +109,7 @@
     return u"'%s'" % _escape_unicode(value)
 
 def escape_str(value, mapping=None):
-    return "'%s'" % escape_string(value, mapping)
+    return "'%s'" % escape_string(str(value), mapping)
 
 def escape_None(value, mapping=None):
     return 'NULL'
@@ -161,6 +161,8 @@
       True
 
     """
+    if not PY2 and isinstance(obj, (bytes, bytearray)):
+        obj = obj.decode('ascii')
     if ' ' in obj:
         sep = ' '
     elif 'T' in obj:
@@ -196,6 +198,8 @@
     can accept values as (+|-)DD HH:MM:SS. The latter format will not
     be parsed correctly by this function.
     """
+    if not PY2 and isinstance(obj, (bytes, bytearray)):
+        obj = obj.decode('ascii')
     try:
         microseconds = 0
         if "." in obj:
@@ -238,6 +242,8 @@
     to be treated as time-of-day and not a time offset, then you can
     use set this function as the converter for FIELD_TYPE.TIME.
     """
+    if not PY2 and isinstance(obj, (bytes, bytearray)):
+        obj = obj.decode('ascii')
     try:
         microseconds = 0
         if "." in obj:
@@ -263,6 +269,8 @@
       True
 
     """
+    if not PY2 and isinstance(obj, (bytes, bytearray)):
+        obj = obj.decode('ascii')
     try:
         return datetime.date(*[ int(x) for x in obj.split('-', 2) ])
     except ValueError:
@@ -290,6 +298,8 @@
       True
 
     """
+    if not PY2 and isinstance(timestamp, (bytes, bytearray)):
+        timestamp = timestamp.decode('ascii')
     if timestamp[4] == '-':
         return convert_datetime(timestamp)
     timestamp += "0"*(14-len(timestamp)) # padding
@@ -302,6 +312,8 @@
         return None
 
 def convert_set(s):
+    if isinstance(s, (bytes, bytearray)):
+        return set(s.split(b","))
     return set(s.split(","))
 
 
@@ -343,6 +355,7 @@
     tuple: escape_sequence,
     list: escape_sequence,
     set: escape_sequence,
+    frozenset: escape_sequence,
     dict: escape_dict,
     bytearray: escape_bytes,
     type(None): escape_None,
@@ -385,7 +398,6 @@
 
 
 # for MySQLdb compatibility
-conversions = decoders
-
-def Thing2Literal(obj):
-    return escape_str(str(obj))
+conversions = encoders.copy()
+conversions.update(decoders)
+Thing2Literal = escape_str
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/pymysql/cursors.py 
new/PyMySQL-0.7.5/pymysql/cursors.py
--- old/PyMySQL-0.7.2/pymysql/cursors.py        2016-02-24 11:35:47.000000000 
+0100
+++ new/PyMySQL-0.7.5/pymysql/cursors.py        2016-06-28 13:27:57.000000000 
+0200
@@ -12,8 +12,11 @@
 #: Regular expression for :meth:`Cursor.executemany`.
 #: executemany only suports simple bulk insert.
 #: You can use it to load large dataset.
-RE_INSERT_VALUES = 
re.compile(r"""(INSERT\s.+\sVALUES\s+)(\(\s*(?:%s|%\(.+\)s)\s*(?:,\s*(?:%s|%\(.+\)s)\s*)*\))(\s*(?:ON
 DUPLICATE.*)?)\Z""",
-                              re.IGNORECASE | re.DOTALL)
+RE_INSERT_VALUES = re.compile(
+    r"\s*((?:INSERT|REPLACE)\s.+\sVALUES?\s+)" +
+    r"(\(\s*(?:%s|%\(.+\)s)\s*(?:,\s*(?:%s|%\(.+\)s)\s*)*\))" +
+    r"(\s*(?:ON DUPLICATE.*)?)\Z",
+    re.IGNORECASE | re.DOTALL)
 
 
 class Cursor(object):
@@ -141,7 +144,7 @@
 
         :param str query: Query to execute.
 
-        :param args: arameters used with query. (optional)
+        :param args: parameters used with query. (optional)
         :type args: tuple, list or dict
 
         :return: Number of affected rows
@@ -160,17 +163,23 @@
         return result
 
     def executemany(self, query, args):
+        # type: (str, list) -> int
         """Run several data against one query
 
-        PyMySQL can execute bulkinsert for query like 'INSERT ... VALUES (%s)'.
-        In other form of queries, just run :meth:`execute` many times.
+        :param query: query to execute on server
+        :param args:  Sequence of sequences or mappings.  It is used as 
parameter.
+        :return: Number of rows affected, if any.
+
+        This method improves performance on multiple-row INSERT and
+        REPLACE. Otherwise it is equivalent to looping over args with
+        execute().
         """
         if not args:
             return
 
         m = RE_INSERT_VALUES.match(query)
         if m:
-            q_prefix = m.group(1)
+            q_prefix = m.group(1) % ()
             q_values = m.group(2).rstrip()
             q_postfix = m.group(3) or ''
             assert q_values[0] == '(' and q_values[-1] == ')'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/pymysql/tests/__init__.py 
new/PyMySQL-0.7.5/pymysql/tests/__init__.py
--- old/PyMySQL-0.7.2/pymysql/tests/__init__.py 2016-02-24 11:30:58.000000000 
+0100
+++ new/PyMySQL-0.7.5/pymysql/tests/__init__.py 2016-06-14 10:59:53.000000000 
+0200
@@ -1,12 +1,14 @@
-from pymysql.tests.test_issues import *
-from pymysql.tests.test_basic import *
-from pymysql.tests.test_nextset import *
+# Sorted by alphabetical order
 from pymysql.tests.test_DictCursor import *
-from pymysql.tests.test_connection import *
 from pymysql.tests.test_SSCursor import *
+from pymysql.tests.test_basic import *
+from pymysql.tests.test_connection import *
+from pymysql.tests.test_converters import *
+from pymysql.tests.test_cursor import *
+from pymysql.tests.test_issues import *
 from pymysql.tests.test_load_local import *
+from pymysql.tests.test_nextset import *
 from pymysql.tests.test_optionfile import *
-from pymysql.tests.test_converters import *
 
 from pymysql.tests.thirdparty import *
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/pymysql/tests/test_basic.py 
new/PyMySQL-0.7.5/pymysql/tests/test_basic.py
--- old/PyMySQL-0.7.2/pymysql/tests/test_basic.py       2015-02-28 
19:44:12.000000000 +0100
+++ new/PyMySQL-0.7.5/pymysql/tests/test_basic.py       2016-05-24 
09:22:27.000000000 +0200
@@ -42,11 +42,15 @@
 
             c.execute("delete from test_datatypes")
 
-            # check sequence type
-            c.execute("insert into test_datatypes (i, l) values (2,4), (6,8), 
(10,12)")
-            c.execute("select l from test_datatypes where i in %s order by i", 
((2,6),))
-            r = c.fetchall()
-            self.assertEqual(((4,),(8,)), r)
+            # check sequences type
+            for seq_type in (tuple, list, set, frozenset):
+                c.execute("insert into test_datatypes (i, l) values (2,4), 
(6,8), (10,12)")
+                seq = seq_type([2,6])
+                c.execute("select l from test_datatypes where i in %s order by 
i", (seq,))
+                r = c.fetchall()
+                self.assertEqual(((4,),(8,)), r)
+                c.execute("delete from test_datatypes")
+
         finally:
             c.execute("drop table test_datatypes")
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/pymysql/tests/test_cursor.py 
new/PyMySQL-0.7.5/pymysql/tests/test_cursor.py
--- old/PyMySQL-0.7.2/pymysql/tests/test_cursor.py      2016-02-24 
11:30:58.000000000 +0100
+++ new/PyMySQL-0.7.5/pymysql/tests/test_cursor.py      2016-06-14 
10:59:53.000000000 +0200
@@ -34,18 +34,8 @@
 
         c2 = conn.cursor()
 
-        with warnings.catch_warnings(record=True) as log:
-            warnings.filterwarnings("always")
-
-            c2.execute("select 1")
-
-        self.assertGreater(len(log), 0)
-        self.assertEqual(
-            "Previous unbuffered result was left incomplete",
-            str(log[-1].message))
-        self.assertEqual(
-            c2.fetchone(), (1,)
-        )
+        c2.execute("select 1")
+        self.assertEqual(c2.fetchone(), (1,))
         self.assertIsNone(c2.fetchone())
 
     def test_cleanup_rows_buffered(self):
@@ -89,13 +79,26 @@
         self.assertIsNotNone(m, 'error parse %(id_name)s')
         self.assertEqual(m.group(3), ' ON duplicate update', 'group 3 not ON 
duplicate update, bug in RE_INSERT_VALUES?')
 
-        # cursor._executed myst bee "insert into test (data) values 
(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)"
+        # cursor._executed must bee "insert into test (data) values 
(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)"
         # list args
-        data = xrange(10)
+        data = range(10)
         cursor.executemany("insert into test (data) values (%s)", data)
-        self.assertTrue(cursor._executed.endswith(",(7),(8),(9)"), 'execute 
many with %s not in one query')
+        self.assertTrue(cursor._executed.endswith(b",(7),(8),(9)"), 'execute 
many with %s not in one query')
 
         # dict args
-        data_dict = [{'data': i} for i in xrange(10)]
+        data_dict = [{'data': i} for i in range(10)]
         cursor.executemany("insert into test (data) values (%(data)s)", 
data_dict)
-        self.assertTrue(cursor._executed.endswith(",(7),(8),(9)"), 'execute 
many with %(data)s not in one query')
+        self.assertTrue(cursor._executed.endswith(b",(7),(8),(9)"), 'execute 
many with %(data)s not in one query')
+
+        # %% in column set
+        cursor.execute("""\
+            CREATE TABLE percent_test (
+                `A%` INTEGER,
+                `B%` INTEGER)""")
+        try:
+            q = "INSERT INTO percent_test (`A%%`, `B%%`) VALUES (%s, %s)"
+            self.assertIsNotNone(pymysql.cursors.RE_INSERT_VALUES.match(q))
+            cursor.executemany(q, [(3, 4), (5, 6)])
+            self.assertTrue(cursor._executed.endswith(b"(3, 4),(5, 6)"), 
"executemany with %% not in one query")
+        finally:
+            cursor.execute("DROP TABLE IF EXISTS percent_test")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/pymysql/tests/test_example.py 
new/PyMySQL-0.7.5/pymysql/tests/test_example.py
--- old/PyMySQL-0.7.2/pymysql/tests/test_example.py     2014-08-29 
13:32:54.000000000 +0200
+++ new/PyMySQL-0.7.5/pymysql/tests/test_example.py     1970-01-01 
01:00:00.000000000 +0100
@@ -1,32 +0,0 @@
-import pymysql
-from pymysql.tests import base
-
-class TestExample(base.PyMySQLTestCase):
-    def test_example(self):
-        conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', 
passwd='', db='mysql')
-
-
-        cur = conn.cursor()
-
-        cur.execute("SELECT Host,User FROM user")
-
-        # print cur.description
-
-        # r = cur.fetchall()
-        # print r
-        # ...or...
-        u = False
-
-        for r in cur.fetchall():
-            u = u or conn.user in r
-
-        self.assertTrue(u)
-
-        cur.close()
-        conn.close()
-
-__all__ = ["TestExample"]
-
-if __name__ == "__main__":
-    import unittest
-    unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/pymysql/tests/test_issues.py 
new/PyMySQL-0.7.5/pymysql/tests/test_issues.py
--- old/PyMySQL-0.7.2/pymysql/tests/test_issues.py      2016-02-24 
11:30:58.000000000 +0100
+++ new/PyMySQL-0.7.5/pymysql/tests/test_issues.py      2016-06-28 
13:58:08.000000000 +0200
@@ -457,7 +457,7 @@
 
         # select WKT
         query = "SELECT AsText(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:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/pymysql/tests/test_load_local.py 
new/PyMySQL-0.7.5/pymysql/tests/test_load_local.py
--- old/PyMySQL-0.7.2/pymysql/tests/test_load_local.py  2016-02-24 
11:30:58.000000000 +0100
+++ new/PyMySQL-0.7.5/pymysql/tests/test_load_local.py  2016-06-14 
10:59:53.000000000 +0200
@@ -1,4 +1,4 @@
-from pymysql import OperationalError, Warning
+from pymysql import cursors, OperationalError, Warning
 from pymysql.tests import base
 
 import os
@@ -42,6 +42,28 @@
         finally:
             c.execute("DROP TABLE test_load_local")
 
+    def test_unbuffered_load_file(self):
+        """Test unbuffered load local infile with a valid file"""
+        conn = self.connections[0]
+        c = conn.cursor(cursors.SSCursor)
+        c.execute("CREATE TABLE test_load_local (a INTEGER, b INTEGER)")
+        filename = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+                                'data',
+                                'load_local_data.txt')
+        try:
+            c.execute(
+                ("LOAD DATA LOCAL INFILE '{0}' INTO TABLE " +
+                 "test_load_local FIELDS TERMINATED BY ','").format(filename)
+            )
+            c.execute("SELECT COUNT(*) FROM test_load_local")
+            self.assertEqual(22749, c.fetchone()[0])
+        finally:
+            c.close()
+            conn.close()
+            conn.connect()
+            c = conn.cursor()
+            c.execute("DROP TABLE test_load_local")
+
     def test_load_warnings(self):
         """Test load local infile produces the appropriate warnings"""
         conn = self.connections[0]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/runtests.py 
new/PyMySQL-0.7.5/runtests.py
--- old/PyMySQL-0.7.2/runtests.py       2015-02-04 18:10:29.000000000 +0100
+++ new/PyMySQL-0.7.5/runtests.py       2016-05-18 11:03:00.000000000 +0200
@@ -10,6 +10,7 @@
 
     @atexit.register
     def report_uncollectable():
+        import gc
         if not gc.garbage:
             print("No garbages!")
             return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/setup.cfg new/PyMySQL-0.7.5/setup.cfg
--- old/PyMySQL-0.7.2/setup.cfg 2016-02-24 11:40:57.000000000 +0100
+++ new/PyMySQL-0.7.5/setup.cfg 2016-06-28 14:18:51.000000000 +0200
@@ -7,7 +7,7 @@
 max-line-length = 119
 
 [egg_info]
-tag_svn_revision = 0
-tag_date = 0
 tag_build = 
+tag_date = 0
+tag_svn_revision = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyMySQL-0.7.2/setup.py new/PyMySQL-0.7.5/setup.py
--- old/PyMySQL-0.7.2/setup.py  2016-02-24 11:39:26.000000000 +0100
+++ new/PyMySQL-0.7.5/setup.py  2016-06-14 10:59:53.000000000 +0200
@@ -20,15 +20,14 @@
     license="MIT",
     packages=find_packages(),
     classifiers=[
+        'Development Status :: 5 - Production/Stable',
         'Programming Language :: Python :: 2',
         'Programming Language :: Python :: 2.7',
         'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.3',
         'Programming Language :: Python :: 3.4',
         'Programming Language :: Python :: 3.5',
         'Programming Language :: Python :: Implementation :: CPython',
         'Programming Language :: Python :: Implementation :: PyPy',
-        'Development Status :: 4 - Beta',
         'Intended Audience :: Developers',
         'License :: OSI Approved :: MIT License',
         'Topic :: Database',


Reply via email to