[chirp_devel] [PATCH] [RFC] Abstract Bank and BankModel to MemoryMapping and MappingModel

Dan Smith
Mon Apr 1 15:30:58 PDT 2013


# HG changeset patch
# User Dan Smith <dsmith at danplanet.com>
# Date 1364855446 25200
# Node ID a11f2427091df6e0a0a2a6fe5fb1c1956333eb58
# Parent  66f225bbeb996964b922ef37800224fc76611870
[RFC] Abstract Bank and BankModel to MemoryMapping and MappingModel

This is mostly just a search-and-replace for the above names, but makes
way for supporting things like scan lists that behave exactly the same
way.

Updated with unit tests, fixes needed to import_logic, and a change to
add a name property to the model so we can adjust the UI's naming of
models like Scan Lists and Banks separately.

diff -r 66f225bbeb99 -r a11f2427091d chirp/chirp_common.py
--- a/chirp/chirp_common.py	Mon Apr 01 13:45:17 2013 -0700
+++ b/chirp/chirp_common.py	Mon Apr 01 15:30:46 2013 -0700
@@ -543,8 +543,8 @@
         except Exception:
             self.dv_code = 0
 
-class Bank:
-    """Base class for a radio's Bank"""
+class MemoryMapping(object):
+    """Base class for a memory mapping"""
     def __init__(self, model, index, name):
         self._model = model
         self._index = index
@@ -554,75 +554,87 @@
         return self.get_name()
 
     def __repr__(self):
-        return "Bank-%s" % self._index
+        return "%s-%s" % (self.__class__.__name__, self._index)
 
     def get_name(self):
-        """Returns the static or user-adjustable bank name"""
+        """Returns the mapping name"""
         return self._name
 
     def get_index(self):
-        """Returns the immutable bank index (string or int)"""
+        """Returns the immutable index (string or int)"""
         return self._index
 
     def __eq__(self, other):
         return self.get_index() == other.get_index()
 
+class MappingModel(object):
+    """Base class for a memory mapping model"""
+
+    def __init__(self, radio, name):
+        self._radio = radio
+        self._name = name
+
+    def get_name(self):
+        return self._name
+
+    def get_num_mappings(self):
+        """Returns the number of mappings in the model (should be
+        callable without consulting the radio"""
+        raise NotImplementedError()
+
+    def get_mappings(self):
+        """Return a list of mappings"""
+        raise NotImplementedError()
+
+    def add_memory_to_mapping(self, memory, mapping):
+        """Add @memory to @mapping."""
+        raise NotImplementedError()
+
+    def remove_memory_from_mapping(self, memory, mapping):
+        """Remove @memory from @mapping.
+        Shall raise exception if @memory is not in @bank"""
+        raise NotImplementedError()
+
+    def get_mapping_memories(self, mapping):
+        """Return a list of memories in @mapping"""
+        raise NotImplementedError()
+
+    def get_memory_mappings(self, memory):
+        """Return a list of mappings that @memory is in"""
+        raise NotImplementedError()
+
+class Bank(MemoryMapping):
+    """Base class for a radio's Bank"""
+
 class NamedBank(Bank):
     """A bank that can have a name"""
     def set_name(self, name):
         """Changes the user-adjustable bank name"""
         self._name = name
 
-class BankModel:
+class BankModel(MappingModel):
     """A bank model where one memory is in zero or one banks at any point"""
     def __init__(self, radio):
-        self._radio = radio
+        super(BankModel, self).__init__(radio, 'Banks')
 
-    def get_num_banks(self):
-        """Returns the number of banks (should be callable without
-        consulting the radio"""
-        raise Exception("Not implemented")
+class MappingModelIndexInterface:
+    """Interface for mappings with index capabilities"""
+    def get_index_bounds(self):
+        """Returns a tuple (lo,hi) of the min and max mapping indices"""
+        raise NotImplementedError()
 
-    def get_banks(self):
-        """Return a list of banks"""
-        raise Exception("Not implemented")
+    def get_memory_index(self, memory, mapping):
+        """Returns the index of @memory in @mapping"""
+        raise NotImplementedError()
 
-    def add_memory_to_bank(self, memory, bank):
-        """Add @memory to @bank."""
-        raise Exception("Not implemented")
+    def set_memory_index(self, memory, mapping, index):
+        """Sets the index of @memory in @mapping to @index"""
+        raise NotImplementedError()
 
-    def remove_memory_from_bank(self, memory, bank):
-        """Remove @memory from @bank.
-        Shall raise exception if @memory is not in @bank."""
-        raise Exception("Not implemented")
-
-    def get_bank_memories(self, bank):
-        """Return a list of memories in @bank"""
-        raise Exception("Not implemented")
-
-    def get_memory_banks(self, memory):
-        """Returns a list of the banks that @memory is in"""
-        raise Exception("Not implemented")
-
-class BankIndexInterface:
-    """Interface for banks with index capabilities"""
-    def get_index_bounds(self):
-        """Returns a tuple (lo,hi) of the minimum and maximum bank indices"""
-        raise Exception("Not implemented")
-
-    def get_memory_index(self, memory, bank):
-        """Returns the index of @memory in @bank"""
-        raise Exception("Not implemented")
-
-    def set_memory_index(self, memory, bank, index):
-        """Sets the index of @memory in @bank to @index"""
-        raise Exception("Not implemented")
-
-    def get_next_bank_index(self, bank):
-        """Returns the next available bank index in @bank, or raises
+    def get_next_mapping_index(self, mapping):
+        """Returns the next available mapping index in @mapping, or raises
         Exception if full"""
-        raise Exception("Not implemented")
-
+        raise NotImplementedError()
 
 class MTOBankModel(BankModel):
     """A bank model where one memory can be in multiple banks at once """
diff -r 66f225bbeb99 -r a11f2427091d chirp/ft7800.py
--- a/chirp/ft7800.py	Mon Apr 01 13:45:17 2013 -0700
+++ b/chirp/ft7800.py	Mon Apr 01 15:30:46 2013 -0700
@@ -336,7 +336,7 @@
 class FT7800BankModel(chirp_common.BankModel):
     """Yaesu FT-7800/7900 bank model"""
     def __init__(self, radio):
-        chirp_common.BankModel.__init__(self, radio)
+        super(FT7800BankModel, self).__init__(radio)
         self.__b2m_cache = defaultdict(list)
         self.__m2b_cache = defaultdict(list)
 
@@ -344,24 +344,24 @@
         if self.__b2m_cache:
             return
 
-        for bank in self.get_banks():
+        for bank in self.get_mappings():
             self.__b2m_cache[bank.index] = self._get_bank_memories(bank)
             for memnum in self.__b2m_cache[bank.index]:
                 self.__m2b_cache[memnum].append(bank.index)
 
-    def get_num_banks(self):
+    def get_num_mappings(self):
         return 20
 
-    def get_banks(self):
+    def get_mappings(self):
         banks = []
-        for i in range(0, self.get_num_banks()):
+        for i in range(0, self.get_num_mappings()):
             bank = chirp_common.Bank(self, "%i" % i, "BANK-%i" % (i + 1))
             bank.index = i
             banks.append(bank)
 
         return banks
 
-    def add_memory_to_bank(self, memory, bank):
+    def add_memory_to_mapping(self, memory, bank):
         self.__precache()
 
         index = memory.number - 1
@@ -371,7 +371,7 @@
         self.__m2b_cache[memory.number].append(bank.index)
         self.__b2m_cache[bank.index].append(memory.number)
 
-    def remove_memory_from_bank(self, memory, bank):
+    def remove_memory_from_mapping(self, memory, bank):
         self.__precache()
 
         index = memory.number - 1
@@ -395,16 +395,16 @@
                 memories.append(i + 1)
         return memories
 
-    def get_bank_memories(self, bank):
+    def get_mapping_memories(self, bank):
         self.__precache()
 
         return [self._radio.get_memory(n)
                 for n in self.__b2m_cache[bank.index]]
 
-    def get_memory_banks(self, memory):
+    def get_memory_mappings(self, memory):
         self.__precache()
 
-        _banks = self.get_banks()
+        _banks = self.get_mappings()
         return [_banks[b] for b in self.__m2b_cache[memory.number]]
 
 @directory.register
@@ -473,7 +473,7 @@
 """
 
 class FT8800BankModel(FT7800BankModel):
-    def get_num_banks(self):
+    def get_num_mappings(self):
         return 10
 
 @directory.register
diff -r 66f225bbeb99 -r a11f2427091d chirp/icf.py
--- a/chirp/icf.py	Mon Apr 01 13:45:17 2013 -0700
+++ b/chirp/icf.py	Mon Apr 01 15:30:46 2013 -0700
@@ -485,10 +485,10 @@
     central implementation can, with a few icom-specific radio interfaces
     serve most/all of them"""
 
-    def get_num_banks(self):
+    def get_num_mappings(self):
         return self._radio._num_banks
 
-    def get_banks(self):
+    def get_mappings(self):
         banks = []
         
         for i in range(0, self._radio._num_banks):
@@ -498,31 +498,32 @@
             banks.append(bank)
         return banks
 
-    def add_memory_to_bank(self, memory, bank):
+    def add_memory_to_mapping(self, memory, bank):
         self._radio._set_bank(memory.number, bank.index)
 
-    def remove_memory_from_bank(self, memory, bank):
+    def remove_memory_from_mapping(self, memory, bank):
         if self._radio._get_bank(memory.number) != bank.index:
             raise Exception("Memory %i not in bank %s. Cannot remove." % \
                                 (memory.number, bank))
 
         self._radio._set_bank(memory.number, None)
 
-    def get_bank_memories(self, bank):
+    def get_mapping_memories(self, bank):
         memories = []
         for i in range(*self._radio.get_features().memory_bounds):
             if self._radio._get_bank(i) == bank.index:
                 memories.append(self._radio.get_memory(i))
         return memories
 
-    def get_memory_banks(self, memory):
+    def get_memory_mappings(self, memory):
         index = self._radio._get_bank(memory.number)
         if index is None:
             return []
         else:
-            return [self.get_banks()[index]]
+            return [self.get_mappings()[index]]
     
-class IcomIndexedBankModel(IcomBankModel, chirp_common.BankIndexInterface):
+class IcomIndexedBankModel(IcomBankModel,
+                           chirp_common.MappingModelIndexInterface):
     """Generic bank model for Icom radios with indexed banks"""
     def get_index_bounds(self):
         return self._radio._bank_index_bounds
@@ -531,7 +532,7 @@
         return self._radio._get_bank_index(memory.number)
 
     def set_memory_index(self, memory, bank, index):
-        if bank not in self.get_memory_banks(memory):
+        if bank not in self.get_memory_mappings(memory):
             raise Exception("Memory %i is not in bank %s" % (memory.number,
                                                              bank))
 
@@ -539,7 +540,7 @@
             raise Exception("Invalid index")
         self._radio._set_bank_index(memory.number, index)
 
-    def get_next_bank_index(self, bank):
+    def get_next_mapping_index(self, bank):
         indexes = []
         for i in range(*self._radio.get_features().memory_bounds):
             if self._radio._get_bank(i) == bank.index:
diff -r 66f225bbeb99 -r a11f2427091d chirp/import_logic.py
--- a/chirp/import_logic.py	Mon Apr 01 13:45:17 2013 -0700
+++ b/chirp/import_logic.py	Mon Apr 01 15:30:46 2013 -0700
@@ -219,27 +219,27 @@
     if not dst_bm:
         return
 
-    dst_banks = dst_bm.get_banks()
+    dst_banks = dst_bm.get_mappings()
 
     src_bm = src_radio.get_bank_model()
     if not src_bm:
         return
 
-    src_banks = src_bm.get_banks()
-    src_mem_banks = src_bm.get_memory_banks(src_mem)
+    src_banks = src_bm.get_mappings()
+    src_mem_banks = src_bm.get_memory_mappings(src_mem)
     src_indexes = [src_banks.index(b) for b in src_mem_banks]
 
-    for bank in dst_bm.get_memory_banks(dst_mem):
-        dst_bm.remove_memory_from_bank(dst_mem, bank)
+    for bank in dst_bm.get_memory_mappings(dst_mem):
+        dst_bm.remove_memory_from_mapping(dst_mem, bank)
 
     for index in src_indexes:
         try:
             bank = dst_banks[index]
             print "Adding memory to bank %s" % bank
-            dst_bm.add_memory_to_bank(dst_mem, bank)
-            if isinstance(dst_bm, chirp_common.BankIndexInterface):
+            dst_bm.add_memory_to_mapping(dst_mem, bank)
+            if isinstance(dst_bm, chirp_common.MappingModelIndexInterface):
                 dst_bm.set_memory_index(dst_mem, bank,
-                                        dst_bm.get_next_bank_index(bank))
+                                        dst_bm.get_next_mapping_index(bank))
 
         except IndexError:
             pass
diff -r 66f225bbeb99 -r a11f2427091d chirp/vx3.py
--- a/chirp/vx3.py	Mon Apr 01 13:45:17 2013 -0700
+++ b/chirp/vx3.py	Mon Apr 01 15:30:46 2013 -0700
@@ -110,10 +110,10 @@
 
 class VX3BankModel(chirp_common.BankModel):
     """A VX-3 bank model"""
-    def get_num_banks(self):
+    def get_num_mappings(self):
         return 24
 
-    def get_banks(self):
+    def get_mappings(self):
         _banks = self._radio._memobj.bank_names
 
         banks = []
diff -r 66f225bbeb99 -r a11f2427091d chirp/vx5.py
--- a/chirp/vx5.py	Mon Apr 01 13:45:17 2013 -0700
+++ b/chirp/vx5.py	Mon Apr 01 15:30:46 2013 -0700
@@ -82,18 +82,18 @@
                 chirp_common.PowerLevel("L1", watts=0.05)]
 
 class VX5BankModel(chirp_common.BankModel):
-    def get_num_banks(self):
+    def get_num_mappings(self):
         return 5
 
-    def get_banks(self):
+    def get_mappings(self):
         banks = []
-        for i in range(0, self.get_num_banks()):
+        for i in range(0, self.get_num_mappings()):
             bank = chirp_common.Bank(self, "%i" % (i+1), "MG%i" % (i+1))
             bank.index = i
             banks.append(bank)
         return banks
 
-    def add_memory_to_bank(self, memory, bank):
+    def add_memory_to_mapping(self, memory, bank):
         _members = self._radio._memobj.bank_groups[bank.index].members
         _bank_used = self._radio._memobj.bank_used[bank.index]
         for i in range(0, len(_members)):
@@ -107,7 +107,7 @@
                 return True
         raise Exception(_("{bank} is full").format(bank=bank))
 
-    def remove_memory_from_bank(self, memory, bank):
+    def remove_memory_from_mapping(self, memory, bank):
         _members = self._radio._memobj.bank_groups[bank.index].members
         _bank_used = self._radio._memobj.bank_used[bank.index]
 
@@ -128,7 +128,7 @@
         if not remaining_members:
             _bank_used.current_member = 0xFF
 
-    def get_bank_memories(self, bank):
+    def get_mapping_memories(self, bank):
         memories = []
 
         _members = self._radio._memobj.bank_groups[bank.index].members
@@ -143,10 +143,11 @@
             memories.append(self._radio.get_memory(member.channel+1))
         return memories
 
-    def get_memory_banks(self, memory):
+    def get_memory_mappings(self, memory):
         banks = []
-        for bank in self.get_banks():
-            if memory.number in [x.number for x in self.get_bank_memories(bank)]:
+        for bank in self.get_mappings():
+            if memory.number in [x.number for x in
+                                 self.get_mapping_memories(bank)]:
                     banks.append(bank)
         return banks
 
diff -r 66f225bbeb99 -r a11f2427091d chirp/vx7.py
--- a/chirp/vx7.py	Mon Apr 01 13:45:17 2013 -0700
+++ b/chirp/vx7.py	Mon Apr 01 15:30:46 2013 -0700
@@ -103,18 +103,18 @@
 
 class VX7BankModel(chirp_common.BankModel):
     """A VX-7 Bank model"""
-    def get_num_banks(self):
+    def get_num_mappings(self):
         return 9
 
-    def get_banks(self):
+    def get_mappings(self):
         banks = []
-        for i in range(0, self.get_num_banks()):
+        for i in range(0, self.get_num_mappings()):
             bank = chirp_common.Bank(self, "%i" % (i+1), "MG%i" % (i+1))
             bank.index = i
             banks.append(bank)
         return banks
 
-    def add_memory_to_bank(self, memory, bank):
+    def add_memory_to_mapping(self, memory, bank):
         _members = self._radio._memobj.bank_members[bank.index]
         _bank_used = self._radio._memobj.bank_used[bank.index]
         for i in range(0, 48):
@@ -123,7 +123,7 @@
                 _bank_used.in_use = 0x0000
                 break
 
-    def remove_memory_from_bank(self, memory, bank):
+    def remove_memory_from_mapping(self, memory, bank):
         _members = self._radio._memobj.bank_members[bank.index].members
         _bank_used = self._radio._memobj.bank_used[bank.index]
 
@@ -143,7 +143,7 @@
         if not remaining_members:
             _bank_used.in_use = 0xFFFF
 
-    def get_bank_memories(self, bank):
+    def get_mapping_memories(self, bank):
         memories = []
 
         _members = self._radio._memobj.bank_members[bank.index].members
@@ -158,11 +158,11 @@
             memories.append(self._radio.get_memory(number+1))
         return memories
 
-    def get_memory_banks(self, memory):
+    def get_memory_mappings(self, memory):
         banks = []
-        for bank in self.get_banks():
+        for bank in self.get_mappings():
             if memory.number in [x.number for x in
-                                 self.get_bank_memories(bank)]:
+                                 self.get_mapping_memories(bank)]:
                 banks.append(bank)
         return banks
 
diff -r 66f225bbeb99 -r a11f2427091d chirp/vx8.py
--- a/chirp/vx8.py	Mon Apr 01 13:45:17 2013 -0700
+++ b/chirp/vx8.py	Mon Apr 01 15:30:46 2013 -0700
@@ -151,10 +151,10 @@
 
 class VX8BankModel(chirp_common.BankModel):
     """A VX-8 bank model"""
-    def get_num_banks(self):
+    def get_num_mappings(self):
         return 24
 
-    def get_banks(self):
+    def get_mappings(self):
         banks = []
         _banks = self._radio._memobj.bank_info
 
@@ -174,7 +174,7 @@
         flags = self._radio._memobj.flag
 
         # Find a suitable bank and MR for VFO A and B.
-        for bank in self.get_banks():
+        for bank in self.get_mappings():
             bank_used = self._radio._memobj.bank_used[bank.index]
             if bank_used != 0xFFFF:
                 members = self._radio._memobj.bank_members[bank.index]
@@ -213,7 +213,7 @@
               vfo_bak.mr_index = vfo.mr_index
               vfo_bak.bank_enable = vfo.bank_enable
 
-    def add_memory_to_bank(self, memory, bank):
+    def add_memory_to_mapping(self, memory, bank):
         _members = self._radio._memobj.bank_members[bank.index]
         _bank_used = self._radio._memobj.bank_used[bank.index]
         for i in range(0, 100):
@@ -224,7 +224,7 @@
 
         self.update_vfo()
 
-    def remove_memory_from_bank(self, memory, bank):
+    def remove_memory_from_mapping(self, memory, bank):
         _members = self._radio._memobj.bank_members[bank.index]
         _bank_used = self._radio._memobj.bank_used[bank.index]
 
@@ -246,7 +246,7 @@
 
         self.update_vfo()
 
-    def get_bank_memories(self, bank):
+    def get_mapping_memories(self, bank):
         memories = []
         _members = self._radio._memobj.bank_members[bank.index]
         _bank_used = self._radio._memobj.bank_used[bank.index]
@@ -260,11 +260,11 @@
 
         return memories
 
-    def get_memory_banks(self, memory):
+    def get_memory_mappings(self, memory):
         banks = []
-        for bank in self.get_banks():
+        for bank in self.get_mappings():
             if memory.number in \
-                    [x.number for x in self.get_bank_memories(bank)]:
+                    [x.number for x in self.get_mapping_memories(bank)]:
                 banks.append(bank)
 
         return banks
diff -r 66f225bbeb99 -r a11f2427091d chirpui/bankedit.py
--- a/chirpui/bankedit.py	Mon Apr 01 13:45:17 2013 -0700
+++ b/chirpui/bankedit.py	Mon Apr 01 15:30:46 2013 -0700
@@ -22,68 +22,70 @@
 from chirp import chirp_common
 from chirpui import common, miscwidgets
 
-class BankNamesJob(common.RadioJob):
-    def __init__(self, bm, editor, cb):
+class MappingNamesJob(common.RadioJob):
+    def __init__(self, model, editor, cb):
         common.RadioJob.__init__(self, cb, None)
-        self.__bm = bm
+        self.__model = model
         self.__editor = editor
 
     def execute(self, radio):
-        self.__editor.banks = []
+        self.__editor.mappings = []
 
-        banks = self.__bm.get_banks()
-        for bank in banks:
-            self.__editor.banks.append((bank, bank.get_name()))
+        mappings = self.__model.get_mappings()
+        for mapping in mappings:
+            self.__editor.mappings.append((mapping, mapping.get_name()))
 
         gobject.idle_add(self.cb, *self.cb_args)
 
-class BankNameEditor(common.Editor):
+class MappingNameEditor(common.Editor):
+    TYPE = _("Mapping")
+
     def refresh(self):
-        def got_banks():
+        def got_mappings():
             self._keys = []
-            for bank, name in self.banks:
-                self._keys.append(bank.get_index())
-                self.listw.set_item(bank.get_index(),
-                                    bank.get_index(),
+            for mapping, name in self.mappings:
+                self._keys.append(mapping.get_index())
+                self.listw.set_item(mapping.get_index(),
+                                    mapping.get_index(),
                                     name)
 
-            self.listw.connect("item-set", self.bank_changed)
+            self.listw.connect("item-set", self.mapping_changed)
 
-        job = BankNamesJob(self._bm, self, got_banks)
-        job.set_desc(_("Retrieving bank information"))
+        job = MappingNamesJob(self._model, self, got_mappings)
+        job.set_desc(_("Retrieving %s information") % self.TYPE)
         self.rthread.submit(job)
 
-    def get_bank_list(self):
-        banks = []
+    def get_mapping_list(self):
+        mappings = []
         keys = self.listw.get_keys()
         for key in keys:
-            banks.append(self.listw.get_item(key)[2])
+            mappings.append(self.listw.get_item(key)[2])
 
-        return banks
-    
-    def bank_changed(self, listw, key):
+        return mappings
+
+    def mapping_changed(self, listw, key):
         def cb(*args):
             self.emit("changed")
 
         name = self.listw.get_item(key)[2]
-        bank, oldname = self.banks[self._keys.index(key)]
+        mapping, oldname = self.mappings[self._keys.index(key)]
 
         def trigger_changed(*args):
             self.emit("changed")
 
         job = common.RadioJob(trigger_changed, "set_name", name)
-        job.set_target(bank)
-        job.set_desc(_("Setting name on bank"))
+        job.set_target(mapping)
+        job.set_desc(_("Setting name on %s") % self.TYPE.lower())
         self.rthread.submit(job)
 
         return True
 
-    def __init__(self, rthread):
-        super(BankNameEditor, self).__init__(rthread)
-        self._bm = rthread.radio.get_bank_model()
+    def __init__(self, rthread, model):
+        super(MappingNameEditor, self).__init__(rthread)
+        self._model = model
 
         types = [(gobject.TYPE_STRING, "key"),
-                 (gobject.TYPE_STRING, _("Bank")),
+                 (gobject.TYPE_STRING, self.TYPE),
                  (gobject.TYPE_STRING, _("Name"))]
 
         self.listw = miscwidgets.KeyedListWidget(types)
@@ -92,7 +94,7 @@
         self.listw.set_sort_column(1, -1)
         self.listw.show()
 
-        self.banks = []
+        self.mappings = []
 
         sw = gtk.ScrolledWindow()
         sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
@@ -108,51 +110,61 @@
         self.refresh()
         self._loaded = True
 
-class MemoryBanksJob(common.RadioJob):
-    def __init__(self, bm, cb, number):
+class BankNameEditor(MappingNameEditor):
+    TYPE = _("Bank")
+
+    def __init__(self, rthread):
+        model = rthread.radio.get_bank_model()
+        super(BankNameEditor, self).__init__(rthread, model)
+
+class MemoryMappingsJob(common.RadioJob):
+    def __init__(self, model, cb, number):
         common.RadioJob.__init__(self, cb, None)
-        self.__bm = bm
+        self.__model = model
         self.__number = number
 
     def execute(self, radio):
         mem = radio.get_memory(self.__number)
         if mem.empty:
-            banks = []
+            mappings = []
             indexes = []
         else:
-            banks = self.__bm.get_memory_banks(mem)
+            mappings = self.__model.get_memory_mappings(mem)
             indexes = []
-            if isinstance(self.__bm, chirp_common.BankIndexInterface):
-                for bank in banks:
-                    indexes.append(self.__bm.get_memory_index(mem, bank))
-        self.cb(mem, banks, indexes, *self.cb_args)
+            if isinstance(self.__model,
+                          chirp_common.MappingModelIndexInterface):
+                for mapping in mappings:
+                    indexes.append(self.__model.get_memory_index(mem, mapping))
+        self.cb(mem, mappings, indexes, *self.cb_args)
             
-class BankMembershipEditor(common.Editor):
+class MappingMembershipEditor(common.Editor):
+    TYPE = _("Mapping")
+
     def _number_to_path(self, number):
         return (number - self._rf.memory_bounds[0],)
 
-    def _get_next_bank_index(self, bank):
-        # NB: Only works for one-to-one bank models right now!
+    def _get_next_mapping_index(self, mapping):
+        # NB: Only works for one-to-one models right now!
         iter = self._store.get_iter_first()
         indexes = []
-        ncols = len(self._cols) + len(self.banks)
+        ncols = len(self._cols) + len(self.mappings)
         while iter:
             vals = self._store.get(iter, *tuple([n for n in range(0, ncols)]))
             loc = vals[self.C_LOC]
             index = vals[self.C_INDEX]
-            banks = vals[self.C_BANKS:]
-            if True in banks and banks.index(True) == bank:
+            mappings = vals[self.C_MAPPINGS:]
+            if True in mappings and mappings.index(True) == mapping:
                 indexes.append(index)
             iter = self._store.iter_next(iter)
 
-        index_bounds = self._bm.get_index_bounds()
+        index_bounds = self._model.get_index_bounds()
         num_indexes = index_bounds[1] - index_bounds[0]
         indexes.sort()
         for i in range(0, num_indexes):
             if i not in indexes:
                 return i + index_bounds[0] # In case not zero-origin index
 
-        return 0 # If the bank is full, just wrap around!
+        return 0 # If the mapping is full, just wrap around!
 
     def _toggled_cb(self, rend, path, colnum):
         try:
@@ -164,56 +176,60 @@
             if not self._store.get(iter, self.C_FILLED)[0]:
                 return
 
-        # The bank index is the column number, minus the 3 label columns
-        bank, name = self.banks[colnum - len(self._cols)]
+        # The mapping index is the column number, minus the 3 label columns
+        mapping, name = self.mappings[colnum - len(self._cols)]
         loc, = self._store.get(self._store.get_iter(path), self.C_LOC)
 
+        is_indexed = isinstance(self._model,
+                                chirp_common.MappingModelIndexInterface)
+
         if rend.get_active():
             # Changing from True to False
-            fn = "remove_memory_from_bank"
+            fn = "remove_memory_from_mapping"
             index = None
         else:
             # Changing from False to True
-            fn = "add_memory_to_bank"
-            if self._rf.has_bank_index:
-                index = self._get_next_bank_index(colnum - len(self._cols))
+            fn = "add_memory_to_mapping"
+            if is_indexed:
+                index = self._get_next_mapping_index(colnum - len(self._cols))
             else:
                 index = None
 
         def do_refresh_memory(*args):
-            # Step 2: Update our notion of the memory's bank information
+            # Step 2: Update our notion of the memory's mapping information
             self.refresh_memory(loc)
 
-        def do_bank_index(result, memory):
+        def do_mapping_index(result, memory):
             if isinstance(result, Exception):
-                common.show_error("Failed to add {mem} to bank: {err}"
+                common.show_error("Failed to add {mem} to mapping: {err}"
                                   .format(mem=memory.number,
                                           err=str(result)),
                                   parent=self.editorset.parent_window)
                 return
             self.emit("changed")
-            # Step 3: Set the memory's bank index (maybe)
-            if not self._rf.has_bank_index or index is None:
+            # Step 3: Set the memory's mapping index (maybe)
+            if not is_indexed or index is None:
                 return do_refresh_memory()
 
             job = common.RadioJob(do_refresh_memory,
-                                  "set_memory_index", memory, bank, index)
-            job.set_target(self._bm)
-            job.set_desc(_("Updating bank index "
-                           "for memory {num}").format(num=memory.number))
+                                  "set_memory_index", memory, mapping, index)
+            job.set_target(self._model)
+            job.set_desc(_("Updating {type} index "
+                           "for memory {num}").format(type=self.TYPE,
+                                                      num=memory.number))
             self.rthread.submit(job)
 
-        def do_bank_adjustment(memory):
-            # Step 1: Do the bank add/remove
-            job = common.RadioJob(do_bank_index, fn, memory, bank)
-            job.set_target(self._bm)
+        def do_mapping_adjustment(memory):
+            # Step 1: Do the mapping add/remove
+            job = common.RadioJob(do_mapping_index, fn, memory, mapping)
+            job.set_target(self._model)
             job.set_cb_args(memory)
-            job.set_desc(_("Updating bank information "
+            job.set_desc(_("Updating mapping information "
                            "for memory {num}").format(num=memory.number))
             self.rthread.submit(job)
 
         # Step 0: Fetch the memory
-        job = common.RadioJob(do_bank_adjustment, "get_memory", loc)
+        job = common.RadioJob(do_mapping_adjustment, "get_memory", loc)
         job.set_desc(_("Getting memory {num}").format(num=loc))
         self.rthread.submit(job)
 
@@ -223,36 +239,37 @@
         def refresh_memory(*args):
             self.refresh_memory(loc)
 
-        def set_index(banks, memory):
+        def set_index(mappings, memory):
             self.emit("changed")
             # Step 2: Set the index
             job = common.RadioJob(refresh_memory, "set_memory_index",
-                                  memory, banks[0], int(new))
-            job.set_target(self._bm)
+                                  memory, mappings[0], int(new))
+            job.set_target(self._model)
             job.set_desc(_("Setting index "
                            "for memory {num}").format(num=memory.number))
             self.rthread.submit(job)
 
-        def get_bank(memory):
-            # Step 1: Get the first/only bank
-            job = common.RadioJob(set_index, "get_memory_banks", memory)
+        def get_mapping(memory):
+            # Step 1: Get the first/only mapping
+            job = common.RadioJob(set_index, "get_memory_mappings", memory)
             job.set_cb_args(memory)
-            job.set_target(self._bm)
-            job.set_desc(_("Getting bank for "
-                           "memory {num}").format(num=memory.number))
+            job.set_target(self._model)
+            job.set_desc(_("Getting {type} for "
+                           "memory {num}").format(type=self.TYPE,
+                                                  num=memory.number))
             self.rthread.submit(job)
 
         # Step 0: Get the memory
-        job = common.RadioJob(get_bank, "get_memory", loc)
+        job = common.RadioJob(get_mapping, "get_memory", loc)
         job.set_desc(_("Getting memory {num}").format(num=loc))
         self.rthread.submit(job)
             
-    def __init__(self, rthread, editorset):
-        super(BankMembershipEditor, self).__init__(rthread)
+    def __init__(self, rthread, editorset, model):
+        super(MappingMembershipEditor, self).__init__(rthread)
 
         self.editorset = editorset
         self._rf = rthread.radio.get_features()
-        self._bm = rthread.radio.get_bank_model()
+        self._model = model
 
         self._view_cols = [
             (_("Loc"),       TYPE_INT,     gtk.CellRendererText, ),
@@ -270,19 +287,22 @@
         self.C_FREQ   = 2
         self.C_NAME   = 3
         self.C_INDEX  = 4
-        self.C_BANKS  = 5 # and beyond
+        self.C_MAPPINGS  = 5 # and beyond
         
         cols = list(self._cols)
 
         self._index_cache = []
 
-        for i in range(0, self._bm.get_num_banks()):
-            label = "Bank %i" % (i+1)
+        for i in range(0, self._model.get_num_mappings()):
+            label = "%s %i" % (self.TYPE, (i+1))
             cols.append((label, TYPE_BOOLEAN, gtk.CellRendererToggle))
 
         self._store = gtk.ListStore(*tuple([y for x,y,z in cols]))
         self._view = gtk.TreeView(self._store)
 
+        is_indexed = isinstance(self._model,
+                                chirp_common.MappingModelIndexInterface)
+
         colnum = 0
         for label, dtype, rtype in cols:
             if not rtype:
@@ -305,7 +325,7 @@
             elif colnum == self.C_INDEX:
                 rend.set_property("editable", True)
                 rend.connect("edited", self._index_edited_cb)
-                col.set_visible(self._rf.has_bank_index)
+                col.set_visible(is_indexed)
             colnum += 1
 
         # A non-rendered column to absorb extra space in the row
@@ -329,7 +349,7 @@
         self._loaded = False
 
     def refresh_memory(self, number):
-        def got_mem(memory, banks, indexes):
+        def got_mem(memory, mappings, indexes):
             iter = self._store.get_iter(self._number_to_path(memory.number))
             row = [self.C_FILLED, not memory.empty,
                    self.C_LOC, memory.number,
@@ -338,29 +358,30 @@
                    # Hack for only one index right now
                    self.C_INDEX, indexes and indexes[0] or 0,
                    ]
-            for i in range(0, len(self.banks)):
+            for i in range(0, len(self.mappings)):
                 row.append(i + len(self._cols))
-                row.append(self.banks[i][0] in banks)
+                row.append(self.mappings[i][0] in mappings)
                 
             self._store.set(iter, *tuple(row))
             if memory.number == self._rf.memory_bounds[1] - 1:
-                print "Got all bank info in %s" % (time.time() - self._start)
+                print "Got all %s info in %s" % (self.TYPE,
+                                                 (time.time() - self._start))
 
-        job = MemoryBanksJob(self._bm, got_mem, number)
-        job.set_desc(_("Getting bank information "
-                       "for memory {num}").format(num=number))
+        job = MemoryMappingsJob(self._model, got_mem, number)
+        job.set_desc(_("Getting {type} information "
+                       "for memory {num}").format(type=self.TYPE, num=number))
         self.rthread.submit(job)
 
     def refresh_all_memories(self):
         for i in range(*self._rf.memory_bounds):
             self.refresh_memory(i)
 
-    def refresh_banks(self, and_memories=False):
-        def got_banks():
+    def refresh_mappings(self, and_memories=False):
+        def got_mappings():
             for i in range(len(self._cols) - len(self._view_cols) - 1,
-                           len(self.banks)):
+                           len(self.mappings)):
                 col = self._view.get_column(i + len(self._view_cols))
-                bank, name = self.banks[i]
+                mapping, name = self.mappings[i]
                 if name:
                     col.set_title(name)
                 else:
@@ -368,8 +389,8 @@
             if and_memories:
                 self.refresh_all_memories()
 
-        job = BankNamesJob(self._bm, self, got_banks)
-        job.set_desc(_("Getting bank information"))
+        job = MappingNamesJob(self._model, self, got_mappings)
+        job.set_desc(_("Getting %s information") % self.TYPE)
         self.rthread.submit(job)
 
     def focus(self):
@@ -378,7 +399,7 @@
             return
 
         self._start = time.time()
-        self.refresh_banks(True)
+        self.refresh_mappings(True)
 
         self._loaded = True
 
@@ -387,5 +408,15 @@
         if self.is_focused():
             self.refresh_all_memories()
 
+    def mappings_changed(self):
+        self.refresh_mappings()
+
+class BankMembershipEditor(MappingMembershipEditor):
+    TYPE = _("Bank")
+
+    def __init__(self, rthread, editorset):
+        model = rthread.radio.get_bank_model()
+        super(BankMembershipEditor, self).__init__(rthread, editorset, model)
+
     def banks_changed(self):
-        self.refresh_banks()
+        self.mappings_changed()
diff -r 66f225bbeb99 -r a11f2427091d tests/unit/test_import_logic.py
--- a/tests/unit/test_import_logic.py	Mon Apr 01 13:45:17 2013 -0700
+++ b/tests/unit/test_import_logic.py	Mon Apr 01 15:30:46 2013 -0700
@@ -349,21 +349,21 @@
 
         self.mox.StubOutWithMock(dst_radio, 'get_bank_model')
         self.mox.StubOutWithMock(src_radio, 'get_bank_model')
-        self.mox.StubOutWithMock(dst_bm, 'get_banks')
-        self.mox.StubOutWithMock(src_bm, 'get_banks')
-        self.mox.StubOutWithMock(dst_bm, 'get_memory_banks')
-        self.mox.StubOutWithMock(src_bm, 'get_memory_banks')
-        self.mox.StubOutWithMock(dst_bm, 'remove_memory_from_bank')
-        self.mox.StubOutWithMock(dst_bm, 'add_memory_to_bank')
+        self.mox.StubOutWithMock(dst_bm, 'get_mappings')
+        self.mox.StubOutWithMock(src_bm, 'get_mappings')
+        self.mox.StubOutWithMock(dst_bm, 'get_memory_mappings')
+        self.mox.StubOutWithMock(src_bm, 'get_memory_mappings')
+        self.mox.StubOutWithMock(dst_bm, 'remove_memory_from_mapping')
+        self.mox.StubOutWithMock(dst_bm, 'add_memory_to_mapping')
 
         dst_radio.get_bank_model().AndReturn(dst_bm)
-        dst_bm.get_banks().AndReturn(dst_banks)
+        dst_bm.get_mappings().AndReturn(dst_banks)
         src_radio.get_bank_model().AndReturn(src_bm)
-        src_bm.get_banks().AndReturn(src_banks)
-        src_bm.get_memory_banks(src_mem).AndReturn([src_banks[0]])
-        dst_bm.get_memory_banks(dst_mem).AndReturn([dst_banks[1]])
-        dst_bm.remove_memory_from_bank(dst_mem, dst_banks[1])
-        dst_bm.add_memory_to_bank(dst_mem, dst_banks[0])
+        src_bm.get_mappings().AndReturn(src_banks)
+        src_bm.get_memory_mappings(src_mem).AndReturn([src_banks[0]])
+        dst_bm.get_memory_mappings(dst_mem).AndReturn([dst_banks[1]])
+        dst_bm.remove_memory_from_mapping(dst_mem, dst_banks[1])
+        dst_bm.add_memory_to_mapping(dst_mem, dst_banks[0])
 
         self.mox.ReplayAll()
 
diff -r 66f225bbeb99 -r a11f2427091d tests/unit/test_mappingmodel.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/unit/test_mappingmodel.py	Mon Apr 01 15:30:46 2013 -0700
@@ -0,0 +1,274 @@
+# Copyright 2013 Dan Smith <dsmith at danplanet.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from tests.unit import base
+from chirp import chirp_common
+from chirp import icf
+
+class TestBaseMapping(base.BaseTest):
+    CLS = chirp_common.MemoryMapping
+
+    def test_mapping(self):
+        model = chirp_common.MappingModel(None, 'Foo')
+        mapping = self.CLS(model, 1, 'Foo')
+        self.assertEqual(str(mapping), 'Foo')
+        self.assertEqual(mapping.get_name(), 'Foo')
+        self.assertEqual(mapping.get_index(), 1)
+        self.assertEqual(repr(mapping), '%s-1' % self.CLS.__name__)
+        self.assertEqual(mapping._model, model)
+
+    def test_mapping_eq(self):
+        mapping1 = self.CLS(None, 1, 'Foo')
+        mapping2 = self.CLS(None, 1, 'Bar')
+        mapping3 = self.CLS(None, 2, 'Foo')
+
+        self.assertEqual(mapping1, mapping2)
+        self.assertNotEqual(mapping1, mapping3)
+
+class TestBaseBank(TestBaseMapping):
+    CLS = chirp_common.Bank
+
+class _TestBaseClass(base.BaseTest):
+    ARGS = tuple()
+
+    def setUp(self):
+        super(_TestBaseClass, self).setUp()
+        self.model = self.CLS(*self.ARGS)
+
+    def _test_base(self, method, *args):
+        self.assertRaises(NotImplementedError,
+                          getattr(self.model, method), *args)
+
+class TestBaseMappingModel(_TestBaseClass):
+    CLS = chirp_common.MappingModel
+    ARGS = tuple([None, 'Foo'])
+
+    def test_base_class(self):
+        methods = [('get_num_mappings', ()),
+                   ('get_mappings', ()),
+                   ('add_memory_to_mapping', (None, None)),
+                   ('remove_memory_from_mapping', (None, None)),
+                   ('get_mapping_memories', (None,)),
+                   ('get_memory_mappings', (None,)),
+                   ]
+        for method, args in methods:
+            self._test_base(method, *args)
+
+    def test_get_name(self):
+        self.assertEqual(self.model.get_name(), 'Foo')
+
+class TestBaseBankModel(TestBaseMappingModel):
+    ARGS = tuple([None])
+    CLS = chirp_common.BankModel
+
+    def test_get_name(self):
+        self.assertEqual(self.model.get_name(), 'Banks')
+
+class TestBaseMappingModelIndexInterface(_TestBaseClass):
+    CLS = chirp_common.MappingModelIndexInterface
+
+    def test_base_class(self):
+        methods = [('get_index_bounds', ()),
+                   ('get_memory_index', (None, None)),
+                   ('set_memory_index', (None, None, None)),
+                   ('get_next_mapping_index', (None,)),
+                   ]
+        for method, args in methods:
+            self._test_base(method, *args)
+
+class TestIcomBanks(TestBaseMapping):
+    def test_icom_bank(self):
+        bank = icf.IcomBank(None, 1, 'Foo')
+        # IcomBank has an index attribute used by IcomBankModel
+        self.assertTrue(hasattr(bank, 'index'))
+
+class TestIcomBankModel(base.BaseTest):
+    CLS = icf.IcomBankModel
+
+    def _get_rf(self):
+        rf = chirp_common.RadioFeatures()
+        rf.memory_bounds = (1, 10)
+        return rf
+
+    def setUp(self):
+        super(TestIcomBankModel, self).setUp()
+
+        class FakeRadio(icf.IcomCloneModeRadio):
+            _num_banks = 10
+            _bank_index_bounds = (0, 10)
+
+            def get_features(the_radio):
+                return self._get_rf()
+
+            def _set_bank(self, number, index):
+                pass
+
+            def _get_bank(self, number):
+                pass
+
+            def _get_bank_index(self, number):
+                pass
+
+            def _set_bank_index(self, number, index):
+                pass
+
+            def get_memory(self, number):
+                pass
+
+        self._radio = FakeRadio(None)
+        self._model = self.CLS(self._radio)
+        self.mox.StubOutWithMock(self._radio, '_set_bank')
+        self.mox.StubOutWithMock(self._radio, '_get_bank')
+        self.mox.StubOutWithMock(self._radio, '_set_bank_index')
+        self.mox.StubOutWithMock(self._radio, '_get_bank_index')
+        self.mox.StubOutWithMock(self._radio, 'get_memory')
+
+    def test_get_num_mappings(self):
+        self.assertEqual(self._model.get_num_mappings(), 10)
+
+    def test_get_mappings(self):
+        banks = self._model.get_mappings()
+        self.assertEqual(len(banks), 10)
+        i = 0
+        for bank in banks:
+            index = chr(ord("A") + i)
+            self.assertEqual(bank.get_index(), index)
+            self.assertEqual(bank.get_name(), 'BANK-%s' % index)
+            self.assertEqual(bank.index, i)
+            i += 1
+
+    def test_add_memory_to_mapping(self):
+        mem = chirp_common.Memory()
+        mem.number = 5
+        banks = self._model.get_mappings()
+        bank = banks[2]
+        self._radio._set_bank(5, 2)
+        self.mox.ReplayAll()
+        self._model.add_memory_to_mapping(mem, bank)
+
+    def _setup_test_remove_memory_from_mapping(self, curbank):
+        mem = chirp_common.Memory()
+        mem.number = 5
+        banks = self._model.get_mappings()
+        bank = banks[2]
+        self._radio._get_bank(5).AndReturn(curbank)
+        if curbank == 2:
+            self._radio._set_bank(5, None)
+        self.mox.ReplayAll()
+        return mem, bank
+
+    def test_remove_memory_from_mapping(self):
+        mem, bank = self._setup_test_remove_memory_from_mapping(2)
+        self._model.remove_memory_from_mapping(mem, bank)
+
+    def test_remove_memory_from_mapping_wrong_bank(self):
+        mem, bank = self._setup_test_remove_memory_from_mapping(3)
+        self.assertRaises(Exception,
+                          self._model.remove_memory_from_mapping, mem, bank)
+
+    def test_remove_memory_from_mapping_no_bank(self):
+        mem, bank = self._setup_test_remove_memory_from_mapping(None)
+        self.assertRaises(Exception,
+                          self._model.remove_memory_from_mapping, mem, bank)
+
+    def test_get_mapping_memories(self):
+        banks = self._model.get_mappings()
+        expected = []
+        for i in range(1, 10):
+            should_include = bool(i % 2)
+            self._radio._get_bank(i).AndReturn(
+                should_include and banks[1].index or None)
+            if should_include:
+                self._radio.get_memory(i).AndReturn(i)
+                expected.append(i)
+        self.mox.ReplayAll()
+        members = self._model.get_mapping_memories(banks[1])
+        self.assertEqual(members, expected)
+
+    def test_get_memory_mappings(self):
+        banks = self._model.get_mappings()
+        mem1 = chirp_common.Memory()
+        mem1.number = 5
+        mem2 = chirp_common.Memory()
+        mem2.number = 6
+        self._radio._get_bank(mem1.number).AndReturn(2)
+        self._radio._get_bank(mem2.number).AndReturn(None)
+        self.mox.ReplayAll()
+        self.assertEqual(self._model.get_memory_mappings(mem1)[0], banks[2])
+        self.assertEqual(self._model.get_memory_mappings(mem2), [])
+
+class TestIcomIndexedBankModel(TestIcomBankModel):
+    CLS = icf.IcomIndexedBankModel
+
+    def _get_rf(self):
+        rf = super(TestIcomIndexedBankModel, self)._get_rf()
+        rf.has_bank_index = True
+        return rf
+
+    def test_get_index_bounds(self):
+        self.assertEqual(self._model.get_index_bounds(), (0, 10))
+
+    def test_get_memory_index(self):
+        mem = chirp_common.Memory()
+        mem.number = 5
+        self._radio._get_bank_index(mem.number).AndReturn(1)
+        self.mox.ReplayAll()
+        self.assertEqual(self._model.get_memory_index(mem, None), 1)
+
+    def test_set_memory_index(self):
+        mem = chirp_common.Memory()
+        mem.number = 5
+        banks = self._model.get_mappings()
+        self.mox.StubOutWithMock(self._model, 'get_memory_mappings')
+        self._model.get_memory_mappings(mem).AndReturn([banks[3]])
+        self._radio._set_bank_index(mem.number, 1)
+        self.mox.ReplayAll()
+        self._model.set_memory_index(mem, banks[3], 1)
+
+    def test_set_memory_index_bad_bank(self):
+        mem = chirp_common.Memory()
+        mem.number = 5
+        banks = self._model.get_mappings()
+        self.mox.StubOutWithMock(self._model, 'get_memory_mappings')
+        self._model.get_memory_mappings(mem).AndReturn([banks[4]])
+        self.mox.ReplayAll()
+        self.assertRaises(Exception,
+                          self._model.set_memory_index, mem, banks[3], 1)
+
+    def test_set_memory_index_bad_index(self):
+        mem = chirp_common.Memory()
+        mem.number = 5
+        banks = self._model.get_mappings()
+        self.mox.StubOutWithMock(self._model, 'get_memory_mappings')
+        self._model.get_memory_mappings(mem).AndReturn([banks[3]])
+        self.mox.ReplayAll()
+        self.assertRaises(Exception,
+                          self._model.set_memory_index, mem, banks[3], 99)
+
+    def test_get_next_mapping_index(self):
+        banks = self._model.get_mappings()
+        for i in range(*self._radio.get_features().memory_bounds):
+            self._radio._get_bank(i).AndReturn((i % 2) and banks[1].index)
+            if bool(i % 2):
+                self._radio._get_bank_index(i).AndReturn(i)
+        idx = 0
+        for i in range(*self._radio.get_features().memory_bounds):
+            self._radio._get_bank(i).AndReturn((i % 2) and banks[2].index)
+            if i % 2:
+                self._radio._get_bank_index(i).AndReturn(idx)
+                idx += 1
+        self.mox.ReplayAll()
+        self.assertEqual(self._model.get_next_mapping_index(banks[1]), 0)
+        self.assertEqual(self._model.get_next_mapping_index(banks[2]), 5)



More information about the chirp_devel mailing list