Merge branch 'master' of git://git.assembla.com/fpdb-eric
This commit is contained in:
		
						commit
						3cc5ed8024
					
				|  | @ -24,25 +24,37 @@ def twoStartCards(value1, suit1, value2, suit2): | |||
|         (y+2) represents rank of second card (2=2 .. 14=Ace) | ||||
|         If x > y then pair is suited, if x < y then unsuited""" | ||||
|     if value1 < 2 or value2 < 2: | ||||
|         return(0) | ||||
|     if (suit1 == suit2 and value1 < value2) or (suit1 != suit2 and value2 > value1): | ||||
|         return(13 * (value2-2) + (value1-1)) | ||||
|         ret = 0 | ||||
|     if value1 == value2: # pairs | ||||
|         ret = (13 * (value2-2) + (value2-1) ) | ||||
|     elif suit1 == suit2: | ||||
|         if value1 > value2: | ||||
|             ret = 13 * (value1-2) + (value2-1) | ||||
|         else: | ||||
|         return(13 * (value1-2) + (value2-1)) | ||||
|             ret = 13 * (value2-2) + (value1-1) | ||||
|     else: | ||||
|         if value1 > value2: | ||||
|             ret = 13 * (value2-2) + (value2-1) | ||||
|         else: | ||||
|             ret = 13 * (value1-2) + (value2-1) | ||||
|              | ||||
| #    print "twoStartCards(", value1, suit1, value2, suit2, ")=", ret | ||||
|     return ret | ||||
| 
 | ||||
| def twoStartCardString(card): | ||||
|     """ Function to convert an int representing 2 holdem hole cards (as created by twoStartCards) | ||||
|         into a string like AQo """ | ||||
|     if card <= 0: | ||||
|         return 'xx' | ||||
|     else: | ||||
|     ret = 'xx' | ||||
|     if card > 0: | ||||
|         card -= 1 | ||||
|         s = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A') | ||||
|         x = card / 13 | ||||
|         y = card - 13 * x | ||||
|         if x == y:  return(s[x] + s[y]) | ||||
|         elif x > y: return(s[x] + s[y] + 's') | ||||
|         else:       return(s[y] + s[x] + 'o') | ||||
|         if x == y:  ret = s[x] + s[y] | ||||
|         elif x > y: ret = s[x] + s[y] + 's' | ||||
|         else:       ret = s[y] + s[x] + 'o' | ||||
| #    print "twoStartCardString(", card ,") = " + ret | ||||
|     return ret | ||||
| 
 | ||||
| def fourStartCards(value1, suit1, value2, suit2, value3, suit3, value4, suit4): | ||||
|     """ Function to convert 4 value,suit pairs into a Omaha style starting hand, | ||||
|  | @ -95,4 +107,7 @@ def valueSuitFromCard(card): | |||
|                 ][card] ) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     for i in xrange(1, 14): | ||||
|         print "card %2d = %s    card %2d = %s    card %2d = %s    card %2d = %s" % \ | ||||
|             (i, valueSuitFromCard(i), i+13, valueSuitFromCard(i+13), i+26, valueSuitFromCard(i+26), i+39, valueSuitFromCard(i+39)) | ||||
|  |  | |||
|  | @ -237,11 +237,14 @@ or None if we fail to get the info """ | |||
|             # Also works with Omaha hands. | ||||
|             cards = m.group('CARDS') | ||||
|             cards = [card.strip() for card in cards.split(',')] | ||||
|             hand.addHoleCards(cards, m.group('PNAME')) | ||||
| #            hand.addHoleCards(cards, m.group('PNAME')) | ||||
|             hand.addHoleCards('PREFLOP', hand.hero, closed=cards, shown=False, mucked=False, dealt=True) | ||||
| 
 | ||||
|         else: | ||||
|             #Not involved in hand | ||||
|             hand.involved = False | ||||
| 
 | ||||
| 
 | ||||
|     def readStudPlayerCards(self, hand, street): | ||||
|         # lol. see Plymouth.txt | ||||
|         logging.warning("Everleaf readStudPlayerCards is only a stub.") | ||||
|  | @ -292,7 +295,8 @@ or None if we fail to get the info """ | |||
|                 cards = cards.split(', ') | ||||
|                 player = m.group('PNAME') | ||||
|                 logging.debug("readShownCards %s cards=%s" % (player, cards)) | ||||
|                 hand.addShownCards(cards=None, player=m.group('PNAME'), holeandboard=cards) | ||||
| #                hand.addShownCards(cards=None, player=m.group('PNAME'), holeandboard=cards) | ||||
|                 hand.addShownCards(cards=cards, player=m.group('PNAME')) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -33,25 +33,33 @@ class Fulltilt(HandHistoryConverter): | |||
|                                     -\s(?P<CURRENCY>\$|)? | ||||
|                                     (?P<SB>[.0-9]+)/ | ||||
|                                     \$?(?P<BB>[.0-9]+)\s | ||||
|                                     (Ante\s\$(?P<ANTE>[.0-9]+)\s)?-\s | ||||
|                                     (Ante\s\$?(?P<ANTE>[.0-9]+)\s)?-\s | ||||
|                                     (?P<LIMIT>(No\sLimit|Pot\sLimit|Limit))?\s | ||||
|                                     (?P<GAME>(Hold\'em|Omaha\sHi|Omaha\sH/L|7\sCard\sStud|Stud\sH/L|Razz)) | ||||
|                                     (?P<GAME>(Hold\'em|Omaha\sHi|Omaha\sH/L|7\sCard\sStud|Stud\sH/L|Razz|Stud\sHi)) | ||||
|                                  ''', re.VERBOSE) | ||||
|     re_SplitHands   = re.compile(r"\n\n+") | ||||
|     re_TailSplitHands   = re.compile(r"(\n\n+)") | ||||
|     re_HandInfo     = re.compile('''.*\#(?P<HID>[0-9]+):\s | ||||
|                                     (?:(?P<TOURNAMENT>.+)\s\((?P<TOURNO>\d+)\),\s)? | ||||
|                                     Table\s(?P<TABLE>[-\s\da-zA-Z]+)\s | ||||
|                                     Table\s | ||||
|                                     (?P<PLAY>Play\sChip\s|PC)? | ||||
|                                     (?P<TABLE>[-\s\da-zA-Z]+)\s | ||||
|                                     (\((?P<TABLEATTRIBUTES>.+)\)\s)?-\s | ||||
|                                     \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\s(Ante\s\$(?P<ANTE>[.0-9]+)\s)?-\s | ||||
|                                     \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\s(Ante\s\$?(?P<ANTE>[.0-9]+)\s)?-\s | ||||
|                                     (?P<GAMETYPE>[a-zA-Z\/\'\s]+)\s-\s | ||||
|                                     (?P<DATETIME>.*) | ||||
|                                  ''', 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>.*) \(\$?(?P<CASH>[,.0-9]+)\)$', re.MULTILINE) | ||||
|     re_Board        = re.compile(r"\[(?P<CARDS>.+)\]") | ||||
| 
 | ||||
| # These regexes are for FTP only | ||||
|     re_Mixed        = re.compile(r'\s\-\s(?P<MIXED>HA|HORSE|HOSE)\s\-\s', re.VERBOSE) | ||||
|     re_Max          = re.compile("(?P<MAX>\d+)( max)?", re.MULTILINE) | ||||
|     # NB: if we ever match "Full Tilt Poker" we should also match "FullTiltPoker", which PT Stud erroneously exports. | ||||
| 
 | ||||
|     mixes = { 'HORSE': 'horse', '7-Game': '7game', 'HOSE': 'hose', 'HA': 'ha'} | ||||
| 
 | ||||
|     def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True, index=0): | ||||
|         """\ | ||||
| in_path   (default '-' = sys.stdin) | ||||
|  | @ -109,7 +117,6 @@ follow :  whether to tail -f the input""" | |||
|         m = self.re_GameInfo.search(handText) | ||||
|         if not m:  | ||||
|             return None | ||||
| 
 | ||||
|         mg = m.groupdict() | ||||
|          | ||||
|         # translations from captured groups to our info strings | ||||
|  | @ -119,7 +126,7 @@ follow :  whether to tail -f the input""" | |||
|                  'Omaha Hi' : ('hold','omahahi'),  | ||||
|                 'Omaha H/L' : ('hold','omahahilo'), | ||||
|                      'Razz' : ('stud','razz'),  | ||||
|               '7 Card Stud' : ('stud','studhi'),  | ||||
|                   'Stud Hi' : ('stud','studhi'),  | ||||
|                  'Stud H/L' : ('stud','studhilo') | ||||
|                } | ||||
|         currencies = { u' €':'EUR', '$':'USD', '':'T$' } | ||||
|  | @ -137,7 +144,6 @@ follow :  whether to tail -f the input""" | |||
| 
 | ||||
|     def readHandInfo(self, hand): | ||||
|         m =  self.re_HandInfo.search(hand.handText,re.DOTALL) | ||||
| 
 | ||||
|         if(m == None): | ||||
|             logging.info("Didn't match re_HandInfo") | ||||
|             logging.info(hand.handText) | ||||
|  | @ -146,12 +152,12 @@ follow :  whether to tail -f the input""" | |||
|         hand.tablename = m.group('TABLE') | ||||
|         hand.starttime = datetime.datetime.strptime(m.group('DATETIME'), "%H:%M:%S ET - %Y/%m/%d") | ||||
|         if m.group('TABLEATTRIBUTES'): | ||||
|             m2 = re.search("(deep )?(\d+)( max)?", m.group('TABLEATTRIBUTES')) | ||||
|             hand.maxseats = int(m2.group(2)) | ||||
|             m2 = self.re_Max.search(m.group('TABLEATTRIBUTES')) | ||||
|             if m2: hand.maxseats = int(m2.group('MAX')) | ||||
| 
 | ||||
|         hand.tourNo = m.group('TOURNO') | ||||
| #        if key == 'PLAY' and info['PLAY'] != None: | ||||
| #            hand.gametype['currency'] = 'play' | ||||
|         if m.group('PLAY') != None: | ||||
|             hand.gametype['currency'] = 'play' | ||||
| 
 | ||||
| # These work, but the info is already in the Hand class - should be used for tourneys though. | ||||
| #       m.group('SB') | ||||
|  | @ -214,6 +220,7 @@ follow :  whether to tail -f the input""" | |||
|         m = self.re_Antes.finditer(hand.handText) | ||||
|         for player in m: | ||||
|             logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE'))) | ||||
| #            if player.group() !=  | ||||
|             hand.addAnte(player.group('PNAME'), player.group('ANTE')) | ||||
| 
 | ||||
|     def readBringIn(self, hand): | ||||
|  | @ -222,7 +229,7 @@ follow :  whether to tail -f the input""" | |||
|             logging.debug("Player bringing in: %s for %s" %(m.group('PNAME'),  m.group('BRINGIN'))) | ||||
|             hand.addBringIn(m.group('PNAME'),  m.group('BRINGIN')) | ||||
|         else: | ||||
|             logging.warning("No bringin found") | ||||
|             logging.warning("No bringin found, handid =%s" % hand.handid) | ||||
| 
 | ||||
|     def readButton(self, hand): | ||||
|         hand.buttonpos = int(self.re_Button.search(hand.handText).group('BUTTON')) | ||||
|  | @ -255,10 +262,10 @@ follow :  whether to tail -f the input""" | |||
|                 else: | ||||
|                     oldcards = found.group('OLDCARDS').split(' ') | ||||
| 
 | ||||
|                 if street == 'THIRD' and len(newcards) == 3: # hero in stud game | ||||
|                 if street == 'THIRD' and len(oldcards) == 2: # hero in stud game | ||||
|                     hand.hero = player | ||||
|                     hand.dealt.add(player) # need this for stud?? | ||||
|                     hand.addHoleCards(street, player, closed=newcards[0:2], open=[newcards[2]], shown=False, mucked=False, dealt=False) | ||||
|                     hand.addHoleCards(street, player, closed=oldcards, open=newcards, shown=False, mucked=False, dealt=False) | ||||
|                 else: | ||||
|                     hand.addHoleCards(street, player, open=newcards, closed=oldcards, shown=False, mucked=False, dealt=False) | ||||
| 
 | ||||
|  | @ -317,6 +324,11 @@ follow :  whether to tail -f the input""" | |||
|         if mo <= 6: return 6 | ||||
|         return 9 | ||||
| 
 | ||||
|     def readOther(self, hand): | ||||
|         m = self.re_Mixed.search(self.in_path) | ||||
|         if m == None: hand.mixed = None | ||||
|         else: | ||||
|             hand.mixed = self.mixes[m.groupdict()['MIXED']] | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     parser = OptionParser() | ||||
|  |  | |||
|  | @ -262,7 +262,8 @@ def main(argv=None): | |||
|     else: | ||||
|         #Do something useful | ||||
|         importer = fpdb_import.Importer(False,settings, config)  | ||||
|         importer.setDropIndexes("auto") | ||||
|         # importer.setDropIndexes("auto") | ||||
|         importer.setDropIndexes("don't drop") | ||||
|         importer.setFailOnError(options.failOnError) | ||||
|         importer.addBulkImportImportFileOrDir(os.path.expanduser(options.filename), site=options.filtername) | ||||
|         importer.setCallHud(False) | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ class Hand(object): | |||
|     UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'} | ||||
|     LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} | ||||
|     SYMBOL = {'USD': '$', 'EUR': u'$', 'T$': '', 'play': ''} | ||||
|     MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose'  : 'HOSE'} | ||||
|     MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose'  : 'HOSE', 'ha': 'HA'} | ||||
| 
 | ||||
| 
 | ||||
|     def __init__(self, sitename, gametype, handText, builtFrom = "HHC"): | ||||
|  | @ -583,7 +583,7 @@ Map the tuple self.gametype onto the pokerstars string describing it | |||
|         table_string = "Table \'%s\' %s-max" % (self.tablename, self.maxseats) | ||||
|         if self.gametype['currency'] == 'play': | ||||
|             table_string = table_string + " (Play Money)" | ||||
|         if self.buttonpos != None: | ||||
|         if self.buttonpos != None and self.buttonpos != 0: | ||||
|             table_string = table_string + " Seat #%s is the button" % self.buttonpos | ||||
|         return table_string | ||||
| 
 | ||||
|  | @ -632,6 +632,7 @@ class HoldemOmahaHand(Hand): | |||
|             hhc.getRake(self) | ||||
|             if self.maxseats == None: | ||||
|                 self.maxseats = hhc.guessMaxSeats(self) | ||||
|             hhc.readOther(self) | ||||
|         elif builtFrom == "DB": | ||||
|             if handid is not None: | ||||
|                 self.select(handid) # Will need a handId | ||||
|  | @ -877,6 +878,9 @@ class DrawHand(Hand): | |||
|             hhc.readShownCards(self) | ||||
|             self.totalPot() # finalise it (total the pot) | ||||
|             hhc.getRake(self) | ||||
|             if self.maxseats == None: | ||||
|                 self.maxseats = hhc.guessMaxSeats(self) | ||||
|             hhc.readOther(self) | ||||
|         elif builtFrom == "DB": | ||||
|             self.select("dummy") # Will need a handId | ||||
| 
 | ||||
|  | @ -1032,7 +1036,8 @@ class StudHand(Hand): | |||
|             hhc.readBringIn(self) | ||||
|             hhc.readHeroCards(self) | ||||
|             # Read actions in street order | ||||
|             for street in self.streetList: | ||||
|             for street in self.actionStreets: | ||||
|                 if street == 'ANTES': continue # OMG--sometime someone folds in the ante round | ||||
|                 if self.streets[street]: | ||||
|                     logging.debug(street) | ||||
|                     logging.debug(self.streets[street]) | ||||
|  | @ -1041,6 +1046,9 @@ class StudHand(Hand): | |||
|             hhc.readShownCards(self) # not done yet | ||||
|             self.totalPot() # finalise it (total the pot) | ||||
|             hhc.getRake(self) | ||||
|             if self.maxseats == None: | ||||
|                 self.maxseats = hhc.guessMaxSeats(self) | ||||
|             hhc.readOther(self) | ||||
|         elif builtFrom == "DB": | ||||
|             self.select("dummy") # Will need a handId | ||||
| 
 | ||||
|  | @ -1079,6 +1087,7 @@ closed    likewise, but known only to player | |||
| Add a complete on [street] by [player] to [amountTo] | ||||
| """ | ||||
|         logging.debug("%s %s completes %s" % (street, player, amountTo)) | ||||
|         amountTo = re.sub(u',', u'', amountTo) #some sites have commas | ||||
|         self.checkPlayerExists(player) | ||||
|         Bp = self.lastBet['THIRD'] | ||||
|         Bc = reduce(operator.add, self.bets[street][player], 0) | ||||
|  | @ -1314,31 +1323,19 @@ class Pot(object): | |||
|         # Total pot $124.30 Main pot $98.90. Side pot $23.40. | Rake $2 | ||||
|          | ||||
|     def __str__(self): | ||||
|         if self.sym is None: | ||||
|             self.sym = "C" | ||||
|         if self.total is None: | ||||
|             print "call Pot.end() before printing pot total" | ||||
|             # NB if I'm sure end() is idempotent, call it here. | ||||
|             raise FpdbParseError | ||||
|          | ||||
|         ret = "Total pot %s%.2f" % (self.sym, self.total) | ||||
|         if len(self.pots) < 2: | ||||
|             return ret; | ||||
|         ret += " Main pot %s%.2f" % (self.sym, self.pots[0]) | ||||
|          | ||||
| # TODO: This really neeads to be a loop to handle multiple side pots | ||||
|         if len(self.pots) == 1: # (only use Total pot) | ||||
|             return "Total pot %s%.2f" % (self.sym, self.total,) | ||||
|         elif len(self.pots) == 2: | ||||
|             return "Total pot %s%.2f Main pot %s%.2f. Side pot %s%2.f." % (self.sym, self.total, self.sym, self.pots[0], self.sym, self.pots[1]) | ||||
|         elif len(self.pots) == 3: | ||||
|             return "Total pot %s%.2f Main pot %s%.2f. Side pot-1 %s%2.2f. Side pot-2 %s%.2f." % (self.sym, self.total, self.sym, self.pots[0], self.sym, self.pots[1], self.sym, self.pots[2]) | ||||
|         elif len(self.pots) == 0: | ||||
|             # no small blind and walk in bb (hopefully) | ||||
|             return "Total pot %s%.2f" % (self.sym, self.total,) | ||||
|         else: | ||||
|             return ("too many pots.. no small blind and walk in bb?. self.pots: %s" %(self.pots)) | ||||
|             # I don't know stars format for a walk in the bb when sb doesn't post. | ||||
|             # The thing to do here is raise a Hand error like fpdb import does and file it into errors.txt | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         return ret + ''.join([ (" Side pot %s%.2f." % (self.sym, self.pots[x]) ) for x in xrange(1, len(self.pots)) ]) | ||||
| 
 | ||||
| def assemble(cnxn, handid): | ||||
|     c = cnxn.cursor() | ||||
|  |  | |||
|  | @ -270,6 +270,11 @@ or None if we fail to get the info """ | |||
|     def readCollectPot(self, hand): abstract | ||||
|     def readShownCards(self, hand): abstract | ||||
| 
 | ||||
|     # Some sites do odd stuff that doesn't fall in to the normal HH parsing. | ||||
|     # e.g., FTP doesn't put mixed game info in the HH, but puts in in the  | ||||
|     # file name. Use readOther() to clean up those messes. | ||||
|     def readOther(self, hand): pass | ||||
|      | ||||
|     # Some sites don't report the rake. This will be called at the end of the hand after the pot total has been calculated | ||||
|     # an inheriting class can calculate it for the specific site if need be. | ||||
|     def getRake(self, hand): | ||||
|  |  | |||
|  | @ -244,6 +244,24 @@ class fpdb: | |||
|             self.release_global_lock() | ||||
|     #end def dia_recreate_tables | ||||
|      | ||||
|     def dia_recreate_hudcache(self, widget, data=None): | ||||
|         if self.obtain_global_lock(): | ||||
|             try: | ||||
|                 dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm recreating HUD cache") | ||||
|                 diastring = "Please confirm that you want to re-create the HUD cache." | ||||
|                 dia_confirm.format_secondary_text(diastring) | ||||
|                  | ||||
|                 response = dia_confirm.run() | ||||
|                 dia_confirm.destroy() | ||||
|                 if response == gtk.RESPONSE_YES: | ||||
|                     self.db.rebuild_hudcache() | ||||
|                 elif response == gtk.REPSONSE_NO: | ||||
|                     print 'User cancelled rebuilding hud cache' | ||||
|             except: | ||||
|                 pass | ||||
|         self.release_global_lock() | ||||
|      | ||||
| 
 | ||||
|     def dia_regression_test(self, widget, data=None): | ||||
|         print "todo: implement dia_regression_test" | ||||
|         self.obtain_global_lock() | ||||
|  | @ -306,6 +324,7 @@ class fpdb: | |||
|                   <menuitem action="createdb"/> | ||||
|                   <menuitem action="createuser"/> | ||||
|                   <menuitem action="createtabs"/> | ||||
|                   <menuitem action="rebuildhudcache"/> | ||||
|                   <menuitem action="stats"/> | ||||
|                   <menuitem action="sessions"/> | ||||
|                 </menu> | ||||
|  | @ -344,6 +363,7 @@ class fpdb: | |||
|                                  ('createdb', None, 'Create or Delete _Database (todo)', None, 'Create or Delete Database', self.dia_create_del_database), | ||||
|                                  ('createuser', None, 'Create or Delete _User (todo)', None, 'Create or Delete User', self.dia_create_del_user), | ||||
|                                  ('createtabs', None, 'Create or Recreate _Tables', None, 'Create or Recreate Tables ', self.dia_recreate_tables), | ||||
|                                  ('rebuildhudcache', None, 'Rebuild HUD Cache', None, 'Rebuild HUD Cache', self.dia_recreate_hudcache), | ||||
|                                  ('stats', None, '_Statistics (todo)', None, 'View Database Statistics', self.dia_database_stats), | ||||
|                                  ('sessions', None, 'Sessions', None, 'View Sessions', self.dia_database_sessions), | ||||
|                                  ('help', None, '_Help'), | ||||
|  |  | |||
|  | @ -361,6 +361,10 @@ class fpdb_db: | |||
|         """Drop some indexes/foreign keys to prepare for bulk import.  | ||||
|            Currently keeping the standalone indexes as needed to import quickly""" | ||||
|         stime = time() | ||||
|         if self.backend == self.MYSQL_INNODB: | ||||
|             self.cursor.execute("SET foreign_key_checks=0") | ||||
|             self.cursor.execute("SET autocommit=0") | ||||
|             return | ||||
|         if self.backend == self.PGSQL: | ||||
|             self.db.set_isolation_level(0)   # allow table/index operations to work | ||||
|         for fk in self.foreignKeys[self.backend]: | ||||
|  | @ -450,6 +454,12 @@ class fpdb_db: | |||
|     def afterBulkImport(self): | ||||
|         """Re-create any dropped indexes/foreign keys after bulk import""" | ||||
|         stime = time() | ||||
|          | ||||
|         if self.backend == self.MYSQL_INNODB: | ||||
|             self.cursor.execute("SET foreign_key_checks=1") | ||||
|             self.cursor.execute("SET autocommit=1") | ||||
|             return | ||||
| 
 | ||||
|         if self.backend == self.PGSQL: | ||||
|             self.db.set_isolation_level(0)   # allow table/index operations to work | ||||
|         for fk in self.foreignKeys[self.backend]: | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user