[gnome-sudoku] gnome-sudoku python 2to3 port.



commit da048b6c3bd4038a491b19988f1767c55187019d
Author: Dmitrijs Ledkovs <dmitrijs ledkovs canonical com>
Date:   Sat Nov 10 00:17:02 2012 +0000

    gnome-sudoku python 2to3 port.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=688024

 configure.ac                         |    2 +-
 src/gnome-sudoku                     |    2 +-
 src/lib/dancer.py                    |    8 ++--
 src/lib/dialog_swallower.py          |    6 +-
 src/lib/game_selector.py             |   14 +++---
 src/lib/gnome_sudoku.py              |    5 ++-
 src/lib/gsudoku.py                   |   38 +++++++++---------
 src/lib/gtk_goodies/Undo.py          |    8 ++--
 src/lib/gtk_goodies/dialog_extras.py |   10 ++--
 src/lib/main.py                      |   45 ++++++++++-----------
 src/lib/number_box.py                |    6 +-
 src/lib/pausable.py                  |    5 +-
 src/lib/printing.py                  |    8 ++--
 src/lib/saver.py                     |   66 ++++++++++++++----------------
 src/lib/simple_debug.py              |    8 ++--
 src/lib/sudoku.py                    |   73 +++++++++++++++++-----------------
 src/lib/sudoku_maker.py              |   69 ++++++++++++++++----------------
 src/lib/tracker_info.py              |   24 ++++++------
 18 files changed, 198 insertions(+), 199 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index bd0cb22..56d7ab3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@ GNOME_MAINTAINER_MODE_DEFINES
 
 GLIB_GSETTINGS
 
-AM_PATH_PYTHON([2.4],,AC_MSG_ERROR([Python not found]))
+AM_PATH_PYTHON([3.0],,AC_MSG_ERROR([Python not found]))
 
 dnl ###########################################################################
 dnl Dependencies
diff --git a/src/gnome-sudoku b/src/gnome-sudoku
index 2515787..504d8c7 100755
--- a/src/gnome-sudoku
+++ b/src/gnome-sudoku
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#!/usr/bin/python3
 # -*- coding: utf-8 -*-
 
 # GNOME Sudoku is a simple sudoku generator and player. Sudoku is a
diff --git a/src/lib/dancer.py b/src/lib/dancer.py
index 6afb7bd..5a597fc 100644
--- a/src/lib/dancer.py
+++ b/src/lib/dancer.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 from gi.repository import Gtk,GObject
-import colors
+from . import colors
 
 class GridDancer:
 
@@ -33,7 +33,7 @@ class GridDancer:
         self.adjustment = 0
 
     def start_dancing (self):
-        for box in self.grid.__entries__.values():
+        for box in list(self.grid.__entries__.values()):
             box.props.can_focus = False
             if box.read_only:
                 box.read_only = False
@@ -46,7 +46,7 @@ class GridDancer:
 
     def stop_dancing (self):
         self.dancing = False
-        for box in self.grid.__entries__.values():
+        for box in list(self.grid.__entries__.values()):
             box.props.can_focus = True
             if box.need_restore:
                 box.read_only = True
@@ -105,7 +105,7 @@ class GridDancer:
 
 if __name__ == '__main__':
     def test_dance_grid ():
-        import gsudoku
+        from . import gsudoku
         window = Gtk.Window()
         game = '''9 1 6 3 2 8 4 5 7
                   5 7 4 6 1 9 2 8 3
diff --git a/src/lib/dialog_swallower.py b/src/lib/dialog_swallower.py
index 4a8ef7a..722d6c9 100644
--- a/src/lib/dialog_swallower.py
+++ b/src/lib/dialog_swallower.py
@@ -41,16 +41,16 @@ class SwappableArea (Gtk.Notebook):
 
     def run_dialog (self, d):
         self.running = d
-        if not self.swallowed.has_key(d):
+        if d not in self.swallowed:
             self.swallow_dialog(d)
         self.set_current_page(self.swallowed[d])
         try:
             Gtk.main()
         except:
-            print 'Error in dialog!'
+            print('Error in dialog!')
             import traceback
             traceback.print_exc()
-            print 'forge on fearlessly...'
+            print('forge on fearlessly...')
         self.set_current_page(self.main_page)
         self.running = None
         tmp_response = self.response
diff --git a/src/lib/game_selector.py b/src/lib/game_selector.py
index 4a2c2a2..7ca290a 100644
--- a/src/lib/game_selector.py
+++ b/src/lib/game_selector.py
@@ -1,14 +1,14 @@
 # -*- coding: utf-8 -*-
 from gi.repository import Gtk,GdkPixbuf,GObject
 import os.path
-import sudoku, saver, sudoku_maker
-import sudoku_thumber
+from . import sudoku, saver, sudoku_maker
+from . import sudoku_thumber
 from gettext import gettext as _
 from gettext import ngettext
 import time
-import defaults
-from simple_debug import simple_debug
-from colors import color_hex_to_float
+from . import defaults
+from .simple_debug import simple_debug
+from .colors import color_hex_to_float
 
 def color_from_difficulty (diff):
     DR = sudoku.DifficultyRating
@@ -128,7 +128,7 @@ class NewOrSavedGameSelector:
             if puzzles:
                 puzzle, diff_val = puzzles[0]
             else:
-                print 'WARNING: Repeating puzzle for difficulty %s -- generate more puzzles to avoid this.' 
% cat
+                print('WARNING: Repeating puzzle for difficulty %s -- generate more puzzles to avoid this.' 
% cat)
                 puzzles = self.sudoku_maker.get_puzzles(1, [cat], new = False)
                 if puzzles:
                     puzzle, diff_val = puzzles[0]
@@ -138,7 +138,7 @@ class NewOrSavedGameSelector:
                     for n in lpuz:
                         puzzle += n
                 else:
-                    print 'WARNING: No puzzle for difficulty', cat
+                    print('WARNING: No puzzle for difficulty', cat)
                     continue
             grid = sudoku.sudoku_grid_from_string(puzzle).grid
             self.new_game_model.append(('<b><i>' + label + '</i></b>',
diff --git a/src/lib/gnome_sudoku.py b/src/lib/gnome_sudoku.py
index 1271ed1..ca37f04 100644
--- a/src/lib/gnome_sudoku.py
+++ b/src/lib/gnome_sudoku.py
@@ -9,6 +9,9 @@ class SafeStdout:
     def fileno(self):
         return self.stdout.fileno()
 
+    def flush(self):
+        return self.stdout.flush()
+
     def write(self, data):
         try:
             self.stdout.write(data)
@@ -18,5 +21,5 @@ class SafeStdout:
 sys.stdout = SafeStdout()
 
 def start_game ():
-    import main
+    from . import main
     main.start_game()
diff --git a/src/lib/gsudoku.py b/src/lib/gsudoku.py
index b222f95..f5dd602 100644
--- a/src/lib/gsudoku.py
+++ b/src/lib/gsudoku.py
@@ -1,13 +1,13 @@
 # -*- coding: utf-8 -*-
 from gi.repository import Gtk,Gdk,GObject
-import colors
+from . import colors
 import math
 import random
 import logging
-from simple_debug import simple_debug
-import sudoku
-import number_box
-import tracker_info
+from .simple_debug import simple_debug
+from . import sudoku
+from . import number_box
+from . import tracker_info
 
 def gtkcolor_to_rgb (color):
     return (color.red   / float(2**16),
@@ -43,11 +43,11 @@ class SudokuNumberGrid (Gtk.AspectFrame):
         self.show_all()
 
     def set_parent_for(self, parent):
-        for entry in self.__entries__.values():
+        for entry in list(self.__entries__.values()):
             entry.set_parent_win(parent)
 
     def set_timer(self, timer):
-        for entry in self.__entries__.values():
+        for entry in list(self.__entries__.values()):
             entry.set_timer(timer)
 
     def get_focused_entry (self):
@@ -69,7 +69,7 @@ class SudokuNumberGrid (Gtk.AspectFrame):
         self.table.override_color(Gtk.StateFlags.NORMAL, color)
         self.table.override_background_color(Gtk.StateFlags.NORMAL, color)
 
-        for e in self.__entries__.values():
+        for e in list(self.__entries__.values()):
             e.override_background_color(Gtk.StateFlags.NORMAL, color)
 
 class SudokuGameDisplay (SudokuNumberGrid, GObject.GObject):
@@ -96,7 +96,7 @@ class SudokuGameDisplay (SudokuNumberGrid, GObject.GObject):
         GObject.GObject.__init__(self)
         SudokuNumberGrid.__init__(self, group_size = group_size)
         self.setup_grid(grid, group_size)
-        for e in self.__entries__.values():
+        for e in list(self.__entries__.values()):
             e.show()
             e.connect('undo-change', self.entry_callback, 'undo-change')
             e.connect('changed', self.entry_callback)
@@ -158,7 +158,7 @@ class SudokuGameDisplay (SudokuNumberGrid, GObject.GObject):
             self.highlight_cells()
 
     def unhighlight_cells (self, *args):
-        for e in self.__entries__.values():
+        for e in list(self.__entries__.values()):
             e.set_background_color(None)
 
     def highlight_cells (self, *args):
@@ -221,8 +221,8 @@ class SudokuGameDisplay (SudokuNumberGrid, GObject.GObject):
     def show_hint (self):
         min_options = 10;
         squares = []
-        for x in xrange(9):
-            for y in xrange(9):
+        for x in range(9):
+            for y in range(9):
                 if self.grid._get_(x, y) != 0:
                     continue
                 n_options = len(self.grid.possible_values(x, y))
@@ -476,7 +476,7 @@ class SudokuGameDisplay (SudokuNumberGrid, GObject.GObject):
         are stored in InteractiveGrid.conflicts
         '''
         # Return if there are no conflicts for this cell
-        if not self.grid.conflicts.has_key((x, y)):
+        if (x, y) not in self.grid.conflicts:
             return
         # Highlight the current cell
         self.__entries__[(x, y)].set_error_highlight(True)
@@ -673,7 +673,7 @@ class SudokuGameDisplay (SudokuNumberGrid, GObject.GObject):
         if check_conflicts:
             for xx, yy in self.grid.cleared_conflicts:
                 self.mark_impossible_implications(xx, yy, False)
-            if self.grid.conflicts.has_key((x, y)):
+            if (x, y) in self.grid.conflicts:
                 for xx, yy in self.grid.conflicts[(x, y)]:
                     self.mark_impossible_implications(xx, yy, False)
         # Update the hints if we need to
@@ -689,7 +689,7 @@ class SudokuGameDisplay (SudokuNumberGrid, GObject.GObject):
         tracker = self.tinfo.get_tracker(self.tinfo.showing_tracker)
         if not tracker:
             return ret
-        for (x, y), value in tracker.items():
+        for (x, y), value in list(tracker.items()):
             ret.append((x, y, value, self.tinfo.showing_tracker))
             self.remove(x, y)
             if self.grid and self.grid._get_(x, y):
@@ -705,7 +705,7 @@ class SudokuGameDisplay (SudokuNumberGrid, GObject.GObject):
         '''
         track = self.tinfo.get_tracker(self.tinfo.showing_tracker)
         if track:
-            for coord in track.keys():
+            for coord in list(track.keys()):
                 self.__entries__[coord].set_value(0, tracker_info.NO_TRACKER)
                 self.grid.remove(*coord)
                 self.remove_error_highlight()
@@ -725,7 +725,7 @@ class SudokuGameDisplay (SudokuNumberGrid, GObject.GObject):
         track = self.tinfo.get_tracker(self.tinfo.showing_tracker)
         if not track:
             return
-        for (x, y), value in track.items():
+        for (x, y), value in list(track.items()):
             self.__entries__[(x, y)].set_value(value, self.tinfo.showing_tracker)
             self.__entries__[(x, y)].recolor(self.tinfo.showing_tracker)
             # Add it to the underlying grid
@@ -760,7 +760,7 @@ if __name__ == '__main__':
         t.__entries__[(3, 1)].set_note_text('234', '12')
 
     def reproduce_foobared_rendering ():
-        from dialog_swallower import SwappableArea
+        from .dialog_swallower import SwappableArea
         sgd = SudokuGameDisplay()
         sgd.set_bg_color('black')
         vb = Gtk.VBox()
@@ -780,7 +780,7 @@ if __name__ == '__main__':
         vb.pack_start(swallower, padding = 12)
         window.add(vb)
         window.show_all()
-        from gtk_goodies.dialog_extras import MessageDialog
+        from .gtk_goodies.dialog_extras import MessageDialog
         md = MessageDialog(title = "Foo", label = "Foo", sublabel = "Bar "*12)
         swallower.run_dialog(md)
         hb.pack_start(sgd, padding = 6)
diff --git a/src/lib/gtk_goodies/Undo.py b/src/lib/gtk_goodies/Undo.py
index 594fba9..e4ae8fd 100644
--- a/src/lib/gtk_goodies/Undo.py
+++ b/src/lib/gtk_goodies/Undo.py
@@ -3,7 +3,7 @@ from gi.repository import Gtk
 import difflib,re
 DEBUG=False
 def debug (*args,**kwargs):
-    if DEBUG: print args,kwargs
+    if DEBUG: print(args,kwargs)
 
 class TooManyChanges (Exception):
     def __init__ (self, value):
@@ -99,7 +99,7 @@ class UndoableTextChange (UndoableObject):
         blocks=self.sm.get_matching_blocks()
         # we only are interested in similar blocks at different positions
         # (which tell us where the changes happened).
-        ch_blocks = filter(lambda x: x[0] != x[1] and x[2] != 0, blocks)
+        ch_blocks = [x for x in blocks if x[0] != x[1] and x[2] != 0]
         if ch_blocks and len(ch_blocks)>1:
             raise TooManyChanges("More than one block changed: %s in %s"%(ch_blocks,text2))
         if ch_blocks:
@@ -418,7 +418,7 @@ class MultipleUndoLists:
 
     def get_history (self):
         hid=self.get_current_id()
-        if self.histories.has_key(hid):
+        if hid in self.histories:
             #debug('Returning history %s for id %s'%([repr(i) for i in self.histories[hid]],hid),0)
             return self.histories[hid]
         else:
@@ -465,7 +465,7 @@ if __name__ == '__main__':
     w.connect('delete-event',lambda *args:Gtk.main_quit())
     def show_changes (*args):
         for c in uhl:
-            print c,' initial: ',c.initial_text,' current: ',c.text
+            print(c,' initial: ',c.initial_text,' current: ',c.text)
     ub.connect('clicked',lambda *args: debug('Undo clicked!',0))
     sc.connect('clicked',show_changes)
     rb.connect('clicked',lambda *args: debug('Redo clicked!',0))    
diff --git a/src/lib/gtk_goodies/dialog_extras.py b/src/lib/gtk_goodies/dialog_extras.py
index 4e75af1..e9128be 100644
--- a/src/lib/gtk_goodies/dialog_extras.py
+++ b/src/lib/gtk_goodies/dialog_extras.py
@@ -82,10 +82,10 @@ class ModalDialog (Gtk.Dialog):
         self.connect('response',self.response_cb)
 
     def response_cb (self, dialog, response, *params):
-        if self.responses.has_key(response):
+        if response in self.responses:
             self.responses[response]()
         else:
-            print 'WARNING, no response for ',response
+            print('WARNING, no response for ',response)
             
     def setup_expander (self, expander):
         label,body = expander
@@ -105,7 +105,7 @@ class ModalDialog (Gtk.Dialog):
             l.set_line_wrap(True)
             expander_vbox.pack_start(l, expand=False, fill=False)
         elif type(item) == [] or type(item) == ():
-            map(self._add_expander_item, expander_vbox, item)
+            list(map(self._add_expander_item, expander_vbox, item))
         else:
             expander_vbox.pack_start(item, True, True, 0)
             
@@ -140,7 +140,7 @@ class MessageDialog (Gtk.MessageDialog, ModalDialog):
 
     def setup_dialog (self, *args, **kwargs):
         kwargs['type']=self.message_type
-        if kwargs.has_key('title'):
+        if 'title' in kwargs:
             del kwargs['title']
         GObject.GObject.__init__(self, *args, **kwargs)
         if self.icon:
@@ -148,7 +148,7 @@ class MessageDialog (Gtk.MessageDialog, ModalDialog):
                 self.image.set_from_file(self.icon)
             else:
                 self.image.set_from_pixbuf(self.icon)
-        print "123"
+        print("123")
 
     def setup_label (self, label):
         label = '<span weight="bold" size="larger">%s</span>'%xml.sax.saxutils.escape(label)
diff --git a/src/lib/main.py b/src/lib/main.py
index 557e5d3..146a448 100644
--- a/src/lib/main.py
+++ b/src/lib/main.py
@@ -10,18 +10,18 @@ from gettext import gettext as _
 from gettext import ngettext
 
 import cairo
-import dialog_swallower
-import game_selector
-import gsudoku
-import printing
-import saver
-import sudoku_maker
-import timer
-import tracker_info
-from defaults import (APPNAME, APPNAME_SHORT, AUTHORS, COPYRIGHT, DESCRIPTION, DOMAIN, 
+from . import dialog_swallower
+from . import game_selector
+from . import gsudoku
+from . import printing
+from . import saver
+from . import sudoku_maker
+from . import timer
+from . import tracker_info
+from .defaults import (APPNAME, APPNAME_SHORT, AUTHORS, COPYRIGHT, DESCRIPTION, DOMAIN,
         IMAGE_DIR, MIN_NEW_PUZZLES, UI_DIR, VERSION, WEBSITE, WEBSITE_LABEL)
-from gtk_goodies import Undo, dialog_extras
-from simple_debug import simple_debug, options
+from .gtk_goodies import Undo, dialog_extras
+from .simple_debug import simple_debug, options
 
 def inactivate_new_game_etc (fun):
     def inactivate_new_game_etc_ (ui, *args, **kwargs):
@@ -45,7 +45,7 @@ def inactivate_new_game_etc (fun):
             if not action:
                 action = ui.uimanager.get_widget(p)
             if not action:
-                print 'No action at path', p
+                print('No action at path', p)
             else:
                 action.set_sensitive(False)
         ret = fun(ui, *args, **kwargs)
@@ -54,7 +54,7 @@ def inactivate_new_game_etc (fun):
             if not action:
                 action = ui.uimanager.get_widget(p)
             if not action:
-                print 'No action at path', p
+                print('No action at path', p)
             else:
                 action.set_sensitive(True)
         return ret
@@ -256,7 +256,7 @@ class UI:
         undo_widg = self.main_actions.get_action('Undo')
         redo_widg = self.main_actions.get_action('Redo')
         self.history = Undo.UndoHistoryList(undo_widg, redo_widg)
-        for entry in self.gsd.__entries__.values():
+        for entry in list(self.gsd.__entries__.values()):
             Undo.UndoableGenericWidget(entry, self.history,
                                        set_method = 'set_value_for_undo',
                                        get_method = 'get_value_for_undo',
@@ -310,7 +310,7 @@ class UI:
 
     def setup_toggles (self):
         # sync up toggles with gsettings values...
-        map(lambda tpl: self.wrap_toggle(*tpl),
+        list(map(lambda tpl: self.wrap_toggle(*tpl),
             [('always-show-hints',
               self.main_actions.get_action('AlwaysShowPossible')),
              ('show-impossible-implications',
@@ -321,7 +321,7 @@ class UI:
               self.main_actions.get_action('ToggleHighlight')),
              ('show-tracker',
               self.main_actions.get_action('Tracker')),
-             ])
+             ]))
 
     @simple_debug
     def start_worker_thread (self, *args):
@@ -348,7 +348,7 @@ class UI:
             delattr(self, 'dancer')
 
     def start_dancer (self):
-        import dancer
+        from . import dancer
         self.dancer = dancer.GridDancer(self.gsd)
         self.dancer.start_dancing()
 
@@ -674,9 +674,9 @@ class UI:
     def show_help (self, *args):
         try:
             Gtk.show_uri(self.w.get_screen(), "help:gnome-sudoku", Gtk.get_current_event_time())
-        except GObject.GError, error:
+        except GObject.GError as error:
             # FIXME: This should create a pop-up dialog
-            print _('Unable to display help: %s') % str(error)
+            print(_('Unable to display help: %s') % str(error))
 
     @simple_debug
     def print_game (self, *args):
@@ -781,7 +781,7 @@ class TrackerBox (Gtk.VBox):
 
     @simple_debug
     def add_tracker (self, *args, **keys):
-        if keys and keys.has_key('tracker_id'):
+        if keys and 'tracker_id' in keys:
             tracker_id = self.tinfo.create_tracker(keys['tracker_id'])
         else:
             tracker_id = self.tinfo.create_tracker()
@@ -964,7 +964,7 @@ class TrackerBox (Gtk.VBox):
 
 def start_game ():
     if options.debug:
-        print 'Starting GNOME Sudoku in debug mode'
+        print('Starting GNOME Sudoku in debug mode')
 
     ##  You must call g_thread_init() before executing any other GLib
     ##  functions in a threaded GLib program.
@@ -984,7 +984,7 @@ def start_game ():
             u.quit_cb()
 
 def profile_me ():
-    print 'Profiling GNOME Sudoku'
+    print('Profiling GNOME Sudoku')
     import tempfile, hotshot, hotshot.stats
     pname = os.path.join(tempfile.gettempdir(), 'GNOME_SUDOKU_HOTSHOT_PROFILE')
     prof = hotshot.Profile(pname)
@@ -992,4 +992,3 @@ def profile_me ():
     stats = hotshot.stats.load(pname)
     stats.strip_dirs()
     stats.sort_stats('time', 'calls').print_stats()
-
diff --git a/src/lib/number_box.py b/src/lib/number_box.py
index 0eb2188..419fbc0 100644
--- a/src/lib/number_box.py
+++ b/src/lib/number_box.py
@@ -4,10 +4,10 @@
 from gi.repository import Gtk,Gdk,GObject,Pango,PangoCairo
 import math
 import random
-import tracker_info
+from . import tracker_info
 from gettext import gettext as _
 
-from simple_debug import simple_debug
+from .simple_debug import simple_debug
 
 ERROR_HIGHLIGHT_COLOR = (1.0, 0, 0)
 
@@ -800,7 +800,7 @@ if __name__ == '__main__':
     def test_number_selector ():
         nselector = NumberSelector(default = 3)
         def tell_me (b):
-            print 'value->', b.get_value()
+            print('value->', b.get_value())
         nselector.connect('changed', tell_me)
         window.add(nselector)
 
diff --git a/src/lib/pausable.py b/src/lib/pausable.py
index 1787ecd..25592b4 100644
--- a/src/lib/pausable.py
+++ b/src/lib/pausable.py
@@ -1,12 +1,13 @@
 # -*- coding: utf-8 -*-
 import time
+import collections
 
 class MethodWrapper:
 
     def __call__ (self, cls):
         for attr in dir(cls):
             attrobj = getattr(cls, attr)
-            if callable(attrobj) and attr.find('__')!=0:
+            if isinstance(attrobj, collections.Callable) and attr.find('__')!=0:
                 setattr(cls, attr, self.wrap(attrobj))
 
     def wrap (self, f):
@@ -16,7 +17,7 @@ class MethodWrapper:
         return _
 
     def wrapper (self, *args, **kwargs):
-        print args, kwargs
+        print(args, kwargs)
 
 class PausableWrapper (MethodWrapper):
 
diff --git a/src/lib/printing.py b/src/lib/printing.py
index 1721cc0..44ea8b8 100644
--- a/src/lib/printing.py
+++ b/src/lib/printing.py
@@ -3,7 +3,7 @@ from gi.repository import Gtk,Gio
 import cairo
 import time
 import os.path
-import sudoku, gsudoku, saver, defaults
+from . import sudoku, gsudoku, saver, defaults
 from gettext import gettext as _
 
 def fit_squares_in_rectangle (width, height, n, margin = 0):
@@ -58,7 +58,7 @@ class SudokuPrinter:
         operation.set_n_pages(pages)
 
     def draw_page(self, operation, context, page_nr):
-        import sudoku_thumber
+        from . import sudoku_thumber
 
         margin = 25
         cr = context.get_cairo_context()
@@ -174,7 +174,7 @@ class GamePrinter:
                        ).get_active():
                 levels.append(cat)
         if not levels:
-            levels = sudoku.DifficultyRating.categories.keys()
+            levels = list(sudoku.DifficultyRating.categories.keys())
         nsudokus = self.sudokusToPrintSpinButton.get_adjustment().get_value()
         sudokus = self.sudoku_maker.get_puzzles(
             nsudokus,
@@ -182,7 +182,7 @@ class GamePrinter:
             new = not self.includeOldGamesToggle.get_active()
             )
         # Convert floating point difficulty into a label string
-        sudokus.sort(cmp = lambda a, b: cmp(a[1], b[1]))
+        sudokus.sort(key=lambda a: a[1])
         labels = {'easy': _('Easy'),
                   'medium': _('Medium'),
                   'hard': _('Hard'),
diff --git a/src/lib/saver.py b/src/lib/saver.py
index 5470751..45f5c58 100644
--- a/src/lib/saver.py
+++ b/src/lib/saver.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
 from gi.repository import Gtk
 import pickle, types, os, errno
-import defaults
-from gtk_goodies.dialog_extras import show_message_dialog
+from . import defaults
+from .gtk_goodies.dialog_extras import show_message_dialog
 from gettext import gettext as _
-import tracker_info
+from . import tracker_info
 
 SAVE_ATTRIBUTES = [('gsd.hints'),
                    ('gsd.impossible_hints'),
@@ -52,7 +52,7 @@ def jar_game (ui):
     jar['game'] = ui.gsd.grid.to_string()
     jar['tracker_info'] = tracker_info.TrackerInfo().save()
     jar['tracked_notes'] = []
-    for e in ui.gsd.__entries__.values():
+    for e in list(ui.gsd.__entries__.values()):
         if e.top_note_list or e.bottom_note_list:
             jar['tracked_notes'].append((e.x, e.y, e.top_note_list, e.bottom_note_list))
     for attr in SAVE_ATTRIBUTES:
@@ -70,26 +70,26 @@ def open_game (ui, jar):
     # The 'notes' and 'trackers' sections are for transition from the old
     # style tracker storage.  The tracker values and notes are stored in the
     # 'tracked_notes' and 'tracker_info' sections now.
-    if jar.has_key('notes') and jar['notes']:
+    if 'notes' in jar and jar['notes']:
         for x, y, top, bot in jar['notes']:
             ui.gsd.__entries__[(x, y)].set_note_text(top, bot)
-    if jar.has_key('trackers'):
-        for tracker, tracked in jar.get('trackers', {}).items():
+    if 'trackers' in jar:
+        for tracker, tracked in list(jar.get('trackers', {}).items()):
             # add 1 tracker per existing tracker...
             ui.tracker_ui.add_tracker()
             for x, y, val in tracked:
                 tinfo.add_trace(x, y, val)
     set_value_from_jar(ui, jar)
-    if jar.has_key('tracking'):
-        for tracker, tracking in jar.get('tracking', {}).items():
+    if 'tracking' in jar:
+        for tracker, tracking in list(jar.get('tracking', {}).items()):
             if tracking:
                 ui.tracker_ui.select_tracker(tracker)
-    if jar.has_key('tracked_notes') and jar['tracked_notes']:
+    if 'tracked_notes' in jar and jar['tracked_notes']:
         for x, y, top, bot in jar['tracked_notes']:
             ui.gsd.__entries__[(x, y)].set_notelist(top, bot)
-    if jar.has_key('tracker_info'):
+    if 'tracker_info' in jar:
         trackers = jar['tracker_info'][2]
-        for tracking in trackers.keys():
+        for tracking in list(trackers.keys()):
             ui.tracker_ui.add_tracker(tracker_id = tracking)
         tinfo.load(jar['tracker_info'])
         ui.tracker_ui.select_tracker(tinfo.current_tracker)
@@ -99,23 +99,19 @@ def open_game (ui, jar):
     ui.gsd.update_all_notes()
 
 def pickle_game (ui, target):
-    close_me = False
-    if type(target) in types.StringTypes:
-        target = file(target, 'w')
-        close_me = True
     to_dump = jar_game(ui)
-    pickle.dump(to_dump, target)
-    if close_me:
-        target.close()
+    if isinstance(target, str):
+        with open(target, 'wb'):
+            pickle.dump(to_dump, target)
+    else:
+        pickle.dump(to_dump, target)
 
 def unpickle_game (ui, target):
-    close_me = False
-    if type(target) == str:
-        target = file(target, 'r')
-        close_me = True
-    open_game(ui, pickle.load(target))
-    if close_me:
-        target.close()
+    if isinstance(target, str):
+        with open(target, 'rb'):
+            open_game(ui, pickle.load(target))
+    else:
+        open_game(ui, pickle.load(target))
 
 class SudokuTracker:
 
@@ -149,7 +145,7 @@ class SudokuTracker:
         if not os.path.exists(path):
             try:
                 os.makedirs(path)
-            except OSError, e:
+            except OSError as e:
                 if e.errno == errno.ENOSPC:
                     show_message_dialog(
                         title = _('No Space'),
@@ -178,10 +174,10 @@ class SudokuTracker:
         jar = jar_game(ui)
         filename = os.path.join(self.save_path, self.get_filename(jar['game']))
         try:
-            outfi = file(filename, 'w')
+            outfi = open(filename, 'wb')
             pickle.dump(jar, outfi)
             outfi.close()
-        except (OSError, IOError), e:
+        except (OSError, IOError) as e:
             show_message_dialog(
                 title = _('Unable to save game.'),
                 label = _('Unable to save game.'),
@@ -203,10 +199,10 @@ class SudokuTracker:
         try:
             filename = os.path.join(self.finished_path,
                                     self.get_filename(jar['game']))
-            outfi = file(filename, 'w')
+            outfi = open(filename, 'wb')
             pickle.dump(jar, outfi)
             outfi.close()
-        except (OSError, IOError), e:
+        except (OSError, IOError) as e:
             show_message_dialog(
                 title = _('Unable to mark game as finished.'),
                 label = _('Unable to mark game as finished.'),
@@ -224,7 +220,7 @@ class SudokuTracker:
             ofi = open(list_of_finished_games, 'a')
             ofi.write(jar['game'].split('\n')[0]+'\n')
             ofi.close()
-        except (OSError, IOError), e:
+        except (OSError, IOError) as e:
             show_message_dialog(
                 title = _('Sudoku unable to mark game as finished.'),
                 label = _('Sudoku unable to mark game as finished.'),
@@ -256,16 +252,16 @@ class SudokuTracker:
         for f in files:
             f = os.path.join(self.save_path, f)
             try:
-                jar = pickle.load(file(f, 'r'))
+                jar = pickle.load(open(f, 'rb'))
             except:
-                print 'Warning: could not read file', f
+                print('Warning: could not read file', f)
             else:
                 update_saved_attributes(jar)
                 if self.is_valid(jar):
                     jar['saved_at'] = os.stat(f)[8]
                     games.append(jar)
                 else:
-                    print 'Warning: malformed save game', f
+                    print('Warning: malformed save game', f)
         return games
 
     def is_valid (self, jar):
diff --git a/src/lib/simple_debug.py b/src/lib/simple_debug.py
index d5573a6..77e9376 100644
--- a/src/lib/simple_debug.py
+++ b/src/lib/simple_debug.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 import optparse
-import defaults
+from . import defaults
 
 parser = optparse.OptionParser(
     version=defaults.VERSION,
@@ -24,7 +24,7 @@ options, args = parser.parse_args()
 if options.debug:
     def simple_debug (f):
         def _ (self, *args, **kwargs):
-            print self.__class__, f.__name__, args, kwargs
+            print(self.__class__, f.__name__, args, kwargs)
             return f(self, *args, **kwargs)
         return _
 
@@ -33,8 +33,8 @@ elif options.walk:
     def simple_debug (f):
         def _ (self, *args, **kwargs):
             if (self.__class__, f.__name__) not in ff:
-                print self.__class__, f.__name__, args, kwargs
-                if raw_input('Hit return to step forward (hit i to ignore this function): ')=='i':
+                print(self.__class__, f.__name__, args, kwargs)
+                if input('Hit return to step forward (hit i to ignore this function): ')=='i':
                     ff.append((self.__class__, f.__name__))
             return f(self, *args, **kwargs)
         return _
diff --git a/src/lib/sudoku.py b/src/lib/sudoku.py
index 7d28608..394c1d1 100644
--- a/src/lib/sudoku.py
+++ b/src/lib/sudoku.py
@@ -3,7 +3,7 @@ import random
 import math
 import re
 from gettext import gettext as _
-import defaults
+from . import defaults
 
 GROUP_SIZE = 9
 
@@ -11,7 +11,7 @@ TYPE_ROW = 0
 TYPE_COLUMN = 1
 TYPE_BOX = 2
 
-digit_set = range(1, GROUP_SIZE + 1)
+digit_set = list(range(1, GROUP_SIZE + 1))
 sets = [digit_set] * 9
 
 def is_set (row):
@@ -82,7 +82,7 @@ class ParallelDict (dict):
         for i in v:
             if i == k:
                 continue
-            if self.has_key(i):
+            if i in self:
                 self[i].add(k)
             else:
                 dict.__setitem__(self, i, set([k]))
@@ -93,7 +93,7 @@ class ParallelDict (dict):
         for i in v:
             if i == k:
                 continue
-            if self.has_key(i):
+            if i in self:
                 # Make sure we have a reference to i. If we don't
                 # something has gone wrong... but according to bug
                 # 385937 this has gone wrong at least once, so we'd
@@ -130,7 +130,7 @@ class SudokuGrid(object):
         for n, col in enumerate([[(x, y) for y in range(self.group_size)] for x in range(self.group_size)]):
             self.col_coords[n] = col
         if grid:
-            if isinstance(grid, basestring):
+            if isinstance(grid, str):
                 g = re.split("\s+", grid)
                 side = int(math.sqrt(len(g)))
                 grid = []
@@ -162,7 +162,7 @@ class SudokuGrid(object):
                 try:
                     self.remove(x, y)
                 except:
-                    print 'Strange: problem with add(', x, y, val, force, ')'
+                    print('Strange: problem with add(', x, y, val, force, ')')
                     import traceback
                     traceback.print_exc()
             else:
@@ -203,12 +203,12 @@ class SudokuGrid(object):
         return self.gen_set - self.rows[y] - self.cols[x] - self.boxes[self.box_by_coords[(x, y)]]
 
     def pretty_print (self):
-        print 'SUDOKU'
+        print('SUDOKU')
         for r in self.grid:
             for i in r:
-                print i,
-            print
-        print
+                print(i, end=' ')
+            print()
+        print()
 
     def populate_from_grid (self, grid):
         for y, row in enumerate(grid):
@@ -347,10 +347,10 @@ class SudokuSolver (SudokuGrid):
         for label, coord_dic, filled_dic in [('Column', self.col_coords, self.cols),
                                            ('Row', self.row_coords, self.rows),
                                            ('Box', self.box_coords, self.boxes)]:
-            for n, coord_set in coord_dic.items():
+            for n, coord_set in list(coord_dic.items()):
                 skip_set = False
                 for coord in coord_set:
-                    if self.conflicts.has_key(coord):
+                    if coord in self.conflicts:
                         skip_set = True
                         break
                 if skip_set:
@@ -360,19 +360,19 @@ class SudokuSolver (SudokuGrid):
                     val = self._get_(*coord)
                     if val:
                         # We already have this value set...
-                        if needs.has_key(val):
+                        if val in needs:
                             del needs[val]
                     else:
                         # Otherwise, register ourselves as possible
                         # for each number we could be
                         for v in self.possible_values(*coord):
                             # if we don't yet have a possible number, plug ourselves in
-                            if needs.has_key(v):
+                            if v in needs:
                                 if not needs[v]:
                                     needs[v] = coord
                                 else:
                                     del needs[v]
-                for n, coords in needs.items():
+                for n, coords in list(needs.items()):
                     if not coords:
                         raise UnsolvablePuzzle('Missing a %s in %s' % (n, label))
                     else:
@@ -386,17 +386,17 @@ class SudokuSolver (SudokuGrid):
         return changed
 
     def fill_deterministically (self):
-        poss = self.calculate_open_squares().items()
-        one_choice = filter(lambda x: len(x[1]) == 1, poss)
+        poss = list(self.calculate_open_squares().items())
+        one_choice = [x for x in poss if len(x[1]) == 1]
         retval = []
         for coords, choices in one_choice:
             if self.verbose:
-                print 'Deterministically adding ', coords, choices
+                print('Deterministically adding ', coords, choices)
             val = choices.pop()
             self.add(coords[0], coords[1], val)
             retval.append([(coords[0], coords[1]), val])
         if self.verbose:
-            print 'deterministically returning ', retval
+            print('deterministically returning ', retval)
         return retval
 
     def solve (self):
@@ -407,7 +407,7 @@ class SudokuSolver (SudokuGrid):
         while not self.guess_least_open_square():
             pass
         if self.verbose:
-            print 'Solved!\n', self
+            print('Solved!\n', self)
         self.solving = False
         self.solved = True
 
@@ -430,19 +430,19 @@ class SudokuSolver (SudokuGrid):
 
     def has_unique_solution (self):
         sf = self.solution_finder()
-        sf.next()
-        if sf.next():
+        next(sf)
+        if next(sf):
             return False
         else:
             return True
 
     def guess_least_open_square (self):
         # get open squares and check them
-        poss = self.calculate_open_squares().items()
+        poss = list(self.calculate_open_squares().items())
         # if there are no open squares, we're done!
         if not poss:
             if self.verbose:
-                print 'Solved!'
+                print('Solved!')
             return True
         # otherwise, find the possibility with the least possibilities
         poss.sort(lambda a, b: len(a[1]) > len(b[1]) and 1 or len(a[1]) < len(b[1]) and -1 or \
@@ -481,7 +481,7 @@ class SudokuSolver (SudokuGrid):
             self.trail.append('Problem filling coordinates after guess')
             self.unwrap_guess(guess_obj)
             return self.guess_least_open_square()
-        if set([]) in self.calculate_open_squares().values():
+        if set([]) in list(self.calculate_open_squares().values()):
             self.trail.append('Guess leaves us with impossible squares.')
             self.unwrap_guess(guess_obj)
             return self.guess_least_open_square()
@@ -490,7 +490,7 @@ class SudokuSolver (SudokuGrid):
         self.trail.append(('-', guess))
         if self._get_(guess.x, guess.y):
             self.remove(guess.x, guess.y)
-        for consequence in guess.consequences.keys():
+        for consequence in list(guess.consequences.keys()):
             if self._get_(*consequence):
                 self.remove(*consequence)
         for child in guess.children:
@@ -533,7 +533,7 @@ class InteractiveSudoku (SudokuSolver):
         broken = set()
         for coord_set in [row_cells, col_cells, box_cells]:
             # just work on the open squares
-            coord_set = filter(lambda coords: not self._get_(*coords), coord_set)
+            coord_set = [coords for coords in coord_set if not self._get_(*coords)]
             for coords in coord_set:
                 if not self.possible_values(*coords):
                     broken.add(coords)
@@ -625,7 +625,7 @@ class InteractiveSudoku (SudokuSolver):
         # Pop the conflicts resolved by this removal
         self.cleared_conflicts = []
         errors_removed = []
-        if self.conflicts.has_key((x, y)):
+        if (x, y) in self.conflicts:
             errors_removed = self.conflicts[(x, y)]
             del self.conflicts[(x, y)]
         # If there are no conflicts for this cell then just remove it in from
@@ -650,7 +650,7 @@ class InteractiveSudoku (SudokuSolver):
         for coord in errors_removed:
             # If it is not an error by some other pairing, append it to a list
             # of conflicts that were actually cleared by this removal.
-            if not self.conflicts.has_key(coord):
+            if coord not in self.conflicts:
                 self.cleared_conflicts.append(coord)
             # When a conflict remains, we need to correct the rows, cols, and
             # boxes arrays properly
@@ -727,7 +727,7 @@ class DifficultyRating:
         self.value = self.calculate()
 
     def count_values (self, dct):
-        kk = dct.keys()
+        kk = list(dct.keys())
         kk.sort()
         return [len(dct[k]) for k in kk]
 
@@ -756,7 +756,7 @@ class DifficultyRating:
                           ('Ease by elimination', self.elimination_ease),
                           ('Calculated difficulty', self.value)
                           ]:
-            print name, ': ', stat
+            print(name, ': ', stat)
 
     def value_category (self):
         """Get category string, without i18n or capitalization
@@ -773,7 +773,7 @@ class DifficultyRating:
             return 'easy'
 
 def get_difficulty_category (diff_float):
-    for category, range in DifficultyRating.categories.items():
+    for category, range in list(DifficultyRating.categories.items()):
         if range[0] <= diff_float < range[1]:
             return category
 
@@ -836,9 +836,8 @@ class SudokuRater (SudokuSolver):
             self.solve()
         self.clues = 0
         # Add up the number of our initial clues through some nifty mapping calls
-        map(lambda r: map(lambda i: setattr(self, 'clues', self.clues.__add__(i and 1 or 0)),
-                          r),
-            self.virgin.grid)
+        list(map(lambda r: [setattr(self, 'clues', self.clues.__add__(i and 1 or 0)) for i in r],
+            self.virgin.grid))
         self.numbers_added = self.group_size ** 2 - self.clues
         rating = DifficultyRating(self.fill_must_fillables,
                                   self.elimination_fillables,
@@ -854,7 +853,7 @@ class GuessList (list):
 
 
     def guesses_for_coord (self, x, y):
-        return set([guess.val for guess in filter(lambda guess: guess.x == x and guess.y == y, self)])
+        return set([guess.val for guess in [guess for guess in self if guess.x == x and guess.y == y]])
 
     def remove_children (self, guess):
         removed = []
@@ -899,7 +898,7 @@ class Guess:
         s =  "<Guess (%s, %s)=%s" % (self.x, self.y, self.val)
         if self.consequences:
             s +=   " implies: "
-            s += ", ".join(["%s->%s" % (k, v) for k, v in self.consequences.items()])
+            s += ", ".join(["%s->%s" % (k, v) for k, v in list(self.consequences.items())])
         s += ">"
         return s
 
diff --git a/src/lib/sudoku_maker.py b/src/lib/sudoku_maker.py
index 360c8ba..72a50d4 100644
--- a/src/lib/sudoku_maker.py
+++ b/src/lib/sudoku_maker.py
@@ -1,12 +1,12 @@
 # -*- coding: utf-8 -*-
 import os, shutil
 import errno
-import sudoku
+from . import sudoku
 import random
 import time
-import pausable
+from . import pausable
 import threading
-import defaults
+from . import defaults
 
 class SudokuGenerator:
 
@@ -149,13 +149,13 @@ class SudokuGenerator:
             self.rated_puzzles.append((sudoku_grid, d))
             return d
         except:
-            print 'Impossible!'
-            print 'Puzzle was:'
-            print solver.virgin
-            print 'Solution: ',
-            print self.start_grid
-            print 'Puzzle foobared in following state:',
-            print solver
+            print('Impossible!')
+            print('Puzzle was:')
+            print(solver.virgin)
+            print('Solution: ', end=' ')
+            print(self.start_grid)
+            print('Puzzle foobared in following state:', end=' ')
+            print(solver)
             raise
 
     def is_unique (self, sudoku_grid):
@@ -243,7 +243,7 @@ class SudokuGenerator:
         ret = []
         for i in range(n):
             #print 'Working on puzzle ',i
-            ret.append(ug.next())
+            ret.append(next(ug))
             #print 'Got one!'
         return ret
 
@@ -319,7 +319,7 @@ class SudokuMaker:
     def load (self):
         try:
             os.makedirs(self.pickle_to)
-        except os.error, e:
+        except os.error as e:
             if e.errno != errno.EEXIST:
                 return
         for cat in sudoku.DifficultyRating.categories:
@@ -329,16 +329,17 @@ class SudokuMaker:
                 try:
                     shutil.copy(source, target)
                 except:
-                    print 'Problem copying base puzzles'
-                    print 'Attempted to copy from %s to %s' % (source, target)
+                    print('Problem copying base puzzles')
+                    print('Attempted to copy from %s to %s' % (source, target))
 
     def get_pregenerated (self, difficulty):
         fname = os.path.join(self.pickle_to, difficulty.replace(' ', '_'))
         try:
-            lines = file(fname).readlines()
-        except IOError, e:
+            with open(fname, 'r') as lines_file:
+                lines = lines_file.readlines()
+        except IOError as e:
             if e.errno != errno.ENOENT:
-                print 'Error reading pregenerated puzzles for difficulty \'%s\': %s' % (difficulty, 
e.strerror)
+                print('Error reading pregenerated puzzles for difficulty \'%s\': %s' % (difficulty, 
e.strerror))
             return []
         else:
             return [line.strip() for line in lines]
@@ -408,18 +409,18 @@ class SudokuMaker:
                 try:
                     p, d = line.split('\t')
                 except ValueError:
-                    print 'WARNING: invalid line %s in file %s' % (line, files[lev])
+                    print('WARNING: invalid line %s in file %s' % (line, files[lev]))
                     continue
                 if sudoku.is_valid_puzzle(p):
                     if (p not in exclude) and (not new or p not in self.played):
                         puzzles.append((p, float(d)))
                         i += 1
                 else:
-                    print 'WARNING: invalid puzzle %s in file %s' % (p, files[lev])
+                    print('WARNING: invalid puzzle %s in file %s' % (p, files[lev]))
             il += 1
         if i < n:
-            print 'WARNING: Not able to provide %s puzzles in levels %s' % (n, levels)
-            print 'WARNING: Generate more puzzles if you really need this many puzzles!'
+            print('WARNING: Not able to provide %s puzzles in levels %s' % (n, levels))
+            print('WARNING: Generate more puzzles if you really need this many puzzles!')
         return puzzles
 
     def get_puzzles (self, n, levels, new = True, randomize = True,
@@ -462,18 +463,18 @@ class SudokuMaker:
                 try:
                     p, d = line.split('\t')
                 except ValueError:
-                    print 'WARNING: invalid line %s in file %s' % (line, files[lev])
+                    print('WARNING: invalid line %s in file %s' % (line, files[lev]))
                     continue
                 if sudoku.is_valid_puzzle(p):
                     if (p not in exclude) and (not new or p not in self.played):
                         puzzles.append((p, float(d)))
                         i += 1
                 else:
-                    print 'WARNING: invalid puzzle %s in file %s' % (p, files[lev])
+                    print('WARNING: invalid puzzle %s in file %s' % (p, files[lev]))
             il += 1
         if i < n:
-            print 'WARNING: Not able to provide %s puzzles in levels %s' % (n, levels)
-            print 'WARNING: Generate more puzzles if you really need this many puzzles!'
+            print('WARNING: Not able to provide %s puzzles in levels %s' % (n, levels))
+            print('WARNING: Generate more puzzles if you really need this many puzzles!')
 
         return puzzles
 
@@ -493,7 +494,7 @@ class SudokuMaker:
         open_files = {}
         for n in range(self.batch_size):
             #print 'start next item...',n
-            puz, diff = ug.next()
+            puz, diff = next(ug)
             #print "GENERATED ",puz,diff
             if (diffs == None or diff.value_category() in diffs):
                 puzstring = puz.to_string()
@@ -508,12 +509,12 @@ class SudokuMaker:
                 existing = self.get_pregenerated(diff.value_category())
                 if not puzstring in existing:
                     try:
-                        outfi = file(outpath, 'a')
+                        outfi = open(outpath, 'a')
                         outfi.write(puzstring+'\t'+str(diff.value)+'\n')
                         outfi.close()
                         self.n_available_sudokus[diff.value_category()]+=1
-                    except IOError, e:
-                        print 'Error appending pregenerated puzzle: %s' % e.strerror
+                    except IOError as e:
+                        print('Error appending pregenerated puzzle: %s' % e.strerror)
 
     def pause (self, *args):
         if hasattr(self, 'new_generator'):
@@ -580,16 +581,16 @@ elif False:
     terminate: kill thread
     quit: to quit
     """
-    print usage
+    print(usage)
     while 1:
-        inp = raw_input('choose:')
+        inp = input('choose:')
         if inp == 'run':
             t = threading.Thread(target = sm.make_batch)
             t.start()
         elif inp == 'show':
-            print sm.puzzles
+            print(sm.puzzles)
         elif inp == 'len':
-            print len(sm.puzzles)
+            print(len(sm.puzzles))
         elif inp == 'pause':
             sm.new_generator.pause()
         elif inp == 'resume':
@@ -603,5 +604,5 @@ elif False:
             try:
                 getattr(sm, inp)()
             except:
-                print usage
+                print(usage)
         
diff --git a/src/lib/tracker_info.py b/src/lib/tracker_info.py
index 798c4ac..0b52080 100644
--- a/src/lib/tracker_info.py
+++ b/src/lib/tracker_info.py
@@ -70,17 +70,17 @@ class TrackerInfo(object):
         '''
         if not tracker_id:
             tracker_id = 0
-        while self._tracks.has_key(tracker_id):
+        while tracker_id in self._tracks:
             tracker_id += 1
         self._tracks[tracker_id] = {}
         return tracker_id
 
     def get_tracker(self, tracker_id):
-        if self._tracks.has_key(tracker_id):
+        if tracker_id in self._tracks:
             return self._tracks[tracker_id]
 
     def delete_tracker(self, tracker_id):
-        if self._tracks.has_key(tracker_id):
+        if tracker_id in self._tracks:
             del self._tracks[tracker_id]
 
     def reset (self):
@@ -115,9 +115,9 @@ class TrackerInfo(object):
         if tracker_id == NO_TRACKER:
             return None
         # Create a random color for new trackers that are beyond the defaults
-        if not self._colors.has_key(tracker_id):
+        if tracker_id not in self._colors:
             random_color = self._colors[0]
-            while random_color in self._colors.values():
+            while random_color in list(self._colors.values()):
                 # If we have generated all possible colors, this will
                 # enter an infinite loop
                 random_color = (random.randint(0, 100)/100.0,
@@ -157,7 +157,7 @@ class TrackerInfo(object):
         if to_tracker == NO_TRACKER:
             return
         # Make sure the dictionary is available for the tracker.
-        if not self._tracks.has_key(to_tracker):
+        if to_tracker not in self._tracks:
             self._tracks[to_tracker] = {}
         # Add it
         self._tracks[to_tracker][(x, y)] = value
@@ -170,12 +170,12 @@ class TrackerInfo(object):
         to remove tracked values from a particular tracker only.
         '''
         if from_tracker == None:
-            from_tracks = self._tracks.keys()
+            from_tracks = list(self._tracks.keys())
         else:
             from_tracks = [from_tracker]
         # Delete them
         for tracker in from_tracks:
-            if self._tracks.has_key(tracker) and self._tracks[tracker].has_key((x, y)):
+            if tracker in self._tracks and (x, y) in self._tracks[tracker]:
                 del self._tracks[tracker][(x, y)]
 
     def get_trackers_for_cell(self, x, y):
@@ -186,8 +186,8 @@ class TrackerInfo(object):
         reset_trackers_for_cell().
         '''
         ret = []
-        for tracker, track in self._tracks.items():
-            if track.has_key((x, y)):
+        for tracker, track in list(self._tracks.items()):
+            if (x, y) in track:
                 ret.append((tracker, track[(x, y)]))
         return ret
 
@@ -198,8 +198,8 @@ class TrackerInfo(object):
         tracked values the list created by get_trackers_for_cell().
         '''
         # Remove all the current traces
-        for tracker, track in self._tracks.items():
-            if track.has_key((x, y)):
+        for tracker, track in list(self._tracks.items()):
+            if (x, y) in track:
                 del self._tracks[tracker][(x, y)]
         # Add the old ones back
         for tracker, value in old_trackers:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]