v3.32.4: rebuild the link on card insertion (the first attempt)
release / release (push) Has been cancelled

v3.32.2 fixed the endless re-arm, but on Windows the first attempt
still failed on the old link (seen in the confirmation log: the
"self._con.connect()" traceback) and only the retry recovered - a failed
init, a 2-4 s delay and a traceback in the log.

The monitor's insert path now marks the transport stale under
_CARD_LOCK, so the first equip attempt rebuilds the PC/SC link.  It also
covers a link created at a cardless startup (never connected).  The
rebuild still happens in the equip worker, never in the pyscard monitor
thread, and _ensure_transport releases the old link first.

Docs: the READMEs' troubleshooting bullet.
Tests: an insertion marks the transport for the rebuild.
1014 Python + 953 frontend green; simple-v462.
This commit is contained in:
2026-10-21 14:44:34 +03:00
parent 8a08f642d4
commit 7e8c483eb1
9 changed files with 83 additions and 8 deletions
+22
View File
@@ -444,6 +444,28 @@ class AutoEquipTests(unittest.TestCase):
self.assertIn('AUTO-EQUIP: init output:', out)
self.assertIn('ProtocolError: Connection failed', out)
def test_a_long_traceback_keeps_its_exception_line(self):
# cmd2 renders a rich-box traceback; a fixed head slice cut the
# exception itself off (seen live on Windows 2026-10-21), so the tail
# is always included.
srv = self.make_server(None)
def onecmd(cmd):
srv.app.card = SimpleNamespace(_scc='scc')
sys.stderr.write('Traceback (most recent call last):\n')
for i in range(30):
sys.stderr.write(' File "f%d", line %d, in step%d\n' % (i, i, i))
sys.stderr.write('CardConnectionException: No card is inserted\n')
srv.app.onecmd_plus_hooks = onecmd
with mock.patch.object(server, '_ensure_transport', lambda s: True), \
mock.patch.object(server, '_apply_equipped_card', lambda s: None), \
mock.patch('sys.stderr', new=StringIO()) as err:
self.assertFalse(server._auto_equip_attempt(srv))
out = err.getvalue()
self.assertIn('AUTO-EQUIP: init output:', out)
self.assertIn('CardConnectionException: No card is inserted', out)
def test_failed_attempt_unequips_the_half_initialized_shell(self):
calls = []
srv = self.make_server(None)