Branch data Line data Source code
1 : : /*
2 : : * This file is part of the MicroPython project, http://micropython.org/
3 : : *
4 : : * The MIT License (MIT)
5 : : *
6 : : * Copyright (c) 2013-2019 Damien P. George
7 : : * Copyright (c) 2014-2015 Paul Sokolovsky
8 : : *
9 : : * Permission is hereby granted, free of charge, to any person obtaining a copy
10 : : * of this software and associated documentation files (the "Software"), to deal
11 : : * in the Software without restriction, including without limitation the rights
12 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 : : * copies of the Software, and to permit persons to whom the Software is
14 : : * furnished to do so, subject to the following conditions:
15 : : *
16 : : * The above copyright notice and this permission notice shall be included in
17 : : * all copies or substantial portions of the Software.
18 : : *
19 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 : : * THE SOFTWARE.
26 : : */
27 : :
28 : : #include <stdlib.h>
29 : : #include <string.h>
30 : : #include <assert.h>
31 : :
32 : : #include "py/bc.h"
33 : : #include "py/objmodule.h"
34 : : #include "py/runtime.h"
35 : : #include "py/builtin.h"
36 : :
37 : : #ifndef NO_QSTR
38 : : // Only include module definitions when not doing qstr extraction, because the
39 : : // qstr extraction stage also generates this module definition header file.
40 : : #include "genhdr/moduledefs.h"
41 : : #endif
42 : :
43 : : #if MICROPY_MODULE_BUILTIN_INIT
44 : : STATIC void mp_module_call_init(mp_obj_t module_name, mp_obj_t module_obj);
45 : : #endif
46 : :
47 : 14 : STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
48 : 14 : (void)kind;
49 : 14 : mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in);
50 : :
51 : 14 : const char *module_name = "";
52 : 14 : mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_MAP_LOOKUP);
53 [ + - ]: 14 : if (elem != NULL) {
54 : 14 : module_name = mp_obj_str_get_str(elem->value);
55 : : }
56 : :
57 : : #if MICROPY_PY___FILE__
58 : : // If we store __file__ to imported modules then try to lookup this
59 : : // symbol to give more information about the module.
60 : 14 : elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___file__), MP_MAP_LOOKUP);
61 [ + + ]: 14 : if (elem != NULL) {
62 : 4 : mp_printf(print, "<module '%s' from '%s'>", module_name, mp_obj_str_get_str(elem->value));
63 : 4 : return;
64 : : }
65 : : #endif
66 : :
67 : 10 : mp_printf(print, "<module '%s'>", module_name);
68 : : }
69 : :
70 : 9728 : STATIC void module_attr_try_delegation(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
71 : : #if MICROPY_MODULE_ATTR_DELEGATION
72 : : // Delegate lookup to a module's custom attr method (found in last lot of globals dict).
73 : 9728 : mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in);
74 : 9728 : mp_map_t *map = &self->globals->map;
75 [ + + ]: 9728 : if (map->table[map->alloc - 1].key == MP_OBJ_NEW_QSTR(MP_QSTRnull)) {
76 : 5446 : ((mp_attr_fun_t)MP_OBJ_TO_PTR(map->table[map->alloc - 1].value))(self_in, attr, dest);
77 : : }
78 : : #else
79 : : (void)self_in;
80 : : (void)attr;
81 : : (void)dest;
82 : : #endif
83 : 9728 : }
84 : :
85 : 404042 : STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
86 : 404042 : mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in);
87 [ + + ]: 404042 : if (dest[0] == MP_OBJ_NULL) {
88 : : // load attribute
89 : 402157 : mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
90 [ + + ]: 402111 : if (elem != NULL) {
91 : 392358 : dest[0] = elem->value;
92 : : #if MICROPY_CPYTHON_COMPAT
93 [ + + ]: 9753 : } else if (attr == MP_QSTR___dict__) {
94 : 26 : dest[0] = MP_OBJ_FROM_PTR(self->globals);
95 : : #endif
96 : : #if MICROPY_MODULE_GETATTR
97 [ + + ]: 9727 : } else if (attr != MP_QSTR___getattr__) {
98 : 9721 : elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___getattr__), MP_MAP_LOOKUP);
99 [ + + ]: 9721 : if (elem != NULL) {
100 : 23 : dest[0] = mp_call_function_1(elem->value, MP_OBJ_NEW_QSTR(attr));
101 : : } else {
102 : 9698 : module_attr_try_delegation(self_in, attr, dest);
103 : : }
104 : : #endif
105 : : } else {
106 : 6 : module_attr_try_delegation(self_in, attr, dest);
107 : : }
108 : : } else {
109 : : // delete/store attribute
110 : 1885 : mp_obj_dict_t *dict = self->globals;
111 [ + + ]: 1885 : if (dict->map.is_fixed) {
112 : : #if MICROPY_CAN_OVERRIDE_BUILTINS
113 [ + + ]: 124 : if (dict == &mp_module_builtins_globals) {
114 [ + + ]: 100 : if (MP_STATE_VM(mp_module_builtins_override_dict) == NULL) {
115 : 32 : MP_STATE_VM(mp_module_builtins_override_dict) = MP_OBJ_TO_PTR(mp_obj_new_dict(1));
116 : : }
117 : 100 : dict = MP_STATE_VM(mp_module_builtins_override_dict);
118 : : } else
119 : : #endif
120 : : {
121 : : // can't delete or store to fixed map
122 : 24 : module_attr_try_delegation(self_in, attr, dest);
123 : 24 : return;
124 : : }
125 : : }
126 [ + + ]: 1861 : if (dest[1] == MP_OBJ_NULL) {
127 : : // delete attribute
128 : 4 : mp_obj_dict_delete(MP_OBJ_FROM_PTR(dict), MP_OBJ_NEW_QSTR(attr));
129 : : } else {
130 : : // store attribute
131 : 1857 : mp_obj_dict_store(MP_OBJ_FROM_PTR(dict), MP_OBJ_NEW_QSTR(attr), dest[1]);
132 : : }
133 : 1861 : dest[0] = MP_OBJ_NULL; // indicate success
134 : : }
135 : : }
136 : :
137 : : MP_DEFINE_CONST_OBJ_TYPE(
138 : : mp_type_module,
139 : : MP_QSTR_module,
140 : : MP_TYPE_FLAG_NONE,
141 : : print, module_print,
142 : : attr, module_attr
143 : : );
144 : :
145 : 1564 : mp_obj_t mp_obj_new_module(qstr module_name) {
146 : 1564 : mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map;
147 : 1564 : mp_map_elem_t *el = mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
148 : : // We could error out if module already exists, but let C extensions
149 : : // add new members to existing modules.
150 [ + - ]: 1564 : if (el->value != MP_OBJ_NULL) {
151 : : return el->value;
152 : : }
153 : :
154 : : // create new module object
155 : 1564 : mp_module_context_t *o = m_new_obj(mp_module_context_t);
156 : 1564 : o->module.base.type = &mp_type_module;
157 : 1564 : o->module.globals = MP_OBJ_TO_PTR(mp_obj_new_dict(MICROPY_MODULE_DICT_SIZE));
158 : :
159 : : // store __name__ entry in the module
160 : 1564 : mp_obj_dict_store(MP_OBJ_FROM_PTR(o->module.globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(module_name));
161 : :
162 : : // store the new module into the slot in the global dict holding all modules
163 : 1564 : el->value = MP_OBJ_FROM_PTR(o);
164 : :
165 : : // return the new module
166 : 1564 : return MP_OBJ_FROM_PTR(o);
167 : : }
168 : :
169 : : /******************************************************************************/
170 : : // Global module table and related functions
171 : :
172 : : STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {
173 : : // builtin modules declared with MP_REGISTER_MODULE()
174 : : MICROPY_REGISTERED_MODULES
175 : : };
176 : :
177 : : MP_DEFINE_CONST_MAP(mp_builtin_module_map, mp_builtin_module_table);
178 : :
179 : : // Tries to find a loaded module, otherwise attempts to load a builtin, otherwise MP_OBJ_NULL.
180 : 3099 : mp_obj_t mp_module_get_loaded_or_builtin(qstr module_name) {
181 : : // First try loaded modules.
182 : 3099 : mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_VM(mp_loaded_modules_dict).map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
183 : :
184 [ + + ]: 3099 : if (!elem) {
185 : : #if MICROPY_MODULE_WEAK_LINKS
186 : 2951 : return mp_module_get_builtin(module_name);
187 : : #else
188 : : // Otherwise try builtin.
189 : : elem = mp_map_lookup((mp_map_t *)&mp_builtin_module_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
190 : : if (!elem) {
191 : : return MP_OBJ_NULL;
192 : : }
193 : :
194 : : #if MICROPY_MODULE_BUILTIN_INIT
195 : : // If found, it's a newly loaded built-in, so init it.
196 : : mp_module_call_init(MP_OBJ_NEW_QSTR(module_name), elem->value);
197 : : #endif
198 : : #endif
199 : : }
200 : :
201 : 148 : return elem->value;
202 : : }
203 : :
204 : : #if MICROPY_MODULE_WEAK_LINKS
205 : : // Tries to find a loaded module, otherwise attempts to load a builtin, otherwise MP_OBJ_NULL.
206 : 3195 : mp_obj_t mp_module_get_builtin(qstr module_name) {
207 : : // Try builtin.
208 : 3195 : mp_map_elem_t *elem = mp_map_lookup((mp_map_t *)&mp_builtin_module_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
209 [ + + ]: 3195 : if (!elem) {
210 : : return MP_OBJ_NULL;
211 : : }
212 : :
213 : : #if MICROPY_MODULE_BUILTIN_INIT
214 : : // If found, it's a newly loaded built-in, so init it.
215 : 1367 : mp_module_call_init(MP_OBJ_NEW_QSTR(module_name), elem->value);
216 : : #endif
217 : :
218 : 1367 : return elem->value;
219 : : }
220 : : #endif
221 : :
222 : : #if MICROPY_MODULE_BUILTIN_INIT
223 : 8 : STATIC void mp_module_register(mp_obj_t module_name, mp_obj_t module) {
224 : 8 : mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map;
225 : 8 : mp_map_lookup(mp_loaded_modules_map, module_name, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = module;
226 : 8 : }
227 : :
228 : 1367 : STATIC void mp_module_call_init(mp_obj_t module_name, mp_obj_t module_obj) {
229 : : // Look for __init__ and call it if it exists
230 : 1367 : mp_obj_t dest[2];
231 : 1367 : mp_load_method_maybe(module_obj, MP_QSTR___init__, dest);
232 [ + + ]: 1367 : if (dest[0] != MP_OBJ_NULL) {
233 : 8 : mp_call_method_n_kw(0, 0, dest);
234 : : // Register module so __init__ is not called again.
235 : : // If a module can be referenced by more than one name (eg due to weak links)
236 : : // then __init__ will still be called for each distinct import, and it's then
237 : : // up to the particular module to make sure it's __init__ code only runs once.
238 : 8 : mp_module_register(module_name, module_obj);
239 : : }
240 : 1367 : }
241 : : #endif
242 : :
243 : 5446 : void mp_module_generic_attr(qstr attr, mp_obj_t *dest, const uint16_t *keys, mp_obj_t *values) {
244 [ + + ]: 21706 : for (size_t i = 0; keys[i] != MP_QSTRnull; ++i) {
245 [ + + ]: 16308 : if (attr == keys[i]) {
246 [ + + ]: 48 : if (dest[0] == MP_OBJ_NULL) {
247 : : // load attribute (MP_OBJ_NULL returned for deleted items)
248 : 28 : dest[0] = values[i];
249 : : } else {
250 : : // delete or store (delete stores MP_OBJ_NULL)
251 : 20 : values[i] = dest[1];
252 : 20 : dest[0] = MP_OBJ_NULL; // indicate success
253 : : }
254 : 48 : return;
255 : : }
256 : : }
257 : : }
|