Merge branch 'master' of git://git.assembla.com/fpdboz

This commit is contained in:
Mika Bostrom 2010-03-04 16:03:11 +02:00
commit 2856b90828
17 changed files with 161 additions and 91 deletions

View File

@ -1,5 +1,5 @@
README.txt
updated 26 March 2009, REB
updated 22 February 2010, REB
fpdb - Free Poker Database
@ -29,7 +29,7 @@ fpdb supports:
Omaha (incl Hi/low)
7 Card Stud (incl Hi/low)
Razz
Draw support is under development
Triple Draw and Badugi
Mixed Games -- HUD under development
Operating Systems:
@ -38,23 +38,38 @@ fpdb supports:
Mac OS/X -- no support for HUD
Databases:
SQLite configured by default
MySQL
PostgreSQL
SQLite under development
Downloads:
Releases: http://sourceforge.net/project/showfiles.php?group_id=226872
Development code via git: http://www.assembla.com/spaces/free_poker_tools/trac_git_tool
Developers:
At least 7 people have contributed code or patches. Others are welcome.
At least 10 people have contributed code or patches. Others are welcome.
Source Code:
If you received fpdb as the Windows compressed exe, then you did not
receive souce code for fpdb or the included libraries. If you wish, you can
obtain the source code here:
fpdb: see Downloads, above.
python: http://python.org/
gtk: http://www.gtk.org/download.html
pygtk: http://www.pygtk.org/downloads.html
psycopg2: http://initd.org/pub/software/psycopg/
mysqldb: http://sourceforge.net/projects/mysql-python/files/
sqlalchemy: http://www.sqlalchemy.org/download.html
numpy: http://www.scipy.org/Download
matplotlib: http://sourceforge.net/projects/matplotlib/files/
License
=======
Trademarks of third parties have been used under Fair Use or similar laws.
Copyright 2008 Steffen Jobbagy-Felso
Copyright 2009 Ray E. Barker
Copyright 2009,2010 Ray E. Barker
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License,
Version 1.2 as published by the Free Software Foundation; with

View File

@ -414,6 +414,7 @@ class Import:
self.hhArchiveBase = node.getAttribute("hhArchiveBase")
self.saveActions = string_to_bool(node.getAttribute("saveActions"), default=True)
self.fastStoreHudCache = string_to_bool(node.getAttribute("fastStoreHudCache"), default=False)
self.saveStarsHH = string_to_bool(node.getAttribute("saveStarsHH"), default=False)
def __str__(self):
return " interval = %s\n callFpdbHud = %s\n hhArchiveBase = %s\n saveActions = %s\n fastStoreHudCache = %s\n" \
@ -469,7 +470,8 @@ class Config:
self.file = file
self.dir_self = get_exec_path()
self.dir_config = os.path.dirname(self.file)
# self.dir_config = os.path.dirname(self.file)
self.dir_config = get_default_config_path()
self.dir_log = os.path.join(self.dir_config, 'log')
self.dir_database = os.path.join(self.dir_config, 'database')
self.log_file = os.path.join(self.dir_log, 'fpdb-log.txt')
@ -822,8 +824,12 @@ class Config:
try: imp['saveActions'] = self.imp.saveActions
except: imp['saveActions'] = True
try: imp['saveStarsHH'] = self.imp.saveStarsHH
except: imp['saveStarsHH'] = False
try: imp['fastStoreHudCache'] = self.imp.fastStoreHudCache
except: imp['fastStoreHudCache'] = True
return imp
def get_default_paths(self, site = None):

View File

@ -917,7 +917,6 @@ class Database:
print "warning: constraint %s_%s_fkey not dropped: %s, continuing ..." \
% (fk['fktab'],fk['fkcol'], str(sys.exc_value).rstrip('\n'))
else:
print "Only MySQL and Postgres supported so far"
return -1
for idx in self.indexes[self.backend]:
@ -952,7 +951,6 @@ class Database:
print "warning: index %s_%s_idx not dropped %s, continuing ..." \
% (idx['tab'],idx['col'], str(sys.exc_value).rstrip('\n'))
else:
print "Error: Only MySQL and Postgres supported so far"
return -1
if self.backend == self.PGSQL:
@ -1007,7 +1005,6 @@ class Database:
except:
print " create fk failed: " + str(sys.exc_info())
else:
print "Only MySQL and Postgres supported so far"
return -1
for idx in self.indexes[self.backend]:
@ -1029,7 +1026,6 @@ class Database:
except:
print " create index failed: " + str(sys.exc_info())
else:
print "Only MySQL and Postgres supported so far"
return -1
if self.backend == self.PGSQL:

View File

@ -162,7 +162,7 @@ class DerivedStats():
self.handsplayers[player]['wonAtSD'] = 1.0
for player in hand.pot.committed:
self.handsplayers[player]['totalProfit'] = int(self.handsplayers[player]['winnings'] - (100*hand.pot.committed[player]))
self.handsplayers[player]['totalProfit'] = int(self.handsplayers[player]['winnings'] - (100*hand.pot.committed[player])- (100*hand.pot.common[player]))
self.calcCBets(hand)
@ -345,9 +345,9 @@ class DerivedStats():
for action in hand.actions[hand.actionStreets[1]]:
# FIXME: fill other(3|4)BStreet0 - i have no idea what does it mean
pname, aggr = action[0], action[1] in ('raises', 'bets')
self.handsplayers[pname]['street0_3BChance'] = bet_level == 2
self.handsplayers[pname]['street0_3BChance'] = self.handsplayers[pname]['street0_3BChance'] or bet_level == 2
self.handsplayers[pname]['street0_4BChance'] = bet_level == 3
self.handsplayers[pname]['street0_3BDone'] = aggr and (self.handsplayers[pname]['street0_3BChance'])
self.handsplayers[pname]['street0_3BDone'] = self.handsplayers[pname]['street0_3BDone'] or (aggr and self.handsplayers[pname]['street0_3BChance'])
self.handsplayers[pname]['street0_4BDone'] = aggr and (self.handsplayers[pname]['street0_4BChance'])
if aggr:
bet_level += 1

View File

@ -65,8 +65,8 @@ class Fulltilt(HandHistoryConverter):
(\s\((?P<TURBO>Turbo)\))?)|(?P<UNREADABLE_INFO>.+))
''', re.VERBOSE)
re_Button = re.compile('^The button is in seat #(?P<BUTTON>\d+)', re.MULTILINE)
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.{3,15}) \(\$(?P<CASH>[,.0-9]+)\)$', re.MULTILINE)
re_TourneyPlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.{3,15}) \(\$?(?P<CASH>[,.0-9]+)\)(, is sitting out)?$', re.MULTILINE)
re_PlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.{2,15}) \(\$(?P<CASH>[,.0-9]+)\)$', re.MULTILINE)
re_TourneyPlayerInfo = re.compile('Seat (?P<SEAT>[0-9]+): (?P<PNAME>.{2,15}) \(\$?(?P<CASH>[,.0-9]+)\)(, is sitting out)?$', re.MULTILINE)
re_Board = re.compile(r"\[(?P<CARDS>.+)\]")
#static regex for tourney purpose
@ -128,6 +128,7 @@ class Fulltilt(HandHistoryConverter):
player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")"
logging.debug("player_re: " + player_re)
self.re_PostSB = re.compile(r"^%s posts the small blind of \$?(?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_PostDead = re.compile(r"^%s posts a dead small blind of \$?(?P<SB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_PostBB = re.compile(r"^%s posts (the big blind of )?\$?(?P<BB>[.0-9]+)" % player_re, re.MULTILINE)
self.re_Antes = re.compile(r"^%s antes \$?(?P<ANTE>[.0-9]+)" % player_re, re.MULTILINE)
self.re_BringIn = re.compile(r"^%s brings in for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE)
@ -298,6 +299,8 @@ class Fulltilt(HandHistoryConverter):
hand.addBlind(m.group('PNAME'), 'small blind', m.group('SB'))
except: # no small blind
hand.addBlind(None, None, None)
for a in self.re_PostDead.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'secondsb', a.group('SB'))
for a in self.re_PostBB.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
for a in self.re_PostBoth.finditer(hand.handText):

View File

@ -81,7 +81,7 @@ class GuiPlayerStats (threading.Thread):
self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
self.filters.registerButton1Name("_Filters")
self.filters.registerButton1Callback(self.showDetailFilter)
self.filters.registerButton2Name("_Refresh Stats")
self.filters.registerButton2Name("_Refresh")
self.filters.registerButton2Callback(self.refreshStats)
# ToDo: store in config
@ -92,7 +92,7 @@ class GuiPlayerStats (threading.Thread):
, ["hand", False, "Hand", 0.0, "%s", "str"] # true not allowed for this line
, ["plposition", False, "Posn", 1.0, "%s", "str"] # true not allowed for this line (set in code)
, ["pname", False, "Name", 0.0, "%s", "str"] # true not allowed for this line (set in code)
, ["n", True, "Hds", 1.0, "%d", "str"]
, ["n", True, "Hds", 1.0, "%1.0f", "str"]
, ["avgseats", False, "Seats", 1.0, "%3.1f", "str"]
, ["vpip", True, "VPIP", 1.0, "%3.1f", "str"]
, ["pfr", True, "PFR", 1.0, "%3.1f", "str"]
@ -482,6 +482,22 @@ class GuiPlayerStats (threading.Thread):
gametest = "and gt.category IS NULL"
query = query.replace("<game_test>", gametest)
sitetest = ""
q = []
for m in self.filters.display.items():
if m[0] == 'Sites' and m[1]:
for n in sitenos:
q.append(n)
if len(q) > 0:
sitetest = str(tuple(q))
sitetest = sitetest.replace("L", "")
sitetest = sitetest.replace(",)",")")
sitetest = sitetest.replace("u'","'")
sitetest = "and gt.siteId in %s" % sitetest
else:
sitetest = "and gt.siteId IS NULL"
query = query.replace("<site_test>", sitetest)
if seats:
query = query.replace('<seats_test>', 'between ' + str(seats['from']) + ' and ' + str(seats['to']))
if 'show' in seats and seats['show']:
@ -539,7 +555,7 @@ class GuiPlayerStats (threading.Thread):
query = query.replace("<orderbyhgameTypeId>", "")
groupLevels = "show" not in str(limits)
if groupLevels:
query = query.replace("<hgameTypeId>", "p.name")
query = query.replace("<hgameTypeId>", "-1")
else:
query = query.replace("<hgameTypeId>", "h.gameTypeId")

View File

@ -61,7 +61,7 @@ import Hud
# get config and set up logger
c = Configuration.Config(file=options.config)
c = Configuration.Config(file=options.config, dbname=options.dbname)
log = Configuration.get_logger("logging.conf", "hud", log_dir=c.dir_log, log_file='HUD-log.txt')
@ -78,14 +78,14 @@ class HUD_main(object):
try:
if not options.errorsToConsole:
fileName = os.path.join(self.config.dir_log, 'HUD-errors.txt')
print "Note: error output is being diverted to:\n"+fileName \
+ "\nAny major error will be reported there _only_.\n"
log.info("Note: error output is being diverted to:"+fileName)
log.info("Any major error will be reported there _only_.")
errorFile = open(fileName, 'w', 0)
sys.stderr = errorFile
sys.stderr.write("HUD_main: starting ...\n")
fileName = os.path.join(self.config.dir_log, 'HUD-errors.txt')
print "Note: error output is being diverted to:\n"+fileName \
+ "\nAny major error will be reported there _only_.\n"
log.info("Note: error output is being diverted to:"+fileName)
log.info("Any major error will be reported there _only_.")
errorFile = open(fileName, 'w', 0)
sys.stderr = errorFile
sys.stderr.write("HUD_main: starting ...\n")
self.hud_dict = {}
self.hud_params = self.config.get_hud_ui_parameters()
@ -237,7 +237,7 @@ class HUD_main(object):
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)
except Exception, err:
except Exception:
log.error("db error: skipping %s" % new_hand_id)
continue
t1 = time.time()

View File

@ -323,7 +323,9 @@ For sites (currently only Carbon Poker) which record "all in" as a special actio
self.stacks[player] -= Decimal(ante)
act = (player, 'posts', "ante", ante, self.stacks[player]==0)
self.actions['BLINDSANTES'].append(act)
self.pot.addMoney(player, Decimal(ante))
# self.pot.addMoney(player, Decimal(ante))
self.pot.addCommonMoney(player, Decimal(ante))
#I think the antes should be common money, don't have enough hand history to check
def addBlind(self, player, blindtype, amount):
# if player is None, it's a missing small blind.
@ -342,14 +344,16 @@ For sites (currently only Carbon Poker) which record "all in" as a special actio
self.actions['BLINDSANTES'].append(act)
if blindtype == 'both':
# work with the real ammount. limit games are listed as $1, $2, where
# the SB 0.50 and the BB is $1, after the turn the minimum bet amount is $2....
amount = self.bb
self.bets['BLINDSANTES'][player].append(Decimal(self.sb))
self.pot.addCommonMoney(Decimal(self.sb))
self.pot.addCommonMoney(player, Decimal(self.sb))
if blindtype == 'secondsb':
amount = Decimal(0)
self.bets['BLINDSANTES'][player].append(Decimal(self.sb))
self.pot.addCommonMoney(Decimal(self.sb))
self.pot.addCommonMoney(player, Decimal(self.sb))
self.bets['PREFLOP'][player].append(Decimal(amount))
self.pot.addMoney(player, Decimal(amount))
@ -513,9 +517,6 @@ Card ranks will be uppercased
for entry in self.collected:
self.totalcollected += Decimal(entry[1])
def getGameTypeAsString(self):
"""\
Map the tuple self.gametype onto the pokerstars string describing it
@ -994,11 +995,12 @@ class DrawHand(Hand):
self.lastBet['DEAL'] = Decimal(amount)
elif blindtype == 'both':
# extra small blind is 'dead'
self.lastBet['DEAL'] = Decimal(self.bb)
amount = Decimal(amount)/3
amount += amount
self.lastBet['DEAL'] = Decimal(amount)
self.posted = self.posted + [[player,blindtype]]
#print "DEBUG: self.posted: %s" %(self.posted)
def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False):
if player == self.hero: # we have hero's cards just update shown/mucked
if shown: self.shown.add(player)
@ -1413,7 +1415,7 @@ class Pot(object):
self.contenders = set()
self.committed = {}
self.streettotals = {}
self.common = Decimal(0)
self.common = {}
self.total = None
self.returned = {}
self.sym = u'$' # this is the default currency symbol
@ -1423,13 +1425,14 @@ class Pot(object):
def addPlayer(self,player):
self.committed[player] = Decimal(0)
self.common[player] = Decimal(0)
def addFold(self, player):
# addFold must be called when a player folds
self.contenders.discard(player)
def addCommonMoney(self, amount):
self.common += amount
def addCommonMoney(self, player, amount):
self.common[player] += amount
def addMoney(self, player, amount):
# addMoney must be called for any actions that put money in the pot, in the order they occur
@ -1437,7 +1440,7 @@ class Pot(object):
self.committed[player] += amount
def markTotal(self, street):
self.streettotals[street] = sum(self.committed.values()) + self.common
self.streettotals[street] = sum(self.committed.values()) + sum(self.common.values())
def getTotalAtStreet(self, street):
if street in self.streettotals:
@ -1445,11 +1448,11 @@ class Pot(object):
return 0
def end(self):
self.total = sum(self.committed.values()) + self.common
self.total = sum(self.committed.values()) + sum(self.common.values())
# Return any uncalled bet.
committed = sorted([ (v,k) for (k,v) in self.committed.items()])
print "DEBUG: committed: %s" % committed
#print "DEBUG: committed: %s" % committed
#ERROR below. lastbet is correct in most cases, but wrong when
# additional money is committed to the pot in cash games
# due to an additional sb being posted. (Speculate that

View File

@ -69,6 +69,7 @@ out_path (default '-' = sys.stdout)
follow : whether to tail -f the input"""
self.config = config
self.import_parameters = self.config.get_import_parameters()
#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) )
@ -87,12 +88,8 @@ follow : whether to tail -f the input"""
if in_path == '-':
self.in_fh = sys.stdin
self.out_fh = get_out_fh(out_path, self.import_parameters)
if out_path == '-':
self.out_fh = sys.stdout
else:
# TODO: out_path should be sanity checked.
self.out_fh = sys.stdout
self.follow = follow
self.compiledPlayers = set()
self.maxseats = 10
@ -446,8 +443,8 @@ or None if we fail to get the info """
def guessMaxSeats(self, hand):
"""Return a guess at maxseats when not specified in HH."""
# if some other code prior to this has already set it, return it
if maxseats > 1 and maxseats < 11:
return maxseats
if self.maxseats > 1 and self.maxseats < 11:
return self.maxseats
mo = self.maxOccSeat(hand)
if mo == 10: return 10 #that was easy
@ -515,3 +512,23 @@ def getSiteHhc(config, sitename):
hhcName = config.supported_sites[sitename].converter
hhcModule = __import__(hhcName)
return getattr(hhcModule, hhcName[:-6])
def get_out_fh(out_path, parameters):
if out_path == '-':
return(sys.stdout)
elif parameters['saveStarsHH']:
out_dir = os.path.dirname(out_path)
if not os.path.isdir(out_dir) and out_dir != '':
try:
os.makedirs(out_dir)
except: # we get a WindowsError here in Windows.. pretty sure something else for Linux :D
log.error("Unable to create output directory %s for HHC!" % out_dir)
print "*** ERROR: UNABLE TO CREATE OUTPUT DIRECTORY", out_dir
else:
log.info("Created directory '%s'" % out_dir)
try:
return(codecs.open(out_path, 'w', 'utf8'))
except:
log.error("out_path %s couldn't be opened" % (out_path))
else:
return(sys.stdout)

View File

@ -27,7 +27,7 @@ def fpdb_options():
action="store_true",
help="If passed error output will go to the console rather than .")
parser.add_option("-d", "--databaseName",
dest="dbname", default="fpdb",
dest="dbname",
help="Overrides the default database name")
parser.add_option("-c", "--configFile",
dest="config", default=None,

View File

@ -465,8 +465,9 @@ class PartyPoker(HandHistoryConverter):
def getTableTitleRe(type, table_name=None, tournament = None, table_number=None):
"Returns string to search in windows titles"
if type=="tour":
print 'party', 'getTableTitleRe', "%s.+Table\s#%s" % (table_name, table_number)
return "%s.+Table\s#%s" % (table_name, table_number)
TableName = table_name.split(" ")
print 'party', 'getTableTitleRe', "%s.+Table\s#%s" % (TableName[0], table_number)
return "%s.+Table\s#%s" % (TableName[0], table_number)
else:
print 'party', 'getTableTitleRe', table_number
return table_name

30
pyfpdb/PokerStarsToFpdb.py Executable file → Normal file
View File

@ -140,6 +140,14 @@ class PokerStars(HandHistoryConverter):
mg = m.groupdict()
# translations from captured groups to fpdb info strings
Lim_Blinds = { '0.04': ('0.01', '0.02'), '0.10': ('0.02', '0.05'), '0.20': ('0.05', '0.10'),
'0.50': ('0.10', '0.25'), '1.00': ('0.25', '0.50'), '2.00': ('0.50', '1.00'),
'4.00': ('1.00', '2.00'), '6.00': ('1.00', '3.00'), '10.00': ('2.00', '5.00'),
'20.00': ('5.00', '10.00'), '30.00': ('10.00', '15.00'), '60.00': ('15.00', '30.00'),
'100.00': ('25.00', '50.00'),'200.00': ('50.00', '100.00'),'400.00': ('100.00', '200.00'),
'1000.00': ('250.00', '500.00')}
limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' }
games = { # base, category
"Hold'em" : ('hold','holdem'),
@ -173,6 +181,10 @@ class PokerStars(HandHistoryConverter):
else:
info['type'] = 'tour'
if info['limitType'] == 'fl' and info['bb'] != None and info['type'] == 'ring':
info['sb'] = Lim_Blinds[mg['BB']][0]
info['bb'] = Lim_Blinds[mg['BB']][1]
# NB: SB, BB must be interpreted as blinds or bets depending on limit type.
return info
@ -287,16 +299,14 @@ class PokerStars(HandHistoryConverter):
hand.addBringIn(m.group('PNAME'), m.group('BRINGIN'))
def readBlinds(self, hand):
try:
count = 0
for a in self.re_PostSB.finditer(hand.handText):
if count == 0:
hand.addBlind(a.group('PNAME'), 'small blind', a.group('SB'))
count = 1
else:
hand.addBlind(a.group('PNAME'), 'secondsb', a.group('SB'))
except: # no small blind
hand.addBlind(None, None, None)
liveBlind = True
for a in self.re_PostSB.finditer(hand.handText):
if liveBlind:
hand.addBlind(a.group('PNAME'), 'small blind', a.group('SB'))
liveBlind = False
else:
# Post dead blinds as ante
hand.addBlind(a.group('PNAME'), 'secondsb', a.group('SB'))
for a in self.re_PostBB.finditer(hand.handText):
hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB'))
for a in self.re_PostBoth.finditer(hand.handText):

View File

@ -1916,6 +1916,7 @@ class Sql:
inner join Players p on (p.Id = hp.playerId)
where hp.playerId in <player_test>
<game_test>
<site_test>
/*and hp.tourneysPlayersId IS NULL*/
and h.seats <seats_test>
<flagtest>
@ -2000,6 +2001,7 @@ class Sql:
inner join Players p on (p.Id = hp.playerId)
where hp.playerId in <player_test>
<game_test>
<site_test>
/*and hp.tourneysPlayersId IS NULL*/
and h.seats <seats_test>
<flagtest>
@ -2086,6 +2088,7 @@ class Sql:
inner join Players p on (p.Id = hp.playerId)
where hp.playerId in <player_test>
<game_test>
<site_test>
/*and hp.tourneysPlayersId IS NULL*/
and h.seats <seats_test>
<flagtest>

View File

@ -89,7 +89,6 @@ class Table(Table_Window):
# break
if window_number is None:
print "Window %s not found. Skipping." % search_string
return None
# my_geo = self.window.get_geometry()

View File

@ -1025,23 +1025,24 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt")
return response
def validate_config(self):
hhbase = self.config.get_import_parameters().get("hhArchiveBase")
hhbase = os.path.expanduser(hhbase)
#hhdir = os.path.join(hhbase,site)
hhdir = hhbase
if not os.path.isdir(hhdir):
diapath = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Setup hh dir")
diastring = "WARNING: Unable to find output hh directory %s\n\n Press YES to create this directory, or NO to select a new one." % hhdir
diapath.format_secondary_text(diastring)
response = diapath.run()
diapath.destroy()
if response == gtk.RESPONSE_YES:
try:
os.makedirs(hhdir)
except:
self.warning_box("WARNING: Unable to create hand output directory. Importing is not likely to work until this is fixed.")
elif response == gtk.RESPONSE_NO:
self.select_hhArchiveBase()
if self.config.get_import_parameters().get('saveStarsHH'):
hhbase = self.config.get_import_parameters().get("hhArchiveBase")
hhbase = os.path.expanduser(hhbase)
#hhdir = os.path.join(hhbase,site)
hhdir = hhbase
if not os.path.isdir(hhdir):
diapath = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Setup hh dir")
diastring = "WARNING: Unable to find output hh directory %s\n\n Press YES to create this directory, or NO to select a new one." % hhdir
diapath.format_secondary_text(diastring)
response = diapath.run()
diapath.destroy()
if response == gtk.RESPONSE_YES:
try:
os.makedirs(hhdir)
except:
self.warning_box("WARNING: Unable to create hand output directory. Importing is not likely to work until this is fixed.")
elif response == gtk.RESPONSE_NO:
self.select_hhArchiveBase()
def select_hhArchiveBase(self, widget=None):
fc = gtk.FileChooserDialog(title="Select HH Output Directory", parent=None, action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, buttons=(gtk.STOCK_OPEN,gtk.RESPONSE_OK), backend=None)

0
run_fpdb.py Executable file → Normal file
View File