diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 639007f1..9c7e44b6 100644 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -52,44 +52,41 @@ def get_default_config_path(): return config_path def get_exec_path(): - """Returns the path to the fpdb.(py|exe) file we are executing""" + """Returns the path to the fpdb(dir|.exe) file we are executing""" if hasattr(sys, "frozen"): # compiled by py2exe return os.path.dirname(sys.executable) else: - return sys.path[0] + return os.path.dirname(sys.path[0]) # should be path to /fpdb def get_config(file_name, fallback = True): """Looks in cwd and in self.default_config_path for a config file.""" exec_dir = get_exec_path() - config_path = os.path.join(exec_dir, file_name) + if file_name == 'logging.conf': + config_path = os.path.join(exec_dir, 'pyfpdb', file_name) + else: + config_path = os.path.join(exec_dir, file_name) # print "config_path=", config_path if os.path.exists(config_path): # there is a file in the cwd - return config_path # so we use it + return (config_path,False) # so we use it 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,False) # No file found if not fallback: - return False + return (False,False) # OK, fall back to the .example file, should be in the start dir if os.path.exists(file_name + ".example"): try: print "" - if not os.path.isdir(default_dir): - msg = "Creating directory: '%s'" % (default_dir) - print msg - logging.info(msg) - os.mkdir(default_dir) + check_dir(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." + msg = "No %s found\n in %s\n or %s\n" % (file_name, exec_dir, default_dir) \ + + "Config file has been created at %s.\n" % config_path print msg logging.info(msg) file_name = config_path @@ -102,13 +99,19 @@ def get_config(file_name, fallback = True): print "No %s found, cannot fall back. Exiting.\n" % file_name sys.stderr.write("No %s found, cannot fall back. Exiting.\n" % file_name) sys.exit() - return file_name + return (file_name,True) -def get_logger(file_name, config = "config", fallback = False): - conf = get_config(file_name, fallback = fallback) - if conf: +def get_logger(file_name, config = "config", fallback = False, log_dir=None): + (conf_file,copied) = get_config(file_name, fallback = fallback) + if conf_file: try: - logging.config.fileConfig(conf) + if log_dir is None: + log_dir = os.path.join(get_exec_path(), 'log') + check_dir(log_dir) + file = os.path.join(log_dir, 'logging.out') + file = file.replace('\\', '\\\\') # replace each \ with \\ +# print " ="+file+" "+ str(type(file))+" len="+str(len(file))+"\n" + logging.config.fileConfig(conf_file, {"logFile":file}) log = logging.getLogger(config) log.debug("%s logger initialised" % config) return log @@ -120,8 +123,23 @@ def get_logger(file_name, config = "config", fallback = False): log.debug("config logger initialised") return log +def check_dir(path, create = True): + """Check if a dir exists, optionally creates if not.""" + if os.path.exists(path): + if os.path.isdir(path): + return path + else: + return False + if create: + msg = "Creating directory: '%s'" % (path) + print msg + log.info(msg) + os.mkdir(path) + else: + return False + # find a logging.conf file and set up logging -log = get_logger("logging.conf") +log = get_logger("logging.conf", "config") ######################################################################## # application wide consts @@ -421,11 +439,11 @@ class Tv: class Config: def __init__(self, file = None, dbname = ''): - # "file" is a path to an xml file with the fpdb/HUD configuration # we check the existence of "file" and try to recover if it doesn't exist # self.default_config_path = self.get_default_config_path() + self.example_copy = False if file is not None: # config file path passed in file = os.path.expanduser(file) if not os.path.exists(file): @@ -433,7 +451,14 @@ class Config: sys.stderr.write("Configuration file %s not found. Using defaults." % (file)) file = None - if file is None: file = get_config("HUD_config.xml", True) + if file is None: (file,self.example_copy) = get_config("HUD_config.xml", True) + + self.file = file + self.dir_self = get_exec_path() + self.dir_config = os.path.dirname(self.file) + self.dir_log = os.path.join(self.dir_config, 'log') + self.dir_database = os.path.join(self.dir_config, 'database') + log = get_logger("logging.conf", "config", log_dir=self.dir_log) # Parse even if there was no real config file found and we are using the example # If using the example, we'll edit it later @@ -449,9 +474,6 @@ class Config: sys.exit() self.doc = doc - self.file = file - self.dir = os.path.dirname(self.file) - self.dir_databases = os.path.join(self.dir, 'database') self.supported_sites = {} self.supported_games = {} self.supported_databases = {} # databaseName --> Database instance diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 754af54a..ebdfceaa 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -224,6 +224,7 @@ class Database: def __init__(self, c, sql = None): + log = Configuration.get_logger("logging.conf", "db", log_dir=c.dir_log) log.info("Creating Database instance, sql = %s" % sql) self.config = c self.__connected = False @@ -379,11 +380,11 @@ class Database: log.warning("SQLite won't work well without 'sqlalchemy' installed.") if database != ":memory:": - if not os.path.isdir(self.config.dir_databases): - print "Creating directory: '%s'" % (self.config.dir_databases) - log.info("Creating directory: '%s'" % (self.config.dir_databases)) - os.mkdir(self.config.dir_databases) - database = os.path.join(self.config.dir_databases, database) + if not os.path.isdir(self.config.dir_database): + print "Creating directory: '%s'" % (self.config.dir_database) + log.info("Creating directory: '%s'" % (self.config.dir_database)) + os.mkdir(self.config.dir_database) + database = os.path.join(self.config.dir_database, database) log.info("Connecting to SQLite: %(database)s" % {'database':database}) print "Connecting to SQLite: %(database)s" % {'database':database} self.connection = sqlite3.connect(database, detect_types=sqlite3.PARSE_DECLTYPES ) @@ -787,6 +788,7 @@ class Database: def get_player_id(self, config, site, player_name): c = self.connection.cursor() + #print "get_player_id: player_name =", player_name, type(player_name) p_name = Charset.to_utf8(player_name) c.execute(self.sql.query['get_player_id'], (p_name, site)) row = c.fetchone() diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 628f7b7f..339ce968 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -194,7 +194,8 @@ class GuiAutoImport (threading.Thread): widget.set_label(u' _Stop Autoimport ') if self.pipe_to_hud is None: if os.name == 'nt': - command = "python "+sys.path[0]+"\\HUD_main.py " + self.settings['cl_options'] + path = sys.path[0].replace('\\','\\\\') + command = 'python "'+path+'\\HUD_main.py" ' + self.settings['cl_options'] bs = 0 else: command = os.path.join(sys.path[0], 'HUD_main.py') diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index df144e92..c792d802 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -51,10 +51,8 @@ import gobject # FreePokerTools modules import Configuration -print "start logging" log = Configuration.get_logger("logging.conf", config = 'hud') -log.debug("%s logger initialized." % "dud") -print "logging started" +log.debug("%s logger initialized." % "hud") import Database @@ -68,36 +66,40 @@ elif os.name == 'nt': import Hud -log = Configuration.get_logger("logging.conf") - - class HUD_main(object): """A main() object to own both the read_stdin thread and the gui.""" # This class mainly provides state for controlling the multiple HUDs. def __init__(self, db_name = 'fpdb'): - self.db_name = db_name - self.log = log - self.config = Configuration.Config(file=options.config, dbname=options.dbname) - self.hud_dict = {} - self.hud_params = self.config.get_hud_ui_parameters() + try: + print "HUD_main: starting ..." + self.db_name = db_name + self.config = Configuration.Config(file=options.config, dbname=options.dbname) + log = Configuration.get_logger("logging.conf", "hud", log_dir=self.config.dir_log) + log.debug("starting ...") + self.hud_dict = {} + self.hud_params = self.config.get_hud_ui_parameters() -# a thread to read stdin - gobject.threads_init() # this is required - thread.start_new_thread(self.read_stdin, ()) # starts the thread + # a thread to read stdin + gobject.threads_init() # this is required + thread.start_new_thread(self.read_stdin, ()) # starts the thread + + # a main window + self.main_window = gtk.Window() + self.main_window.connect("destroy", self.destroy) + self.vb = gtk.VBox() + self.label = gtk.Label('Closing this window will exit from the HUD.') + self.vb.add(self.label) + self.main_window.add(self.vb) + self.main_window.set_title("HUD Main Window") + self.main_window.show_all() + except: + log.debug("commit "+str(i)+" failed: info=" + str(sys.exc_info()) + + " value=" + str(sys.exc_value)) -# a main window - self.main_window = gtk.Window() - self.main_window.connect("destroy", self.destroy) - self.vb = gtk.VBox() - self.label = gtk.Label('Closing this window will exit from the HUD.') - self.vb.add(self.label) - self.main_window.add(self.vb) - self.main_window.set_title("HUD Main Window") - self.main_window.show_all() def destroy(self, *args): # call back for terminating the main eventloop - self.log.info("Terminating normally.") + log.info("Terminating normally.") gtk.main_quit() def kill_hud(self, event, table): @@ -205,7 +207,7 @@ class HUD_main(object): t0 = time.time() t1 = t2 = t3 = t4 = t5 = t6 = t0 new_hand_id = string.rstrip(new_hand_id) - self.log.debug("Received hand no %s" % new_hand_id) + log.debug("Received hand no %s" % 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() @@ -217,7 +219,7 @@ class HUD_main(object): (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) except Exception, err: - self.log.error("db error: skipping %s" % new_hand_id) + log.error("db error: skipping %s" % new_hand_id) continue t1 = time.time() @@ -276,7 +278,7 @@ class HUD_main(object): if type == "tour": table_name = "%s %s" % (tour_number, tab_number) # sys.stderr.write("HUD create: table name "+table_name+" not found, skipping.\n") - self.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: tablewindow.max = max tablewindow.site = site_name diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 9c7ea23f..0f69121a 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -28,12 +28,14 @@ from decimal import Decimal import operator import time,datetime from copy import deepcopy -from Exceptions import * import pprint + +import Configuration +from Exceptions import * import DerivedStats import Card -log = logging.getLogger("parser") +log = Configuration.get_logger("logging.conf", "parser") class Hand(object): @@ -46,7 +48,9 @@ class Hand(object): SITEIDS = {'Fulltilt':1, 'PokerStars':2, 'Everleaf':3, 'Win2day':4, 'OnGame':5, 'UltimateBet':6, 'Betfair':7, 'Absolute':8, 'PartyPoker':9, 'Partouche':10, 'Carbon':11 } - def __init__(self, sitename, gametype, handText, builtFrom = "HHC"): + def __init__(self, config, sitename, gametype, handText, builtFrom = "HHC"): + self.config = config + log = Configuration.get_logger("logging.conf", "db", log_dir=self.config.dir_log) self.sitename = sitename self.siteId = self.SITEIDS[sitename] self.stats = DerivedStats.DerivedStats(self) @@ -617,7 +621,8 @@ Map the tuple self.gametype onto the pokerstars string describing it class HoldemOmahaHand(Hand): - def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None): + def __init__(self, config, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None): + self.config = config if gametype['base'] != 'hold': pass # or indeed don't pass and complain instead log.debug("HoldemOmahaHand") @@ -625,7 +630,7 @@ class HoldemOmahaHand(Hand): self.holeStreets = ['PREFLOP'] self.communityStreets = ['FLOP', 'TURN', 'RIVER'] self.actionStreets = ['BLINDSANTES','PREFLOP','FLOP','TURN','RIVER'] - Hand.__init__(self, sitename, gametype, handText, builtFrom = "HHC") + Hand.__init__(self, self.config, sitename, gametype, handText, builtFrom = "HHC") self.sb = gametype['sb'] self.bb = gametype['bb'] @@ -916,7 +921,8 @@ class HoldemOmahaHand(Hand): print >>fh, "\n\n" class DrawHand(Hand): - def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"): + def __init__(self, config, hhc, sitename, gametype, handText, builtFrom = "HHC"): + self.config = config if gametype['base'] != 'draw': pass # or indeed don't pass and complain instead self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] @@ -924,7 +930,7 @@ class DrawHand(Hand): self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] self.actionStreets = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] self.communityStreets = [] - Hand.__init__(self, sitename, gametype, handText) + Hand.__init__(self, self.config, sitename, gametype, handText) self.sb = gametype['sb'] self.bb = gametype['bb'] # Populate the draw hand. @@ -1108,7 +1114,8 @@ class DrawHand(Hand): class StudHand(Hand): - def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"): + def __init__(self, config, hhc, sitename, gametype, handText, builtFrom = "HHC"): + self.config = config if gametype['base'] != 'stud': pass # or indeed don't pass and complain instead @@ -1118,7 +1125,7 @@ class StudHand(Hand): self.streetList = ['BLINDSANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order self.holeStreets = ['THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] - Hand.__init__(self, sitename, gametype, handText) + Hand.__init__(self, self.config, sitename, gametype, handText) self.sb = gametype['sb'] self.bb = gametype['bb'] #Populate the StudHand @@ -1511,7 +1518,8 @@ limit 1""", {'handid':handid}) #TODO: siteid should be in hands table - we took the scenic route through players here. res = c.fetchone() gametype = {'category':res[1],'base':res[2],'type':res[3],'limitType':res[4],'hilo':res[5],'sb':res[6],'bb':res[7], 'currency':res[10]} - h = HoldemOmahaHand(hhc = None, sitename=res[0], gametype = gametype, handText=None, builtFrom = "DB", handid=handid) + c = Configuration.Config() + h = HoldemOmahaHand(config = c, hhc = None, sitename=res[0], gametype = gametype, handText=None, builtFrom = "DB", handid=handid) cards = map(Card.valueSuitFromCard, res[11:16] ) if cards[0]: h.setCommunityCards('FLOP', cards[0:3]) diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index bec2ebae..45760ee6 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -16,8 +16,6 @@ #In the "official" distribution you can find the license in #agpl-3.0.txt in the docs folder of the package. -import Hand -import Tourney import re import sys import traceback @@ -31,13 +29,16 @@ import operator from xml.dom.minidom import Node import time import datetime + +import Hand +import Tourney from Exceptions import FpdbParseError import Configuration import gettext gettext.install('fpdb') -log = Configuration.get_logger("logging.conf") +log = Configuration.get_logger("logging.conf", "parser") import pygtk import gtk @@ -57,12 +58,14 @@ class HandHistoryConverter(): codepage = "cp1252" - def __init__(self, in_path = '-', out_path = '-', follow=False, index=0, autostart=True, starsArchive=False): + def __init__(self, config, in_path = '-', out_path = '-', follow=False, index=0, autostart=True, starsArchive=False): """\ in_path (default '-' = sys.stdin) out_path (default '-' = sys.stdout) follow : whether to tail -f the input""" + self.config = config + log = Configuration.get_logger("logging.conf", "parser", log_dir=self.config.dir_log) log.info("HandHistory init - %s subclass, in_path '%s'; out_path '%s'" % (self.sitename, in_path, out_path) ) self.index = index @@ -283,11 +286,11 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. if l in self.readSupportedGames(): if gametype['base'] == 'hold': log.debug("hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handtext)") - hand = Hand.HoldemOmahaHand(self, self.sitename, gametype, handText) + hand = Hand.HoldemOmahaHand(self.config, self, self.sitename, gametype, handText) elif gametype['base'] == 'stud': - hand = Hand.StudHand(self, self.sitename, gametype, handText) + hand = Hand.StudHand(self.config, self, self.sitename, gametype, handText) elif gametype['base'] == 'draw': - hand = Hand.DrawHand(self, self.sitename, gametype, handText) + hand = Hand.DrawHand(self.config, self, self.sitename, gametype, handText) else: log.info("Unsupported game type: %s" % gametype) @@ -417,7 +420,7 @@ or None if we fail to get the info """ list.pop() #Last entry is empty for l in list: # print "'" + l + "'" - hands = hands + [Hand.Hand(self.sitename, self.gametype, l)] + hands = hands + [Hand.Hand(self.config, self.sitename, self.gametype, l)] # TODO: This looks like it could be replaced with a list comp.. ? return hands diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index f202698d..58e0128d 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -695,6 +695,12 @@ class fpdb: def load_profile(self): """Loads profile from the provided path name.""" self.config = Configuration.Config(file=options.config, dbname=options.dbname) + log = Configuration.get_logger("logging.conf", "fpdb", log_dir=self.config.dir_log) + if self.config.example_copy: + self.info_box( "Config file" + , "has been created at:\n%s.\n" % self.config.file + + "Edit your screen_name and hand history path in the supported_sites " + + "section of the Preferences window (Main menu) before trying to import hands.") self.settings = {} self.settings['global_lock'] = self.lock if (os.sep=="/"): @@ -962,16 +968,24 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.window.show() self.window.present() + def info_box(self, str1, str2): + diapath = gtk.MessageDialog( parent=None, flags=0, type=gtk.MESSAGE_INFO + , buttons=(gtk.BUTTONS_OK), message_format=str1 ) + diapath.format_secondary_text(str2) + response = diapath.run() + diapath.destroy() + return response + def warning_box(self, str, diatitle="FPDB WARNING"): - diaWarning = gtk.Dialog(title=diatitle, parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) + diaWarning = gtk.Dialog(title=diatitle, parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) - label = gtk.Label(str) - diaWarning.vbox.add(label) - label.show() + label = gtk.Label(str) + diaWarning.vbox.add(label) + label.show() - response = diaWarning.run() - diaWarning.destroy() - return response + response = diaWarning.run() + diaWarning.destroy() + return response def validate_config(self): hhbase = self.config.get_import_parameters().get("hhArchiveBase") diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 859a6bc0..a02d3d99 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -65,6 +65,7 @@ class Importer: self.config = config self.sql = sql + log = Configuration.get_logger("logging.conf", "importer", log_dir=self.config.dir_log) self.filelist = {} self.dirlist = {} self.siteIds = {} @@ -429,7 +430,7 @@ class Importer: idx = self.pos_in_file[file] else: self.pos_in_file[file] = 0 - hhc = obj(in_path = file, out_path = out_path, index = idx, starsArchive = self.settings['starsArchive']) + hhc = obj(self.config, in_path = file, out_path = out_path, index = idx, starsArchive = self.settings['starsArchive']) if hhc.getStatus(): handlist = hhc.getProcessedHands() self.pos_in_file[file] = hhc.getLastCharacterRead() diff --git a/pyfpdb/logging.conf b/pyfpdb/logging.conf index 1b54b453..a7c0323f 100644 --- a/pyfpdb/logging.conf +++ b/pyfpdb/logging.conf @@ -1,64 +1,69 @@ [loggers] -keys=root,parser,importer,config,db +keys=root,fpdb,logview,parser,importer,config,db,hud [handlers] -keys=consoleHandler,fileHandler +keys=consoleHandler,rotatingFileHandler [formatters] keys=fileFormatter,stderrFormatter [logger_root] level=INFO -handlers=consoleHandler,fileHandler +handlers=consoleHandler,rotatingFileHandler [logger_fpdb] level=INFO -handlers=consoleHandler,fileHandler +handlers=consoleHandler,rotatingFileHandler qualname=fpdb propagate=0 [logger_logview] level=INFO -handlers=consoleHandler,fileHandler +handlers=consoleHandler,rotatingFileHandler qualname=logview propagate=0 [logger_parser] level=INFO -handlers=consoleHandler,fileHandler +handlers=consoleHandler,rotatingFileHandler qualname=parser propagate=0 [logger_importer] level=DEBUG -handlers=consoleHandler,fileHandler +handlers=consoleHandler,rotatingFileHandler qualname=importer propagate=0 [logger_config] level=INFO -handlers=consoleHandler,fileHandler +handlers=consoleHandler,rotatingFileHandler qualname=config propagate=0 [logger_db] level=DEBUG -handlers=consoleHandler,fileHandler +handlers=consoleHandler,rotatingFileHandler qualname=db propagate=0 +[logger_hud] +level=DEBUG +handlers=consoleHandler,rotatingFileHandler +qualname=hud +propagate=0 + [handler_consoleHandler] class=StreamHandler level=ERROR formatter=stderrFormatter args=(sys.stderr,) -[handler_fileHandler] -class=FileHandler +[handler_rotatingFileHandler] +class=handlers.RotatingFileHandler level=DEBUG formatter=fileFormatter -args=('logging.out', 'a') - +args=('%(logFile)s', 'a', 100000000, 5) [formatter_fileFormatter] format=%(asctime)s - %(name)-12s %(levelname)-8s %(message)s