Fix unicode issue that made Python 3.3 fail. Continue dict cleanup
authorMichael Petch <mpetch@capp-sysware.com>
Tue, 31 Dec 2013 04:21:29 +0000 (21:21 -0700)
committerMichael Petch <mpetch@capp-sysware.com>
Tue, 31 Dec 2013 16:19:58 +0000 (09:19 -0700)
extractxgdata.py
xgstruct.py
xgutils.py

index dc2c987..003ae0e 100755 (executable)
@@ -90,17 +90,17 @@ if __name__ == '__main__':
                         if rec is None:
                             break
                         if isinstance(rec, xgstruct.HeaderMatchEntry):
-                            fileversion = rec.version
+                            fileversion = rec.Version
                         elif isinstance(rec, xgstruct.UnimplementedEntry):
                             continue
-                        pprint.pprint (rec.__dict__)
+                        pprint.pprint (rec,width=160)
                 elif segment.type == xgimport.Import.Segment.XG_ROLLOUTS:
                     segment.fd.seek(os.SEEK_SET, 0)
                     while True:
                         rec = xgstruct.RolloutFileRecord().fromstream(segment.fd)
                         if rec is None:
                             break
-                        pprint.pprint (rec.__dict__)
+                        pprint.pprint (rec.__dict__,width=160)
 
         except (xgimport.Error, xgzarc.Error) as e:
             print (e.value)
index 3615402..50be494 100755 (executable)
@@ -40,7 +40,7 @@ class TimeSettingRecord(dict):
             'Penalty': 0,
             'TimeLeft1': 0,
             'TimeLeft2': 0,
-            'PenaltyMoney': 0,            
+            'PenaltyMoney': 0            
             }
         super(TimeSettingRecord, self).__init__(defaults, **kw)
 
@@ -65,533 +65,459 @@ class TimeSettingRecord(dict):
         return self
 
 
-class EvalLevelRecord(object):
+class EvalLevelRecord(dict):
 
     SIZEOFREC = 4
 
-    def __init__(self):
-        pass
-        self.level = 0
-        self.isdouble = False
-        self.fill1 = 0
+    def __init__(self, **kw):
+        defaults = {
+            'Level': 0,
+            'isDouble': False
+            }
+        super(EvalLevelRecord, self).__init__(defaults, **kw)
 
-    def __str__(self):
-        return str(self.todict())
+    def __setattr__(self, key, value):
+        self[key] = value
 
-    def __repr__(self):
-        return str(self.todict())
+    def __getattr__(self, key):
+       return self[key]
 
     def fromstream(self, stream):
         unpacked_data = _struct.unpack(
             '<hBb',
             stream.read(self.SIZEOFREC))
-        self.level = unpacked_data[0]
-        self.isdouble = bool(unpacked_data[1])
-        self.fill1 = unpacked_data[2]
+        self.Level = unpacked_data[0]
+        self.isDouble = bool(unpacked_data[1])
 
         return self
 
-    def todict(self):
-        return {'level': self.level, 'isdouble': self.isdouble}
-
 
-class EngineStructBestMoveRecord(object):
+class EngineStructBestMoveRecord(dict):
 
     SIZEOFREC = 2184
 
-    def __init__(self):
-        self.pos = None
-        self.dice = None
-        self.level = 0
-        self.score = None
-        self.cube = 0
-        self.cubepos = 0
-        self.crawford = False
-        self.jacoby = False
-        self.nmoves = 0
-        self.posplayed = None
-        self.moves = None
-        self.evallevel = None
-        self.evallevel = None
-        self.eval = None
-        self.irrelevant = False
-        self.met = 0
-        self.choice0 = 0
-        self.choice3 = 0
+    def __init__(self, **kw):
+        defaults = {
+            'Pos': None,
+            'Dice': None,
+            'Level': 0,
+            'Score': None,
+            'Cube': 0,
+            'CubePos': 0,
+            'Crawford': 0,
+            'Jacoby': 0,
+            'Nmoves': 0,
+            'PosPlayed': None,
+            'Moves': None,
+            'EvalLevel': None,
+            'Eval': None,
+            'Unused': 0,
+            'met': 0,
+            'Choice0': 0,
+            'Choice3': 0
+            }
+        super(EngineStructBestMoveRecord, self).__init__(defaults, **kw)
 
-    def __str__(self):
-        return str(self.todict())
+    def __setattr__(self, key, value):
+        self[key] = value
 
-    def __repr__(self):
-        return str(self.todict())
+    def __getattr__(self, key):
+        return self[key]
 
     def fromstream(self, stream):
         unpacked_data = _struct.unpack(
                 '<26bxx2ll2llllll',
                 stream.read(68))
-        self.pos = unpacked_data[0:26]
-        self.dice = unpacked_data[26:28]
-        self.level = unpacked_data[28]
-        self.score = unpacked_data[29:31]
-        self.cube = unpacked_data[31]
-        self.cubepos = unpacked_data[32]
-        self.crawford = bool(unpacked_data[33])
-        self.jacoby = bool(unpacked_data[34])
-        self.nmoves = unpacked_data[35]
-
-        self.posplayed = ()
+        self.Pos = unpacked_data[0:26]
+        self.Dice = unpacked_data[26:28]
+        self.Level = unpacked_data[28]
+        self.Score = unpacked_data[29:31]
+        self.Cube = unpacked_data[31]
+        self.Cubepos = unpacked_data[32]
+        self.Crawford = unpacked_data[33]
+        self.Jacoby = unpacked_data[34]
+        self.Nmoves = unpacked_data[35]
+
+        self.PosPlayed = ()
         for row in range(32):
             unpacked_data = _struct.unpack('<26b', stream.read(26))
-            self.posplayed += (unpacked_data[0:26],)
+            self.PosPlayed += (unpacked_data[0:26],)
 
-        self.moves = ()
+        self.Moves = ()
         for row in range(32):
-            self.moves += (_struct.unpack('<8b', stream.read(8))[0:8],)
+            self.Moves += (_struct.unpack('<8b', stream.read(8))[0:8],)
 
-        self.evallevel = ()
+        self.EvalLevel = ()
         for row in range(32):
-            self.evallevel += (EvalLevelRecord().fromstream(stream),)
+            self.EvalLevel += (EvalLevelRecord().fromstream(stream),)
 
-        self.eval = ()
+        self.Eval = ()
         for row in range(32):
             unpacked_data = _struct.unpack('<7f', stream.read(28))
-            self.eval += (unpacked_data,)
+            self.Eval += (unpacked_data,)
 
-        unpacked_data = _struct.unpack('<Bbbb', stream.read(4))
-        self.irrelevant = bool(unpacked_data[0])
+        unpacked_data = _struct.unpack('<bbbb', stream.read(4))
+        self.Unused = unpacked_data[0]
         self.met = unpacked_data[1]
-        self.choice0 = unpacked_data[2]
-        self.choice3 = unpacked_data[3]
+        self.Choice0 = unpacked_data[2]
+        self.Choice3 = unpacked_data[3]
 
         return self
 
-    def todict(self):
-        return {'pos': self.pos, 'dice': self.dice, 'level': self.level,
-                'score': self.score, 'cube': self.cube,
-                'cubepos': self.cubepos, 'crawford': self.crawford,
-                'jacoby': self.jacoby, 'nmoves': self.nmoves,
-                'posplayed': self.posplayed, 'moves': self.moves,
-                'evallevel': self.evallevel, 'eval': self.eval,
-                'irrelevant': self.irrelevant, 'met': self.met,
-                'choice0': self.choice0, 'choice3': self.choice3}
-
 
-class EngineStructDoubleAction(object):
+class EngineStructDoubleAction(dict):
 
     SIZEOFREC = 132
 
-    def __init__(self):
-        self.pos = None
-        self.level = 0
-        self.score = None
-        self.cube = 0
-        self.cubepos = 0
-        self.jacoby = 0
-        self.crawford = 0
-        self.met = 0
-        self.flagdouble = 0
-        self.isbeaver = 0
-        self.eval = None
-        self.equb = 0.0
-        self.equdouble = 0.0
-        self.equdrop = 0.0
-        self.levelrequest = 0
-        self.doublechoice3 = 0
-        self.evaldouble = None
+    def __init__(self, **kw):
+        defaults = {
+            'Pos': None,
+            'Level': 0,
+            'Score': None,
+            'Cube': 0,
+            'CubePos': 0,
+            'Jacoby': 0,
+            'Crawford': 0,
+            'met': 0,
+            'FlagDouble': 0,
+            'isBeaver': 0,
+            'Eval': None,
+            'equB': 0.0,
+            'equDouble': 0.0,
+            'equDrop': 0.0,
+            'LevelRequest': 0,
+            'DoubleChoice3': 0,
+            'EvalDouble': None
+            }
+        super(EngineStructDoubleAction, self).__init__(defaults, **kw)
         
-    def __str__(self):
-        return str(self.todict())
+    def __setattr__(self, key, value):
+        self[key] = value
 
-    def __repr__(self):
-        return str(self.todict())
+    def __getattr__(self, key):
+       return self[key]
 
     def fromstream(self, stream):
         unpacked_data = _struct.unpack(
                 '<26bxxl2llllhhhh7ffffhh7f',
                 stream.read(132))
-        self.pos = unpacked_data[0:26]
-        self.level = unpacked_data[26]
-        self.score = unpacked_data[27:29]
-        self.cube = unpacked_data[29]
-        self.cubepos = unpacked_data[30]
-        self.jacoby = unpacked_data[31]
-        self.crawford = unpacked_data[32]
+        self.Pos = unpacked_data[0:26]
+        self.Level = unpacked_data[26]
+        self.Score = unpacked_data[27:29]
+        self.Cube = unpacked_data[29]
+        self.CubePos = unpacked_data[30]
+        self.Jacoby = unpacked_data[31]
+        self.Crawford = unpacked_data[32]
         self.met = unpacked_data[33]
-        self.flagdouble = unpacked_data[34]
-        self.isbeaver = unpacked_data[35]
-        self.eval = unpacked_data[36:43]
-        self.equb = unpacked_data[43]
-        self.equdouble = unpacked_data[44]
-        self.equdrop = unpacked_data[45]
-        self.levelrequest = unpacked_data[46]
-        self.doublechoice3 = unpacked_data[47]
-        self.evaldouble = unpacked_data[48:55]
+        self.FlagDouble = unpacked_data[34]
+        self.isBeaver = unpacked_data[35]
+        self.Eval = unpacked_data[36:43]
+        self.equB = unpacked_data[43]
+        self.equDouble = unpacked_data[44]
+        self.equDrop = unpacked_data[45]
+        self.LevelRequest = unpacked_data[46]
+        self.DoubleChoice3 = unpacked_data[47]
+        self.EvalDouble = unpacked_data[48:55]
 
         return self
 
-    def todict(self):
-        return {'pos': self.pos, 'level': self.level, 'score': self.score,
-                'cube': self.cube, 'cubepos:': self.cubepos,
-                'jacoby': self.jacoby, 'crawford': self.crawford,
-                'met': self.met, 'flagdouble': self.flagdouble,
-                'isbeaver': self.isbeaver, 'eval': self.eval,
-                'equb': self.equb, 'equdouble': self.equdouble,
-                'equdrop': self.equdrop, 'levelrequest': self.levelrequest,
-                'doublechoice3': self.doublechoice3, 
-                'evaldouble': self.evaldouble}
-        
-
-class HeaderMatchEntry(object):
+class HeaderMatchEntry(dict):
 
     SIZEOFREC = 2560
 
-    def __init__(self):
-        self.name = 'MatchInfo'
-        self.entrytype = GameFileRecord.ENTRYTYPE_HEADERMATCH
-        self.splayer1 = None
-        self.splayer2 = None
-        self.matchlength = 0
-        self.variation = 0
-        self.crawford = False
-        self.jacoby = False
-        self.beaver = False
-        self.autodouble = False
-        self.elo1 = 0.0
-        self.elo2 = 0.0
-        self.exp1 = 0
-        self.exp2 = 0
-        self.date = 0
-        self.sevent = None
-        self.gameid = 0
-        self.complevel1 = -1
-        self.complevel2 = -1
-        self.countforelo = False
-        self.addtoprofile1 = False
-        self.addtoprofile2 = False
-        self.slocation = None
-        self.gamemode = 0
-        self.imported = False
-        self.sround = None
-        self.invert = 0
-        self.version = 0
-        self.magic = 0x494C4D44
-        self.moneyinitg = 0
-        self.moneyinitscore = [0, 0]
-        self.entered = False
-        self.counted = False
-        self.unratedimp = False
-        self.commentheadermatch = -1
-        self.commentfootermatch = -1
-        self.ismoneymatch = False
-        self.winmoney = 0.0
-        self.losemoney = 0.0
-        self.currency = 0
-        self.feemoney = 0.0
-        self.tablestake = 0
-        self.siteid = -1
-        self.cubelimit = 0
-        self.autodoublemax = 0
-        self.transcribed = False
-        self.event = None
-        self.player1 = None
-        self.player2 = None
-        self.location = None
-        self.round = None
-        self.timesetting = None
-        self.tottimedelaymove = 0
-        self.tottimedelaycube = 0
-        self.tottimedelaymovedone = 0
-        self.tottimedelaycubedone = 0
-        self.transcriber = None
+    def __init__(self, version=0, **kw):
+        defaults = {
+            'Name': 'MatchInfo',
+            'EntryType': GameFileRecord.ENTRYTYPE_HEADERMATCH,
+            'SPlayer1': None,
+            'SPlayer2': None,
+            'MatchLength': 0,
+            'Variation': 0,
+            'Crawford': False,
+            'Jacoby': False,
+            'Beaver': False,
+            'AutoDouble': False,
+            'Elo1': 0.0,
+            'Elo2': 0.0,
+            'Exp1': 0,
+            'Exp2': 0,
+            'Date': 0,
+            'SEvent': None,
+            'GameId': 0,
+            'CompLevel1': -1,
+            'CompLevel2': -1,
+            'CountForElo': False,
+            'AddtoProfile1': False,
+            'AddtoProfile2': False,
+            'SLocation': None,
+            'GameMode': 0,
+            'Imported': False,
+            'SRound': None,
+            'Invert': 0,
+            'Version': version,
+            'Magic': 0x494C4D44,
+            'MoneyInitG': 0,
+            'MoneyInitScore': [0, 0],
+            'Entered': False,
+            'Counted': False,
+            'UnratedImp': False,
+            'CommentHeaderMatch': -1,
+            'CommentFooterMatch': -1,
+            'isMoneyMatch': False,
+            'WinMoney': 0.0,
+            'LoseMoney': 0.0,
+            'Currency': 0,
+            'FeeMoney': 0.0,
+            'TableStake': 0,
+            'SiteId': -1,
+            'CubeLimit': 0,
+            'AutoDoubleMax': 0,
+            'Transcribed': False,
+            'Event': None,
+            'Player1': None,
+            'Player2': None,
+            'Location': None,
+            'Round': None,
+            'TimeSetting': None,
+            'TotTimeDelayMove': 0,
+            'TotTimeDelayCube': 0,
+            'TotTimeDelayMoveDone': 0,
+            'TotTimeDelayCubeDone': 0,
+            'Transcriber': None
+            }
+        super(HeaderMatchEntry, self).__init__(defaults, **kw)
 
-    def __str__(self):
-        return str(self.todict())
+    def __setattr__(self, key, value):
+        self[key] = value
 
-    def __repr__(self):
-        return str(self)
+    def __getattr__(self, key):
+       return self[key]
 
     def fromstream(self, stream):
 
         unpacked_data = _struct.unpack(
             '<9x41B41BxllBBBBddlld129BxxxlllBBB129BlB129BxxllLl2lBBB'
             'xllBxxxfflfll', stream.read(612))
-        self.splayer1 = _xgutils.delphishortstrtostr(unpacked_data[0:41])
-        self.splayer2 = _xgutils.delphishortstrtostr(unpacked_data[41:82])
-        self.matchlength = unpacked_data[82]
-        self.variation = unpacked_data[83]
-        self.crawford = bool(unpacked_data[84])
-        self.jacoby = bool(unpacked_data[85])
-        self.beaver = bool(unpacked_data[86])
-        self.autodouble = bool(unpacked_data[87])
-        self.elo1 = unpacked_data[88]
-        self.elo2 = unpacked_data[89]
-        self.exp1 = unpacked_data[90]
-        self.exp2 = unpacked_data[91]
-        self.date = str(_xgutils.delphidatetimeconv(unpacked_data[92]))
-        self.sevent = _xgutils.delphishortstrtostr(unpacked_data[93:222])
-        self.gameid = unpacked_data[222]
-        self.complevel1 = unpacked_data[223]
-        self.complevel2 = unpacked_data[224]
-        self.countforelo = bool(unpacked_data[225])
-        self.addtoprofile1 = bool(unpacked_data[226])
-        self.addtoprofile2 = bool(unpacked_data[227])
-        self.slocation = _xgutils.delphishortstrtostr(unpacked_data[228:357])
-        self.gamemode = unpacked_data[357]
-        self.imported = bool(unpacked_data[358])
-        self.sround = _xgutils.delphishortstrtostr(unpacked_data[359:487])
-        self.invert = unpacked_data[488]
-        self.version = unpacked_data[489]
-        self.magic = unpacked_data[490]
-        self.moneyinitg = unpacked_data[491]
-        self.moneyinitscore = unpacked_data[492:494]
-        self.entered = bool(unpacked_data[494])
-        self.counted = bool(unpacked_data[495])
-        self.unratedimp = bool(unpacked_data[496])
-        self.commentheadermatch = unpacked_data[497]
-        self.commentfootermatch = unpacked_data[498]
-        self.ismoneymatch = bool(unpacked_data[499])
-        self.winmoney = unpacked_data[500]
-        self.losemoney = unpacked_data[501]
-        self.currency = unpacked_data[502]
-        self.feemoney = unpacked_data[503]
-        self.tablestake = unpacked_data[504]
-        self.siteid = unpacked_data[505]
-        if self.version >= 8:
+        self.SPlayer1 = _xgutils.delphishortstrtostr(unpacked_data[0:41])
+        self.SPlayer2 = _xgutils.delphishortstrtostr(unpacked_data[41:82])
+        self.MatchLength = unpacked_data[82]
+        self.Variation = unpacked_data[83]
+        self.Crawford = bool(unpacked_data[84])
+        self.Jacoby = bool(unpacked_data[85])
+        self.Beaver = bool(unpacked_data[86])
+        self.AutoDouble = bool(unpacked_data[87])
+        self.Elo1 = unpacked_data[88]
+        self.Elo2 = unpacked_data[89]
+        self.Exp1 = unpacked_data[90]
+        self.Exp2 = unpacked_data[91]
+        self.Date = str(_xgutils.delphidatetimeconv(unpacked_data[92]))
+        self.SEvent = _xgutils.delphishortstrtostr(unpacked_data[93:222])
+        self.GameId = unpacked_data[222]
+        self.CompLevel1 = unpacked_data[223]
+        self.CompLevel2 = unpacked_data[224]
+        self.CountForElo = bool(unpacked_data[225])
+        self.AddtoProfile1 = bool(unpacked_data[226])
+        self.AddtoProfile2 = bool(unpacked_data[227])
+        self.SLocation = _xgutils.delphishortstrtostr(unpacked_data[228:357])
+        self.GameMode = unpacked_data[357]
+        self.Imported = bool(unpacked_data[358])
+        self.SRound = _xgutils.delphishortstrtostr(unpacked_data[359:487])
+        self.Invert = unpacked_data[488]
+        self.Version = unpacked_data[489]
+        self.Magic = unpacked_data[490]
+        self.MoneyInitG = unpacked_data[491]
+        self.MoneyInitScore = unpacked_data[492:494]
+        self.Entered = bool(unpacked_data[494])
+        self.Counted = bool(unpacked_data[495])
+        self.UnratedImp = bool(unpacked_data[496])
+        self.CommentHeaderMatch = unpacked_data[497]
+        self.CommentFooterMatch = unpacked_data[498]
+        self.isMoneyMatch = bool(unpacked_data[499])
+        self.WinMoney = unpacked_data[500]
+        self.LoseMoney = unpacked_data[501]
+        self.Currency = unpacked_data[502]
+        self.FeeMoney = unpacked_data[503]
+        self.TableStake = unpacked_data[504]
+        self.SiteId = unpacked_data[505]
+        if self.Version >= 8:
             unpacked_data = _struct.unpack('<ll', stream.read(8))
-            self.cubelimit = unpacked_data[0]
-            self.autodoublemax = unpacked_data[1]
-        if self.version >= 24:
+            self.CubeLimit = unpacked_data[0]
+            self.AutoDoubleMax = unpacked_data[1]
+        if self.Version >= 24:
             unpacked_data = _struct.unpack('<Bx129H129H129H129H129H',
                                            stream.read(1292))
-            self.transcribed = bool(unpacked_data[0])
-            self.event = _xgutils.utf16intarraytostr(unpacked_data[1:130],
-                                                     'utf-8')
-            self.player1 = _xgutils.utf16intarraytostr(unpacked_data[130:259],
-                                                       'utf-8')
-            self.player2 = _xgutils.utf16intarraytostr(unpacked_data[259:388],
-                                                       'utf-8')
-            self.location = _xgutils.utf16intarraytostr(unpacked_data[388:517],
-                                                        'utf-8')
-            self.round = _xgutils.utf16intarraytostr(unpacked_data[517:646],
-                                                     'utf-8')
-        if self.version >= 25:
-            self.timesetting = TimeSettingRecord().fromstream(stream)
-        if self.version >= 26:
+            self.Transcribed = bool(unpacked_data[0])
+            self.Event = _xgutils.utf16intarraytostr(unpacked_data[1:130])
+            self.Player1 = _xgutils.utf16intarraytostr(unpacked_data[130:259])
+            self.Player2 = _xgutils.utf16intarraytostr(unpacked_data[259:388])
+            self.Location = _xgutils.utf16intarraytostr(unpacked_data[388:517])
+            self.Round = _xgutils.utf16intarraytostr(unpacked_data[517:646])
+        if self.Version >= 25:
+            self.TimeSetting = TimeSettingRecord().fromstream(stream)
+        if self.Version >= 26:
             unpacked_data = _struct.unpack('<llll', stream.read(16))
-            self.tottimedelaymove = unpacked_data[0]
-            self.tottimedelaycube = unpacked_data[1]
-            self.tottimedelaymovedone = unpacked_data[2]
-            self.tottimedelaycubedone = unpacked_data[3]
-        if self.version >= 30:
+            self.TotTimeDelayMove = unpacked_data[0]
+            self.TotTimeDelayCube = unpacked_data[1]
+            self.TotTimeDelayMoveDone = unpacked_data[2]
+            self.TotTimeDelayCubeDone = unpacked_data[3]
+        if self.Version >= 30:
             unpacked_data = _struct.unpack('<129H', stream.read(258))
-            self.transcriber = _xgutils.utf16intarraytostr(
-                unpacked_data[0:129], 'utf-8')
+            self.Transcriber = _xgutils.utf16intarraytostr(
+                unpacked_data[0:129])
 
         return self
 
-    def todict(self):
-        return {'splayer1': self.splayer1,  'splayer2': self.splayer2,
-                'matchlength': self.matchlength,
-                'variation': self.variation, 'crawford': self.crawford,
-                'jacoby': self.jacoby, 'beaver': self.beaver,
-                'autodouble': self.autodouble, 'elo1': self.elo1,
-                'elo2:': self.elo2, 'exp1': self.exp1, 'exp2': self.exp2,
-                'date': self.date, 'sevent': self.sevent,
-                'gameid': self.gameid, 'complevel1': self.complevel1,
-                'complevel2': self.complevel2,
-                'addtoprofile1': self.addtoprofile1,
-                'addtoprofile2': self.addtoprofile2,
-                'countforelo': self.countforelo,
-                'slocation': self.slocation, 'gamemode': self.gamemode,
-                'imported': self.imported, 'sround': self.sround,
-                'invert': self.invert, 'version': self.version,
-                'magic': self.magic, 'moneyinitg': self.moneyinitg,
-                'moneyinitscore': self.moneyinitscore,
-                'entered': self.entered, 'counted': self.counted,
-                'unratedimp': self.unratedimp,
-                'commentheadermatch': self.commentheadermatch,
-                'commentfootermatch': self.commentfootermatch,
-                'ismoneymatch': self.ismoneymatch,
-                'winmoney': self.winmoney, 'losemoney': self.losemoney,
-                'currency': self.currency, 'feemoney': self.feemoney,
-                'tablestake': self.tablestake, 'siteid': self.siteid,
-                'cubelimit': self.cubelimit,
-                'autodoublemax': self.autodoublemax,
-                'transcribed': self.transcribed, 'event': self.event,
-                'player1': self.player1, 'player2': self.player2,
-                'location': self.location, 'round': self.round,
-                'transcriber': self.transcriber,
-                'timesetting': self.timesetting,
-                'tottimedelaymove': self.tottimedelaymove,
-                'tottimedelaycube': self.tottimedelaycube,
-                'tottimedelaymovedone': self.tottimedelaymovedone,
-                'tottimedelaycubedone': self.tottimedelaycubedone}
-
-class FooterGameEntry(object):
 
-    SIZEOFREC = 2560
+class FooterGameEntry(dict):
 
-    def __init__(self):
-        self.name = 'GameFooter'
-        self.entrytype = GameFileRecord.ENTRYTYPE_FOOTERGAME
-        self.score1g = 0
-        self.score2g = 0
-        self.crawfordapplyg = False
-        self.winner = 0
-        self.pointswon = 0
-        self.termination = 0
-        self.errresign = 0.0
-        self.errtakeresign = 0.0
-        self.eval = None
-        self.evallevel = 0
+    SIZEOFREC = 2560
 
-    def __str__(self):
-        return str(self.todict())
+    def __init__(self, **kw):
+        defaults = {
+            'Name': 'GameFooter',
+            'EntryType': GameFileRecord.ENTRYTYPE_FOOTERGAME,
+            'Score1g': 0,
+            'Score2g': 0,
+            'CrawfordApplyg': False,
+            'Winner': 0,
+            'PointsWon': 0,
+            'Termination': 0,
+            'ErrResign': 0.0,
+            'ErrTakeResign': 0.0,
+            'Eval': None,
+            'EvalLevel': 0
+            }
+        super(FooterGameEntry, self).__init__(defaults, **kw)
+        
+    def __setattr__(self, key, value):
+        self[key] = value
 
-    def __repr__(self):
-        return str(self)
+    def __getattr__(self, key):
+       return self[key]
 
     def fromstream(self, stream):
         unpacked_data = _struct.unpack('<9xxxxllBxxxlllxxxxdd7dl', stream.read(116))
-        self.score1g = unpacked_data[0]
-        self.score2g = unpacked_data[1]
-        self.crawfordapplyg = bool(unpacked_data[2])
-        self.winner = unpacked_data[3]
-        self.pointswon = unpacked_data[4]
-        self.termination = unpacked_data[5]
-        self.errresign = unpacked_data[6]
-        self.errtakeresign = unpacked_data[7]
-        self.eval = unpacked_data[8:15]
-        self.evallevel = unpacked_data[15]
+        self.Score1g = unpacked_data[0]
+        self.Score2g = unpacked_data[1]
+        self.CrawfordApplyg = bool(unpacked_data[2])
+        self.Winner = unpacked_data[3]
+        self.PointsWon = unpacked_data[4]
+        self.Termination = unpacked_data[5]
+        self.ErrResign = unpacked_data[6]
+        self.ErrTakeResign = unpacked_data[7]
+        self.Eval = unpacked_data[8:15]
+        self.EvalLevel = unpacked_data[15]
         return self
+         
 
-    def todict(self):
-        return {'score1g': self.score1g, 'score2g': self.score2g,
-                'crawfordapplyg': self.crawfordapplyg,
-                'winner': self.winner, 'pointswon': self.pointswon,
-                'termination': self.termination, 'errresign': self.errresign,
-                'errtakeresign': self.errtakeresign, 'eval': self.eval,
-                'evallevel': self.evallevel}
-
-class MissingEntry(object):
+class MissingEntry(dict):
 
     SIZEOFREC = 2560
 
-    def __init__(self):
-        self.name = 'Missing'
-        self.entrytype = GameFileRecord.ENTRYTYPE_MISSING
-        self.missingerrluck = 0.0
-        self.missingwinner = 0
-        self.missingpoints = 0
-
-    def __str__(self):
-        return str(self.todict())
+    def __init__(self, **kw):
+        defaults = {
+            'Name': 'Missing',
+            'EntryType': GameFileRecord.ENTRYTYPE_MISSING,
+            'MissingErrLuck': 0.0,
+            'MissingWinner': 0,
+            'MissingPoints': 0
+            }
+        super(MissingEntry, self).__init__(defaults, **kw)
+        
+    def __setattr__(self, key, value):
+        self[key] = value
 
-    def __repr__(self):
-        return str(self)
+    def __getattr__(self, key):
+       return self[key]
 
     def fromstream(self, stream):
         unpacked_data = _struct.unpack('<9xxxxxxxxdll', stream.read(32))
-        self.missingerrluck = unpacked_data[0]
-        self.missingwinner = unpacked_data[1]
-        self.missingpoints = unpacked_data[2]
+        self.MissingErrLuck = unpacked_data[0]
+        self.MissingWinner = unpacked_data[1]
+        self.MissingPoints = unpacked_data[2]
         return self
 
-    def todict(self):
-        return {'missingerrluck': self.missingerrluck,
-                'missingwinner': self.missingwinner,
-                'missingpoints': self.missingpoints}
 
 class FooterMatchEntry(dict):
 
     SIZEOFREC = 2560
 
-    def __init__(self):
-        name = 'MatchFooter'
-        entrytype = GameFileRecord.ENTRYTYPE_FOOTERMATCH
-        self.score1m = 0
-        self.score2m = 0
-        self.winnerm = 0
-        self.elo1m = 0.0
-        self.elo2m = 0.0
-        self.exp1m = 0
-        self.exp2m = 0
-        self.datem = 0.0
-
-    def __str__(self):
-        return str(self.__dict__)
+    def __init__(self, **kw):
+        defaults = {
+            'Name': 'MatchFooter',
+            'EntryType': GameFileRecord.ENTRYTYPE_FOOTERMATCH,
+            'Score1m': 0,
+            'Score2m': 0,
+            'WinnerM': 0,
+            'Elo1m': 0.0,
+            'Elo2m': 0.0,
+            'Exp1m': 0,
+            'Exp2m': 0,
+            'Datem': 0.0
+            }
+        super(FooterMatchEntry, self).__init__(defaults, **kw)
+        
+    def __setattr__(self, key, value):
+        self[key] = value
 
-    def __repr__(self):
-        return str(self)
+    def __getattr__(self, key):
+       return self[key]
 
     def fromstream(self, stream):
         unpacked_data = _struct.unpack('<9xxxxlllddlld', stream.read(56))
-        self.score1m = unpacked_data[0]
-        self.score2m = unpacked_data[1]
-        self.winnerm = unpacked_data[2]
-        self.elo1m = unpacked_data[3]
-        self.elo2m = unpacked_data[4]
-        self.exp1m = unpacked_data[5]
-        self.exp2m = unpacked_data[6]
-        self.datem = str(_xgutils.delphidatetimeconv(unpacked_data[7]))
+        self.Score1m = unpacked_data[0]
+        self.Score2m = unpacked_data[1]
+        self.WinnerM = unpacked_data[2]
+        self.Elo1m = unpacked_data[3]
+        self.Elo2m = unpacked_data[4]
+        self.Exp1m = unpacked_data[5]
+        self.Exp2m = unpacked_data[6]
+        self.Datem = str(_xgutils.delphidatetimeconv(unpacked_data[7]))
 
         return self
 
-    def todict(self):
-        return {'score1m': self.score1m, 'score2m': self.score2m,
-                'winnerm': self.winnerm, 'elo1m': self.elo1m,
-                'elo2m': self.elo2m, 'exp1m': self.exp1m,
-                'exp2m': self.exp2m, 'datem': self.datem}
-
 
-class HeaderGameEntry(object):
+class HeaderGameEntry(dict):
 
     SIZEOFREC = 2560
 
-    def __init__(self):
-        self.name = 'GameHeader'
-        self.entrytype = GameFileRecord.ENTRYTYPE_HEADERGAME
-        self.score1 = 0
-        self.score2 = 0
-        self.crawfordapply = False
-        self.posinit = (0,) * 26    # Tuple of 26 integers
-        self.gamenumber = 0
-        self.inprogress = False
-        self.commentheadergame = -1
-        self.commentfootergame = -1
-        self.numberofautodoubles = 0
-
-    def __str__(self):
-        return str(self.todict())
+    def __init__(self, **kw):
+        defaults = {
+            'Name': 'GameHeader',
+            'EntryType': GameFileRecord.ENTRYTYPE_HEADERGAME,
+            'Score1': 0,
+            'Score2': 0,
+            'CrawfordApply': False,
+            'PosInit': (0,) * 26,    # Tuple of 26 integers
+            'GameNumber': 0,
+            'InProgress': False,
+            'CommentHeaderGame': -1,
+            'CommentFooterGame': -1,
+            'NumberOfAutoDoubles': 0
+            }
+        super(HeaderGameEntry, self).__init__(defaults, **kw)
+        
+    def __setattr__(self, key, value):
+        self[key] = value
 
-    def __repr__(self):
-        return str(self)
+    def __getattr__(self, key):
+       return self[key]
 
     def fromstream(self, stream):
         unpacked_data = _struct.unpack('<9xxxxllB26bxlBxxxlll', stream.read(68))
-        self.score1 = unpacked_data[0]
-        self.score2 = unpacked_data[1]
-        self.crawfordapply = bool(unpacked_data[2])
-        self.posinit = unpacked_data[3:29]
-        self.gamenumber = unpacked_data[29]
-        self.inprogress = bool(unpacked_data[30])
-        self.commentheadergame = unpacked_data[31]
-        self.commentfootergame = unpacked_data[32]
-        if self.version >= 26:
-            self.numberofautodoubles = unpacked_data[33]
+        self.Score1 = unpacked_data[0]
+        self.Score2 = unpacked_data[1]
+        self.CrawfordApply = bool(unpacked_data[2])
+        self.PosInit = unpacked_data[3:29]
+        self.GameNumber = unpacked_data[29]
+        self.InProgress = bool(unpacked_data[30])
+        self.CommentHeaderGame = unpacked_data[31]
+        self.CommentFooterGame = unpacked_data[32]
+        if self.Version >= 26:
+            self.NumberOfAutoDoubles = unpacked_data[33]
 
         return self
 
-    def todict(self):
-        return {'score1': self.score1, 'score2': self.score2,
-                'crawfordapply': self.crawfordapply, 'posinit': self.posinit,
-                'gamenumber': self.gamenumber, 'inprogress': self.inprogress,
-                'commentheadergame': self.commentheadergame, 
-                'commentfootergame': self.commentfootergame, 
-                'numberofautodoubles': self.numberofautodoubles }
-
 
 class CubeEntry(object):
 
@@ -667,14 +593,14 @@ class CubeEntry(object):
         self.errtutortake = unpacked_data[15]
         self.flaggeddouble = bool(unpacked_data[16])
         self.commentcube = unpacked_data[17]
-        if self.version >= 24:
+        if self.Version >= 24:
             self.editedcube = bool(unpacked_data[18])
-        if self.version >= 26:
+        if self.Version >= 26:
             self.timedelaycube = bool(unpacked_data[19])
             self.timedelaycubedone = bool(unpacked_data[20])
-        if self.version >= 27:
+        if self.Version >= 27:
             self.numberofautodoublecube = unpacked_data[21]
-        if self.version >= 28:
+        if self.Version >= 28:
             self.timebot = unpacked_data[22]
             self.timetop = unpacked_data[23]
         return self
@@ -772,14 +698,14 @@ class MoveEntry(object):
         self.errtutormove = unpacked_data[67]
         self.flagged = bool(unpacked_data[68])
         self.commentmove = unpacked_data[69]
-        if self.version >= 24:
+        if self.Version >= 24:
             unpacked_data = _struct.unpack('<B', stream.read(1))
             self.editedmove = bool(unpacked_data[0])
-        if self.version >= 26:
+        if self.Version >= 26:
             unpacked_data = _struct.unpack('<xxxLL', stream.read(11))
             self.timedelaymove = unpacked_data[0]
             self.timedelaymovedone = unpacked_data[1]
-        if self.version >= 27:
+        if self.Version >= 27:
             unpacked_data = _struct.unpack('<l', stream.read(4))
             self.numberofautodoublemove = unpacked_data[0]
         unpacked_data = _struct.unpack('<4l', stream.read(16))
@@ -822,7 +748,7 @@ class UnimplementedEntry(object):
         return {}
 
 
-class GameFileRecord(object):
+class GameFileRecord(dict):
 
     __SIZEOFSRHDR = 9
     __REC_CLASSES = [HeaderMatchEntry, HeaderGameEntry,
@@ -840,15 +766,15 @@ class GameFileRecord(object):
         object. The version needs to be propogated to all other game 
         file objects within the same archive.
         """
-        self.entrytype = -1
-        self.record = None
-        self.version = version
+        self.EntryType = -1
+        self.Record = None
+        self.Version = version
 
-    def __str__(self):
-        return str(self.todict())
+#    def __str__(self):
+#        return str(self.todict())
 
-    def __repr__(self):
-        return str(self.todict())
+#    def __repr__(self):
+#        return str(self.todict())
 
     def fromstream(self, stream):
         # Read the header. First 8 bytes are unused. 9th byte is record type
@@ -860,7 +786,7 @@ class GameFileRecord(object):
                                            stream.read(self.__SIZEOFSRHDR))
         except _struct.error:
             return None
-        self.entrytype = unpacked_data[0]
+        self.EntryType = unpacked_data[0]
 
         # Back up to the beginning of the record after getting the record 
         # type and feed the entire stream back into the corresponding 
@@ -868,16 +794,16 @@ class GameFileRecord(object):
         stream.seek(-self.__SIZEOFSRHDR, _os.SEEK_CUR)
 
         # Using the appropriate class, read the data stream 
-        self.record = self.__REC_CLASSES[self.entrytype]()
-        self.record.version = self.version
-        self.record.fromstream(stream)
+        self.Record = self.__REC_CLASSES[self.EntryType]()
+        self.Record.Version = self.Version
+        self.Record.fromstream(stream)
         realrecsize = stream.tell() - startpos
 
         # Each record is actually 2560 bytes long. We need to advance past
         # the unused filler data to be at the start of the next record
-        stream.seek(self.record.SIZEOFREC - realrecsize, _os.SEEK_CUR)
+        stream.seek(self.Record.SIZEOFREC - realrecsize, _os.SEEK_CUR)
 
-        return self.record
+        return self.Record
 
     def todict(self):
         return {'entrytype': self.entrytype, 'record': self.record}
index 46884a3..a6993ab 100644 (file)
@@ -18,6 +18,7 @@
 #
 #
 
+import sys as _sys
 import zlib as _zlib
 import datetime as _datetime
 
@@ -56,19 +57,31 @@ def streamcrc32(stream, numbytes=None, startpos=None, blksize=32768):
     return crc32 & 0xffffffff
 
 
-def utf16intarraytostr(intarray, encoding):
-    """Convert an array of integers (UTF16) into a string encoded
-    with the specified output type. Input array is null terminated.
+def utf16intarraytostr3x(intarray):
+    """Python 3.x - Convert an array of integers (UTF16) to a
+    string. Input array is null terminated.
     """
     newstr = []
     for intval in intarray:
         if intval == 0:
             break
-        newstr += [intval]
+        newstr += [chr(intval).encode('utf-8')]
 
-    return ''.join(bytearray(newstr).decode(encoding))
+    return (b''.join([x for x in newstr]))
 
 
+def utf16intarraytostr2x(intarray):
+    """Python 2.x - Convert an array of integers (UTF16) to a
+    string. Input array is null terminated.
+    """
+    newstr = []
+    for intval in intarray:
+        if intval == 0:
+            break
+        newstr += [unichr(intval).encode('utf-8')]
+
+    return ''.join(newstr)
+
 def delphidatetimeconv(delphi_datetime):
     """Convert a double float Delphi style timedate object to a Python
     datetime object. Delphi uses the number of days since
@@ -95,3 +108,11 @@ def delphishortstrtostr(shortstring_abytes):
 
 if __name__ == '__main__':
     pass
+else:
+    # Map the utf16intarraytostr function depending on whether
+    # we are using Python 3.x or 2.x
+    if _sys.version_info >= (3, 0):
+        utf16intarraytostr = utf16intarraytostr3x
+    else:
+        utf16intarraytostr = utf16intarraytostr2x
+