mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) { #if DEBUG_PRINT DEBUG_printf("__import__:\n"); for (mp_uint_t i = 0; i < n_args; i++) { DEBUG_printf(" "); mp_obj_print(args[i], PRINT_REPR); DEBUG_printf("\n"); } #endif mp_obj_t module_name = args[0]; mp_obj_t fromtuple = mp_const_none; mp_int_t level = 0; if (n_args >= 4) { fromtuple = args[3]; if (n_args >= 5) { level = MP_OBJ_SMALL_INT_VALUE(args[4]); } } mp_uint_t mod_len; const char *mod_str = mp_obj_str_get_data(module_name, &mod_len); if (level != 0) { // What we want to do here is to take name of current module, // chop <level> trailing components, and concatenate with passed-in // module name, thus resolving relative import name into absolue. // This even appears to be correct per // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name // "Relative imports use a module's __name__ attribute to determine that // module's position in the package hierarchy." level--; mp_obj_t this_name_q = mp_obj_dict_get(mp_globals_get(), MP_OBJ_NEW_QSTR(MP_QSTR___name__)); assert(this_name_q != MP_OBJ_NULL); #if MICROPY_CPYTHON_COMPAT if (MP_OBJ_QSTR_VALUE(this_name_q) == MP_QSTR___main__) { // This is a module run by -m command-line switch, get its real name from backup attribute this_name_q = mp_obj_dict_get(mp_globals_get(), MP_OBJ_NEW_QSTR(MP_QSTR___main__)); } #endif mp_map_t *globals_map = mp_obj_dict_get_map(mp_globals_get()); mp_map_elem_t *elem = mp_map_lookup(globals_map, MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP); bool is_pkg = (elem != NULL); #if DEBUG_PRINT DEBUG_printf("Current module/package: "); mp_obj_print(this_name_q, PRINT_REPR); DEBUG_printf(", is_package: %d", is_pkg); DEBUG_printf("\n"); #endif mp_uint_t this_name_l; const char *this_name = mp_obj_str_get_data(this_name_q, &this_name_l); const char *p = this_name + this_name_l; if (!is_pkg) { // We have module, but relative imports are anchored at package, so // go there. chop_component(this_name, &p); } uint dots_seen = 0; while (level--) { chop_component(this_name, &p); dots_seen++; } if (dots_seen == 0 && level >= 1) { // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name // "If the module's name does not contain any package information // (e.g. it is set to '__main__') then relative imports are // resolved as if the module were a top level module, regardless // of where the module is actually located on the file system." // Supposedly this if catches this condition and resolve it properly // TODO: But nobody knows for sure. This condition happens when // package's __init__.py does something like "import .submod". So, // maybe we should check for package here? But quote above doesn't // talk about packages, it talks about dot-less module names. DEBUG_printf("Warning: no dots in current module name and level>0\n"); p = this_name + this_name_l; } else if (level != -1) { nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "Invalid relative import")); } uint new_mod_l = (mod_len == 0 ? (size_t)(p - this_name) : (size_t)(p - this_name) + 1 + mod_len); char *new_mod = alloca(new_mod_l); memcpy(new_mod, this_name, p - this_name); if (mod_len != 0) { new_mod[p - this_name] = '.'; memcpy(new_mod + (p - this_name) + 1, mod_str, mod_len); } qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l); DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q)); if (new_mod_q == MP_QSTR_) { // CPython raises SystemError nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "cannot perform relative import")); } module_name = MP_OBJ_NEW_QSTR(new_mod_q); mod_str = new_mod; mod_len = new_mod_l; } // check if module already exists qstr module_name_qstr = mp_obj_str_get_qstr(module_name); mp_obj_t module_obj = mp_module_get(module_name_qstr); if (module_obj != MP_OBJ_NULL) { DEBUG_printf("Module already loaded\n"); // If it's not a package, return module right away char *p = strchr(mod_str, '.'); if (p == NULL) { return module_obj; } // If fromlist is not empty, return leaf module if (fromtuple != mp_const_none) { return module_obj; } // Otherwise, we need to return top-level package qstr pkg_name = qstr_from_strn(mod_str, p - mod_str); return mp_module_get(pkg_name); } DEBUG_printf("Module not yet loaded\n"); #if MICROPY_MODULE_FROZEN mp_lexer_t *lex = mp_find_frozen_module(mod_str, mod_len); if (lex != NULL) { module_obj = mp_obj_new_module(module_name_qstr); // if args[3] (fromtuple) has magic value False, set up // this module for command-line "-m" option (set module's // name to __main__ instead of real name). // TODO: Duplicated below too. if (fromtuple == mp_const_false) { mp_obj_module_t *o = module_obj; mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__)); } do_load_from_lexer(module_obj, lex, mod_str); return module_obj; } #endif uint last = 0; VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX) module_obj = MP_OBJ_NULL; mp_obj_t top_module_obj = MP_OBJ_NULL; mp_obj_t outer_module_obj = MP_OBJ_NULL; uint i; for (i = 1; i <= mod_len; i++) { if (i == mod_len || mod_str[i] == '.') { // create a qstr for the module name up to this depth qstr mod_name = qstr_from_strn(mod_str, i); DEBUG_printf("Processing module: %s\n", qstr_str(mod_name)); DEBUG_printf("Previous path: =%.*s=\n", vstr_len(&path), vstr_str(&path)); // find the file corresponding to the module name mp_import_stat_t stat; if (vstr_len(&path) == 0) { // first module in the dotted-name; search for a directory or file stat = find_file(mod_str, i, &path); } else { // latter module in the dotted-name; append to path vstr_add_char(&path, PATH_SEP_CHAR); vstr_add_strn(&path, mod_str + last, i - last); stat = stat_dir_or_file(&path); } DEBUG_printf("Current path: %.*s\n", vstr_len(&path), vstr_str(&path)); if (stat == MP_IMPORT_STAT_NO_EXIST) { #if MICROPY_MODULE_WEAK_LINKS // check if there is a weak link to this module if (i == mod_len) { mp_map_elem_t *el = mp_map_lookup((mp_map_t*)&mp_builtin_module_weak_links_map, MP_OBJ_NEW_QSTR(mod_name), MP_MAP_LOOKUP); if (el == NULL) { goto no_exist; } // found weak linked module module_obj = el->value; } else { no_exist: #else { #endif // couldn't find the file, so fail if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "module not found")); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "no module named '%q'", mod_name)); } } } else { // found the file, so get the module module_obj = mp_module_get(mod_name); } if (module_obj == MP_OBJ_NULL) { // module not already loaded, so load it! module_obj = mp_obj_new_module(mod_name); // if args[3] (fromtuple) has magic value False, set up // this module for command-line "-m" option (set module's // name to __main__ instead of real name). if (i == mod_len && fromtuple == mp_const_false) { mp_obj_module_t *o = module_obj; mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__)); #if MICROPY_CPYTHON_COMPAT // Store real name in "__main__" attribute. Choosen semi-randonly, to reuse existing qstr's. mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___main__), MP_OBJ_NEW_QSTR(mod_name)); #endif } if (stat == MP_IMPORT_STAT_DIR) { DEBUG_printf("%.*s is dir\n", vstr_len(&path), vstr_str(&path)); // https://docs.python.org/3/reference/import.html // "Specifically, any module that contains a __path__ attribute is considered a package." mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path), false)); vstr_add_char(&path, PATH_SEP_CHAR); vstr_add_str(&path, "__init__.py"); if (mp_import_stat(vstr_null_terminated_str(&path)) != MP_IMPORT_STAT_FILE) { vstr_cut_tail_bytes(&path, sizeof("/__init__.py") - 1); // cut off /__init__.py mp_warning("%s is imported as namespace package", vstr_str(&path)); } else { do_load(module_obj, &path); vstr_cut_tail_bytes(&path, sizeof("/__init__.py") - 1); // cut off /__init__.py } } else { // MP_IMPORT_STAT_FILE do_load(module_obj, &path); // TODO: We cannot just break here, at the very least, we must execute // trailer code below. But otherwise if there're remaining components, // that would be (??) object path within module, not modules path within FS. // break; } } if (outer_module_obj != MP_OBJ_NULL) { qstr s = qstr_from_strn(mod_str + last, i - last); mp_store_attr(outer_module_obj, s, module_obj); } outer_module_obj = module_obj; if (top_module_obj == MP_OBJ_NULL) { top_module_obj = module_obj; } last = i + 1; } }
void mp_emitter_warning(pass_kind_t pass, const char *msg) { if (pass == MP_PASS_CODE_SIZE) { mp_warning(msg, NULL); } }
// This function implements the '==' operator (and so the inverse of '!='). // // From the Python language reference: // (https://docs.python.org/3/reference/expressions.html#not-in) // "The objects need not have the same type. If both are numbers, they are converted // to a common type. Otherwise, the == and != operators always consider objects of // different types to be unequal." // // This means that False==0 and True==1 are true expressions. // // Furthermore, from the v3.4.2 code for object.c: "Practical amendments: If rich // comparison returns NotImplemented, == and != are decided by comparing the object // pointer." bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { // Float (and complex) NaN is never equal to anything, not even itself, // so we must have a special check here to cover those cases. if (o1 == o2 #if MICROPY_PY_BUILTINS_FLOAT && !mp_obj_is_float(o1) #endif #if MICROPY_PY_BUILTINS_COMPLEX && !MP_OBJ_IS_TYPE(o1, &mp_type_complex) #endif ) { return true; } if (o1 == mp_const_none || o2 == mp_const_none) { return false; } // fast path for small ints if (MP_OBJ_IS_SMALL_INT(o1)) { if (MP_OBJ_IS_SMALL_INT(o2)) { // both SMALL_INT, and not equal if we get here return false; } else { mp_obj_t temp = o2; o2 = o1; o1 = temp; // o2 is now the SMALL_INT, o1 is not // fall through to generic op } } // fast path for strings if (MP_OBJ_IS_STR(o1)) { if (MP_OBJ_IS_STR(o2)) { // both strings, use special function return mp_obj_str_equal(o1, o2); } else { // a string is never equal to anything else goto str_cmp_err; } } else if (MP_OBJ_IS_STR(o2)) { // o1 is not a string (else caught above), so the objects are not equal str_cmp_err: #if MICROPY_PY_STR_BYTES_CMP_WARN if (MP_OBJ_IS_TYPE(o1, &mp_type_bytes) || MP_OBJ_IS_TYPE(o2, &mp_type_bytes)) { mp_warning("Comparison between bytes and str"); } #endif return false; } // generic type, call binary_op(MP_BINARY_OP_EQUAL) mp_obj_type_t *type = mp_obj_get_type(o1); if (type->binary_op != NULL) { mp_obj_t r = type->binary_op(MP_BINARY_OP_EQUAL, o1, o2); if (r != MP_OBJ_NULL) { return r == mp_const_true ? true : false; } } // equality not implemented, and objects are not the same object, so // they are defined as not equal return false; }
STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { (void)n_args; // always 4 mp_warning("setsockopt() not implemented"); return mp_const_none; }