Merge branch 'master' of git://git.assembla.com/fpdb-sql

This commit is contained in:
Worros 2010-02-07 19:56:46 +08:00
commit 55cb03b4f2
9 changed files with 151 additions and 60 deletions

View File

@ -42,6 +42,9 @@ def to_utf8(s):
except UnicodeDecodeError: except UnicodeDecodeError:
sys.stderr.write('Could not convert: "%s"\n' % s) sys.stderr.write('Could not convert: "%s"\n' % s)
raise raise
except UnicodeEncodeError:
sys.stderr.write('Could not encode: "%s"\n' % s)
raise
except TypeError: # TypeError is raised when we give unicode() an already encoded string except TypeError: # TypeError is raised when we give unicode() an already encoded string
return s return s
@ -54,13 +57,21 @@ def to_db_utf8(s):
except UnicodeDecodeError: except UnicodeDecodeError:
sys.stderr.write('Could not convert: "%s"\n' % s) sys.stderr.write('Could not convert: "%s"\n' % s)
raise raise
except UnicodeEncodeError:
sys.stderr.write('Could not encode: "%s"\n' % s)
raise
def to_gui(s): def to_gui(s):
if not_needed3: return s if not_needed3: return s
try: try:
(_out, _len) = encoder_to_sys.encode(s) # we usually don't want to use 'replace' but this is only for displaying
# in the gui so it doesn't matter if names are missing an accent or two
(_out, _len) = encoder_to_sys.encode(s, 'replace')
return _out return _out
except UnicodeDecodeError: except UnicodeDecodeError:
sys.stderr.write('Could not convert: "%s"\n' % s) sys.stderr.write('Could not convert: "%s"\n' % s)
raise raise
except UnicodeEncodeError:
sys.stderr.write('Could not encode: "%s"\n' % s)
raise

View File

@ -380,8 +380,8 @@ class Database:
import sqlite3 import sqlite3
if use_pool: if use_pool:
sqlite3 = pool.manage(sqlite3, pool_size=1) sqlite3 = pool.manage(sqlite3, pool_size=1)
else: #else:
log.warning("SQLite won't work well without 'sqlalchemy' installed.") # log.warning("SQLite won't work well without 'sqlalchemy' installed.")
if database != ":memory:": if database != ":memory:":
if not os.path.isdir(self.config.dir_database): if not os.path.isdir(self.config.dir_database):

View File

@ -194,8 +194,11 @@ class GuiAutoImport (threading.Thread):
widget.set_label(u' _Stop Autoimport ') widget.set_label(u' _Stop Autoimport ')
if self.pipe_to_hud is None: if self.pipe_to_hud is None:
if os.name == 'nt': if os.name == 'nt':
path = sys.path[0].replace('\\','\\\\') if sys.argv[0] == 'fpdb.exe':
command = 'python "'+path+'\\HUD_main.py" ' + self.settings['cl_options'] command = 'HUD_main.exe'
else:
path = sys.path[0].replace('\\','\\\\')
command = 'python "'+path+'\\HUD_main.py" ' + self.settings['cl_options']
bs = 0 bs = 0
else: else:
command = os.path.join(sys.path[0], 'HUD_main.py') command = os.path.join(sys.path[0], 'HUD_main.py')
@ -208,7 +211,8 @@ class GuiAutoImport (threading.Thread):
universal_newlines=True) universal_newlines=True)
except: except:
err = traceback.extract_tb(sys.exc_info()[2])[-1] err = traceback.extract_tb(sys.exc_info()[2])[-1]
self.addText( "\n*** GuiAutoImport Error opening pipe: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])) #self.addText( "\n*** GuiAutoImport Error opening pipe: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]))
self.addText( "\n*** GuiAutoImport Error opening pipe: " + traceback.format_exc() )
else: else:
for site in self.input_settings: for site in self.input_settings:
self.importer.addImportDirectory(self.input_settings[site][0], True, site, self.input_settings[site][1]) self.importer.addImportDirectory(self.input_settings[site][0], True, site, self.input_settings[site][1])

View File

@ -69,17 +69,16 @@ class HUD_main(object):
# This class mainly provides state for controlling the multiple HUDs. # This class mainly provides state for controlling the multiple HUDs.
def __init__(self, db_name = 'fpdb'): def __init__(self, db_name = 'fpdb'):
try: print "\nHUD_main: starting ..."
print "HUD_main: starting ..." self.db_name = db_name
self.db_name = db_name self.config = Configuration.Config(file=options.config, dbname=db_name)
self.config = Configuration.Config(file=options.config, dbname=db_name) log = Configuration.get_logger("logging.conf", "hud", log_dir=self.config.dir_log)
log = Configuration.get_logger("logging.conf", "hud", log_dir=self.config.dir_log) log.info("HUD_main starting: using db name = %s" % (db_name))
log.info("HUD_main starting")
log.info("Using db name = %s" % (db_name))
try:
if not options.errorsToConsole: if not options.errorsToConsole:
fileName = os.path.join(self.config.dir_log, 'HUD-errors.txt') fileName = os.path.join(self.config.dir_log, 'HUD-errors.txt')
print "Note: error output is being diverted to\n"+fileName \ print "Note: error output is being diverted to:\n"+fileName \
+ "\nAny major error will be reported there _only_.\n" + "\nAny major error will be reported there _only_.\n"
errorFile = open(fileName, 'w', 0) errorFile = open(fileName, 'w', 0)
sys.stderr = errorFile sys.stderr = errorFile
@ -101,8 +100,9 @@ class HUD_main(object):
self.main_window.set_title("HUD Main Window") self.main_window.set_title("HUD Main Window")
self.main_window.show_all() self.main_window.show_all()
except: except:
log.debug("commit "+str(i)+" failed: info=" + str(sys.exc_info()) log.error( "*** Exception in HUD_main.init() *** " )
+ " value=" + str(sys.exc_value)) for e in traceback.format_tb(sys.exc_info()[2]):
log.error(e)
def destroy(self, *args): # call back for terminating the main eventloop def destroy(self, *args): # call back for terminating the main eventloop
@ -139,8 +139,9 @@ class HUD_main(object):
self.hud_dict[table_name].update(new_hand_id, self.config) self.hud_dict[table_name].update(new_hand_id, self.config)
self.hud_dict[table_name].reposition_windows() self.hud_dict[table_name].reposition_windows()
except: except:
print "*** Exception in HUD_main::idle_func() *** " log.error( "*** Exception in HUD_main::idle_func() *** " )
traceback.print_stack() for e in traceback.format_tb(sys.exc_info()[2]):
log.error(e)
finally: finally:
gtk.gdk.threads_leave() gtk.gdk.threads_leave()
return False return False
@ -247,8 +248,8 @@ class HUD_main(object):
try: try:
self.hud_dict[temp_key].stat_dict = stat_dict self.hud_dict[temp_key].stat_dict = stat_dict
except KeyError: # HUD instance has been killed off, key is stale except KeyError: # HUD instance has been killed off, key is stale
sys.stderr.write('hud_dict[%s] was not found\n' % temp_key) log.error('hud_dict[%s] was not found\n' % temp_key)
sys.stderr.write('will not send hand\n') log.error('will not send hand\n')
# Unlocks table, copied from end of function # Unlocks table, copied from end of function
self.db_connection.connection.rollback() self.db_connection.connection.rollback()
return return
@ -282,7 +283,7 @@ class HUD_main(object):
# If no client window is found on the screen, complain and continue # If no client window is found on the screen, complain and continue
if type == "tour": if type == "tour":
table_name = "%s %s" % (tour_number, tab_number) table_name = "%s %s" % (tour_number, tab_number)
# sys.stderr.write("HUD create: table name "+table_name+" not found, skipping.\n") # log.error("HUD create: table name "+table_name+" not found, skipping.\n")
log.error("HUD create: table name %s not found, skipping." % table_name) log.error("HUD create: table name %s not found, skipping." % table_name)
else: else:
tablewindow.max = max tablewindow.max = max
@ -291,7 +292,7 @@ class HUD_main(object):
if hasattr(tablewindow, 'number'): if hasattr(tablewindow, 'number'):
self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, type, stat_dict, cards) self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, type, stat_dict, cards)
else: else:
sys.stderr.write('Table "%s" no longer exists\n' % table_name) log.error('Table "%s" no longer exists\n' % table_name)
t6 = time.time() t6 = time.time()
log.info("HUD_main.read_stdin: hand read in %4.3f seconds (%4.3f,%4.3f,%4.3f,%4.3f,%4.3f,%4.3f)" log.info("HUD_main.read_stdin: hand read in %4.3f seconds (%4.3f,%4.3f,%4.3f,%4.3f,%4.3f,%4.3f)"

View File

@ -26,6 +26,10 @@ Create and manage the hud overlays.
import os import os
import sys import sys
import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings:
log = logging.getLogger("hud")
# pyGTK modules # pyGTK modules
import pygtk import pygtk
import gtk import gtk
@ -365,7 +369,7 @@ class Hud:
self.create(*self.creation_attrs) self.create(*self.creation_attrs)
self.update(self.hand, self.config) self.update(self.hand, self.config)
except Exception, e: except Exception, e:
print "Exception:",str(e) log.error("Exception:",str(e))
pass pass
def set_aggregation(self, widget, val): def set_aggregation(self, widget, val):
@ -377,7 +381,7 @@ class Hud:
if self.hud_params['h_agg_bb_mult'] != num \ if self.hud_params['h_agg_bb_mult'] != num \
and getattr(self, 'h_aggBBmultItem'+str(num)).get_active(): and getattr(self, 'h_aggBBmultItem'+str(num)).get_active():
print 'set_player_aggregation', num log.debug('set_player_aggregation', num)
self.hud_params['h_agg_bb_mult'] = num self.hud_params['h_agg_bb_mult'] = num
for mult in ('1', '2', '3', '10', '10000'): for mult in ('1', '2', '3', '10', '10000'):
if mult != str(num): if mult != str(num):
@ -388,7 +392,7 @@ class Hud:
if self.hud_params['agg_bb_mult'] != num \ if self.hud_params['agg_bb_mult'] != num \
and getattr(self, 'aggBBmultItem'+str(num)).get_active(): and getattr(self, 'aggBBmultItem'+str(num)).get_active():
print 'set_opponent_aggregation', num log.debug('set_opponent_aggregation', num)
self.hud_params['agg_bb_mult'] = num self.hud_params['agg_bb_mult'] = num
for mult in ('1', '2', '3', '10', '10000'): for mult in ('1', '2', '3', '10', '10000'):
if mult != str(num): if mult != str(num):
@ -415,7 +419,7 @@ class Hud:
self.hud_params[param] = 'E' self.hud_params[param] = 'E'
getattr(self, prefix+'seatsStyleOptionA').set_active(False) getattr(self, prefix+'seatsStyleOptionA').set_active(False)
getattr(self, prefix+'seatsStyleOptionC').set_active(False) getattr(self, prefix+'seatsStyleOptionC').set_active(False)
print "setting self.hud_params[%s] = %s" % (param, style) log.debug("setting self.hud_params[%s] = %s" % (param, style))
def set_hud_style(self, widget, val): def set_hud_style(self, widget, val):
(player_opp, style) = val (player_opp, style) = val
@ -438,7 +442,7 @@ class Hud:
self.hud_params[param] = 'T' self.hud_params[param] = 'T'
getattr(self, prefix+'hudStyleOptionA').set_active(False) getattr(self, prefix+'hudStyleOptionA').set_active(False)
getattr(self, prefix+'hudStyleOptionS').set_active(False) getattr(self, prefix+'hudStyleOptionS').set_active(False)
print "setting self.hud_params[%s] = %s" % (param, style) log.debug("setting self.hud_params[%s] = %s" % (param, style))
def update_table_position(self): def update_table_position(self):
if os.name == 'nt': if os.name == 'nt':
@ -515,7 +519,7 @@ class Hud:
# ask each aux to save its layout back to the config object # ask each aux to save its layout back to the config object
[aux.save_layout() for aux in self.aux_windows] [aux.save_layout() for aux in self.aux_windows]
# save the config object back to the file # save the config object back to the file
print "saving new xml file" print "Updating config file"
self.config.save() self.config.save()
def adj_seats(self, hand, config): def adj_seats(self, hand, config):
@ -611,8 +615,8 @@ class Hud:
try: try:
statd = self.stat_dict[s] statd = self.stat_dict[s]
except KeyError: except KeyError:
print "KeyError at the start of the for loop in update in hud_main. How this can possibly happen is totally beyond my comprehension. Your HUD may be about to get really weird. -Eric" log.error("KeyError at the start of the for loop in update in hud_main. How this can possibly happen is totally beyond my comprehension. Your HUD may be about to get really weird. -Eric")
print "(btw, the key was ", s, " and statd is...", statd log.error("(btw, the key was ", s, " and statd is...", statd)
continue continue
try: try:
self.stat_windows[statd['seat']].player_id = statd['player_id'] self.stat_windows[statd['seat']].player_id = statd['player_id']

View File

@ -24,6 +24,10 @@ Routines for detecting and handling poker client windows for MS Windows.
# Standard Library modules # Standard Library modules
import re import re
import logging
# logging has been set up in fpdb.py or HUD_main.py, use their settings:
log = logging.getLogger("hud")
# pyGTK modules # pyGTK modules
import pygtk import pygtk
import gtk import gtk
@ -62,19 +66,19 @@ class Table(Table_Window):
try: try:
if self.window == None: if self.window == None:
print "Window %s not found. Skipping." % search_string log.error( "Window %s not found. Skipping." % search_string )
return None return None
except AttributeError: except AttributeError:
print "self.window doesn't exist? why?" log.error( "self.window doesn't exist? why?" )
return None return None
(x, y, width, height) = win32gui.GetWindowRect(hwnd) (x, y, width, height) = win32gui.GetWindowRect(hwnd)
print "x = %s y = %s width = %s height = %s" % (x, y, width, height) log.debug("x = %s y = %s width = %s height = %s" % (x, y, width, height))
self.x = int(x) + b_width self.x = int(x) + b_width
self.y = int(y) + tb_height self.y = int(y) + tb_height
self.width = width - x self.width = width - x
self.height = height - y self.height = height - y
print "x = %s y = %s width = %s height = %s" % (self.x, self.y, self.width, self.height) log.debug("x = %s y = %s width = %s height = %s" % (self.x, self.y, self.width, self.height))
#self.height = int(height) - b_width - tb_height #self.height = int(height) - b_width - tb_height
#self.width = int(width) - 2*b_width #self.width = int(width) - 2*b_width

View File

@ -906,14 +906,16 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
if not options.errorsToConsole: if not options.errorsToConsole:
fileName = os.path.join(self.config.dir_log, 'fpdb-errors.txt') fileName = os.path.join(self.config.dir_log, 'fpdb-errors.txt')
print "\nNote: error output is being diverted to fpdb-errors.txt and HUD-errors.txt in\n" \ print "\nNote: error output is being diverted to fpdb-errors.txt and HUD-errors.txt in:\n" \
+ self.config.dir_log + "Any major error will be reported there _only_.\n" + self.config.dir_log + "\nAny major error will be reported there _only_.\n"
errorFile = open(fileName, 'w', 0) errorFile = open(fileName, 'w', 0)
sys.stderr = errorFile sys.stderr = errorFile
self.statusIcon = gtk.StatusIcon() self.statusIcon = gtk.StatusIcon()
if os.path.exists(os.path.join(sys.path[0], '../gfx/fpdb-cards.png')): # use getcwd() here instead of sys.path[0] so that py2exe works:
self.statusIcon.set_from_file(os.path.join(sys.path[0], '../gfx/fpdb-cards.png')) cards = os.path.join(os.getcwd(), '..','gfx','fpdb-cards.png')
if os.path.exists(cards):
self.statusIcon.set_from_file(cards)
elif os.path.exists('/usr/share/pixmaps/fpdb-cards.png'): elif os.path.exists('/usr/share/pixmaps/fpdb-cards.png'):
self.statusIcon.set_from_file('/usr/share/pixmaps/fpdb-cards.png') self.statusIcon.set_from_file('/usr/share/pixmaps/fpdb-cards.png')
else: else:

View File

@ -22,29 +22,78 @@ Py2exe script for fpdb.
######################################################################## ########################################################################
#TODO: change GuiAutoImport so that it knows to start HUD_main.exe, when appropriate #TODO:
# include the lib needed to handle png files in mucked # include the lib needed to handle png files in mucked
# get rid of all the uneeded libraries (e.g., pyQT) # get rid of all the uneeded libraries (e.g., pyQT)
# think about an installer # think about an installer
# done: change GuiAutoImport so that it knows to start HUD_main.exe, when appropriate
#HOW TO USE this script: #HOW TO USE this script:
# #
# cd to the folder where this script is stored, usually .../pyfpdb. #- cd to the folder where this script is stored, usually .../pyfpdb.
# If there are build and dist subfolders present , delete them to get # [If there are build and dist subfolders present , delete them to get
# rid of earlier builds. # rid of earlier builds. Update: script now does this for you]
# Run the script with "py2exe_setup.py py2exe" #- Run the script with "py2exe_setup.py py2exe"
# You will frequently get messages about missing .dll files. E. g., #- You will frequently get messages about missing .dll files. E. g.,
# MSVCP90.dll. These are somewhere in your windows install, so you # MSVCP90.dll. These are somewhere in your windows install, so you
# can just copy them to your working folder. # can just copy them to your working folder. (or just assume other
# If it works, you'll have 2 new folders, build and dist. Build is # person will have them? any copyright issues with including them?)
# working space and should be deleted. Dist contains the files to be #- If it works, you'll have 3 new folders, build and dist and gfx. Build is
# distributed. Last, you must copy the etc/, lib/ and share/ folders # working space and should be deleted. Dist and gfx contain the files to be
# from your gtk/bin/ folder to the dist folder. (the whole folders, not # distributed.
# just the contents) You can (should) then prune the etc/, lib/ and #- Last, you must copy the etc/, lib/ and share/ folders from your
# share/ folders to remove components we don't need. # gtk/bin/ (just /gtk/?) folder to the dist folder. (the whole folders,
# not just the contents)
#- You can (should) then prune the etc/, lib/ and share/ folders to
# remove components we don't need.
import os
import sys
from distutils.core import setup from distutils.core import setup
import py2exe import py2exe
import glob
import matplotlib
from datetime import date
def remove_tree(top):
# Delete everything reachable from the directory named in 'top',
# assuming there are no symbolic links.
# CAUTION: This is dangerous! For example, if top == '/', it
# could delete all your disk files.
# sc: Nicked this from somewhere, added the if statement to try
# make it a bit safer
if top in ('build','dist','gfx') and os.path.basename(os.getcwd()) == 'pyfpdb':
#print "removing directory '"+top+"' ..."
for root, dirs, files in os.walk(top, topdown=False):
for name in files:
os.remove(os.path.join(root, name))
for name in dirs:
os.rmdir(os.path.join(root, name))
os.rmdir(top)
def test_and_remove(top):
if os.path.exists(top):
if os.path.isdir(top):
remove_tree(top)
else:
print "Unexpected file '"+top+"' found. Exiting."
exit()
# remove build and dist dirs if they exist
test_and_remove('dist')
test_and_remove('build')
test_and_remove('gfx')
today = date.today().strftime('%Y%m%d')
print "\n" + r"Output will be created in \dist\ and \fpdb_XXX_"+today+'\\'
print "Enter value for XXX (any length): ", # the comma means no newline
xxx = sys.stdin.readline().rstrip()
dist_dir = r'..\fpdb-' + xxx + '-' + today + '-exe'
print
setup( setup(
name = 'fpdb', name = 'fpdb',
@ -57,17 +106,26 @@ setup(
], ],
options = {'py2exe': { options = {'py2exe': {
'packages' :'encodings', 'packages' : ['encodings', 'matplotlib'],
'includes' : 'cairo, pango, pangocairo, atk, gobject, PokerStarsToFpdb', 'includes' : ['cairo', 'pango', 'pangocairo', 'atk', 'gobject'
'excludes' : '_tkagg, _agg2, cocoaagg, fltkagg', ,'PokerStarsToFpdb', 'matplotlib.numerix.random_array'],
'dll_excludes': 'libglade-2.0-0.dll', 'excludes' : ['_gtkagg', '_tkagg', '_agg2', 'cocoaagg', 'fltkagg'],
'dll_excludes': ['libglade-2.0-0.dll', 'libgdk-win32-2.0-0.dll'
,'libgobject-2.0-0.dll'],
} }
}, },
data_files = ['HUD_config.xml.example', # files in 2nd value in tuple are moved to dir named in 1st value
'Cards01.png', data_files = [('', ['HUD_config.xml.example', 'Cards01.png', 'logging.conf'])
'logging.conf', ,(dist_dir, [r'..\run_fpdb.bat'])
(r'matplotlibdata', glob.glob(r'c:\python26\Lib\site-packages\matplotlib\mpl-data\*')) ,( dist_dir + r'\gfx', glob.glob(r'..\gfx\*.*') )
] # line below has problem with fonts subdir ('not a regular file')
#,(r'matplotlibdata', glob.glob(r'c:\python25\Lib\site-packages\matplotlib\mpl-data\*'))
] + matplotlib.get_py2exe_datafiles()
) )
print '\n' + r'If py2exe was successful move the \dist\ directory '
print 'into \\'+dist_dir+'\\ and rename it as \\pyfpdb\\'
print "Don't forget to add the \\etc \\lib and \\share dirs from your gtk dir\n"

7
run_fpdb.bat Executable file
View File

@ -0,0 +1,7 @@
rem .bat script to run fpdb
cd pyfpdb
fpdb.exe