From 8ad1525c3f11ac299cdf94e9a6b7f6244d37ee7f Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Fri, 14 Dec 2018 16:46:30 +0900 Subject: [PATCH] Raise ProgrammingError for nan and inf (#314) * Raise ProgrammingError when inf or nan is passed Fixes #246 * Rename _mysql_exceptions -> _exceptions --- MySQLdb/{_mysql_exceptions.py => _exceptions.py} | 10 +++------- MySQLdb/_mysql.c | 2 +- MySQLdb/compat.py | 2 ++ MySQLdb/connections.py | 2 +- MySQLdb/converters.py | 3 +++ MySQLdb/cursors.py | 4 ++-- doc/{_mysql_exceptions.rst => _exceptions.rst} | 4 ++-- doc/_mysql.rst | 2 +- doc/user_guide.rst | 8 ++++---- metadata.cfg | 2 +- 10 files changed, 20 insertions(+), 19 deletions(-) rename MySQLdb/{_mysql_exceptions.py => _exceptions.py} (91%) rename doc/{_mysql_exceptions.rst => _exceptions.rst} (58%) diff --git a/MySQLdb/_mysql_exceptions.py b/MySQLdb/_exceptions.py similarity index 91% rename from MySQLdb/_mysql_exceptions.py rename to MySQLdb/_exceptions.py index 99a79d7..0f14f3b 100644 --- a/MySQLdb/_mysql_exceptions.py +++ b/MySQLdb/_exceptions.py @@ -1,15 +1,10 @@ -"""_mysql_exceptions: Exception classes for _mysql and MySQLdb. +"""Exception classes for _mysql and MySQLdb. These classes are dictated by the DB API v2.0: https://www.python.org/dev/peps/pep-0249/ """ - -try: - from exceptions import Exception, StandardError, Warning -except ImportError: - # Python 3 - StandardError = Exception +from .compat import StandardError class MySQLError(StandardError): @@ -20,6 +15,7 @@ class Warning(Warning, MySQLError): """Exception raised for important warnings like data truncations while inserting, etc.""" + class Error(MySQLError): """Exception that is the base class of all other error exceptions (not Warning).""" diff --git a/MySQLdb/_mysql.c b/MySQLdb/_mysql.c index 1f1b299..5ae6652 100644 --- a/MySQLdb/_mysql.c +++ b/MySQLdb/_mysql.c @@ -2669,7 +2669,7 @@ init_mysql(void) (PyObject *)&_mysql_ResultObject_Type)) goto error; Py_INCREF(&_mysql_ResultObject_Type); - if (!(emod = PyImport_ImportModule("MySQLdb._mysql_exceptions"))) { + if (!(emod = PyImport_ImportModule("MySQLdb._exceptions"))) { PyErr_Print(); goto error; } diff --git a/MySQLdb/compat.py b/MySQLdb/compat.py index 8fe6709..f8d98ac 100644 --- a/MySQLdb/compat.py +++ b/MySQLdb/compat.py @@ -5,8 +5,10 @@ if sys.version_info[0] == 2: unicode = unicode unichr = unichr long = long + StandardError = StandardError else: PY2 = False unicode = str unichr = chr long = int + StandardError = Exception diff --git a/MySQLdb/connections.py b/MySQLdb/connections.py index 7de8c8c..c7c4c14 100644 --- a/MySQLdb/connections.py +++ b/MySQLdb/connections.py @@ -9,7 +9,7 @@ import sys from MySQLdb import cursors, _mysql from MySQLdb.compat import unicode, PY2 -from MySQLdb._mysql_exceptions import ( +from MySQLdb._exceptions import ( Warning, Error, InterfaceError, DataError, DatabaseError, OperationalError, IntegrityError, InternalError, NotSupportedError, ProgrammingError, diff --git a/MySQLdb/converters.py b/MySQLdb/converters.py index 9b9cb8b..4c4a1a1 100644 --- a/MySQLdb/converters.py +++ b/MySQLdb/converters.py @@ -36,6 +36,7 @@ from MySQLdb._mysql import string_literal, escape from MySQLdb.constants import FIELD_TYPE, FLAG from MySQLdb.times import * from MySQLdb.compat import PY2, long, unicode +from MySQLdb._exceptions import ProgrammingError NoneType = type(None) @@ -66,6 +67,8 @@ def Unicode2Str(s, d): def Float2Str(o, d): s = repr(o) + if s in ('inf', 'nan'): + raise ProgrammingError("%s can not be used with MySQL" % s) if 'e' not in s: s += 'e0' return s diff --git a/MySQLdb/cursors.py b/MySQLdb/cursors.py index 9a5e76f..b8c0d88 100644 --- a/MySQLdb/cursors.py +++ b/MySQLdb/cursors.py @@ -9,7 +9,7 @@ import re import sys from .compat import unicode -from ._mysql_exceptions import ( +from ._exceptions import ( Warning, Error, InterfaceError, DataError, DatabaseError, OperationalError, IntegrityError, InternalError, NotSupportedError, ProgrammingError) @@ -48,7 +48,7 @@ class BaseCursor(object): #: Default value of max_allowed_packet is 1048576. max_stmt_length = 64*1024 - from ._mysql_exceptions import ( + from ._exceptions import ( MySQLError, Warning, Error, InterfaceError, DatabaseError, DataError, OperationalError, IntegrityError, InternalError, ProgrammingError, NotSupportedError, diff --git a/doc/_mysql_exceptions.rst b/doc/_exceptions.rst similarity index 58% rename from doc/_mysql_exceptions.rst rename to doc/_exceptions.rst index 2d43525..b509338 100644 --- a/doc/_mysql_exceptions.rst +++ b/doc/_exceptions.rst @@ -1,7 +1,7 @@ -_mysql_exceptions Module +_exceptions Module ======================== -.. automodule:: _mysql_exceptions +.. automodule:: MySQLdb._exceptions :members: :undoc-members: :show-inheritance: diff --git a/doc/_mysql.rst b/doc/_mysql.rst index 7ac4918..cf464b4 100644 --- a/doc/_mysql.rst +++ b/doc/_mysql.rst @@ -1,7 +1,7 @@ _mysql Module ============= -.. automodule:: _mysql +.. automodule:: MySQLdb._mysql :members: :undoc-members: :show-inheritance: diff --git a/doc/user_guide.rst b/doc/user_guide.rst index 173918d..7c4302b 100644 --- a/doc/user_guide.rst +++ b/doc/user_guide.rst @@ -106,7 +106,7 @@ Okay, so you want to use ``_mysql`` anyway. Here are some examples. The simplest possible database connection is:: - import _mysql + from MySQLdb import _mysql db=_mysql.connect() This creates a connection to the MySQL server running on the local @@ -162,8 +162,8 @@ substitution, so you have to pass a complete query string to WHERE price < 5""") There's no return value from this, but exceptions can be raised. The -exceptions are defined in a separate module, ``_mysql_exceptions``, -but ``_mysql`` exports them. Read DB API specification PEP-249_ to +exceptions are defined in a separate module, ``MySQLdb._exceptions``, +but ``MySQLdb._mysql`` exports them. Read DB API specification PEP-249_ to find out what they are, or you can use the catch-all ``MySQLError``. .. _PEP-249: https://www.python.org/dev/peps/pep-0249/ @@ -213,7 +213,7 @@ implicitly asked for one row, since we didn't specify ``maxrows``. The other oddity is: Assuming these are numeric columns, why are they returned as strings? Because MySQL returns all data as strings and expects you to convert it yourself. This would be a real pain in the -ass, but in fact, ``_mysql`` can do this for you. (And ``MySQLdb`` +ass, but in fact, ``MySQLdb._mysql`` can do this for you. (And ``MySQLdb`` does do this for you.) To have automatic type conversion done, you need to create a type converter dictionary, and pass this to ``connect()`` as the ``conv`` keyword parameter. diff --git a/metadata.cfg b/metadata.cfg index 589e52f..8d185a8 100644 --- a/metadata.cfg +++ b/metadata.cfg @@ -28,7 +28,7 @@ classifiers: Topic :: Database Topic :: Database :: Database Engines/Servers py_modules: - MySQLdb._mysql_exceptions + MySQLdb._exceptions MySQLdb.compat MySQLdb.connections MySQLdb.converters