Skip to content

Commit 7768ebc

Browse files
committed
Rework comparison operators
This commit reworks the comparison operators used between Guide, Recorded, Program, and Video. The operators fall through a series of stages until they find a common ground that can be used for comparison between the two class types, in the following order: chanid recording start program start inetref season/episode title subtitle
1 parent 4bf6056 commit 7768ebc

File tree

1 file changed

+207
-14
lines changed

1 file changed

+207
-14
lines changed

mythtv/bindings/python/MythTV/utility.py

Lines changed: 207 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -291,26 +291,219 @@ def buildQuery(self, where, select=None, tfrom=None, joinbit=0):
291291
class CMPVideo( object ):
292292
"""
293293
Utility class providing comparison operators between data objects
294-
with 'title' and 'subtitle' attributes.
294+
containing video metadata.
295295
"""
296-
def __cmp__(self, other):
297-
res = cmp(self.title, other.title)
298-
if res:
299-
return res
300-
return cmp(self.subtitle, other.subtitle)
296+
def __le__(self, other): return (self<other) or (self==other)
297+
def __ge__(self, other): return (self>other) or (self==other)
298+
def __ne__(self, other): return not self==other
299+
300+
def __lt__(self, other):
301+
"""
302+
If season and episode are defined for both and inetref matches, use
303+
those. Otherwise, use title and subtitle
304+
"""
305+
try:
306+
# if inetref is not defined, fall through
307+
if (self.inetref not in ('00000000', '0','')) and \
308+
(other.inetref not in ('00000000', '0','')):
309+
if self.inetref != other.inetref:
310+
# series mismatch
311+
return False
312+
if (self.season != 0) or (self.episode != 0):
313+
# if season and episode are not defined, fall through
314+
if self.season > other.season:
315+
return False
316+
if self.season < other.season:
317+
return True
318+
if self.episode < other.episode:
319+
return True
320+
return False
321+
except AttributeError:
322+
# inetref, season, and episode number are not supported for
323+
# one or the other object. fall through to title/subtitle
324+
pass
325+
326+
try:
327+
if self.title < other.title:
328+
return True
329+
if self.title > other.title:
330+
return False
331+
if self.subtitle < other.subtitle:
332+
return True
333+
return False
334+
except AttributeError:
335+
# objects cannot be compared, return as such
336+
return NotImplemented
337+
338+
def __eq__(self, other):
339+
"""
340+
If inetref is defined, following through to season and episode, use
341+
those. Otherwise, fall back to title and subtitle.
342+
"""
343+
try:
344+
# if inetref is not defined, fall through
345+
if (self.inetref not in ('00000000', '0','')) and \
346+
(other.inetref not in ('00000000', '0','')):
347+
if (self.inetref == other.inetref) and \
348+
(self.season == other.season) and \
349+
(self.episode == other.episode):
350+
return True
351+
return False
352+
except AttributeError:
353+
# inetref, season, and episode number are not supported for
354+
# one or the other object. fall through to title/subtitle
355+
pass
356+
357+
try:
358+
if (self.title == other.title) and \
359+
(self.subtitle == other.subtitle):
360+
return True
361+
return False
362+
except AttributeError:
363+
# objects cannot be compared, return as such
364+
return NotImplemented
365+
366+
def __gt__(self, other):
367+
"""
368+
If season and episode are defined for both and inetref matches, use
369+
those. Otherwise, use title and subtitle
370+
"""
371+
try:
372+
# if inetref is not defined, fall through
373+
if (self.inetref not in ('00000000', '0','')) and \
374+
(other.inetref not in ('00000000', '0','')):
375+
if self.inetref != other.inetref:
376+
# series mismatch
377+
return False
378+
if (self.season != 0) or (self.episode != 0):
379+
# if season and episode are not defined, fall through
380+
if self.season < other.season:
381+
return False
382+
if self.season > other.season:
383+
return True
384+
if self.episode > other.episode:
385+
return True
386+
return False
387+
except AttributeError:
388+
# inetref, season, and episode number are not supported for
389+
# one or the other object. fall through to title/subtitle
390+
pass
391+
392+
try:
393+
if self.title > other.title:
394+
return True
395+
if self.title < other.title:
396+
return False
397+
if self.subtitle > other.subtitle:
398+
return True
399+
return False
400+
except AttributeError:
401+
# objects cannot be compared, return as such
402+
return NotImplemented
301403

302404
class CMPRecord( CMPVideo ):
303405
"""
304406
Utility class providing comparison operators between data objects
305-
with 'chanid' and 'starttime', falling back to 'title' and 'subtitle'.
407+
containing video metadata.
306408
"""
307-
def __cmp__(self, other):
308-
if ('starttime' not in other) or ('chanid' not in other):
309-
return CMPVideo.__cmd__(self, other)
310-
res = cmp(self.starttime, other.starttime)
311-
if res:
312-
return res
313-
return cmp(self.chanid, other.chanid)
409+
@staticmethod
410+
def __get_rec_start(obj):
411+
# find the start of the recording, or return an attribute error
412+
if hasattr(obj, 'recstartts'):
413+
return obj.recstartts
414+
if hasattr(obj, 'progstart'):
415+
return obj.starttime
416+
raise AttributeError
417+
418+
@staticmethod
419+
def __get_prog_start(obj):
420+
# find the start of the program
421+
if hasattr(obj, 'progstart'):
422+
return obj.progstart
423+
return obj.starttime
424+
425+
def __lt__(self, other):
426+
# test for chanid first
427+
try:
428+
if self.chanid > other.chanid:
429+
return False
430+
if self.chanid < other.chanid:
431+
return True
432+
except AttributeError:
433+
# either object is not a recording-related object
434+
# fall through to video matching
435+
return super(CMPRecord, self).__lt__(other)
436+
437+
try:
438+
# try matching on recording start
439+
if self.__get_rec_start(self) < self.__get_rec_start(other):
440+
return True
441+
return False
442+
except AttributeError:
443+
pass
444+
445+
try:
446+
# try matching on program start
447+
if self.__get_prog_start(self) < self.__get_prog_start(other):
448+
return True
449+
return False
450+
except AttributeError:
451+
return super(CMPRecord, self).__lt__(other)
452+
453+
def __eq__(self, other):
454+
# test for chanid first
455+
try:
456+
if self.chanid != other.chanid:
457+
return False
458+
except AttributeError:
459+
# either object is not a recording-related object
460+
# fall through to video matching
461+
return super(CMPRecord, self).__eq__(other)
462+
463+
try:
464+
# try matching on recording start
465+
if self.__get_rec_start(self) == self.__get_rec_start(other):
466+
return True
467+
return False
468+
except AttributeError:
469+
pass
470+
471+
try:
472+
# try matching on program start
473+
if self.__get_prog_start(self) == self.__get_prog_start(other):
474+
return True
475+
return False
476+
except AttributeError:
477+
return super(CMPRecord, self).__eq__(other)
478+
479+
480+
def __gt__(self, other):
481+
# test for chanid first
482+
try:
483+
if self.chanid < other.chanid:
484+
return False
485+
if self.chanid > other.chanid:
486+
return True
487+
except AttributeError:
488+
# either object is not a recording-related object
489+
# fall through to video matching
490+
return super(CMPRecord, self).__gt__(other)
491+
492+
try:
493+
# try matching on recording start
494+
if self.__get_rec_start(self) > self.__get_rec_start(other):
495+
return True
496+
return False
497+
except AttributeError:
498+
pass
499+
500+
try:
501+
# try matching on program start
502+
if self.__get_prog_start(self) > self.__get_prog_start(other):
503+
return True
504+
return False
505+
except AttributeError:
506+
return super(CMPRecord, self).__gt__(other)
314507

315508
class deadlinesocket( socket.socket ):
316509
"""

0 commit comments

Comments
 (0)