Opened 4 years ago

Closed 4 years ago

#13502 closed Patch - Feature (Won't Fix)

Support python-PyMySQL as alternative MySQL connector for python bindings

Reported by: Gary Buhrmaster Owned by: Bill Meek
Priority: minor Milestone: 31.0
Component: Bindings - Python Version: Master Head
Severity: medium Keywords:
Cc: Ticket locked: no

Description

Support python-PyMySQL as an alternative implementation for the MythTV python database connector.

The pure python PyMySQL implementation is (asserted to be) functionally equivalent to the MySQLdb implementation for high level calls, and has advantages for installation on certain platforms and distributions where building support modules with C dependencies can be more complicated.

The particular motivator for this patch in this case, is that the maintainer for the python-mysql connector has indicated they do not have the resources to build python-mysql for EPEL8 at this time, so are recommending using this pure python implementation.

Only lightly tested.

Note: This patch hits an area that is also touched by the python3 patches, so depending on which patch set gets applied first there will likely be patch failures due to the diff context overlap, and some minor adjustment(s) may be needed, but as the code itself is quite contained, it should be a trivial conflict fix for the committer if the patch is accepted.

Thank you for your consideration.

Proposed patch:

diff --git a/mythtv/bindings/python/MythTV/_conn_mysqldb.py b/mythtv/bindings/python/MythTV/_conn_mysqldb.py
index 676d147a62..38fcf98d04 100644
--- a/mythtv/bindings/python/MythTV/_conn_mysqldb.py
+++ b/mythtv/bindings/python/MythTV/_conn_mysqldb.py
@@ -5,6 +5,11 @@ from weakref import ref
 
 import sys
 import warnings
+try:
+    import pymysql
+    pymysql.install_as_MySQLdb()
+except ImportError:
+    pass
 with warnings.catch_warnings():
     warnings.simplefilter('ignore')
     import MySQLdb, MySQLdb.cursors
diff --git a/mythtv/configure b/mythtv/configure
index b9de822bc3..f257963255 100755
--- a/mythtv/configure
+++ b/mythtv/configure
@@ -6989,7 +6989,7 @@ fi
 if enabled bindings_python; then
     is_python3                 && python=python2
     check_python               || disable_bindings_python "Python 2.6"
-    check_py_lib MySQLdb       || disable_bindings_python "MySQLdb"
+    check_py_lib pymysql       || { check_py_lib MySQLdb || disable_bindings_python "MySQLdb" ; }
     check_py_lib lxml          || disable_bindings_python "lxml"
     check_py_lib urlgrabber    || disable_bindings_python "urlgrabber"
 fi

Change History (7)

comment:1 Changed 4 years ago by Stuart Auchterlonie

Milestone: needs_triage31.0
Owner: changed from Raymond Wagner to Bill Meek
Status: newassigned

comment:2 Changed 4 years ago by Bill Meek

Status: assignedaccepted

comment:3 Changed 4 years ago by Bill Meek

Update: just simple tests like

import MythTV
help(MythTV)

Works fine on my Fedora 31 box, but fails on Ubuntu 18.04. On 19.04 it works, but one of my tools fails. Ubuntu tests were on python 3.6 and 3.7. The "asserted to be" comment above may be important. For now, I could add a Python version test and only do this with 3.something.

comment:4 in reply to:  3 Changed 4 years ago by Gary Buhrmaster

.... fails on Ubuntu 18.04. On 19.04 it works ...

My recollection is 18.04LTS ships an older version of the library.

comment:5 Changed 4 years ago by rcrdnalor

Looking at the MythTV wiki, the proposed call to get a 'Recorded' instance through the python bindings is

rec = Recorded((chanid,starttime), db = MythDB())

I have proplems running my test cases against PyMySQL as proposed by the attached patch : Latest installed via pip3: https://pypi.org/project/PyMySQL/

Python 3.7.5 (default, Nov  7 2019, 10:50:52) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pymysql
>>> pymysql.__version__
'0.9.3'

Running a simple code as recommended in MythTV wiki with the patch applied:

$ python
Python 3.7.5 (default, Nov  7 2019, 10:50:52) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from MythTV import MythDB, Recorded
>>> db = MythDB()
>>> rec = Recorded((3030, 20190305135100),db=db)
Traceback (most recent call last):
......
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/local-admin/MythTV/MythTV_python/MythTV/dataheap.py", line 344, in __init__
    DBDataWrite.__init__(self, data, db)
  File "/home/local-admin/MythTV/MythTV_python/MythTV/database.py", line 318, in __init__
    DBData.__init__(self, data, db)
  File "/home/local-admin/MythTV/MythTV_python/MythTV/database.py", line 180, in __init__
    self._pull()
  File "/home/local-admin/MythTV/MythTV_python/MythTV/database.py", line 388, in _pull
    DBData._pull(self)
  File "/home/local-admin/MythTV/MythTV_python/MythTV/database.py", line 201, in _pull
    % (self._table, self._where), self._getwheredat())
  File "/home/local-admin/MythTV/MythTV_python/MythTV/_conn_mysqldb.py", line 90, in execute
    raise MythDBError(MythDBError.DB_RAW, e.args)
AttributeError: 'datetime' object has no attribute 'translate'

Running the same code as mentioned above with python3-mysqldb ( source from https://pypi.org/project/mysqlclient/ ) gives the following result as expected:

$ python
Python 3.7.5 (default, Nov  7 2019, 10:50:52) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from MythTV import MythDB, Recorded
>>> db = MythDB()
>>> rec = Recorded((3030, 20190305135100),db=db)
>>> rec
<Recorded 'Die Lady von Shanghai','2019-03-05 13:51:00+01:00' at 0x7fa7b93b44d0>
>>> 

Conclusion: The patch from this ticket prefers PyMySQL over MySQLDB. Expect major troubles from users of the MythTV python bindings once this patch gets applied.

comment:6 Changed 4 years ago by Gary Buhrmaster

Looks like an excellent reason to close this ticket WONTFIX.

It turns out that there is a reported issue for this case within the module where the root cause is actually poor database invocation cleanliness, but changing the module, or cleaning up the bindings themselves, would be a larger developer task for some future time.

comment:7 Changed 4 years ago by Bill Meek

Resolution: Won't Fix
Status: acceptedclosed

In Ubuntu 19.04, the python2 version fails but the python3 one works. Both are pymysql.version 0.9.3. In 18.04 it also fails, the version is 0.8.0.

Don't see a way to import based on version only (plus any user could choose install the package for other reasons even if ansible only included it for EPEL8.)

Note: See TracTickets for help on using tickets.