From 93729a479806b59a02425b30ab77ced645e0e5a1 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Wed, 27 Jan 2010 13:42:03 -0500 Subject: [PATCH 1/8] merge --- run_fpdb.py | 68 ++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/run_fpdb.py b/run_fpdb.py index 24f6a4dd..78e2803b 100755 --- a/run_fpdb.py +++ b/run_fpdb.py @@ -1,34 +1,34 @@ -#!/usr/bin/python - -#Copyright 2008 Carl Gherardi -#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 -#the Free Software Foundation, version 3 of the License. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. -# -#You should have received a copy of the GNU Affero General Public License -#along with this program. If not, see . -#In the "official" distribution you can find the license in -#agpl-3.0.txt in the docs folder of the package. - - -import os -import sys - -# sys.path[0] holds the directory run_fpdb.py is in -sys.path[0] = sys.path[0]+os.sep+"pyfpdb" -os.chdir(sys.path[0]) -#print "sys.path[0] =", sys.path[0], "cwd =", os.getcwd() - - -import fpdb - - -if __name__ == "__main__": - me = fpdb.fpdb() - me.main() - exit() +#!/usr/bin/python + +#Copyright 2008 Carl Gherardi +#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 +#the Free Software Foundation, version 3 of the License. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU Affero General Public License +#along with this program. If not, see . +#In the "official" distribution you can find the license in +#agpl-3.0.txt in the docs folder of the package. + + +import os +import sys + +# sys.path[0] holds the directory run_fpdb.py is in +sys.path[0] = sys.path[0]+os.sep+"pyfpdb" +os.chdir(sys.path[0]) +#print "sys.path[0] =", sys.path[0], "cwd =", os.getcwd() + + +import fpdb + + +if __name__ == "__main__": + me = fpdb.fpdb() + me.main() + exit() From 1df418c8e4cf761007c708f4092fa5dbea5c2d16 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 27 Jan 2010 23:48:39 +0000 Subject: [PATCH 2/8] create fpdb dir if required, improve sqlite performance :-) --- pyfpdb/Configuration.py | 22 ++++++++--- pyfpdb/Database.py | 85 +++++++++++++++++++++++++---------------- pyfpdb/HUD_main.py | 5 ++- 3 files changed, 72 insertions(+), 40 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 11d38bf4..09f7ca2e 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -60,12 +60,14 @@ def get_exec_path(): 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) + exec_dir = get_exec_path() + 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 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) + 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 @@ -77,14 +79,24 @@ def get_config(file_name, fallback = True): # 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) shutil.copyfile(file_name + ".example", config_path) - print "No %s found, using %s.example.\n" % (file_name, file_name) - print "Config file has been created at %s.\nYou will probably have to edit it." % config_path - sys.stderr.write("No %s found, copying %s.example.\n" % (file_name, file_name) ) + 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: 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() else: print "No %s found, cannot fall back. Exiting.\n" % file_name diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index f17f1d33..54690979 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -39,40 +39,38 @@ import string import re import Queue import codecs -import logging import math # 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 try: import sqlalchemy.pool as pool use_pool = True except ImportError: - logging.info("Not using sqlalchemy connection pool.") + log.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.") + log.info("Not using numpy to define variance in sqlite.") use_numpy = False -# FreePokerTools modules -import Configuration -import SQL -import Card -import Tourney -import Charset -from Exceptions import * - -log = Configuration.get_logger("logging.conf") - - DB_VERSION = 119 @@ -374,20 +372,20 @@ class Database: print msg raise FpdbError(msg) elif backend == Database.SQLITE: - logging.info("Connecting to SQLite: %(database)s" % {'database':database}) + log.info("Connecting to SQLite: %(database)s" % {'database':database}) import sqlite3 if use_pool: sqlite3 = pool.manage(sqlite3, pool_size=1) 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 not os.path.isdir(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) 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 ) sqlite3.register_converter("bool", lambda x: bool(int(x))) sqlite3.register_adapter(bool, lambda x: "1" if x else "0") @@ -397,7 +395,10 @@ class Database: if use_numpy: self.connection.create_aggregate("variance", 1, VARIANCE) 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: raise FpdbError("unrecognised database backend:"+backend) @@ -412,7 +413,7 @@ class Database: self.cursor.execute("SELECT * FROM Settings") settings = self.cursor.fetchone() 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])) self.wrongDbVersion = True except:# _mysql_exceptions.ProgrammingError: @@ -422,11 +423,6 @@ class Database: log.info("failed to read settings table - recreating tables") self.recreate_tables() 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: print "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 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): self.connection.rollback() @@ -1750,7 +1766,10 @@ class Database: def insertPlayer(self, name, site_id): 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() q = "SELECT name, id FROM Players WHERE siteid=%s and name=%s" q = q.replace('%s', self.sql.query['placeholder']) @@ -1906,7 +1925,7 @@ class Database: # end def send_finish_msg(): def tRecogniseTourneyType(self, tourney): - logging.debug("Database.tRecogniseTourneyType") + log.debug("Database.tRecogniseTourneyType") typeId = 1 # Check if Tourney exists, and if so retrieve TTypeId : in that case, check values of the ttype cursor = self.get_cursor() @@ -1922,10 +1941,10 @@ class Database: try: len(result) 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 : 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 #break except: @@ -1935,7 +1954,7 @@ class Database: if typeIdMatch == False : # Check for an existing TTypeId that matches tourney info (buyin/fee, knockout, rebuy, speed, matrix, shootout) # 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']), (tourney.siteId, tourney.buyin, tourney.fee, tourney.isKO, tourney.isRebuy, tourney.speed, tourney.isHU, tourney.isShootout, tourney.isMatrix) @@ -1945,9 +1964,9 @@ class Database: try: len(result) 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 - 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']), (tourney.siteId, tourney.buyin, tourney.fee, tourney.isKO, tourney.isRebuy, tourney.speed, tourney.isHU, tourney.isShootout, tourney.isMatrix) diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py index 62025018..3fcd0fca 100755 --- a/pyfpdb/HUD_main.py +++ b/pyfpdb/HUD_main.py @@ -204,6 +204,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 + log.info("HUD_main.read_stdin: hand processing starting ...") try: (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) @@ -230,6 +231,7 @@ class HUD_main(object): try: 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']) + 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]) self.hud_dict[temp_key].stat_dict = stat_dict except KeyError: # HUD instance has been killed off, key is stale @@ -238,6 +240,7 @@ class HUD_main(object): # Unlocks table, copied from end of function self.db_connection.connection.rollback() return + t5 = time.time() cards = self.db_connection.get_cards(new_hand_id) comm_cards = self.db_connection.get_common_cards(new_hand_id) if comm_cards != {}: # stud! @@ -250,10 +253,8 @@ class HUD_main(object): else: # 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'] ) - t4 = time.time() stat_dict = self.db_connection.get_stats_from_hand(new_hand_id, type, self.hud_params ,self.hero_ids[site_id], num_seats) - t5 = time.time() cards = self.db_connection.get_cards(new_hand_id) comm_cards = self.db_connection.get_common_cards(new_hand_id) if comm_cards != {}: # stud! From 803fcec6dc85fb248a7d98c22d59646faab10a69 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Thu, 28 Jan 2010 04:45:33 -0500 Subject: [PATCH 3/8] make hud_main call with full path in windows, as has been done in unix --- pyfpdb/GuiAutoImport.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index f9f1c335..628f7b7f 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -194,7 +194,7 @@ class GuiAutoImport (threading.Thread): widget.set_label(u' _Stop Autoimport ') if self.pipe_to_hud is None: 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 else: command = os.path.join(sys.path[0], 'HUD_main.py') From 997483f909fb6ef27b798429a650fcfde1e7db1f Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Thu, 28 Jan 2010 05:19:19 -0500 Subject: [PATCH 4/8] make import timer work again --- pyfpdb/fpdb_import.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index fe66fcda..1df0ad7a 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -365,7 +365,7 @@ class Importer: pass (stored, duplicates, partial, errors, ttime) = self.import_file_dict(self.database, file, self.filelist[file][0], self.filelist[file][1], None) 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)) except KeyError: # TODO: Again, what error happens here? fix when we find out .. pass @@ -402,7 +402,7 @@ class Importer: return (0,0,0,0,0) 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) @@ -440,6 +440,7 @@ class Importer: #try, except duplicates here? hand.prepInsert(self.database) hand.insert(self.database) + if self.callHud and hand.dbid_hands != 0: to_hud.append(hand.dbid_hands) else: @@ -463,10 +464,12 @@ class Importer: else: # conversion didn't work # TODO: appropriate response? - return (0, 0, 0, 1, 0) + return (0, 0, 0, 1, time() - ttime) else: 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 return (stored, duplicates, partial, errors, ttime) From 2be8b9d33be280e1f0edaa4f83e6a552dabcb2a8 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Thu, 28 Jan 2010 05:19:39 -0500 Subject: [PATCH 5/8] get fpdb icon from absolute path instead of relative to cwd --- pyfpdb/fpdb.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 5136d56b..f202698d 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -769,7 +769,7 @@ class fpdb: self.status_bar.show() 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)) # rollback to make sure any locks are cleared: 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.statusIcon = gtk.StatusIcon() - if os.path.exists('../gfx/fpdb-cards.png'): - self.statusIcon.set_from_file('../gfx/fpdb-cards.png') + if os.path.exists(os.path.join(sys.path[0], '../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'): self.statusIcon.set_from_file('/usr/share/pixmaps/fpdb-cards.png') else: From d36ac3f92707fbfbf9c7c78ee65b8a9302304321 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Thu, 28 Jan 2010 05:55:06 -0500 Subject: [PATCH 6/8] rename DuplicateError to FpdbHandDuplicate, add matching FpdbHandError and FpdbHandPartial (not sure where to implement catching those though) --- pyfpdb/Exceptions.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Exceptions.py b/pyfpdb/Exceptions.py index fd7c20e3..789c7b83 100644 --- a/pyfpdb/Exceptions.py +++ b/pyfpdb/Exceptions.py @@ -48,5 +48,11 @@ class FpdbPostgresqlNoDatabase(FpdbDatabaseError): def __str__(self): return repr(self.value +" " + self.errmsg) -class DuplicateError(FpdbError): +class FpdbHandError(FpdbError): + pass + +class FpdbHandDuplicate(FpdbHandError): + pass + +class FpdbHandPartial(FpdbHandError): pass From 3381527afc14f6a1fbfac49078f99bd41f294323 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Thu, 28 Jan 2010 05:56:17 -0500 Subject: [PATCH 7/8] raise FpdbHandDuplicate error on duplicate insert attempt, catch it in import_file_dict, increment duplicates count --- pyfpdb/Hand.py | 12 +++++------- pyfpdb/fpdb_import.py | 15 +++++++++------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 7023d50c..4fdc555e 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -229,8 +229,7 @@ db: a connected Database object""" # TourneysPlayers else: log.info("Hand.insert(): hid #: %s is a duplicate" % hh['siteHandNo']) - #Raise Duplicate exception? - pass + raise FpdbHandDuplicate(hh['siteHandNo']) def updateHudCache(self, db): db.storeHudCache(self.dbid_gt, self.dbid_pids, self.starttime, self.stats.getHandsPlayers()) @@ -618,7 +617,7 @@ class HoldemOmahaHand(Hand): if builtFrom == "HHC": hhc.readHandInfo(self) 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.compilePlayerRegexs(self) hhc.markStreets(self) @@ -914,7 +913,7 @@ class DrawHand(Hand): if builtFrom == "HHC": hhc.readHandInfo(self) 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.compilePlayerRegexs(self) hhc.markStreets(self) @@ -1110,7 +1109,7 @@ class StudHand(Hand): if builtFrom == "HHC": hhc.readHandInfo(self) 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.compilePlayerRegexs(self) hhc.markStreets(self) @@ -1202,7 +1201,7 @@ Add a complete on [street] by [player] to [amountTo] # showdownPot INT, /* pot size at sd/street7 */ return (0,0,0,0,0) - + def writeHand(self, fh=sys.__stdout__): # PokerStars format. @@ -1597,4 +1596,3 @@ ORDER BY return h - diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 1df0ad7a..859a6bc0 100644 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -437,13 +437,15 @@ class Importer: for hand in handlist: if hand is not None: - #try, except duplicates here? hand.prepInsert(self.database) - hand.insert(self.database) - - if self.callHud and hand.dbid_hands != 0: - to_hud.append(hand.dbid_hands) - else: + try: + hand.insert(self.database) + except Exceptions.FpdbHandDuplicate: + 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") self.database.commit() # Call hudcache update if not in bulk import mode @@ -461,6 +463,7 @@ class Importer: errors = getattr(hhc, 'numErrors') stored = getattr(hhc, 'numHands') + stored -= duplicates else: # conversion didn't work # TODO: appropriate response? From e29491c25cc3cfc32dff4dfc375c2a56400a21df Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Thu, 28 Jan 2010 20:29:43 -0500 Subject: [PATCH 8/8] use getpreferredencoding() instead of getdefaultlocale() to get LOCALE_ENCODING, default to cp1252 if it comes back with US-ASCII (Mac) --- pyfpdb/Configuration.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 09f7ca2e..9c14d16f 100644 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -138,7 +138,11 @@ DATABASE_TYPES = ( DATABASE_TYPE_MYSQL, ) -LOCALE_ENCODING = locale.getdefaultlocale()[1] +#LOCALE_ENCODING = locale.getdefaultlocale()[1] +LOCALE_ENCODING = locale.getpreferredencoding() +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." + LOCALE_ENCODING = "cp1252" ######################################################################## def string_to_bool(string, default=True):