LCOV - code coverage report
Current view: top level - py - builtinimport.c (source / functions) Hit Total Coverage
Test: unix_coverage_v1.19.1-724-gfb7d21153.info Lines: 191 193 99.0 %
Date: 2022-12-01 09:37:31 Functions: 12 12 100.0 %
Branches: 77 80 96.2 %

           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 Paul Sokolovsky
       8                 :            :  * Copyright (c) 2021 Jim Mussared
       9                 :            :  *
      10                 :            :  * Permission is hereby granted, free of charge, to any person obtaining a copy
      11                 :            :  * of this software and associated documentation files (the "Software"), to deal
      12                 :            :  * in the Software without restriction, including without limitation the rights
      13                 :            :  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      14                 :            :  * copies of the Software, and to permit persons to whom the Software is
      15                 :            :  * furnished to do so, subject to the following conditions:
      16                 :            :  *
      17                 :            :  * The above copyright notice and this permission notice shall be included in
      18                 :            :  * all copies or substantial portions of the Software.
      19                 :            :  *
      20                 :            :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      21                 :            :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22                 :            :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      23                 :            :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24                 :            :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      25                 :            :  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      26                 :            :  * THE SOFTWARE.
      27                 :            :  */
      28                 :            : 
      29                 :            : #include <stdio.h>
      30                 :            : #include <string.h>
      31                 :            : #include <assert.h>
      32                 :            : 
      33                 :            : #include "py/compile.h"
      34                 :            : #include "py/objmodule.h"
      35                 :            : #include "py/persistentcode.h"
      36                 :            : #include "py/runtime.h"
      37                 :            : #include "py/builtin.h"
      38                 :            : #include "py/frozenmod.h"
      39                 :            : 
      40                 :            : #if MICROPY_DEBUG_VERBOSE // print debugging info
      41                 :            : #define DEBUG_PRINT (1)
      42                 :            : #define DEBUG_printf DEBUG_printf
      43                 :            : #else // don't print debugging info
      44                 :            : #define DEBUG_PRINT (0)
      45                 :            : #define DEBUG_printf(...) (void)0
      46                 :            : #endif
      47                 :            : 
      48                 :            : #if MICROPY_MODULE_WEAK_LINKS
      49                 :        234 : STATIC qstr make_weak_link_name(vstr_t *buffer, qstr name) {
      50                 :        234 :     vstr_reset(buffer);
      51                 :        234 :     vstr_add_char(buffer, 'u');
      52                 :        234 :     vstr_add_str(buffer, qstr_str(name));
      53                 :        234 :     return qstr_from_strn(buffer->buf, buffer->len);
      54                 :            : }
      55                 :            : #endif
      56                 :            : 
      57                 :            : #if MICROPY_ENABLE_EXTERNAL_IMPORT
      58                 :            : 
      59                 :            : // Must be a string of one byte.
      60                 :            : #define PATH_SEP_CHAR "/"
      61                 :            : 
      62                 :            : // Virtual sys.path entry that maps to the frozen modules.
      63                 :            : #define MP_FROZEN_PATH_PREFIX ".frozen/"
      64                 :            : 
      65                 :       1309 : bool mp_obj_is_package(mp_obj_t module) {
      66                 :       1309 :     mp_obj_t dest[2];
      67                 :       1309 :     mp_load_method_maybe(module, MP_QSTR___path__, dest);
      68                 :       1309 :     return dest[0] != MP_OBJ_NULL;
      69                 :            : }
      70                 :            : 
      71                 :            : // Wrapper for mp_import_stat (which is provided by the port, and typically
      72                 :            : // uses mp_vfs_import_stat) to also search frozen modules. Given an exact
      73                 :            : // path to a file or directory (e.g. "foo/bar", foo/bar.py" or "foo/bar.mpy"),
      74                 :            : // will return whether the path is a file, directory, or doesn't exist.
      75                 :      17444 : STATIC mp_import_stat_t stat_path_or_frozen(const char *path) {
      76                 :            :     #if MICROPY_MODULE_FROZEN
      77                 :            :     // Only try and load as a frozen module if it starts with .frozen/.
      78                 :      17444 :     const int frozen_path_prefix_len = strlen(MP_FROZEN_PATH_PREFIX);
      79         [ +  + ]:      17444 :     if (strncmp(path, MP_FROZEN_PATH_PREFIX, frozen_path_prefix_len) == 0) {
      80                 :       4423 :         return mp_find_frozen_module(path + frozen_path_prefix_len, NULL, NULL);
      81                 :            :     }
      82                 :            :     #endif
      83                 :      13021 :     return mp_import_stat(path);
      84                 :            : }
      85                 :            : 
      86                 :            : // Given a path to a .py file, try and find this path as either a .py or .mpy
      87                 :            : // in either the filesystem or frozen modules.
      88                 :       5825 : STATIC mp_import_stat_t stat_file_py_or_mpy(vstr_t *path) {
      89                 :       5825 :     mp_import_stat_t stat = stat_path_or_frozen(vstr_null_terminated_str(path));
      90         [ +  + ]:       5825 :     if (stat == MP_IMPORT_STAT_FILE) {
      91                 :            :         return stat;
      92                 :            :     }
      93                 :            : 
      94                 :            :     #if MICROPY_PERSISTENT_CODE_LOAD
      95                 :            :     // Didn't find .py -- try the .mpy instead by inserting an 'm' into the '.py'.
      96                 :       5584 :     vstr_ins_byte(path, path->len - 2, 'm');
      97                 :       5584 :     stat = stat_path_or_frozen(vstr_null_terminated_str(path));
      98         [ +  + ]:       5584 :     if (stat == MP_IMPORT_STAT_FILE) {
      99                 :       1325 :         return stat;
     100                 :            :     }
     101                 :            :     #endif
     102                 :            : 
     103                 :            :     return MP_IMPORT_STAT_NO_EXIST;
     104                 :            : }
     105                 :            : 
     106                 :            : // Given an import path (e.g. "foo/bar"), try and find "foo/bar" (a directory)
     107                 :            : // or "foo/bar.(m)py" in either the filesystem or frozen modules.
     108                 :       6035 : STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {
     109                 :       6035 :     mp_import_stat_t stat = stat_path_or_frozen(vstr_null_terminated_str(path));
     110                 :       6035 :     DEBUG_printf("stat %s: %d\n", vstr_str(path), stat);
     111         [ +  + ]:       6035 :     if (stat == MP_IMPORT_STAT_DIR) {
     112                 :            :         return stat;
     113                 :            :     }
     114                 :            : 
     115                 :            :     // not a directory, add .py and try as a file
     116                 :       5737 :     vstr_add_str(path, ".py");
     117                 :       5737 :     return stat_file_py_or_mpy(path);
     118                 :            : }
     119                 :            : 
     120                 :            : // Given a top-level module, try and find it in each of the sys.path entries
     121                 :            : // via stat_dir_or_file.
     122                 :       2942 : STATIC mp_import_stat_t stat_top_level_dir_or_file(qstr mod_name, vstr_t *dest) {
     123                 :       2942 :     DEBUG_printf("stat_top_level_dir_or_file: '%s'\n", qstr_str(mod_name));
     124                 :            :     #if MICROPY_PY_SYS
     125                 :       2942 :     size_t path_num;
     126                 :       2942 :     mp_obj_t *path_items;
     127                 :       2942 :     mp_obj_list_get(mp_sys_path, &path_num, &path_items);
     128                 :            : 
     129         [ +  - ]:       2942 :     if (path_num > 0) {
     130                 :            :         // go through each path looking for a directory or file
     131         [ +  + ]:       7195 :         for (size_t i = 0; i < path_num; i++) {
     132                 :       5912 :             vstr_reset(dest);
     133                 :       5912 :             size_t p_len;
     134                 :       5912 :             const char *p = mp_obj_str_get_data(path_items[i], &p_len);
     135         [ +  + ]:       5912 :             if (p_len > 0) {
     136                 :       4281 :                 vstr_add_strn(dest, p, p_len);
     137                 :       4281 :                 vstr_add_char(dest, PATH_SEP_CHAR[0]);
     138                 :            :             }
     139                 :       5912 :             vstr_add_str(dest, qstr_str(mod_name));
     140                 :       5912 :             mp_import_stat_t stat = stat_dir_or_file(dest);
     141         [ +  + ]:       5912 :             if (stat != MP_IMPORT_STAT_NO_EXIST) {
     142                 :       1659 :                 return stat;
     143                 :            :             }
     144                 :            :         }
     145                 :            : 
     146                 :            :         // could not find a directory or file
     147                 :            :         return MP_IMPORT_STAT_NO_EXIST;
     148                 :            :     }
     149                 :            :     #endif
     150                 :            : 
     151                 :            :     // mp_sys_path is empty (or not enabled), so just stat the given path
     152                 :            :     // directly.
     153                 :          0 :     vstr_add_str(dest, qstr_str(mod_name));
     154                 :          0 :     return stat_dir_or_file(dest);
     155                 :            : }
     156                 :            : 
     157                 :            : #if MICROPY_MODULE_FROZEN_STR || MICROPY_ENABLE_COMPILER
     158                 :        213 : STATIC void do_load_from_lexer(mp_module_context_t *context, mp_lexer_t *lex) {
     159                 :            :     #if MICROPY_PY___FILE__
     160                 :        213 :     qstr source_name = lex->source_name;
     161                 :        213 :     mp_store_attr(MP_OBJ_FROM_PTR(&context->module), MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
     162                 :            :     #endif
     163                 :            : 
     164                 :            :     // parse, compile and execute the module in its context
     165                 :        213 :     mp_obj_dict_t *mod_globals = context->module.globals;
     166                 :        213 :     mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals);
     167                 :        213 : }
     168                 :            : #endif
     169                 :            : 
     170                 :            : #if (MICROPY_HAS_FILE_READER && MICROPY_PERSISTENT_CODE_LOAD) || MICROPY_MODULE_FROZEN_MPY
     171                 :       1323 : STATIC void do_execute_raw_code(const mp_module_context_t *context, const mp_raw_code_t *rc, const char *source_name) {
     172                 :       1323 :     (void)source_name;
     173                 :            : 
     174                 :            :     #if MICROPY_PY___FILE__
     175                 :       1323 :     mp_store_attr(MP_OBJ_FROM_PTR(&context->module), MP_QSTR___file__, MP_OBJ_NEW_QSTR(qstr_from_str(source_name)));
     176                 :            :     #endif
     177                 :            : 
     178                 :            :     // execute the module in its context
     179                 :       1323 :     mp_obj_dict_t *mod_globals = context->module.globals;
     180                 :            : 
     181                 :            :     // save context
     182                 :       1323 :     mp_obj_dict_t *volatile old_globals = mp_globals_get();
     183                 :       1323 :     mp_obj_dict_t *volatile old_locals = mp_locals_get();
     184                 :            : 
     185                 :            :     // set new context
     186                 :       1323 :     mp_globals_set(mod_globals);
     187                 :       1323 :     mp_locals_set(mod_globals);
     188                 :            : 
     189                 :       1323 :     nlr_buf_t nlr;
     190         [ +  + ]:       1323 :     if (nlr_push(&nlr) == 0) {
     191                 :       1323 :         mp_obj_t module_fun = mp_make_function_from_raw_code(rc, context, NULL);
     192                 :       1323 :         mp_call_function_0(module_fun);
     193                 :            : 
     194                 :            :         // finish nlr block, restore context
     195                 :       1317 :         nlr_pop();
     196                 :       1317 :         mp_globals_set(old_globals);
     197                 :       1317 :         mp_locals_set(old_locals);
     198                 :            :     } else {
     199                 :            :         // exception; restore context and re-raise same exception
     200                 :          6 :         mp_globals_set(old_globals);
     201                 :          6 :         mp_locals_set(old_locals);
     202                 :          6 :         nlr_jump(nlr.ret_val);
     203                 :            :     }
     204                 :       1317 : }
     205                 :            : #endif
     206                 :            : 
     207                 :       1552 : STATIC void do_load(mp_module_context_t *module_obj, vstr_t *file) {
     208                 :            :     #if MICROPY_MODULE_FROZEN || MICROPY_ENABLE_COMPILER || (MICROPY_PERSISTENT_CODE_LOAD && MICROPY_HAS_FILE_READER)
     209                 :       1552 :     const char *file_str = vstr_null_terminated_str(file);
     210                 :            :     #endif
     211                 :            : 
     212                 :            :     // If we support frozen modules (either as str or mpy) then try to find the
     213                 :            :     // requested filename in the list of frozen module filenames.
     214                 :            :     #if MICROPY_MODULE_FROZEN
     215                 :       1552 :     void *modref;
     216                 :       1552 :     int frozen_type;
     217                 :       1552 :     const int frozen_path_prefix_len = strlen(MP_FROZEN_PATH_PREFIX);
     218         [ +  + ]:       1552 :     if (strncmp(file_str, MP_FROZEN_PATH_PREFIX, frozen_path_prefix_len) == 0) {
     219                 :         20 :         mp_find_frozen_module(file_str + frozen_path_prefix_len, &frozen_type, &modref);
     220                 :            : 
     221                 :            :         // If we support frozen str modules and the compiler is enabled, and we
     222                 :            :         // found the filename in the list of frozen files, then load and execute it.
     223                 :            :         #if MICROPY_MODULE_FROZEN_STR
     224         [ +  + ]:         20 :         if (frozen_type == MP_FROZEN_STR) {
     225                 :          6 :             do_load_from_lexer(module_obj, modref);
     226                 :          6 :             return;
     227                 :            :         }
     228                 :            :         #endif
     229                 :            : 
     230                 :            :         // If we support frozen mpy modules and we found a corresponding file (and
     231                 :            :         // its data) in the list of frozen files, execute it.
     232                 :            :         #if MICROPY_MODULE_FROZEN_MPY
     233         [ +  - ]:         14 :         if (frozen_type == MP_FROZEN_MPY) {
     234                 :         14 :             const mp_frozen_module_t *frozen = modref;
     235                 :         14 :             module_obj->constants = frozen->constants;
     236                 :         14 :             do_execute_raw_code(module_obj, frozen->rc, file_str + frozen_path_prefix_len);
     237                 :         14 :             return;
     238                 :            :         }
     239                 :            :         #endif
     240                 :            :     }
     241                 :            : 
     242                 :            :     #endif // MICROPY_MODULE_FROZEN
     243                 :            : 
     244                 :            :     // If we support loading .mpy files then check if the file extension is of
     245                 :            :     // the correct format and, if so, load and execute the file.
     246                 :            :     #if MICROPY_HAS_FILE_READER && MICROPY_PERSISTENT_CODE_LOAD
     247         [ +  + ]:       1532 :     if (file_str[file->len - 3] == 'm') {
     248                 :       1325 :         mp_compiled_module_t cm = mp_raw_code_load_file(file_str, module_obj);
     249                 :       1309 :         do_execute_raw_code(cm.context, cm.rc, file_str);
     250                 :       1305 :         return;
     251                 :            :     }
     252                 :            :     #endif
     253                 :            : 
     254                 :            :     // If we can compile scripts then load the file and compile and execute it.
     255                 :            :     #if MICROPY_ENABLE_COMPILER
     256                 :            :     {
     257                 :        207 :         mp_lexer_t *lex = mp_lexer_new_from_file(file_str);
     258                 :        207 :         do_load_from_lexer(module_obj, lex);
     259                 :        207 :         return;
     260                 :            :     }
     261                 :            :     #else
     262                 :            :     // If we get here then the file was not frozen and we can't compile scripts.
     263                 :            :     mp_raise_msg(&mp_type_ImportError, MP_ERROR_TEXT("script compilation not supported"));
     264                 :            :     #endif
     265                 :            : }
     266                 :            : 
     267                 :            : // Convert a relative (to the current module) import, going up "level" levels,
     268                 :            : // into an absolute import.
     269                 :        106 : STATIC void evaluate_relative_import(mp_int_t level, const char **module_name, size_t *module_name_len) {
     270                 :            :     // What we want to do here is to take the name of the current module,
     271                 :            :     // remove <level> trailing components, and concatenate the passed-in
     272                 :            :     // module name.
     273                 :            :     // For example, level=3, module_name="foo.bar", __name__="a.b.c.d" --> "a.foo.bar"
     274                 :            :     // "Relative imports use a module's __name__ attribute to determine that
     275                 :            :     // module's position in the package hierarchy."
     276                 :            :     // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name
     277                 :            : 
     278                 :        106 :     mp_obj_t current_module_name_obj = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___name__));
     279         [ -  + ]:        106 :     assert(current_module_name_obj != MP_OBJ_NULL);
     280                 :            : 
     281                 :            :     #if MICROPY_MODULE_OVERRIDE_MAIN_IMPORT && MICROPY_CPYTHON_COMPAT
     282         [ +  + ]:        106 :     if (MP_OBJ_QSTR_VALUE(current_module_name_obj) == MP_QSTR___main__) {
     283                 :            :         // This is a module loaded by -m command-line switch (e.g. unix port),
     284                 :            :         // and so its __name__ has been set to "__main__". Get its real name
     285                 :            :         // that we stored during import in the __main__ attribute.
     286                 :          2 :         current_module_name_obj = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
     287                 :            :     }
     288                 :            :     #endif
     289                 :            : 
     290                 :            :     // If we have a __path__ in the globals dict, then we're a package.
     291                 :        104 :     bool is_pkg = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP);
     292                 :            : 
     293                 :            :     #if DEBUG_PRINT
     294                 :            :     DEBUG_printf("Current module/package: ");
     295                 :            :     mp_obj_print_helper(MICROPY_DEBUG_PRINTER, current_module_name_obj, PRINT_REPR);
     296                 :            :     DEBUG_printf(", is_package: %d", is_pkg);
     297                 :            :     DEBUG_printf("\n");
     298                 :            :     #endif
     299                 :            : 
     300                 :        104 :     size_t current_module_name_len;
     301                 :        104 :     const char *current_module_name = mp_obj_str_get_data(current_module_name_obj, &current_module_name_len);
     302                 :            : 
     303                 :        104 :     const char *p = current_module_name + current_module_name_len;
     304         [ +  + ]:        104 :     if (is_pkg) {
     305                 :            :         // If we're evaluating relative to a package, then take off one fewer
     306                 :            :         // level (i.e. the relative search starts inside the package, rather
     307                 :            :         // than as a sibling of the package).
     308                 :         75 :         --level;
     309                 :            :     }
     310                 :            : 
     311                 :            :     // Walk back 'level' dots (or run out of path).
     312         [ +  + ]:        387 :     while (level && p > current_module_name) {
     313         [ +  + ]:        283 :         if (*--p == '.') {
     314                 :         43 :             --level;
     315                 :            :         }
     316                 :            :     }
     317                 :            : 
     318                 :            :     // We must have some component left over to import from.
     319         [ +  + ]:        104 :     if (p == current_module_name) {
     320                 :          2 :         mp_raise_msg(&mp_type_ImportError, MP_ERROR_TEXT("can't perform relative import"));
     321                 :            :     }
     322                 :            : 
     323                 :            :     // New length is len("<chopped path>.<module_name>"). Note: might be one byte
     324                 :            :     // more than we need if module_name is empty (for the extra . we will
     325                 :            :     // append).
     326                 :        102 :     uint new_module_name_len = (size_t)(p - current_module_name) + 1 + *module_name_len;
     327                 :        102 :     char *new_mod = mp_local_alloc(new_module_name_len);
     328                 :        102 :     memcpy(new_mod, current_module_name, p - current_module_name);
     329                 :            : 
     330                 :            :     // Only append ".<module_name>" if there was one).
     331         [ +  + ]:        102 :     if (*module_name_len != 0) {
     332                 :         79 :         new_mod[p - current_module_name] = '.';
     333                 :         79 :         memcpy(new_mod + (p - current_module_name) + 1, *module_name, *module_name_len);
     334                 :            :     } else {
     335                 :            :         --new_module_name_len;
     336                 :            :     }
     337                 :            : 
     338                 :            :     // Copy into a QSTR.
     339                 :        102 :     qstr new_mod_q = qstr_from_strn(new_mod, new_module_name_len);
     340                 :        102 :     mp_local_free(new_mod);
     341                 :            : 
     342                 :        102 :     DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q));
     343                 :        102 :     *module_name = qstr_str(new_mod_q);
     344                 :        102 :     *module_name_len = new_module_name_len;
     345                 :        102 : }
     346                 :            : 
     347                 :            : // Load a module at the specified absolute path, possibly as a submodule of the given outer module.
     348                 :            : // full_mod_name:    The full absolute path to this module (e.g. "foo.bar.baz").
     349                 :            : // level_mod_name:   The final component of the path (e.g. "baz").
     350                 :            : // outer_module_obj: The parent module (we need to store this module as an
     351                 :            : //                   attribute on it) (or MP_OBJ_NULL for top-level).
     352                 :            : // path:             The filesystem path where we found the parent module
     353                 :            : //                   (or empty for a top level module).
     354                 :            : // override_main:    Whether to set the __name__ to "__main__" (and use __main__
     355                 :            : //                   for the actual path).
     356                 :       3065 : STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, mp_obj_t outer_module_obj, vstr_t *path, bool override_main) {
     357                 :       3065 :     mp_import_stat_t stat = MP_IMPORT_STAT_NO_EXIST;
     358                 :            : 
     359                 :            :     // Exact-match of built-in (or already-loaded) takes priority.
     360                 :       3065 :     mp_obj_t module_obj = mp_module_get_loaded_or_builtin(full_mod_name);
     361                 :            : 
     362                 :            :     // Even if we find the module, go through the motions of searching for it
     363                 :            :     // because we may actually be in the process of importing a sub-module.
     364                 :            :     // So we need to (re-)find the correct path to be finding the sub-module
     365                 :            :     // on the next iteration of process_import_at_level.
     366                 :            : 
     367         [ +  + ]:       3065 :     if (outer_module_obj == MP_OBJ_NULL) {
     368                 :       2942 :         DEBUG_printf("Searching for top-level module\n");
     369                 :            : 
     370                 :            :         // First module in the dotted-name; search for a directory or file
     371                 :            :         // relative to all the locations in sys.path.
     372                 :       2942 :         stat = stat_top_level_dir_or_file(full_mod_name, path);
     373                 :            : 
     374                 :            :         // If the module "foo" doesn't exist on the filesystem, and it's not a
     375                 :            :         // builtin, try and find "ufoo" as a built-in. (This feature was
     376                 :            :         // formerly known as "weak links").
     377                 :            :         #if MICROPY_MODULE_WEAK_LINKS
     378         [ +  + ]:       2942 :         if (stat == MP_IMPORT_STAT_NO_EXIST && module_obj == MP_OBJ_NULL) {
     379                 :        234 :             qstr umodule_name = make_weak_link_name(path, level_mod_name);
     380                 :        234 :             module_obj = mp_module_get_builtin(umodule_name);
     381                 :            :         }
     382                 :            :         #elif MICROPY_PY_SYS
     383                 :            :         if (stat == MP_IMPORT_STAT_NO_EXIST && module_obj == MP_OBJ_NULL && level_mod_name == MP_QSTR_sys) {
     384                 :            :             module_obj = MP_OBJ_FROM_PTR(&mp_module_sys);
     385                 :            :         }
     386                 :            :         #endif
     387                 :            :     } else {
     388                 :        123 :         DEBUG_printf("Searching for sub-module\n");
     389                 :            : 
     390                 :            :         // Add the current part of the module name to the path.
     391                 :        123 :         vstr_add_char(path, PATH_SEP_CHAR[0]);
     392                 :        123 :         vstr_add_str(path, qstr_str(level_mod_name));
     393                 :            : 
     394                 :            :         // Because it's not top level, we already know which path the parent was found in.
     395                 :        123 :         stat = stat_dir_or_file(path);
     396                 :            :     }
     397                 :       3065 :     DEBUG_printf("Current path: %.*s\n", (int)vstr_len(path), vstr_str(path));
     398                 :            : 
     399         [ +  + ]:       3065 :     if (module_obj == MP_OBJ_NULL) {
     400                 :            :         // Not a built-in and not already-loaded.
     401                 :            : 
     402         [ +  + ]:       1578 :         if (stat == MP_IMPORT_STAT_NO_EXIST) {
     403                 :            :             // And the file wasn't found -- fail.
     404                 :            :             #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
     405                 :            :             mp_raise_msg(&mp_type_ImportError, MP_ERROR_TEXT("module not found"));
     406                 :            :             #else
     407                 :         20 :             mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("no module named '%q'"), full_mod_name);
     408                 :            :             #endif
     409                 :            :         }
     410                 :            : 
     411                 :            :         // Not a built-in but found on the filesystem, try and load it.
     412                 :            : 
     413                 :       1558 :         DEBUG_printf("Found path: %.*s\n", (int)vstr_len(path), vstr_str(path));
     414                 :            : 
     415                 :            :         // Prepare for loading from the filesystem. Create a new shell module.
     416                 :       1558 :         module_obj = mp_obj_new_module(full_mod_name);
     417                 :            : 
     418                 :            :         #if MICROPY_MODULE_OVERRIDE_MAIN_IMPORT
     419                 :            :         // If this module is being loaded via -m on unix, then
     420                 :            :         // override __name__ to "__main__". Do this only for *modules*
     421                 :            :         // however - packages never have their names replaced, instead
     422                 :            :         // they're -m'ed using a special __main__ submodule in them. (This all
     423                 :            :         // apparently is done to not touch the package name itself, which is
     424                 :            :         // important for future imports).
     425         [ +  + ]:       1558 :         if (override_main && stat != MP_IMPORT_STAT_DIR) {
     426                 :       1297 :             mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj);
     427                 :       1297 :             mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
     428                 :            :             #if MICROPY_CPYTHON_COMPAT
     429                 :            :             // Store module as "__main__" in the dictionary of loaded modules (returned by sys.modules).
     430                 :       1297 :             mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)), MP_OBJ_NEW_QSTR(MP_QSTR___main__), module_obj);
     431                 :            :             // Store real name in "__main__" attribute. Need this for
     432                 :            :             // resolving relative imports later. "__main__ was chosen
     433                 :            :             // semi-randonly, to reuse existing qstr's.
     434                 :       1297 :             mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___main__), MP_OBJ_NEW_QSTR(full_mod_name));
     435                 :            :             #endif
     436                 :            :         }
     437                 :            :         #endif // MICROPY_MODULE_OVERRIDE_MAIN_IMPORT
     438                 :            : 
     439         [ +  + ]:       1558 :         if (stat == MP_IMPORT_STAT_DIR) {
     440                 :            :             // Directory -- execute "path/__init__.py".
     441                 :         88 :             DEBUG_printf("%.*s is dir\n", (int)vstr_len(path), vstr_str(path));
     442                 :            :             // Store the __path__ attribute onto this module.
     443                 :            :             // https://docs.python.org/3/reference/import.html
     444                 :            :             // "Specifically, any module that contains a __path__ attribute is considered a package."
     445                 :         88 :             mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(path), vstr_len(path)));
     446                 :         88 :             size_t orig_path_len = path->len;
     447                 :         88 :             vstr_add_str(path, PATH_SEP_CHAR "__init__.py");
     448         [ +  + ]:         88 :             if (stat_file_py_or_mpy(path) == MP_IMPORT_STAT_FILE) {
     449                 :         82 :                 do_load(MP_OBJ_TO_PTR(module_obj), path);
     450                 :            :             } else {
     451                 :            :                 // No-op. Nothing to load.
     452                 :            :                 // mp_warning("%s is imported as namespace package", vstr_str(&path));
     453                 :         88 :             }
     454                 :            :             // Remove /__init__.py suffix.
     455                 :         88 :             path->len = orig_path_len;
     456                 :            :         } else { // MP_IMPORT_STAT_FILE
     457                 :            :             // File -- execute "path.(m)py".
     458                 :       1470 :             do_load(MP_OBJ_TO_PTR(module_obj), path);
     459                 :            :             // Note: This should be the last component in the import path.  If
     460                 :            :             // there are remaining components then it's an ImportError
     461                 :            :             // because the current path(the module that was just loaded) is
     462                 :            :             // not a package.  This will be caught on the next iteration
     463                 :            :             // because the file will not exist.
     464                 :            :         }
     465                 :            :     }
     466                 :            : 
     467         [ +  + ]:       3023 :     if (outer_module_obj != MP_OBJ_NULL) {
     468                 :            :         // If it's a sub-module (not a built-in one), then make it available on
     469                 :            :         // the parent module.
     470                 :        123 :         mp_store_attr(outer_module_obj, level_mod_name, module_obj);
     471                 :            :     }
     472                 :            : 
     473                 :       3023 :     return module_obj;
     474                 :            : }
     475                 :            : 
     476                 :       2958 : mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) {
     477                 :            :     #if DEBUG_PRINT
     478                 :            :     DEBUG_printf("__import__:\n");
     479                 :            :     for (size_t i = 0; i < n_args; i++) {
     480                 :            :         DEBUG_printf("  ");
     481                 :            :         mp_obj_print_helper(MICROPY_DEBUG_PRINTER, args[i], PRINT_REPR);
     482                 :            :         DEBUG_printf("\n");
     483                 :            :     }
     484                 :            :     #endif
     485                 :            : 
     486                 :            :     // This is the import path, with any leading dots stripped.
     487                 :            :     // "import foo.bar" --> module_name="foo.bar"
     488                 :            :     // "from foo.bar import baz" --> module_name="foo.bar"
     489                 :            :     // "from . import foo" --> module_name=""
     490                 :            :     // "from ...foo.bar import baz" --> module_name="foo.bar"
     491                 :       2958 :     mp_obj_t module_name_obj = args[0];
     492                 :            : 
     493                 :            :     // These are the imported names.
     494                 :            :     // i.e. "from foo.bar import baz, zap" --> fromtuple=("baz", "zap",)
     495                 :            :     // Note: There's a special case on the Unix port, where this is set to mp_const_false which means that it's __main__.
     496                 :       2958 :     mp_obj_t fromtuple = mp_const_none;
     497                 :            : 
     498                 :            :     // Level is the number of leading dots in a relative import.
     499                 :            :     // i.e. "from . import foo" --> level=1
     500                 :            :     // i.e. "from ...foo.bar import baz" --> level=3
     501                 :       2958 :     mp_int_t level = 0;
     502                 :            : 
     503         [ +  + ]:       2958 :     if (n_args >= 4) {
     504                 :       2910 :         fromtuple = args[3];
     505         [ +  + ]:       2910 :         if (n_args >= 5) {
     506                 :       1609 :             level = MP_OBJ_SMALL_INT_VALUE(args[4]);
     507         [ +  + ]:       1609 :             if (level < 0) {
     508                 :          2 :                 mp_raise_ValueError(NULL);
     509                 :            :             }
     510                 :            :         }
     511                 :            :     }
     512                 :            : 
     513                 :       2956 :     size_t module_name_len;
     514                 :       2956 :     const char *module_name = mp_obj_str_get_data(module_name_obj, &module_name_len);
     515                 :            : 
     516         [ +  + ]:       2954 :     if (level != 0) {
     517                 :            :         // Turn "foo.bar" into "<current module minus 3 components>.foo.bar".
     518                 :        106 :         evaluate_relative_import(level, &module_name, &module_name_len);
     519                 :            :     }
     520                 :            : 
     521         [ +  + ]:       2950 :     if (module_name_len == 0) {
     522                 :          2 :         mp_raise_ValueError(NULL);
     523                 :            :     }
     524                 :            : 
     525                 :       2948 :     DEBUG_printf("Starting module search for '%s'\n", module_name);
     526                 :            : 
     527                 :       2948 :     VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX)
     528                 :       2948 :     mp_obj_t top_module_obj = MP_OBJ_NULL;
     529                 :       2948 :     mp_obj_t outer_module_obj = MP_OBJ_NULL;
     530                 :            : 
     531                 :            :     // Search for the end of each component.
     532                 :       2948 :     size_t current_component_start = 0;
     533         [ +  + ]:      30391 :     for (size_t i = 1; i <= module_name_len; i++) {
     534   [ +  +  +  + ]:      27491 :         if (i == module_name_len || module_name[i] == '.') {
     535                 :            :             // The module name up to this depth (e.g. foo.bar.baz).
     536                 :       3071 :             qstr full_mod_name = qstr_from_strn(module_name, i);
     537                 :            :             // The current level name (e.g. baz).
     538                 :       3065 :             qstr level_mod_name = qstr_from_strn(module_name + current_component_start, i - current_component_start);
     539                 :            : 
     540                 :       3065 :             DEBUG_printf("Processing module: '%s' at level '%s'\n", qstr_str(full_mod_name), qstr_str(level_mod_name));
     541                 :       3065 :             DEBUG_printf("Previous path: =%.*s=\n", (int)vstr_len(&path), vstr_str(&path));
     542                 :            : 
     543                 :            :             #if MICROPY_MODULE_OVERRIDE_MAIN_IMPORT
     544                 :            :             // On unix, if this is being loaded via -m (magic mp_const_false),
     545                 :            :             // then handle that if it's the final component.
     546   [ +  +  +  + ]:       3065 :             bool override_main = (i == module_name_len && fromtuple == mp_const_false);
     547                 :            :             #else
     548                 :            :             bool override_main = false;
     549                 :            :             #endif
     550                 :            : 
     551                 :            :             // Import this module.
     552                 :       3065 :             mp_obj_t module_obj = process_import_at_level(full_mod_name, level_mod_name, outer_module_obj, &path, override_main);
     553                 :            : 
     554                 :            :             // Set this as the parent module, and remember the top-level module if it's the first.
     555                 :       3023 :             outer_module_obj = module_obj;
     556         [ +  + ]:       3023 :             if (top_module_obj == MP_OBJ_NULL) {
     557                 :       2900 :                 top_module_obj = module_obj;
     558                 :            :             }
     559                 :            : 
     560                 :       3023 :             current_component_start = i + 1;
     561                 :            :         }
     562                 :            :     }
     563                 :            : 
     564         [ +  + ]:       2900 :     if (fromtuple != mp_const_none) {
     565                 :            :         // If fromtuple is not empty, return leaf module
     566                 :            :         return outer_module_obj;
     567                 :            :     } else {
     568                 :            :         // Otherwise, we need to return top-level package
     569                 :       1157 :         return top_module_obj;
     570                 :            :     }
     571                 :            : }
     572                 :            : 
     573                 :            : #else // MICROPY_ENABLE_EXTERNAL_IMPORT
     574                 :            : 
     575                 :            : mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) {
     576                 :            :     // Check that it's not a relative import
     577                 :            :     if (n_args >= 5 && MP_OBJ_SMALL_INT_VALUE(args[4]) != 0) {
     578                 :            :         mp_raise_NotImplementedError(MP_ERROR_TEXT("relative import"));
     579                 :            :     }
     580                 :            : 
     581                 :            :     // Check if module already exists, and return it if it does
     582                 :            :     qstr module_name_qstr = mp_obj_str_get_qstr(args[0]);
     583                 :            :     mp_obj_t module_obj = mp_module_get_loaded_or_builtin(module_name_qstr);
     584                 :            :     if (module_obj != MP_OBJ_NULL) {
     585                 :            :         return module_obj;
     586                 :            :     }
     587                 :            : 
     588                 :            :     #if MICROPY_MODULE_WEAK_LINKS
     589                 :            :     // Check if there is a weak link to this module
     590                 :            :     VSTR_FIXED(umodule_path, MICROPY_ALLOC_PATH_MAX);
     591                 :            :     qstr umodule_name_qstr = make_weak_link_name(&umodule_path, module_name_qstr);
     592                 :            :     module_obj = mp_module_get_loaded_or_builtin(umodule_name_qstr);
     593                 :            :     if (module_obj != MP_OBJ_NULL) {
     594                 :            :         return module_obj;
     595                 :            :     }
     596                 :            :     #endif
     597                 :            : 
     598                 :            :     // Couldn't find the module, so fail
     599                 :            :     #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
     600                 :            :     mp_raise_msg(&mp_type_ImportError, MP_ERROR_TEXT("module not found"));
     601                 :            :     #else
     602                 :            :     mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("no module named '%q'"), module_name_qstr);
     603                 :            :     #endif
     604                 :            : }
     605                 :            : 
     606                 :            : #endif // MICROPY_ENABLE_EXTERNAL_IMPORT
     607                 :            : 
     608                 :            : MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj, 1, 5, mp_builtin___import__);

Generated by: LCOV version 1.15-5-g462f71d