Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package chirp for openSUSE:Factory checked in at 2025-10-04 18:51:43 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/chirp (Old) and /work/SRC/openSUSE:Factory/.chirp.new.11973 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "chirp" Sat Oct 4 18:51:43 2025 rev:40 rq:1308886 version:20251003 Changes: -------- --- /work/SRC/openSUSE:Factory/chirp/chirp.changes 2025-09-26 22:28:00.370824489 +0200 +++ /work/SRC/openSUSE:Factory/.chirp.new.11973/chirp.changes 2025-10-04 18:53:16.326843840 +0200 @@ -1,0 +2,7 @@ +Fri Oct 3 16:24:19 UTC 2025 - Andreas Stieger <[email protected]> + +- Update to version 20251003: + * uvk5: Fix step index list + * bitwise: Add memory union support + +------------------------------------------------------------------- Old: ---- chirp-20250926.obscpio New: ---- chirp-20251003.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ chirp.spec ++++++ --- /var/tmp/diff_new_pack.6zikJZ/_old 2025-10-04 18:53:16.886867168 +0200 +++ /var/tmp/diff_new_pack.6zikJZ/_new 2025-10-04 18:53:16.886867168 +0200 @@ -19,7 +19,7 @@ %define pythons python3 Name: chirp -Version: 20250926 +Version: 20251003 Release: 0 Summary: Tool for programming amateur radio sets License: GPL-3.0-only ++++++ _service ++++++ --- /var/tmp/diff_new_pack.6zikJZ/_old 2025-10-04 18:53:16.938869334 +0200 +++ /var/tmp/diff_new_pack.6zikJZ/_new 2025-10-04 18:53:16.942869501 +0200 @@ -4,8 +4,8 @@ <param name="scm">git</param> <param name="changesgenerate">enable</param> <param name="filename">chirp</param> - <param name="versionformat">20250926</param> - <param name="revision">b1d5cb2acdbdb2c99407dacce0ef952a3786c3cf</param> + <param name="versionformat">20251003</param> + <param name="revision">bf848935eef3a739948a4a6c3ef8b5a31807481e</param> </service> <service mode="manual" name="set_version"/> <service name="tar" mode="buildtime"/> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.6zikJZ/_old 2025-10-04 18:53:16.970870668 +0200 +++ /var/tmp/diff_new_pack.6zikJZ/_new 2025-10-04 18:53:16.974870834 +0200 @@ -1,7 +1,7 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/kk7ds/chirp.git</param> - <param name="changesrevision">b1d5cb2acdbdb2c99407dacce0ef952a3786c3cf</param> + <param name="changesrevision">bf848935eef3a739948a4a6c3ef8b5a31807481e</param> </service> </servicedata> (No newline at EOF) ++++++ chirp-20250926.obscpio -> chirp-20251003.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/chirp-20250926/chirp/bitwise.py new/chirp-20251003/chirp/bitwise.py --- old/chirp-20250926/chirp/bitwise.py 2025-09-26 01:10:11.000000000 +0200 +++ new/chirp-20251003/chirp/bitwise.py 2025-10-03 00:42:47.000000000 +0200 @@ -41,6 +41,10 @@ # u8 foo; # u16 bar; # } baz; /* Structure with u8 and u16 */ +# union { +# u16 whole; +# bbcd digits[2]; +# }; /* Union where all elements occupy the same memory */ # # Example directives: # @@ -785,7 +789,10 @@ class structDataElement(DataElement): def __repr__(self): - s = "struct {" + os.linesep + return self._make_repr('struct') + + def _make_repr(self, typename): + s = typename + " {" + os.linesep for prop in self._keys: s += " %15s: %s%s" % (prop, repr(self._generators[prop]), os.linesep) @@ -887,6 +894,20 @@ yield key, self._generators[key] +class unionDataElement(structDataElement): + def __repr__(self): + return self._make_repr('union') + + def set_union_size(self, size): + # We don't know the size of the union until we have processed the first + # member, so allow this to be set after creation. + assert (size % 8 == 0) + self.__dict__['_size'] = size + + def size(self): + return self._size + + def parse_count(string): if string.startswith('0x'): return int(string, 16) @@ -1073,6 +1094,51 @@ else: raise Exception("Internal error: What is `%s'?" % struct[0][0]) + def parse_union(self, union): + deftype = union[-1] + block = union[:-1] + union_size = 0 + tmp = self._generators + + if deftype[0] == "array": + name = deftype[1][0][1] + count = parse_count(deftype[1][1][1]) + elif deftype[0] == "symbol": + name = deftype[1] + count = 1 + + result = arrayDataElement(self._offset) + for i in range(0, count): + start_of_union_offset = self._offset + self._generators = element = unionDataElement( + self._data, + start_of_union_offset, + name=name) + for t, d in block: + self._offset = start_of_union_offset + if t not in ("definition", "struct", "union"): + raise ParseError("Not supported in union: %s" % t) + self.parse_statement(t, d) + size = self._offset - start_of_union_offset + if union_size == 0: + union_size = size + elif union_size != size: + LOG.error('Union member size mismatch parsing %s', name) + raise ParseError('Union members must be the same size ' + '(found %i, expected %i)' % (size, + union_size)) + element.set_union_size(union_size * 8) + if union_size == 0: + raise ParseError('Empty union %r is not valid' % name) + # Increment the offset only past the end of the union + self._offset = start_of_union_offset + union_size + result.append(element) + + self._generators = tmp + if count == 1: + result = result[0] + self._generators[name] = result + def assert_negative_seek(self, message): warnings.warn(message, DeprecationWarning, stacklevel=6) @@ -1097,14 +1163,19 @@ LOG.debug("%s: %i (0x%08X)" % (value[1:-1], self._offset, self._offset)) + def parse_statement(self, type_, data): + if type_ == "struct": + self.parse_struct(data) + elif type_ == "definition": + self.parse_defn(data) + elif type_ == "directive": + self.parse_directive(data) + elif type_ == "union": + self.parse_union(data) + def parse_block(self, lang): for t, d in lang: - if t == "struct": - self.parse_struct(d) - elif t == "definition": - self.parse_defn(d) - elif t == "directive": - self.parse_directive(d) + self.parse_statement(t, d) def parse(self, lang): self._lines = {} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/chirp-20250926/chirp/bitwise_grammar.py new/chirp-20251003/chirp/bitwise_grammar.py --- old/chirp-20250926/chirp/bitwise_grammar.py 2025-09-26 01:10:11.000000000 +0200 +++ new/chirp-20251003/chirp/bitwise_grammar.py 2025-10-03 00:42:47.000000000 +0200 @@ -75,7 +75,7 @@ def _block_inner(): - return -2, [definition, struct, directive] + return -2, [definition, struct, union, directive] def _block(): @@ -94,6 +94,10 @@ return keyword("struct"), [struct_defn, struct_decl], ";" +def union(): + return keyword("union"), _block, [array, symbol], ";" + + def _language(): return _block_inner diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/chirp-20250926/chirp/drivers/uvk5.py new/chirp-20251003/chirp/drivers/uvk5.py --- old/chirp-20250926/chirp/drivers/uvk5.py 2025-09-26 01:10:11.000000000 +0200 +++ new/chirp-20251003/chirp/drivers/uvk5.py 2025-10-03 00:42:47.000000000 +0200 @@ -613,7 +613,7 @@ _expanded_limits = False _upload_calibration = False _pttid_list = ["off", "BOT", "EOT", "BOTH"] - _steps = [1.0, 2.5, 5.0, 6.25, 10.0, 12.5, 25.0, 8.33] + _steps = [2.5, 5.0, 6.25, 10.0, 12.5, 25.0] _langs = ["Chinese", "English"] _backlight = ["Off"] + ['%is' % (i + 1) for i in range(5)] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/chirp-20250926/tests/unit/test_bitwise.py new/chirp-20251003/tests/unit/test_bitwise.py --- old/chirp-20250926/tests/unit/test_bitwise.py 2025-09-26 01:10:11.000000000 +0200 +++ new/chirp-20251003/tests/unit/test_bitwise.py 2025-10-03 00:42:47.000000000 +0200 @@ -395,6 +395,120 @@ self.assertEqual(ord('1'), obj.foo[0].bar) +class TestBitwiseUnionTypes(BaseTest): + def test_union_one_element(self): + defn = 'union { u8 bar; } foo;' + data = memmap.MemoryMapBytes(bytes(b'\x80')) + obj = bitwise.parse(defn, data) + self.assertEqual(128, obj.foo.bar) + + def test_union_two_elements(self): + defn = 'union { u8 bar; u8 baz; } foo;' + data = memmap.MemoryMapBytes(bytes(b'\x80')) + obj = bitwise.parse(defn, data) + self.assertEqual(128, obj.foo.bar) + self.assertEqual(128, obj.foo.baz) + obj.foo.baz = 1 + self.assertEqual(1, obj.foo.baz) + self.assertEqual(1, obj.foo.bar) + obj.foo.bar = 2 + self.assertEqual(2, obj.foo.baz) + self.assertEqual(2, obj.foo.bar) + + def test_empty_union(self): + defn = 'union { } foo;' + data = memmap.MemoryMapBytes(bytes(b'\x80')) + self.assertRaises(SyntaxError, bitwise.parse, defn, data) + + def test_union_size_mismatch(self): + defn = 'union { u16 bar; u8 baz; } foo;' + data = memmap.MemoryMapBytes(bytes(b'\x80')) + self.assertRaises(bitwise.ParseError, bitwise.parse, defn, data) + + def test_union_adjacent(self): + # Make sure that unions don't mess up adjacent fields + defn = 'u8 pre; union { u8 bar; u8 baz; } foo; u8 post;' + data = memmap.MemoryMapBytes(bytes(b'\x01\x02\x03')) + obj = bitwise.parse(defn, data) + self.assertEqual(1, obj.pre) + self.assertEqual(2, obj.foo.bar) + self.assertEqual(2, obj.foo.baz) + self.assertEqual(3, obj.post) + obj.pre = 4 + obj.foo.baz = 5 + obj.post = 6 + self.assertEqual(4, obj.pre) + self.assertEqual(5, obj.foo.bar) + self.assertEqual(5, obj.foo.baz) + self.assertEqual(6, obj.post) + + def test_complex_union(self): + defn = """u8 pre; + union { + u16 whole; + struct { u8 lo; u8 hi; } bytes; + union { u16 big; ul16 little; } endian; + bbcd digits[2]; + } foo; + u8 post; + """ + data = memmap.MemoryMapBytes(bytes(b'\x01\x02\x03\x04')) + obj = bitwise.parse(defn, data) + + self.assertEqual(1, obj.pre) + self.assertEqual(4, obj.post) + self.assertEqual(0x0203, obj.foo.whole) + self.assertEqual(2, obj.foo.bytes.lo) + self.assertEqual(3, obj.foo.bytes.hi) + self.assertEqual(0x0203, obj.foo.endian.big) + self.assertEqual(0x0302, obj.foo.endian.little) + self.assertEqual(2, int(obj.foo.digits[0])) + self.assertEqual(3, int(obj.foo.digits[1])) + + obj.foo.bytes.lo = 5 + self.assertEqual(1, obj.pre) + self.assertEqual(4, obj.post) + self.assertEqual(0x0503, obj.foo.whole) + self.assertEqual(5, obj.foo.bytes.lo) + self.assertEqual(3, obj.foo.bytes.hi) + self.assertEqual(0x0503, obj.foo.endian.big) + self.assertEqual(0x0305, obj.foo.endian.little) + self.assertEqual(5, int(obj.foo.digits[0])) + self.assertEqual(3, int(obj.foo.digits[1])) + + def test_union_array(self): + defn = 'union { u8 bar; u8 baz; } foo[2];' + data = memmap.MemoryMapBytes(bytes(b'\x01\x02')) + obj = bitwise.parse(defn, data) + self.assertEqual(1, obj.foo[0].bar) + self.assertEqual(1, obj.foo[0].baz) + self.assertEqual(2, obj.foo[1].bar) + self.assertEqual(2, obj.foo[1].baz) + obj.foo[0].bar = 3 + obj.foo[1].baz = 4 + self.assertEqual(3, obj.foo[0].bar) + self.assertEqual(3, obj.foo[0].baz) + self.assertEqual(4, obj.foo[1].bar) + self.assertEqual(4, obj.foo[1].baz) + + def test_struct_size_with_union(self): + # Make sure to include a bitfield at the start of the union to + # confirm that we properly account for the union size separately. + defn = ('struct { u8 pre; union { u8 bar1:4, bar2:4; u8 baz; } foo; ' + 'u8 post; } st;') + data = memmap.MemoryMapBytes(bytes(b'\x01\x02\x03')) + obj = bitwise.parse(defn, data) + # Make sure the union is counted as a single byte + self.assertEqual(8 * 3, obj.st.size()) + + # Make sure raw operations work across unions + obj.st.set_raw(b'\x00' * 3) + self.assertEqual(0, obj.st.foo.bar1) + obj.st.fill_raw(b'\xFF') + self.assertEqual(0x0F, obj.st.foo.bar1) + self.assertEqual(b'\xFF\xFF\xFF', obj.st.get_raw()) + + class TestBitwisePrintoffset(BaseTest): @mock.patch.object(bitwise.LOG, 'debug') def test_printoffset(self, mock_log): ++++++ chirp.obsinfo ++++++ --- /var/tmp/diff_new_pack.6zikJZ/_old 2025-10-04 18:53:18.094917491 +0200 +++ /var/tmp/diff_new_pack.6zikJZ/_new 2025-10-04 18:53:18.102917823 +0200 @@ -1,5 +1,5 @@ name: chirp -version: 20250926 -mtime: 1758841811 -commit: b1d5cb2acdbdb2c99407dacce0ef952a3786c3cf +version: 20251003 +mtime: 1759444967 +commit: bf848935eef3a739948a4a6c3ef8b5a31807481e
