Highlights
๐ Fix device restore hanging after reset() (regression since v9.40.0)
A device restore/update could hang indefinitely at If the restore hangs here, disconnect & reconnect the device: IRecv._find() would spin forever and never re-acquire the device after a USB reset() ("no device in the desired mode"), even though the device was present โ a fresh re-run of the restore would then succeed.
Root cause: the v9.40.0 typing cleanup introduced local captures (device = self.device) in send_buffer(), which calls reset() โ _reinit() while that local is still live. Setting self._device = None therefore no longer dropped the last reference, so the usb.core.Device was never garbage-collected and its libusb handle stayed claimed โ blocking the reset device from re-enumerating and hanging the subsequent _find(). _reinit() now releases the handle explicitly via usb.util.dispose_resources(), independent of refcount/GC.
If you hit this on v9.40.0โv10.0.3, upgrade:
python3 -m pip install -U pymobiledevice3๐งน Static-typing hardening (no user-facing behavior change)
The package is now considerably more strictly typed, which surfaced and fixed several latent bugs along the way. The DTX and CoreDevice-tunnel wire structs moved to construct's typed DataclassStruct API (byte-identical wire format, verified on both the Python 3.9 and 3.10+ construct-typing lines), all bare dict/list generics were parametrized, and every function parameter is now annotated โ with reportMissingTypeArgument and reportMissingParameterType enforced package-wide in CI.
What's Changed
- 8322b59 irecv: dispose the USB handle in _reinit to fix restore hang after reset (#1799) (@doronz88)
- 88aadb4 typing: finish reportMissingParameterType โ cycle 3 + enforce globally (#1797) (@doronz88)
- 24fb309 typing: param annotations for the rest of web_protocol (cycle 2b) (#1797) (@doronz88)
- 183cebd typing: param annotations for web_protocol survivors (cycle 2a) (#1797) (@doronz88)
- 2cdbc6e typing: annotate unannotated params (slice 1 of reportMissingParameterType) (#1797) (@doronz88)
- 82e5a66 tunnel: type CDTunnelPacket / RPPairingPacket with construct_typed (#1796) (@doronz88)
- 887cb4b construct: extract the csfield_const version shim into construct_compat (#1795) (@doronz88)
- 5d3474b dtx: type the DTX wire structs with construct_typed (DataclassStruct) (#1795) (@doronz88)
- 6b1ffba typing: enforce reportMissingTypeArgument globally (final slice) (#1794) (@doronz88)
- c3befab typing: parametrize bare dict/list generics (slice 3 of reportMissingTypeArgument) (#1793) (@doronz88)
- 26323c1 typing: parametrize bare dict/list generics (slice 2 of reportMissingTypeArgument) (#1792) (@doronz88)
- af68af2 typing: parametrize bare dict/list generics (slice 1 of reportMissingTypeArgument) (#1791) (@doronz88)
Full Changelog: v10.0.3...v10.0.4