From 868cb8c3dc6dd2fb83f72c4dcd9403c5e72ee8bf Mon Sep 17 00:00:00 2001 From: "Walter A. Boring IV" Date: Fri, 28 Aug 2026 14:36:59 -0400 Subject: [PATCH] fix: remove mutable class-level data: list = [] from RingBuffer (#269) The class-level annotation 'data: list = []' creates a single list shared among all instances. While __init__ already rebinds self.data = [], the class-level default is confusing and fragile. Remove the class-level default; move the annotation to __init__. Closes #250 --- ChangeLog.md | 2 ++ aprsd/utils/ring_buffer.py | 3 +-- tests/utils/test_ring_buffer.py | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index f57cc18..d85143f 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -14,6 +14,8 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Remove dead-code Python version guard in utils/__init__.py: both branches were identical [`aa43f60`](https://github.com/craigerl/aprsd/commit/aa43f60) +- Fix RingBuffer mutable class-level 'data: list = []' default — move to __init__ instance attribute [`aa43f60`](https://github.com/craigerl/aprsd/commit/aa43f60) + - Add reset() to @singleton decorator; update tests to use ClassName.reset() instead of ClassName.instance = None [`ef19aaa`](https://github.com/craigerl/aprsd/commit/ef19aaa) - Fix PacketTrack.keys/items/values — return list snapshots instead of live dict views outside the lock [`088436e`](https://github.com/craigerl/aprsd/commit/088436e) diff --git a/aprsd/utils/ring_buffer.py b/aprsd/utils/ring_buffer.py index 6db4dfe..e5ff442 100644 --- a/aprsd/utils/ring_buffer.py +++ b/aprsd/utils/ring_buffer.py @@ -2,11 +2,10 @@ class RingBuffer: """class that implements a not-yet-full buffer""" max: int = 100 - data: list = [] def __init__(self, size_max): self.max = size_max - self.data = [] + self.data: list = [] class __Full: """class that implements a full buffer""" diff --git a/tests/utils/test_ring_buffer.py b/tests/utils/test_ring_buffer.py index f8930d4..7092e09 100644 --- a/tests/utils/test_ring_buffer.py +++ b/tests/utils/test_ring_buffer.py @@ -142,3 +142,17 @@ class TestRingBuffer(unittest.TestCase): result = rb.get() self.assertEqual(len(result), 1) self.assertIn(2, result) + + def test_instances_do_not_share_data(self): + """RingBuffer instances must not share the class-level data list. + + Previously 'data: list = []' at class level created a single shared list + object. Even though __init__ rebinds self.data, this is a regression guard + to ensure two independently created instances have independent lists. + """ + rb1 = RingBuffer(5) + rb2 = RingBuffer(5) + rb1.append(42) + # rb2 should still be empty — class-level shared list would have 42 here + self.assertEqual(len(rb2), 0) + self.assertIsNot(rb1.data, rb2.data)