Merge branch 'master' of git://repo.or.cz/fpbd-bostik

This commit is contained in:
Worros 2008-12-07 14:17:05 +09:00
commit 425997d66a
4 changed files with 426 additions and 401 deletions

View File

@ -577,7 +577,7 @@ class FpdbSQLQueries:
self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD INDEX siteTourneyNo(siteTourneyNo)"""
elif(self.dbname == 'PostgreSQL'):
# FIXME: This query has a different syntax
self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD INDEX siteTourneyNo(siteTourneyNo)"""
self.query['addTourneyIndex'] = """CREATE INDEX siteTourneyNo ON Tourneys (siteTourneyNo)"""
elif(self.dbname == 'SQLite'):
self.query['addHandsIndex'] = """ """
@ -585,7 +585,7 @@ class FpdbSQLQueries:
self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)"""
elif(self.dbname == 'PostgreSQL'):
# FIXME: This query has a different syntax
self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)"""
self.query['addHandsIndex'] = """CREATE INDEX siteHandNo ON Hands (siteHandNo)"""
elif(self.dbname == 'SQLite'):
self.query['addHandsIndex'] = """ """
@ -593,9 +593,9 @@ class FpdbSQLQueries:
self.query['addPlayersIndex'] = """ALTER TABLE Players ADD INDEX name(name)"""
elif(self.dbname == 'PostgreSQL'):
# FIXME: This query has a different syntax
self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)"""
self.query['addPlayersIndex'] = """CREATE INDEX name ON Players (name)"""
elif(self.dbname == 'SQLite'):
self.query['addHandsIndex'] = """ """
self.query['addPlayersIndex'] = """ """
################################
# Queries used in GuiGraphViewer

View File

@ -118,12 +118,12 @@ class fpdb:
def dia_create_del_database(self, widget, data):
print "todo: implement dia_create_del_database"
obtain_global_lock()
self.obtain_global_lock()
#end def dia_create_del_database
def dia_create_del_user(self, widget, data):
print "todo: implement dia_create_del_user"
obtain_global_lock()
self.obtain_global_lock()
#end def dia_create_del_user
def dia_database_stats(self, widget, data):
@ -133,17 +133,17 @@ class fpdb:
def dia_delete_db_parts(self, widget, data):
print "todo: implement dia_delete_db_parts"
obtain_global_lock()
self.obtain_global_lock()
#end def dia_delete_db_parts
def dia_edit_profile(self, widget=None, data=None, create_default=False, path=None):
print "todo: implement dia_edit_profile"
obtain_global_lock()
self.obtain_global_lock()
#end def dia_edit_profile
def dia_export_db(self, widget, data):
print "todo: implement dia_export_db"
obtain_global_lock()
self.obtain_global_lock()
#end def dia_export_db
def dia_get_db_root_credentials(self):
@ -168,7 +168,7 @@ class fpdb:
def dia_import_db(self, widget, data):
print "todo: implement dia_import_db"
obtain_global_lock()
self.obtain_global_lock()
#end def dia_import_db
def dia_licensing(self, widget, data):
@ -264,7 +264,11 @@ class fpdb:
self.db = fpdb_db.fpdb_db()
#print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName']
self.db.connect(self.settings['db-backend'], self.settings['db-host'], self.settings['db-databaseName'], self.settings['db-user'], self.settings['db-password'])
self.db.connect(self.settings['db-backend'],
self.settings['db-host'],
self.settings['db-databaseName'],
self.settings['db-user'],
self.settings['db-password'])
if self.db.wrongDbVersion:
diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))

View File

@ -21,156 +21,170 @@ import fpdb_simple
import FpdbSQLQueries
class fpdb_db:
def __init__(self):
"""Simple constructor, doesnt really do anything"""
self.db=None
self.cursor=None
self.sql = {}
self.MYSQL_INNODB=2
self.PGSQL=3
self.SQLITE=4
#end def __init__
def connect(self, backend, host, database, user, password):
"""Connects a database with the given parameters"""
self.backend=backend
self.host=host
self.database=database
self.user=user
self.password=password
if backend==self.MYSQL_INNODB:
import MySQLdb
self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database)
elif backend==self.PGSQL:
import psycopg2
self.db = psycopg2.connect(host = host, user = user, password = password, database = database)
else:
raise fpdb_simple.FpdbError("unrecognised database backend:"+backend)
self.cursor=self.db.cursor()
self.cursor.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED')
# Set up query dictionary as early in the connection process as we can.
self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name())
self.wrongDbVersion=False
try:
self.cursor.execute("SELECT * FROM Settings")
settings=self.cursor.fetchone()
if settings[0]!=118:
print "outdated or too new database version - please recreate tables"
self.wrongDbVersion=True
except:# _mysql_exceptions.ProgrammingError:
print "failed to read settings table - please recreate tables"
self.wrongDbVersion=True
#end def connect
def __init__(self):
"""Simple constructor, doesnt really do anything"""
self.db=None
self.cursor=None
self.sql = {}
self.MYSQL_INNODB=2
self.PGSQL=3
self.SQLITE=4
#end def __init__
def connect(self, backend=None, host=None, database=None,
user=None, password=None):
"""Connects a database with the given parameters"""
if backend is None:
raise FpdbError('Database backend not defined')
self.backend=backend
self.host=host
self.user=user
self.password=password
self.database=database
if backend==self.MYSQL_INNODB:
import MySQLdb
self.db=MySQLdb.connect(host = host, user = user, passwd = password, db = database)
elif backend==self.PGSQL:
import psycopg2
# If DB connection is made over TCP, then the variables
# host, user and password are required
if self.host or self.user:
self.db = psycopg2.connect(host = host,
user = user,
password = password,
database = database)
# For local domain-socket connections, only DB name is
# needed, and everything else is in fact undefined and/or
# flat out wrong
else:
self.db = psycopg2.connect(database = database)
else:
raise fpdb_simple.FpdbError("unrecognised database backend:"+backend)
self.cursor=self.db.cursor()
self.cursor.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED')
# Set up query dictionary as early in the connection process as we can.
self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name())
self.wrongDbVersion=False
try:
self.cursor.execute("SELECT * FROM Settings")
settings=self.cursor.fetchone()
if settings[0]!=118:
print "outdated or too new database version - please recreate tables"
self.wrongDbVersion=True
except:# _mysql_exceptions.ProgrammingError:
print "failed to read settings table - please recreate tables"
self.wrongDbVersion=True
#end def connect
def disconnect(self, due_to_error=False):
"""Disconnects the DB"""
if due_to_error:
self.db.rollback()
else:
self.db.commit()
self.cursor.close()
self.db.close()
#end def disconnect
def reconnect(self, due_to_error=False):
"""Reconnects the DB"""
#print "started fpdb_db.reconnect"
self.disconnect(due_to_error)
self.connect(self.backend, self.host, self.database, self.user, self.password)
def disconnect(self, due_to_error=False):
"""Disconnects the DB"""
if due_to_error:
self.db.rollback()
else:
self.db.commit()
self.cursor.close()
self.db.close()
#end def disconnect
def reconnect(self, due_to_error=False):
"""Reconnects the DB"""
#print "started fpdb_db.reconnect"
self.disconnect(due_to_error)
self.connect(self.backend, self.host, self.database, self.user, self.password)
def create_tables(self):
#todo: should detect and fail gracefully if tables already exist.
self.cursor.execute(self.sql.query['createSettingsTable'])
self.cursor.execute(self.sql.query['createSitesTable'])
self.cursor.execute(self.sql.query['createGametypesTable'])
self.cursor.execute(self.sql.query['createPlayersTable'])
self.cursor.execute(self.sql.query['createAutoratesTable'])
self.cursor.execute(self.sql.query['createHandsTable'])
self.cursor.execute(self.sql.query['createBoardCardsTable'])
self.cursor.execute(self.sql.query['createTourneyTypesTable'])
self.cursor.execute(self.sql.query['createTourneysTable'])
self.cursor.execute(self.sql.query['createTourneysPlayersTable'])
self.cursor.execute(self.sql.query['createHandsPlayersTable'])
self.cursor.execute(self.sql.query['createHandsActionsTable'])
self.cursor.execute(self.sql.query['createHudCacheTable'])
self.cursor.execute(self.sql.query['addTourneyIndex'])
self.cursor.execute(self.sql.query['addHandsIndex'])
self.cursor.execute(self.sql.query['addPlayersIndex'])
self.fillDefaultData()
self.db.commit()
def create_tables(self):
#todo: should detect and fail gracefully if tables already exist.
self.cursor.execute(self.sql.query['createSettingsTable'])
self.cursor.execute(self.sql.query['createSitesTable'])
self.cursor.execute(self.sql.query['createGametypesTable'])
self.cursor.execute(self.sql.query['createPlayersTable'])
self.cursor.execute(self.sql.query['createAutoratesTable'])
self.cursor.execute(self.sql.query['createHandsTable'])
self.cursor.execute(self.sql.query['createBoardCardsTable'])
self.cursor.execute(self.sql.query['createTourneyTypesTable'])
self.cursor.execute(self.sql.query['createTourneysTable'])
self.cursor.execute(self.sql.query['createTourneysPlayersTable'])
self.cursor.execute(self.sql.query['createHandsPlayersTable'])
self.cursor.execute(self.sql.query['createHandsActionsTable'])
self.cursor.execute(self.sql.query['createHudCacheTable'])
self.cursor.execute(self.sql.query['addTourneyIndex'])
self.cursor.execute(self.sql.query['addHandsIndex'])
self.cursor.execute(self.sql.query['addPlayersIndex'])
self.fillDefaultData()
self.db.commit()
#end def disconnect
def drop_tables(self):
"""Drops the fpdb tables from the current db"""
def drop_tables(self):
"""Drops the fpdb tables from the current db"""
if(self.get_backend_name() == 'MySQL InnoDB'):
#Databases with FOREIGN KEY support need this switched of before you can drop tables
self.drop_referencial_integrity()
if(self.get_backend_name() == 'MySQL InnoDB'):
#Databases with FOREIGN KEY support need this switched of before you can drop tables
self.drop_referencial_integrity()
# Query the DB to see what tables exist
self.cursor.execute(self.sql.query['list_tables'])
for table in self.cursor:
self.cursor.execute(self.sql.query['drop_table'] + table[0])
elif(self.get_backend_name() == 'PostgreSQL'):
self.db.commit()# I have no idea why this makes the query work--REB 07OCT2008
self.cursor.execute(self.sql.query['list_tables'])
tables = self.cursor.fetchall()
for table in tables:
self.cursor.execute(self.sql.query['drop_table'] + table[0] + ' cascade')
elif(self.get_backend_name() == 'SQLite'):
#todo: sqlite version here
print "Empty function here"
# Query the DB to see what tables exist
self.cursor.execute(self.sql.query['list_tables'])
for table in self.cursor:
self.cursor.execute(self.sql.query['drop_table'] + table[0])
elif(self.get_backend_name() == 'PostgreSQL'):
self.db.commit()# I have no idea why this makes the query work--REB 07OCT2008
self.cursor.execute(self.sql.query['list_tables'])
tables = self.cursor.fetchall()
for table in tables:
self.cursor.execute(self.sql.query['drop_table'] + table[0] + ' cascade')
elif(self.get_backend_name() == 'SQLite'):
#todo: sqlite version here
print "Empty function here"
self.db.commit()
#end def drop_tables
self.db.commit()
#end def drop_tables
def drop_referencial_integrity(self):
"""Update all tables to remove foreign keys"""
def drop_referencial_integrity(self):
"""Update all tables to remove foreign keys"""
self.cursor.execute(self.sql.query['list_tables'])
result = self.cursor.fetchall()
self.cursor.execute(self.sql.query['list_tables'])
result = self.cursor.fetchall()
for i in range(len(result)):
self.cursor.execute("SHOW CREATE TABLE " + result[i][0])
inner = self.cursor.fetchall()
for i in range(len(result)):
self.cursor.execute("SHOW CREATE TABLE " + result[i][0])
inner = self.cursor.fetchall()
for j in range(len(inner)):
# result[i][0] - Table name
# result[i][1] - CREATE TABLE parameters
#Searching for CONSTRAINT `tablename_ibfk_1`
for m in re.finditer('(ibfk_[0-9]+)', inner[j][1]):
key = "`" + inner[j][0] + "_" + m.group() + "`"
self.cursor.execute("ALTER TABLE " + inner[j][0] + " DROP FOREIGN KEY " + key)
for j in range(len(inner)):
# result[i][0] - Table name
# result[i][1] - CREATE TABLE parameters
#Searching for CONSTRAINT `tablename_ibfk_1`
for m in re.finditer('(ibfk_[0-9]+)', inner[j][1]):
key = "`" + inner[j][0] + "_" + m.group() + "`"
self.cursor.execute("ALTER TABLE " + inner[j][0] + " DROP FOREIGN KEY " + key)
self.db.commit()
#end drop_referencial_inegrity
def get_backend_name(self):
"""Returns the name of the currently used backend"""
if self.backend==2:
return "MySQL InnoDB"
elif self.backend==3:
return "PostgreSQL"
else:
raise fpdb_simple.FpdbError("invalid backend")
#end def get_backend_name
def get_db_info(self):
return (self.host, self.database, self.user, self.password)
#end def get_db_info
def fillDefaultData(self):
self.cursor.execute("INSERT INTO Settings VALUES (118);")
self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Full Tilt Poker', 'USD');")
self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'PokerStars', 'USD');")
self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);")
#end def fillDefaultData
def recreate_tables(self):
"""(Re-)creates the tables of the current DB"""
self.drop_tables()
self.create_tables()
self.db.commit()
print "Finished recreating tables"
#end def recreate_tables
def get_backend_name(self):
"""Returns the name of the currently used backend"""
if self.backend==2:
return "MySQL InnoDB"
elif self.backend==3:
return "PostgreSQL"
else:
raise fpdb_simple.FpdbError("invalid backend")
#end def get_backend_name
def get_db_info(self):
return (self.host, self.database, self.user, self.password)
#end def get_db_info
def fillDefaultData(self):
self.cursor.execute("INSERT INTO Settings VALUES (118);")
self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'Full Tilt Poker', 'USD');")
self.cursor.execute("INSERT INTO Sites VALUES (DEFAULT, 'PokerStars', 'USD');")
self.cursor.execute("INSERT INTO TourneyTypes VALUES (DEFAULT, 1, 0, 0, 0, False);")
#end def fillDefaultData
def recreate_tables(self):
"""(Re-)creates the tables of the current DB"""
self.drop_tables()
self.create_tables()
self.db.commit()
print "Finished recreating tables"
#end def recreate_tables
#end class fpdb_db

View File

@ -20,16 +20,16 @@
import sys
try:
import MySQLdb
mysqlLibFound=True
import MySQLdb
mysqlLibFound=True
except:
pass
pass
try:
import psycopg2
pgsqlLibFound=True
import psycopg2
pgsqlLibFound=True
except:
pass
pass
import traceback
import math
@ -42,274 +42,281 @@ from time import time
class Importer:
def __init__(self, caller, settings, config):
"""Constructor"""
self.settings=settings
self.caller=caller
self.config = config
self.db = None
self.cursor = None
self.filelist = {}
self.dirlist = {}
self.monitor = False
self.updated = {} #Time last import was run {file:mtime}
self.lines = None
self.faobs = None #File as one big string
self.pos_in_file = {} # dict to remember how far we have read in the file
#Set defaults
self.callHud = self.config.get_import_parameters().get("callFpdbHud")
if not self.settings.has_key('minPrint'):
self.settings['minPrint'] = 30
self.dbConnect()
def __init__(self, caller, settings, config):
"""Constructor"""
self.settings=settings
self.caller=caller
self.config = config
self.db = None
self.cursor = None
self.filelist = {}
self.dirlist = {}
self.monitor = False
self.updated = {} #Time last import was run {file:mtime}
self.lines = None
self.faobs = None #File as one big string
self.pos_in_file = {} # dict to remember how far we have read in the file
#Set defaults
self.callHud = self.config.get_import_parameters().get("callFpdbHud")
if not self.settings.has_key('minPrint'):
self.settings['minPrint'] = 30
self.dbConnect()
def dbConnect(self):
#connect to DB
if self.settings['db-backend'] == 2:
if not mysqlLibFound:
raise fpdb_simple.FpdbError("interface library MySQLdb not found but MySQL selected as backend - please install the library or change the config file")
self.db = MySQLdb.connect(self.settings['db-host'], self.settings['db-user'],
self.settings['db-password'], self.settings['db-databaseName'])
elif self.settings['db-backend'] == 3:
if not pgsqlLibFound:
raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file")
print self.settings
self.db = psycopg2.connect(host = self.settings['db-host'],
user = self.settings['db-user'],
password = self.settings['db-password'],
database = self.settings['db-databaseName'])
elif self.settings['db-backend'] == 4:
pass
else:
pass
self.cursor = self.db.cursor()
# XXX: Why is this here, when fpdb_db.connect() already does the
# same?
def dbConnect(self):
#connect to DB
if self.settings['db-backend'] == 2:
if not mysqlLibFound:
raise fpdb_simple.FpdbError("interface library MySQLdb not found but MySQL selected as backend - please install the library or change the config file")
self.db = MySQLdb.connect(self.settings['db-host'], self.settings['db-user'],
self.settings['db-password'], self.settings['db-databaseName'])
elif self.settings['db-backend'] == 3:
if not pgsqlLibFound:
raise fpdb_simple.FpdbError("interface library psycopg2 not found but PostgreSQL selected as backend - please install the library or change the config file")
print self.settings
if not self.settings.has_key('db-host') or \
not self.settings.has_key('db-user'):
self.db = psycopg2.connect(host = self.settings['db-host'],
user = self.settings['db-user'],
password = self.settings['db-password'],
database = self.settings['db-databaseName'])
else:
dbname = self.settings['db-databaseName']
self.db = psycopg2.connect(database = dbname)
elif self.settings['db-backend'] == 4:
pass
else:
pass
self.cursor = self.db.cursor()
#Set functions
def setCallHud(self, value):
self.callHud = value
#Set functions
def setCallHud(self, value):
self.callHud = value
def setMinPrint(self, value):
self.settings['minPrint'] = int(value)
def setMinPrint(self, value):
self.settings['minPrint'] = int(value)
def setHandCount(self, value):
self.settings['handCount'] = int(value)
def setHandCount(self, value):
self.settings['handCount'] = int(value)
def setQuiet(self, value):
self.settings['quiet'] = value
def setQuiet(self, value):
self.settings['quiet'] = value
def setFailOnError(self, value):
self.settings['failOnError'] = value
def setFailOnError(self, value):
self.settings['failOnError'] = value
# def setWatchTime(self):
# self.updated = time()
# def setWatchTime(self):
# self.updated = time()
def clearFileList(self):
self.filelist = {}
def clearFileList(self):
self.filelist = {}
#Add an individual file to filelist
def addImportFile(self, filename, site = "default", filter = "passthrough"):
#TODO: test it is a valid file
self.filelist[filename] = [site] + [filter]
#Add an individual file to filelist
def addImportFile(self, filename, site = "default", filter = "passthrough"):
#TODO: test it is a valid file
self.filelist[filename] = [site] + [filter]
#Add a directory of files to filelist
#Only one import directory per site supported.
#dirlist is a hash of lists:
#dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] }
def addImportDirectory(self,dir,monitor = False, site = "default", filter = "passthrough"):
if os.path.isdir(dir):
if monitor == True:
self.monitor = True
self.dirlist[site] = [dir] + [filter]
#Add a directory of files to filelist
#Only one import directory per site supported.
#dirlist is a hash of lists:
#dirlist{ 'PokerStars' => ["/path/to/import/", "filtername"] }
def addImportDirectory(self,dir,monitor = False, site = "default", filter = "passthrough"):
if os.path.isdir(dir):
if monitor == True:
self.monitor = True
self.dirlist[site] = [dir] + [filter]
for file in os.listdir(dir):
self.addImportFile(os.path.join(dir, file), site, filter)
else:
print "Warning: Attempted to add: '" + str(dir) + "' as an import directory"
for file in os.listdir(dir):
self.addImportFile(os.path.join(dir, file), site, filter)
else:
print "Warning: Attempted to add: '" + str(dir) + "' as an import directory"
#Run full import on filelist
def runImport(self):
for file in self.filelist:
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
#Run full import on filelist
def runImport(self):
for file in self.filelist:
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
#Run import on updated files, then store latest update time.
def runUpdated(self):
#Check for new files in directory
#todo: make efficient - always checks for new file, should be able to use mtime of directory
# ^^ May not work on windows
for site in self.dirlist:
self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1])
#Run import on updated files, then store latest update time.
def runUpdated(self):
#Check for new files in directory
#todo: make efficient - always checks for new file, should be able to use mtime of directory
# ^^ May not work on windows
for site in self.dirlist:
self.addImportDirectory(self.dirlist[site][0], False, site, self.dirlist[site][1])
for file in self.filelist:
stat_info = os.stat(file)
try:
lastupdate = self.updated[file]
if stat_info.st_mtime > lastupdate:
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
self.updated[file] = time()
except:
self.updated[file] = time()
# This codepath only runs first time the file is found, if modified in the last
# minute run an immediate import.
if (time() - stat_info.st_mtime) < 60:
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
for file in self.filelist:
stat_info = os.stat(file)
try:
lastupdate = self.updated[file]
if stat_info.st_mtime > lastupdate:
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
self.updated[file] = time()
except:
self.updated[file] = time()
# This codepath only runs first time the file is found, if modified in the last
# minute run an immediate import.
if (time() - stat_info.st_mtime) < 60:
self.import_file_dict(file, self.filelist[file][0], self.filelist[file][1])
# This is now an internal function that should not be called directly.
def import_file_dict(self, file, site, filter):
if(filter == "passthrough"):
self.import_fpdb_file(file, site)
else:
#Load filter, and run filtered file though main importer
self.import_fpdb_file(file, site)
# This is now an internal function that should not be called directly.
def import_file_dict(self, file, site, filter):
if(filter == "passthrough"):
self.import_fpdb_file(file, site)
else:
#Load filter, and run filtered file though main importer
self.import_fpdb_file(file, site)
def import_fpdb_file(self, file, site):
starttime = time()
last_read_hand=0
loc = 0
if (file=="stdin"):
inputFile=sys.stdin
else:
inputFile=open(file, "rU")
try: loc = self.pos_in_file[file]
except: pass
def import_fpdb_file(self, file, site):
starttime = time()
last_read_hand=0
loc = 0
if (file=="stdin"):
inputFile=sys.stdin
else:
inputFile=open(file, "rU")
try: loc = self.pos_in_file[file]
except: pass
# Read input file into class and close file
inputFile.seek(loc)
self.lines=fpdb_simple.removeTrailingEOL(inputFile.readlines())
self.pos_in_file[file] = inputFile.tell()
inputFile.close()
# Read input file into class and close file
inputFile.seek(loc)
self.lines=fpdb_simple.removeTrailingEOL(inputFile.readlines())
self.pos_in_file[file] = inputFile.tell()
inputFile.close()
try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return.
firstline = self.lines[0]
except:
# print "import_fpdb_file", file, site, self.lines, "\n"
return
try: # sometimes we seem to be getting an empty self.lines, in which case, we just want to return.
firstline = self.lines[0]
except:
# print "import_fpdb_file", file, site, self.lines, "\n"
return
if firstline.find("Tournament Summary")!=-1:
print "TODO: implement importing tournament summaries"
#self.faobs = readfile(inputFile)
#self.parseTourneyHistory()
return 0
site=fpdb_simple.recogniseSite(firstline)
category=fpdb_simple.recogniseCategory(firstline)
if firstline.find("Tournament Summary")!=-1:
print "TODO: implement importing tournament summaries"
#self.faobs = readfile(inputFile)
#self.parseTourneyHistory()
return 0
site=fpdb_simple.recogniseSite(firstline)
category=fpdb_simple.recogniseCategory(firstline)
startpos=0
stored=0 #counter
duplicates=0 #counter
partial=0 #counter
errors=0 #counter
startpos=0
stored=0 #counter
duplicates=0 #counter
partial=0 #counter
errors=0 #counter
for i in range (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method
if (len(self.lines[i])<2):
endpos=i
hand=self.lines[startpos:endpos]
if (len(hand[0])<2):
hand=hand[1:]
cancelled=False
damaged=False
if (site=="ftp"):
for i in range (len(hand)):
if (hand[i].endswith(" has been canceled")): #this is their typo. this is a typo, right?
cancelled=True
seat1=hand[i].find("Seat ") #todo: make this recover by skipping this line
if (seat1!=-1):
if (hand[i].find("Seat ", seat1+3)!=-1):
damaged=True
if (len(hand)<3):
pass
#todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work.
elif (hand[0].endswith(" (partial)")): #partial hand - do nothing
partial+=1
elif (hand[1].find("Seat")==-1 and hand[2].find("Seat")==-1 and hand[3].find("Seat")==-1):#todo: should this be or instead of and?
partial+=1
elif (cancelled or damaged):
partial+=1
else: #normal processing
isTourney=fpdb_simple.isTourney(hand[0])
if not isTourney:
fpdb_simple.filterAnteBlindFold(site,hand)
hand=fpdb_simple.filterCrap(site, hand, isTourney)
self.hand=hand
try:
handsId=fpdb_parse_logic.mainParser(self.db, self.cursor, site, category, hand)
self.db.commit()
stored+=1
self.db.commit()
if self.callHud:
#print "call to HUD here. handsId:",handsId
#pipe the Hands.id out to the HUD
self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep)
except fpdb_simple.DuplicateError:
duplicates+=1
except (ValueError), fe:
errors+=1
self.printEmailErrorMessage(errors, file, hand)
if (self.settings['failOnError']):
self.db.commit() #dont remove this, in case hand processing was cancelled.
raise
except (fpdb_simple.FpdbError), fe:
errors+=1
self.printEmailErrorMessage(errors, file, hand)
for i in range (len(self.lines)): #main loop, iterates through the lines of a file and calls the appropriate parser method
if (len(self.lines[i])<2):
endpos=i
hand=self.lines[startpos:endpos]
if (len(hand[0])<2):
hand=hand[1:]
cancelled=False
damaged=False
if (site=="ftp"):
for i in range (len(hand)):
if (hand[i].endswith(" has been canceled")): #this is their typo. this is a typo, right?
cancelled=True
seat1=hand[i].find("Seat ") #todo: make this recover by skipping this line
if (seat1!=-1):
if (hand[i].find("Seat ", seat1+3)!=-1):
damaged=True
if (len(hand)<3):
pass
#todo: the above 2 lines are kind of a dirty hack, the mentioned circumstances should be handled elsewhere but that doesnt work with DOS/Win EOL. actually this doesnt work.
elif (hand[0].endswith(" (partial)")): #partial hand - do nothing
partial+=1
elif (hand[1].find("Seat")==-1 and hand[2].find("Seat")==-1 and hand[3].find("Seat")==-1):#todo: should this be or instead of and?
partial+=1
elif (cancelled or damaged):
partial+=1
else: #normal processing
isTourney=fpdb_simple.isTourney(hand[0])
if not isTourney:
fpdb_simple.filterAnteBlindFold(site,hand)
hand=fpdb_simple.filterCrap(site, hand, isTourney)
self.hand=hand
try:
handsId=fpdb_parse_logic.mainParser(self.db, self.cursor, site, category, hand)
self.db.commit()
stored+=1
self.db.commit()
if self.callHud:
#print "call to HUD here. handsId:",handsId
#pipe the Hands.id out to the HUD
self.caller.pipe_to_hud.stdin.write("%s" % (handsId) + os.linesep)
except fpdb_simple.DuplicateError:
duplicates+=1
except (ValueError), fe:
errors+=1
self.printEmailErrorMessage(errors, file, hand)
if (self.settings['failOnError']):
self.db.commit() #dont remove this, in case hand processing was cancelled.
raise
except (fpdb_simple.FpdbError), fe:
errors+=1
self.printEmailErrorMessage(errors, file, hand)
#fe.printStackTrace() #todo: get stacktrace
self.db.rollback()
if (self.settings['failOnError']):
self.db.commit() #dont remove this, in case hand processing was cancelled.
raise
if (self.settings['minPrint']!=0):
if ((stored+duplicates+partial+errors)%self.settings['minPrint']==0):
print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors
if (self.settings['handCount']!=0):
if ((stored+duplicates+partial+errors)>=self.settings['handCount']):
if (not self.settings['quiet']):
print "quitting due to reaching the amount of hands to be imported"
print "Total stored:", stored, "duplicates:", duplicates, "partial/damaged:", partial, "errors:", errors, " time:", (time() - starttime)
sys.exit(0)
startpos=endpos
print "Total stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", (time() - starttime)
if stored==0:
if duplicates>0:
for line_no in range(len(self.lines)):
if self.lines[line_no].find("Game #")!=-1:
final_game_line=self.lines[line_no]
handsId=fpdb_simple.parseSiteHandNo(final_game_line)
else:
print "failed to read a single hand from file:", inputFile
handsId=0
#todo: this will cause return of an unstored hand number if the last hand was error or partial
self.db.commit()
self.handsId=handsId
return handsId
#fe.printStackTrace() #todo: get stacktrace
self.db.rollback()
if (self.settings['failOnError']):
self.db.commit() #dont remove this, in case hand processing was cancelled.
raise
if (self.settings['minPrint']!=0):
if ((stored+duplicates+partial+errors)%self.settings['minPrint']==0):
print "stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors
if (self.settings['handCount']!=0):
if ((stored+duplicates+partial+errors)>=self.settings['handCount']):
if (not self.settings['quiet']):
print "quitting due to reaching the amount of hands to be imported"
print "Total stored:", stored, "duplicates:", duplicates, "partial/damaged:", partial, "errors:", errors, " time:", (time() - starttime)
sys.exit(0)
startpos=endpos
print "Total stored:", stored, "duplicates:", duplicates, "partial:", partial, "errors:", errors, " time:", (time() - starttime)
if stored==0:
if duplicates>0:
for line_no in range(len(self.lines)):
if self.lines[line_no].find("Game #")!=-1:
final_game_line=self.lines[line_no]
handsId=fpdb_simple.parseSiteHandNo(final_game_line)
else:
print "failed to read a single hand from file:", inputFile
handsId=0
#todo: this will cause return of an unstored hand number if the last hand was error or partial
self.db.commit()
self.handsId=handsId
return handsId
#end def import_file_dict
def parseTourneyHistory(self):
print "Tourney history parser stub"
#Find tournament boundaries.
#print self.foabs
def parseTourneyHistory(self):
print "Tourney history parser stub"
#Find tournament boundaries.
#print self.foabs
def printEmailErrorMessage(self, errors, filename, line):
traceback.print_exc(file=sys.stderr)
print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it."
print "Filename:", filename
print "Here is the first line so you can identify it. Please mention that the error was a ValueError:"
print self.hand[0]
print "Hand logged to hand-errors.txt"
logfile = open('hand-errors.txt', 'a')
for s in self.hand:
logfile.write(str(s) + "\n")
logfile.write("\n")
logfile.close()
def printEmailErrorMessage(self, errors, filename, line):
traceback.print_exc(file=sys.stderr)
print "Error No.",errors,", please send the hand causing this to steffen@sycamoretest.info so I can fix it."
print "Filename:", filename
print "Here is the first line so you can identify it. Please mention that the error was a ValueError:"
print self.hand[0]
print "Hand logged to hand-errors.txt"
logfile = open('hand-errors.txt', 'a')
for s in self.hand:
logfile.write(str(s) + "\n")
logfile.write("\n")
logfile.close()
if __name__ == "__main__":
print "CLI for fpdb_import is now available as CliFpdb.py"
print "CLI for fpdb_import is now available as CliFpdb.py"