Attached please find a patch against trunk (which is also a r4971 on the
locale-server-side branch) which implements proper handling of the
locale field in the users database.

The way it will now work is the locale setting in the database for the
user is used until a PACKET_POKER_SET_LOCALE is sent.  When one is sent,
it will always override the database version.

Unless someone objects here or on IRC, I plan to merge this trunk in 24
hours.

This patch is licensed AGPLv3-or-later.

diff --git a/poker-network/ChangeLog b/poker-network/ChangeLog
index a089d0f..8182288 100644
--- a/poker-network/ChangeLog
+++ b/poker-network/ChangeLog
@@ -1,3 +1,38 @@
+2008-11-23  Bradley M. Kuhn  <[EMAIL PROTECTED]>
+
+	* tests/test-pokeravatar.py.in
+	(PokerAvatarTestCase.forceDbToLocaleValue): Wrote function.
+
+2008-11-22  Bradley M. Kuhn  <[EMAIL PROTECTED]>
+
+	* tests/test-pokeravatar.py
+	(PokerAvatarTestCase.test15a_handPlay_dbLocalesAndOverridesThereof):
+	Wrote test.
+
+	* tests/test-pokeravatar.py.in
+	(PokerAvatarNoClientServerTestCase): Created test class.
+	(PokerAvatarNoClientServerTestCase.setUp): Wrote method.
+	(PokerAvatarNoClientServerTestCase.test01_reloginCoverage): Wrote
+	test.
+	(PokerAvatarNoClientServerTestCase.test02_relogin_localeAlreadySet):
+	Wrote test.
+
+	* pokernetwork/pokeravatar.py (PokerAvatar.setLocale): Make sure
+	locale is not None before looking up translation function.
+	(PokerAvatar._setDefaultLocale): Wrote method.
+	(PokerAvatar.relogin): Added call to _setDefaultLocale().
+	(PokerAvatar.login): Added call to _setDefaultLocale().
+
+	* tests/test-pokerservice.py.in
+	(PokerServiceCoverageTests.test21_getPlayerInfo_validReturns):
+	Wrote test.
+
+	* database/schema.sql.in: Switched locale default from "en" to
+	"en_US.UTF-8".
+
+	* pokernetwork/pokerservice.py (PokerService.getPlayerInfo): Added
+	locale to include the lookup.
+
 2008-11-20  Loic Dachary <[EMAIL PROTECTED]>
 
 	* Release 1.0.17
diff --git a/poker-network/database/schema.sql.in b/poker-network/database/schema.sql.in
index 6e944d1..558e8c6 100644
--- a/poker-network/database/schema.sql.in
+++ b/poker-network/database/schema.sql.in
@@ -60,7 +60,7 @@ CREATE TABLE users (
   -- 1 is a regular player, 0 is an observer and cannot play, 2 is admin
   privilege INT DEFAULT 1,
   -- locale
-  locale VARCHAR(32) DEFAULT "en",
+  locale VARCHAR(32) DEFAULT "en_US.UTF-8",
 
   rating INT DEFAULT 1000,
   future_rating FLOAT DEFAULT 1000,
diff --git a/poker-network/pokernetwork/pokeravatar.py b/poker-network/pokernetwork/pokeravatar.py
index ee321e9..6c9bdad 100644
--- a/poker-network/pokernetwork/pokeravatar.py
+++ b/poker-network/pokernetwork/pokeravatar.py
@@ -78,8 +78,20 @@ class PokerAvatar:
             self.explain = None
         return True
 
+    def _setDefaultLocale(self, locale):
+        """Set self.localFunc using locale iff. it is not already set.
+        Typically, this method is only used for a locale found for the
+        user in the database.  If the client sends a
+        PacketPokerSetLocale(), that will always take precedent and should
+        not use this method, but self.setLocale() instead."""
+        if not self.localeFunc:
+            return self.setLocale(locale)
+        else:
+            return None
+            
     def setLocale(self, locale):
-        self.localeFunc = self.service.locale2translationFunc(locale)
+        if locale:
+            self.localeFunc = self.service.locale2translationFunc(locale)
         return self.localeFunc
 
     def setProtocol(self, protocol):
@@ -104,6 +116,8 @@ class PokerAvatar:
         self.user.privilege = User.REGULAR
         self.user.url = player_info.url
         self.user.outfit = player_info.outfit
+        self._setDefaultLocale(player_info.locale)
+
         if self.explain:
             self.explain.handleSerial(PacketSerial(serial = serial))
         assert self.service.serial2client.has_key(serial) == False
@@ -120,7 +134,8 @@ class PokerAvatar:
         player_info = self.service.getPlayerInfo(serial)
         self.user.url = player_info.url
         self.user.outfit = player_info.outfit
-        
+        self._setDefaultLocale(player_info.locale)
+
         self.sendPacketVerbose(PacketSerial(serial = self.user.serial))
         if PacketPokerRoles.PLAY in self.roles:
             self.service.serial2client[serial] = self
diff --git a/poker-network/pokernetwork/pokerservice.py b/poker-network/pokernetwork/pokerservice.py
index 588b71e..c2a6a87 100644
--- a/poker-network/pokernetwork/pokerservice.py
+++ b/poker-network/pokernetwork/pokerservice.py
@@ -445,6 +445,7 @@ class PokerService(service.Service):
             )
     
     def createAvatar(self):
+        #FIXME BKUHN
         avatar = pokeravatar.PokerAvatar(self)
         self.avatars.append(avatar)
         return avatar
@@ -1491,19 +1492,25 @@ class PokerService(service.Service):
             return placeholder
 
         cursor = self.db.cursor()
-        sql = ( "select name,skin_url,skin_outfit from users where serial = " + str(serial) )
+        sql = ( "select locale,name,skin_url,skin_outfit from users where serial = " + str(serial) )
         cursor.execute(sql)
         if cursor.rowcount != 1:
             self.error("getPlayerInfo(%d) expected one row got %d" % ( serial, cursor.rowcount ))
             return placeholder
-        (name,skin_url,skin_outfit) = cursor.fetchone()
+        (locale,name,skin_url,skin_outfit) = cursor.fetchone()
         if skin_outfit == None:
             skin_outfit = "random"
         cursor.close()
-        return PacketPokerPlayerInfo(serial = serial,
+        pack = PacketPokerPlayerInfo(serial = serial,
                                      name = name,
                                      url = skin_url,
                                      outfit = skin_outfit)
+        # pokerservice generally provides playerInfo() internally to
+        # methods like pokeravatar.(re)?login.  Since this is the central
+        # internal location where the query occurs, we hack in the locale
+        # returned from the DB.
+        pack.locale = locale
+        return pack
 
     def getPlayerPlaces(self, serial):
         cursor = self.db.cursor()
diff --git a/poker-network/tests/test-pokeravatar.py.in b/poker-network/tests/test-pokeravatar.py.in
index dd6a241..fa8f430 100644
--- a/poker-network/tests/test-pokeravatar.py.in
+++ b/poker-network/tests/test-pokeravatar.py.in
@@ -34,6 +34,7 @@ from twisted.trial import unittest, runner, reporter
 import twisted.internet.base
 from twisted.internet import reactor, defer, error, base
 from twisted.python import failure, runtime
+from twisted.python.runtime import seconds
 
 from pokerengine import pokertournament
 #
@@ -856,8 +857,8 @@ class PokerAvatarTestCase(unittest.TestCase):
                     self.assertEquals(packet.game_id, gameId)
                     self.assertEquals(packet.serial, 0)
                     if (packet.message not in lang2strings[self.avatarLocales[avid]]):
-                        self.fail("Unexpected and/or Wrong Language message: %s" 
-                                  % packet.message)
+                        self.fail("Unexpected and/or Wrong Language (expected %s) message: %s for avatar %d" 
+                                  % (self.avatarLocales[avid], packet.message, avid))
                 elif packet.type == PACKET_POKER_STATE:
                     found += 1
                     self.assertEquals(packet.game_id, gameId)
@@ -968,6 +969,57 @@ class PokerAvatarTestCase(unittest.TestCase):
         avatar.noqueuePackets()
         client.sendPacket(PacketPokerExplain(value = PacketPokerExplain.ALL))
         return  d
+    # ------------------------------------------------------------------------
+    def forceDbToLocaleValue(self, (client, packet), avid = 0, setTo = '', expect = '', updateCount = 0):
+        from pokernetwork.pokerauth import get_auth_instance
+        auth = get_auth_instance(self.service.db, self.service.settings)
+
+        avatar = self.service.avatars[avid]
+        self.avatarLocales[avid] = expect
+
+        cursor = self.service.db.cursor()
+        cursor.execute("insert into users(created, name, password, locale) values(%d, 'user%d', '%s', '%s')"
+                       % (seconds(), avid, 'password1', setTo))
+        self.assertEquals(cursor.rowcount, 1)
+        cursor.close()
+        return (client, packet)
+    # ------------------------------------------------------------------------
+    def test15a_handPlay_dbLocalesAndOverridesThereof(self):
+        """Test playing an actual hand all the way through when locale changes"""
+
+        d = self.client_factory[0].established_deferred
+        d.addCallback(self.sendExplain)
+        d.addCallback(self.forceDbToLocaleValue, avid = 0, 
+                      setTo = 'fr_FR.UTF-8', expect = "RESET_BY_SET_LOCALE")
+        d.addCallback(self.sendRolePlay)
+        d.addCallback(self.login, 0)
+        d.addCallback(self.setLocale, "en_US.UTF-8")
+        d.addCallback(self.createRankDBTable, 2, rank = 50, percentile = 30)
+        d.addCallback(self.joinTable, 0, 2, 'Table2', '2-4-limit')
+        d.addCallback(self.seatTable, 0, 2, 50, 30)
+        d.addCallback(self.buyInTable, 0, 2, 1000)
+        d.addCallback(self.autoBlindAnte, 0, 2)
+        d.addCallback(self.sitTable, 0, 2)
+        d.addCallback(self.readyToPlay, 0, 2)
+        d2 = self.client_factory[1].established_deferred
+
+        d2.addCallback(self.sendExplain)
+        d2.addCallback(self.forceDbToLocaleValue, avid = 1, 
+                       setTo = 'fr_FR.UTF-8', expect = "fr_FR.UTF-8")
+        d2.addCallback(self.sendRolePlay)
+        d2.addCallback(self.login, 1)
+        d2.addCallback(self.joinTable, 1, 2, 'Table2', '2-4-limit',
+                       [{ 'rank' : 50, 'percentile' : 30, 'serial' : 4}] )
+        d2.addCallback(self.seatTable, 1, 2)
+        d2.addCallback(self.buyInTable, 1, 2, 1000)
+        # Note: this avatar does not autopost, and doBlindPost handles it.
+        d2.addCallback(self.sitTable, 1, 2)
+        d2.addCallback(self.readyToPlay, 1, 2)
+        d2.addCallback(self.dealTable, 2)
+        d2.addCallback(self.beginHandSetup, 2)
+        d2.addCallback(self.doBlindPost, 1, 2)
+        d2.addCallback(self.startHandAndReceiveCards, 2)
+        return defer.DeferredList((d, d2))
     # -------------------------------------------------------------------------
     def test16_explainTooLate(self):
         """This test covers the case where you attempt to turn on explain
@@ -3640,12 +3692,111 @@ class PokerAvatarTestCase(unittest.TestCase):
         d.addCallback(self.login, 0)
         d.addCallback(self.getStatsIgnored, 0, 1, 2)
         return d
+##############################################################################
+class PokerAvatarNoClientServerTestCase(unittest.TestCase):
+    class MockPlayerInfo:
+        def __init__(mpiSelf):
+            mpiSelf.url = "http://example.org/";
+            mpiSelf.outfit = "naked"
+            mpiSelf.locale = 'mylocale'
+            mpiSelf.name = 'Doyle Brunson'
+    class MockService:
+        def __init__(msSelf):
+            def transFunc(locale):
+                if locale == 'mylocale':
+                    return lambda s: "MYTRANSLATION"
+                else:
+                    return lambda s: "BROKEN FAIL"
+            msSelf.locale2translationFunc = transFunc
+            msSelf.serial2client = {}
+            
+        def getPlayerInfo(msSelf, serial):
+            return PokerAvatarNoClientServerTestCase.MockPlayerInfo()
+        def getPlayerPlaces(msSelf, serial):
+            class MockPlace:
+                def __init__(mpSelf): mpSelf.tourneys = "MOCKPLACES"
+            return MockPlace()
+
+    class MockExplain:
+        def __init__(meSelf): meSelf.handleSerialPackets = []
+        def handleSerial(meSelf, pack):
+            meSelf.handleSerialPackets.append(pack)
+    # ------------------------------------------------------
+    def setUp(self):
+        testclock._seconds_reset()        
+
+        self.avatarLocales = {}
+        self.avatarLocales[0] = "default"
+        self.avatarLocales[1] = "default"
     # ------------------------------------------------------------------------
+    def test01_reloginCoverage(self):
+        """No packet actualy does a relogin, this covers it 'by-hand', as
+        it were."""
+        from pokernetwork import pokeravatar
+
+        service = PokerAvatarNoClientServerTestCase.MockService()
+        avatar = pokeravatar.PokerAvatar(service)
+        explain = PokerAvatarNoClientServerTestCase.MockExplain()
+        saveExplain = avatar.explain
+        avatar.explain = explain
+
+        avatar.localeFunc = lambda s: "DONOTOVERRIDE"
+
+        avatar.relogin(1042)
+        self.assertEquals(avatar.user.serial, 1042)
+        self.assertEquals(avatar.user.name, 'Doyle Brunson')
+        self.assertEquals(avatar.user.url, "http://example.org/";)
+        self.assertEquals(avatar.user.outfit, "naked")
+        self.assertEquals(avatar.user.privilege, pokeravatar.User.REGULAR)
+        self.assertEquals(avatar.tourneys, "MOCKPLACES")
+
+        self.failUnless(service.serial2client.keys(), [1042])
+        self.assertEquals(service.serial2client[1042], avatar)
+
+        avatar.explain = saveExplain
+
+        self.assertEquals(len(explain.handleSerialPackets), 1)
+        self.assertEquals(explain.handleSerialPackets[0].serial, 1042)
+        self.assertEquals(explain.handleSerialPackets[0].type, PACKET_SERIAL)
+
+        self.assertEquals(avatar.localeFunc("DUMMY"),  "DONOTOVERRIDE")
+    # ------------------------------------------------------------------------
+    def test02_relogin_localeAlreadySet(self):
+        """No packet actualy does a relogin, this covers it 'by-hand', as
+        it were."""
+        from pokernetwork import pokeravatar
+
+        service = PokerAvatarNoClientServerTestCase.MockService()
+        avatar = pokeravatar.PokerAvatar(service)
+        explain = PokerAvatarNoClientServerTestCase.MockExplain()
+        saveExplain = avatar.explain
+        avatar.explain = explain
+
+        avatar.relogin(1042)
+        self.assertEquals(avatar.user.serial, 1042)
+        self.assertEquals(avatar.user.name, 'Doyle Brunson')
+        self.assertEquals(avatar.user.url, "http://example.org/";)
+        self.assertEquals(avatar.user.outfit, "naked")
+        self.assertEquals(avatar.user.privilege, pokeravatar.User.REGULAR)
+        self.assertEquals(avatar.tourneys, "MOCKPLACES")
+
+        self.failUnless(service.serial2client.keys(), [1042])
+        self.assertEquals(service.serial2client[1042], avatar)
+
+        avatar.explain = saveExplain
+
+        self.assertEquals(len(explain.handleSerialPackets), 1)
+        self.assertEquals(explain.handleSerialPackets[0].serial, 1042)
+        self.assertEquals(explain.handleSerialPackets[0].type, PACKET_SERIAL)
+
+        self.assertEquals(avatar.localeFunc("DUMMY"), "MYTRANSLATION")
+##############################################################################
 def Run():
     loader = runner.TestLoader()
-#    loader.methodPrefix = "test35"
+#    loader.methodPrefix = "test15a"
     suite = loader.suiteFactory()
     suite.addTest(loader.loadClass(PokerAvatarTestCase))
+    suite.addTest(loader.loadClass(PokerAvatarNoClientServerTestCase))
     return runner.TrialRunner(
         reporter.VerboseTextReporter,
 #                              tracebackFormat='verbose',
diff --git a/poker-network/tests/test-pokerservice.py.in b/poker-network/tests/test-pokerservice.py.in
index dd5cae3..c37f3d4 100644
--- a/poker-network/tests/test-pokerservice.py.in
+++ b/poker-network/tests/test-pokerservice.py.in
@@ -2199,6 +2199,65 @@ class UpdatePlayerRakeTestCase(PokerServiceTestCaseBase):
         self.assertEqual(15, row['points'])
         cursor.close()
 
+##############################################################################        
+class PokerServiceCoverageTests(unittest.TestCase):
+    # ----------------------------------------------------------------
+    def setUp(self):
+        testclock._seconds_reset()        
+        self.settings = pokernetworkconfig.Config([])
+        self.settings.doc = libxml2.parseMemory(settings_xml, len(settings_xml))
+        self.settings.header = self.settings.doc.xpathNewContext()
+    # ----------------------------------------------------------------
+    def tearDown(self):
+        if hasattr(self, 'service'):
+            d = self.service.stopService()
+            return d
+    # ----------------------------------------------------------------
+    def test21_getPlayerInfo_validReturns(self):
+        class MockCursor:
+            def __init__(cursorSelf):
+                cursorSelf.rowcount = 0
+                cursorSelf.counts = {}
+                cursorSelf.acceptedStatements = [ "select locale,name,skin_url,skin_outfit"]
+                cursorSelf.row = ()
+                for cntType in cursorSelf.acceptedStatements:
+                    cursorSelf.counts[cntType] = 0 
+            def close(cursorSelf): pass
+            def execute(*args):
+                cursorSelf = args[0]
+                sql = args[1]
+                found = False
+                for str in cursorSelf.acceptedStatements:
+                    if sql[:len(str)] == str:
+                        cursorSelf.counts[str] += 1
+                        cursorSelf.rowcount = 0
+                        found = True
+                        break
+                cursorSelf.rowcount = 1
+                cursorSelf.row = ('ourlocal','ourname','ourskinurl',None)
+                self.failUnless(found)
+                return cursorSelf.rowcount
+            def fetchone(cursorSelf): return cursorSelf.row
+        class MockDatabase:
+            def __init__(dbSelf):
+                class MockInternalDatabase:
+                    def literal(intDBSelf, *args): return args[0]
+                dbSelf.db = MockInternalDatabase()
+                dbSelf.cursorValue = MockCursor()
+            def cursor(dbSelf): return dbSelf.cursorValue
+
+        self.service = pokerservice.PokerService(self.settings)
+
+        oldDb = self.service.db
+        self.service.db = MockDatabase()
+
+        pack = self.service.getPlayerInfo(5)
+        self.assertEquals(pack.locale, 'ourlocal')
+        self.assertEquals(pack.name, 'ourname')
+        self.assertEquals(pack.url, 'ourskinurl')
+        self.assertEquals(pack.outfit, 'random')
+
+        self.service.db = oldDb
 # ----------------------------------------------------------------
 def Run():
     loader = runner.TestLoader()
@@ -2223,6 +2282,7 @@ def Run():
     suite.addTest(loader.loadClass(PlayerPlacesTestCase))
     suite.addTest(loader.loadClass(CleanUpTestCase))
     suite.addTest(loader.loadClass(ResthostTestCase))
+    suite.addTest(loader.loadClass(PokerServiceCoverageTests))
     return runner.TrialRunner(
         reporter.VerboseTextReporter,
 #       reporter.TextReporter,
-- 

   -- bkuhn
_______________________________________________
Pokersource-users mailing list
[email protected]
https://mail.gna.org/listinfo/pokersource-users

Reply via email to