Skip to content

Commit 38300fe

Browse files
committed
WIP, prototype: Allow to override sys.stdout.
1 parent af3e454 commit 38300fe

File tree

6 files changed

+62
-7
lines changed

6 files changed

+62
-7
lines changed

py/modbuiltins.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ STATIC mp_obj_t mp_builtin_print(mp_uint_t n_args, const mp_obj_t *args, mp_map_
376376
end_data = mp_obj_str_get_data(end_elem->value, &end_len);
377377
}
378378
#if MICROPY_PY_IO
379-
mp_obj_t stream_obj = &mp_sys_stdout_obj;
379+
mp_obj_t stream_obj = mp_sys_stdout_print.data;
380380
mp_map_elem_t *file_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_file), MP_MAP_LOOKUP);
381381
if (file_elem != NULL && file_elem->value != mp_const_none) {
382382
stream_obj = file_elem->value;

py/modsys.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,12 @@ extern struct _mp_dummy_t mp_sys_stdout_obj;
4545
extern struct _mp_dummy_t mp_sys_stderr_obj;
4646

4747
#if MICROPY_PY_IO
48+
#if 1
49+
mp_print_t mp_sys_stdout_print = {&mp_sys_stdout_obj, (mp_print_strn_t)mp_stream_write};
50+
#else
4851
const mp_print_t mp_sys_stdout_print = {&mp_sys_stdout_obj, (mp_print_strn_t)mp_stream_write};
4952
#endif
53+
#endif
5054

5155
/// \constant version - Python language version that this implementation conforms to, as a string
5256
STATIC const MP_DEFINE_STR_OBJ(version_obj, "3.4.0");
@@ -106,7 +110,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit);
106110

107111
STATIC mp_obj_t mp_sys_print_exception(mp_uint_t n_args, const mp_obj_t *args) {
108112
#if MICROPY_PY_IO
109-
mp_obj_t stream_obj = &mp_sys_stdout_obj;
113+
mp_obj_t stream_obj = mp_sys_stdout_print.data;
110114
if (n_args > 1) {
111115
stream_obj = args[1];
112116
}
@@ -197,10 +201,25 @@ STATIC const mp_map_elem_t mp_module_sys_globals_table[] = {
197201

198202
STATIC MP_DEFINE_CONST_DICT(mp_module_sys_globals, mp_module_sys_globals_table);
199203

204+
mp_obj_dict_t *mp_module_sys_override;
205+
206+
STATIC void sys_setattr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
207+
if (attr == MP_QSTR_stdout) {
208+
mp_sys_stdout_print.data = dest[1];
209+
dest[0] = MP_OBJ_NULL;
210+
}
211+
}
212+
213+
STATIC const mp_obj_module_override_helper_t sys_overrides = {
214+
.overrides = &mp_module_sys_override,
215+
.setattr = sys_setattr,
216+
};
217+
200218
const mp_obj_module_t mp_module_sys = {
201219
.base = { &mp_type_module },
202220
.name = MP_QSTR_sys,
203221
.globals = (mp_obj_dict_t*)&mp_module_sys_globals,
222+
.override_helper = &sys_overrides,
204223
};
205224

206225
#endif

py/mpprint.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ typedef struct _mp_print_t {
5151
extern const mp_print_t mp_plat_print;
5252
#if MICROPY_PY_IO
5353
// 2) Wrapper for printing to sys.stdout.
54-
extern const mp_print_t mp_sys_stdout_print;
54+
extern /*const*/ mp_print_t mp_sys_stdout_print;
5555
#endif
5656

5757
int mp_print_str(const mp_print_t *print, const char *str);

py/obj.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,11 +676,19 @@ qstr mp_obj_code_get_name(const byte *code_info);
676676
mp_obj_t mp_identity(mp_obj_t self);
677677
MP_DECLARE_CONST_FUN_OBJ(mp_identity_obj);
678678

679+
// Helper structure to support overriding of attributes
680+
// in a builtin (ROM) module.
681+
typedef struct _mp_obj_module_override_helper_t {
682+
mp_obj_dict_t **overrides;
683+
mp_attr_fun_t setattr;
684+
} mp_obj_module_override_helper_t;
685+
679686
// module
680687
typedef struct _mp_obj_module_t {
681688
mp_obj_base_t base;
682689
qstr name;
683690
mp_obj_dict_t *globals;
691+
const mp_obj_module_override_helper_t *override_helper;
684692
} mp_obj_module_t;
685693
mp_obj_dict_t *mp_obj_module_get_globals(mp_obj_t self_in);
686694
// check if given module object is a package

py/objmodule.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include "py/runtime.h"
3434
#include "py/builtin.h"
3535

36+
STATIC const mp_map_t mp_builtin_module_map;
37+
3638
STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
3739
(void)kind;
3840
mp_obj_module_t *self = self_in;
@@ -54,6 +56,16 @@ STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
5456
mp_obj_module_t *self = self_in;
5557
if (dest[0] == MP_OBJ_NULL) {
5658
// load attribute
59+
if (self->override_helper) {
60+
mp_obj_dict_t *overrides = *self->override_helper->overrides;
61+
if (overrides != MP_OBJ_NULL) {
62+
mp_map_elem_t *elem = mp_map_lookup(&overrides->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
63+
if (elem != NULL) {
64+
dest[0] = elem->value;
65+
return;
66+
}
67+
}
68+
}
5769
mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
5870
if (elem != NULL) {
5971
dest[0] = elem->value;
@@ -71,8 +83,23 @@ STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
7183
} else
7284
#endif
7385
{
74-
// can't delete or store to fixed map
75-
return;
86+
#if 1
87+
if (self->override_helper) {
88+
if (*self->override_helper->overrides != MP_OBJ_NULL) {
89+
//printf("Found existing override\n");
90+
dict = *self->override_helper->overrides;
91+
} else {
92+
//printf("Creating new override\n");
93+
dict = mp_obj_new_dict(1);
94+
*self->override_helper->overrides = dict;
95+
}
96+
self->override_helper->setattr(self_in, attr, dest);
97+
} else
98+
#endif
99+
{
100+
// can't delete or store to fixed map
101+
return;
102+
}
76103
}
77104
}
78105
if (dest[1] == MP_OBJ_NULL) {
@@ -107,6 +134,7 @@ mp_obj_t mp_obj_new_module(qstr module_name) {
107134
o->base.type = &mp_type_module;
108135
o->name = module_name;
109136
o->globals = mp_obj_new_dict(MICROPY_MODULE_DICT_SIZE);
137+
o->override_helper = NULL;
110138

111139
// store __name__ entry in the module
112140
mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(module_name));

tests/basics/module2.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# uPy behaviour only: builtin modules are read-only
2-
import sys
2+
import micropython
33
try:
4-
sys.x = 1
4+
micropython.x = 1
55
except AttributeError:
66
print("AttributeError")

0 commit comments

Comments
 (0)