Index: MythData.py =================================================================== --- MythData.py (revision 24213) +++ MythData.py (working copy) @@ -318,7 +318,7 @@ if res[0] == 'ERROR': return None else: - return Program(res[1:], db=self.db) + return Program(res[1:], db=self._db) def deleteRecording(self, program, force=False): """ @@ -400,38 +400,38 @@ INACTIVE = 10 NEVERRECORD = 11 - field_order = [ 'title', 'subtitle', 'description', - 'category', 'chanid', 'channum', - 'callsign', 'channame', 'filename', - 'fs_high', 'fs_low', 'starttime', - 'endtime', 'duplicate', 'shareable', - 'findid', 'hostname', 'sourceid', - 'cardid', 'inputid', 'recpriority', - 'recstatus', 'recordid', 'rectype', - 'dupin', 'dupmethod', 'recstartts', - 'recendts', 'repeat', 'programflags', - 'recgroup', 'commfree', 'outputfilters', - 'seriesid', 'programid', 'lastmodified', - 'stars', 'airdate', 'hasairdate', - 'playgroup', 'recpriority2', 'parentid', - 'storagegroup', 'audio_props', 'video_props', - 'subtitle_type','year'] - field_type = [ 3, 3, 3, - 3, 0, 3, - 3, 3, 3, - 0, 0, 4, - 4, 0, 0, - 0, 3, 0, - 0, 0, 0, - 0, 0, 3, - 0, 0, 4, - 4, 0, 3, - 3, 0, 3, - 3, 3, 3, - 1, 3, 0, - 3, 0, 3, - 3, 0, 0, - 0, 0] + _field_order = [ 'title', 'subtitle', 'description', + 'category', 'chanid', 'channum', + 'callsign', 'channame', 'filename', + 'fs_high', 'fs_low', 'starttime', + 'endtime', 'duplicate', 'shareable', + 'findid', 'hostname', 'sourceid', + 'cardid', 'inputid', 'recpriority', + 'recstatus', 'recordid', 'rectype', + 'dupin', 'dupmethod', 'recstartts', + 'recendts', 'repeat', 'programflags', + 'recgroup', 'commfree', 'outputfilters', + 'seriesid', 'programid', 'lastmodified', + 'stars', 'airdate', 'hasairdate', + 'playgroup', 'recpriority2', 'parentid', + 'storagegroup', 'audio_props', 'video_props', + 'subtitle_type','year'] + _field_type = [ 3, 3, 3, + 3, 0, 3, + 3, 3, 3, + 0, 0, 4, + 4, 0, 0, + 0, 3, 0, + 0, 0, 0, + 0, 0, 3, + 0, 0, 4, + 4, 0, 3, + 3, 0, 3, + 3, 3, 3, + 1, 3, 0, + 3, 0, 3, + 3, 0, 0, + 0, 0] def __str__(self): return u"" % (self.title, self.starttime.strftime('%Y-%m-%d %H:%M:%S'), hex(id(self))) @@ -468,15 +468,15 @@ raw = [] defs = (0,0,0,'',0) - for i in range(len(self.field_order)): - if self.field_order[i] in dat: - raw.append(dat[self.field_order[i]]) + for i in range(len(self._field_order)): + if self._field_order[i] in dat: + raw.append(dat[self._field_order[i]]) else: - raw.append(defs[self.field_type[i]]) + raw.append(defs[self._field_type[i]]) DictData.__init__(self, raw) else: raise InputError("Either 'raw' or 'etree' must be provided") - self.db = MythDBBase(db) + self._db = MythDBBase(db) self.filesize = self.joinInt(self.fs_high,self.fs_low) def toString(self): @@ -484,23 +484,7 @@ Program.toString() -> string representation for use with backend protocol commands """ - data = [] - for i in range(0,PROGRAM_FIELDS): - if self.data[self.field_order[i]] == None: - datum = '' - elif self.field_type[i] == 0: - datum = str(self.data[self.field_order[i]]) - elif self.field_type[i] == 1: - datum = locale.format("%0.6f", self.data[self.field_order[i]]) - elif self.field_type[i] == 2: - datum = str(int(self.data[self.field_order[i]])) - elif self.field_type[i] == 3: - datum = self.data[self.field_order[i]] - elif self.field_type[i] == 4: - datum = str(int(mktime(self.data[self.field_order[i]].\ - timetuple()))) - data.append(datum) - return BACKEND_SEP.join(data) + return BACKEND_SEP.join(self._deprocess) def delete(self, force=False, rerecord=False): """ @@ -509,7 +493,7 @@ 'force' forces a delete if the file cannot be found. 'rerecord' sets the file as recordable in oldrecorded """ - be = FileOps(db=self.db) + be = FileOps(db=self._db) res = int(be.deleteRecording(self, force=force)) if res < -1: raise MythBEError('Failed to delete file') @@ -519,7 +503,7 @@ def getRecorded(self): """Program.getRecorded() -> Recorded object""" - return Recorded((self.chanid,self.recstartts), db=self.db) + return Recorded((self.chanid,self.recstartts), db=self._db) def open(self, type='r'): """Program.open(type='r') -> file or FileTransfer object""" @@ -545,19 +529,19 @@ kFindDailyRecord = 9 kFindWeeklyRecord = 10 - table = 'record' - where = 'recordid=%s' - setwheredat = 'self.recordid,' - defaults = {'recordid':None, 'type':kAllRecord, 'title':u'Unknown', - 'subtitle':'', 'description':'', 'category':'', - 'station':'', 'seriesid':'', 'search':0, - 'last_record':datetime(1900,1,1), - 'next_record':datetime(1900,1,1), - 'last_delete':datetime(1900,1,1)} - logmodule = 'Python Record' + _table = 'record' + _where = 'recordid=%s' + _setwheredat = 'self.recordid,' + _defaults = {'recordid':None, 'type':kAllRecord, 'title':u'Unknown', + 'subtitle':'', 'description':'', 'category':'', + 'station':'', 'seriesid':'', 'search':0, + 'last_record':datetime(1900,1,1), + 'next_record':datetime(1900,1,1), + 'last_delete':datetime(1900,1,1)} + _logmodule = 'Python Record' def __str__(self): - if self.wheredat is None: + if self._wheredat is None: return u"" % hex(id(self)) return u"" \ % (self.title, self.type, hex(id(self))) @@ -570,35 +554,35 @@ def create(self, data=None): """Record.create(data=None) -> Record object""" - self.wheredat = (DBDataWrite.create(self, data),) + self._wheredat = (DBDataWrite.create(self, data),) self._pull() - FileOps(db=self.db).reschedule(self.recordid) + FileOps(db=self._db).reschedule(self.recordid) return self def update(self, *args, **keywords): DBDataWrite.update(*args, **keywords) - FileOps(db=self.db).reschedule(self.recordid) + FileOps(db=self._db).reschedule(self.recordid) class Recorded( DBDataWrite ): """ Recorded(data=None, db=None, raw=None) -> Recorded object 'data' is a tuple containing (chanid, storagegroup) """ - table = 'recorded' - where = 'chanid=%s AND starttime=%s' - setwheredat = 'self.chanid,self.starttime' - defaults = {'title':u'Unknown', 'subtitle':'', 'description':'', - 'category':'', 'hostname':'', 'bookmark':0, - 'editing':0, 'cutlist':0, 'autoexpire':0, - 'commflagged':0, 'recgroup':'Default', 'seriesid':'', - 'programid':'', 'lastmodified':'CURRENT_TIMESTAMP', - 'filesize':0, 'stars':0, 'previouslyshown':0, - 'preserve':0, 'bookmarkupdate':0, - 'findid':0, 'deletepending':0, 'transcoder':0, - 'timestretch':1, 'recpriority':0, 'playgroup':'Default', - 'profile':'No', 'duplicate':1, 'transcoded':0, - 'watched':0, 'storagegroup':'Default'} - logmodule = 'Python Recorded' + _table = 'recorded' + _where = 'chanid=%s AND starttime=%s' + _setwheredat = 'self.chanid,self.starttime' + _defaults = {'title':u'Unknown', 'subtitle':'', 'description':'', + 'category':'', 'hostname':'', 'bookmark':0, + 'editing':0, 'cutlist':0, 'autoexpire':0, + 'commflagged':0, 'recgroup':'Default', 'seriesid':'', + 'programid':'', 'lastmodified':'CURRENT_TIMESTAMP', + 'filesize':0, 'stars':0, 'previouslyshown':0, + 'preserve':0, 'bookmarkupdate':0, + 'findid':0, 'deletepending':0, 'transcoder':0, + 'timestretch':1, 'recpriority':0, 'playgroup':'Default', + 'profile':'No', 'duplicate':1, 'transcoded':0, + 'watched':0, 'storagegroup':'Default'} + _logmodule = 'Python Recorded' class _Cast( DBDataCRef ): table = 'people' @@ -627,7 +611,7 @@ wfield = ['chanid','starttime'] def __str__(self): - if self.wheredat is None: + if self._wheredat is None: return u"" % hex(id(self)) return u"" % (self.title, self.starttime.strftime('%Y-%m-%d %H:%M:%S'), hex(id(self))) @@ -638,18 +622,18 @@ def __init__(self, data=None, db=None, raw=None): DBDataWrite.__init__(self, data, db, raw) if (data is not None) or (raw is not None): - self.cast = self._Cast(self.wheredat, self.db) - self.seek = self._Seek(self.wheredat, self.db) - self.markup = self._Markup(self.wheredat, self.db) + self.cast = self._Cast(self._wheredat, self._db) + self.seek = self._Seek(self._wheredat, self._db) + self.markup = self._Markup(self._wheredat, self._db) def create(self, data=None): """Recorded.create(data=None) -> Recorded object""" DBDataWrite.create(self, data) - self.wheredat = (self.chanid,self.starttime) + self._wheredat = (self.chanid,self.starttime) self._pull() - self.cast = self._Cast(self.wheredat, self.db) - self.seek = self._Seek(self.wheredat, self.db) - self.markup = self._Markup(self.wheredat, self.db) + self.cast = self._Cast(self._wheredat, self._db) + self.seek = self._Seek(self._wheredat, self._db) + self.markup = self._Markup(self._wheredat, self._db) return self def delete(self, force=False, rerecord=False): @@ -665,17 +649,17 @@ """Recorded.open(type='r') -> file or FileTransfer object""" return ftopen("myth://%s@%s/%s" % ( self.storagegroup, \ self.hostname,\ - self.basename), type, db=self.db) + self.basename), type, db=self._db) def getProgram(self): """Recorded.getProgram() -> Program object""" - be = FileOps(db=self.db) + be = FileOps(db=self._db) return be.getRecording(self.chanid, int(self.starttime.strftime('%Y%m%d%H%M%S'))) def getRecordedProgram(self): """Recorded.getRecordedProgram() -> RecordedProgram object""" - return RecordedProgram((self.chanid,self.progstart), db=self.db) + return RecordedProgram((self.chanid,self.progstart), db=self._db) def formatPath(self, path, replace=None): """ @@ -686,7 +670,7 @@ ('R','description'), ('C','category'), ('U','recgroup'), ('hn','hostname'), ('c','chanid') ): - tmp = str(self[data]).replace('/','-') + tmp = unicode(self[data]).replace('/','-') path = path.replace('%'+tag, tmp) for (data, pre) in ( ('starttime','%'), ('endtime','%e'), ('progstart','%p'),('progend','%pe') ): @@ -710,28 +694,29 @@ return path class RecordedProgram( DBDataWrite ): + """ RecordedProgram(data=None, db=None, raw=None) -> RecordedProgram object 'data' is a tuple containing (chanid, storagegroup) """ - table = 'recordedprogram' - where = 'chanid=%s AND starttime=%s' - setwheredat = 'self.chanid,self.starttime' - defaults = {'title':'', 'subtitle':'', - 'category':'', 'category_type':'', 'airdate':0, - 'stars':0, 'previouslyshown':0, 'title_pronounce':'', - 'stereo':0, 'subtitled':0, 'hdtv':0, - 'partnumber':0, 'closecaptioned':0, 'parttotal':0, - 'seriesid':'', 'originalairdate':'', 'showtype':u'', - 'colorcode':'', 'syndicatedepisodenumber':'', - 'programid':'', 'manualid':0, 'generic':0, - 'first':0, 'listingsource':0, 'last':0, - 'audioprop':u'','videoprop':u'', - 'subtitletypes':u''} - logmodule = 'Python RecordedProgram' + _table = 'recordedprogram' + _where = 'chanid=%s AND starttime=%s' + _setwheredat = 'self.chanid,self.starttime' + _defaults = {'title':'', 'subtitle':'', + 'category':'', 'category_type':'', 'airdate':0, + 'stars':0, 'previouslyshown':0, 'title_pronounce':'', + 'stereo':0, 'subtitled':0, 'hdtv':0, + 'partnumber':0, 'closecaptioned':0, 'parttotal':0, + 'seriesid':'', 'originalairdate':'', 'showtype':u'', + 'colorcode':'', 'syndicatedepisodenumber':'', + 'programid':'', 'manualid':0, 'generic':0, + 'first':0, 'listingsource':0, 'last':0, + 'audioprop':u'','videoprop':u'', + 'subtitletypes':u''} + _logmodule = 'Python RecordedProgram' def __str__(self): - if self.wheredat is None: + if self._wheredat is None: return u"" % hex(id(self)) return u"" % (self.title, self.starttime.strftime('%Y-%m-%d %H:%M:%S'), hex(id(self))) @@ -742,7 +727,7 @@ def create(self, data=None): """RecordedProgram.create(data=None) -> RecordedProgram object""" DBDataWrite.create(self, data) - self.wheredat = (self.chanid, self.starttime) + self._wheredat = (self.chanid, self.starttime) self._pull() return self @@ -751,18 +736,18 @@ OldRecorded(data=None, db=None, raw=None) -> OldRecorded object 'data' is a tuple containing (chanid, storagegroup) """ - table = 'oldrecorded' - where = 'chanid=%s AND starttime=%s' - setwheredat = 'self.chanid,self.starttime' - defaults = {'title':'', 'subtitle':'', - 'category':'', 'seriesid':'', 'programid':'', - 'findid':0, 'recordid':0, 'station':'', - 'rectype':0, 'duplicate':0, 'recstatus':-3, - 'reactivate':0, 'generic':0} - logmodule = 'Python OldRecorded' + _table = 'oldrecorded' + _where = 'chanid=%s AND starttime=%s' + _setwheredat = 'self.chanid,self.starttime' + _defaults = {'title':'', 'subtitle':'', + 'category':'', 'seriesid':'', 'programid':'', + 'findid':0, 'recordid':0, 'station':'', + 'rectype':0, 'duplicate':0, 'recstatus':-3, + 'reactivate':0, 'generic':0} + _logmodule = 'Python OldRecorded' def __str__(self): - if self.wheredat is None: + if self._wheredat is None: return u"" % hex(id(self)) return u"" % (self.title, self.starttime.strftime('%Y-%m-%d %H:%M:%S'), hex(id(self))) @@ -773,7 +758,7 @@ def create(self, data=None): """OldRecorded.create(data=None) -> OldRecorded object""" DBDataWrite.create(self, data) - self.wheredat = (self.chanid, self.starttime) + self._wheredat = (self.chanid, self.starttime) self._pull() return self @@ -782,11 +767,11 @@ OldRecorded.setDuplicate(record=False) -> None Toggles re-recordability """ - c = self.db.cursor(self.log) + c = self._db.cursor(self._log) c.execute("""UPDATE oldrecorded SET duplicate=%%s - WHERE %s""" % self.where, \ - tuple([record]+list(self.wheredat))) - FileOps(db=self.db).reschedule(0) + WHERE %s""" % self._where, \ + tuple([record]+list(self._wheredat))) + FileOps(db=self._db).reschedule(0) def update(self, *args, **keywords): """OldRecorded entries can not be altered""" @@ -838,12 +823,12 @@ ERRORED = 0x0130 CANCELLED = 0x0140 - table = 'jobqueue' - logmodule = 'Python Jobqueue' - defaults = {'id': None} + _table = 'jobqueue' + _logmodule = 'Python Jobqueue' + _defaults = {'id': None} def __str__(self): - if self.wheredat is None: + if self._wheredat is None: return u"" % hex(id(self)) return u"" % (self.id, hex(id(self))) @@ -852,15 +837,15 @@ def __init__(self, id=None, chanid=None, starttime=None, \ db=None, raw=None): - self.__dict__['where'] = 'id=%s' - self.__dict__['setwheredat'] = 'self.id,' + self.__dict__['_where'] = 'id=%s' + self.__dict__['_setwheredat'] = 'self.id,' if raw is not None: DBDataWrite.__init__(self, None, db, raw) elif id is not None: DBDataWrite.__init__(self, (id,), db, None) elif (chanid is not None) and (starttime is not None): - self.__dict__['where'] = 'chanid=%s AND starttime=%s' + self.__dict__['_where'] = 'chanid=%s AND starttime=%s' DBDataWrite.__init__(self, (chanid,starttime), db, None) else: DBDataWrite.__init__(self, None, db, None) @@ -868,8 +853,8 @@ def create(self, data=None): """Job.create(data=None) -> Job object""" id = DBDataWrite.create(self, data) - self.where = 'id=%s' - self.wheredat = (id,) + self._where = 'id=%s' + self._wheredat = (id,) return self def setComment(self,comment): @@ -884,21 +869,21 @@ class Channel( DBDataWrite ): """Channel(chanid=None, data=None, raw=None) -> Channel object""" - table = 'channel' - where = 'chanid=%s' - setwheredat = 'self.chanid,' - defaults = {'icon':'none', 'videofilters':'', 'callsign':u'', - 'xmltvid':'', 'recpriority':0, 'contrast':32768, - 'brightness':32768, 'colour':32768, 'hue':32768, - 'tvformat':u'Default', 'visible':1, 'outputfilters':'', - 'useonairguide':0, 'atsc_major_chan':0, - 'tmoffset':0, 'default_authority':'', - 'commmethod':-1, 'atsc_minor_chan':0, - 'last_record':datetime(1900,1,1)} - logmodule = 'Python Channel' + _table = 'channel' + _where = 'chanid=%s' + _setwheredat = 'self.chanid,' + _defaults = {'icon':'none', 'videofilters':'', 'callsign':u'', + 'xmltvid':'', 'recpriority':0, 'contrast':32768, + 'brightness':32768, 'colour':32768, 'hue':32768, + 'tvformat':u'Default', 'visible':1, 'outputfilters':'', + 'useonairguide':0, 'atsc_major_chan':0, + 'tmoffset':0, 'default_authority':'', + 'commmethod':-1, 'atsc_minor_chan':0, + 'last_record':datetime(1900,1,1)} + _logmodule = 'Python Channel' def __str__(self): - if self.wheredat is None: + if self._wheredat is None: return u"" % hex(id(self)) return u"" % \ (self.chanid, self.name, hex(id(self))) @@ -912,7 +897,7 @@ def create(self, data=None): """Channel.create(data=None) -> Channel object""" DBDataWrite.create(self, data) - self.wheredat = (self.chanid,) + self._wheredat = (self.chanid,) self._pull() return self @@ -921,13 +906,13 @@ Guide(data=None, db=None, raw=None) -> Guide object Data is a tuple of (chanid, starttime). """ - table = 'program' - where = 'chanid=%s AND starttime=%s' - setwheredat = 'self.chanid,self.starttime' - logmodule = 'Python Guide' + _table = 'program' + _where = 'chanid=%s AND starttime=%s' + _setwheredat = 'self.chanid,self.starttime' + _logmodule = 'Python Guide' def __str__(self): - if self.wheredat is None: + if self._wheredat is None: return u"" % hex(id(self)) return u"" % (self.title, self.starttime.strftime('%Y-%m-%d %H:%M:%S'), hex(id(self))) @@ -964,7 +949,7 @@ DBData.__init__(self, data=data, db=db, raw=raw) def record(self, type=Record.kAllRecord): - rec = Record(db=self.db) + rec = Record(db=self._db) for key in ('chanid','title','subtitle','description', 'category', 'seriesid','programid'): rec[key] = self[key] @@ -974,7 +959,7 @@ rec.enddate = self.endtime.date() rec.endtime = self.endtime-datetime.combine(rec.enddate, time()) - rec.station = Channel(self.chanid, db=self.db).callsign + rec.station = Channel(self.chanid, db=self._db).callsign rec.type = type return rec.create() @@ -983,59 +968,59 @@ class Video( DBDataWrite ): """Video(id=None, db=None, raw=None) -> Video object""" - table = 'videometadata' - where = 'intid=%s' - setwheredat = 'self.intid,' - defaults = {'subtitle':u'', 'director':u'Unknown', - 'rating':u'NR', 'inetref':u'00000000', - 'year':1895, 'userrating':0.0, - 'length':0, 'showlevel':1, - 'coverfile':u'No Cover', 'host':u'', - 'intid':None, 'homepage':u'', - 'watched':False, 'category':'none', - 'browse':True, 'hash':u'', - 'season':0, 'episode':0, - 'releasedate':date(1,1,1), 'childid':-1, - 'insertdate': datetime.now()} - logmodule = 'Python Video' - schema_value = 'mythvideo.DBSchemaVer' - schema_local = MVSCHEMA_VERSION - schema_name = 'MythVideo' - category_map = [{'None':0},{0:'None'}] + _table = 'videometadata' + _where = 'intid=%s' + _setwheredat = 'self.intid,' + _defaults = {'subtitle':u'', 'director':u'Unknown', + 'rating':u'NR', 'inetref':u'00000000', + 'year':1895, 'userrating':0.0, + 'length':0, 'showlevel':1, + 'coverfile':u'No Cover', 'host':u'', + 'intid':None, 'homepage':u'', + 'watched':False, 'category':'none', + 'browse':True, 'hash':u'', + 'season':0, 'episode':0, + 'releasedate':date(1,1,1), 'childid':-1, + 'insertdate': datetime.now()} + _logmodule = 'Python Video' + _schema_value = 'mythvideo.DBSchemaVer' + _schema_local = MVSCHEMA_VERSION + _schema_name = 'MythVideo' + _category_map = [{'None':0},{0:'None'}] def _fill_cm(self, name=None, id=None): if name: - if name not in self.category_map[0]: - c = self.db.cursor(self.log) + if name not in self._category_map[0]: + c = self._db.cursor(self._log) q1 = """SELECT intid FROM videocategory WHERE category=%s""" q2 = """INSERT INTO videocategory SET category=%s""" if c.execute(q1, name) == 0: c.execute(q2, name) c.execute(q1, name) id = c.fetchone()[0] - self.category_map[0][name] = id - self.category_map[1][id] = name + self._category_map[0][name] = id + self._category_map[1][id] = name elif id: - if id not in self.category_map[1]: - c = self.db.cursor(self.log) + if id not in self._category_map[1]: + c = self._db.cursor(self._log) if c.execute("""SELECT category FROM videocategory WHERE intid=%s""", id) == 0: raise MythDBError('Invalid ID found in videometadata.category') else: name = c.fetchone()[0] - self.category_map[0][name] = id - self.category_map[1][id] = name + self._category_map[0][name] = id + self._category_map[1][id] = name def _pull(self): DBDataWrite._pull(self) self._fill_cm(id=self.category) - self.category = self.category_map[1][self.category] + self.category = self._category_map[1][self.category] def _push(self): name = self.category self._fill_cm(name=name) - self.category = self.category_map[0][name] + self.category = self._category_map[0][name] DBDataWrite._push(self) self.category = name @@ -1043,7 +1028,7 @@ return str(self).encode('utf-8') def __str__(self): - if self.wheredat is None: + if self._wheredat is None: return u"" % hex(id(self)) res = self.title if self.season and self.episode: @@ -1056,15 +1041,15 @@ DBDataWrite.__init__(self, (id,), db, raw) if raw is not None: self._fill_cm(id=self.category) - self.category = self.category_map[1][self.category] + self.category = self._category_map[1][self.category] if (id is not None) or (raw is not None): - self.cast = self._Cast((self.intid,), self.db) - self.genre = self._Genre((self.intid,), self.db) - self.country = self._Country((self.intid,), self.db) + self.cast = self._Cast((self.intid,), self._db) + self.genre = self._Genre((self.intid,), self._db) + self.country = self._Country((self.intid,), self._db) def create(self, data=None): """Video.create(data=None) -> Video object""" - c = self.db.cursor(self.log) + c = self._db.cursor(self._log) fields = ' AND '.join(['%s=%%s' % f for f in \ ('title','subtitle','season','episode')]) count = c.execute("""SELECT intid FROM videometadata WHERE %s""" % @@ -1075,16 +1060,16 @@ if data: if 'category' in data: self._fill_cm(name=data['category']) - data['category'] = self.category_map[0][data['category']] + data['category'] = self._category_map[0][data['category']] self._fill_cm(name=self.category) - self.category = self.category_map[0][self.category] + self.category = self._category_map[0][self.category] id = DBDataWrite.create(self, data) c.close() - self.wheredat = (id,) + self._wheredat = (id,) self._pull() - self.cast = self._Cast((self.intid,), self.db) - self.genre = self._Genre((self.intid,), self.db) - self.country = self._Country((self.intid,), self.db) + self.cast = self._Cast((self.intid,), self._db) + self.genre = self._Genre((self.intid,), self._db) + self.country = self._Country((self.intid,), self._db) return self class _Cast( DBDataCRef ): @@ -1167,25 +1152,25 @@ sgroup = { 'filename':'Videos', 'banner':'Banners', 'coverfile':'Coverart', 'fanart':'Fanart', 'screenshot':'Screenshots', 'trailer':'Trailers'} - if self.data is None: + if self._data is None: return None if type not in sgroup: raise MythFileError(MythError.FILE_ERROR, 'Invalid type passed to Video._open(): '+str(type)) - SG = self.db.getStorageGroup(sgroup[type], self.host) + SG = self._db.getStorageGroup(sgroup[type], self.host) if len(SG) == 0: - SG = self.db.getStorageGroup('Videos', self.host) + SG = self._db.getStorageGroup('Videos', self.host) if len(SG) == 0: raise MythFileError(MythError.FILE_ERROR, 'Could not find MythVideo Storage Groups') return ftopen('myth://%s@%s/%s' % ( SG[0].groupname, self.host, - self.data[type]), - mode, False, nooverwrite, self.db) + self[type]), + mode, False, nooverwrite, self._db) def delete(self): """Video.delete() -> None""" - if self.data is None: + if self._data is None: return self.cast.clean() self.genre.clean() @@ -1231,7 +1216,7 @@ return hash def fromFilename(self, filename): - if self.wheredat is not None: + if self._wheredat is not None: return self self.filename = filename filename = filename[:filename.rindex('.')] @@ -1386,15 +1371,15 @@ """ Represents a single program from the netvisionrssitems table """ - table = 'netvisionrssitems' - where = 'feedtitle=%s AND title=%s' - setwheredat = 'self.feedtitle,self.title' - schema_value = 'NetvisionDBSchemaVer' - schema_local = NVSCHEMA_VERSION - schema_name = 'NetVision' + _table = 'netvisionrssitems' + _where = 'feedtitle=%s AND title=%s' + _setwheredat = 'self.feedtitle,self.title' + _schema_value = 'NetvisionDBSchemaVer' + _schema_local = NVSCHEMA_VERSION + _schema_name = 'NetVision' def __str__(self): - if self.wheredat is None: + if self._wheredat is None: return u"" % hex(id(self)) return u"" % \ (self.title, self.feedtitle, hex(id(self))) @@ -1406,15 +1391,15 @@ """ Represents a single program from the netvisiontreeitems table """ - table = 'netvisiontreeitems' - where = 'feedtitle=%s AND path=%s' - setwheredat = 'self.feedtitle,self.path' - schema_value = 'NetvisionDBSchemaVer' - schema_local = NVSCHEMA_VERSION - schema_name = 'NetVision' + _table = 'netvisiontreeitems' + _where = 'feedtitle=%s AND path=%s' + _setwheredat = 'self.feedtitle,self.path' + _schema_value = 'NetvisionDBSchemaVer' + _schema_local = NVSCHEMA_VERSION + _schema_name = 'NetVision' def __str__(self): - if self.wheredat is None: + if self._wheredat is None: return u"" % hex(id(self)) return u"" % \ (self.path, self.feedtitle, hex(id(self))) @@ -1426,15 +1411,15 @@ """ Represents a single site from the netvisionsites table """ - table = 'netvisionsites' - where = 'name=%' - setwheredat = 'name,' - schema_value = 'NetvisionDBSchemaVer' - schema_local = NVSCHEMA_VERSION - schema_name = 'NetVision' + _table = 'netvisionsites' + _where = 'name=%' + _setwheredat = 'name,' + _schema_value = 'NetvisionDBSchemaVer' + _schema_local = NVSCHEMA_VERSION + _schema_name = 'NetVision' def __str__(self): - if self.wheredat is None: + if self._wheredat is None: return u"" % hex(id(self)) return u"" % \ (self.name, self.url, hex(id(self))) Index: MythBase.py =================================================================== --- MythBase.py (revision 24213) +++ MythBase.py (working copy) @@ -6,7 +6,12 @@ from MythStatic import * -import os, re, socket, sys, locale, weakref +import os +import re +import socket +import sys +import locale +import weakref import xml.etree.cElementTree as etree from datetime import datetime from time import sleep, time @@ -25,9 +30,9 @@ Must be subclassed for use. Subclasses must provide: - field_order + _field_order string list of field names - field_type + _field_type integer list of field types by: 0: integer - int(value) 1: float - float(value) @@ -42,7 +47,7 @@ obj['field_name'] """ - class DictIterator( object ): + class _DictIterator( object ): def __init__(self, mode, parent): # modes = 1:keys, 2:values, 3:items self.index = 0 @@ -51,9 +56,9 @@ def __iter__(self): return self def next(self): self.index += 1 - if self.index > len(self.data.field_order): + if self.index > len(self.data._field_order): raise StopIteration - key = self.data.field_order[self.index-1] + key = self.data._field_order[self.index-1] if self.mode == 1: return key elif self.mode == 2: @@ -61,10 +66,10 @@ elif self.mode == 3: return (key, self.data[key]) - logmodule = 'Python DictData' - # class emulation functions + _logmodule = 'Python DictData' + # class emulation methods def __getattr__(self,name): - # function for class attribute access of data fields + # method for class attribute access of data fields # accesses real attributes, falls back to data fields, and errors if name in self.__dict__: return self.__dict__[name] @@ -75,57 +80,57 @@ raise AttributeError(str(name)) def __setattr__(self,name,value): - # function for class attribute access of data fields + # method for class attribute access of data fields # sets value in data fields, falling back to real attributes - if name in self.field_order: - self.data[name] = value + if name in self._field_order: + self._data[name] = value else: self.__dict__[name] = value - # container emulation functions + # container emulation methods def __getitem__(self,key): - # function for and dist-like access to content + # method for and dict-like access to content # as a side effect of dual operation, dict data cannot be indexed # keyed off integer values - if key in self.data: - return self.data[key] + if key in self._data: + return self._data[key] else: raise KeyError("'DictData' object has no key '%s'" %key) def __setitem__(self,key,value): - # function for dist-like access to content + # method for dist-like access to content # does not allow setting of data not already in field_order - if key in self.field_order: - self.data[key] = value + if key in self._field_order: + self._data[key] = value else: raise KeyError("'DictData' does not allow new data") def __contains__(self,item): - return bool(item in self.data.keys()) + return bool(item in self._data.keys()) def __iter__(self): - return self.DictIterator(2,self) + return self._DictIterator(2,self) def iterkeys(self): """ obj.iterkeys() -> an iterator over the keys of obj ordered by self.field_order """ - return self.DictIterator(1,self) + return self._DictIterator(1,self) def itervalues(self): """ obj.itervalues() -> an iterator over the values of obj ordered by self.field_order """ - return self.DictIterator(2,self) + return self._DictIterator(2,self) def iteritems(self): """ obj.iteritems() -> an iterator of over the (key,value) pairs of obj ordered by self.field_order """ - return self.DictIterator(3,self) + return self._DictIterator(3,self) def keys(self): """obj.keys() -> list of self.field_order""" @@ -139,7 +144,7 @@ return list(self.itervalues()) def get(self,key): - return self.data[key] + return self._data[key] def items(self): """ @@ -148,46 +153,64 @@ return list(self.iteritems()) def pop(self,key): raise NotImplementedError - def popitem(self): raise NotImplementedError def __len__(self): - return len(self.field_order) + return len(self._field_order) def __length_hint__(self): - return len(self.field_order) + return len(self._field_order) def update(self, *args, **keywords): - self.data.update(*args, **keywords) + self._data.update(*args, **keywords) ### additional management functions def _setDefs(self): - self.data = {} - self.log = MythLog(self.logmodule) + self._data = {} + self._log = MythLog(self._logmodule) def __init__(self, raw): self._setDefs() - self.data.update(self._process(raw)) + self._data.update(self._process(raw)) def _process(self, data): data = list(data) - for i in range(0, len(data)): + for i in range(len(data)): if data[i] == '': data[i] = None - elif self.field_type == 'Pass': + elif self._field_type == 'Pass': data[i] = data[i] - elif self.field_type[i] == 0: + elif self._field_type[i] == 0: data[i] = int(data[i]) - elif self.field_type[i] == 1: + elif self._field_type[i] == 1: data[i] = locale.atof(data[i]) - elif self.field_type[i] == 2: + elif self._field_type[i] == 2: data[i] = bool(data[i]) - elif self.field_type[i] == 3: + elif self._field_type[i] == 3: data[i] = data[i] - elif self.field_type[i] == 4: + elif self._field_type[i] == 4: data[i] = datetime.fromtimestamp(int(data[i])) - return dict(zip(self.field_order,data)) + return dict(zip(self._field_order,data)) + def _deprocess(self): + data = self.values() + for i in range(len(data)): + if data[i] is None: + data[i] = '' + elif self._field_type == 'Pass': + pass + elif self._field_type[i] == 0: + data[i] = str(data[i]) + elif self._field_type[i] == 1: + data[i] = locale.format("%0.6f", data[i]) + elif self._field_type[i] == 2: + data[i] = str(int(data[i])) + elif self._field_type[i] == 3: + pass + elif self._field_type[i] == 4: + data[i] = str(int(mktime(data[i].timetuple()))) + return data + @staticmethod def joinInt(high,low): """obj.joinInt(high, low) -> 64-bit int, from two signed ints""" @@ -206,14 +229,14 @@ a tuple of two-tuples. Accepts new information stored as attributes or keys. """ - _localvars = ['field_order','data','log'] + _localvars = ['_field_order','_data','_log'] def __init__(self, raw): self._setDefs() - self.field_order = [k for k,v in raw] - self.data.update(raw) + self._field_order = [k for k,v in raw] + self._data.update(raw) def _setDefs(self): - self.__dict__['field_order'] = [] + self.__dict__['_field_order'] = [] DictData._setDefs(self) def __setattr__(self, name, value): @@ -223,13 +246,13 @@ self.__setitem__(name, value) def __setitem__(self, key, value): - if key not in self.field_order: - self.field_order.append(key) - self.data[key] = value + if key not in self._field_order: + self._field_order.append(key) + self._data[key] = value def clear(self): - self.field_order = [] - self.data.clear() + self._field_order = [] + self._data.clear() class DBData( DictData ): """ @@ -239,19 +262,19 @@ Must be subclassed for use. Subclasses must provide: - table + _table Name of database table to be accessed - where + _where String defining WHERE clause for database lookup - setwheredat + _setwheredat String of comma separated variables to be evaluated to set 'wheredat'. 'eval(setwheredat)' must return a tuple, so string must contain at least one comma. Subclasses may provide: - allow_empty + _allow_empty Controls whether DBData() will allow an empty instance. - schema_value, schema_local, schema_name + _schema_value, _schema_local, _schema_name Allows checking of alternate plugin schemas Can be populated in two manners: @@ -261,71 +284,71 @@ raw Raw list as returned by 'select * from mytable' """ - field_type = 'Pass' - allow_empty = False - logmodule = 'Python DBData' - schema_value = 'DBSchemaVer' - schema_local = SCHEMA_VERSION - schema_name = 'Database' + _field_type = 'Pass' + _allow_empty = False + _logmodule = 'Python DBData' + _schema_value = 'DBSchemaVer' + _schema_local = SCHEMA_VERSION + _schema_name = 'Database' def getAllEntries(self): """obj.getAllEntries() -> tuple of DBData objects""" - c = self.db.cursor(self.log) - query = """SELECT * FROM %s""" % self.table - self.log(MythLog.DATABASE, query) + c = self._db.cursor(self._log) + query = """SELECT * FROM %s""" % self._table + self._log(MythLog.DATABASE, query) if c.execute(query) == 0: return () objs = [] for row in c.fetchall(): - objs.append(self.__class__(db=self.db, raw=row)) + objs.append(self.__class__(db=self._db, raw=row)) c.close() return objs def _setDefs(self): - self.__dict__['field_order'] = self.db.tablefields[self.table] + self.__dict__['_field_order'] = self._db.tablefields[self._table] DictData._setDefs(self) self._fillNone() - self.wheredat = None - self.log = MythLog(self.logmodule, db=self.db) + self._wheredat = None + self._log = MythLog(self._logmodule, db=self._db) def __init__(self, data=None, db=None, raw=None): - self.__dict__['db'] = MythDBBase(db) - self.db._check_schema(self.schema_value, - self.schema_local, self.schema_name) + self.__dict__['_db'] = MythDBBase(db) + self._db._check_schema(self._schema_value, + self._schema_local, self._schema_name) self._setDefs() if raw is not None: - if len(raw) == len(self.field_order): - self.data.update(self._process(raw)) - self.wheredat = eval(self.setwheredat) + if len(raw) == len(self._field_order): + self._data.update(self._process(raw)) + self._wheredat = eval(self._setwheredat) else: raise MythError('Incorrect raw input length to DBData()') elif data is not None: if None not in data: - self.wheredat = tuple(data) + self._wheredat = tuple(data) self._pull() else: - if self.allow_empty: + if self._allow_empty: self._fillNone() else: raise MythError('DBData() not given sufficient information') def _pull(self): """Updates table with data pulled from database.""" - c = self.db.cursor(self.log) + c = self._db.cursor(self._log) c.execute("""SELECT * FROM %s WHERE %s""" \ - % (self.table, self.where), self.wheredat) + % (self._table, self._where), self._wheredat) data = c.fetchone() c.close() if data is None: return - self.data.update(self._process(data)) + self._data.update(self._process(data)) def _fillNone(self): """Fills out dictionary fields with empty data""" - self.field_order = self.db.tablefields[self.table] - for field in self.field_order: - self.data[field] = None + self._field_order = self._db.tablefields[self._table] + for field in self._field_order: + self._data[field] = None class DBDataWrite( DBData ): """ @@ -335,17 +358,17 @@ Must be subclassed for use. Subclasses must provide: - table + _table Name of database table to be accessed - where + _where String defining WHERE clause for database lookup - setwheredat + _setwheredat String of comma separated variables to be evaluated to set 'wheredat'. 'eval(setwheredat)' must return a tuple, so string must contain at least one comma. Subclasses may provide: - defaults + _defaults Dictionary of default values to be used when creating new database entries. Additionally, values of 'None' will be stripped and not used to alter the database. @@ -358,24 +381,24 @@ Raw list as returned by 'select * from mytable' Additionally, can be left uninitialized to allow creation of a new entry """ - defaults = None - allow_empty = True - logmodule = 'Python DBDataWrite' + _defaults = None + _allow_empty = True + _logmodule = 'Python DBDataWrite' def _sanitize(self, data, fill=True): """Remove fields from dictionary that are not in database table.""" data = data.copy() for key in data.keys(): - if key not in self.field_order: + if key not in self._field_order: del data[key] - if self.defaults is not None: - for key in self.defaults: + if self._defaults is not None: + for key in self._defaults: if key in data: - if self.defaults[key] is None: + if self._defaults[key] is None: del data[key] elif data[key] is None: if fill: - data[key] = self.defaults[key] + data[key] = self._defaults[key] return data def _setDefs(self): @@ -384,12 +407,12 @@ def _fillDefs(self): self._fillNone() - self.data.update(self.defaults) + self._data.update(self._defaults) def __init__(self, data=None, db=None, raw=None): DBData.__init__(self, data, db, raw) if raw is not None: - self.origdata = self.data.copy() + self._origdata = self._data.copy() def create(self,data=None): """ @@ -400,37 +423,37 @@ before pushing the entire set onto the database. Will only function with an uninitialized object. """ - if self.wheredat is not None: + if self._wheredat is not None: raise MythError('DBDataWrite object already bound to '+\ 'existing instance') if data is not None: data = self._sanitize(data, False) - self.data.update(data) + self._data.update(data) data = self._sanitize(self.data) for key in data.keys(): if data[key] is None: del data[key] - c = self.db.cursor(self.log) + c = self._db.cursor(self.log) fields = ', '.join(data.keys()) format_string = ', '.join(['%s' for d in data.values()]) c.execute("""INSERT INTO %s (%s) VALUES(%s)""" \ - % (self.table, fields, format_string), data.values()) + % (self._table, fields, format_string), data.values()) intid = c.lastrowid c.close() return intid def _pull(self): DBData._pull(self) - self.origdata = self.data.copy() + self._origdata = self._data.copy() def _push(self): - if (self.where is None) or (self.wheredat is None): + if (self._where is None) or (self._wheredat is None): return - c = self.db.cursor(self.log) - data = self._sanitize(self.data) + c = self._db.cursor(self._log) + data = self._sanitize(self._data) for key, value in data.items(): - if value == self.origdata[key]: + if value == self._origdata[key]: # filter unchanged data del data[key] if len(data) == 0: @@ -438,10 +461,10 @@ return format_string = ', '.join(['%s = %%s' % d for d in data]) sql_values = data.values() - sql_values.extend(self.wheredat) + sql_values.extend(self._wheredat) c.execute("""UPDATE %s SET %s WHERE %s""" \ - % (self.table, format_string, self.where), sql_values) + % (self._table, format_string, self._where), sql_values) c.close() self._pull() @@ -456,7 +479,7 @@ data = {} data.update(*args, **keywords) - self.data.update(self._sanitize(data)) + self._data.update(self._sanitize(data)) self._push() def delete(self): @@ -465,13 +488,13 @@ Delete video entry from database. """ - if (self.where is None) or \ - (self.wheredat is None) or \ - (self.data is None): + if (self._where is None) or \ + (self._wheredat is None) or \ + (self._data is None): return - c = self.db.cursor(self.log) + c = self._db.cursor(self.log) c.execute("""DELETE FROM %s WHERE %s""" \ - % (self.table, self.where), self.wheredat) + % (self._table, self._where), self._wheredat) c.close() class DBDataRef( object ): @@ -491,17 +514,17 @@ class SubData( DictData ): def _setDefs(self): - self.__dict__['field_order'] = [] + self.__dict__['_field_order'] = [] DictData._setDefs(self) def __repr__(self): return str(tuple(self)) def __init__(self,data,fields): self._setDefs() - self.field_order = fields - self.field_type = 'Pass' - self.data.update(self._process(data)) + self._field_order = fields + self._field_type = 'Pass' + self._data.update(self._process(data)) def __hash__(self): - dat = self.data.copy() + dat = self._data.copy() keys = dat.keys() keys.sort() return hash(str([hash(dat[k]) for k in keys])) @@ -618,17 +641,17 @@ class SubData( DictData ): def _setDefs(self): - self.__dict__['field_order'] = [] + self.__dict__['_field_order'] = [] DictData._setDefs(self) def __repr__(self): - return str(tuple(self.data.values())) + return str(tuple(self._data.values())) def __init__(self,data,fields): self._setDefs() - self.field_order = ['cross']+fields - self.field_type = 'Pass' - self.data.update(self._process(data)) + self._field_order = ['cross']+fields + self._field_type = 'Pass' + self._data.update(self._process(data)) def __hash__(self): - dat = self.data.copy() + dat = self._data.copy() del dat['cross'] keys = dat.keys() keys.sort() @@ -892,7 +915,7 @@ class _FieldData( QuickDictData ): def __str__(self): return str(list(self)) def __repr__(self): return str(self).encode('utf-8') - def __iter__(self): return self.DictIterator(1,self) + def __iter__(self): return self._DictIterator(1,self) def __init__(self, result): data = [(row[0], QuickDictData(zip( \ @@ -901,129 +924,129 @@ )for row in result] QuickDictData.__init__(self, data) def __getitem__(self,key): - if key in self.data: - return self.data[key] + if key in self._data: + return self._data[key] else: try: - return self.field_order[key] + return self._field_order[key] except: raise KeyError(str(key)) - _localvars = QuickDictData._localvars+['db'] + _localvars = QuickDictData._localvars+['_db'] def __str__(self): return str(list(self)) def __repr__(self): return str(self).encode('utf-8') - def __iter__(self): return self.DictIterator(1,self) + def __iter__(self): return self._DictIterator(1,self) def __init__(self, db, log): QuickDictData.__init__(self, ()) - self.db = db - self.log = log - self.data = self.db.tablefields - self.field_order = self.data.keys() + self._db = db + self._log = log + self._data = self._db.tablefields + self._field_order = self._data.keys() def __getitem__(self,key): - if key not in self.data: + if key not in self._data: # pull field list from database - c = self.db.cursor(self.log) + c = self._db.cursor(self._log) try: c.execute("DESC %s" % (key,)) except: return None - self.field_order.append(key) - self.data[key] = self._FieldData(c.fetchall()) + self._field_order.append(key) + self._data[key] = self._FieldData(c.fetchall()) c.close() # return cached information - return self.data[key] + return self._data[key] class _Settings( QuickDictData ): """Provides dictionary-like list of hosts""" class _HostSettings( QuickDictData ): - _localvars = QuickDictData._localvars+['db','host'] + _localvars = QuickDictData._localvars+['_db','_host'] def __str__(self): return str(list(self)) def __repr__(self): return str(self).encode('utf-8') - def __iter__(self): return self.DictIterator(1,self) + def __iter__(self): return self._DictIterator(1,self) def __init__(self, db, log, host): QuickDictData.__init__(self, ()) - self.db = db - self.host = host - self.log = log + self._db = db + self._host = host + self._log = log def __getitem__(self, key): - if key not in self.data: - if self.host == 'NULL': + if key not in self._data: + if self._host == 'NULL': where = 'IS NULL' wheredat = (key,) else: where = 'LIKE(%s)' - wheredat = (key, self.host) + wheredat = (key, self._host) - c = self.db.cursor(self.log) + c = self._db.cursor(self._log) if c.execute("""SELECT data FROM settings WHERE value=%%s AND hostname %s LIMIT 1""" % where, wheredat) > 0: - self.data[key] = c.fetchone()[0] + self._data[key] = c.fetchone()[0] else: - self.data[key] = None - self.field_order.append(key) + self._data[key] = None + self._field_order.append(key) c.close() - return self.data[key] + return self._data[key] def __setitem__(self, key, value): - if key not in self.data: + if key not in self._data: self.__getitem__(key) - c = self.db.cursor(self.log) - if self.data[key] is None: + c = self._db.cursor(self._log) + if self._data[key] is None: c.execute("""INSERT INTO settings (value, data, hostname) VALUES (%s,%s,%s)""", - (key, value, self.host)) + (key, value, self._host)) else: if self._host == 'NULL': where = 'IS NULL' wheredat = (value, key) else: where = 'LIKE(%s)' - wheredat = (value, key, self.host) + wheredat = (value, key, self._host) c.execute("""UPDATE settings SET data=%%s WHERE value=%%s AND hostname %s""" % where, wheredat) - self.data[key] = value + self._data[key] = value def getall(self): - c = self.db.cursor(self.log) - if self.host == 'NULL': + c = self._db.cursor(self._log) + if self._host == 'NULL': where = 'IS NULL' wheredat = () else: where = 'LIKE(%s)' - wheredat = (self.host,) + wheredat = (self._host,) c.execute("""SELECT value,data FROM settings WHERE hostname %s""" % where, wheredat) for k,v in c.fetchall(): - self.data[k] = v - if k not in self.field_order: - self.field_order.append(k) + self._data[k] = v + if k not in self._field_order: + self._field_order.append(k) return self.items() - _localvars = QuickDictData._localvars+['db'] + _localvars = QuickDictData._localvars+['_db'] def __str__(self): return str(list(self)) def __repr__(self): return str(self).encode('utf-8') def __iter__(self): return self.DictIterator(1,self) def __init__(self, db, log): QuickDictData.__init__(self, ()) - self.db = db - self.log = log - self.data = self.db.settings - self.field_order = self.data.keys() + self._db = db + self._log = log + self._data = self._db.settings + self._field_order = self._data.keys() def __getitem__(self, key): - if key not in self.data: - self.data[key] = self._HostSettings(self.db, self.log, key) - self.field_order.append(key) - return self.data[key] + if key not in self._data: + self._data[key] = self._HostSettings(self._db, self._log, key) + self._field_order.append(key) + return self._data[key] def __init__(self, db=None, args=None, **dbconn): self.db = None @@ -1850,10 +1873,10 @@ StorageGroup(id=None, db=None, raw=None) -> StorageGroup object Represents a single storage group entry """ - table = 'storagegroup' - where = 'id=%s' - setwheredat = 'self.id,' - logmodule = 'Python StorageGroup' + _table = 'storagegroup' + _where = 'id=%s' + _setwheredat = 'self.id,' + _logmodule = 'Python StorageGroup' def __str__(self): return u"