Ticket #4600: mythtv_python_bindings.5.diff
File mythtv_python_bindings.5.diff, 23.5 KB (added by , 16 years ago) |
---|
-
configure
181 181 echo "" 182 182 echo " --with-bindings=LIST install the bindings specified in the" 183 183 echo " comma-separated list" 184 echo " Supported bindings: perl "184 echo " Supported bindings: perl, python" 185 185 <<BLOCK_QUOTE 186 186 echo " --disable-network disable network support [default=no]" 187 187 echo " --disable-ipv6 disable ipv6 support [default=no]" … … 902 902 USING_LIST=' 903 903 appleremote 904 904 bindings_perl 905 bindings_python 905 906 darwin_da 906 907 dvdv 907 908 opengl … … 1143 1144 audio_jack_libs="-ljack" 1144 1145 enable audio_oss 1145 1146 bindings_perl="yes" 1147 bindings_python="yes" 1146 1148 dbox2="yes" 1147 1149 directfb="yes" 1148 1150 dvb_path="/usr/include" … … 1369 1371 if test x"${binding}" = x"perl"; then 1370 1372 bindings_perl="yes" 1371 1373 fi 1374 if test x"${binding}" = x"python"; then 1375 bindings_python="yes" 1376 fi 1372 1377 done 1373 1378 ;; 1374 1379 --without-bindings=*) … … 1377 1382 if test x"${binding}" = x"perl"; then 1378 1383 bindings_perl="no" 1379 1384 fi 1385 if test x"${binding}" = x"python"; then 1386 bindings_python="no" 1387 fi 1380 1388 done 1381 1389 ;; 1382 1390 --disable-encoders) disable $ENCODER_LIST … … 1611 1619 disable ffserver 1612 1620 disable v4l 1613 1621 disable bindings_perl 1622 disable bindings_python 1614 1623 SLIBPREF="lib" 1615 1624 SLIBSUF=".dll" 1616 1625 EXESUF=".exe" … … 2973 2982 2974 2983 echo "# Bindings" 2975 2984 echo "bindings_perl ${bindings_perl-no}" 2985 echo "bindings_python ${bindings_python-no}" 2976 2986 echo "" 2977 2987 2978 2988 MYTH_CONFIG_H=libs/libmyth/mythconfig.h -
libs/libmythtv/programinfo.h
16 16 17 17 /* If NUMPROGRAMLINES gets updated following files need 18 18 updates and code changes: 19 mythplugins/mythvideo/mythvideo/scripts/MythTV.py20 19 mythplugins/mythweb/includes/mythbackend.php 21 20 mythplugins/mythweb/objects/MythTV.php 22 21 mythtv/bindings/perl/MythTV.pm 22 mythtv/bindings/python/mythtv.py 23 23 */ 24 24 #define NUMPROGRAMLINES 46 25 25 -
libs/libmyth/mythcontext.h
121 121 * mythtv/bindings/perl/MythTV.pm (version number) 122 122 * mythtv/bindings/perl/MythTV/Program.pm (layout) 123 123 * 124 * Myth Video125 * mythplugins/mythvideo/mythvideo/scripts/MythTV.py (version number)126 * mythplugins/mythvideo/mythvideo/scripts/MythTV.py (layout)124 * MythTV Python Bindings 125 * mythtv/bindings/python/mythtv.py (version number) 126 * mythtv/bindings/python/mythtv.py (layout) 127 127 */ 128 128 #define MYTH_PROTO_VERSION "39" 129 129 -
bindings/python/python.pro
1 include ( ../../config.mak ) 2 3 python_install.target = install 4 python_install.depends = all 5 python_install.commands = python setup.py install 6 7 QMAKE_LINK=@-echo 8 QMAKE_EXTRA_UNIX_TARGETS += python_install 9 -
bindings/python/setup.py
1 #!/usr/bin/python 2 3 from distutils.core import setup 4 5 setup( 6 name='mythtv', 7 version='0.21', 8 description='MythTV Python bindings.', 9 packages=['mythtv'], 10 ) -
bindings/python/mythtv/mythvideo.py
1 #!/usr/bin/python 2 3 """ 4 Provides the MythVideo class with convinience methods to access the MythTV mythvideo database. 5 """ 6 7 import mythdb 8 from mythlog import * 9 10 log = MythLog(INFO, '%(levelname)s - %(message)s', 'mythvideo') 11 12 class MythVideo: 13 """ 14 Provides convinience methods to access the MythTV mythvideo database. 15 """ 16 def __init__(self): 17 """ 18 Initialise the MythDB connection. 19 """ 20 self.db = mythdb.MythDB() 21 22 def pruneMetadata(self): 23 """ 24 Removes metadata from the database for files that no longer exist. 25 """ 26 c = self.db.cursor() 27 c.execute(""" 28 SELECT intid, filename 29 FROM videometadata""") 30 31 row = c.fetchone() 32 while row is not None: 33 intid = row[0] 34 filename = row[1] 35 if not os.path.exists(filename): 36 log.Msg(INFO, '%s not exist, removing metadata...', filename) 37 c2 = self.db.cursor() 38 c2.execute("""DELETE FROM videometadata WHERE intid = %s""", (intid,)) 39 c2.close() 40 row = c.fetchone() 41 c.close() 42 43 def getGenreId(self, genre_name): 44 """ 45 Find the id of the given genre from MythDB. 46 47 If the genre does not exist, insert it and return its id. 48 """ 49 c = self.db.cursor() 50 c.execute("SELECT intid FROM videocategory WHERE lower(category) = %s", (genre_name,)) 51 row = c.fetchone() 52 c.close() 53 54 if row is not None: 55 return row[0] 56 57 # Insert a new genre. 58 c = self.db.cursor() 59 c.execute("INSERT INTO videocategory(category) VALUES (%s)", (genre_name.capitalize(),)) 60 newid = c.lastrowid 61 c.close() 62 63 return newid 64 65 def getMetadataId(self, videopath): 66 """ 67 Finds the MythVideo metadata id for the given video path from the MythDB, if any. 68 69 Returns None if no metadata was found. 70 """ 71 c = self.db.cursor() 72 c.execute(""" 73 SELECT intid 74 FROM videometadata 75 WHERE filename = %s""", (videopath,)) 76 row = c.fetchone() 77 c.close() 78 79 if row is not None: 80 return row[0] 81 else: 82 return None 83 84 def hasMetadata(self, videopath): 85 """ 86 Determines if the given videopath has any metadata in the DB 87 88 Returns False if no metadata was found. 89 """ 90 c = self.db.cursor() 91 c.execute(""" 92 SELECT category, year 93 FROM videometadata 94 WHERE filename = %s""", (videopath,)) 95 row = c.fetchone() 96 c.close() 97 98 if row is not None: 99 # If category is 0 and year is 1895, we can safely assume no metadata 100 if (row[0] == 0) and (row[1] == 1895): 101 return False 102 else: 103 return True 104 else: 105 return False 106 107 def getMetadata(self, id): 108 """ 109 Finds the MythVideo metadata for the given id from the MythDB, if any. 110 111 Returns None if no metadata was found. 112 """ 113 c = self.db.cursor() 114 c.execute(""" 115 SELECT * 116 FROM videometadata 117 WHERE intid = %s""", (id,)) 118 row = c.fetchone() 119 c.close() 120 121 if row is not None: 122 return row 123 else: 124 return None 125 126 def setMetadata(self, data, id=None): 127 """ 128 Adds or updates the metadata in the database for a video item. 129 """ 130 c = self.db.cursor() 131 if id is None: 132 fields = ', '.join(data.keys()) 133 format_string = ', '.join(['%s' for d in data.values()]) 134 sql = "INSERT INTO videometadata(%s) VALUES(%s)" % (fields, format_string) 135 c.execute(sql, data.values()) 136 intid = c.lastrowid 137 c.close() 138 return intid 139 else: 140 log.Msg(DEBUG, 'Updating metadata for %s', id) 141 format_string = ', '.join(['%s = %%s' % d for d in data]) 142 sql = "UPDATE videometadata SET %s WHERE intid = %%s" % format_string 143 sql_values = data.values() 144 sql_values.append(id) 145 c.execute(sql, sql_values) 146 c.close() 147 148 if __name__ == '__main__': 149 print 'mythvideo can only be used as a module' -
bindings/python/mythtv/mythtv.py
1 #!/usr/bin/python 2 3 """ 4 Provides classes for connecting to a MythTV backend. 5 6 The MythTV class to handle connection to and querying of a MythTV backend. 7 The Recorder class representing and storing details of a tuner card. 8 The Program class for storing details of a TV program. 9 """ 10 11 # vim:ts=4 sw=4 nowrap: 12 13 import os 14 import sys 15 import socket 16 import shlex 17 import socket 18 import code 19 from datetime import datetime 20 21 import mythdb 22 from mythlog import * 23 24 log = MythLog(INFO, '%(levelname)s - %(message)s', 'mythtv') 25 26 RECSTATUS = { 27 'TunerBusy': -8, 28 'LowDiskSpace': -7, 29 'Cancelled': -6, 30 'Deleted': -5, 31 'Aborted': -4, 32 'Recorded': -3, 33 'Recording': -2, 34 'WillRecord': -1, 35 'Unknown': 0, 36 'DontRecord': 1, 37 'PreviousRecording': 2, 38 'CurrentRecording': 3, 39 'EarlierShowing': 4, 40 'TooManyRecordings': 5, 41 'NotListed': 6, 42 'Conflict': 7, 43 'LaterShowing': 8, 44 'Repeat': 9, 45 'Inactive': 10, 46 'NeverRecord': 11, 47 } 48 49 BACKEND_SEP = '[]:[]' 50 PROTO_VERSION = 39 51 PROGRAM_FIELDS = 46 52 53 class MythTV: 54 """ 55 A connection to a MythTV backend. 56 """ 57 def __init__(self, conn_type='Monitor'): 58 self.db = mythdb.MythDB(sys.argv[1:]) 59 self.master_host = self.db.getSetting('MasterServerIP') 60 self.master_port = int(self.db.getSetting('MasterServerPort')) 61 62 if not self.master_host: 63 log.Msg(CRITICAL, 'Unable to find MasterServerIP in database') 64 sys.exit(1) 65 if not self.master_port: 66 log.Msg(CRITICAL, 'Unable to find MasterServerPort in database') 67 sys.exit(1) 68 69 try: 70 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 71 self.socket.settimeout(10) 72 self.socket.connect((self.master_host, self.master_port)) 73 res = self.backendCommand('MYTH_PROTO_VERSION %s' % PROTO_VERSION).split(BACKEND_SEP) 74 if res[0] == 'REJECT': 75 log.Msg(CRITICAL, 'Backend has version %s and we speak version %s', res[1], PROTO_VERSION) 76 sys.exit(1) 77 res = self.backendCommand('ANN %s %s 0' % (conn_type, socket.gethostname())) 78 if res != 'OK': 79 log.Msg(CRITICAL, 'Unexpected answer to ANN command: %s', res) 80 else: 81 log.Msg(INFO, 'Successfully connected mythbackend at %s:%d', self.master_host, self.master_port) 82 except socket.error, e: 83 log.Msg(CRITICAL, 'Couldn\'t connect to %s:%d (is the backend running)', self.master_host, self.master_port) 84 sys.exit(1) 85 86 def backendCommand(self, data): 87 """ 88 Sends a formatted command via a socket to the mythbackend. 89 90 Returns the result from the backend. 91 """ 92 def recv(): 93 """ 94 Reads the data returned from the backend. 95 """ 96 # The first 8 bytes of the response gives us the length 97 data = self.socket.recv(8) 98 try: 99 length = int(data) 100 except: 101 return '' 102 data = [] 103 while length > 0: 104 chunk = self.socket.recv(length) 105 length = length - len(chunk) 106 data.append(chunk) 107 return ''.join(data) 108 109 command = '%-8d%s' % (len(data), data) 110 log.Msg(DEBUG, 'Sending command: %s', command) 111 self.socket.send(command) 112 return recv() 113 114 def getPendingRecordings(self): 115 """ 116 Returns a list of Program objects which are scheduled to be recorded. 117 """ 118 programs = [] 119 res = self.backendCommand('QUERY_GETALLPENDING').split(BACKEND_SEP) 120 has_conflict = int(res.pop(0)) 121 num_progs = int(res.pop(0)) 122 log.Msg(DEBUG, '%s pending recordings', num_progs) 123 for i in range(num_progs): 124 programs.append( 125 Program(res[i * PROGRAM_FIELDS:(i * PROGRAM_FIELDS) + PROGRAM_FIELDS])) 126 return programs 127 128 def getScheduledRecordings(self): 129 """ 130 Returns a list of Program objects which are scheduled to be recorded. 131 """ 132 programs = [] 133 res = self.backendCommand('QUERY_GETALLSCHEDULED').split(BACKEND_SEP) 134 num_progs = int(res.pop(0)) 135 log.Msg(DEBUG, '%s scheduled recordings', num_progs) 136 for i in range(num_progs): 137 programs.append( 138 Program(res[i * PROGRAM_FIELDS:(i * PROGRAM_FIELDS) + PROGRAM_FIELDS])) 139 return programs 140 141 def getUpcomingRecordings(self): 142 """ 143 Returns a list of Program objects which are scheduled to be recorded. 144 145 Sorts the list by recording start time and only returns those with 146 record status of WillRecord. 147 """ 148 def sort_programs_by_starttime(x, y): 149 if x.starttime > y.starttime: 150 return 1 151 elif x.starttime == y.starttime: 152 return 0 153 else: 154 return -1 155 programs = [] 156 res = self.getPendingRecordings() 157 for p in res: 158 if p.recstatus == RECSTATUS['WillRecord']: 159 programs.append(p) 160 programs.sort(sort_programs_by_starttime) 161 return programs 162 163 def getRecorderList(self): 164 """ 165 Returns a list of recorders, or an empty list if none. 166 """ 167 recorders = [] 168 c = self.db.cursor() 169 c.execute('SELECT cardid FROM capturecard') 170 row = c.fetchone() 171 while row is not None: 172 recorders.append(int(row[0])) 173 row = c.fetchone() 174 c.close() 175 return recorders 176 177 def getFreeRecorderList(self): 178 """ 179 Returns a list of free recorders, or an empty list if none. 180 """ 181 res = self.backendCommand('GET_FREE_RECORDER_LIST').split(BACKEND_SEP) 182 recorders = [int(d) for d in res] 183 return recorders 184 185 def getRecorderDetails(self, recorder_id): 186 """ 187 Returns a Recorder object with details of the recorder. 188 """ 189 c = self.db.cursor() 190 c.execute("""SELECT cardid, cardtype, videodevice, hostname 191 FROM capturecard WHERE cardid = %s""", recorder_id) 192 row = c.fetchone() 193 if row: 194 recorder = Recorder(row) 195 return recorder 196 else: 197 return None 198 199 def getCurrentRecording(self, recorder): 200 """ 201 Returns a Program object for the current recorders recording. 202 """ 203 res = self.backendCommand('QUERY_RECORDER %s[]:[]GET_CURRENT_RECORDING' % recorder) 204 return Program(res.split(BACKEND_SEP)) 205 206 def isRecording(self, recorder): 207 """ 208 Returns a boolean as to whether the given recorder is recording. 209 """ 210 res = self.backendCommand('QUERY_RECORDER %s[]:[]IS_RECORDING' % recorder) 211 if res == '1': 212 return True 213 else: 214 return False 215 216 def isActiveBackend(self, hostname): 217 """ 218 Returns a boolean as to whether the given host is an active backend 219 """ 220 res = self.backendCommand('QUERY_IS_ACTIVE_BACKEND[]:[]%s' % hostname) 221 if res == 'TRUE': 222 return True 223 else: 224 return False 225 226 class Recorder: 227 """ 228 Represents a MythTV capture card. 229 """ 230 def __str__(self): 231 return "Recorder %s (%s)" % (self.cardid, self.cardtype) 232 233 def __repr__(self): 234 return "Recorder %s (%s)" % (self.cardid, self.cardtype) 235 236 def __init__(self, data): 237 """ 238 Load the list of data into the object. 239 """ 240 self.cardid = data[0] 241 self.cardtype = data[1] 242 self.videodevice = data[2] 243 self.hostname = data[3] 244 245 class Program: 246 """ 247 Represents a program with all the detail known. 248 """ 249 def __str__(self): 250 return "%s (%s)" % (self.title, self.starttime.strftime('%Y-%m-%d %H:%M:%S')) 251 252 def __repr__(self): 253 return "%s (%s)" % (self.title, self.starttime.strftime('%Y-%m-%d %H:%M:%S')) 254 255 def __init__(self, data): 256 """ 257 Load the list of data into the object. 258 """ 259 self.title = data[0] 260 self.subtitle = data[1] 261 self.description = data[2] 262 self.category = data[3] 263 try: 264 self.chanid = int(data[4]) 265 except ValueError: 266 self.chanid = None 267 self.channum = data[5] #chanstr 268 self.callsign = data[6] #chansign 269 self.channame = data[7] 270 self.filename = data[8] #pathname 271 self.fs_high = data[9] 272 self.fs_low = data[10] 273 self.starttime = datetime.fromtimestamp(int(data[11])) # startts 274 self.endtime = datetime.fromtimestamp(int(data[12])) #endts 275 self.duplicate = int(data[13]) 276 self.shareable = int(data[14]) 277 self.findid = int(data[15]) 278 self.hostname = data[16] 279 self.sourceid = int(data[17]) 280 self.cardid = int(data[18]) 281 self.inputid = int(data[19]) 282 self.recpriority = int(data[20]) 283 self.recstatus = int(data[21]) 284 self.recordid = int(data[22]) 285 self.rectype = data[23] 286 self.dupin = data[24] 287 self.dupmethod = data[25] 288 self.recstartts = datetime.fromtimestamp(int(data[26])) 289 self.recendts = datetime.fromtimestamp(int(data[27])) 290 self.repeat = int(data[28]) 291 self.programflags = data[29] 292 self.recgroup = data[30] 293 self.commfree = int(data[31]) 294 self.outputfilters = data[32] 295 self.seriesid = data[33] 296 self.programid = data[34] 297 self.lastmodified = data[35] 298 self.stars = float(data[36]) 299 self.airdate = data[37] 300 self.hasairdate = int(data[38]) 301 self.playgroup = data[39] 302 self.recpriority2 = int(data[40]) 303 self.parentid = data[41] 304 self.storagegroup = data[42] 305 self.audio_props = data[43] 306 self.video_props = data[44] 307 self.subtitle_type = data[45] 308 309 if __name__ == '__main__': 310 banner = '\'m\' is a MythTV instance.' 311 try: 312 import readline, rlcompleter 313 except: 314 pass 315 else: 316 readline.parse_and_bind("tab: complete") 317 banner = banner + " TAB completion is available." 318 m = MythTV() 319 namespace = globals().copy() 320 namespace.update(locals()) 321 code.InteractiveConsole(namespace).interact(banner) -
bindings/python/mythtv/__init__.py
1 __all__ = ['mythtv', 'mythlog', 'mythdb', 'mythvideo'] 2 3 from mythlog import * 4 from mythdb import * 5 from mythtv import * 6 from mythvideo import * -
bindings/python/mythtv/mythlog.py
1 #!/usr/bin/python 2 3 """ 4 Provides simple logging and exception classes. 5 """ 6 7 # vim:ts=4 sw=4 nowrap: 8 9 import logging 10 11 # Vars to imporove readability 12 CRITICAL = logging.CRITICAL 13 FATAL = logging.FATAL 14 ERROR = logging.ERROR 15 WARNING = logging.WARNING 16 INFO = logging.INFO 17 DEBUG = logging.DEBUG 18 19 class MythLog: 20 """ 21 A simple logging class 22 """ 23 def __init__(self, level, format, instance): 24 self.log = logging.getLogger(instance) 25 self.log.setLevel(level) 26 self.ch = logging.StreamHandler() 27 self.ch.setFormatter(logging.Formatter(format)) 28 self.log.addHandler(self.ch) 29 30 def Msg(self, level, msg, *args, **kwargs): 31 self.log.log(level, msg, *args, **kwargs) 32 33 class MythError: 34 """ 35 A simple exception class 36 """ 37 def __init__(self, message): 38 self.message = message 39 40 def __repr__(self): 41 print ': ' + self.message 42 43 if __name__ == '__main__': 44 print 'mythlog can only be used as a module' -
bindings/python/mythtv/mythdb.py
1 #!/usr/bin/python 2 3 """ 4 Provides a class giving access to the MythTV database. 5 """ 6 7 # vim:ts=4 sw=4 nowrap: 8 9 import os 10 import sys 11 import shlex 12 import code 13 import getopt 14 from datetime import datetime 15 16 from mythlog import * 17 18 # create logging object 19 log = MythLog(INFO, '%(levelname)s - %(message)s', 'mythdb') 20 21 # check for dependency 22 try: 23 import MySQLdb 24 except: 25 log.Msg(CRITICAL, "MySQLdb (python-mysqldb) is required but is not found.") 26 sys.exit(1) 27 28 class MythDB: 29 """ 30 A connection to the mythtv database. 31 """ 32 def __init__(self, args=None): 33 # Setup connection variables 34 dbconn = { 35 'host' : None, 36 'name' : None, 37 'user' : None, 38 'pass' : None 39 } 40 41 # Try to read the mysql.txt file used by MythTV. 42 # Order taken from libs/libmyth/mythcontext.cpp 43 config_files = [ 44 '/usr/local/share/mythtv/mysql.txt', 45 '/usr/share/mythtv/mysql.txt', 46 '/usr/local/etc/mythtv/mysql.txt', 47 '/etc/mythtv/mysql.txt', 48 os.path.expanduser('~/.mythtv/mysql.txt'), 49 ] 50 if 'MYTHCONFDIR' in os.environ: 51 config_locations.append('%s/mysql.txt' % os.environ['MYTHCONFDIR']) 52 53 found_config = False 54 for config_file in config_files: 55 try: 56 config = shlex.shlex(open(config_file)) 57 config.wordchars += "." 58 except: 59 continue 60 61 dbconn['host'] = None 62 dbconn['name'] = None 63 dbconn['user'] = None 64 dbconn['pass'] = None 65 token = config.get_token() 66 while token != config.eof and not found_config: 67 if token == "DBHostName": 68 if config.get_token() == "=": 69 dbconn['host'] = config.get_token() 70 elif token == "DBName": 71 if config.get_token() == "=": 72 dbconn['name'] = config.get_token() 73 elif token == "DBUserName": 74 if config.get_token() == "=": 75 dbconn['user'] = config.get_token() 76 elif token == "DBPassword": 77 if config.get_token() == "=": 78 dbconn['pass'] = config.get_token() 79 token = config.get_token() 80 if dbconn['host'] != None and dbconn['name'] != None and dbconn['user'] != None and dbconn['pass'] != None: 81 log.Msg(INFO, 'Using config %s', config_file) 82 found_config = True 83 break 84 85 # Overrides from command line parameters 86 try: 87 opts, args = getopt.getopt(args, '', ['dbhost=', 'user=', 'pass=', 'database=']) 88 for o, a in opts: 89 if o == '--dbhost': 90 dbconn['host'] = a 91 if o == '--user': 92 dbconn['user'] = a 93 if o == '--pass': 94 dbconn['pass'] = a 95 if o == '--database': 96 dbconn['name'] = a 97 except: 98 pass 99 100 if not dbconn['host'] and not found_config: 101 raise MythError('Unable to find MythTV configuration file') 102 103 try: 104 self.db = MySQLdb.connect(user=dbconn['user'], host=dbconn['host'], passwd=dbconn['pass'], db=dbconn['name']) 105 log.Msg(INFO, 'DB Connection info (host:%s, name:%s, user:%s, pass:%s)', dbconn['host'], dbconn['name'], dbconn['user'], dbconn['pass']) 106 except: 107 raise MythError('Connection failed for \'%s\'@\'%s\' to database %s using password %s' % (dbconn['user'], dbconn['host'], dbconn['name'], dbconn['pass'])) 108 109 def getAllSettings(self, hostname=None): 110 """ 111 Returns values for all settings. 112 113 Returns None if there are no settings. If multiple rows are 114 found (multiple hostnames), returns the value of the first one. 115 """ 116 log.Msg(DEBUG, 'Retrieving all setting for host %s', hostname) 117 c = self.db.cursor() 118 if hostname is None: 119 c.execute(""" 120 SELECT value, data 121 FROM settings 122 WHERE hostname IS NULL""") 123 else: 124 c.execute(""" 125 SELECT value, data 126 FROM settings 127 WHERE hostname LIKE('%s%%')""" % 128 (hostname) 129 ) 130 rows = c.fetchall() 131 c.close() 132 133 if rows: 134 return rows 135 else: 136 return None 137 138 def getSetting(self, value, hostname=None): 139 """ 140 Returns the value for the given MythTV setting. 141 142 Returns None if the setting was not found. If multiple rows are 143 found (multiple hostnames), returns the value of the first one. 144 """ 145 log.Msg(DEBUG, 'Looking for setting %s for host %s', value, hostname) 146 c = self.db.cursor() 147 if hostname is None: 148 c.execute(""" 149 SELECT data 150 FROM settings 151 WHERE value LIKE('%s') AND hostname IS NULL LIMIT 1""" % 152 (value)) 153 else: 154 c.execute(""" 155 SELECT data 156 FROM settings 157 WHERE value LIKE('%s') AND hostname LIKE('%s%%') LIMIT 1""" % 158 (value, hostname)) 159 row = c.fetchone() 160 c.close() 161 162 if row: 163 return row[0] 164 else: 165 return None 166 167 def cursor(self): 168 return self.db.cursor() 169 170 if __name__ == '__main__': 171 banner = "'mdb' is a MythDB instance." 172 try: 173 import readline, rlcompleter 174 except: 175 pass 176 else: 177 readline.parse_and_bind("tab: complete") 178 banner = banner + " TAB completion is available." 179 mdb = MythDB(sys.argv[1:]) 180 namespace = globals().copy() 181 namespace.update(locals()) 182 code.InteractiveConsole(namespace).interact(banner) -
bindings/bindings.pro
6 6 using_bindings_perl { 7 7 SUBDIRS+=perl 8 8 } 9 10 using_bindings_python { 11 SUBDIRS+=python 12 }