From da64e336d79b01122f55ffea3526abb3b23fb054 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 26 Oct 2009 21:12:57 +0000 Subject: [PATCH 1/7] allow sorts on both grids --- pyfpdb/GuiPlayerStats.py | 94 ++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 42 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 1faa40c5..8b0b7fc3 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -41,7 +41,8 @@ class GuiPlayerStats (threading.Thread): self.main_window = mainwin self.sql = querylist - self.liststore = None + self.liststore = [] # gtk.ListStore[] stores the contents of the grids + self.listcols = [] # gtk.TreeViewColumn[][] stores the columns in the grids self.MYSQL_INNODB = 2 self.PGSQL = 3 @@ -162,6 +163,8 @@ class GuiPlayerStats (threading.Thread): def refreshStats(self, widget, data): try: self.stats_vbox.destroy() except AttributeError: pass + self.liststore = [] + self.listcols = [] #self.stats_vbox = gtk.VBox(False, 0) self.stats_vbox = gtk.VPaned() self.stats_vbox.show() @@ -217,8 +220,10 @@ class GuiPlayerStats (threading.Thread): # 3rd parameter passes extra flags, currently includes: # holecards - whether to display card breakdown (True/False) # numhands - min number hands required when displaying all players - flags = [False, self.filters.getNumHands()] - self.addTable(swin, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) + # gridnum - index for grid data structures + flags = [False, self.filters.getNumHands(), 0] + self.addGrid(swin, 'playerDetailedStats', flags, playerids + ,sitenos, limits, type, seats, groups, dates) # Separator vbox2 = gtk.VBox(False, 0) @@ -236,7 +241,9 @@ class GuiPlayerStats (threading.Thread): # Detailed table flags[0] = True - self.addTable(swin, 'playerDetailedStats', flags, playerids, sitenos, limits, type, seats, groups, dates) + flags[2] = 1 + self.addGrid(swin, 'playerDetailedStats', flags, playerids + ,sitenos, limits, type, seats, groups, dates) self.db.rollback() print "Stats page displayed in %4.2f seconds" % (time() - starttime) @@ -257,11 +264,12 @@ class GuiPlayerStats (threading.Thread): return - def sortnums(self, model, iter1, iter2, n): + def sortnums(self, model, iter1, iter2, nums): try: ret = 0 - a = self.liststore.get_value(iter1, n) - b = self.liststore.get_value(iter2, n) + (n, grid) = nums + a = self.liststore[grid].get_value(iter1, n) + b = self.liststore[grid].get_value(iter2, n) if 'f' in self.cols_to_show[n][4]: try: a = float(a) except: a = 0.0 @@ -281,7 +289,7 @@ class GuiPlayerStats (threading.Thread): ret = 0 else: ret = 1 - #print "n =", n, "iter1[n] =", self.liststore.get_value(iter1,n), "iter2[n] =", self.liststore.get_value(iter2,n), "ret =", ret + #print "n =", n, "iter1[n] =", self.liststore[grid].get_value(iter1,n), "iter2[n] =", self.liststore[grid].get_value(iter2,n), "ret =", ret except: err = traceback.extract_tb(sys.exc_info()[2]) print "***sortnums error: " + str(sys.exc_info()[1]) @@ -289,18 +297,19 @@ class GuiPlayerStats (threading.Thread): return(ret) - def sortcols(self, col, n): + def sortcols(self, col, nums): try: #This doesn't actually work yet - clicking heading in top section sorts bottom section :-( - if col.get_sort_order() == gtk.SORT_ASCENDING: + (n, grid) = nums + if not col.get_sort_indicator() or col.get_sort_order() == gtk.SORT_ASCENDING: col.set_sort_order(gtk.SORT_DESCENDING) else: col.set_sort_order(gtk.SORT_ASCENDING) - self.liststore.set_sort_column_id(n, col.get_sort_order()) - self.liststore.set_sort_func(n, self.sortnums, n) - for i in xrange(len(self.listcols)): - self.listcols[i].set_sort_indicator(False) - self.listcols[n].set_sort_indicator(True) + self.liststore[grid].set_sort_column_id(n, col.get_sort_order()) + self.liststore[grid].set_sort_func(n, self.sortnums, (n,grid)) + for i in xrange(len(self.listcols[grid])): + self.listcols[grid][i].set_sort_indicator(False) + self.listcols[grid][n].set_sort_indicator(True) # use this listcols[col].set_sort_indicator(True) # to turn indicator off for other cols except: @@ -308,12 +317,12 @@ class GuiPlayerStats (threading.Thread): print "***sortcols error: " + str(sys.exc_info()[1]) print "\n".join( [e[0]+':'+str(e[1])+" "+e[2] for e in err] ) - def addTable(self, vbox, query, flags, playerids, sitenos, limits, type, seats, groups, dates): + def addGrid(self, vbox, query, flags, playerids, sitenos, limits, type, seats, groups, dates): counter = 0 row = 0 sqlrow = 0 - if not flags: holecards = False - else: holecards = flags[0] + if not flags: holecards,grid = False,0 + else: holecards,grid = flags[0],flags[2] tmp = self.sql.query[query] tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, type, seats, groups, dates) @@ -325,8 +334,9 @@ class GuiPlayerStats (threading.Thread): self.cols_to_show = [x for x in self.columns if x[colshow]] hgametypeid_idx = colnames.index('hgametypeid') - self.liststore = gtk.ListStore(*([str] * len(self.cols_to_show))) - view = gtk.TreeView(model=self.liststore) + assert len(self.liststore) == grid, "len(self.liststore)="+str(len(self.liststore))+" grid-1="+str(grid) + self.liststore.append( gtk.ListStore(*([str] * len(self.cols_to_show))) ) + view = gtk.TreeView(model=self.liststore[grid]) view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) #vbox.pack_start(view, expand=False, padding=3) vbox.add(view) @@ -335,7 +345,8 @@ class GuiPlayerStats (threading.Thread): textcell50.set_property('xalign', 0.5) numcell = gtk.CellRendererText() numcell.set_property('xalign', 1.0) - self.listcols = [] + assert len(self.listcols) == grid + self.listcols.append( [] ) # Create header row eg column: ("game", True, "Game", 0.0, "%s") for col, column in enumerate(self.cols_to_show): @@ -343,31 +354,30 @@ class GuiPlayerStats (threading.Thread): s = [x for x in self.columns if x[colalias] == 'hand'][0][colheading] else: s = column[colheading] - self.listcols.append(gtk.TreeViewColumn(s)) - view.append_column(self.listcols[col]) + self.listcols[grid].append(gtk.TreeViewColumn(s)) + view.append_column(self.listcols[grid][col]) if column[colformat] == '%s': if column[colxalign] == 0.0: - self.listcols[col].pack_start(textcell, expand=True) - self.listcols[col].add_attribute(textcell, 'text', col) + self.listcols[grid][col].pack_start(textcell, expand=True) + self.listcols[grid][col].add_attribute(textcell, 'text', col) else: - self.listcols[col].pack_start(textcell50, expand=True) - self.listcols[col].add_attribute(textcell50, 'text', col) - self.listcols[col].set_expand(True) + self.listcols[grid][col].pack_start(textcell50, expand=True) + self.listcols[grid][col].add_attribute(textcell50, 'text', col) + self.listcols[grid][col].set_expand(True) else: - self.listcols[col].pack_start(numcell, expand=True) - self.listcols[col].add_attribute(numcell, 'text', col) - self.listcols[col].set_expand(True) - #self.listcols[col].set_alignment(column[colxalign]) # no effect? - if holecards: - self.listcols[col].set_clickable(True) - self.listcols[col].connect("clicked", self.sortcols, col) - if col == 0: - self.listcols[col].set_sort_order(gtk.SORT_DESCENDING) - self.listcols[col].set_sort_indicator(True) + self.listcols[grid][col].pack_start(numcell, expand=True) + self.listcols[grid][col].add_attribute(numcell, 'text', col) + self.listcols[grid][col].set_expand(True) + #self.listcols[grid][col].set_alignment(column[colxalign]) # no effect? + self.listcols[grid][col].set_clickable(True) + self.listcols[grid][col].connect("clicked", self.sortcols, (col,grid)) + if col == 0: + self.listcols[grid][col].set_sort_order(gtk.SORT_DESCENDING) + self.listcols[grid][col].set_sort_indicator(True) if column[coltype] == 'cash': - self.listcols[col].set_cell_data_func(numcell, self.ledger_style_render_func) + self.listcols[grid][col].set_cell_data_func(numcell, self.ledger_style_render_func) else: - self.listcols[col].set_cell_data_func(numcell, self.reset_style_render_func) + self.listcols[grid][col].set_cell_data_func(numcell, self.reset_style_render_func) rows = len(result) # +1 for title row @@ -408,12 +418,12 @@ class GuiPlayerStats (threading.Thread): treerow.append(column[colformat] % value) else: treerow.append(' ') - iter = self.liststore.append(treerow) + iter = self.liststore[grid].append(treerow) sqlrow += 1 row += 1 vbox.show_all() - #end def addTable(self, query, vars, playerids, sitenos, limits, type, seats, groups, dates): + #end def addGrid(self, query, vars, playerids, sitenos, limits, type, seats, groups, dates): def refineQuery(self, query, flags, playerids, sitenos, limits, type, seats, groups, dates): having = '' From 6b280d7db90d9fd87dd4dee1fee8bd0a39cfc333 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 26 Oct 2009 21:38:04 +0000 Subject: [PATCH 2/7] stop warning message from set_cell_data_func --- pyfpdb/GuiPlayerStats.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 8b0b7fc3..8b5f1f05 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -360,14 +360,17 @@ class GuiPlayerStats (threading.Thread): if column[colxalign] == 0.0: self.listcols[grid][col].pack_start(textcell, expand=True) self.listcols[grid][col].add_attribute(textcell, 'text', col) + cellrend = textcell else: self.listcols[grid][col].pack_start(textcell50, expand=True) self.listcols[grid][col].add_attribute(textcell50, 'text', col) + cellrend = textcell50 self.listcols[grid][col].set_expand(True) else: self.listcols[grid][col].pack_start(numcell, expand=True) self.listcols[grid][col].add_attribute(numcell, 'text', col) self.listcols[grid][col].set_expand(True) + cellrend = numcell #self.listcols[grid][col].set_alignment(column[colxalign]) # no effect? self.listcols[grid][col].set_clickable(True) self.listcols[grid][col].connect("clicked", self.sortcols, (col,grid)) @@ -377,7 +380,7 @@ class GuiPlayerStats (threading.Thread): if column[coltype] == 'cash': self.listcols[grid][col].set_cell_data_func(numcell, self.ledger_style_render_func) else: - self.listcols[grid][col].set_cell_data_func(numcell, self.reset_style_render_func) + self.listcols[grid][col].set_cell_data_func(cellrend, self.reset_style_render_func) rows = len(result) # +1 for title row From fabec1604a21e429307dc312c7d459b1948157b7 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 26 Oct 2009 21:59:41 +0000 Subject: [PATCH 3/7] stop warnings when importing from fpdb.py --- pyfpdb/GuiSessionViewer.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pyfpdb/GuiSessionViewer.py b/pyfpdb/GuiSessionViewer.py index 2013f8a2..7695cf73 100755 --- a/pyfpdb/GuiSessionViewer.py +++ b/pyfpdb/GuiSessionViewer.py @@ -24,18 +24,22 @@ import os import traceback from time import time, strftime, localtime try: + calluse = not 'matplotlib' in sys.modules import matplotlib - matplotlib.use('GTK') + if calluse: + matplotlib.use('GTK') from matplotlib.figure import Figure from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas from matplotlib.backends.backend_gtkagg import NavigationToolbar2GTKAgg as NavigationToolbar from matplotlib.finance import candlestick2 - from numpy import diff, nonzero, sum, cumsum, max, mina + from numpy import diff, nonzero, sum, cumsum, max, min # from matplotlib.dates import DateFormatter, WeekdayLocator, HourLocator, \ # DayLocator, MONDAY, timezone except: + err = traceback.extract_tb(sys.exc_info()[2])[-1] + print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) print """Failed to load numpy in Session Viewer""" print """This is of no consequence as the module currently doesn't do anything.""" From d2cf8e9bc94f311724136c9d631849acb87c1664 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 26 Oct 2009 22:26:22 +0000 Subject: [PATCH 4/7] attempt at making system tray icon go away when quitting --- pyfpdb/fpdb.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index fe2ddd39..ef67749d 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -516,6 +516,8 @@ class fpdb: print "Quitting normally" #check if current settings differ from profile, if so offer to save or abort self.db.disconnect() + # hide icon as it doesn't go away immediately in Windows - is this ok in Linux Eric? + self.statusIcon.set_visible(False) gtk.main_quit() def release_global_lock(self): From 7bd7b5b053af4d4f31bf9121aa07ef39b2395f4d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 Oct 2009 11:01:45 -0400 Subject: [PATCH 5/7] add todo to remind me --- pyfpdb/fpdb_db.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 986c747f..da0bbbe7 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -77,10 +77,11 @@ class fpdb_db: import MySQLdb if use_pool: MySQLdb = pool.manage(MySQLdb, pool_size=5) - try: - self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) - except: - raise FpdbMySQLFailedError("MySQL connection failed") +# try: + self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) + #TODO: Add port option +# except: +# raise FpdbMySQLFailedError("MySQL connection failed") elif backend==fpdb_db.PGSQL: import psycopg2 import psycopg2.extensions From dcbc7d72038726513c5e42b948a6162f90ea03fb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 Oct 2009 17:40:25 -0400 Subject: [PATCH 6/7] fix format of line --- pyfpdb/fpdb_db.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index da0bbbe7..3dc77a51 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -78,7 +78,7 @@ class fpdb_db: if use_pool: MySQLdb = pool.manage(MySQLdb, pool_size=5) # try: - self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True) + self.db = MySQLdb.connect(host=host, user=user, passwd=password, db=database, use_unicode=True) #TODO: Add port option # except: # raise FpdbMySQLFailedError("MySQL connection failed") From 02e8154710d109be3126c6958570350113f174bf Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 Oct 2009 19:53:31 -0400 Subject: [PATCH 7/7] remove error trap on read_stdin() - please fix bugs instead of relying on error trap some reformatting in Tables.py, as well as some new debug prints to deal with some potential issues. Add code to deal with potential problems in Win x64, that are biting me at random. Not finished, but the problems stopped happening so can't continue. --- pyfpdb/HUD_main.py | 162 ++++++++++++++++++++++----------------------- pyfpdb/Tables.py | 52 ++++++++++----- 2 files changed, 114 insertions(+), 100 deletions(-) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index a0f152b7..8ccc194e 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -189,99 +189,95 @@ class HUD_main(object): # be passed to HUDs for use in the gui thread. HUD objects should not # need their own access to the database, but should open their own # if it is required. - try: - self.db_connection = Database.Database(self.config) - tourny_finder = re.compile('(\d+) (\d+)') - -# get hero's screen names and player ids - self.hero, self.hero_ids = {}, {} - for site in self.config.get_supported_sites(): - result = self.db_connection.get_site_id(site) - if result: - site_id = result[0][0] - self.hero[site_id] = self.config.supported_sites[site].screen_name - self.hero_ids[site_id] = self.db_connection.get_player_id(self.config, site, self.hero[site_id]) + self.db_connection = Database.Database(self.config) + tourny_finder = re.compile('(\d+) (\d+)') - while 1: # wait for a new hand number on stdin - new_hand_id = sys.stdin.readline() - new_hand_id = string.rstrip(new_hand_id) - if new_hand_id == "": # blank line means quit - self.destroy() - break # this thread is not always killed immediately with gtk.main_quit() +# get hero's screen names and player ids + self.hero, self.hero_ids = {}, {} + for site in self.config.get_supported_sites(): + result = self.db_connection.get_site_id(site) + if result: + site_id = result[0][0] + self.hero[site_id] = self.config.supported_sites[site].screen_name + self.hero_ids[site_id] = self.db_connection.get_player_id(self.config, site, self.hero[site_id]) + + while 1: # wait for a new hand number on stdin + new_hand_id = sys.stdin.readline() + new_hand_id = string.rstrip(new_hand_id) + if new_hand_id == "": # blank line means quit + self.destroy() + break # this thread is not always killed immediately with gtk.main_quit() # get basic info about the new hand from the db # if there is a db error, complain, skip hand, and proceed - try: - (table_name, max, poker_game, type, site_id) = self.db_connection.get_table_name(new_hand_id) + try: + (table_name, max, poker_game, type, site_id) = self.db_connection.get_table_name(new_hand_id) - cards = self.db_connection.get_cards(new_hand_id) - comm_cards = self.db_connection.get_common_cards(new_hand_id) - if comm_cards != {}: # stud! - cards['common'] = comm_cards['common'] - except Exception, err: - err = traceback.extract_tb(sys.exc_info()[2])[-1] - print "db error: skipping "+str(new_hand_id)+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) - if new_hand_id: # new_hand_id is none if we had an error prior to the store - sys.stderr.write("Database error %s in hand %d. Skipping.\n" % (err, int(new_hand_id))) + cards = self.db_connection.get_cards(new_hand_id) + comm_cards = self.db_connection.get_common_cards(new_hand_id) + if comm_cards != {}: # stud! + cards['common'] = comm_cards['common'] + except Exception, err: + err = traceback.extract_tb(sys.exc_info()[2])[-1] + print "db error: skipping "+str(new_hand_id)+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) + if new_hand_id: # new_hand_id is none if we had an error prior to the store + sys.stderr.write("Database error %s in hand %d. Skipping.\n" % (err, int(new_hand_id))) + continue + + if type == "tour": # hand is from a tournament + mat_obj = tourny_finder.search(table_name) + if mat_obj: + (tour_number, tab_number) = mat_obj.group(1, 2) + temp_key = tour_number + else: # tourney, but can't get number and table + print "could not find tournament: skipping " + #sys.stderr.write("Could not find tournament %d in hand %d. Skipping.\n" % (int(tour_number), int(new_hand_id))) continue - - if type == "tour": # hand is from a tournament - mat_obj = tourny_finder.search(table_name) - if mat_obj: - (tour_number, tab_number) = mat_obj.group(1, 2) - temp_key = tour_number - else: # tourney, but can't get number and table - print "could not find tournament: skipping " - #sys.stderr.write("Could not find tournament %d in hand %d. Skipping.\n" % (int(tour_number), int(new_hand_id))) - continue - - else: - temp_key = table_name + + else: + temp_key = table_name # Update an existing HUD - if temp_key in self.hud_dict: - try: - # get stats using hud's specific params - self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] - , self.hud_dict[temp_key].hud_params['h_hud_days']) - stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_dict[temp_key].hud_params, self.hero_ids[site_id]) - except: - err = traceback.extract_tb(sys.exc_info()[2])[-1] - print "db get_stats error: skipping "+str(new_hand_id)+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) - if new_hand_id: # new_hand_id is none if we had an error prior to the store - sys.stderr.write("Database get_stats error %s in hand %d. Skipping.\n" % (err, int(new_hand_id))) - continue - self.hud_dict[temp_key].stat_dict = stat_dict - self.hud_dict[temp_key].cards = cards - [aw.update_data(new_hand_id, self.db_connection) for aw in self.hud_dict[temp_key].aux_windows] - self.update_HUD(new_hand_id, temp_key, self.config) - + if temp_key in self.hud_dict: + try: + # get stats using hud's specific params + self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] + , self.hud_dict[temp_key].hud_params['h_hud_days']) + stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_dict[temp_key].hud_params, self.hero_ids[site_id]) + except: + err = traceback.extract_tb(sys.exc_info()[2])[-1] + print "db get_stats error: skipping "+str(new_hand_id)+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) + if new_hand_id: # new_hand_id is none if we had an error prior to the store + sys.stderr.write("Database get_stats error %s in hand %d. Skipping.\n" % (err, int(new_hand_id))) + continue + self.hud_dict[temp_key].stat_dict = stat_dict + self.hud_dict[temp_key].cards = cards + [aw.update_data(new_hand_id, self.db_connection) for aw in self.hud_dict[temp_key].aux_windows] + self.update_HUD(new_hand_id, temp_key, self.config) + # Or create a new HUD + else: + try: + # get stats using default params + self.db_connection.init_hud_stat_vars( self.hud_params['hud_days'], self.hud_params['h_hud_days'] ) + stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params, self.hero_ids[site_id]) + except: + err = traceback.extract_tb(sys.exc_info()[2])[-1] + print "db get_stats error: skipping "+str(new_hand_id)+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) + if new_hand_id: # new_hand_id is none if we had an error prior to the store + sys.stderr.write("Database get_stats error %s in hand %d. Skipping.\n" % (err, int(new_hand_id))) + continue + if type == "tour": + tablewindow = Tables.discover_tournament_table(self.config, tour_number, tab_number) else: - try: - # get stats using default params - self.db_connection.init_hud_stat_vars( self.hud_params['hud_days'], self.hud_params['h_hud_days'] ) - stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params, self.hero_ids[site_id]) - except: - err = traceback.extract_tb(sys.exc_info()[2])[-1] - print "db get_stats error: skipping "+str(new_hand_id)+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) - if new_hand_id: # new_hand_id is none if we had an error prior to the store - sys.stderr.write("Database get_stats error %s in hand %d. Skipping.\n" % (err, int(new_hand_id))) - continue - if type == "tour": - tablewindow = Tables.discover_tournament_table(self.config, tour_number, tab_number) - else: - tablewindow = Tables.discover_table_by_name(self.config, table_name) - if tablewindow == None: + tablewindow = Tables.discover_table_by_name(self.config, table_name) + if tablewindow == None: # If no client window is found on the screen, complain and continue - if type == "tour": - table_name = "%s %s" % (tour_number, tab_number) - sys.stderr.write("table name "+table_name+" not found, skipping.\n") - else: - self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, type, stat_dict, cards) - self.db_connection.connection.rollback() - except: - err = traceback.extract_tb(sys.exc_info()[2])[-1] - print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1]) + if type == "tour": + table_name = "%s %s" % (tour_number, tab_number) + sys.stderr.write("table name "+table_name+" not found, skipping.\n") + else: + self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, type, stat_dict, cards) + self.db_connection.connection.rollback() if __name__== "__main__": diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py index e725d5b8..46addabc 100755 --- a/pyfpdb/Tables.py +++ b/pyfpdb/Tables.py @@ -238,7 +238,8 @@ def discover_nt_by_name(c, tablename): try: # maybe it's better to make global titles[hwnd] decoding? # this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html - if not tablename.lower() in titles[hwnd].decode(LOCALE_ENCODING).lower(): continue + if not tablename.lower() in titles[hwnd].decode(LOCALE_ENCODING).lower(): + continue except: continue if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window @@ -246,8 +247,8 @@ def discover_nt_by_name(c, tablename): if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows if ' - Table ' in titles[hwnd]: continue # Absolute table Chat window.. sigh. TODO: Can we tell what site we're trying to discover for somehow in here, so i can limit this check just to AP searches? temp = decode_windows(c, titles[hwnd], hwnd) - #print "attach to window", temp - return decode_windows(c, titles[hwnd], hwnd) + print "attach to window", temp + return temp return None def discover_nt_tournament(c, tour_number, tab_number): @@ -257,9 +258,12 @@ def discover_nt_tournament(c, tour_number, tab_number): titles ={} win32gui.EnumWindows(win_enum_handler, titles) for hwnd in titles: - if 'Chat:' in titles[hwnd]: continue # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows - if 'History for table:' in titles[hwnd]: continue # Everleaf Network HH viewer window - if 'HUD:' in titles[hwnd]: continue # FPDB HUD window + # Some sites (FTP? PS? Others?) have seperable or seperately constructed chat windows + if 'Chat:' in titles[hwnd]: continue + # Everleaf Network HH viewer window + if 'History for table:' in titles[hwnd]: continue + # FPDB HUD window + if 'HUD:' in titles[hwnd]: continue if re.search(search_string, titles[hwnd]): return decode_windows(c, titles[hwnd], hwnd) @@ -268,22 +272,34 @@ def discover_nt_tournament(c, tour_number, tab_number): def get_nt_exe(hwnd): """Finds the name of the executable that the given window handle belongs to.""" - # Request privileges to enable "debug process", so we can later use PROCESS_VM_READ, retardedly required to GetModuleFileNameEx() + # Request privileges to enable "debug process", so we can later use + # PROCESS_VM_READ, retardedly required to GetModuleFileNameEx() priv_flags = win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY - hToken = win32security.OpenProcessToken (win32api.GetCurrentProcess(), priv_flags) + hToken = win32security.OpenProcessToken (win32api.GetCurrentProcess(), + priv_flags) # enable "debug process" - privilege_id = win32security.LookupPrivilegeValue (None, win32security.SE_DEBUG_NAME) - old_privs = win32security.AdjustTokenPrivileges (hToken, 0, [(privilege_id, win32security.SE_PRIVILEGE_ENABLED)]) + privilege_id = win32security.LookupPrivilegeValue(None, + win32security.SE_DEBUG_NAME) + old_privs = win32security.AdjustTokenPrivileges(hToken, 0, + [(privilege_id, + win32security.SE_PRIVILEGE_ENABLED)]) # Open the process, and query it's filename processid = win32process.GetWindowThreadProcessId(hwnd) - pshandle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, processid[1]) - exename = win32process.GetModuleFileNameEx(pshandle, 0) - - # clean up - win32api.CloseHandle(pshandle) - win32api.CloseHandle(hToken) - + pshandle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | + win32con.PROCESS_VM_READ, False, + processid[1]) + try: + exename = win32process.GetModuleFileNameEx(pshandle, 0) + except pywintypes.error: + # insert code to call GetProcessImageName if we can find it.. + # returning None from here will hopefully break all following code + exename = None + finally: + # clean up + win32api.CloseHandle(pshandle) + win32api.CloseHandle(hToken) + return exename def decode_windows(c, title, hwnd): @@ -305,6 +321,8 @@ def decode_windows(c, title, hwnd): info['width'] = int( width ) - 2*b_width info['height'] = int( height ) - b_width - tb_height info['exe'] = get_nt_exe(hwnd) + print "get_nt_exe returned ", info['exe'] + # TODO: 'width' here is all sorts of screwed up. title_bits = re.split(' - ', info['title']) info['name'] = title_bits[0]