Skip to content

Commit

Permalink
Rework _getPrograms and _getSortedPrograms utilities
Browse files Browse the repository at this point in the history
Reworks both utilities into a shared decorator.  This allows the handler
type it outputs data in to be dynamically altered by a script, rather
than having to wrap the subsequent Program objects.
  • Loading branch information
wagnerrp committed Jan 1, 2012
1 parent c7bda80 commit bff0380
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 39 deletions.
32 changes: 19 additions & 13 deletions mythtv/bindings/python/MythTV/methodheap.py
Expand Up @@ -57,34 +57,38 @@ class MythBE( FileOps ):
def __del__(self):
self.freeTuner()

def getPendingRecordings(self):
@FileOps._ProgramQuery('QUERY_GETALLPENDING', header_length=1, sorted=True)
def getPendingRecordings(self, pg):
"""
Returns a list of Program objects which are scheduled to be recorded.
"""
return self._getSortedPrograms('QUERY_GETALLPENDING', header=1)
return pg

def getScheduledRecordings(self):
@FileOps._ProgramQuery('QUERY_GETALLSCHEDULED', sorted=True)
def getScheduledRecordings(self, pg):
"""
Returns a list of Program objects which are scheduled to be recorded.
"""
return self._getSortedPrograms('QUERY_GETALLSCHEDULED')
return pg

def getUpcomingRecordings(self):
@FileOps._ProgramQuery('QUERY_GETALLPENDING', header_length=1, sorted=True,
recstatus=Program.rsWillRecord)
def getUpcomingRecordings(self, pg):
"""
Returns a list of Program objects which are scheduled to be recorded.
Sorts the list by recording start time and only returns those with
record status of WillRecord.
"""
return self._getSortedPrograms('QUERY_GETALLPENDING', \
recstatus=Program.rsWillRecord, header=1)
return pg

@FileOps._ProgramQuery('QUERY_GETALLPENDING', header_length=1, sorted=True,
recstatus=Program.rsConflict)
def getConflictedRecordings(self):
"""
Retuns a list of Program objects subject to conflicts in the schedule.
"""
return self._getSortedPrograms('QUERY_GETALLPENDING', \
recstatus=Program.rsConflict, header=1)
return pg

def getRecorderList(self):
"""
Expand Down Expand Up @@ -214,17 +218,19 @@ def isActiveBackend(self, hostname):
else:
return False

def getRecordings(self):
@FileOps._ProgramQuery('QUERY_RECORDINGS Ascending', sorted=True)
def getRecordings(self, pg):
"""
Returns a list of all Program objects which have already recorded
"""
return self._getSortedPrograms('QUERY_RECORDINGS Ascending')
return pg

def getExpiring(self):
@FileOps._ProgramQuery('QUERY_GETEXPIRING', sorted=True)
def getExpiring(self, pg):
"""
Returns a tuple of all Program objects nearing expiration
"""
return self._getSortedPrograms('QUERY_GETEXPIRING')
return pg

def getCheckfile(self,program):
"""
Expand Down
91 changes: 65 additions & 26 deletions mythtv/bindings/python/MythTV/mythproto.py
Expand Up @@ -727,32 +727,71 @@ def allocateEventLock(self, regex):
regex = re.compile(regex)
return EventLock(regex, self.hostname, self.db)

def _getPrograms(self, query, recstatus=None, recordid=None, header=0):
pgfieldcount = len(Program._field_order)
pgrecstatus = Program._field_order.index('recstatus')
pgrecordid = Program._field_order.index('recordid')

res = self.backendCommand(query).split(BACKEND_SEP)
for i in xrange(header):
res.pop(0)
num_progs = int(res.pop(0))
if num_progs*pgfieldcount != len(res):
raise MythBEError(MythBEError.PROTO_PROGRAMINFO)

for i in range(num_progs):
offs = i * pgfieldcount
if recstatus is not None:
if int(res[offs+pgrecstatus]) != recstatus:
continue
if recordid is not None:
if int(res[offs+pgrecordid]) != recordid:
continue
yield Program(res[offs:offs+pgfieldcount], db=self.db)

def _getSortedPrograms(self, query, recstatus=None, \
recordid=None, header=0):
return sorted(self._getPrograms(query, recstatus, recordid, header),\
key=lambda p: p.starttime)
class _ProgramQuery( object ):
def __init__(self, query, header_length=0, sorted=False,
recstatus=None, handler=None):
self.query = query
self.header_length = header_length
self.recstatus = recstatus
self.handler = handler if handler else Program
self.sorted = sorted
self.inst = None
self.func = None

def __call__(self, *args, **kwargs):
if self.func is None:
if len(args) == 1:
self.func = args[0]
elif 'func' in kwargs:
self.func = kwargs['func']
if not callable(self.func):
raise MythError('_ProgramQuery must receive a callable '+\
'before it is functional')
self.__doc__ = self.func.__doc__
self.__name__ = self.func.__name__
self.__module__ = self.func.__module__
return self
elif self.inst is None:
raise MythError('Call to uninitialized _ProgramQuery instance')
if self.sorted:
return self.sortedrun(*args, **kwargs)
return self.run(*args, **kwargs)

def __get__(self, obj, type):
if obj is None:
return self
cls = self.__class__(self.query, self.header_length, self.sorted,
self.recstatus, self.handler)
cls.inst = obj
cls.func = self.func.__get__(obj, type)
return cls

def run(self, *args, **kwargs):
pgfieldcount = len(Program._field_order)
pgrecstatus = Program._field_order.index('recstatus')
pgrecordid = Program._field_order.index('recordid')

res = self.inst.backendCommand(self.query).split(BACKEND_SEP)
for i in xrange(self.header_length):
res.pop(0)
num_progs = int(res.pop(0))
if num_progs*pgfieldcount != len(res):
raise MythBEError(MythBEError.PROTO_PROGRAMINFO)

for i in range(num_progs):
offs = i * pgfieldcount
if self.recstatus is not None:
if int(res[offs+pgrecstatus]) != self.recstatus:
continue
pg = self.handler(res[offs:offs+pgfieldcount],
db=self.inst.db)
pg = self.func(pg, *args, **kwargs)
if pg is not None:
yield pg

def sortedrun(self, *args, **kwargs):
return iter(sorted(self.run(*args, **kwargs),
key=lambda p: p.starttime))

class FreeSpace( DictData ):
"""Represents a FreeSpace entry."""
Expand Down

0 comments on commit bff0380

Please sign in to comment.