Patch to replace the use of collections.Callable to callable(); the former was
already deprecated for a while and remove in Python 3.10
diff --git a/contrib/MCListbox.py b/contrib/MCListbox.py
index ca3b313..db08908 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/contrib/MCListbox.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/contrib/MCListbox.py
@@ -29,7 +29,6 @@
 import string
 import tkinter
 import Pmw
-import collections
 
 class MultiColumnListbox(Pmw.MegaWidget):
     def __init__(self, parent = None, **kw):
@@ -641,7 +640,7 @@ class MultiColumnListbox(Pmw.MegaWidget):
         self._cursel = [row]
 
         cmd = self['command']
-        if isinstance(cmd, collections.Callable):
+        if callable(cmd):
             cmd()
 
 
@@ -649,13 +648,13 @@ class MultiColumnListbox(Pmw.MegaWidget):
     def _cellframedblclick(self, event):
         #print 'double click cell frame'
         cmd = self['dblclickcommand']
-        if isinstance(cmd, collections.Callable):
+        if callable(cmd):
             cmd()
 
     def _celldblclick(self, event):
         #print 'double click cell'
         cmd = self['dblclickcommand']
-        if isinstance(cmd, collections.Callable):
+        if callable(cmd):
             cmd()
 
 if __name__ == '__main__':
diff --git a/contrib/PmwFileDialog.py b/contrib/PmwFileDialog.py
index b510516..a007d06 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/contrib/PmwFileDialog.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/contrib/PmwFileDialog.py
@@ -18,7 +18,6 @@ __version__ = '$Id: PmwFileDialog.py,v 1.2.2.1 2012/08/04 00:56:51 adyh Exp $'
 ################################################################################
 import os,fnmatch,time
 import tkinter,Pmw
-import collections
 #Pmw.setversion("0.8.5")
 
 def _errorpop(master,text):
@@ -224,7 +223,7 @@ class PmwFileDialog(Pmw.Dialog):
         self.configure(directory=dir,filename=value)
 
         c=self['command']
-        if isinstance(c, collections.Callable):
+        if callable(c):
             c()
 
     def newfilename(self):
diff --git a/contrib/PmwFullTimeCounter.py b/contrib/PmwFullTimeCounter.py
index 8bc6d17..730b088 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/contrib/PmwFullTimeCounter.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/contrib/PmwFullTimeCounter.py
@@ -5,7 +5,6 @@ import sys
 import time
 import tkinter
 import Pmw
-import collections
 
 class FullTimeCounter(Pmw.MegaWidget):
     """Up-down counter
@@ -461,7 +460,7 @@ class FullTimeCounter(Pmw.MegaWidget):
 
     def invoke(self, event = None):
         cmd = self['command']
-        if isinstance(cmd, collections.Callable):
+        if callable(cmd):
             cmd()
 
     def destroy(self):
diff --git a/contrib/TreeBrowser.py b/contrib/TreeBrowser.py
index 17cccbc..a191c9f 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/contrib/TreeBrowser.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/contrib/TreeBrowser.py
@@ -34,7 +34,6 @@
 import types
 import tkinter
 import Pmw
-import collections
 
 
 class _Branching:
@@ -292,7 +291,7 @@ class _LeafNode(Pmw.MegaWidget):
             self._labelWidget.configure(label_foreground = self['selectforeground'])
         #self._viewButton.configure(background = self._selectbg)
         cmd = self['selectcommand']
-        if isinstance(cmd, collections.Callable):
+        if callable(cmd):
             cmd(self)
 
     def _unhighlight(self):
@@ -302,7 +301,7 @@ class _LeafNode(Pmw.MegaWidget):
             self._labelWidget.configure(label_foreground = self['foreground'])
         #self._viewButton.configure(background = self._bg)
         cmd = self['deselectcommand']
-        if isinstance(cmd, collections.Callable):
+        if callable(cmd)
             cmd(self)
 
     def _setlast(self, last):
diff --git a/lib/PmwBalloon.py b/lib/PmwBalloon.py
index b17917d..73c3439 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwBalloon.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwBalloon.py
@@ -2,7 +2,6 @@ import os
 import string
 import tkinter
 import Pmw
-import collections
 
 class Balloon(Pmw.MegaToplevel):
     def __init__(self, parent = None, **kw):
@@ -201,7 +200,7 @@ class Balloon(Pmw.MegaToplevel):
     def showstatus(self, statusHelp):
         if self['state'] in ('status', 'both'):
             cmd = self['statuscommand']
-            if isinstance(cmd, collections.Callable):
+            if callable(cmd):
                 cmd(statusHelp)
 
     def clearstatus(self):
diff --git a/lib/PmwBase.py b/lib/PmwBase.py
index 2223f04..fff8237 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwBase.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwBase.py
@@ -20,11 +20,10 @@ import sys
 import traceback
 import types
 import tkinter
-import collections
 
 # tkinter 8.5 -> 8.6 fixed a problem in which selected indexes
 # were reported as strings instead of ints
-# by default emulate the same functionality so we don't break 
+# by default emulate the same functionality so we don't break
 # existing interfaces but allow for easy switching
 #_forceTkinter85Compatibility = True
 
@@ -32,7 +31,7 @@ import collections
 #    global _forceTkinter85Compatibility
 #    if isinstance(value, bool):
 #        _forceTkinter85Compatibility = value and tkinter.TkVersion > 8.5
-        
+
 #def emulateTk85():
 #    global _forceTkinter85Compatibility
 #    return _forceTkinter85Compatibility
@@ -996,7 +995,7 @@ class MegaToplevel(MegaArchetype):
         # Initialise the base class (after defining the options).
         #MegaArchetype.__init__(self, parent, tkinter.Toplevel)
         super().__init__(parent, tkinter.Toplevel)
-        
+
         # Initialise instance.
 
         # Set WM_DELETE_WINDOW protocol, deleting any old callback, so
@@ -1174,7 +1173,7 @@ class MegaToplevel(MegaArchetype):
 
         pushgrab(self._hull, globalMode, self.deactivate)
         command = self['activatecommand']
-        if isinstance(command, collections.Callable):
+        if callable(command):
             command()
         self.wait_variable(self._wait)
 
@@ -1192,7 +1191,7 @@ class MegaToplevel(MegaArchetype):
         popgrab(self._hull)
 
         command = self['deactivatecommand']
-        if isinstance(command, collections.Callable):
+        if callable(command):
             command()
 
         self.withdraw()
@@ -1237,7 +1236,7 @@ def tracetk(root = None, on = 1, withStackTrace = 0, file=None):
 
     if root is None:
         root = tkinter._default_root
-    
+
     _withStackTrace = withStackTrace
     _traceTk = on
     if on == 1:
@@ -1382,7 +1381,7 @@ def _addRootToToplevelBusyInfo():
         _addToplevelBusyInfo(root)
 
 def busycallback(command, updateFunction = None):
-    if not isinstance(command, collections.Callable):
+    if not callable(command):
         raise ValueError('cannot register non-command busy callback %s %s' % \
                 (repr(command), type(command)))
     wrapper = _BusyWrapper(command, updateFunction)
@@ -1649,7 +1648,7 @@ class _BusyWrapper:
 
         # Call update before hiding the busy windows to clear any
         # events that may have occurred over the busy windows.
-        if isinstance(self._updateFunction, collections.Callable):
+        if callable(self._updateFunction):
             self._updateFunction()
 
         hidebusycursor()
diff --git a/lib/PmwComboBox.py b/lib/PmwComboBox.py
index 6d27dd8..36b817d 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwComboBox.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwComboBox.py
@@ -5,7 +5,6 @@ import string
 import types
 import tkinter
 import Pmw
-import collections
 
 class ComboBox(Pmw.MegaWidget):
     def __init__(self, parent = None, **kw):
@@ -32,14 +31,14 @@ class ComboBox(Pmw.MegaWidget):
 
         # Create the components.
         interior = self.interior()
-        
+
         self._entryfield = self.createcomponent('entryfield',
                 (('entry', 'entryfield_entry'),), None,
                 Pmw.EntryField, (interior,))
         self._entryfield.grid(column=2, row=2, sticky=self['sticky'])
         interior.grid_columnconfigure(2, weight = 1)
         self._entryWidget = self._entryfield.component('entry')
-        
+
         if self['dropdown']:
             self._isPosted = 0
             interior.grid_rowconfigure(2, weight = 1)
@@ -275,7 +274,7 @@ class ComboBox(Pmw.MegaWidget):
             self._entryfield.setentry(item)
 
         cmd = self['selectioncommand']
-        if isinstance(cmd, collections.Callable):
+        if callable(cmd):
             if event is None:
                 # Return result of selectioncommand for invoke() method.
                 return cmd(item)
diff --git a/lib/PmwCounter.py b/lib/PmwCounter.py
index 65b4b28..c069e5a 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwCounter.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwCounter.py
@@ -3,7 +3,6 @@ import sys
 import types
 import tkinter
 import Pmw
-import collections
 
 class Counter(Pmw.MegaWidget):
 
@@ -206,7 +205,7 @@ class Counter(Pmw.MegaWidget):
 
         if datatype in _counterCommands:
             self._counterCommand = _counterCommands[datatype]
-        elif isinstance(datatype, collections.Callable):
+        elif callable(datatype):
             self._counterCommand = datatype
         else:
             validValues = list(_counterCommands.keys())
@@ -277,9 +276,9 @@ Pmw.forwardmethods(Counter, Pmw.EntryField, '_counterEntry')
 def _changeNumber(text, factor, increment):
     value = int(text)
     if factor > 0:
-        value = (value // increment) * increment + increment 
+        value = (value // increment) * increment + increment
     else:
-        value = ((value - 1) // increment) * increment  
+        value = ((value - 1) // increment) * increment
 
     #removed "L" check since we're working with Python 3
     return str(int(value))
diff --git a/lib/PmwDialog.py b/lib/PmwDialog.py
index e8c4f8c..d0cad65 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwDialog.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwDialog.py
@@ -10,7 +10,6 @@ import sys
 import types
 import tkinter
 import Pmw
-import collections
 
 # A Toplevel with a ButtonBox and child site.
 
@@ -128,7 +127,7 @@ class Dialog(Pmw.MegaToplevel):
             return
 
         command = self['command']
-        if isinstance(command, collections.Callable):
+        if callable(command):
             return command(name)
         else:
             if self.active():
diff --git a/lib/PmwEntryField.py b/lib/PmwEntryField.py
index 077dcee..15d4339 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwEntryField.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwEntryField.py
@@ -5,7 +5,6 @@ import string
 import types
 import tkinter
 import Pmw
-import collections
 
 # Possible return values of validation functions.
 OK = 1
@@ -170,7 +169,7 @@ class EntryField(Pmw.MegaWidget):
     def _checkValidateFunction(self, function, option, validator):
         # Raise an error if 'function' is not a function or None.
 
-        if function is not None and not isinstance(function, collections.Callable):
+        if function is not None and not callable(function):
             extraValidators = self['extravalidators']
             extra = list(extraValidators.keys())
             extra.sort()
@@ -184,7 +183,7 @@ class EntryField(Pmw.MegaWidget):
 
     def _executeCommand(self, event = None):
         cmd = self['command']
-        if isinstance(cmd, collections.Callable):
+        if callable(cmd):
             if event is None:
                 # Return result of command for invoke() method.
                 return cmd()
@@ -215,7 +214,7 @@ class EntryField(Pmw.MegaWidget):
             return valid
 
         cmd = self['modifiedcommand']
-        if isinstance(cmd, collections.Callable) and previousText != self._entryFieldEntry.get():
+        if callable(cmd) and previousText != self._entryFieldEntry.get():
             cmd()
         return valid
 
@@ -263,7 +262,7 @@ class EntryField(Pmw.MegaWidget):
         if valid == ERROR:
             # The entry is invalid.
             cmd = self['invalidcommand']
-            if isinstance(cmd, collections.Callable):
+            if callable(cmd):
                 cmd()
             if self.hulldestroyed():
                 # The invalidcommand destroyed us.
diff --git a/lib/PmwHistoryText.py b/lib/PmwHistoryText.py
index 919f94a..4cd6b11 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwHistoryText.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwHistoryText.py
@@ -1,5 +1,4 @@
 import Pmw
-import collections
 
 _ORIGINAL = 0
 _MODIFIED = 1
@@ -65,7 +64,7 @@ class HistoryText(Pmw.ScrolledText):
             # so allow the 'Next' button to go to the entry after this one.
             self._pastIndex = self._currIndex
             nextState = 'normal'
-        if isinstance(historycommand, collections.Callable):
+        if callable(historycommand):
             historycommand('normal', nextState)
 
         # Create the new history entry.
@@ -132,7 +131,7 @@ class HistoryText(Pmw.ScrolledText):
                 if self._currIndex == 0:
                     prevstate = 'disabled'
             historycommand = self['historycommand']
-            if isinstance(historycommand, collections.Callable):
+            if callable(historycommand):
                 historycommand(prevstate, nextstate)
             currentEntry =  self._list[self._currIndex]
         else:
diff --git a/lib/PmwOptionMenu.py b/lib/PmwOptionMenu.py
index 31ace8f..b9a9206 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwOptionMenu.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwOptionMenu.py
@@ -2,7 +2,6 @@ import types
 import tkinter
 import Pmw
 import sys
-import collections
 
 class OptionMenu(Pmw.MegaWidget):
 
@@ -144,5 +143,5 @@ class OptionMenu(Pmw.MegaWidget):
         self.setvalue(text)
 
         command = self['command']
-        if isinstance(command, collections.Callable):
+        if callable(command):
             return command(text)
diff --git a/lib/PmwPanedWidget.py b/lib/PmwPanedWidget.py
index 82fdbdc..d07d12f 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwPanedWidget.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwPanedWidget.py
@@ -6,7 +6,6 @@ import sys
 import types
 import tkinter
 import Pmw
-import collections
 
 class PanedWidget(Pmw.MegaWidget):
 
@@ -152,7 +151,7 @@ class PanedWidget(Pmw.MegaWidget):
         # Note that, since the hull is a frame, the width and height
         # options specify the geometry *outside* the borderwidth and
         # highlightthickness.
-        
+
         #Python 3 conversion
         #bw = string.atoi(str(self.cget('hull_borderwidth')))
         #hl = string.atoi(str(self.cget('hull_highlightthickness')))
@@ -441,7 +440,7 @@ class PanedWidget(Pmw.MegaWidget):
 
         # Invoke the callback command
         cmd = self['command']
-        if isinstance(cmd, collections.Callable):
+        if callable(cmd):
             cmd(list(map(lambda x, s = self: s._size[x], self._paneNames)))
 
     def _plotHandles(self):
diff --git a/lib/PmwRadioSelect.py b/lib/PmwRadioSelect.py
index c68e0e0..0ba53c5 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwRadioSelect.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwRadioSelect.py
@@ -1,7 +1,6 @@
 import types
 import tkinter
 import Pmw
-import collections
 
 class RadioSelect(Pmw.MegaWidget):
     # A collection of several buttons.  In single mode, only one
@@ -209,7 +208,7 @@ class RadioSelect(Pmw.MegaWidget):
         if self._singleSelect:
             self.__setSingleValue(name)
             command = self['command']
-            if isinstance(command, collections.Callable):
+            if callable(command):
                 return command(name)
         else:
             # Multiple selections
@@ -230,5 +229,5 @@ class RadioSelect(Pmw.MegaWidget):
                 state = 1
 
             command = self['command']
-            if isinstance(command, collections.Callable):
+            if callable(command):
                 return command(name, state)
diff --git a/lib/PmwScrolledListBox.py b/lib/PmwScrolledListBox.py
index cf014ec..3e2a571 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwScrolledListBox.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwScrolledListBox.py
@@ -3,7 +3,6 @@
 import types
 import tkinter
 import Pmw
-import collections
 
 class ScrolledListBox(Pmw.MegaWidget):
     _classBindingsDefinedFor = 0
@@ -340,7 +339,7 @@ class ScrolledListBox(Pmw.MegaWidget):
 
             command = self['selectioncommand']
 
-        if isinstance(command, collections.Callable):
+        if callable(command):
             command()
 
     # Need to explicitly forward this to override the stupid
diff --git a/lib/PmwTimeCounter.py b/lib/PmwTimeCounter.py
index f88788a..795fd3b 100755
--- Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwTimeCounter.py
+++ Pmw-2.0.0/Pmw/Pmw_2_0_0/lib/PmwTimeCounter.py
@@ -5,7 +5,6 @@ import sys
 import time
 import tkinter
 import Pmw
-import collections
 
 class TimeCounter(Pmw.MegaWidget):
     """Up-down counter
@@ -367,12 +366,12 @@ class TimeCounter(Pmw.MegaWidget):
 
     def _invoke(self, event):
         cmd = self['command']
-        if isinstance(cmd, collections.Callable):
+        if callable(cmd):
             cmd()
 
     def invoke(self):
         cmd = self['command']
-        if isinstance(cmd, collections.Callable):
+        if callable(cmd):
             return cmd()
 
     def destroy(self):
--
2.34.1

