Skip to content

Commit db06041

Browse files
stephanelsmithdpgeorge
authored andcommitted
extmod/vfs_posix_file: Implement sys.std*.buffer objects.
Add the buffer attribute to sys.stdin, sys.stdout and sys.stderr. This provides raw access to underlying stdio streams for the unix port (and others that use VfsPosix). Signed-off-by: stephanelsmith <[email protected]>
1 parent 1c04774 commit db06041

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

extmod/vfs_posix_file.c

+46
Original file line numberDiff line numberDiff line change
@@ -274,12 +274,58 @@ STATIC const mp_stream_p_t vfs_posix_textio_stream_p = {
274274
.is_text = true,
275275
};
276276

277+
#if MICROPY_PY_SYS_STDIO_BUFFER
278+
279+
const mp_obj_vfs_posix_file_t mp_sys_stdin_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDIN_FILENO};
280+
const mp_obj_vfs_posix_file_t mp_sys_stdout_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDOUT_FILENO};
281+
const mp_obj_vfs_posix_file_t mp_sys_stderr_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDERR_FILENO};
282+
283+
// Forward declarations.
284+
const mp_obj_vfs_posix_file_t mp_sys_stdin_obj;
285+
const mp_obj_vfs_posix_file_t mp_sys_stdout_obj;
286+
const mp_obj_vfs_posix_file_t mp_sys_stderr_obj;
287+
288+
STATIC void vfs_posix_textio_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
289+
if (dest[0] != MP_OBJ_NULL) {
290+
// These objects are read-only.
291+
return;
292+
}
293+
294+
if (attr == MP_QSTR_buffer) {
295+
// Implement the `buffer` attribute only on std{in,out,err} instances.
296+
if (MP_OBJ_TO_PTR(self_in) == &mp_sys_stdin_obj) {
297+
dest[0] = MP_OBJ_FROM_PTR(&mp_sys_stdin_buffer_obj);
298+
return;
299+
}
300+
if (MP_OBJ_TO_PTR(self_in) == &mp_sys_stdout_obj) {
301+
dest[0] = MP_OBJ_FROM_PTR(&mp_sys_stdout_buffer_obj);
302+
return;
303+
}
304+
if (MP_OBJ_TO_PTR(self_in) == &mp_sys_stderr_obj) {
305+
dest[0] = MP_OBJ_FROM_PTR(&mp_sys_stderr_buffer_obj);
306+
return;
307+
}
308+
}
309+
310+
// Any other attribute - forward to locals dict.
311+
dest[1] = MP_OBJ_SENTINEL;
312+
};
313+
314+
#define VFS_POSIX_TEXTIO_TYPE_ATTR attr, vfs_posix_textio_attr,
315+
316+
#else
317+
318+
#define VFS_POSIX_TEXTIO_TYPE_ATTR
319+
320+
#endif // MICROPY_PY_SYS_STDIO_BUFFER
321+
277322
MP_DEFINE_CONST_OBJ_TYPE(
278323
mp_type_vfs_posix_textio,
279324
MP_QSTR_TextIOWrapper,
280325
MP_TYPE_FLAG_ITER_IS_STREAM,
281326
print, vfs_posix_file_print,
282327
protocol, &vfs_posix_textio_stream_p,
328+
VFS_POSIX_TEXTIO_TYPE_ATTR
283329
locals_dict, &vfs_posix_rawfile_locals_dict
284330
);
285331

tests/io/file_stdio.py

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22

33
print(sys.stdin.fileno())
44
print(sys.stdout.fileno())
5+
print(sys.stderr.fileno())

tests/io/file_stdio2.py

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Test sys.std*.buffer objects.
2+
3+
import sys
4+
5+
try:
6+
sys.stdout.buffer
7+
sys.stdin.buffer
8+
sys.stderr.buffer
9+
except AttributeError:
10+
print("SKIP")
11+
raise SystemExit
12+
13+
14+
# force cpython to flush after every print
15+
# this is to sequence stdout and stderr
16+
def print_flush(*args, **kwargs):
17+
try:
18+
print(*args, **kwargs, flush=True)
19+
except TypeError:
20+
print(*args, **kwargs)
21+
22+
23+
print_flush("==stdin==")
24+
print_flush(sys.stdin.buffer.fileno())
25+
26+
27+
print_flush("==stdout==")
28+
print_flush(sys.stdout.buffer.fileno())
29+
n_text = sys.stdout.write("The quick brown fox jumps over the lazy dog\n")
30+
sys.stdout.flush()
31+
n_binary = sys.stdout.buffer.write("The quick brown fox jumps over the lazy dog\n".encode("utf-8"))
32+
sys.stdout.buffer.flush()
33+
print_flush("n_text:{} n_binary:{}".format(n_text, n_binary))
34+
35+
# temporarily disabling unicode tests until future PR which fixes unicode write character count
36+
# n_text = sys.stdout.write("🚀")
37+
# sys.stdout.flush()
38+
# n_binary = sys.stdout.buffer.write("🚀".encode("utf-8"))
39+
# sys.stdout.buffer.flush()
40+
# print_flush("")
41+
# print_flush("n_text:{} n_binary:{}".format(n_text, n_binary))
42+
# n_text = sys.stdout.write("1🚀2a3α4b5β6c7γ8d9δ0ぁ1🙐")
43+
# sys.stdout.flush()
44+
# n_binary = sys.stdout.buffer.write("1🚀2a3α4b5β6c7γ8d9δ0ぁ1🙐".encode("utf-8"))
45+
# sys.stdout.buffer.flush()
46+
# print_flush("")
47+
# print_flush("n_text:{} n_binary:{}".format(n_text, n_binary))
48+
49+
50+
print_flush("==stderr==")
51+
print_flush(sys.stderr.buffer.fileno())
52+
n_text = sys.stderr.write("The quick brown fox jumps over the lazy dog\n")
53+
sys.stderr.flush()
54+
n_binary = sys.stderr.buffer.write("The quick brown fox jumps over the lazy dog\n".encode("utf-8"))
55+
sys.stderr.buffer.flush()
56+
print_flush("n_text:{} n_binary:{}".format(n_text, n_binary))
57+
58+
# temporarily disabling unicode tests until future PR which fixes unicode write character count
59+
# n_text = sys.stderr.write("🚀")
60+
# sys.stderr.flush()
61+
# n_binary = sys.stderr.buffer.write("🚀".encode("utf-8"))
62+
# sys.stderr.buffer.flush()
63+
# print_flush("")
64+
# print_flush("n_text:{} n_binary:{}".format(n_text, n_binary))
65+
# print_flush("")

0 commit comments

Comments
 (0)