Reported in #262: on an emulated ESP32, MicroPython's WLAN.scan() always
returned [], ifconfig() reported 10.0.2.15/10.0.2.2/10.0.2.3, and
outbound sockets raised EHOSTUNREACH — while Arduino WiFi.h on the same
board and container scanned, connected on 192.168.4.x and completed real
HTTP requests. Two independent faults, both needed for the failure.
1. The MicroPython prelude injected a stub `network` module into
sys.modules unconditionally, so user code never reached the firmware
driver. The stub's hardcoded ifconfig() happens to be QEMU's SLIRP
defaults, which is why the symptom read so convincingly as a routing
bug.
2. hasWifi survived a language switch. It is a property of the compiled
sketch, set only by arduino-cli, but setBoardLanguageMode kept it — so
a board compiled once as Arduino carried that verdict into a later
MicroPython run. The source-scanning fallback only fires when hasWifi
is undefined, so it never got a chance, and the backend attaches the
`-nic` device only when wifi_enabled is true.
The stub is NOT removed, which is where this departs from the patch in
the issue. It exists for a reason the report didn't have: without a NIC,
`network.WLAN(STA_IF)` hangs forever waiting on peripheral status bits
QEMU never sets, tripping the FreeRTOS watchdog after ~26s. Deleting it
would trade a fake-but-working network for a hung board. It is now
conditional — real driver when a NIC is attached, stub when none is —
so both paths are honest.
Also kept: the ntptime and urequests stubs, which the issue's diff would
have dropped along with `network` (it removed the whole prelude block).
Those back 29 call sites in the 100-days gallery examples, which have no
emulated internet to reach regardless of the NIC.
The detector is now one shared function instead of two copies that could
disagree — the stub decision and the -nic decision MUST match. Folded in
`from network import WLAN`, which matched neither previous pattern: such
a sketch was judged WiFi-less and hung on the missing peripheral. The
existing tests re-implemented the detection inline, so they only ever
proved that copy self-consistent; the new ones call the shipped function.