Skip to content

Commit

Permalink
ttvdb: Update to support new JSON API.
Browse files Browse the repository at this point in the history
The old xml ttvdb api will be terminated on September 30th 2017.

Consolidated from multiple commits.

Fixes #13084

* Update ttdvb to use V2 API
* Update python to 2/3 compatability
* Update tvdb_api with upstream 2.0-dev
* Fix some incorrect exception formatting in ttvdb.py

* Upstream support for partial language data
* Upstream handle loadurl errors by callers
* Upstream support no cache and non-conforming cache
* Upstream tolerate missing cache _ignored_parameters attribute
* Remove username and userkey from auth info, not required, less brittle
* python 3.6 support for num-seasons output order

* ttvdb fix output of more commands
* -l de -m -a US -D 72449 1 10
* -l en -a US -D 281053

* Handle empty cast
* ttvdb: Add more detailed episode data
* ttvdb.py Handle no actors in returned data
* ttvdb: add old requests_cache version compatability
* ttvdb Fix User-Agent to a specific one, fixes auth 403
* ttvdb Restore original api key
* ttvdb Fix up python3 compatability
* ttvdb fix all error outputs to stderr
* ttvdb: make doctest a bit less brittle with changing data

Signed-off-by: Peter Bennett <pbennett@mythtv.org>
  • Loading branch information
Mark Spieth authored and bennettpeter committed Aug 26, 2017
1 parent deeed3c commit e60c028
Show file tree
Hide file tree
Showing 30 changed files with 2,637 additions and 1,273 deletions.
22 changes: 11 additions & 11 deletions mythtv/bindings/python/MythTV/__init__.py
Expand Up @@ -29,17 +29,17 @@
+__all_data__\
+__all_method__

import static
from exceptions import *
from logging import *
from msearch import *
from utility import *
from connections import dbmodule
from database import *
from system import *
from mythproto import *
from dataheap import *
from methodheap import *
from . import static
from .exceptions import *
from .logging import *
from .msearch import *
from .utility import *
from .connections import dbmodule
from .database import *
from .system import *
from .mythproto import *
from .dataheap import *
from .methodheap import *


__version__ = OWN_VERSION
Expand Down
6 changes: 3 additions & 3 deletions mythtv/bindings/python/MythTV/_conn_mysqldb.py
Expand Up @@ -44,7 +44,7 @@ def _ping122(self): self._get_db().ping()
def _sanitize(self, query): return query.replace('?', '%s')

def log_query(self, query, args):
self.log(self.log.DATABASE, MythLog.DEBUG,
self.log(self.log.DATABASE, MythLog.DEBUG,
' '.join(query.split()), str(args))

def execute(self, query, args=None):
Expand All @@ -67,7 +67,7 @@ def execute(self, query, args=None):
if args is None:
return super(LoggedCursor, self).execute(query)
return super(LoggedCursor, self).execute(query, args)
except Exception, e:
except Exception as e:
raise MythDBError(MythDBError.DB_RAW, e.args)

def executemany(self, query, args):
Expand All @@ -92,7 +92,7 @@ def executemany(self, query, args):
self.log_query(query, args)
try:
return super(LoggedCursor, self).executemany(query, args)
except Exception, e:
except Exception as e:
raise MythDBError(MythDBError.DB_RAW, e.args)

def commit(self): self._get_db().commit()
Expand Down
4 changes: 2 additions & 2 deletions mythtv/bindings/python/MythTV/_conn_oursql.py
Expand Up @@ -54,7 +54,7 @@ def execute(self, query, args=None):
if args:
return super(LoggedCursor, self).execute(query, args)
return super(LoggedCursor, self).execute(query)
except Exception, e:
except Exception as e:
raise MythDBError(MythDBError.DB_RAW, e.args)

def executemany(self, query, args):
Expand All @@ -74,7 +74,7 @@ def executemany(self, query, args):
self.log_query(query, args)
try:
return super(LoggedCursor, self).executemany(query, args)
except Exception, e:
except Exception as e:
raise MythDBError(MythDBError.DB_RAW, e.args)

def commit(self): self.connection.commit()
Expand Down
9 changes: 5 additions & 4 deletions mythtv/bindings/python/MythTV/altdict.py
Expand Up @@ -4,7 +4,8 @@
from MythTV.exceptions import MythError
from MythTV.utility import datetime

from itertools import imap, izip
from builtins import map as imap
from builtins import zip as izip
from datetime import date
import locale

Expand Down Expand Up @@ -182,7 +183,7 @@ def _fillNone(self):
field_order = self._field_order
dict.update(self, zip(field_order, [None]*len(field_order)))

def copy(self):
def copy(self):
"""Returns a deep copy of itself."""
return self.__class__(zip(self.iteritems()), _process=False)

Expand All @@ -192,7 +193,7 @@ def __getstate__(self):
def __setstate__(self, state):
for k,v in state.iteritems():
self[k] = v


class DictInvert(dict):
"""
Expand All @@ -204,7 +205,7 @@ class DictInvert(dict):
def __init__(self, other, mine=None):
self.other = other
if mine is None:
mine = dict(zip(*reversed(zip(*other.items()))))
mine = dict(zip(*reversed(list(zip(*other.items())))))
dict.__init__(self, mine)

@classmethod
Expand Down
48 changes: 29 additions & 19 deletions mythtv/bindings/python/MythTV/connections.py
Expand Up @@ -10,22 +10,32 @@

from time import sleep, time
from select import select
from thread import start_new_thread, allocate_lock, get_ident
try:
from thread import start_new_thread, allocate_lock, get_ident
except ImportError:
from _thread import start_new_thread, allocate_lock, get_ident
import lxml.etree as etree
import weakref
import urllib2
try:
import urllib2
except ImportError:
import urllib.request as urllib2
import socket
import Queue
try:
import Queue
except ImportError:
import queue as Queue
import json
import re
from builtins import str

try:
import _conn_oursql as dbmodule
from _conn_oursql import LoggedCursor
from . import _conn_oursql as dbmodule
from ._conn_oursql import LoggedCursor
except:
try:
import _conn_mysqldb as dbmodule
from _conn_mysqldb import LoggedCursor
from . import _conn_mysqldb as dbmodule
from ._conn_mysqldb import LoggedCursor
except:
raise MythError("No viable database module found.")

Expand Down Expand Up @@ -198,7 +208,7 @@ def __init__(self, backend, port, localname=None,

try:
self.connect()
except socket.error, e:
except socket.error as e:
self.log.logTB(MythLog.SOCKET)
self.connected = False
self.log(MythLog.GENERAL, MythLog.CRIT,
Expand Down Expand Up @@ -273,7 +283,7 @@ def backendCommand(self, data, deadline=None):
obj.backendCommand(data=None, timeout=None) -> response string
Sends a formatted command via a socket to the mythbackend. 'timeout'
will override the default timeout given when the object was
will override the default timeout given when the object was
created. If 'data' is None, the method will return any events
in the receive buffer.
"""
Expand Down Expand Up @@ -303,12 +313,12 @@ def backendCommand(self, data, deadline=None):

# convert to unicode
try:
res = unicode(''.join([res]), 'utf8')
res = str(''.join([res]), 'utf8')
except:
res = u''.join([res])

return res
except MythError, e:
except MythError as e:
if e.sockcode == 54:
# remote has closed connection, attempt reconnect
self.reconnect(True)
Expand Down Expand Up @@ -342,7 +352,7 @@ def __init__(self, backend, port, localname=None, deadline=10.0, level=2):
self.threadrunning = False
self.eventqueue = Queue.Queue()

super(BEEventConnection, self).__init__(backend, port, localname,
super(BEEventConnection, self).__init__(backend, port, localname,
False, deadline)

def connect(self):
Expand Down Expand Up @@ -386,22 +396,22 @@ def queueEvents(self):
event = self.socket.recvheader(deadline=0.0)

try:
event = unicode(''.join([event]), 'utf8')
event = str(''.join([event]), 'utf8')
except:
event = u''.join([event])

if event[:15] == 'BACKEND_MESSAGE':
self.eventqueue.put(event)
# else discard

except MythError, e:
except MythError as e:
if e.sockcode == 54:
# remote has closed connection, attempt reconnect
self.reconnect(True, True)
return self.backendCommand(data, deadline)
return self.backendCommand(event, self.socket.getdeadline())
else:
raise

def registeruser(self, uuid, opts):
self._regusers[uuid] = opts

Expand Down Expand Up @@ -482,7 +492,7 @@ def testList(cls, felist):
try:
t = time()
fe._test(t + 2.0)
except MythError, e:
except MythError as e:
continue
yield fe

Expand Down Expand Up @@ -582,7 +592,7 @@ def readJSON(self):

def __repr__(self):
return "<%s 'http://%s:%d/' at %s>" % \
(str(self.__class__).split("'")[1].split(".")[-1],
(str(self.__class__).split("'")[1].split(".")[-1],
self.host, self.port, hex(id(self)))

def __init__(self, host, port):
Expand All @@ -605,7 +615,7 @@ def _request(self, path='', **keyvars):
'keyvars' are a series of optional variables to specify on the URL.
The request object supports open() and read(), as well as supports
editing of HTTP headers and POST data.
editing of HTTP headers and POST data.
"""
url = 'http://{0.host}:{0.port}/{1}'.format(self, path)
if keyvars:
Expand Down
17 changes: 8 additions & 9 deletions mythtv/bindings/python/MythTV/database.py
Expand Up @@ -8,7 +8,7 @@
from MythTV.altdict import OrdDict, DictData
from MythTV.logging import MythLog
from MythTV.msearch import MSearch
from MythTV.utility import datetime, _donothing, QuickProperty
from MythTV.utility import datetime, dt, _donothing, QuickProperty
from MythTV.exceptions import MythError, MythDBError, MythTZError
from MythTV.connections import DBConnection, LoggedCursor, XMLConnection

Expand All @@ -19,6 +19,7 @@
import time as _pyt
import weakref
import os
from builtins import int, str


class DBData( DictData, MythSchema ):
Expand Down Expand Up @@ -118,7 +119,7 @@ def _fromQuery(cls, where, args, db=None):
for row in cursor:
try:
yield cls.fromRaw(row, db)
except MythDBError, e:
except MythDBError as e:
if e.ecode == MythError.DB_RESTRICT:
pass

Expand Down Expand Up @@ -507,7 +508,7 @@ def __xor__(self, other):
if dat not in self:
data.append(dat)
return self.fromCopy(data, self._db)

def __and__(self, other):
data = []
for dat in self:
Expand Down Expand Up @@ -566,7 +567,7 @@ def fromRaw(cls, data, db=None):
c = cls('', db=db, bypass=True)
c._populated = True
for dat in data:
list.append(c, c.SubData(zip(self._datfields, row)))
list.append(c, c.SubData(zip(cls._datfields, dat)))
return c

@classmethod
Expand Down Expand Up @@ -1147,7 +1148,7 @@ def __getitem__(self,key):
# pull field list from database
try:
cursor.execute("DESC %s" % (key,))
except Exception, e:
except Exception as e:
raise MythDBError(MythDBError.DB_RAW, e.args)
self[key] = self._FieldData(cursor.fetchall())

Expand Down Expand Up @@ -1280,7 +1281,7 @@ def __init__(self, db=None, args=None, **dbconn):

# apply the rest of object init if not already done
self._testconfig(self.dbconfig)

def _testconfig(self, dbconfig):
self.dbconfig = dbconfig
if dbconfig in self.shared:
Expand Down Expand Up @@ -1393,9 +1394,7 @@ def literal(self, query, args=None):
"""
conv = {int: str,
str: lambda x: '"%s"'%x,
long: str,
float: str,
unicode: lambda x: '"%s"'%x,
bool: str,
type(None): lambda x: 'NULL',
_pydt.datetime: lambda x: x.strftime('"%Y-%m-%d %H:%M:%S"'),
Expand All @@ -1407,7 +1406,7 @@ def literal(self, query, args=None):
x.seconds%60),
_pyt.struct_time: lambda x: _pyt.\
strftime('"%Y-%m-%d %H:%M:%S"',x)}

if args is None:
return query

Expand Down

0 comments on commit e60c028

Please sign in to comment.