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/objmodule.h"
33#include "py/runtime.h"
34#include "py/builtin.h"
35
36#include "genhdr/moduledefs.h"
37
38STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
39 (void)kind;
40 mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in);
41
42 const char *module_name = "";
43 mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_MAP_LOOKUP);
44 if (elem != NULL) {
45 module_name = mp_obj_str_get_str(elem->value);
46 }
47
48 #if MICROPY_PY___FILE__
49 // If we store __file__ to imported modules then try to lookup this
50 // symbol to give more information about the module.
51 elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___file__), MP_MAP_LOOKUP);
52 if (elem != NULL) {
53 mp_printf(print, "<module '%s' from '%s'>", module_name, mp_obj_str_get_str(elem->value));
54 return;
55 }
56 #endif
57
58 mp_printf(print, "<module '%s'>", module_name);
59}
60
61STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
62 mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in);
63 if (dest[0] == MP_OBJ_NULL) {
64 // load attribute
65 mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
66 if (elem != NULL) {
67 dest[0] = elem->value;
68 #if MICROPY_MODULE_GETATTR
69 } else if (attr != MP_QSTR___getattr__) {
70 elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___getattr__), MP_MAP_LOOKUP);
71 if (elem != NULL) {
72 dest[0] = mp_call_function_1(elem->value, MP_OBJ_NEW_QSTR(attr));
73 }
74 #endif
75 }
76 } else {
77 // delete/store attribute
78 mp_obj_dict_t *dict = self->globals;
79 if (dict->map.is_fixed) {
80 #if MICROPY_CAN_OVERRIDE_BUILTINS
81 if (dict == &mp_module_builtins_globals) {
82 if (MP_STATE_VM(mp_module_builtins_override_dict) == NULL) {
83 MP_STATE_VM(mp_module_builtins_override_dict) = MP_OBJ_TO_PTR(mp_obj_new_dict(1));
84 }
85 dict = MP_STATE_VM(mp_module_builtins_override_dict);
86 } else
87 #endif
88 {
89 // can't delete or store to fixed map
90 return;
91 }
92 }
93 if (dest[1] == MP_OBJ_NULL) {
94 // delete attribute
95 mp_obj_dict_delete(MP_OBJ_FROM_PTR(dict), MP_OBJ_NEW_QSTR(attr));
96 } else {
97 // store attribute
98 mp_obj_dict_store(MP_OBJ_FROM_PTR(dict), MP_OBJ_NEW_QSTR(attr), dest[1]);
99 }
100 dest[0] = MP_OBJ_NULL; // indicate success
101 }
102}
103
104const mp_obj_type_t mp_type_module = {
105 { &mp_type_type },
106 .name = MP_QSTR_module,
107 .print = module_print,
108 .attr = module_attr,
109};
110
111mp_obj_t mp_obj_new_module(qstr module_name) {
112 mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map;
113 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);
114 // We could error out if module already exists, but let C extensions
115 // add new members to existing modules.
116 if (el->value != MP_OBJ_NULL) {
117 return el->value;
118 }
119
120 // create new module object
121 mp_obj_module_t *o = m_new_obj(mp_obj_module_t);
122 o->base.type = &mp_type_module;
123 o->globals = MP_OBJ_TO_PTR(mp_obj_new_dict(MICROPY_MODULE_DICT_SIZE));
124
125 // store __name__ entry in the module
126 mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(module_name));
127
128 // store the new module into the slot in the global dict holding all modules
129 el->value = MP_OBJ_FROM_PTR(o);
130
131 // return the new module
132 return MP_OBJ_FROM_PTR(o);
133}
134
135/******************************************************************************/
136// Global module table and related functions
137
138STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {
139 { MP_ROM_QSTR(MP_QSTR___main__), MP_ROM_PTR(&mp_module___main__) },
140 { MP_ROM_QSTR(MP_QSTR_builtins), MP_ROM_PTR(&mp_module_builtins) },
141 { MP_ROM_QSTR(MP_QSTR_micropython), MP_ROM_PTR(&mp_module_micropython) },
142
143 #if MICROPY_PY_IO
144 { MP_ROM_QSTR(MP_QSTR_uio), MP_ROM_PTR(&mp_module_io) },
145 #endif
146 #if MICROPY_PY_COLLECTIONS
147 { MP_ROM_QSTR(MP_QSTR_ucollections), MP_ROM_PTR(&mp_module_collections) },
148 #endif
149 #if MICROPY_PY_STRUCT
150 { MP_ROM_QSTR(MP_QSTR_ustruct), MP_ROM_PTR(&mp_module_ustruct) },
151 #endif
152
153 #if MICROPY_PY_BUILTINS_FLOAT
154 #if MICROPY_PY_MATH
155 { MP_ROM_QSTR(MP_QSTR_math), MP_ROM_PTR(&mp_module_math) },
156 #endif
157 #if MICROPY_PY_BUILTINS_COMPLEX && MICROPY_PY_CMATH
158 { MP_ROM_QSTR(MP_QSTR_cmath), MP_ROM_PTR(&mp_module_cmath) },
159 #endif
160 #endif
161 #if MICROPY_PY_SYS
162 { MP_ROM_QSTR(MP_QSTR_usys), MP_ROM_PTR(&mp_module_sys) },
163 #endif
164 #if MICROPY_PY_GC && MICROPY_ENABLE_GC
165 { MP_ROM_QSTR(MP_QSTR_gc), MP_ROM_PTR(&mp_module_gc) },
166 #endif
167 #if MICROPY_PY_THREAD
168 { MP_ROM_QSTR(MP_QSTR__thread), MP_ROM_PTR(&mp_module_thread) },
169 #endif
170
171 // extmod modules
172
173 #if MICROPY_PY_UASYNCIO
174 { MP_ROM_QSTR(MP_QSTR__uasyncio), MP_ROM_PTR(&mp_module_uasyncio) },
175 #endif
176 #if MICROPY_PY_UERRNO
177 { MP_ROM_QSTR(MP_QSTR_uerrno), MP_ROM_PTR(&mp_module_uerrno) },
178 #endif
179 #if MICROPY_PY_UCTYPES
180 { MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },
181 #endif
182 #if MICROPY_PY_UZLIB
183 { MP_ROM_QSTR(MP_QSTR_uzlib), MP_ROM_PTR(&mp_module_uzlib) },
184 #endif
185 #if MICROPY_PY_UJSON
186 { MP_ROM_QSTR(MP_QSTR_ujson), MP_ROM_PTR(&mp_module_ujson) },
187 #endif
188 #if MICROPY_PY_URE
189 { MP_ROM_QSTR(MP_QSTR_ure), MP_ROM_PTR(&mp_module_ure) },
190 #endif
191 #if MICROPY_PY_UHEAPQ
192 { MP_ROM_QSTR(MP_QSTR_uheapq), MP_ROM_PTR(&mp_module_uheapq) },
193 #endif
194 #if MICROPY_PY_UTIMEQ
195 { MP_ROM_QSTR(MP_QSTR_utimeq), MP_ROM_PTR(&mp_module_utimeq) },
196 #endif
197 #if MICROPY_PY_UHASHLIB
198 { MP_ROM_QSTR(MP_QSTR_uhashlib), MP_ROM_PTR(&mp_module_uhashlib) },
199 #endif
200 #if MICROPY_PY_UCRYPTOLIB
201 { MP_ROM_QSTR(MP_QSTR_ucryptolib), MP_ROM_PTR(&mp_module_ucryptolib) },
202 #endif
203 #if MICROPY_PY_UBINASCII
204 { MP_ROM_QSTR(MP_QSTR_ubinascii), MP_ROM_PTR(&mp_module_ubinascii) },
205 #endif
206 #if MICROPY_PY_URANDOM
207 { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&mp_module_urandom) },
208 #endif
209 #if MICROPY_PY_USELECT
210 { MP_ROM_QSTR(MP_QSTR_uselect), MP_ROM_PTR(&mp_module_uselect) },
211 #endif
212 #if MICROPY_PY_USSL
213 { MP_ROM_QSTR(MP_QSTR_ussl), MP_ROM_PTR(&mp_module_ussl) },
214 #endif
215 #if MICROPY_PY_LWIP
216 { MP_ROM_QSTR(MP_QSTR_lwip), MP_ROM_PTR(&mp_module_lwip) },
217 #endif
218 #if MICROPY_PY_UWEBSOCKET
219 { MP_ROM_QSTR(MP_QSTR_uwebsocket), MP_ROM_PTR(&mp_module_uwebsocket) },
220 #endif
221 #if MICROPY_PY_WEBREPL
222 { MP_ROM_QSTR(MP_QSTR__webrepl), MP_ROM_PTR(&mp_module_webrepl) },
223 #endif
224 #if MICROPY_PY_FRAMEBUF
225 { MP_ROM_QSTR(MP_QSTR_framebuf), MP_ROM_PTR(&mp_module_framebuf) },
226 #endif
227 #if MICROPY_PY_BTREE
228 { MP_ROM_QSTR(MP_QSTR_btree), MP_ROM_PTR(&mp_module_btree) },
229 #endif
230 #if MICROPY_PY_BLUETOOTH
231 { MP_ROM_QSTR(MP_QSTR_ubluetooth), MP_ROM_PTR(&mp_module_ubluetooth) },
232 #endif
233
234 // extra builtin modules as defined by a port
235 MICROPY_PORT_BUILTIN_MODULES
236
237 #ifdef MICROPY_REGISTERED_MODULES
238 // builtin modules declared with MP_REGISTER_MODULE()
239 MICROPY_REGISTERED_MODULES
240 #endif
241};
242
243MP_DEFINE_CONST_MAP(mp_builtin_module_map, mp_builtin_module_table);
244
245// returns MP_OBJ_NULL if not found
246mp_obj_t mp_module_get(qstr module_name) {
247 mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map;
248 // lookup module
249 mp_map_elem_t *el = mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
250
251 if (el == NULL) {
252 // module not found, look for builtin module names
253 el = mp_map_lookup((mp_map_t *)&mp_builtin_module_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP);
254 if (el == NULL) {
255 return MP_OBJ_NULL;
256 }
257 mp_module_call_init(module_name, el->value);
258 }
259
260 // module found, return it
261 return el->value;
262}
263
264void mp_module_register(qstr qst, mp_obj_t module) {
265 mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map;
266 mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = module;
267}
268
269#if MICROPY_MODULE_WEAK_LINKS
270// Search for u"foo" in built-in modules, return MP_OBJ_NULL if not found
271mp_obj_t mp_module_search_umodule(const char *module_str) {
272 for (size_t i = 0; i < MP_ARRAY_SIZE(mp_builtin_module_table); ++i) {
273 const mp_map_elem_t *entry = (const mp_map_elem_t *)&mp_builtin_module_table[i];
274 const char *key = qstr_str(MP_OBJ_QSTR_VALUE(entry->key));
275 if (key[0] == 'u' && strcmp(&key[1], module_str) == 0) {
276 return (mp_obj_t)entry->value;
277 }
278
279 }
280 return MP_OBJ_NULL;
281}
282#endif
283
284#if MICROPY_MODULE_BUILTIN_INIT
285void mp_module_call_init(qstr module_name, mp_obj_t module_obj) {
286 // Look for __init__ and call it if it exists
287 mp_obj_t dest[2];
288 mp_load_method_maybe(module_obj, MP_QSTR___init__, dest);
289 if (dest[0] != MP_OBJ_NULL) {
290 mp_call_method_n_kw(0, 0, dest);
291 // Register module so __init__ is not called again.
292 // If a module can be referenced by more than one name (eg due to weak links)
293 // then __init__ will still be called for each distinct import, and it's then
294 // up to the particular module to make sure it's __init__ code only runs once.
295 mp_module_register(module_name, module_obj);
296 }
297}
298#endif
299