Bug #71806 Python Connector cannot work with South(because filterwarnings)
Submitted: 23 Feb 2014 5:27 Modified: 8 May 2014 15:08
Reporter: RobberPhex RobberPhex Email Updates:
Status: Closed Impact on me:
Category:Connector / Python Severity:S1 (Critical)
Version:1.1.6 OS:Any
Assigned to: CPU Architecture:Any

[23 Feb 2014 5:27] RobberPhex RobberPhex
In Django 1.6, Python connector 1.1.6, south 0.8.4.
When enable settings.DEBUG, connector will process all warming as error. So, if we use south command 'schemamigration app --initial', We will receive the error 'PendingDeprecationWarning: Options.module_name has been deprecated in favor of model_name'

How to repeat:
create a Django project and app(with model).
add south to project, set DATABASES to mysql connector.
syncdb to MySQL database.

execute command 'schemamigration app --initial' will return:
''PendingDeprecationWarning: Options.module_name has been deprecated in favor of model_name''

Suggested fix:
The Reason:
in 'mysql/connector/django/base.py' line 61, the connector call filterwarnings with default 'append'(False). Then, all warming will be catch here.

The suggestion:
in call of 'mysql/connector/django/base.py', add the parameter 'append=True'
[23 Feb 2014 6:46] RobberPhex RobberPhex
Before you try to repeat, please Add pair 'mysql.connector.django': 'mysql', to variable engine_modules in file south/db/__init__.py .
[26 Feb 2014 13:54] Geert Vanderkelen
We will look into using Connector/Python with South. However, is this a S1 or S2, I think more S2.
Most of the issues right now is to keep 1 code base compatible with multiple Django versions.
[15 Apr 2014 17:25] Vova Krya
Actually the problem does not only have to do with South.
Any Warnings that might be in your codebase are thrown as exceptions because of the above mentioned filter:

mysql.connector.Warning = Warning
if settings.DEBUG:
    warnings.filterwarnings("error", category=mysql.connector.Warning)

Basically by these 3 lines of code you enable all warnings to throw exceptions. E.g any PendingDeprecationWarning, DeprecationWarning, etc.
Please explain why you are doing this.
[18 Apr 2014 21:32] Gary Wilson
As previous comments have indicated, this is not a specific issue with use of South, but rather an issue with the use of filterwarnings.

I assume that the filterwarnings call was just brought over from Django's mysql backend (since the docstring mentions it's heavily based upon Django's mysql backend), which does:

# Raise exceptions for database warnings if DEBUG is on
if settings.DEBUG:
    warnings.filterwarnings("error", category=Database.Warning)

Code snippet from: https://github.com/django/django/blob/master/django/db/backends/mysql/base.py#L51
This filterwarnings code was originally added in: https://github.com/django/django/commit/f9c4ce51235aac4862cfe2dfaaf6836acaea1c3d as part of ticket: https://code.djangoproject.com/ticket/2635

I'm not sure I agree that Django's mysql backend or the mysql.connector.django backend should be adjusting any warning filters, as that can be done via a command-line switch (see: https://docs.python.org/2/using/cmdline.html#cmdoption-W).  However, the difference with mysql.connector.django's use of filterwarnings is that, before the filterwarnings call, mysql.connector.Warning is set to equal Python's Warning class.  Warning is a parent of PendingDeprecationWarning and DeprecationWarning, so this aliasing causes much more than just mysql.connector.Warning instances to be caught and turned into errors.

I see the following options:

1) Remove the filterwarnings code altogether, allowing users to specify warning filters on the command line when desired.

2) Set the filterwarnings action to "default" instead of "error", so that warnings are printed instead of becoming exceptions.  While this would fix the conversion of DeprecationWarnings to exceptions, it doesn't seem right that this library creates such a broad warning filter (caused by the mysql.connector.Warning class aliasing).  Note that according to the Python docs, Python 2.7 and greater now use a default action of "ignore" for DeprecationWarning and its descendants, so setting the action to "default" here would be a nice middle ground.  Even if the action is changed, probably still want to remove the mysql.connector.Warning class aliasing described below in option 3, since I'm not sure the original intent here was to catch all Warning instances, rather just those thrown by this mysql library.

3) Keep the filterwarnings action of "error", but remove the mysql.connector.Warning class aliasing so that it doesn't cause DeprecationWarnings to become exceptions.  See attached diff.
[18 Apr 2014 21:35] Gary Wilson
Patch to only use filterwarnings on mysql.connector.Warning instances instead of all Warning instances.

Attachment: warnings.diff (text/x-patch), 1.40 KiB.

[8 May 2014 15:08] Paul DuBois
Noted in 1.2.2 changelog.

Connector/Python raised all deprecation warnings as errors when
Django was run in debug mode. Now only database warnings are raised
as errors in debug mode.