Numworks Epsilon  1.4.1
Graphing Calculator Operating System
builtinimport.c
Go to the documentation of this file.
1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2013, 2014 Damien P. George
7  * Copyright (c) 2014 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 <stdio.h>
29 #include <string.h>
30 #include <assert.h>
31 
32 #include "py/compile.h"
33 #include "py/objmodule.h"
34 #include "py/persistentcode.h"
35 #include "py/runtime.h"
36 #include "py/builtin.h"
37 #include "py/frozenmod.h"
38 
39 #if MICROPY_DEBUG_VERBOSE // print debugging info
40 #define DEBUG_PRINT (1)
41 #define DEBUG_printf DEBUG_printf
42 #else // don't print debugging info
43 #define DEBUG_PRINT (0)
44 #define DEBUG_printf(...) (void)0
45 #endif
46 
47 #define PATH_SEP_CHAR '/'
48 
50  mp_obj_t dest[2];
51  mp_load_method_maybe(module, MP_QSTR___path__, dest);
52  return dest[0] != MP_OBJ_NULL;
53 }
54 
55 // Stat either frozen or normal module by a given path
56 // (whatever is available, if at all).
58  #if MICROPY_MODULE_FROZEN
60  if (st != MP_IMPORT_STAT_NO_EXIST) {
61  return st;
62  }
63  #endif
64  return mp_import_stat(path);
65 }
66 
69  if (stat == MP_IMPORT_STAT_FILE) {
70  return stat;
71  }
72 
73  #if MICROPY_PERSISTENT_CODE_LOAD
74  vstr_ins_byte(path, path->len - 2, 'm');
76  if (stat == MP_IMPORT_STAT_FILE) {
77  return stat;
78  }
79  #endif
80 
82 }
83 
86  DEBUG_printf("stat %s: %d\n", vstr_str(path), stat);
87  if (stat == MP_IMPORT_STAT_DIR) {
88  return stat;
89  }
90 
91  // not a directory, add .py and try as a file
92  vstr_add_str(path, ".py");
93  return stat_file_py_or_mpy(path);
94 }
95 
96 STATIC mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *dest) {
97 #if MICROPY_PY_SYS
98  // extract the list of paths
99  size_t path_num;
100  mp_obj_t *path_items;
101  mp_obj_list_get(mp_sys_path, &path_num, &path_items);
102 
103  if (path_num == 0) {
104 #endif
105  // mp_sys_path is empty, so just use the given file name
106  vstr_add_strn(dest, file_str, file_len);
107  return stat_dir_or_file(dest);
108 #if MICROPY_PY_SYS
109  } else {
110  // go through each path looking for a directory or file
111  for (size_t i = 0; i < path_num; i++) {
112  vstr_reset(dest);
113  size_t p_len;
114  const char *p = mp_obj_str_get_data(path_items[i], &p_len);
115  if (p_len > 0) {
116  vstr_add_strn(dest, p, p_len);
118  }
119  vstr_add_strn(dest, file_str, file_len);
120  mp_import_stat_t stat = stat_dir_or_file(dest);
121  if (stat != MP_IMPORT_STAT_NO_EXIST) {
122  return stat;
123  }
124  }
125 
126  // could not find a directory or file
128  }
129 #endif
130 }
131 
132 #if MICROPY_ENABLE_COMPILER
133 STATIC void do_load_from_lexer(mp_obj_t module_obj, mp_lexer_t *lex) {
134  #if MICROPY_PY___FILE__
135  qstr source_name = lex->source_name;
136  mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
137  #endif
138 
139  // parse, compile and execute the module in its context
140  mp_obj_dict_t *mod_globals = mp_obj_module_get_globals(module_obj);
141  mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals);
142 }
143 #endif
144 
145 #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_MODULE_FROZEN_MPY
146 STATIC void do_execute_raw_code(mp_obj_t module_obj, mp_raw_code_t *raw_code) {
147  #if MICROPY_PY___FILE__
148  // TODO
149  //qstr source_name = lex->source_name;
150  //mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
151  #endif
152 
153  // execute the module in its context
154  mp_obj_dict_t *mod_globals = mp_obj_module_get_globals(module_obj);
155 
156  // save context
157  mp_obj_dict_t *volatile old_globals = mp_globals_get();
158  mp_obj_dict_t *volatile old_locals = mp_locals_get();
159 
160  // set new context
161  mp_globals_set(mod_globals);
162  mp_locals_set(mod_globals);
163 
164  nlr_buf_t nlr;
165  if (nlr_push(&nlr) == 0) {
167  mp_call_function_0(module_fun);
168 
169  // finish nlr block, restore context
170  nlr_pop();
171  mp_globals_set(old_globals);
172  mp_locals_set(old_locals);
173  } else {
174  // exception; restore context and re-raise same exception
175  mp_globals_set(old_globals);
176  mp_locals_set(old_locals);
177  nlr_jump(nlr.ret_val);
178  }
179 }
180 #endif
181 
182 STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
183  #if MICROPY_MODULE_FROZEN || MICROPY_PERSISTENT_CODE_LOAD || MICROPY_ENABLE_COMPILER
184  char *file_str = vstr_null_terminated_str(file);
185  #endif
186 
187  // If we support frozen modules (either as str or mpy) then try to find the
188  // requested filename in the list of frozen module filenames.
189  #if MICROPY_MODULE_FROZEN
190  void *modref;
191  int frozen_type = mp_find_frozen_module(file_str, file->len, &modref);
192  #endif
193 
194  // If we support frozen str modules and the compiler is enabled, and we
195  // found the filename in the list of frozen files, then load and execute it.
196  #if MICROPY_MODULE_FROZEN_STR
197  if (frozen_type == MP_FROZEN_STR) {
198  do_load_from_lexer(module_obj, modref);
199  return;
200  }
201  #endif
202 
203  // If we support frozen mpy modules and we found a corresponding file (and
204  // its data) in the list of frozen files, execute it.
205  #if MICROPY_MODULE_FROZEN_MPY
206  if (frozen_type == MP_FROZEN_MPY) {
207  do_execute_raw_code(module_obj, modref);
208  return;
209  }
210  #endif
211 
212  // If we support loading .mpy files then check if the file extension is of
213  // the correct format and, if so, load and execute the file.
214  #if MICROPY_PERSISTENT_CODE_LOAD
215  if (file_str[file->len - 3] == 'm') {
216  mp_raw_code_t *raw_code = mp_raw_code_load_file(file_str);
217  do_execute_raw_code(module_obj, raw_code);
218  return;
219  }
220  #endif
221 
222  // If we can compile scripts then load the file and compile and execute it.
223  #if MICROPY_ENABLE_COMPILER
224  {
225  mp_lexer_t *lex = mp_lexer_new_from_file(file_str);
226  do_load_from_lexer(module_obj, lex);
227  return;
228  }
229  #else
230 
231  // If we get here then the file was not frozen and we can't compile scripts.
232  mp_raise_msg(&mp_type_ImportError, "script compilation not supported");
233  #endif
234 }
235 
236 STATIC void chop_component(const char *start, const char **end) {
237  const char *p = *end;
238  while (p > start) {
239  if (*--p == '.') {
240  *end = p;
241  return;
242  }
243  }
244  *end = p;
245 }
246 
247 mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
248 #if DEBUG_PRINT
249  DEBUG_printf("__import__:\n");
250  for (size_t i = 0; i < n_args; i++) {
251  DEBUG_printf(" ");
253  DEBUG_printf("\n");
254  }
255 #endif
256 
257  mp_obj_t module_name = args[0];
258  mp_obj_t fromtuple = mp_const_none;
259  mp_int_t level = 0;
260  if (n_args >= 4) {
261  fromtuple = args[3];
262  if (n_args >= 5) {
264  if (level < 0) {
266  }
267  }
268  }
269 
270  size_t mod_len;
271  const char *mod_str = mp_obj_str_get_data(module_name, &mod_len);
272 
273  if (level != 0) {
274  // What we want to do here is to take name of current module,
275  // chop <level> trailing components, and concatenate with passed-in
276  // module name, thus resolving relative import name into absolute.
277  // This even appears to be correct per
278  // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name
279  // "Relative imports use a module's __name__ attribute to determine that
280  // module's position in the package hierarchy."
281  level--;
282  mp_obj_t this_name_q = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___name__));
283  assert(this_name_q != MP_OBJ_NULL);
284  #if MICROPY_CPYTHON_COMPAT
285  if (MP_OBJ_QSTR_VALUE(this_name_q) == MP_QSTR___main__) {
286  // This is a module run by -m command-line switch, get its real name from backup attribute
287  this_name_q = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
288  }
289  #endif
290  mp_map_t *globals_map = &mp_globals_get()->map;
291  mp_map_elem_t *elem = mp_map_lookup(globals_map, MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP);
292  bool is_pkg = (elem != NULL);
293 
294 #if DEBUG_PRINT
295  DEBUG_printf("Current module/package: ");
296  mp_obj_print(this_name_q, PRINT_REPR);
297  DEBUG_printf(", is_package: %d", is_pkg);
298  DEBUG_printf("\n");
299 #endif
300 
301  size_t this_name_l;
302  const char *this_name = mp_obj_str_get_data(this_name_q, &this_name_l);
303 
304  const char *p = this_name + this_name_l;
305  if (!is_pkg) {
306  // We have module, but relative imports are anchored at package, so
307  // go there.
308  chop_component(this_name, &p);
309  }
310 
311  while (level--) {
312  chop_component(this_name, &p);
313  }
314 
315  // We must have some component left over to import from
316  if (p == this_name) {
317  mp_raise_ValueError("cannot perform relative import");
318  }
319 
320  uint new_mod_l = (mod_len == 0 ? (size_t)(p - this_name) : (size_t)(p - this_name) + 1 + mod_len);
321  char *new_mod = alloca(new_mod_l);
322  memcpy(new_mod, this_name, p - this_name);
323  if (mod_len != 0) {
324  new_mod[p - this_name] = '.';
325  memcpy(new_mod + (p - this_name) + 1, mod_str, mod_len);
326  }
327 
328  qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l);
329  DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q));
330  module_name = MP_OBJ_NEW_QSTR(new_mod_q);
331  mod_str = new_mod;
332  mod_len = new_mod_l;
333  }
334 
335  // check if module already exists
336  qstr module_name_qstr = mp_obj_str_get_qstr(module_name);
337  mp_obj_t module_obj = mp_module_get(module_name_qstr);
338  if (module_obj != MP_OBJ_NULL) {
339  DEBUG_printf("Module already loaded\n");
340  // If it's not a package, return module right away
341  char *p = strchr(mod_str, '.');
342  if (p == NULL) {
343  return module_obj;
344  }
345  // If fromlist is not empty, return leaf module
346  if (fromtuple != mp_const_none) {
347  return module_obj;
348  }
349  // Otherwise, we need to return top-level package
350  qstr pkg_name = qstr_from_strn(mod_str, p - mod_str);
351  return mp_module_get(pkg_name);
352  }
353  DEBUG_printf("Module not yet loaded\n");
354 
355  uint last = 0;
357  module_obj = MP_OBJ_NULL;
358  mp_obj_t top_module_obj = MP_OBJ_NULL;
359  mp_obj_t outer_module_obj = MP_OBJ_NULL;
360  uint i;
361  for (i = 1; i <= mod_len; i++) {
362  if (i == mod_len || mod_str[i] == '.') {
363  // create a qstr for the module name up to this depth
364  qstr mod_name = qstr_from_strn(mod_str, i);
365  DEBUG_printf("Processing module: %s\n", qstr_str(mod_name));
366  DEBUG_printf("Previous path: =%.*s=\n", vstr_len(&path), vstr_str(&path));
367 
368  // find the file corresponding to the module name
369  mp_import_stat_t stat;
370  if (vstr_len(&path) == 0) {
371  // first module in the dotted-name; search for a directory or file
372  stat = find_file(mod_str, i, &path);
373  } else {
374  // latter module in the dotted-name; append to path
376  vstr_add_strn(&path, mod_str + last, i - last);
377  stat = stat_dir_or_file(&path);
378  }
379  DEBUG_printf("Current path: %.*s\n", vstr_len(&path), vstr_str(&path));
380 
381  if (stat == MP_IMPORT_STAT_NO_EXIST) {
382  #if MICROPY_MODULE_WEAK_LINKS
383  // check if there is a weak link to this module
384  if (i == mod_len) {
386  if (el == NULL) {
387  goto no_exist;
388  }
389  // found weak linked module
390  module_obj = el->value;
391  } else {
392  no_exist:
393  #else
394  {
395  #endif
396  // couldn't find the file, so fail
398  mp_raise_msg(&mp_type_ImportError, "module not found");
399  } else {
401  "no module named '%q'", mod_name));
402  }
403  }
404  } else {
405  // found the file, so get the module
406  module_obj = mp_module_get(mod_name);
407  }
408 
409  if (module_obj == MP_OBJ_NULL) {
410  // module not already loaded, so load it!
411 
412  module_obj = mp_obj_new_module(mod_name);
413 
414  // if args[3] (fromtuple) has magic value False, set up
415  // this module for command-line "-m" option (set module's
416  // name to __main__ instead of real name). Do this only
417  // for *modules* however - packages never have their names
418  // replaced, instead they're -m'ed using a special __main__
419  // submodule in them. (This all apparently is done to not
420  // touch package name itself, which is important for future
421  // imports).
422  if (i == mod_len && fromtuple == mp_const_false && stat != MP_IMPORT_STAT_DIR) {
423  mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj);
424  mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
425  #if MICROPY_CPYTHON_COMPAT
426  // Store module as "__main__" in the dictionary of loaded modules (returned by sys.modules).
427  mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)), MP_OBJ_NEW_QSTR(MP_QSTR___main__), module_obj);
428  // Store real name in "__main__" attribute. Chosen semi-randonly, to reuse existing qstr's.
429  mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___main__), MP_OBJ_NEW_QSTR(mod_name));
430  #endif
431  }
432 
433  if (stat == MP_IMPORT_STAT_DIR) {
434  DEBUG_printf("%.*s is dir\n", vstr_len(&path), vstr_str(&path));
435  // https://docs.python.org/3/reference/import.html
436  // "Specifically, any module that contains a __path__ attribute is considered a package."
437  mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path), false));
438  size_t orig_path_len = path.len;
440  vstr_add_str(&path, "__init__.py");
442  //mp_warning("%s is imported as namespace package", vstr_str(&path));
443  } else {
444  do_load(module_obj, &path);
445  }
446  path.len = orig_path_len;
447  } else { // MP_IMPORT_STAT_FILE
448  do_load(module_obj, &path);
449  // This should be the last component in the import path. If there are
450  // remaining components then it's an ImportError because the current path
451  // (the module that was just loaded) is not a package. This will be caught
452  // on the next iteration because the file will not exist.
453  }
454  }
455  if (outer_module_obj != MP_OBJ_NULL) {
456  qstr s = qstr_from_strn(mod_str + last, i - last);
457  mp_store_attr(outer_module_obj, s, module_obj);
458  }
459  outer_module_obj = module_obj;
460  if (top_module_obj == MP_OBJ_NULL) {
461  top_module_obj = module_obj;
462  }
463  last = i + 1;
464  }
465  }
466 
467  // If fromlist is not empty, return leaf module
468  if (fromtuple != mp_const_none) {
469  return module_obj;
470  }
471  // Otherwise, we need to return top-level package
472  return top_module_obj;
473 }
474 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj, 1, 5, mp_builtin___import__);
Charge level()
Definition: battery.cpp:20
qstr mp_obj_str_get_qstr(mp_obj_t self_in)
Definition: objstr.c:2082
intptr_t mp_int_t
Definition: mpconfigport.h:73
qstr qstr_from_strn(const char *str, size_t len)
Definition: qstr.c:187
NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg)
Definition: runtime.c:1448
Definition: misc.h:142
const char * qstr_str(qstr q)
Definition: qstr.c:278
void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest)
Definition: runtime.c:1040
#define assert(e)
Definition: assert.h:9
#define PATH_SEP_CHAR
Definition: builtinimport.c:47
#define MICROPY_ERROR_REPORTING_TERSE
Definition: mpconfig.h:521
#define mp_const_none
Definition: obj.h:614
void vstr_add_strn(vstr_t *vstr, const char *str, size_t len)
Definition: vstr.c:179
mp_raw_code_t * mp_raw_code_load_file(const char *filename)
STATIC void chop_component(const char *start, const char **end)
const mp_map_t mp_builtin_module_weak_links_map
#define nlr_push(buf)
Definition: nlr.h:73
STATIC void do_load(mp_obj_t module_obj, vstr_t *file)
void vstr_add_char(vstr_t *vstr, unichar chr)
Definition: vstr.c:146
mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt,...)
Definition: objexcept.c:380
#define MP_OBJ_QSTR_VALUE(o)
Definition: obj.h:91
unsigned int size_t
Definition: stddef.h:7
void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind)
Definition: obj.c:76
#define MP_OBJ_FROM_PTR(p)
Definition: obj.h:233
#define MP_OBJ_NEW_QSTR(qst)
Definition: obj.h:92
const mp_obj_type_t mp_type_ImportError
mp_import_stat_t mp_import_stat(const char *path)
Definition: port.cpp:159
size_t len
Definition: misc.h:144
mp_obj_t mp_module_get(qstr module_name)
Definition: objmodule.c:239
#define MP_STATE_VM(x)
Definition: mpstate.h:241
mp_obj_dict_t * mp_obj_module_get_globals(mp_obj_t self_in)
Definition: objmodule.c:125
#define VSTR_FIXED(vstr, alloc)
Definition: misc.h:150
mp_obj_t mp_call_function_0(mp_obj_t fun)
Definition: runtime.c:599
void vstr_add_str(vstr_t *vstr, const char *str)
Definition: vstr.c:175
mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_input_kind, mp_obj_dict_t *globals, mp_obj_dict_t *locals)
#define STATIC
Definition: mpconfig.h:1178
#define MP_OBJ_SMALL_INT_VALUE(o)
Definition: obj.h:86
mp_lexer_t * mp_lexer_new_from_file(const char *filename)
Definition: port.cpp:146
STATIC mp_import_stat_t stat_file_py_or_mpy(vstr_t *path)
Definition: builtinimport.c:67
mp_map_elem_t * mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind)
Definition: map.c:138
#define MICROPY_ERROR_REPORTING
Definition: mpconfigport.h:32
const char * mp_obj_str_get_data(mp_obj_t self_in, size_t *len)
Definition: objstr.c:2105
#define MICROPY_ALLOC_PATH_MAX
Definition: mpconfigport.h:13
#define NULL
Definition: stddef.h:4
#define MP_OBJ_NULL
Definition: obj.h:73
char * strchr(const char *s, int c)
Definition: strchr.c:3
size_t qstr
Definition: qstr.h:48
#define mp_sys_path
Definition: runtime.h:171
void mp_obj_list_get(mp_obj_t self_in, size_t *len, mp_obj_t **items)
Definition: objlist.c:480
bool mp_obj_is_package(mp_obj_t module)
Definition: builtinimport.c:49
mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args)
Definition: emitglue.c:116
mp_obj_t value
Definition: obj.h:343
mp_obj_t mp_obj_new_str(const char *data, size_t len, bool make_qstr_if_not_already)
Definition: objstr.c:2025
args
Definition: i18n.py:175
#define nlr_pop()
Definition: nlr.h:74
mp_obj_dict_t * globals
Definition: obj.h:815
mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index)
Definition: objdict.c:164
Definition: obj.h:356
void * ret_val
Definition: nlr.h:42
STATIC mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *dest)
Definition: builtinimport.c:96
void start()
Definition: rt0.cpp:31
NORETURN void mp_raise_ValueError(const char *msg)
Definition: runtime.c:1456
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value)
Definition: objdict.c:595
char * vstr_null_terminated_str(vstr_t *vstr)
Definition: vstr.c:132
#define DEBUG_printf(...)
Definition: builtinimport.c:44
#define MP_OBJ_TO_PTR(o)
Definition: obj.h:228
Definition: nlr.h:39
STATIC mp_import_stat_t mp_import_stat_any(const char *path)
Definition: builtinimport.c:57
#define nlr_raise(val)
Definition: nlr.h:89
void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value)
Definition: runtime.c:1100
mp_import_stat_t mp_frozen_stat(const char *str)
#define alloca(size)
Definition: alloca.h:4
uint64_t mp_obj_t
Definition: obj.h:39
#define nlr_jump(val)
Definition: nlr.h:75
qstr source_name
Definition: lexer.h:149
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj, 1, 5, mp_builtin___import__)
mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args)
mp_import_stat_t
Definition: lexer.h:182
void * memcpy(void *dst, const void *src, size_t n)
Definition: memcpy.c:3
int mp_find_frozen_module(const char *str, size_t len, void **data)
mp_obj_t mp_obj_new_module(qstr module_name)
Definition: objmodule.c:101
STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path)
Definition: builtinimport.c:84
void vstr_ins_byte(vstr_t *vstr, size_t byte_pos, byte b)
Definition: vstr.c:201
#define mp_const_false
Definition: obj.h:615
unsigned int uint
Definition: misc.h:38