uos.dupterm() behavior in underspecified, implementations broken
While not directly related to HW API, https://github.com/micropython/micropython/wiki/Hardware-API#os-module-additions specifies os.dupterm(), used for:
os.dupterm([stream_obj]) get or set duplication of controlling terminal, so that REPL can be redirected to UART or other (note: could allow to duplicate to multiple stream objs but that's arguably overkill and could anyway be done in Python by making a stream multiplexer)
Unfortunately, this description is not clear/detailed enough, or alternatively, current implementations of it in stmhal and cc3200 ports are not general or just broken. First of all, it should be made clear if the talk is about duplicating "controlling terminal", or replacing it. If there's talk about duplicating, then there should be immediate talk about non-blocking streams. Otherwise this line https://github.com/micropython/micropython/blob/master/cc3200/hal/cc3200_hal.c#L187 will simply hang the entire REPL, as it will wait until a character is available on that particular stream, ignoring all other input sources.
And then if there's requirement to non-blocking streams, it should be kept in mind that all other REPL sources should be non-blocking too, otherwise standard source can block custom installed one. But requirement of non-blocking sources is merely a minimal condition to get it all working, but working quite inefficiently and requiring weird workaround to not make it burn CPU cycles (and a battery of battery-powered device), e.g. https://github.com/micropython/micropython/blob/master/cc3200/hal/cc3200_hal.c#L196. So, next step is making requirement that REPL sources are pollable, and actually poll them.
That's quite a bunch of requirements to get it working in the general case, sure.
docs/library: Add description of "index" parameter to uos.dupterm().
Following on from #2891 (and previous discussions on dupterm) this is a proposal to extend uos.dupterm() behaviour to support multiple slots.
Current behaviour is slightly modified: currently uos.dupterm() with no args will return the current stream object. But with an additional (optional) argument to specify the index, this becomes messy. So the proposal is to remove this "getter" behaviour and instead return the previous stream object when a new one is set, ie:
old_stream0 = uos.dupterm(uart) # duplicate on uart and get previous stream (default slot 0)
old_stream1 = uos.dupterm(uart2, 1) # duplicate a second time in slot 1
...
# restore previous streams
uos.dupterm(old_stream0)
uos.dupterm(old_stream1, 1)
Also, the proposal is to use negative indices to indicate slots that are configured by default (if a port has multiple slots). So stmhal would have USB_VCP at index=-1, and indices 0, 1, 2, ... (up to some max, which could be dynamic depending if the slot is ever referenced) are for the user to configure (the user can also access the negative slot, to disable USB_VCP). And esp8266 could have UART0 at index=-1 and then webrepl goes on index=0 (and it would have just 2 solts).