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

This commit is contained in:
Eratosthenes 2010-01-29 00:02:52 -05:00
commit d11ad8f1ed
9 changed files with 163 additions and 137 deletions

85
pyfpdb/Configuration.py Executable file → Normal file
View File

@ -59,28 +59,44 @@ def get_exec_path():
return sys.path[0] return sys.path[0]
def get_config(file_name, fallback = True): def get_config(file_name, fallback = True):
"""Looks in exec dir and in self.default_config_path for a config file.""" """Looks in cwd and in self.default_config_path for a config file."""
config_path = os.path.join(DIR_SELF, file_name) # look in exec dir exec_dir = get_exec_path()
if os.path.exists(config_path) and os.path.isfile(config_path): config_path = os.path.join(exec_dir, file_name)
return config_path # there is a file in the exec dir so we use it # print "config_path=", config_path
else: if os.path.exists(config_path): # there is a file in the cwd
config_path = os.path.join(DIR_CONFIG, file_name) # look in config dir return config_path # so we use it
if os.path.exists(config_path) and os.path.isfile(config_path): else: # no file in the cwd, look where it should be in the first place
default_dir = get_default_config_path()
config_path = os.path.join(default_dir, file_name)
# print "config path 2=", config_path
if os.path.exists(config_path):
return config_path return config_path
# No file found # No file found
if not fallback: if not fallback:
return False return False
# OK, fall back to the .example file, should be in the exec dir # OK, fall back to the .example file, should be in the start dir
if os.path.exists(os.path.join(DIR_SELF, file_name + ".example")): if os.path.exists(file_name + ".example"):
try: try:
shutil.copyfile(os.path.join(DIR_SELF, file_name + ".example"), os.path.join(DIR_CONFIG, file_name)) print ""
print "No %s found, using %s.example.\n" % (file_name, file_name) if not os.path.isdir(default_dir):
print "A %s file has been created. You will probably have to edit it." % os.path.join(DIR_CONFIG, file_name) msg = "Creating directory: '%s'" % (default_dir)
log.error("No %s found, using %s.example.\n" % (file_name, file_name) ) print msg
logging.info(msg)
os.mkdir(default_dir)
shutil.copyfile(file_name + ".example", config_path)
msg = "No %s found in %s or %s\n" % (file_name, exec_dir, default_dir) \
+ "Config file has been created at %s.\n" % config_path \
+ "Edit your screen_name and hand history path in the supported_sites "\
+ "section of the \nPreferences window (Main menu) before trying to import hands."
print msg
logging.info(msg)
file_name = config_path
except: except:
print "No %s found, cannot fall back. Exiting.\n" % file_name print "Error copying .example file, cannot fall back. Exiting.\n"
sys.stderr.write("Error copying .example file, cannot fall back. Exiting.\n")
sys.stderr.write( str(sys.exc_info()) )
sys.exit() sys.exit()
else: else:
print "No %s found, cannot fall back. Exiting.\n" % file_name print "No %s found, cannot fall back. Exiting.\n" % file_name
@ -94,26 +110,18 @@ def get_logger(file_name, config = "config", fallback = False):
try: try:
logging.config.fileConfig(conf) logging.config.fileConfig(conf)
log = logging.getLogger(config) log = logging.getLogger(config)
log.debug("%s logger initialised" % config)
return log return log
except: except:
pass pass
log = logging.basicConfig() log = logging.basicConfig()
log = logging.getLogger() log = logging.getLogger()
log.error("basicConfig logger initialised") log.debug("config logger initialised")
return log return log
def check_dir(path, create = True): # find a logging.conf file and set up logging
"""Check if a dir exists, optionally creates if not.""" log = get_logger("logging.conf")
if os.path.exists(path):
if os.path.isdir(path):
return path
else:
return False
if create:
print "creating directory %s" % path
else:
return False
######################################################################## ########################################################################
# application wide consts # application wide consts
@ -121,32 +129,20 @@ def check_dir(path, create = True):
APPLICATION_NAME_SHORT = 'fpdb' APPLICATION_NAME_SHORT = 'fpdb'
APPLICATION_VERSION = 'xx.xx.xx' APPLICATION_VERSION = 'xx.xx.xx'
DIR_SELF = get_exec_path()
DIR_CONFIG = check_dir(get_default_config_path())
DIR_DATABASE = check_dir(os.path.join(DIR_CONFIG, 'database'))
DIR_LOG = check_dir(os.path.join(DIR_CONFIG, 'log'))
DATABASE_TYPE_POSTGRESQL = 'postgresql' DATABASE_TYPE_POSTGRESQL = 'postgresql'
DATABASE_TYPE_SQLITE = 'sqlite' DATABASE_TYPE_SQLITE = 'sqlite'
DATABASE_TYPE_MYSQL = 'mysql' DATABASE_TYPE_MYSQL = 'mysql'
#TODO: should this be a tuple or a dict
DATABASE_TYPES = ( DATABASE_TYPES = (
DATABASE_TYPE_POSTGRESQL, DATABASE_TYPE_POSTGRESQL,
DATABASE_TYPE_SQLITE, DATABASE_TYPE_SQLITE,
DATABASE_TYPE_MYSQL, DATABASE_TYPE_MYSQL,
) )
# find a logging.conf file and set up logging #LOCALE_ENCODING = locale.getdefaultlocale()[1]
log = get_logger("logging.conf", config = "config") LOCALE_ENCODING = locale.getpreferredencoding()
log.debug("config logger initialised") if LOCALE_ENCODING == "US-ASCII":
print "Default encoding set to US-ASCII, defaulting to CP1252 instead -- If you're not on a Mac, please report this problem."
# and then log our consts LOCALE_ENCODING = "cp1252"
log.info("DIR SELF = %s" % DIR_SELF)
log.info("DIR CONFIG = %s" % DIR_CONFIG)
log.info("DIR DATABASE = %s" % DIR_DATABASE)
log.info("DIR LOG = %s" % DIR_LOG)
NEWIMPORT = True
LOCALE_ENCODING = locale.getdefaultlocale()[1]
######################################################################## ########################################################################
def string_to_bool(string, default=True): def string_to_bool(string, default=True):
@ -428,7 +424,8 @@ class Config:
if file is not None: # config file path passed in if file is not None: # config file path passed in
file = os.path.expanduser(file) file = os.path.expanduser(file)
if not os.path.exists(file): if not os.path.exists(file):
log.error("Specified configuration file %s not found. Using defaults." % (file)) print "Configuration file %s not found. Using defaults." % (file)
sys.stderr.write("Configuration file %s not found. Using defaults." % (file))
file = None file = None
if file is None: file = get_config("HUD_config.xml", True) if file is None: file = get_config("HUD_config.xml", True)

View File

@ -39,41 +39,38 @@ import string
import re import re
import Queue import Queue
import codecs import codecs
import logging
import math import math
# pyGTK modules # pyGTK modules
# FreePokerTools modules
import SQL
import Card
import Tourney
import Charset
from Exceptions import *
import Configuration
log = Configuration.get_logger("logging.conf","db")
# Other library modules # Other library modules
try: try:
import sqlalchemy.pool as pool import sqlalchemy.pool as pool
use_pool = True use_pool = True
except ImportError: except ImportError:
logging.info("Not using sqlalchemy connection pool.") log.info("Not using sqlalchemy connection pool.")
use_pool = False use_pool = False
try: try:
from numpy import var from numpy import var
use_numpy = True use_numpy = True
except ImportError: except ImportError:
logging.info("Not using numpy to define variance in sqlite.") log.info("Not using numpy to define variance in sqlite.")
use_numpy = False use_numpy = False
# FreePokerTools modules
import Configuration
import SQL
import Card
import Tourney
import Charset
from Exceptions import *
log = Configuration.get_logger("logging.conf", config = "db")
log.debug("db logger initialized.")
encoder = codecs.lookup('utf-8')
DB_VERSION = 119 DB_VERSION = 119
@ -247,13 +244,14 @@ class Database:
# connect to db # connect to db
self.do_connect(c) self.do_connect(c)
print "connection =", self.connection
if self.backend == self.PGSQL: if self.backend == self.PGSQL:
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE
#ISOLATION_LEVEL_AUTOCOMMIT = 0 #ISOLATION_LEVEL_AUTOCOMMIT = 0
#ISOLATION_LEVEL_READ_COMMITTED = 1 #ISOLATION_LEVEL_READ_COMMITTED = 1
#ISOLATION_LEVEL_SERIALIZABLE = 2 #ISOLATION_LEVEL_SERIALIZABLE = 2
if self.backend == self.SQLITE and self.database == ':memory:' and self.wrongDbVersion: if self.backend == self.SQLITE and self.database == ':memory:' and self.wrongDbVersion:
log.info("sqlite/:memory: - creating") log.info("sqlite/:memory: - creating")
self.recreate_tables() self.recreate_tables()
@ -374,20 +372,20 @@ class Database:
print msg print msg
raise FpdbError(msg) raise FpdbError(msg)
elif backend == Database.SQLITE: elif backend == Database.SQLITE:
logging.info("Connecting to SQLite: %(database)s" % {'database':database}) log.info("Connecting to SQLite: %(database)s" % {'database':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:
logging.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_databases): if not os.path.isdir(self.config.dir_databases):
print "Creating directory: '%s'" % (self.config.dir_databases) print "Creating directory: '%s'" % (self.config.dir_databases)
logging.info("Creating directory: '%s'" % (self.config.dir_databases)) log.info("Creating directory: '%s'" % (self.config.dir_databases))
os.mkdir(self.config.dir_databases) os.mkdir(self.config.dir_databases)
database = os.path.join(self.config.dir_databases, database) database = os.path.join(self.config.dir_databases, database)
logging.info(" sqlite db: " + database) log.info(" sqlite db: " + database)
self.connection = sqlite3.connect(database, detect_types=sqlite3.PARSE_DECLTYPES ) self.connection = sqlite3.connect(database, detect_types=sqlite3.PARSE_DECLTYPES )
sqlite3.register_converter("bool", lambda x: bool(int(x))) sqlite3.register_converter("bool", lambda x: bool(int(x)))
sqlite3.register_adapter(bool, lambda x: "1" if x else "0") sqlite3.register_adapter(bool, lambda x: "1" if x else "0")
@ -397,7 +395,10 @@ class Database:
if use_numpy: if use_numpy:
self.connection.create_aggregate("variance", 1, VARIANCE) self.connection.create_aggregate("variance", 1, VARIANCE)
else: else:
logging.warning("Some database functions will not work without NumPy support") log.warning("Some database functions will not work without NumPy support")
self.cursor = self.connection.cursor()
self.cursor.execute('PRAGMA temp_store=2') # use memory for temp tables/indexes
self.cursor.execute('PRAGMA synchronous=0') # don't wait for file writes to finish
else: else:
raise FpdbError("unrecognised database backend:"+backend) raise FpdbError("unrecognised database backend:"+backend)
@ -412,7 +413,7 @@ class Database:
self.cursor.execute("SELECT * FROM Settings") self.cursor.execute("SELECT * FROM Settings")
settings = self.cursor.fetchone() settings = self.cursor.fetchone()
if settings[0] != DB_VERSION: if settings[0] != DB_VERSION:
logging.error("outdated or too new database version (%s) - please recreate tables" log.error("outdated or too new database version (%s) - please recreate tables"
% (settings[0])) % (settings[0]))
self.wrongDbVersion = True self.wrongDbVersion = True
except:# _mysql_exceptions.ProgrammingError: except:# _mysql_exceptions.ProgrammingError:
@ -422,11 +423,6 @@ class Database:
log.info("failed to read settings table - recreating tables") log.info("failed to read settings table - recreating tables")
self.recreate_tables() self.recreate_tables()
self.check_version(database=database, create=False) self.check_version(database=database, create=False)
if not self.wrongDbVersion:
msg = "Edit your screen_name and hand history path in the supported_sites "\
+"section of the \nPreferences window (Main menu) before trying to import hands"
print "\n%s" % msg
log.warning(msg)
else: else:
print "Failed to read settings table - please recreate tables" print "Failed to read settings table - please recreate tables"
log.info("failed to read settings table - please recreate tables") log.info("failed to read settings table - please recreate tables")
@ -436,7 +432,27 @@ class Database:
#end def connect #end def connect
def commit(self): def commit(self):
self.connection.commit() if self.backend != self.SQLITE:
self.connection.commit()
else:
# sqlite commits can fail because of shared locks on the database (SQLITE_BUSY)
# re-try commit if it fails in case this happened
maxtimes = 5
pause = 1
ok = False
for i in xrange(maxtimes):
try:
ret = self.connection.commit()
log.debug("commit finished ok, i = "+str(i))
ok = True
except:
log.debug("commit "+str(i)+" failed: info=" + str(sys.exc_info())
+ " value=" + str(sys.exc_value))
sleep(pause)
if ok: break
if not ok:
log.debug("commit failed")
raise FpdbError('sqlite commit failed')
def rollback(self): def rollback(self):
self.connection.rollback() self.connection.rollback()
@ -1311,7 +1327,6 @@ class Database:
c.execute("INSERT INTO Sites (name,currency) VALUES ('Absolute', 'USD')") c.execute("INSERT INTO Sites (name,currency) VALUES ('Absolute', 'USD')")
c.execute("INSERT INTO Sites (name,currency) VALUES ('PartyPoker', 'USD')") c.execute("INSERT INTO Sites (name,currency) VALUES ('PartyPoker', 'USD')")
c.execute("INSERT INTO Sites (name,currency) VALUES ('Partouche', 'EUR')") c.execute("INSERT INTO Sites (name,currency) VALUES ('Partouche', 'EUR')")
c.execute("INSERT INTO Sites (name,currency) VALUES ('Carbon', 'USD')")
if self.backend == self.SQLITE: if self.backend == self.SQLITE:
c.execute("INSERT INTO TourneyTypes (id, siteId, buyin, fee) VALUES (NULL, 1, 0, 0);") c.execute("INSERT INTO TourneyTypes (id, siteId, buyin, fee) VALUES (NULL, 1, 0, 0);")
elif self.backend == self.PGSQL: elif self.backend == self.PGSQL:
@ -1751,7 +1766,10 @@ class Database:
def insertPlayer(self, name, site_id): def insertPlayer(self, name, site_id):
result = None result = None
_name = Charset.to_db_utf8(name) if self.backend == self.SQLITE:
_name = name
else:
_name = Charset.to_db_utf8(name)
c = self.get_cursor() c = self.get_cursor()
q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s" q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s"
q = q.replace('%s', self.sql.query['placeholder']) q = q.replace('%s', self.sql.query['placeholder'])
@ -1907,7 +1925,7 @@ class Database:
# end def send_finish_msg(): # end def send_finish_msg():
def tRecogniseTourneyType(self, tourney): def tRecogniseTourneyType(self, tourney):
logging.debug("Database.tRecogniseTourneyType") log.debug("Database.tRecogniseTourneyType")
typeId = 1 typeId = 1
# Check if Tourney exists, and if so retrieve TTypeId : in that case, check values of the ttype # Check if Tourney exists, and if so retrieve TTypeId : in that case, check values of the ttype
cursor = self.get_cursor() cursor = self.get_cursor()
@ -1923,10 +1941,10 @@ class Database:
try: try:
len(result) len(result)
typeId = result[0] typeId = result[0]
logging.debug("Tourney found in db with Tourney_Type_ID = %d" % typeId) log.debug("Tourney found in db with Tourney_Type_ID = %d" % typeId)
for ev in expectedValues : for ev in expectedValues :
if ( getattr( tourney, expectedValues.get(ev) ) <> result[ev] ): if ( getattr( tourney, expectedValues.get(ev) ) <> result[ev] ):
logging.debug("TypeId mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValues.get(ev), getattr( tourney, expectedValues.get(ev)), result[ev]) ) log.debug("TypeId mismatch : wrong %s : Tourney=%s / db=%s" % (expectedValues.get(ev), getattr( tourney, expectedValues.get(ev)), result[ev]) )
typeIdMatch = False typeIdMatch = False
#break #break
except: except:
@ -1936,7 +1954,7 @@ class Database:
if typeIdMatch == False : if typeIdMatch == False :
# Check for an existing TTypeId that matches tourney info (buyin/fee, knockout, rebuy, speed, matrix, shootout) # Check for an existing TTypeId that matches tourney info (buyin/fee, knockout, rebuy, speed, matrix, shootout)
# if not found create it # if not found create it
logging.debug("Searching for a TourneyTypeId matching TourneyType data") log.debug("Searching for a TourneyTypeId matching TourneyType data")
cursor.execute (self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder']), cursor.execute (self.sql.query['getTourneyTypeId'].replace('%s', self.sql.query['placeholder']),
(tourney.siteId, tourney.buyin, tourney.fee, tourney.isKO, (tourney.siteId, tourney.buyin, tourney.fee, tourney.isKO,
tourney.isRebuy, tourney.speed, tourney.isHU, tourney.isShootout, tourney.isMatrix) tourney.isRebuy, tourney.speed, tourney.isHU, tourney.isShootout, tourney.isMatrix)
@ -1946,9 +1964,9 @@ class Database:
try: try:
len(result) len(result)
typeId = result[0] typeId = result[0]
logging.debug("Existing Tourney Type Id found : %d" % typeId) log.debug("Existing Tourney Type Id found : %d" % typeId)
except TypeError: #this means we need to create a new entry except TypeError: #this means we need to create a new entry
logging.debug("Tourney Type Id not found : create one") log.debug("Tourney Type Id not found : create one")
cursor.execute (self.sql.query['insertTourneyTypes'].replace('%s', self.sql.query['placeholder']), cursor.execute (self.sql.query['insertTourneyTypes'].replace('%s', self.sql.query['placeholder']),
(tourney.siteId, tourney.buyin, tourney.fee, tourney.isKO, tourney.isRebuy, (tourney.siteId, tourney.buyin, tourney.fee, tourney.isKO, tourney.isRebuy,
tourney.speed, tourney.isHU, tourney.isShootout, tourney.isMatrix) tourney.speed, tourney.isHU, tourney.isShootout, tourney.isMatrix)

View File

@ -48,5 +48,11 @@ class FpdbPostgresqlNoDatabase(FpdbDatabaseError):
def __str__(self): def __str__(self):
return repr(self.value +" " + self.errmsg) return repr(self.value +" " + self.errmsg)
class DuplicateError(FpdbError): class FpdbHandError(FpdbError):
pass
class FpdbHandDuplicate(FpdbHandError):
pass
class FpdbHandPartial(FpdbHandError):
pass pass

View File

@ -194,7 +194,7 @@ 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':
command = "python HUD_main.py " + self.settings['cl_options'] command = "python "+sys.path[0]+"\\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')

View File

@ -212,6 +212,7 @@ class HUD_main(object):
# get basic info about the new hand from the db # get basic info about the new hand from the db
# if there is a db error, complain, skip hand, and proceed # if there is a db error, complain, skip hand, and proceed
log.info("HUD_main.read_stdin: hand processing starting ...")
try: try:
(table_name, max, poker_game, type, site_id, site_name, num_seats, tour_number, tab_number) = \ (table_name, max, poker_game, type, site_id, site_name, num_seats, tour_number, tab_number) = \
self.db_connection.get_table_info(new_hand_id) self.db_connection.get_table_info(new_hand_id)
@ -237,6 +238,7 @@ class HUD_main(object):
try: try:
self.db_connection.init_hud_stat_vars( self.hud_dict[temp_key].hud_params['hud_days'] 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']) , self.hud_dict[temp_key].hud_params['h_hud_days'])
t4 = time.time()
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]) 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])
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
@ -245,6 +247,7 @@ class HUD_main(object):
# 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
t5 = time.time()
cards = self.db_connection.get_cards(new_hand_id) cards = self.db_connection.get_cards(new_hand_id)
comm_cards = self.db_connection.get_common_cards(new_hand_id) comm_cards = self.db_connection.get_common_cards(new_hand_id)
if comm_cards != {}: # stud! if comm_cards != {}: # stud!
@ -257,10 +260,8 @@ class HUD_main(object):
else: else:
# get stats using default params--also get cards # get stats using default params--also get cards
self.db_connection.init_hud_stat_vars( self.hud_params['hud_days'], self.hud_params['h_hud_days'] ) self.db_connection.init_hud_stat_vars( self.hud_params['hud_days'], self.hud_params['h_hud_days'] )
t4 = time.time()
stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params
,self.hero_ids[site_id], num_seats) ,self.hero_ids[site_id], num_seats)
t5 = time.time()
cards = self.db_connection.get_cards(new_hand_id) cards = self.db_connection.get_cards(new_hand_id)
comm_cards = self.db_connection.get_common_cards(new_hand_id) comm_cards = self.db_connection.get_common_cards(new_hand_id)
if comm_cards != {}: # stud! if comm_cards != {}: # stud!

View File

@ -229,8 +229,7 @@ db: a connected Database object"""
# TourneysPlayers # TourneysPlayers
else: else:
log.info("Hand.insert(): hid #: %s is a duplicate" % hh['siteHandNo']) log.info("Hand.insert(): hid #: %s is a duplicate" % hh['siteHandNo'])
#Raise Duplicate exception? raise FpdbHandDuplicate(hh['siteHandNo'])
pass
def updateHudCache(self, db): def updateHudCache(self, db):
db.storeHudCache(self.dbid_gt, self.dbid_pids, self.starttime, self.stats.getHandsPlayers()) db.storeHudCache(self.dbid_gt, self.dbid_pids, self.starttime, self.stats.getHandsPlayers())
@ -636,7 +635,7 @@ class HoldemOmahaHand(Hand):
if builtFrom == "HHC": if builtFrom == "HHC":
hhc.readHandInfo(self) hhc.readHandInfo(self)
if self.gametype['type'] == 'tour': if self.gametype['type'] == 'tour':
self.tablename = "%s %s" % (self.tourNo, self.tablename) self.tablename = "%s %s" % (self.tourNo, self.tablename)
hhc.readPlayerStacks(self) hhc.readPlayerStacks(self)
hhc.compilePlayerRegexs(self) hhc.compilePlayerRegexs(self)
hhc.markStreets(self) hhc.markStreets(self)
@ -932,7 +931,7 @@ class DrawHand(Hand):
if builtFrom == "HHC": if builtFrom == "HHC":
hhc.readHandInfo(self) hhc.readHandInfo(self)
if self.gametype['type'] == 'tour': if self.gametype['type'] == 'tour':
self.tablename = "%s %s" % (self.tourNo, self.tablename) self.tablename = "%s %s" % (self.tourNo, self.tablename)
hhc.readPlayerStacks(self) hhc.readPlayerStacks(self)
hhc.compilePlayerRegexs(self) hhc.compilePlayerRegexs(self)
hhc.markStreets(self) hhc.markStreets(self)
@ -1128,7 +1127,7 @@ class StudHand(Hand):
if builtFrom == "HHC": if builtFrom == "HHC":
hhc.readHandInfo(self) hhc.readHandInfo(self)
if self.gametype['type'] == 'tour': if self.gametype['type'] == 'tour':
self.tablename = "%s %s" % (self.tourNo, self.tablename) self.tablename = "%s %s" % (self.tourNo, self.tablename)
hhc.readPlayerStacks(self) hhc.readPlayerStacks(self)
hhc.compilePlayerRegexs(self) hhc.compilePlayerRegexs(self)
hhc.markStreets(self) hhc.markStreets(self)
@ -1220,7 +1219,7 @@ Add a complete on [street] by [player] to [amountTo]
# showdownPot INT, /* pot size at sd/street7 */ # showdownPot INT, /* pot size at sd/street7 */
return (0,0,0,0,0) return (0,0,0,0,0)
def writeHand(self, fh=sys.__stdout__): def writeHand(self, fh=sys.__stdout__):
# PokerStars format. # PokerStars format.
@ -1615,4 +1614,3 @@ ORDER BY
return h return h

View File

@ -769,7 +769,7 @@ class fpdb:
self.status_bar.show() self.status_bar.show()
if self.db is not None and self.db.connected: if self.db is not None and self.db.connected:
self.status_bar.set_text("Status: Connected to %s database named %s on host %s" self.status_bar.set_text("Status: Connected to %s database named %s on host %s"
% (self.db.get_backend_name(),self.db.database, self.db.host)) % (self.db.get_backend_name(),self.db.database, self.db.host))
# rollback to make sure any locks are cleared: # rollback to make sure any locks are cleared:
self.db.rollback() self.db.rollback()
@ -902,8 +902,8 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
self.load_profile() self.load_profile()
self.statusIcon = gtk.StatusIcon() self.statusIcon = gtk.StatusIcon()
if os.path.exists('../gfx/fpdb-cards.png'): if os.path.exists(os.path.join(sys.path[0], '../gfx/fpdb-cards.png')):
self.statusIcon.set_from_file('../gfx/fpdb-cards.png') self.statusIcon.set_from_file(os.path.join(sys.path[0], '../gfx/fpdb-cards.png'))
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

@ -365,7 +365,7 @@ class Importer:
pass pass
(stored, duplicates, partial, errors, ttime) = self.import_file_dict(self.database, file, self.filelist[file][0], self.filelist[file][1], None) (stored, duplicates, partial, errors, ttime) = self.import_file_dict(self.database, file, self.filelist[file][0], self.filelist[file][1], None)
try: try:
if not os.path.isdir(file): if not os.path.isdir(file): # Note: This assumes that whatever calls us has an "addText" func
self.caller.addText(" %d stored, %d duplicates, %d partial, %d errors (time = %f)" % (stored, duplicates, partial, errors, ttime)) self.caller.addText(" %d stored, %d duplicates, %d partial, %d errors (time = %f)" % (stored, duplicates, partial, errors, ttime))
except KeyError: # TODO: Again, what error happens here? fix when we find out .. except KeyError: # TODO: Again, what error happens here? fix when we find out ..
pass pass
@ -402,7 +402,7 @@ class Importer:
return (0,0,0,0,0) return (0,0,0,0,0)
conv = None conv = None
(stored, duplicates, partial, errors, ttime) = (0, 0, 0, 0, 0) (stored, duplicates, partial, errors, ttime) = (0, 0, 0, 0, time())
file = file.decode(Configuration.LOCALE_ENCODING) file = file.decode(Configuration.LOCALE_ENCODING)
@ -437,12 +437,15 @@ class Importer:
for hand in handlist: for hand in handlist:
if hand is not None: if hand is not None:
#try, except duplicates here?
hand.prepInsert(self.database) hand.prepInsert(self.database)
hand.insert(self.database) try:
if self.callHud and hand.dbid_hands != 0: hand.insert(self.database)
to_hud.append(hand.dbid_hands) except Exceptions.FpdbHandDuplicate:
else: duplicates += 1
else:
if self.callHud and hand.dbid_hands != 0:
to_hud.append(hand.dbid_hands)
else: # TODO: Treat empty as an error, or just ignore?
log.error("Hand processed but empty") log.error("Hand processed but empty")
self.database.commit() self.database.commit()
# Call hudcache update if not in bulk import mode # Call hudcache update if not in bulk import mode
@ -460,13 +463,16 @@ class Importer:
errors = getattr(hhc, 'numErrors') errors = getattr(hhc, 'numErrors')
stored = getattr(hhc, 'numHands') stored = getattr(hhc, 'numHands')
stored -= duplicates
else: else:
# conversion didn't work # conversion didn't work
# TODO: appropriate response? # TODO: appropriate response?
return (0, 0, 0, 1, 0) return (0, 0, 0, 1, time() - ttime)
else: else:
log.warning("Unknown filter filter_name:'%s' in filter:'%s'" %(filter_name, filter)) log.warning("Unknown filter filter_name:'%s' in filter:'%s'" %(filter_name, filter))
return (0, 0, 0, 1, 0) return (0, 0, 0, 1, time() - ttime)
ttime = time() - ttime
#This will barf if conv.getStatus != True #This will barf if conv.getStatus != True
return (stored, duplicates, partial, errors, ttime) return (stored, duplicates, partial, errors, ttime)

View File

@ -1,34 +1,34 @@
#!/usr/bin/python #!/usr/bin/python
#Copyright 2008 Carl Gherardi #Copyright 2008 Carl Gherardi
#This program is free software: you can redistribute it and/or modify #This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU Affero General Public License as published by #it under the terms of the GNU Affero General Public License as published by
#the Free Software Foundation, version 3 of the License. #the Free Software Foundation, version 3 of the License.
# #
#This program is distributed in the hope that it will be useful, #This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of #but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details. #GNU General Public License for more details.
# #
#You should have received a copy of the GNU Affero General Public License #You should have received a copy of the GNU Affero General Public License
#along with this program. If not, see <http://www.gnu.org/licenses/>. #along with this program. If not, see <http://www.gnu.org/licenses/>.
#In the "official" distribution you can find the license in #In the "official" distribution you can find the license in
#agpl-3.0.txt in the docs folder of the package. #agpl-3.0.txt in the docs folder of the package.
import os import os
import sys import sys
# sys.path[0] holds the directory run_fpdb.py is in # sys.path[0] holds the directory run_fpdb.py is in
sys.path[0] = sys.path[0]+os.sep+"pyfpdb" sys.path[0] = sys.path[0]+os.sep+"pyfpdb"
os.chdir(sys.path[0]) os.chdir(sys.path[0])
#print "sys.path[0] =", sys.path[0], "cwd =", os.getcwd() #print "sys.path[0] =", sys.path[0], "cwd =", os.getcwd()
import fpdb import fpdb
if __name__ == "__main__": if __name__ == "__main__":
me = fpdb.fpdb() me = fpdb.fpdb()
me.main() me.main()
exit() exit()