From ac30e912c76bc3f6a731d5657850d1ee1133a0a4 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 21:39:14 +0100 Subject: [PATCH 1/7] smarten up positional stats tab (still needs configurable columns) --- pyfpdb/GuiPositionalStats.py | 184 ++++++++++++++++++++++------------- 1 file changed, 119 insertions(+), 65 deletions(-) diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 0e20e632..dce7cb77 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -62,17 +62,46 @@ class GuiPositionalStats (threading.Thread): self.filters.registerButton1Name("Refresh") self.filters.registerButton1Callback(self.refreshStats) + # ToDo: store in config + # ToDo: create popup to adjust column config + # columns to display, keys match column name returned by sql, values in tuple are: + # is column displayed, column heading, xalignment, formatting + self.columns = [ ["game", True, "Game", 0.0, "%s"] + , ["hand", False, "Hand", 0.0, "%s"] # true not allowed for this line + , ["plposition", False, "Posn", 1.0, "%s"] # true not allowed for this line (set in code) + , ["n", True, "Hds", 1.0, "%d"] + , ["avgseats", True, "Seats", 1.0, "%3.1f"] + , ["vpip", True, "VPIP", 1.0, "%3.1f"] + , ["pfr", True, "PFR", 1.0, "%3.1f"] + , ["pf3", True, "PF3", 1.0, "%3.1f"] + , ["steals", True, "Steals", 1.0, "%3.1f"] + , ["saw_f", True, "Saw_F", 1.0, "%3.1f"] + , ["sawsd", True, "SawSD", 1.0, "%3.1f"] + , ["wtsdwsf", True, "WtSDwsF", 1.0, "%3.1f"] + , ["wmsd", True, "W$SD", 1.0, "%3.1f"] + , ["flafq", True, "FlAFq", 1.0, "%3.1f"] + , ["tuafq", True, "TuAFq", 1.0, "%3.1f"] + , ["rvafq", True, "RvAFq", 1.0, "%3.1f"] + , ["pofafq", False, "PoFAFq", 1.0, "%3.1f"] + , ["net", True, "Net($)", 1.0, "%6.2f"] + , ["bbper100", True, "bb/100", 1.0, "%4.2f"] + , ["rake", True, "Rake($)", 1.0, "%6.2f"] + , ["bb100xr", True, "bbxr/100", 1.0, "%4.2f"] + , ["variance", True, "Variance", 1.0, "%5.2f"] + ] + self.stat_table = None self.stats_frame = None + self.stats_vbox = None self.main_hbox = gtk.HBox(False, 0) self.main_hbox.show() - statsFrame = gtk.Frame("Stats:") - statsFrame.set_label_align(0.0, 0.0) - statsFrame.show() - self.stats_frame = gtk.VBox(False, 0) + self.stats_frame = gtk.Frame() + self.stats_frame.set_label_align(0.0, 0.0) self.stats_frame.show() + self.stats_vbox = gtk.VBox(False, 0) + self.stats_vbox.show() # This could be stored in config eventually, or maybe configured in this window somehow. # Each posncols element is the name of a column returned by the sql @@ -90,11 +119,11 @@ class GuiPositionalStats (threading.Thread): , "PoFAFq", "Net($)", "bb/100", "$/hand", "Variance", "Hds" ) - self.fillStatsFrame(self.stats_frame) - statsFrame.add(self.stats_frame) + self.fillStatsFrame(self.stats_vbox) + self.stats_frame.add(self.stats_vbox) self.main_hbox.pack_start(self.filters.get_vbox()) - self.main_hbox.pack_start(statsFrame) + self.main_hbox.pack_start(self.stats_frame) def get_vbox(self): @@ -107,9 +136,12 @@ class GuiPositionalStats (threading.Thread): print "DEBUG: activesite set to %s" %(self.activesite) def refreshStats(self, widget, data): - try: self.stats_table.destroy() + try: self.stats_vbox.destroy() except AttributeError: pass - self.fillStatsFrame(self.stats_frame) + self.stats_vbox = gtk.VBox(False, 0) + self.stats_vbox.show() + self.stats_frame.add(self.stats_vbox) + self.fillStatsFrame(self.stats_vbox) def fillStatsFrame(self, vbox): sites = self.filters.getSites() @@ -144,66 +176,103 @@ class GuiPositionalStats (threading.Thread): self.createStatsTable(vbox, playerids, sitenos, limits, seats, dates) def createStatsTable(self, vbox, playerids, sitenos, limits, seats, dates): - self.stats_table = gtk.Table(1, 1, False) # gtk table expands as required - self.stats_table.set_col_spacings(4) - self.stats_table.show() - vbox.add(self.stats_table) + colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4 row = 0 col = 0 - for t in self.posnheads: - l = gtk.Label(self.posnheads[col]) - l.show() - self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) - col +=1 tmp = self.sql.query['playerStatsByPosition'] tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats, dates) self.cursor.execute(tmp) result = self.cursor.fetchall() + colnames = [desc[0].lower() for desc in self.cursor.description] + + liststore = gtk.ListStore(*([str] * len(colnames))) + view = gtk.TreeView(model=liststore) + view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) + vbox.pack_start(view, expand=False, padding=3) + # left-aligned cells: + textcell = gtk.CellRendererText() + # centred cells: + textcell50 = gtk.CellRendererText() + textcell50.set_property('xalign', 0.5) + # right-aligned cells: + numcell = gtk.CellRendererText() + numcell.set_property('xalign', 1.0) + listcols = [] + + for t in self.posnheads: + listcols.append(gtk.TreeViewColumn(self.posnheads[col])) + view.append_column(listcols[col]) + if col == 0: + listcols[col].pack_start(textcell, expand=True) + listcols[col].add_attribute(textcell, 'text', col) + listcols[col].set_expand(True) + elif col in (1, 2): + listcols[col].pack_start(textcell50, expand=True) + listcols[col].add_attribute(textcell50, 'text', col) + listcols[col].set_expand(True) + else: + listcols[col].pack_start(numcell, expand=True) + listcols[col].add_attribute(numcell, 'text', col) + listcols[col].set_expand(True) + col +=1 + + # Code below to be used when full column data structures implemented like in player stats: + + # Create header row eg column: ("game", True, "Game", 0.0, "%s") + #for col, column in enumerate(cols_to_show): + # if column[colalias] == 'game' and holecards: + # s = [x for x in self.columns if x[colalias] == 'hand'][0][colheading] + # else: + # s = column[colheading] + # listcols.append(gtk.TreeViewColumn(s)) + # view.append_column(listcols[col]) + # if column[colformat] == '%s': + # if column[colxalign] == 0.0: + # listcols[col].pack_start(textcell, expand=True) + # listcols[col].add_attribute(textcell, 'text', col) + # else: + # listcols[col].pack_start(textcell50, expand=True) + # listcols[col].add_attribute(textcell50, 'text', col) + # listcols[col].set_expand(True) + # else: + # listcols[col].pack_start(numcell, expand=True) + # listcols[col].add_attribute(numcell, 'text', col) + # listcols[col].set_expand(True) + # #listcols[col].set_alignment(column[colxalign]) # no effect? rows = len(result) - colnames = [desc[0].lower() for desc in self.cursor.description] last_game,last_seats,sqlrow = "","",0 while sqlrow < rows: - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" rowprinted=0 + treerow = [] avgcol = colnames.index('avgseats') for col,colname in enumerate(self.posncols): if colname in colnames: sqlcol = colnames.index(colname) else: continue - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) - # print blank row between levels: if result[sqlrow][sqlcol]: if sqlrow == 0: - l = gtk.Label(result[sqlrow][sqlcol]) + value = result[sqlrow][sqlcol] rowprinted=1 elif result[sqlrow][0] != last_game: - l = gtk.Label(' ') + value = ' ' elif 'show' in seats and seats['show'] and result[sqlrow][avgcol] != last_seats: - l = gtk.Label(' ') + value = ' ' else: - l = gtk.Label(result[sqlrow][sqlcol]) + value = result[sqlrow][sqlcol] rowprinted=1 else: l = gtk.Label(' ') - if col == 0: - l.set_alignment(xalign=0.0, yalign=0.5) - elif col == 1: - l.set_alignment(xalign=0.5, yalign=0.5) + value = ' ' + if value and value != -999: + treerow.append(value) else: - l.set_alignment(xalign=1.0, yalign=0.5) - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) - l.show() - eb.show() + treerow.append(' ') + iter = liststore.append(treerow) last_game = result[sqlrow][0] last_seats = result[sqlrow][avgcol] if rowprinted: @@ -220,48 +289,33 @@ class GuiPositionalStats (threading.Thread): # blank row between main stats and totals: col = 0 - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) - l = gtk.Label(' ') - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) - l.show() - eb.show() + treerow = [' ' for x in self.posncols] + iter = liststore.append(treerow) row = row + 1 for sqlrow in range(rows): - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" + treerow = [] for col,colname in enumerate(self.posncols): if colname in colnames: sqlcol = colnames.index(colname) elif colname != "plposition": continue - eb = gtk.EventBox() - eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) if colname == 'plposition': l = gtk.Label('Totals') + value = 'Totals' elif result[sqlrow][sqlcol]: l = gtk.Label(result[sqlrow][sqlcol]) + value = result[sqlrow][sqlcol] else: l = gtk.Label(' ') - if col == 0: - l.set_alignment(xalign=0.0, yalign=0.5) - elif col == 1: - l.set_alignment(xalign=0.5, yalign=0.5) + value = ' ' + if value and value != -999: + treerow.append(value) else: - l.set_alignment(xalign=1.0, yalign=0.5) - eb.add(l) - self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) - l.show() - eb.show() + treerow.append(' ') + iter = liststore.append(treerow) row = row + 1 + vbox.show_all() self.db.db.rollback() #end def fillStatsFrame(self, vbox): From 1fbb7d166c2ec32c2a02fbbeeb0f122df121ef22 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 21:41:41 +0100 Subject: [PATCH 2/7] remove redundant code --- pyfpdb/GuiPlayerStats.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 268aeab3..79ab75a4 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -227,11 +227,6 @@ class GuiPlayerStats (threading.Thread): if not flags: holecards = False else: holecards = flags[0] - - self.stats_table = gtk.Table(1, 1, False) - self.stats_table.set_col_spacings(4) - self.stats_table.show() - tmp = self.sql.query[query] tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, seats, groups, dates) self.cursor.execute(tmp) @@ -279,10 +274,6 @@ class GuiPlayerStats (threading.Thread): while sqlrow < rows: treerow = [] - if(row%2 == 0): - bgcolor = "white" - else: - bgcolor = "lightgrey" for col,column in enumerate(cols_to_show): if column[colalias] in colnames: value = result[sqlrow][colnames.index(column[colalias])] From 699f79722b99b073ce7fc27a5bfd8d83fda0dcf5 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 22:05:28 +0100 Subject: [PATCH 3/7] add time print for positional stats tab --- pyfpdb/GuiPositionalStats.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index dce7cb77..21a3bc9a 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -20,6 +20,7 @@ import pygtk pygtk.require('2.0') import gtk import os +from time import time, strftime import fpdb_import import fpdb_db @@ -177,6 +178,7 @@ class GuiPositionalStats (threading.Thread): def createStatsTable(self, vbox, playerids, sitenos, limits, seats, dates): + starttime = time() colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4 row = 0 col = 0 @@ -318,6 +320,7 @@ class GuiPositionalStats (threading.Thread): vbox.show_all() self.db.db.rollback() + print "Positional Stats page displayed in %4.2f seconds" % (time() - starttime) #end def fillStatsFrame(self, vbox): def refineQuery(self, query, playerids, sitenos, limits, seats, dates): From 45a9358cbd67a111ac42a056712fbc1995f9d000 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 23:16:34 +0100 Subject: [PATCH 4/7] set defaults for unused params to allow new calls without needing to set them --- pyfpdb/Database.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 932a8578..5bc8afe9 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -39,7 +39,7 @@ import SQL import Card class Database: - def __init__(self, c, db_name, game): + def __init__(self, c, db_name = None, game = None): # db_name and game not used any more self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.fdb.do_connect(c) self.connection = self.fdb.db @@ -48,7 +48,7 @@ class Database: self.import_options = c.get_import_parameters() self.type = db_params['db-type'] self.backend = db_params['db-backend'] - self.sql = SQL.Sql(game = game, type = self.type, db_server = db_params['db-server']) + self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server']) self.connection.rollback() # To add to config: From 456ddb3e91ceda9d9305d562a56769f38a9ddc23 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 23:19:03 +0100 Subject: [PATCH 5/7] use do_connect() instead of connect() and remove settings parameter (config includes them) --- pyfpdb/Filters.py | 20 ++++---------------- pyfpdb/GuiGraphViewer.py | 2 +- pyfpdb/GuiPlayerStats.py | 2 +- pyfpdb/GuiPositionalStats.py | 2 +- 4 files changed, 7 insertions(+), 19 deletions(-) diff --git a/pyfpdb/Filters.py b/pyfpdb/Filters.py index 4846b998..9ded56b4 100644 --- a/pyfpdb/Filters.py +++ b/pyfpdb/Filters.py @@ -30,12 +30,11 @@ import fpdb_db import FpdbSQLQueries class Filters(threading.Thread): - def __init__(self, db, settings, config, qdict, display = {},debug=True): + def __init__(self, db, config, qdict, display = {}, debug=True): self.debug=debug #print "start of GraphViewer constructor" self.db=db self.cursor=db.cursor - self.settings=settings self.sql=qdict self.conf = config self.display = display @@ -235,7 +234,7 @@ class Filters(threading.Thread): def __set_hero_name(self, w, site): self.heroes[site] = w.get_text() -# print "DEBUG: settings heroes[%s]: %s"%(site, self.heroes[site]) +# print "DEBUG: setting heroes[%s]: %s"%(site, self.heroes[site]) def createSiteLine(self, hbox, site): cb = gtk.CheckButton(site) @@ -556,23 +555,12 @@ def main(argv=None): config = Configuration.Config() db = None - settings = {} - - settings.update(config.get_db_parameters()) - settings.update(config.get_tv_parameters()) - settings.update(config.get_import_parameters()) - settings.update(config.get_default_paths()) - db = fpdb_db.fpdb_db() - db.connect(settings['db-backend'], - settings['db-host'], - settings['db-databaseName'], - settings['db-user'], - settings['db-password']) + db.do_connect(config) qdict = FpdbSQLQueries.FpdbSQLQueries(db.get_backend_name()) - i = Filters(db, settings, config, qdict) + i = Filters(db, config, qdict) main_window = gtk.Window() main_window.connect('destroy', destroy) main_window.add(i.get_vbox()) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index cec91e61..fc14a536 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -63,7 +63,7 @@ class GuiGraphViewer (threading.Thread): "Button2" : True } - self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display) + self.filters = Filters.Filters(db, config, querylist, display = filters_display) self.filters.registerButton1Name("Refresh Graph") self.filters.registerButton1Callback(self.generateGraph) self.filters.registerButton2Name("Export to File") diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 79ab75a4..4ad21764 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -66,7 +66,7 @@ class GuiPlayerStats (threading.Thread): "Button2" : True } - self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) + self.filters = Filters.Filters(self.db, config, querylist, display = filters_display) self.filters.registerButton1Name("_Filters") self.filters.registerButton1Callback(self.showDetailFilter) self.filters.registerButton2Name("_Refresh") diff --git a/pyfpdb/GuiPositionalStats.py b/pyfpdb/GuiPositionalStats.py index 21a3bc9a..6fde0617 100644 --- a/pyfpdb/GuiPositionalStats.py +++ b/pyfpdb/GuiPositionalStats.py @@ -59,7 +59,7 @@ class GuiPositionalStats (threading.Thread): "Button2" : False } - self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) + self.filters = Filters.Filters(self.db, config, querylist, display = filters_display) self.filters.registerButton1Name("Refresh") self.filters.registerButton1Callback(self.refreshStats) From 14561043828eed31639787a7751a3e54b28e79d2 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 23:30:54 +0100 Subject: [PATCH 6/7] make graph viewer use its own db connection --- pyfpdb/GuiGraphViewer.py | 16 ++++++++-------- pyfpdb/fpdb.py | 5 ++++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/pyfpdb/GuiGraphViewer.py b/pyfpdb/GuiGraphViewer.py index fc14a536..811b1e82 100644 --- a/pyfpdb/GuiGraphViewer.py +++ b/pyfpdb/GuiGraphViewer.py @@ -43,14 +43,14 @@ import Filters class GuiGraphViewer (threading.Thread): - def __init__(self, db, settings, querylist, config, debug=True): + def __init__(self, querylist, config, debug=True): """Constructor for GraphViewer""" self.debug=debug #print "start of GraphViewer constructor" - self.db=db - self.cursor=db.cursor - self.settings=settings - self.sql=querylist + self.db = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql + self.db.do_connect(config) + + self.sql = querylist self.conf = config filters_display = { "Heroes" : True, @@ -63,7 +63,7 @@ class GuiGraphViewer (threading.Thread): "Button2" : True } - self.filters = Filters.Filters(db, config, querylist, display = filters_display) + self.filters = Filters.Filters(self.db, config, querylist, display = filters_display) self.filters.registerButton1Name("Refresh Graph") self.filters.registerButton1Callback(self.generateGraph) self.filters.registerButton2Name("Export to File") @@ -146,7 +146,7 @@ class GuiGraphViewer (threading.Thread): for site in sites: if sites[site] == True: sitenos.append(siteids[site]) - self.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) + self.db.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) result = self.db.cursor.fetchall() if len(result) == 1: playerids.append(result[0][0]) @@ -226,7 +226,7 @@ class GuiGraphViewer (threading.Thread): #print "DEBUG: sql query:" #print tmp - self.cursor.execute(tmp) + self.db.cursor.execute(tmp) #returns (HandId,Winnings,Costs,Profit) winnings = self.db.cursor.fetchall() self.db.db.rollback() diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index b03e8424..172eedee 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -41,6 +41,7 @@ import GuiTableViewer import GuiAutoImport import GuiGraphViewer import GuiSessionViewer +import Database import FpdbSQLQueries import Configuration @@ -388,6 +389,8 @@ class fpdb: # Database connected to successfully, load queries to pass on to other classes self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) + self.dbi = Database.Database(self.config) # dbi for db interface and to avoid clashes with db/database/etc + # can rename later if required self.db.db.rollback() #end def load_profile @@ -474,7 +477,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") def tabGraphViewer(self, widget, data=None): """opens a graph viewer tab""" #print "start of tabGraphViewer" - new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config) + new_gv_thread = GuiGraphViewer.GuiGraphViewer(self.querydict, self.config) self.threads.append(new_gv_thread) gv_tab=new_gv_thread.get_vbox() self.add_and_display_tab(gv_tab, "Graphs") From 0afd8e2e707dba139d879242564604f48bbcb26d Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Mon, 22 Jun 2009 23:43:11 +0100 Subject: [PATCH 7/7] use do_connect() instead of connect() --- pyfpdb/fpdb.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 172eedee..b36c62bb 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -364,11 +364,7 @@ class fpdb: self.db = fpdb_db.fpdb_db() #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] - self.db.connect(self.settings['db-backend'], - self.settings['db-host'], - self.settings['db-databaseName'], - self.settings['db-user'], - self.settings['db-password']) + self.db.do_connect(self.config) if self.db.wrongDbVersion: diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) @@ -401,11 +397,7 @@ class fpdb: def obtain_global_lock(self): print "\nTaking global lock ..." self.fdb_lock = fpdb_db.fpdb_db() - self.fdb_lock.connect(self.settings['db-backend'], - self.settings['db-host'], - self.settings['db-databaseName'], - self.settings['db-user'], - self.settings['db-password']) + self.fdb_lock.do_connect(self.config) return self.fdb_lock.get_global_lock() #end def obtain_global_lock