From 0f4b5827d0d0cbe716347a148dabf10b2ede08e4 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Sat, 20 Nov 2010 03:29:53 -0500 Subject: [PATCH 01/15] re-undo the last merge change i made oops --- pyfpdb/CarbonToFpdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/CarbonToFpdb.py b/pyfpdb/CarbonToFpdb.py index 1a1541ee..cf8794da 100644 --- a/pyfpdb/CarbonToFpdb.py +++ b/pyfpdb/CarbonToFpdb.py @@ -66,7 +66,7 @@ class Carbon(HandHistoryConverter): # Static regexes re_SplitHands = re.compile(r'\n+(?=)') - re_GameInfo = re.compile(r'', re.MULTILINE) + re_GameInfo = re.compile(r'', re.MULTILINE) re_HandInfo = re.compile(r'[0-9]+)">') re_PlayerInfo = re.compile(r'', re.MULTILINE) From 7c4d08833bc95a51317dd1224ea644980792ba82 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Fri, 26 Nov 2010 16:57:47 -0500 Subject: [PATCH 02/15] add strptime to Database --- pyfpdb/Database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 65e7a87d..29637c96 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -37,7 +37,7 @@ import os import sys import traceback from datetime import datetime, date, time, timedelta -from time import time, strftime, sleep +from time import time, strftime, sleep, strptime from decimal import Decimal import string import re From 927d27ecce93521160e14115b6a759966eaf1d5a Mon Sep 17 00:00:00 2001 From: Worros Date: Fri, 26 Nov 2010 12:45:41 +0800 Subject: [PATCH 03/15] Winamax: Pull in tournament support from Forrest Also add tournament directory to regression test file --- pyfpdb/TestHandsPlayers.py | 1 + pyfpdb/WinamaxToFpdb.py | 81 +++++++++++++++++++++++++++++++++++--- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/pyfpdb/TestHandsPlayers.py b/pyfpdb/TestHandsPlayers.py index ee3be1e9..e0013ecc 100755 --- a/pyfpdb/TestHandsPlayers.py +++ b/pyfpdb/TestHandsPlayers.py @@ -201,6 +201,7 @@ def main(argv=None): walk_testfiles("regression-test-files/cash/iPoker/", compare, importer, iPokerErrors, "iPoker") if sites['Winamax'] == True: walk_testfiles("regression-test-files/cash/Winamax/", compare, importer, WinamaxErrors, "Winamax") + walk_testfiles("regression-test-files/tour/Winamax/", compare, importer, WinamaxErrors, "Winamax") if sites['Win2day'] == True: walk_testfiles("regression-test-files/cash/Win2day/", compare, importer, Win2dayErrors, "Win2day") diff --git a/pyfpdb/WinamaxToFpdb.py b/pyfpdb/WinamaxToFpdb.py index c49f4e09..47721515 100644 --- a/pyfpdb/WinamaxToFpdb.py +++ b/pyfpdb/WinamaxToFpdb.py @@ -82,15 +82,26 @@ class Winamax(HandHistoryConverter): # Winamax Poker - CashGame - HandId: #279823-223-1285031451 - Holdem no limit (0.02€/0.05€) - 2010/09/21 03:10:51 UTC # Table: 'Charenton-le-Pont' 9-max (real money) Seat #5 is the button re_HandInfo = re.compile(u""" - \s*Winamax\sPoker\s-\sCashGame\s-\sHandId:\s\#(?P\d+)-(?P\d+)-(?P\d+).*\s + \s*Winamax\sPoker\s-\s + (?PCashGame)? + (?PTournament\s + (?P.+)?\s + buyIn:\s(?P(?P[%(LS)s\d\,]+)?\s\+?\s(?P[%(LS)s\d\,]+)?\+?(?P[%(LS)s\d\.]+)?\s?(?P%(LEGAL_ISO)s)?|Gratuit|Ticket\suniquement)?\s + (level:\s(?P\d+))? + .*)? + \s-\sHandId:\s\#(?P\d+)-(?P\d+)-(?P\d+).*\s (?PHoldem|Omaha)\s (?Pno\slimit|pot\slimit)\s \( + (((%(LS)s)?(?P[.0-9]+)(%(LS)s)?)/)? ((%(LS)s)?(?P[.0-9]+)(%(LS)s)?)/ ((%(LS)s)?(?P[.0-9]+)(%(LS)s)?) \)\s-\s (?P.*) - Table:\s\'(?P[^']+)\'\s(?P\d+)\-max + Table:\s\'(?P
[^(]+) + (.(?P\d+).\#(?P\d+))?.* + \' + \s(?P\d+)\-max """ % substitutions, re.MULTILINE|re.DOTALL|re.VERBOSE) re_TailSplitHands = re.compile(r'\n\s*\n') @@ -126,8 +137,8 @@ class Winamax(HandHistoryConverter): self.re_PostSB = re.compile('%(PLYR)s posts small blind (%(CUR)s)?(?P[\.0-9]+)(%(CUR)s)?' % subst, re.MULTILINE) self.re_PostBB = re.compile('%(PLYR)s posts big blind (%(CUR)s)?(?P[\.0-9]+)(%(CUR)s)?' % subst, re.MULTILINE) self.re_DenySB = re.compile('(?P.*) deny SB' % subst, re.MULTILINE) - self.re_Antes = re.compile(r"^%(PLYR)s: posts the ante (%(CUR)s)?(?P[\.0-9]+)(%(CUR)s)?" % subst, re.MULTILINE) - self.re_BringIn = re.compile(r"^%(PLYR)s: brings[- ]in( low|) for (%(CUR)s)?(?P[\.0-9]+(%(CUR)s)?)" % subst, re.MULTILINE) + self.re_Antes = re.compile(r"^%(PLYR)s posts ante (%(CUR)s)?(?P[\.0-9]+)(%(CUR)s)?" % subst, re.MULTILINE) + self.re_BringIn = re.compile(r"^%(PLYR)s brings[- ]in( low|) for (%(CUR)s)?(?P[\.0-9]+(%(CUR)s)?)" % subst, re.MULTILINE) self.re_PostBoth = re.compile('(?P.*): posts small \& big blind \( (%(CUR)s)?(?P[\.0-9]+)(%(CUR)s)?\)' % subst) self.re_PostDead = re.compile('(?P.*) posts dead blind \((%(CUR)s)?(?P[\.0-9]+)(%(CUR)s)?\)' % subst, re.MULTILINE) self.re_HeroCards = re.compile('Dealt\sto\s%(PLYR)s\s\[(?P.*)\]' % subst) @@ -144,6 +155,9 @@ class Winamax(HandHistoryConverter): ["ring", "hold", "fl"], ["ring", "hold", "nl"], ["ring", "hold", "pl"], + ["tour", "hold", "fl"], + ["tour", "hold", "nl"], + ["tour", "hold", "pl"], ] def determineGameType(self, handText): @@ -160,7 +174,11 @@ class Winamax(HandHistoryConverter): mg = m.groupdict() - info['type'] = 'ring' + if mg.get('TOUR'): + info['type'] = 'tour' + elif mg.get('RING'): + info['type'] = 'ring' + info['currency'] = 'EUR' if 'LIMIT' in mg: @@ -202,11 +220,62 @@ class Winamax(HandHistoryConverter): hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") # also timezone at end, e.g. " ET" hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, "CET", "UTC") if key == 'HID1': - hand.handid = "1%.4d%s%s"%(int(info['HID2']),info['HID1'],info['HID3']) # Need to remove non-alphanumerics for MySQL + hand.handid = "1%.9d%s%s"%(int(info['HID2']),info['HID1'],info['HID3']) + if key == 'TOURNO': + hand.tourNo = info[key] if key == 'TABLE': hand.tablename = info[key] + if key == 'BUYIN': + if hand.tourNo!=None: + #print "DEBUG: info['BUYIN']: %s" % info['BUYIN'] + #print "DEBUG: info['BIAMT']: %s" % info['BIAMT'] + #print "DEBUG: info['BIRAKE']: %s" % info['BIRAKE'] + #print "DEBUG: info['BOUNTY']: %s" % info['BOUNTY'] + for k in ['BIAMT','BIRAKE']: + if k in info.keys() and info[k]: + info[k] = info[k].replace(',','.') + + if info[key] == 'Freeroll': + hand.buyin = 0 + hand.fee = 0 + hand.buyinCurrency = "FREE" + else: + if info[key].find("$")!=-1: + hand.buyinCurrency="USD" + elif info[key].find(u"€")!=-1: + hand.buyinCurrency="EUR" + elif info[key].find("FPP")!=-1: + hand.buyinCurrency="PSFP" + else: + #FIXME: handle other currencies, FPP, play money + raise FpdbParseError(_("failed to detect currency")) + + info['BIAMT'] = info['BIAMT'].strip(u'$€FPP') + + if hand.buyinCurrency!="PSFP": + if info['BOUNTY'] != None: + # There is a bounty, Which means we need to switch BOUNTY and BIRAKE values + tmp = info['BOUNTY'] + info['BOUNTY'] = info['BIRAKE'] + info['BIRAKE'] = tmp + info['BOUNTY'] = info['BOUNTY'].strip(u'$€') # Strip here where it isn't 'None' + hand.koBounty = int(100*Decimal(info['BOUNTY'])) + hand.isKO = True + else: + hand.isKO = False + + info['BIRAKE'] = info['BIRAKE'].strip(u'$€') + hand.buyin = int(100*Decimal(info['BIAMT'])) + hand.fee = int(100*Decimal(info['BIRAKE'])) + else: + hand.buyin = int(Decimal(info['BIAMT'])) + hand.fee = 0 + + if key == 'LEVEL': + hand.level = info[key] + # TODO: These hand.buttonpos = 1 hand.maxseats = 10 # Set to None - Hand.py will guessMaxSeats() From 622b3507952fe395af36a2a3840adce9710690d8 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Fri, 26 Nov 2010 18:15:28 -0500 Subject: [PATCH 04/15] Revert "Merge branch 'chaz' of git://github.com/ChazDazzle/fpdb-chaz" This reverts commit 61ac6be0fab6f2ca9395bbb3cc4f4cba222842b2, reversing changes made to 18df2ef2c6fb77d9ece345d2c051b911fa6d0f8d. Conflicts: pyfpdb/SQL.py --- pyfpdb/Database.py | 41 +++++----- pyfpdb/IdentifySite.py | 15 ++-- pyfpdb/Options.py | 2 - pyfpdb/PokerStarsToFpdb.py | 2 +- pyfpdb/SQL.py | 22 +++--- pyfpdb/SplitHandHistory.py | 76 +++++++------------ pyfpdb/interlocks.py | 2 +- .../LHE-10max-USD-1.00-2.00-No_max_seats.txt | 42 ---------- 8 files changed, 67 insertions(+), 135 deletions(-) mode change 100644 => 100755 pyfpdb/interlocks.py delete mode 100644 pyfpdb/regression-test-files/cash/Stars/Flop/LHE-10max-USD-1.00-2.00-No_max_seats.txt diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 65e7a87d..9a17a1f1 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -55,7 +55,6 @@ import Card import Charset from Exceptions import * import Configuration -import Filters # Other library modules @@ -292,8 +291,8 @@ class Database: # vars for hand ids or dates fetched according to above config: self.hand_1day_ago = 0 # max hand id more than 24 hrs earlier than now - self.date_ndays_ago = 'd00000000' # date N days ago ('d' + YYMMDD) - self.h_date_ndays_ago = 'd00000000' # date N days ago ('d' + YYMMDD) for hero + self.date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) + self.h_date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) for hero self.date_nhands_ago = {} # dates N hands ago per player - not used yet self.saveActions = False if self.import_options['saveActions'] == False else True @@ -690,23 +689,21 @@ class Database: else: if row and row[0]: self.hand_1day_ago = int(row[0]) - - offset = strptime(Filters.Filters(self, self.config, self.sql).getDates()[0],"%Y-%m-%d %H:%M:%S").tm_hour - - d = timedelta(days=hud_days, hours=offset) - now = datetime.utcnow() - d - self.date_ndays_ago = "d%02d%02d%02d%02d" % (now.year - 2000, now.month, now.day, offset) - d = timedelta(days=h_hud_days, hours=offset) + d = timedelta(days=hud_days) now = datetime.utcnow() - d - self.h_date_ndays_ago = "d%02d%02d%02d%02d" % (now.year - 2000, now.month, now.day, offset) + self.date_ndays_ago = "d%02d%02d%02d" % (now.year - 2000, now.month, now.day) + + d = timedelta(days=h_hud_days) + now = datetime.utcnow() - d + self.h_date_ndays_ago = "d%02d%02d%02d" % (now.year - 2000, now.month, now.day) def init_player_hud_stat_vars(self, playerid): # not sure if this is workable, to be continued ... try: # self.date_nhands_ago is used for fetching stats for last n hands (hud_style = 'H') # This option not used yet - needs to be called for each player :-( - self.date_nhands_ago[str(playerid)] = 'd00000000' + self.date_nhands_ago[str(playerid)] = 'd000000' # should use aggregated version of query if appropriate c.execute(self.sql.query['get_date_nhands_ago'], (self.hud_hands, playerid)) @@ -774,11 +771,11 @@ class Database: if hud_style == 'T': stylekey = self.date_ndays_ago elif hud_style == 'A': - stylekey = '000000000' # all stylekey values should be higher than this + stylekey = '0000000' # all stylekey values should be higher than this elif hud_style == 'S': - stylekey = 'zzzzzzzzz' # all stylekey values should be lower than this + stylekey = 'zzzzzzz' # all stylekey values should be lower than this else: - stylekey = '000000000' + stylekey = '0000000' log.info('hud_style: %s' % hud_style) #elif hud_style == 'H': @@ -787,11 +784,11 @@ class Database: if h_hud_style == 'T': h_stylekey = self.h_date_ndays_ago elif h_hud_style == 'A': - h_stylekey = '000000000' # all stylekey values should be higher than this + h_stylekey = '0000000' # all stylekey values should be higher than this elif h_hud_style == 'S': - h_stylekey = 'zzzzzzzzz' # all stylekey values should be lower than this + h_stylekey = 'zzzzzzz' # all stylekey values should be lower than this else: - h_stylekey = '00000000' + h_stylekey = '000000' log.info('h_hud_style: %s' % h_hud_style) #elif h_hud_style == 'H': @@ -1827,11 +1824,11 @@ class Database: """Update cached statistics. If update fails because no record exists, do an insert.""" if self.use_date_in_hudcache: - styleKey = datetime.strftime(starttime, 'd%y%m%d%H') - #styleKey = "d%02d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day, hand_start_time.hour) + styleKey = datetime.strftime(starttime, 'd%y%m%d') + #styleKey = "d%02d%02d%02d" % (hand_start_time.year-2000, hand_start_time.month, hand_start_time.day) else: - # hard-code styleKey as 'A00000000' (all-time cache, no key) for now - styleKey = 'A00000000' + # hard-code styleKey as 'A000000' (all-time cache, no key) for now + styleKey = 'A000000' update_hudcache = self.sql.query['update_hudcache'] update_hudcache = update_hudcache.replace('%s', self.sql.query['placeholder']) diff --git a/pyfpdb/IdentifySite.py b/pyfpdb/IdentifySite.py index 723991f3..b4f1a8a7 100644 --- a/pyfpdb/IdentifySite.py +++ b/pyfpdb/IdentifySite.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python # -*- coding: utf-8 -*- #Copyright 2010 Chaz Littlejohn @@ -28,21 +28,18 @@ import Configuration import Database __ARCHIVE_PRE_HEADER_REGEX='^Hand #(\d+)\s*$|\*{20}\s#\s\d+\s\*+\s+' -re_SplitArchive = re.compile(__ARCHIVE_PRE_HEADER_REGEX, re.MULTILINE) +re_SplitArchive = re.compile(__ARCHIVE_PRE_HEADER_REGEX) class IdentifySite: def __init__(self, config, in_path = '-'): self.in_path = in_path self.config = config - self.db = Database.Database(self.config) + self.db = Database.Database(config) self.sitelist = {} self.filelist = {} self.generateSiteList() - if os.path.isdir(self.in_path): - self.walkDirectory(self.in_path, self.sitelist) - else: - self.idSite(self.in_path, self.sitelist) + self.walkDirectory(self.in_path, self.sitelist) def generateSiteList(self): """Generates a ordered dictionary of site, filter and filter name for each site in hhcs""" @@ -83,7 +80,7 @@ class IdentifySite: for kodec in self.__listof(obj.codepage): try: in_fh = codecs.open(file, 'r', kodec) - whole_file = in_fh.read(2000) + whole_file = in_fh.read() in_fh.close() if info[2] in ('OnGame', 'Winamax'): @@ -97,7 +94,7 @@ class IdentifySite: if re_SplitArchive.search(whole_file): archive = True if m: - self.filelist[file] = [info[1]] + [kodec] + [archive] + self.filelist[file] = [info[0]] + [info[1]] + [kodec] + [archive] break except: pass diff --git a/pyfpdb/Options.py b/pyfpdb/Options.py index 6369b485..b8be3d2a 100644 --- a/pyfpdb/Options.py +++ b/pyfpdb/Options.py @@ -59,8 +59,6 @@ def fpdb_options(): help=_("File to be split is a PokerStars or Full Tilt Poker archive file")) parser.add_option("-n", "--numhands", dest="hands", default="100", type="int", help=_("How many hands do you want saved to each file. Default is 100")) - parser.add_option("-w", "--workerid", dest="workerid", default="0", type="int", - help=_("Specifies the worker id running the script")) (options, argv) = parser.parse_args() diff --git a/pyfpdb/PokerStarsToFpdb.py b/pyfpdb/PokerStarsToFpdb.py index 3817ae3f..16c4091e 100644 --- a/pyfpdb/PokerStarsToFpdb.py +++ b/pyfpdb/PokerStarsToFpdb.py @@ -298,7 +298,7 @@ class PokerStars(HandHistoryConverter): if key == 'BUTTON': hand.buttonpos = info[key] if key == 'MAX': - if info[key]: hand.maxseats = int(info[key]) + hand.maxseats = int(info[key]) if key == 'MIXED': hand.mixed = self.mixes[info[key]] if info[key] is not None else None diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 6a505eae..d45ccd38 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1064,7 +1064,7 @@ class Sql: activeSeats SMALLINT NOT NULL, position CHAR(1), tourneyTypeId SMALLINT UNSIGNED, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), - styleKey CHAR(9) NOT NULL, /* 1st char is style (A/T/H/S), other 8 are the key */ + styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */ HDs INT NOT NULL, wonWhenSeenStreet1 FLOAT, @@ -1165,7 +1165,7 @@ class Sql: activeSeats SMALLINT, position CHAR(1), tourneyTypeId INT, FOREIGN KEY (tourneyTypeId) REFERENCES TourneyTypes(id), - styleKey CHAR(9) NOT NULL, /* 1st char is style (A/T/H/S), other 8 are the key */ + styleKey CHAR(7) NOT NULL, /* 1st char is style (A/T/H/S), other 6 are the key */ HDs INT, wonWhenSeenStreet1 FLOAT, @@ -2047,7 +2047,7 @@ class Sql: # gets a date, would need to use handsplayers (not hudcache) to get exact hand Id if db_server == 'mysql': self.query['get_date_nhands_ago'] = """ - select concat( 'd', date_format(max(h.startTime), '%Y%m%d%H') ) + select concat( 'd', date_format(max(h.startTime), '%Y%m%d') ) from (select hp.playerId ,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx from HandsPlayers hp @@ -2059,7 +2059,7 @@ class Sql: """ elif db_server == 'postgresql': self.query['get_date_nhands_ago'] = """ - select 'd' || to_char(max(h3.startTime), 'YYMMDDHH') + select 'd' || to_char(max(h3.startTime), 'YYMMDD') from (select hp.playerId ,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx from HandsPlayers hp @@ -2071,7 +2071,7 @@ class Sql: """ elif db_server == 'sqlite': # untested guess at query: self.query['get_date_nhands_ago'] = """ - select 'd' || strftime(max(h3.startTime), 'YYMMDDHH') + select 'd' || strftime(max(h3.startTime), 'YYMMDD') from (select hp.playerId ,coalesce(greatest(max(hp.handId)-%s,1),1) as maxminusx from HandsPlayers hp @@ -3290,7 +3290,7 @@ class Sql: else 'E' end AS hc_position - ,date_format(h.startTime, 'd%y%m%d%H') + ,date_format(h.startTime, 'd%y%m%d') ,count(1) ,sum(wonWhenSeenStreet1) ,sum(wonWhenSeenStreet2) @@ -3379,7 +3379,7 @@ class Sql: ,h.seats ,hc_position - ,date_format(h.startTime, 'd%y%m%d%H') + ,date_format(h.startTime, 'd%y%m%d') """ elif db_server == 'postgresql': self.query['rebuildHudCache'] = """ @@ -3488,7 +3488,7 @@ class Sql: else 'E' end AS hc_position - ,'d' || to_char(h.startTime, 'YYMMDDHH') + ,'d' || to_char(h.startTime, 'YYMMDD') ,count(1) ,sum(wonWhenSeenStreet1) ,sum(wonWhenSeenStreet2) @@ -3577,7 +3577,7 @@ class Sql: ,h.seats ,hc_position - ,to_char(h.startTime, 'YYMMDDHH') + ,to_char(h.startTime, 'YYMMDD') """ else: # assume sqlite self.query['rebuildHudCache'] = """ @@ -3686,7 +3686,7 @@ class Sql: else 'E' end AS hc_position - ,'d' || substr(strftime('%Y%m%d%H', h.startTime),3,9) + ,'d' || substr(strftime('%Y%m%d', h.startTime),3,7) ,count(1) ,sum(wonWhenSeenStreet1) ,sum(wonWhenSeenStreet2) @@ -3775,7 +3775,7 @@ class Sql: ,h.seats ,hc_position - ,'d' || substr(strftime('%Y%m%d%H', h.startTime),3,9) + ,'d' || substr(strftime('%Y%m%d', h.startTime),3,7) """ self.query['insert_hudcache'] = """ diff --git a/pyfpdb/SplitHandHistory.py b/pyfpdb/SplitHandHistory.py index c996f903..52c1d340 100644 --- a/pyfpdb/SplitHandHistory.py +++ b/pyfpdb/SplitHandHistory.py @@ -1,22 +1,19 @@ -#!/usr/bin/env python +#!/usr/bin/python +# -*- coding: utf-8 -*- -# Copyright 2010, Chaz Littlejohn -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# 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 General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -######################################################################## +#Copyright 2010 Chaz Littlejohn +#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. import L10n _ = L10n.get_translation() @@ -31,7 +28,6 @@ import Options import Configuration from Exceptions import * from cStringIO import StringIO -import time (options, argv) = Options.fpdb_options() @@ -41,7 +37,7 @@ codepage = ["utf-16", "utf-8", "cp1252"] class SplitHandHistory: - def __init__(self, config, in_path = '-', out_path = None, hands = 100, filter = "PokerStarsToFpdb", archive = False, workerid = 0): + def __init__(self, config, in_path = '-', out_path = None, hands = 100, filter = "PokerStarsToFpdb", archive = False): self.config = config self.in_path = in_path self.out_path = out_path @@ -54,25 +50,22 @@ class SplitHandHistory: self.line_addendum = None self.filedone = False - self.timestamp = str(time.time()) - self.workerid = '%02d' % workerid - #Acquire re_SplitHands for this hh - self.filter_name = filter.replace("ToFpdb", "") + filter_name = filter.replace("ToFpdb", "") mod = __import__(filter) - obj = getattr(mod, self.filter_name, None) + obj = getattr(mod, filter_name, None) self.re_SplitHands = obj.re_SplitHands #Determine line delimiter type if any - if self.re_SplitHands.match('\n\n\n'): - self.line_delimiter = '\n\n\n' if self.re_SplitHands.match('\n\n'): self.line_delimiter = '\n\n' + if self.re_SplitHands.match('\n\n\n'): + self.line_delimiter = '\n\n\n' #Add new line addendum for sites which match SplitHand to next line as well - if self.filter_name == 'OnGame': + if filter_name == 'OnGame': self.line_addendum = '*' - if self.filter_name == 'Carbon': + if filter_name == 'Carbon': self.line_addendum = ' %s' % name newfile = file(name, 'w') - os.chmod(name, 0775) return newfile #Archive Hand Splitter @@ -131,11 +122,8 @@ class SplitHandHistory: except FpdbEndOfFile: done = True break - except UnicodeEncodeError: - print _('Absurd character done messed you up') - sys.exit(2) except: - print _('Unexpected error processing file') + print _("Unexpected error processing file") sys.exit(2) n += 1 outfile.close() @@ -186,7 +174,7 @@ class SplitHandHistory: l = infile.readline() l = l.replace('\r\n', '\n') outfile.write(l) - l = infile.readline().encode(self.kodec) + l = infile.readline() while len(l) < 3: l = infile.readline() @@ -194,7 +182,7 @@ class SplitHandHistory: while len(l) > 2: l = l.replace('\r\n', '\n') outfile.write(l) - l = infile.readline().encode(self.kodec) + l = infile.readline() outfile.write(self.line_delimiter) return infile @@ -207,19 +195,13 @@ class SplitHandHistory: def main(argv=None): if argv is None: argv = sys.argv[1:] - - if not options.filename: - options.filename = sys.argv[1] if not options.config: - options.config = sys.argv[2] - - if sys.argv[3] == "True": - options.archive = True - + options.config = Configuration.Config(file = "HUD_config.test.xml") + if options.filename: SplitHH = SplitHandHistory(options.config, options.filename, options.outpath, options.hands, - options.hhc, options.archive, options.workerid) + options.hhc, options.archive) if __name__ == '__main__': sys.exit(main()) diff --git a/pyfpdb/interlocks.py b/pyfpdb/interlocks.py old mode 100644 new mode 100755 index 496c5d0b..c2e6abd6 --- a/pyfpdb/interlocks.py +++ b/pyfpdb/interlocks.py @@ -108,7 +108,7 @@ class InterProcessLockFcntl(InterProcessLockBase): self.lockfd = 0 try: os.unlink(self.lock_file_name) - except OSError: + except IOError: # We don't care about the existence of the file too much here. It's the flock() we care about, # And that should just go away magically. pass diff --git a/pyfpdb/regression-test-files/cash/Stars/Flop/LHE-10max-USD-1.00-2.00-No_max_seats.txt b/pyfpdb/regression-test-files/cash/Stars/Flop/LHE-10max-USD-1.00-2.00-No_max_seats.txt deleted file mode 100644 index 173da216..00000000 --- a/pyfpdb/regression-test-files/cash/Stars/Flop/LHE-10max-USD-1.00-2.00-No_max_seats.txt +++ /dev/null @@ -1,42 +0,0 @@ -PokerStars Game #2428142447: Hold'em Limit ($1/$2 USD) - 2005/08/26 16:12:22 ET -Table 'Teucer II' Seat #5 is the button -Seat 1: Frankson34 ($24 in chips) -Seat 2: webb22 ($64 in chips) -Seat 3: eric_mtx ($26 in chips) -Seat 4: sososolid ($147.75 in chips) -Seat 5: DRILHER ($48.25 in chips) -Seat 6: Naughtychic ($60 in chips) -Seat 7: Terps78 ($71.50 in chips) -Seat 8: ChazDazzle ($69.25 in chips) -Seat 9: alekos ($55 in chips) -Seat 10: BigNards84 ($64.25 in chips) -Naughtychic: posts small blind $0.50 -Terps78: posts big blind $1 -*** HOLE CARDS *** -Dealt to ChazDazzle [8c Kd] -ChazDazzle: folds -alekos: folds -BigNards84: raises $1 to $2 -Frankson34: folds -webb22: folds -eric_mtx: folds -ChazDazzle leaves the table -sososolid: folds -DRILHER: folds -cdhender joins the table at seat #8 -Naughtychic: folds -Terps78: folds -BigNards84 collected $2.50 from pot -BigNards84: doesn't show hand -*** SUMMARY *** -Total pot $2.50 | Rake $0 -Seat 1: Frankson34 folded before Flop (didn't bet) -Seat 2: webb22 folded before Flop (didn't bet) -Seat 3: eric_mtx folded before Flop (didn't bet) -Seat 4: sososolid folded before Flop (didn't bet) -Seat 5: DRILHER (button) folded before Flop (didn't bet) -Seat 6: Naughtychic (small blind) folded before Flop -Seat 7: Terps78 (big blind) folded before Flop -Seat 8: ChazDazzle folded before Flop (didn't bet) -Seat 9: alekos folded before Flop (didn't bet) -Seat 10: BigNards84 collected ($2.50) From bfa3cfc20cdf1612b4e74dd834cba217d2015858 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Fri, 26 Nov 2010 18:51:25 -0500 Subject: [PATCH 05/15] check for AttributeError at new window_foreign_new call --- pyfpdb/TableWindow.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/TableWindow.py b/pyfpdb/TableWindow.py index 61d7bd80..c0241df4 100644 --- a/pyfpdb/TableWindow.py +++ b/pyfpdb/TableWindow.py @@ -138,7 +138,10 @@ class Table_Window(object): self.search_string = getTableTitleRe(self.config, self.site, self.type, **table_kwargs) self.find_table_parameters() - self.gdkhandle = gtk.gdk.window_foreign_new(self.number) + try: + self.gdkhandle = gtk.gdk.window_foreign_new(self.number) + except AttributeError: # self.number does not exist, table was closed + return None geo = self.get_geometry() if geo is None: return None self.width = geo['width'] From e5f4f5710d51744a7fbba33e0301fc728d532b85 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Fri, 26 Nov 2010 23:13:14 -0500 Subject: [PATCH 06/15] read_stdin: return if fail to find table, rather than continue along, also trap KeyError at end of func when checking tournament tables. (maybe this'll finally fix the hud locking up on table close sometimes?) --- pyfpdb/HUD_main.pyw | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyfpdb/HUD_main.pyw b/pyfpdb/HUD_main.pyw index 145e9048..54484c45 100755 --- a/pyfpdb/HUD_main.pyw +++ b/pyfpdb/HUD_main.pyw @@ -354,6 +354,7 @@ class HUD_main(object): self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, type, stat_dict, cards) else: log.error(_('Table "%s" no longer exists\n') % table_name) + return t6 = time.time() log.info(_("HUD_main.read_stdin: hand read in %4.3f seconds (%4.3f,%4.3f,%4.3f,%4.3f,%4.3f,%4.3f)") @@ -361,7 +362,10 @@ class HUD_main(object): self.db_connection.connection.rollback() if type == "tour": - self.hud_dict[temp_key].table.check_table_no(self.hud_dict[temp_key]) + try: + self.hud_dict[temp_key].table.check_table_no(self.hud_dict[temp_key]) + except KeyError: + pass if __name__== "__main__": From 2990e5856dc00919469804d19fde8f8a0d45944d Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Sat, 27 Nov 2010 18:34:30 -0500 Subject: [PATCH 07/15] Button changes immediately after pressing it instead of waiting until the pipe is ready. Terminates HUD process rather than asking it to close --- pyfpdb/GuiAutoImport.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 0121509d..59fe808c 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -213,6 +213,8 @@ class GuiAutoImport (threading.Thread): self.addText(_("\nGlobal lock taken ... Auto Import Started.\n")) self.doAutoImportBool = True widget.set_label(_(u' _Stop Auto Import ')) + while gtk.events_pending(): # change the label NOW don't wait for the pipe to open + gtk.main_iteration(False) if self.pipe_to_hud is None: if Configuration.FROZEN: # if py2exe, run hud_main.exe path = Configuration.EXEC_PATH @@ -224,15 +226,14 @@ class GuiAutoImport (threading.Thread): command = 'pythonw "'+path+'\\HUD_main.pyw" ' + self.settings['cl_options'] else: command = 'python "'+path+'\\HUD_main.pyw" ' + self.settings['cl_options'] - # uncomment above line if you want hud_main stdout to work ... and make sure you are running fpdb.py using python.exe not pythonw.exe bs = 0 else: command = os.path.join(sys.path[0], 'HUD_main.pyw') command = [command, ] + string.split(self.settings['cl_options']) bs = 1 - try: print _("opening pipe to HUD") + try: if Configuration.FROZEN or (os.name == "nt" and win32console.GetConsoleWindow()) == 0: self.pipe_to_hud = subprocess.Popen(command, bufsize=bs, stdin=subprocess.PIPE, @@ -242,8 +243,6 @@ class GuiAutoImport (threading.Thread): ) else: self.pipe_to_hud = subprocess.Popen(command, bufsize=bs, stdin=subprocess.PIPE, universal_newlines=True) - #self.pipe_to_hud.stdout.close() - #self.pipe_to_hud.stderr.close() except: err = traceback.extract_tb(sys.exc_info()[2])[-1] #self.addText( "\n*** GuiAutoImport Error opening pipe: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1])) @@ -268,8 +267,9 @@ class GuiAutoImport (threading.Thread): if self.pipe_to_hud.poll() is not None: self.addText(_("\n * Stop Auto Import: HUD already terminated")) else: + self.pipe_to_hud.terminate() #print >>self.pipe_to_hud.stdin, "\n" - self.pipe_to_hud.communicate('\n') # waits for process to terminate + # self.pipe_to_hud.communicate('\n') # waits for process to terminate self.pipe_to_hud = None self.startButton.set_label(_(u' Start _Auto Import ')) From f94ad0126ad6d912e72ea81562f8aa7603b01d1f Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Sat, 27 Nov 2010 19:16:15 -0500 Subject: [PATCH 08/15] add --xloc and --yloc options for specifying where to start windows at --- pyfpdb/HUD_main.pyw | 6 ++++++ pyfpdb/Options.py | 4 ++++ pyfpdb/fpdb.pyw | 10 ++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pyfpdb/HUD_main.pyw b/pyfpdb/HUD_main.pyw index 54484c45..098ff57a 100755 --- a/pyfpdb/HUD_main.pyw +++ b/pyfpdb/HUD_main.pyw @@ -102,6 +102,12 @@ class HUD_main(object): # a main window self.main_window = gtk.Window() + if options.xloc is not None or options.yloc is not None: + if options.xloc is None: + options.xloc = 0 + if options.yloc is None: + options.yloc = 0 + self.main_window.move(options.xloc,options.yloc) self.main_window.connect("client_moved", self.client_moved) self.main_window.connect("client_resized", self.client_resized) self.main_window.connect("client_destroyed", self.client_destroyed) diff --git a/pyfpdb/Options.py b/pyfpdb/Options.py index b8be3d2a..d66675c5 100644 --- a/pyfpdb/Options.py +++ b/pyfpdb/Options.py @@ -59,6 +59,10 @@ def fpdb_options(): help=_("File to be split is a PokerStars or Full Tilt Poker archive file")) parser.add_option("-n", "--numhands", dest="hands", default="100", type="int", help=_("How many hands do you want saved to each file. Default is 100")) + parser.add_option("--xloc", dest="xloc", default=None, type="int", + help=_("X location to open window")) + parser.add_option("--yloc", dest="yloc", default=None, type="int", + help=_("Y location to open Window")) (options, argv) = parser.parse_args() diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 3660dd57..0135aa26 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -14,7 +14,6 @@ #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. - import L10n _ = L10n.get_translation() @@ -1097,6 +1096,13 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an self.visible = False self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) + if options.xloc is not None or options.yloc is not None: + if options.xloc is None: + options.xloc = 0 + if options.yloc is None: + options.yloc = 0 + self.window.move(options.xloc,options.yloc) + self.window.connect("delete_event", self.delete_event) self.window.connect("destroy", self.destroy) self.window.set_title("Free Poker DB - v%s" % (VERSION, )) @@ -1148,7 +1154,7 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an cards = os.path.join(os.getcwd(), '..','gfx','fpdb-cards.png') if os.path.exists(cards): self.statusIcon.set_from_file(cards) - self.window.set_icon_from_file(cards) + self.window.set_icon_from_file(cards) elif os.path.exists('/usr/share/pixmaps/fpdb-cards.png'): self.statusIcon.set_from_file('/usr/share/pixmaps/fpdb-cards.png') self.window.set_icon_from_file('/usr/share/pixmaps/fpdb-cards.png') From e2b86eb239320f89e95fda78ab0c2e1160fef55b Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Sat, 27 Nov 2010 19:32:28 -0500 Subject: [PATCH 09/15] Add --autoimport command argument --- pyfpdb/GuiAutoImport.py | 2 +- pyfpdb/Options.py | 2 ++ pyfpdb/fpdb.pyw | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 59fe808c..3cc816ed 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -204,7 +204,7 @@ class GuiAutoImport (threading.Thread): # That is not correct. It should open another dir for importing while piping the # results to the same pipe. This means that self.path should be a a list of dirs # to watch. - if widget.get_active(): # toggled on + if widget.get_active() or data == "autostart": # toggled on # - Does the lock acquisition need to be more sophisticated for multiple dirs? # (see comment above about what to do if pipe already open) # - Ideally we want to release the lock if the auto-import is killed by some diff --git a/pyfpdb/Options.py b/pyfpdb/Options.py index d66675c5..9f5778ea 100644 --- a/pyfpdb/Options.py +++ b/pyfpdb/Options.py @@ -63,6 +63,8 @@ def fpdb_options(): help=_("X location to open window")) parser.add_option("--yloc", dest="yloc", default=None, type="int", help=_("Y location to open Window")) + parser.add_option("--autoimport", action="store_true", dest="autoimport", + help=_("Auto-start Auto-import")) (options, argv) = parser.parse_args() diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 0135aa26..90ce59e8 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -993,6 +993,9 @@ class fpdb: self.threads.append(new_aimp_thread) aimp_tab=new_aimp_thread.get_vbox() self.add_and_display_tab(aimp_tab, _("Auto Import")) + if options.autoimport: + new_aimp_thread.startClicked(new_aimp_thread.startButton, "autostart") + options.autoimport = False def tab_bulk_import(self, widget, data=None): """opens a tab for bulk importing""" @@ -1177,6 +1180,9 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an self.window.connect('window-state-event', self.window_state_event_cb) sys.stderr.write(_("fpdb starting ...")) + + if options.autoimport: + self.tab_auto_import(None) def __iconify(self): From 7402c57eb1c040c01974bffee2401dcfa4b1338a Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Sat, 27 Nov 2010 20:35:34 -0500 Subject: [PATCH 10/15] --hidden --minimized --- pyfpdb/HUD_main.pyw | 8 +++++++- pyfpdb/Options.py | 4 ++++ pyfpdb/fpdb.pyw | 5 +++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/pyfpdb/HUD_main.pyw b/pyfpdb/HUD_main.pyw index 098ff57a..cb2d7b3f 100755 --- a/pyfpdb/HUD_main.pyw +++ b/pyfpdb/HUD_main.pyw @@ -102,6 +102,11 @@ class HUD_main(object): # a main window self.main_window = gtk.Window() + if options.minimized: + self.main_window.iconify() + if options.hidden: + self.main_window.hide() + if options.xloc is not None or options.yloc is not None: if options.xloc is None: options.xloc = 0 @@ -126,7 +131,8 @@ class HUD_main(object): self.main_window.set_icon_from_file('/usr/share/pixmaps/fpdb-cards.png') else: self.main_window.set_icon_stock(gtk.STOCK_HOME) - self.main_window.show_all() + if not options.hidden: + self.main_window.show_all() gobject.timeout_add(100, self.check_tables) except: diff --git a/pyfpdb/Options.py b/pyfpdb/Options.py index 9f5778ea..fb23d43c 100644 --- a/pyfpdb/Options.py +++ b/pyfpdb/Options.py @@ -65,6 +65,10 @@ def fpdb_options(): help=_("Y location to open Window")) parser.add_option("--autoimport", action="store_true", dest="autoimport", help=_("Auto-start Auto-import")) + parser.add_option("--minimized", action="store_true", dest="minimized", + help=_("Start Minimized")) + parser.add_option("--hidden", action="store_true", dest="hidden", + help=_("Start Hidden")) (options, argv) = parser.parse_args() diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 90ce59e8..9ba1dfea 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -1140,6 +1140,11 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an self.nb_tab_names=[] # list of tab names currently displayed in notebook self.tab_main_help(None, None) + + if options.minimized: + self.window.iconify() + if options.hidden: + self.window.hide() self.window.show() self.visible = True # Flip on From 336fee0f3d1f4e748e986dc98ad0908d0e5870a9 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Sat, 27 Nov 2010 20:36:42 -0500 Subject: [PATCH 11/15] oops --- pyfpdb/fpdb.pyw | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 9ba1dfea..83463e36 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -1146,7 +1146,8 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an if options.hidden: self.window.hide() - self.window.show() + if not options.hidden: + self.window.show() self.visible = True # Flip on self.load_profile(create_db = True) From e5782dd7360ad00980d49f588bc41c9d1ab71e5f Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Sun, 28 Nov 2010 20:00:56 -0500 Subject: [PATCH 12/15] some cleanups and comments --- pyfpdb/GuiAutoImport.py | 10 ++++-- pyfpdb/fpdb.pyw | 67 ++++++++++++++++++++++++++++------------- 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index 3cc816ed..b6d7bcaf 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -204,15 +204,19 @@ class GuiAutoImport (threading.Thread): # That is not correct. It should open another dir for importing while piping the # results to the same pipe. This means that self.path should be a a list of dirs # to watch. - if widget.get_active() or data == "autostart": # toggled on + if data == "autostart": + self.startButton.set_active(True) + return + + if widget == self.startButton and self.startButton.get_active(): # - Does the lock acquisition need to be more sophisticated for multiple dirs? # (see comment above about what to do if pipe already open) # - Ideally we want to release the lock if the auto-import is killed by some # kind of exception - is this possible? - if self.settings['global_lock'].acquire(False): # returns false immediately if lock not acquired + if self.settings['global_lock'].acquire(False, source="AutoImport"): # returns false immediately if lock not acquired self.addText(_("\nGlobal lock taken ... Auto Import Started.\n")) self.doAutoImportBool = True - widget.set_label(_(u' _Stop Auto Import ')) + self.startButton.set_label(_(u' _Stop Auto Import ')) while gtk.events_pending(): # change the label NOW don't wait for the pipe to open gtk.main_iteration(False) if self.pipe_to_hud is None: diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 83463e36..53f74aa4 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -964,8 +964,8 @@ class fpdb: self.quitting = True # TODO: check if current settings differ from profile, if so offer to save or abort - if self.db!=None: - if self.db.backend==self.db.MYSQL_INNODB: + if self.db is not None: + if self.db.backend == self.db.MYSQL_INNODB: try: import _mysql_exceptions if self.db is not None and self.db.is_connected(): @@ -991,7 +991,7 @@ class fpdb: """opens the auto import tab""" new_aimp_thread = GuiAutoImport.GuiAutoImport(self.settings, self.config, self.sql, self.window) self.threads.append(new_aimp_thread) - aimp_tab=new_aimp_thread.get_vbox() + aimp_tab = new_aimp_thread.get_vbox() self.add_and_display_tab(aimp_tab, _("Auto Import")) if options.autoimport: new_aimp_thread.startClicked(new_aimp_thread.startButton, "autostart") @@ -1096,8 +1096,11 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an self.db = None self.status_bar = None self.quitting = False - self.visible = False + self.threads = [] # objects used by tabs - no need for threads, gtk handles it + self.closeq = Queue.Queue(20) # used to signal ending of a thread (only logviewer for now) + + # create window, move it to specific location on command line self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) if options.xloc is not None or options.yloc is not None: if options.xloc is None: @@ -1106,9 +1109,11 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an options.yloc = 0 self.window.move(options.xloc,options.yloc) + # connect to required events self.window.connect("delete_event", self.delete_event) self.window.connect("destroy", self.destroy) self.window.set_title("Free Poker DB - v%s" % (VERSION, )) + # set a default x/y size for the window self.window.set_border_width(1) defx, defy = 900, 720 sx, sy = gtk.gdk.screen_width(), gtk.gdk.screen_height() @@ -1117,30 +1122,31 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an self.window.set_default_size(defx, defy) self.window.set_resizable(True) + # main area of window self.main_vbox = gtk.VBox(False, 1) self.main_vbox.set_border_width(1) self.window.add(self.main_vbox) self.main_vbox.show() + # create our Main Menu Bar menubar = self.get_menu(self.window) self.main_vbox.pack_start(menubar, False, True, 0) menubar.show() - #done menubar - - self.threads = [] # objects used by tabs - no need for threads, gtk handles it - self.closeq = Queue.Queue(20) # used to signal ending of a thread (only logviewer for now) + # create a tab bar self.nb = gtk.Notebook() self.nb.set_show_tabs(True) self.nb.show() self.main_vbox.pack_start(self.nb, True, True, 0) - self.tabs=[] # the event_boxes forming the actual tabs - self.tab_names=[] # names of tabs used since program started, not removed if tab is closed - self.pages=[] # the contents of the page, not removed if tab is closed - self.nb_tab_names=[] # list of tab names currently displayed in notebook + self.tabs = [] # the event_boxes forming the actual tabs + self.tab_names = [] # names of tabs used since program started, not removed if tab is closed + self.pages = [] # the contents of the page, not removed if tab is closed + self.nb_tab_names = [] # list of tab names currently displayed in notebook + # create the first tab self.tab_main_help(None, None) + # determine window visibility from command line options if options.minimized: self.window.iconify() if options.hidden: @@ -1148,9 +1154,11 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an if not options.hidden: self.window.show() - self.visible = True # Flip on + self.visible = True # Flip on + self.load_profile(create_db = True) + # setup error logging if not options.errorsToConsole: fileName = os.path.join(self.config.dir_log, 'fpdb-errors.txt') print (_("\nNote: error output is being diverted to fpdb-errors.txt and HUD-errors.txt in: %s") % self.config.dir_log) \ @@ -1158,6 +1166,7 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an errorFile = open(fileName, 'w', 0) sys.stderr = errorFile + # set up tray-icon and menu self.statusIcon = gtk.StatusIcon() # use getcwd() here instead of sys.path[0] so that py2exe works: cards = os.path.join(os.getcwd(), '..','gfx','fpdb-cards.png') @@ -1173,13 +1182,10 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an self.statusIcon.set_tooltip("Free Poker Database") self.statusIcon.connect('activate', self.statusicon_activate) self.statusMenu = gtk.Menu() - menuItem = gtk.ImageMenuItem(gtk.STOCK_ABOUT) - menuItem.connect('activate', self.dia_about) - self.statusMenu.append(menuItem) - - menuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT) - menuItem.connect('activate', self.quit) - self.statusMenu.append(menuItem) + + # set default menu options + self.addImageToTrayMenu(gtk.STOCK_ABOUT, self.dia_about) + self.addImageToTrayMenu(gtk.STOCK_QUIT, self.quit) self.statusIcon.connect('popup-menu', self.statusicon_menu, self.statusMenu) self.statusIcon.set_visible(True) @@ -1189,7 +1195,26 @@ You can find the full license texts in agpl-3.0.txt, gpl-2.0.txt, gpl-3.0.txt an if options.autoimport: self.tab_auto_import(None) - + + def addImageToTrayMenu(self, image, event=None): + menuItem = gtk.ImageMenuItem(image) + if event is not None: + menuItem.connect('activate', event) + self.statusMenu.append(menuItem) + menuItem.show() + return menuItem + + def addLabelToTrayMenu(self, label, event=None): + menuItem = gtk.MenuItem(label) + if event is not None: + menuItem.connect('activate', event) + self.statusMenu.append(menuItem) + menuItem.show() + return menuItem + + def removeFromTrayMenu(self, menuItem): + menuItem.destroy() + menuItem = None def __iconify(self): self.visible = False From 7b1143a6ffdf5e4f45286b4bdbaccd1f9b625001 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Sun, 28 Nov 2010 20:04:32 -0500 Subject: [PATCH 13/15] make "source" argument to interlocks.acquire mandatory --- pyfpdb/interlocks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/interlocks.py b/pyfpdb/interlocks.py index c2e6abd6..3ec53b4d 100755 --- a/pyfpdb/interlocks.py +++ b/pyfpdb/interlocks.py @@ -45,7 +45,7 @@ class InterProcessLockBase: def acquire_impl(self, wait): abstract - def acquire(self, wait=False, retry_time=1, source=None): + def acquire(self, source, wait=False, retry_time=1): if source == None: source="Unknown" if self._has_lock: # make sure 2nd acquire in same process fails From 99535cddbbffc4f3e81a8b51a586aad363432926 Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Sun, 28 Nov 2010 20:15:09 -0500 Subject: [PATCH 14/15] cleanups --- pyfpdb/GuiAutoImport.py | 7 ++----- pyfpdb/fpdb.pyw | 10 +++++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/pyfpdb/GuiAutoImport.py b/pyfpdb/GuiAutoImport.py index b6d7bcaf..03bec89d 100755 --- a/pyfpdb/GuiAutoImport.py +++ b/pyfpdb/GuiAutoImport.py @@ -204,16 +204,13 @@ class GuiAutoImport (threading.Thread): # That is not correct. It should open another dir for importing while piping the # results to the same pipe. This means that self.path should be a a list of dirs # to watch. - if data == "autostart": + if data == "autostart" or (widget == self.startButton and self.startButton.get_active()): self.startButton.set_active(True) - return - - if widget == self.startButton and self.startButton.get_active(): # - Does the lock acquisition need to be more sophisticated for multiple dirs? # (see comment above about what to do if pipe already open) # - Ideally we want to release the lock if the auto-import is killed by some # kind of exception - is this possible? - if self.settings['global_lock'].acquire(False, source="AutoImport"): # returns false immediately if lock not acquired + if self.settings['global_lock'].acquire(wait=False, source="AutoImport"): # returns false immediately if lock not acquired self.addText(_("\nGlobal lock taken ... Auto Import Started.\n")) self.doAutoImportBool = True self.startButton.set_label(_(u' _Stop Auto Import ')) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index 53f74aa4..e7663007 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -75,7 +75,7 @@ try: pygtk.require('2.0') import gtk import pango -except: +except ImportError: print _("Unable to load PyGTK modules required for GUI. Please install PyCairo, PyGObject, and PyGTK from www.pygtk.org.") raw_input(_("Press ENTER to continue.")) exit() @@ -86,18 +86,18 @@ import interlocks try: import matplotlib matplotlib_version = matplotlib.__version__ -except: +except ImportError: matplotlib_version = 'not found' try: import numpy numpy_version = numpy.__version__ -except: +except ImportError: numpy_version = 'not found' try: import sqlite3 sqlite3_version = sqlite3.version sqlite_version = sqlite3.sqlite_version -except: +except ImportError: sqlite3_version = 'not found' sqlite_version = 'not found' @@ -203,7 +203,7 @@ class fpdb: gtk.Button.set_relief(button, gtk.RELIEF_NONE) settings = gtk.Widget.get_settings(button); (w,h) = gtk.icon_size_lookup_for_settings(settings, gtk.ICON_SIZE_SMALL_TOOLBAR); - gtk.Widget.set_size_request (button, w + 4, h + 4); + gtk.Widget.set_size_request(button, w + 4, h + 4); image.show() iconBox.pack_start(image, True, False, 0) button.add(iconBox) From 2d0ea89b9ac3b7308a5390b057581cbc6d1beb4b Mon Sep 17 00:00:00 2001 From: Eric Blade Date: Sun, 28 Nov 2010 20:24:39 -0500 Subject: [PATCH 15/15] comment --- pyfpdb/fpdb.pyw | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/fpdb.pyw b/pyfpdb/fpdb.pyw index e7663007..47636e99 100755 --- a/pyfpdb/fpdb.pyw +++ b/pyfpdb/fpdb.pyw @@ -931,6 +931,7 @@ class fpdb: response = diaDbVersionWarning.run() diaDbVersionWarning.destroy() + # TODO: This should probably be setup in GUI Init if self.status_bar is None: self.status_bar = gtk.Label("") self.main_vbox.pack_end(self.status_bar, False, True, 0)