diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index dbdf159f..3f183204 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -37,20 +37,79 @@ from xml.dom.minidom import Node import logging, logging.config import ConfigParser -try: # local path - logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf")) -except ConfigParser.NoSectionError: # debian package path - logging.config.fileConfig('/usr/share/python-fpdb/logging.conf') +############################################################################## +# Functions for finding config files and setting up logging +# Also used in other modules that use logging. + +def get_default_config_path(): + """Returns the path where the fpdb config file _should_ be stored.""" + if os.name == 'posix': + config_path = os.path.join(os.path.expanduser("~"), '.fpdb') + elif os.name == 'nt': + config_path = os.path.join(os.environ["APPDATA"], 'fpdb') + else: config_path = False + return config_path + +def get_exec_path(): + """Returns the path to the fpdb.(py|exe) file we are executing""" + if hasattr(sys, "frozen"): # compiled by py2exe + return os.path.dirname(sys.executable) + else: + return os.path.dirname(sys.path[0]) + +def get_config(file_name, fallback = True): + """Looks in cwd and in self.default_config_path for a config file.""" + config_path = os.path.join(get_exec_path(), file_name) + if os.path.exists(config_path): # there is a file in the cwd + return config_path # so we use it + else: # no file in the cwd, look where it should be in the first place + config_path = os.path.join(get_default_config_path(), file_name) + if os.path.exists(config_path): + return config_path + +# No file found + if not fallback: + return False + +# OK, fall back to the .example file, should be in the start dir + if os.path.exists(file_name + ".example"): + try: + shutil.copyfile(file_name + ".example", file_name) + print "No %s found, using %s.example.\n" % (file_name, file_name) + print "A %s file has been created. You will probably have to edit it." % file_name + sys.stderr.write("No %s found, using %s.example.\n" % (file_name, file_name) ) + except: + 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 + +def get_logger(file_name, config = "config", fallback = False): + conf = get_config(file_name, fallback = fallback) + if conf: + try: + logging.config.fileConfig(conf) + log = logging.getLogger(config) + log.debug("%s logger initialised" % config) + return log + except: + pass + + log = logging.basicConfig() + log = logging.getLogger() + log.debug("config logger initialised") + return log + +# find a logging.conf file and set up logging +log = get_logger("logging.conf") -log = logging.getLogger("config") -log.debug("config logger initialised") ######################################################################## # application wide consts APPLICATION_NAME_SHORT = 'fpdb' APPLICATION_VERSION = 'xx.xx.xx' -DIR_SELF = os.path.dirname(os.path.abspath(__file__)) +DIR_SELF = os.path.dirname(get_exec_path()) #TODO: imo no good idea to place 'database' in parent dir DIR_DATABASES = os.path.join(os.path.dirname(DIR_SELF), 'database') @@ -335,7 +394,7 @@ class Config: # "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.default_config_path = self.get_default_config_path() if file is not None: # config file path passed in file = os.path.expanduser(file) if not os.path.exists(file): @@ -343,28 +402,12 @@ class Config: sys.stderr.write("Configuration file %s not found. Using defaults." % (file)) file = None - if file is None: # configuration file path not passed or invalid - file = self.find_config() #Look for a config file in the normal places - - if file is None: # no config file in the normal places - file = self.find_example_config() #Look for an example file to edit - - if file is None: # that didn't work either, just die - print "No HUD_config_xml found after looking in current directory and "+self.default_config_path+"\nExiting" - sys.stderr.write("No HUD_config_xml found after looking in current directory and "+self.default_config_path+"\nExiting") - print "press enter to continue" - sys.stdin.readline() - sys.exit() + if file is None: file = get_config("HUD_config.xml") # 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 -# sc 2009/10/04 Example already copied to main filename, is this ok? log.info("Reading configuration file %s" % file) - if os.sep in file: - print "\nReading configuration file %s\n" % file - else: - print "\nReading configuration file %s" % file - print "in %s\n" % os.getcwd() + print "\nReading configuration file %s\n" % file try: doc = xml.dom.minidom.parse(file) except: @@ -460,28 +503,6 @@ class Config: def set_hhArchiveBase(self, path): self.imp.node.setAttribute("hhArchiveBase", path) - def find_config(self): - """Looks in cwd and in self.default_config_path for a config file.""" - if os.path.exists('HUD_config.xml'): # there is a HUD_config in the cwd - file = 'HUD_config.xml' # so we use it - else: # no HUD_config in the cwd, look where it should be in the first place - config_path = os.path.join(self.default_config_path, 'HUD_config.xml') - if os.path.exists(config_path): - file = config_path - else: - file = None - return file - - def get_default_config_path(self): - """Returns the path where the fpdb config file _should_ be stored.""" - if os.name == 'posix': - config_path = os.path.join(os.path.expanduser("~"), '.fpdb') - elif os.name == 'nt': - config_path = os.path.join(os.environ["APPDATA"], 'fpdb') - else: config_path = None - return config_path - - def find_default_conf(self): if os.name == 'posix': config_path = os.path.join(os.path.expanduser("~"), '.fpdb', 'default.conf') @@ -495,30 +516,6 @@ class Config: file = None return file - def read_default_conf(self, file): - parms = {} - with open(file, "r") as fh: - for line in fh: - line = string.strip(line) - (key, value) = line.split('=') - parms[key] = value - return parms - - def find_example_config(self): - if os.path.exists('HUD_config.xml.example'): # there is a HUD_config in the cwd - file = 'HUD_config.xml' # so we use it - try: - shutil.copyfile(file+'.example', file) - except: - file = '' - print "No HUD_config.xml found, using HUD_config.xml.example.\n", \ - "A HUD_config.xml has been created. You will probably have to edit it." - sys.stderr.write("No HUD_config.xml found, using HUD_config.xml.example.\n" + \ - "A HUD_config.xml has been created. You will probably have to edit it.") - else: - file = None - return file - def get_site_node(self, site): for site_node in self.doc.getElementsByTagName("site"): if site_node.getAttribute("site_name") == site: @@ -948,3 +945,7 @@ if __name__== "__main__": print c.get_game_parameters(game) print "start up path = ", c.execution_path("") + + from xml.dom.ext import PrettyPrint + for site_node in c.doc.getElementsByTagName("site"): + PrettyPrint(site_node, stream=sys.stdout, encoding="utf-8") diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f7e873bc..0314d78d 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -45,16 +45,7 @@ import Card import Tourney from Exceptions import * -import logging, logging.config -import ConfigParser - -try: # local path - logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf")) -except ConfigParser.NoSectionError: # debian package path - logging.config.fileConfig('/usr/share/python-fpdb/logging.conf') - -log = logging.getLogger('db') - +log = Configuration.get_logger("logging.conf") class Database: @@ -2690,13 +2681,11 @@ class HandToWrite: if __name__=="__main__": c = Configuration.Config() - db_connection = Database(c, 'fpdb', 'holdem') # mysql fpdb holdem + db_connection = Database(c) # mysql fpdb holdem # db_connection = Database(c, 'fpdb-p', 'test') # mysql fpdb holdem # db_connection = Database(c, 'PTrackSv2', 'razz') # mysql razz # db_connection = Database(c, 'ptracks', 'razz') # postgres print "database connection object = ", db_connection.connection - print "database type = ", db_connection.type - db_connection.recreate_tables() h = db_connection.get_last_hand() @@ -2710,18 +2699,12 @@ if __name__=="__main__": for p in stat_dict.keys(): print p, " ", stat_dict[p] - #print "nutOmatics stats:" - #stat_dict = db_connection.get_stats_from_hand(h, "ring") - #for p in stat_dict.keys(): - # print p, " ", stat_dict[p] - print "cards =", db_connection.get_cards(u'1') db_connection.close_connection print "press enter to continue" sys.stdin.readline() - #Code borrowed from http://push.cx/2008/caching-dictionaries-in-python-vs-ruby class LambdaDict(dict): def __init__(self, l): diff --git a/pyfpdb/Exceptions.py b/pyfpdb/Exceptions.py index eaf5d798..f7e9fa54 100644 --- a/pyfpdb/Exceptions.py +++ b/pyfpdb/Exceptions.py @@ -9,8 +9,8 @@ class FpdbParseError(FpdbError): self.value = value self.hid = hid def __str__(self): - if hid: - return repr("HID:"+hid+", "+self.value) + if self.hid: + return repr("HID:"+self.hid+", "+self.value) else: return repr(self.value) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 0fce160f..48a412ee 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -53,7 +53,13 @@ import gobject # FreePokerTools modules import Configuration import Database -import Tables +from HandHistoryConverter import getTableTitleRe +# get the correct module for the current os +if os.name == 'posix': + import XTables as Tables +elif os.name == 'nt': + import WinTables as Tables +#import Tables import Hud @@ -131,6 +137,7 @@ class HUD_main(object): # TODO: The purpose of this try/finally block is to make darn sure that threads_leave() # TODO: gets called. If there is an exception and threads_leave() doesn't get called we # TODO: lock up. REB + table.gdkhandle = gtk.gdk.window_foreign_new(table.number) newlabel = gtk.Label("%s - %s" % (table.site, table_name)) self.vb.add(newlabel) newlabel.show() @@ -210,7 +217,7 @@ class HUD_main(object): # get basic info about the new hand from the db # if there is a db error, complain, skip hand, and proceed try: - (table_name, max, poker_game, type, site_id, tour_number, tab_number) = \ + (table_name, max, poker_game, type, site_id, site_name, tour_number, tab_number) = \ self.db_connection.get_table_info(new_hand_id) except Exception, err: print "db error: skipping %s" % new_hand_id @@ -247,16 +254,18 @@ class HUD_main(object): if comm_cards != {}: # stud! cards['common'] = comm_cards['common'] - if type == "tour": - tablewindow = Tables.discover_tournament_table(self.config, tour_number, tab_number) - else: - tablewindow = Tables.discover_table_by_name(self.config, table_name) + table_kwargs = dict(table_name = table_name, tournament = tour_number, table_number = tab_number) + search_string = getTableTitleRe(self.config, site, type, **table_kwargs) + tablewindow = Tables.Table(search_string, **table_kwargs) + if tablewindow is None: # If no client window is found on the screen, complain and continue if type == "tour": table_name = "%s %s" % (tour_number, tab_number) sys.stderr.write("HUD create: table name "+table_name+" not found, skipping.\n") else: + tablewindow.max = max + tablewindow.site = site_name self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, type, stat_dict, cards) self.db_connection.connection.rollback() diff --git a/pyfpdb/HandHistoryConverter.py b/pyfpdb/HandHistoryConverter.py index bced9d93..a662ca79 100644 --- a/pyfpdb/HandHistoryConverter.py +++ b/pyfpdb/HandHistoryConverter.py @@ -32,19 +32,12 @@ from xml.dom.minidom import Node import time import datetime from Exceptions import FpdbParseError +import Configuration import gettext gettext.install('fpdb') -import logging, logging.config -import ConfigParser - -try: - logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf")) -except ConfigParser.NoSectionError: # debian package path - logging.config.fileConfig('/usr/share/python-fpdb/logging.conf') - -log = logging.getLogger("parser") +log = Configuration.get_logger("logging.conf") import pygtk import gtk @@ -154,6 +147,7 @@ Otherwise, finish at EOF. except FpdbParseError, e: numErrors += 1 log.warning("Failed to convert hand %s" % e.hid) + log.warning("Exception msg: '%s'" % str(e)) log.debug(handText) else: handsList = self.allHandsAsList() @@ -168,6 +162,7 @@ Otherwise, finish at EOF. except FpdbParseError, e: numErrors += 1 log.warning("Failed to convert hand %s" % e.hid) + log.warning("Exception msg: '%s'" % str(e)) log.debug(handText) numHands = len(handsList) endtime = time.time() @@ -506,3 +501,26 @@ or None if we fail to get the info """ def getTourney(self): return self.tourney + + @staticmethod + def getTableTitleRe(type, table_name=None, tournament = None, table_number=None): + "Returns string to search in windows titles" + if type=="tour": + return "%s.+Table\s%s" % (tournament, table_number) + else: + return table_name + + + +def getTableTitleRe(config, sitename, *args, **kwargs): + "Returns string to search in windows titles for current site" + return getSiteHhc(config, sitename).getTableTitleRe(*args, **kwargs) + +def getSiteHhc(config, sitename): + "Returns HHC class for current site" + hhcName = config.supported_sites[sitename].converter + hhcModule = __import__(hhcName) + return getattr(hhcModule, hhcName[:-6]) + + + diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py index f0f47898..674b0a09 100644 --- a/pyfpdb/Hud.py +++ b/pyfpdb/Hud.py @@ -386,9 +386,9 @@ class Hud: (x, y) = loc[adj[i+1]] w.relocate(x, y) - # While we're at it, fix the positions of mucked cards too - for aux in self.aux_windows: - aux.update_card_positions() + # While we're at it, fix the positions of mucked cards too + for aux in self.aux_windows: + aux.update_card_positions() return True @@ -440,7 +440,7 @@ class Hud: new_layout[self.stat_windows[sw].adj - 1] = new_loc self.config.edit_layout(self.table.site, self.max, locations = new_layout) # 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 print "saving new xml file" self.config.save() diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index d9e652d9..7f242789 100755 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -92,7 +92,7 @@ class PokerStars(HandHistoryConverter): self.compiledPlayers = players player_re = "(?P" + "|".join(map(re.escape, players)) + ")" subst = {'PLYR': player_re, 'CUR': self.sym[hand.gametype['currency']]} - logging.debug("player_re: " + player_re) + log.debug("player_re: " + player_re) self.re_PostSB = re.compile(r"^%(PLYR)s: posts small blind %(CUR)s(?P[.0-9]+)" % subst, re.MULTILINE) self.re_PostBB = re.compile(r"^%(PLYR)s: posts big blind %(CUR)s(?P[.0-9]+)" % subst, re.MULTILINE) self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante %(CUR)s(?P[.0-9]+)" % subst, re.MULTILINE) @@ -186,7 +186,7 @@ class PokerStars(HandHistoryConverter): # m = self.re_Button.search(hand.handText) # if m: info.update(m.groupdict()) # TODO : I rather like the idea of just having this dict as hand.info - logging.debug("readHandInfo: %s" % info) + log.debug("readHandInfo: %s" % info) for key in info: if key == 'DATETIME': #2008/11/12 10:00:48 CET [2008/11/12 4:00:48 ET] @@ -197,15 +197,6 @@ class PokerStars(HandHistoryConverter): hand.starttime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") if key == 'HID': hand.handid = info[key] - if key == 'TABLE': - hand.tablename = info[key] - if key == 'BUTTON': - hand.buttonpos = info[key] - if key == 'MAX': - hand.maxseats = int(info[key]) - - if key == 'MIXED': - hand.mixed = self.mixes[info[key]] if info[key] is not None else None if key == 'TOURNO': hand.tourNo = info[key] @@ -213,6 +204,19 @@ class PokerStars(HandHistoryConverter): hand.buyin = info[key] if key == 'LEVEL': hand.level = info[key] + + if key == 'TABLE': + if hand.tourNo != None: + hand.tablename = re.split(" ", info[key])[1] + else: + hand.tablename = info[key] + if key == 'BUTTON': + hand.buttonpos = info[key] + if key == 'MAX': + hand.maxseats = int(info[key]) + + if key == 'MIXED': + hand.mixed = self.mixes[info[key]] if info[key] is not None else None if key == 'PLAY' and info['PLAY'] is not None: # hand.currency = 'play' # overrides previously set value hand.gametype['currency'] = 'play' @@ -222,10 +226,10 @@ class PokerStars(HandHistoryConverter): if m: hand.buttonpos = int(m.group('BUTTON')) else: - logging.info('readButton: not found') + log.info('readButton: not found') def readPlayerStacks(self, hand): - logging.debug("readPlayerStacks") + log.debug("readPlayerStacks") m = self.re_PlayerInfo.finditer(hand.handText) players = [] for a in m: @@ -261,7 +265,7 @@ class PokerStars(HandHistoryConverter): hand.setCommunityCards(street, m.group('CARDS').split(' ')) def readAntes(self, hand): - logging.debug("reading antes") + log.debug("reading antes") m = self.re_Antes.finditer(hand.handText) for player in m: #~ logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE'))) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 3522b890..3846a371 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1604,11 +1604,11 @@ class Sql: """ self.query['get_table_name'] = """ - select h.tableName, h.maxSeats, gt.category, gt.type, gt.siteId - from Hands h - ,Gametypes gt - where h.id = %s - and gt.id = h.gametypeId + SELECT h.tableName, h.maxSeats, gt.category, gt.type, s.id, s.name + FROM Hands h, Gametypes gt, Sites s + WHERE h.id = %s + AND gt.id = h.gametypeId + AND s.id = gt.siteID """ self.query['get_actual_seat'] = """ @@ -2942,8 +2942,9 @@ class Sql: ,hc_position ,hp.tourneyTypeId ,date_format(h.handStart, 'd%y%m%d') ->>>>>>> 28ca49d592c8e706ad6ee58dd26655bcc33fc5fb:pyfpdb/SQL.py """ +#>>>>>>> 28ca49d592c8e706ad6ee58dd26655bcc33fc5fb:pyfpdb/SQL.py +#""" elif db_server == 'postgresql': self.query['rebuildHudCache'] = """ INSERT INTO HudCache diff --git a/pyfpdb/TableWindow.py b/pyfpdb/TableWindow.py index 0fa2bf22..10607b16 100644 --- a/pyfpdb/TableWindow.py +++ b/pyfpdb/TableWindow.py @@ -93,19 +93,17 @@ gobject.signal_new("client_destroyed", gtk.Window, # screen location of (0, 0) in the working window. class Table_Window(object): - def __init__(self, table_name = None, tournament = None, table_number = None): + def __init__(self, search_string, table_name = None, tournament = None, table_number = None): - if table_name is not None: - search_string = table_name - self.name = table_name - self.tournament = None - self.table = None - elif tournament is not None and table_number is not None: + if tournament is not None and table_number is not None: print "tournament %s, table %s" % (tournament, table_number) self.tournament = int(tournament) self.table = int(table_number) self.name = "%s - %s" % (self.tournament, self.table) - search_string = "%s.+Table\s%s" % (tournament, table_number) + elif table_name is not None: + search_string = table_name + self.name = table_name + self.tournament = None else: return None @@ -113,12 +111,12 @@ class Table_Window(object): def __str__(self): # __str__ method for testing + likely_attrs = ("site", "number", "title", "width", "height", "x", "y", + "tournament", "table", "gdkhandle") temp = 'TableWindow object\n' - temp = temp + " name = %s\n site = %s\n number = %s\n title = %s\n" % (self.name, self.site, self.number, self.title) -# temp = temp + " game = %s\n structure = %s\n max = %s\n" % (self.game, self.structure, self.max) - temp = temp + " width = %d\n height = %d\n x = %d\n y = %d\n" % (self.width, self.height, self.x, self.y) - if getattr(self, 'tournament', 0): - temp = temp + " tournament = %d\n table = %d" % (self.tournament, self.table) + for a in likely_attrs: + if getattr(self, a, 0): + temp += " %s = %s\n" % (a, getattr(self, a)) return temp def get_game(self): @@ -151,4 +149,4 @@ class Table_Window(object): def check_bad_words(self, title): for word in bad_words: if word in title: return True - return False \ No newline at end of file + return False diff --git a/pyfpdb/Tables_Demo.py b/pyfpdb/Tables_Demo.py old mode 100644 new mode 100755 diff --git a/pyfpdb/XTables.py b/pyfpdb/XTables.py index 1e692209..fd1ce9c1 100644 --- a/pyfpdb/XTables.py +++ b/pyfpdb/XTables.py @@ -79,7 +79,8 @@ class Table(Table_Window): self.gdk_handle = None else: self.number = int( mo.group(1), 0) - self.gdk_handle = gtk.gdk.window_foreign_new(int(self.number)) + print "number =", self.number +# self.gdk_handle = gtk.gdk.window_foreign_new(int(self.number)) def get_geometry(self): try: diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 18958880..27291d7f 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -30,11 +30,29 @@ except ImportError: logging.info("Not using sqlalchemy connection pool.") use_pool = False +try: + from numpy import var + use_numpy = True +except ImportError: + logging.info("Not using numpy to define variance in sqlite.") + use_numpy = False import fpdb_simple import FpdbSQLQueries import Configuration +# Variance created as sqlite has a bunch of undefined aggregate functions. + +class VARIANCE: + def __init__(self): + self.store = [] + + def step(self, value): + self.store.append(value) + + def finalize(self): + return float(var(self.store)) + class fpdb_db: MYSQL_INNODB = 2 PGSQL = 3 @@ -130,6 +148,10 @@ class fpdb_db: , detect_types=sqlite3.PARSE_DECLTYPES ) sqlite3.register_converter("bool", lambda x: bool(int(x))) sqlite3.register_adapter(bool, lambda x: "1" if x else "0") + if use_numpy: + self.db.create_aggregate("variance", 1, VARIANCE) + else: + logging.warning("Some database functions will not work without NumPy support") else: raise FpdbError("unrecognised database backend:"+backend) self.cursor = self.db.cursor() diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index fcad30be..850f34b6 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -42,15 +42,7 @@ import fpdb_parse_logic import Configuration import Exceptions -import logging, logging.config -import ConfigParser - -try: - logging.config.fileConfig(os.path.join(sys.path[0],"logging.conf")) -except ConfigParser.NoSectionError: # debian package path - logging.config.fileConfig('/usr/share/python-fpdb/logging.conf') - -log = logging.getLogger('importer') +log = Configuration.get_logger("logging.conf", "importer") # database interface modules try: diff --git a/pyfpdb/py2exe_setup.py b/pyfpdb/py2exe_setup.py index 028d004c..9565ac0b 100644 --- a/pyfpdb/py2exe_setup.py +++ b/pyfpdb/py2exe_setup.py @@ -27,6 +27,22 @@ Py2exe script for fpdb. # get rid of all the uneeded libraries (e.g., pyQT) # think about an installer +#HOW TO USE this script: +# +# cd to the folder where this script is stored, usually .../pyfpdb. +# If there are build and dist subfolders present , delete them to get +# rid of earlier builds. +# Run the script with "py2exe_setup.py py2exe" +# You will frequently get messages about missing .dll files. E. g., +# MSVCP90.dll. These are somewhere in your windows install, so you +# can just copy them to your working folder. +# If it works, you'll have 2 new folders, build and dist. Build is +# working space and should be deleted. Dist contains the files to be +# distributed. Last, you must copy the etc/, lib/ and share/ folders +# from your gtk/bin/ 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. + from distutils.core import setup import py2exe @@ -36,7 +52,8 @@ setup( version = '0.12', console = [ {'script': 'fpdb.py', }, - {'script': 'HUD_main.py', } + {'script': 'HUD_main.py', }, + {'script': 'Configuration.py', } ], options = {'py2exe': { @@ -47,8 +64,10 @@ setup( } }, - data_files = ['HUD_config.xml', - 'Cards01.png' + data_files = ['HUD_config.xml.example', + 'Cards01.png', + 'logging.conf', + (r'matplotlibdata', glob.glob(r'c:\python26\Lib\site-packages\matplotlib\mpl-data\*')) ] )