# HG changeset patch
# User Zhaofeng Li <hello@zhaofeng.li>
# Date 1549691138 28800
#      Fri Feb 08 21:45:38 2019 -0800
# Branch py3
# Node ID 43b0ff04101924566c17de190dcce79515516edf
# Parent  7b4ced760655069500d74f232f4f01adc14cb009
[py3] bitwise.py: Python 3-ize

diff -r 7b4ced760655 -r 43b0ff041019 chirp/bitwise.py
--- a/chirp/bitwise.py	Fri Feb 08 13:15:15 2019 -0800
+++ b/chirp/bitwise.py	Fri Feb 08 21:45:38 2019 -0800
@@ -254,7 +254,7 @@
         return list(self.__items)
 
     def get_raw(self):
-        return "".join([item.get_raw() for item in self.__items])
+        return b"".join([item.get_raw() for item in self.__items])
 
     def __setitem__(self, index, val):
         self.__items[index].set_value(val)
@@ -371,9 +371,12 @@
     def __mul__(self, val):
         return self.get_value() * val
 
-    def __div__(self, val):
+    def __truediv__(self, val):
         return self.get_value() / val
 
+    def __floordiv__(self, val):
+        return self.get_value() // val
+
     def __add__(self, val):
         return self.get_value() + val
 
# HG changeset patch
# User Zhaofeng Li <hello@zhaofeng.li>
# Date 1549691161 28800
#      Fri Feb 08 21:46:01 2019 -0800
# Branch py3
# Node ID 076ea7f0fbcc0af8d630c62c619bc1cb0588ecb1
# Parent  43b0ff04101924566c17de190dcce79515516edf
[py3] chirp_common.py: Fix file saving

diff -r 43b0ff041019 -r 076ea7f0fbcc chirp/chirp_common.py
--- a/chirp/chirp_common.py	Fri Feb 08 21:45:38 2019 -0800
+++ b/chirp/chirp_common.py	Fri Feb 08 21:46:01 2019 -0800
@@ -1183,7 +1183,7 @@
         """
         try:
             mapfile = open(filename, "wb")
-            mapfile.write(self._mmap.get_packed())
+            mapfile.write(self._mmap.get_byte_compatible().get_packed())
             if filename.lower().endswith(".img"):
                 mapfile.write(self.MAGIC)
                 mapfile.write(self._make_metadata())
# HG changeset patch
# User Zhaofeng Li <hello@zhaofeng.li>
# Date 1549691367 28800
#      Fri Feb 08 21:49:27 2019 -0800
# Branch py3
# Node ID 877f5097b5b0b47bebc6eae90333affb162e09b0
# Parent  076ea7f0fbcc0af8d630c62c619bc1cb0588ecb1
[py3] uvb5.py: 2to3 with manual fixes

diff -r 076ea7f0fbcc -r 877f5097b5b0 chirp/drivers/uvb5.py
--- a/chirp/drivers/uvb5.py	Fri Feb 08 21:46:01 2019 -0800
+++ b/chirp/drivers/uvb5.py	Fri Feb 08 21:49:27 2019 -0800
@@ -176,7 +176,7 @@
 def do_ident(radio):
     radio.pipe.timeout = 3
     radio.pipe.write("\x05PROGRAM")
-    for x in xrange(10):
+    for x in range(10):
         ack = radio.pipe.read(1)
         if ack == '\x06':
             break
@@ -314,7 +314,7 @@
                           (220000000, 269000000),
                           (400000000, 520000000)]
         rf.valid_modes = ["FM", "NFM"]
-        rf.valid_special_chans = self.SPECIALS.keys()
+        rf.valid_special_chans = list(self.SPECIALS.keys())
         rf.valid_power_levels = POWER_LEVELS
         rf.has_ctone = True
         rf.has_bank = False
@@ -327,7 +327,7 @@
             self._mmap = do_download(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         self.process_mmap()
 
@@ -336,7 +336,7 @@
             do_upload(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
     def process_mmap(self):
@@ -384,7 +384,7 @@
         if isinstance(number, str):
             return (getattr(self._memobj, number.lower()), None)
         elif number < 0:
-            for k, v in SPECIALS.items():
+            for k, v in list(SPECIALS.items()):
                 if number == v:
                     return (getattr(self._memobj, k.lower()), None)
         else:
@@ -400,7 +400,7 @@
         else:
             mem.number = number
 
-        if _mem.freq.get_raw()[0] == "\xFF":
+        if _mem.freq.get_raw()[0] == 0xff:
             mem.empty = True
             return mem
 
@@ -630,7 +630,7 @@
                           RadioSettingValueBoolean(not _settings.ste_disabled))
         basic.append(rs)
 
-        _limit = int(self._memobj.limits.lower_vhf) / 10
+        _limit = int(self._memobj.limits.lower_vhf) // 10
         rs = RadioSetting("limits.lower_vhf", "VHF Lower Limit (MHz)",
                           RadioSettingValueInteger(128, 270, _limit))
 
@@ -640,7 +640,7 @@
         rs.set_apply_callback(apply_limit, self._memobj.limits)
         basic.append(rs)
 
-        _limit = int(self._memobj.limits.upper_vhf) / 10
+        _limit = int(self._memobj.limits.upper_vhf) // 10
         rs = RadioSetting("limits.upper_vhf", "VHF Upper Limit (MHz)",
                           RadioSettingValueInteger(128, 270, _limit))
 
@@ -650,7 +650,7 @@
         rs.set_apply_callback(apply_limit, self._memobj.limits)
         basic.append(rs)
 
-        _limit = int(self._memobj.limits.lower_uhf) / 10
+        _limit = int(self._memobj.limits.lower_uhf) // 10
         rs = RadioSetting("limits.lower_uhf", "UHF Lower Limit (MHz)",
                           RadioSettingValueInteger(400, 520, _limit))
 
@@ -660,7 +660,7 @@
         rs.set_apply_callback(apply_limit, self._memobj.limits)
         basic.append(rs)
 
-        _limit = int(self._memobj.limits.upper_uhf) / 10
+        _limit = int(self._memobj.limits.upper_uhf) // 10
         rs = RadioSetting("limits.upper_uhf", "UHF Upper Limit (MHz)",
                           RadioSettingValueInteger(400, 520, _limit))
 
@@ -769,7 +769,7 @@
                     else:
                         LOG.debug("Setting %s = %s" % (setting, element.value))
                         setattr(obj, setting, element.value)
-                except Exception, e:
+                except Exception as e:
                     LOG.debug(element.get_name())
                     raise
 
@@ -785,7 +785,7 @@
                 LOG.debug("Setting fm_presets[%1i] = %s" % (index, value))
                 setting = self._memobj.fm_presets
                 setting[index] = value
-            except Exception, e:
+            except Exception as e:
                 LOG.debug(element.get_name())
                 raise
 
# HG changeset patch
# User Zhaofeng Li <hello@zhaofeng.li>
# Date 1549694574 28800
#      Fri Feb 08 22:42:54 2019 -0800
# Branch py3
# Node ID 7418b296e2c6f4dc40470b78d936979986a6f9db
# Parent  877f5097b5b0b47bebc6eae90333affb162e09b0
[py3] uvb5.py: Adapt for new Serial

diff -r 877f5097b5b0 -r 7418b296e2c6 chirp/drivers/uvb5.py
--- a/chirp/drivers/uvb5.py	Fri Feb 08 21:49:27 2019 -0800
+++ b/chirp/drivers/uvb5.py	Fri Feb 08 22:42:54 2019 -0800
@@ -175,21 +175,21 @@
 
 def do_ident(radio):
     radio.pipe.timeout = 3
-    radio.pipe.write("\x05PROGRAM")
+    radio.pipe.write(b"\x05PROGRAM")
     for x in range(10):
         ack = radio.pipe.read(1)
-        if ack == '\x06':
+        if ack == b'\x06':
             break
     else:
         raise errors.RadioError("Radio did not ack programming mode")
-    radio.pipe.write("\x02")
+    radio.pipe.write(b"\x02")
     ident = radio.pipe.read(8)
     LOG.debug(util.hexprint(ident))
-    if not ident.startswith('HKT511'):
+    if not ident.startswith(b'HKT511'):
         raise errors.RadioError("Unsupported model")
-    radio.pipe.write("\x06")
+    radio.pipe.write(b"\x06")
     ack = radio.pipe.read(1)
-    if ack != "\x06":
+    if ack != b"\x06":
         raise errors.RadioError("Radio did not ack ident")
 
 
@@ -203,8 +203,8 @@
 
 def do_download(radio):
     do_ident(radio)
-    data = "KT511 Radio Program data v1.08\x00\x00"
-    data += ("\x00" * 16)
+    data = b"KT511 Radio Program data v1.08\x00\x00"
+    data += (b"\x00" * 16)
     firstack = None
     for i in range(0, 0x1000, 16):
         frame = struct.pack(">cHB", "R", i, 16)
@@ -213,7 +213,7 @@
         if frame[1:4] != result[1:4]:
             LOG.debug(util.hexprint(result))
             raise errors.RadioError("Invalid response for address 0x%04x" % i)
-        radio.pipe.write("\x06")
+        radio.pipe.write(b"\x06")
         ack = radio.pipe.read(1)
         if not firstack:
             firstack = ack
@@ -225,19 +225,19 @@
         data += result[4:]
         do_status(radio, "from", i)
 
-    return memmap.MemoryMap(data)
+    return memmap.MemoryMapBytes(data)
 
 
 def do_upload(radio):
     do_ident(radio)
-    data = radio._mmap[0x0030:]
+    data = radio._mmap.get_byte_compatible()[0x0030:]
 
     for i in range(0, 0x1000, 16):
-        frame = struct.pack(">cHB", "W", i, 16)
+        frame = struct.pack(">cHB", b"W", i, 16)
         frame += data[i:i + 16]
         radio.pipe.write(frame)
         ack = radio.pipe.read(1)
-        if ack != "\x06":
+        if ack != b"\x06":
             # UV-B5/UV-B6 radios with 27 menus do not support service settings
             # and will stop ACKing when the upload reaches 0x0F10
             if i == 0x0F10:
@@ -264,6 +264,7 @@
     VENDOR = "Baofeng"
     MODEL = "UV-B5"
     BAUD_RATE = 9600
+    NEEDS_COMPAT_SERIAL = False
     SPECIALS = {
         "VFO1": -2,
         "VFO2": -1,
# HG changeset patch
# User Zhaofeng Li <hello@zhaofeng.li>
# Date 1549694633 28800
#      Fri Feb 08 22:43:53 2019 -0800
# Branch py3
# Node ID d9f6791f09b8c015398efffd99bb74acee1fa43a
# Parent  7418b296e2c6f4dc40470b78d936979986a6f9db
[py3] memmap.py: Fix slicing

diff -r 7418b296e2c6 -r d9f6791f09b8 chirp/memmap.py
--- a/chirp/memmap.py	Fri Feb 08 22:42:54 2019 -0800
+++ b/chirp/memmap.py	Fri Feb 08 22:43:53 2019 -0800
@@ -57,7 +57,7 @@
 
     def get(self, start, length=1):
         """Return a chunk of memory of @length bytes from @start"""
-        if start == -1:
+        if length == -1:
             return data_type(self._data[start:])
         else:
             end = start + length
@@ -96,6 +96,9 @@
 
     def __getitem__(self, pos):
         if isinstance(pos, slice):
+            if pos.stop is None:
+                return self.get(pos.start, -1)
+
             return self.get(pos.start, pos.stop - pos.start)
         else:
             return self.get(pos)
# HG changeset patch
# User Zhaofeng Li <hello@zhaofeng.li>
# Date 1549694673 28800
#      Fri Feb 08 22:44:33 2019 -0800
# Branch py3
# Node ID 3012d240b25774bdf9fbd94e0b8cc107f3b018c8
# Parent  d9f6791f09b8c015398efffd99bb74acee1fa43a
[py3] memedit.py: Convert power to str

diff -r d9f6791f09b8 -r 3012d240b257 chirp/ui/memedit.py
--- a/chirp/ui/memedit.py	Fri Feb 08 22:43:53 2019 -0800
+++ b/chirp/ui/memedit.py	Fri Feb 08 22:44:33 2019 -0800
@@ -1122,7 +1122,7 @@
                        self.col(_("Duplex")), memory.duplex,
                        self.col(_("Offset")), memory.offset,
                        self.col(_("Mode")), memory.mode,
-                       self.col(_("Power")), memory.power or "",
+                       self.col(_("Power")), str(memory.power) or "",
                        self.col(_("Tune Step")), memory.tuning_step,
                        self.col(_("Skip")), memory.skip,
                        self.col(_("Comment")), memory.comment)
# HG changeset patch
# User Zhaofeng Li <hello@zhaofeng.li>
# Date 1549694726 28800
#      Fri Feb 08 22:45:26 2019 -0800
# Branch py3
# Node ID 4c864212fdf201ca7b341933d792a7309c4c70ee
# Parent  3012d240b25774bdf9fbd94e0b8cc107f3b018c8
[py3] th350.py: 2to3, with many manual fixes

diff -r 3012d240b257 -r 4c864212fdf2 chirp/drivers/th350.py
--- a/chirp/drivers/th350.py	Fri Feb 08 22:44:33 2019 -0800
+++ b/chirp/drivers/th350.py	Fri Feb 08 22:45:26 2019 -0800
@@ -18,7 +18,7 @@
 import logging
 from math import floor
 from chirp import chirp_common, directory, bitwise, memmap, errors, util
-from uvb5 import BaofengUVB5
+from .uvb5 import BaofengUVB5
 
 LOG = logging.getLogger(__name__)
 
@@ -176,21 +176,21 @@
 
 def do_ident(radio):
     radio.pipe.timeout = 3
-    radio.pipe.write("\x05TROGRAM")
-    for x in xrange(10):
+    radio.pipe.write(b"\x05TROGRAM")
+    for x in range(10):
         ack = radio.pipe.read(1)
-        if ack == '\x06':
+        if ack == b'\x06':
             break
     else:
         raise errors.RadioError("Radio did not ack programming mode")
-    radio.pipe.write("\x02")
+    radio.pipe.write(b"\x02")
     ident = radio.pipe.read(8)
     LOG.debug(util.hexprint(ident))
-    if not ident.startswith('HKT511'):
+    if not ident.startswith(b'HKT511'):
         raise errors.RadioError("Unsupported model")
-    radio.pipe.write("\x06")
+    radio.pipe.write(b"\x06")
     ack = radio.pipe.read(1)
-    if ack != "\x06":
+    if ack != b"\x06":
         raise errors.RadioError("Radio did not ack ident")
 
 
@@ -204,11 +204,11 @@
 
 def do_download(radio):
     do_ident(radio)
-    data = "TH350 Radio Program data v1.08\x00\x00"
-    data += ("\x00" * 16)
+    data = b"TRI350 Radio Program data v1.08\x00"
+    data += (b"\x00" * 16)
     firstack = None
     for i in range(0, 0x1000, 16):
-        frame = struct.pack(">cHB", "R", i, 16)
+        frame = struct.pack(">cHB", b"R", i, 16)
         radio.pipe.write(frame)
         result = radio.pipe.read(20)
         if frame[1:4] != result[1:4]:
@@ -217,19 +217,19 @@
         data += result[4:]
         do_status(radio, "from", i)
 
-    return memmap.MemoryMap(data)
+    return memmap.MemoryMapBytes(data)
 
 
 def do_upload(radio):
     do_ident(radio)
-    data = radio._mmap[0x0030:]
+    data = radio._mmap.get_byte_compatible()[0x0030:]
 
     for i in range(0, 0x1000, 16):
-        frame = struct.pack(">cHB", "W", i, 16)
+        frame = struct.pack(">cHB", b"W", i, 16)
         frame += data[i:i + 16]
         radio.pipe.write(frame)
         ack = radio.pipe.read(1)
-        if ack != "\x06":
+        if ack != b"\x06":
             # UV-B5/UV-B6 radios with 27 menus do not support service settings
             # and will stop ACKing when the upload reaches 0x0F10
             if i == 0x0F10:
@@ -255,6 +255,7 @@
     VENDOR = "TYT"
     MODEL = "TH-350"
     BAUD_RATE = 9600
+    NEEDS_COMPAT_SERIAL = False
     SPECIALS = {
         "VFO1": -3,
         "VFO2": -2,
@@ -290,7 +291,7 @@
                           (220000000, 269000000),
                           (400000000, 520000000)]
         rf.valid_modes = ["FM", "NFM"]
-        rf.valid_special_chans = self.SPECIALS.keys()
+        rf.valid_special_chans = list(self.SPECIALS.keys())
         rf.valid_power_levels = POWER_LEVELS
         rf.has_ctone = True
         rf.has_bank = False
@@ -303,7 +304,7 @@
             self._mmap = do_download(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
         self.process_mmap()
 
@@ -312,7 +313,7 @@
             do_upload(self)
         except errors.RadioError:
             raise
-        except Exception, e:
+        except Exception as e:
             raise errors.RadioError("Failed to communicate with radio: %s" % e)
 
     def process_mmap(self):
@@ -320,7 +321,7 @@
 
     def _decode_tone(self, _mem, which):
         def _get(field):
-            return getattr(_mem, "%s%s" % (which, field))
+            return int(getattr(_mem, "%s%s" % (which, field)))
 
         tonea, toneb = _get('tonea'), _get('toneb')
 
@@ -332,24 +333,24 @@
             # D754I -> 0xc7 0x54
             # Yes. Decimal digits as hex. You're seeing that right.
             # No idea why TYT engineers would do something like that.
-            pold = tonea / 16
+            pold = tonea // 16
             if pold not in [0x8, 0xc]:
                 LOG.warn("Bug: tone is %04x %04x" % (tonea, toneb))
                 mode = val = pol = None
             else:
                 mode = 'DTCS'
-                val = (tonea % 16) * 100 + \
-                    toneb / 16 * 10 + \
-                    (toneb % 16)
+                val = ((tonea % 16) * 100 +
+                        toneb // 16 * 10 +
+                        (toneb % 16))
                 pol = 'N' if pold == 8 else 'R'
         else:
             # Tone
             # 107.2 -> 0x10 0x72. Seriously.
             mode = 'Tone'
-            val = tonea / 16 * 100 + \
-                (tonea % 16) * 10 + \
-                toneb / 16 + \
-                float(toneb % 16) / 10
+            val = (tonea // 16 * 100 + 
+                    (tonea % 16) * 10 +
+                    toneb // 16 +
+                    toneb % 16 / 10)
             pol = None
 
         return mode, val, pol
@@ -360,8 +361,8 @@
 
         if mode == "Tone":
             tonea = int(
-                        floor(val / 100) * 16 +
-                        floor(val / 10) % 10
+                        val // 100 * 16 +
+                        val // 10 % 10
                     )
             toneb = int(
                         floor(val % 10) * 16 +
@@ -369,8 +370,8 @@
                     )
         elif mode == "DTCS":
             tonea = (0x80 if pol == 'N' else 0xc0) + \
-                val / 100
-            toneb = (val / 10) % 10 * 16 + \
+                val // 100
+            toneb = (val // 10) % 10 * 16 + \
                 val % 10
         else:
             tonea = toneb = 0xff
@@ -382,7 +383,7 @@
         if isinstance(number, str):
             return (getattr(self._memobj, number.lower()), None)
         elif number < 0:
-            for k, v in self.SPECIALS.items():
+            for k, v in list(self.SPECIALS.items()):
                 if number == v:
                     return (getattr(self._memobj, k.lower()), None)
         else:
@@ -391,5 +392,5 @@
 
     @classmethod
     def match_model(cls, filedata, filename):
-        return (filedata.startswith("TH350 Radio Program data") and
+        return (filedata.startswith("TRI350 Radio Program data") and
                 len(filedata) == (cls._memsize + 0x30))
