# HG changeset patch
# User Zhaofeng Li <hello@zhaofeng.li>
# Date 1549691367 28800
#      Fri Feb 08 21:49:27 2019 -0800
# Branch py3
# Node ID 42adf7c4b6674ca89d9e8dfb9a7cfad44897206a
# Parent  ecd9578bfd2ebf6ff3bdde3fcc61acc845b3e808
[py3] uvb5.py: 2to3 with manual fixes

diff -r ecd9578bfd2e -r 42adf7c4b667 chirp/drivers/uvb5.py
--- a/chirp/drivers/uvb5.py	Sat Feb 09 13:39:07 2019 -0800
+++ b/chirp/drivers/uvb5.py	Fri Feb 08 21:49:27 2019 -0800
@@ -13,6 +13,8 @@
 # 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 __future__ import division
+
 import struct
 import logging
 from chirp import chirp_common, directory, bitwise, memmap, errors, util
@@ -176,7 +178,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 +316,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 +329,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 +338,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 +386,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 +402,7 @@
         else:
             mem.number = number
 
-        if _mem.freq.get_raw()[0] == "\xFF":
+        if _mem.freq.get_raw(asbytes=True)[0] == 0xff:
             mem.empty = True
             return mem
 
@@ -630,7 +632,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 +642,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 +652,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 +662,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 +771,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
 
@@ -778,14 +780,14 @@
             try:
                 index = (int(element.get_name().split("_")[-1]))
                 val = element.value
-                if val[0].get_value():
-                    value = int(val[1].get_value() * 10 - 650)
+                if list(val)[0].get_value():
+                    value = int(list(val)[1].get_value() * 10 - 650)
                 else:
                     value = 0x01AF
                 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 6343ceb248e32a21ab4f954c57e878c9477651c9
# Parent  42adf7c4b6674ca89d9e8dfb9a7cfad44897206a
[py3] uvb5.py: Adapt for new Serial

diff -r 42adf7c4b667 -r 6343ceb248e3 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
@@ -177,21 +177,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")
 
 
@@ -205,8 +205,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)
@@ -215,7 +215,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
@@ -227,19 +227,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:
@@ -266,6 +266,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 1549763351 28800
#      Sat Feb 09 17:49:11 2019 -0800
# Branch py3
# Node ID aa1502dc34d4c8e66dc87b82a34931c6aefc91a2
# Parent  6343ceb248e32a21ab4f954c57e878c9477651c9
[py3] th350.py: 2to3, with many manual fixes

diff -r 6343ceb248e3 -r aa1502dc34d4 chirp/drivers/th350.py
--- a/chirp/drivers/th350.py	Fri Feb 08 22:42:54 2019 -0800
+++ b/chirp/drivers/th350.py	Sat Feb 09 17:49:11 2019 -0800
@@ -14,11 +14,13 @@
 # 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 __future__ import division
+
 import struct
 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 +178,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 +206,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 +219,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 +257,7 @@
     VENDOR = "TYT"
     MODEL = "TH-350"
     BAUD_RATE = 9600
+    NEEDS_COMPAT_SERIAL = False
     SPECIALS = {
         "VFO1": -3,
         "VFO2": -2,
@@ -290,7 +293,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 +306,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 +315,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 +323,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 +335,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 +363,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 +372,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 +385,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 +394,5 @@
 
     @classmethod
     def match_model(cls, filedata, filename):
-        return (filedata.startswith("TH350 Radio Program data") and
+        return (filedata.startswith(b"TRI350 Radio Program data") and
                 len(filedata) == (cls._memsize + 0x30))
# HG changeset patch
# User Zhaofeng Li <hello@zhaofeng.li>
# Date 1549764368 28800
#      Sat Feb 09 18:06:08 2019 -0800
# Branch py3
# Node ID 826e5f1a7a514a03bc0bdae687bd321b439a51aa
# Parent  aa1502dc34d4c8e66dc87b82a34931c6aefc91a2
[py3] bitwise.py: Always return a bytes-compatible object when asbytes=True

This commit ensures that drivers that ask for bytes representations will always
get bytes or a bytes-compatible object, whether on Python 2 or 3.

python-future provides a mostly-complete implementation of bytes for Python 2.

diff -r aa1502dc34d4 -r 826e5f1a7a51 chirp/bitwise.py
--- a/chirp/bitwise.py	Sat Feb 09 17:49:11 2019 -0800
+++ b/chirp/bitwise.py	Sat Feb 09 18:06:08 2019 -0800
@@ -62,6 +62,7 @@
 import logging
 
 import six
+from builtins import bytes
 
 from chirp import bitwise_grammar
 from chirp.memmap import MemoryMap
@@ -215,7 +216,7 @@
     def get_raw(self, asbytes=False):
         raw = self._data[self._offset:self._offset+self._size]
         if asbytes:
-            return raw
+            return bytes(raw)
         else:
             return string_straight_decode(raw)
 
@@ -260,7 +261,7 @@
     def get_raw(self, asbytes=False):
         raw = [item.get_raw(asbytes=asbytes) for item in self.__items]
         if asbytes:
-            return b''.join(raw)
+            return bytes(b''.join(raw))
         else:
             return "".join(raw)
 
@@ -793,7 +794,7 @@
         size = self.size() // 8
         raw = self._data[self._offset:self._offset+size]
         if asbytes:
-            return raw
+            return bytes(raw)
         else:
             return string_straight_decode(raw)
 
diff -r aa1502dc34d4 -r 826e5f1a7a51 requirements.txt
--- a/requirements.txt	Sat Feb 09 17:49:11 2019 -0800
+++ b/requirements.txt	Sat Feb 09 18:06:08 2019 -0800
@@ -1,3 +1,4 @@
 six
 PyGObject
 pyserial
+future
