Skip to content

Commit ef6fb66

Browse files
committed
docs/uio: Describe differences between uPy an CPy stream hierarchy.
1 parent 6947a7f commit ef6fb66

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

docs/library/uio.rst

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,71 @@
77
This module contains additional types of stream (file-like) objects
88
and helper functions.
99

10+
Conceptual hierarchy
11+
--------------------
12+
13+
.. admonition:: Difference to CPython
14+
:class: attention
15+
16+
Conceptual hierarchy of stream base classes is simplified in MicroPython,
17+
as described in this section.
18+
19+
(Abstract) base stream classes, which serve as a foundation for behavior
20+
of all the concrete classes, adhere to few dichotomies (pair-wise
21+
classifications) in CPython. In MicroPython, they are somewhat simplified
22+
and made implicit to achieve higher efficiencies and save resources.
23+
24+
An important dichotomy in CPython is unbuffered vs buffered streams. In
25+
MicroPython, all streams are currently unbuffered. This is because all
26+
modern OSes, and even many RTOSes and filesystem drivers already perform
27+
buffering on their side. Adding another later of buffering is counter-
28+
productive (an issue known as "bufferbloat") and spends precious memory.
29+
Note that there still cases where buffering may be useful, so we may
30+
introduce optional buffering support at a later time.
31+
32+
But in CPython, another important dichotomy is tied with "bufferedness" -
33+
it's whether a stream may incur short read/writes or not. A short read
34+
is when a user asks e.g. 10 bytes from a stream, but gets less, similarly
35+
for writes. In CPython, unbuffered streams are automatically short
36+
operation susceptible, while buffered are guarantee against them. The
37+
no short read/writes is an important traits, as it allows to develop
38+
more concise and efficient programs - something which is highly desirable
39+
for MicroPython. So, while MicroPython doesn't support buffered streams,
40+
it still provides for no-short-operations streams. Whether there will
41+
be short operations or not depends on each particular class' needs, but
42+
developers are strongly advised to favor no-short-operations behavior
43+
for the reasons stated above. For example, MicroPython sockets are
44+
guaranteed to avoid short read/writes. Actually, at this time, there is
45+
no example of a short-operations stream class in the core, and one would
46+
be a port-specific class, where such a need is governed by hardware
47+
peculiarities.
48+
49+
The no-short-operations behavior gets tricky in case of non-blocking
50+
streams, blockedness vs non-blockedness being another CPython dichotomy,
51+
fully supported by MicroPython. Non-blocking streams never wait for
52+
data either to arrive or be written - they read/write whatever possible,
53+
or signal lack of data (or ability to write data). Clearly, this conflicts
54+
with "no-short-operations" policy, and indeed, a case of non-blocking
55+
buffered (and this no-short-ops) streams is convoluted in CPython - in
56+
some places, such combination is prohibited, in some it's undefined or
57+
just not documented, in some cases it raises verbose exceptions. The
58+
matter is much simpler in MicroPython: non-blocking stream are important
59+
for efficient asynchronuous operations, so this property prevails on
60+
the "no-short-ops" one. So, while blocking streams will avoid short
61+
reads/writes whenever possible (the only case to get a short read is
62+
if end of file is reached, or in case of error (but errors don't
63+
return short data, but raise exceptions)), non-blocking streams may
64+
produce short data to avoid blocking the operation.
65+
66+
The final dichotomy is binary vs text streams. MicroPython of course
67+
supports these, but while in CPython text streams are inherently
68+
buffered, they aren't in MicroPython. (Indeed, that's one of the cases
69+
for which we may introduce buffering support.)
70+
71+
Note that for efficiency, MicroPython doesn't provide abstract base
72+
classes corresponding to the hierarchy above, and it's not possible
73+
to implement, or subclass, a stream class in pure Python.
74+
1075
Functions
1176
---------
1277

0 commit comments

Comments
 (0)