LCOV - code coverage report
Current view: top level - py - builtinimport.c (source / functions) Hit Total Coverage
Test: unix_coverage_v1.19.1-992-g38e7b842c.info Lines: 193 195 99.0 %
Date: 2023-03-23 12:38:05 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                 :        244 : STATIC qstr make_weak_link_name(vstr_t *buffer, qstr name) {
      50                 :        244 :     vstr_reset(buffer);
      51                 :        244 :     vstr_add_char(buffer, 'u');
      52                 :        244 :     vstr_add_str(buffer, qstr_str(name));
      53                 :        244 :     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                 :       1315 : bool mp_obj_is_package(mp_obj_t module) {
      66                 :       1315 :     mp_obj_t dest[2];
      67                 :       1315 :     mp_load_method_maybe(module, MP_QSTR___path__, dest);
      68                 :       1315 :     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                 :      17698 : 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                 :      17698 :     const int frozen_path_prefix_len = strlen(MP_FROZEN_PATH_PREFIX);
      79         [ +  + ]:      17698 :     if (strncmp(path, MP_FROZEN_PATH_PREFIX, frozen_path_prefix_len) == 0) {
      80                 :       4501 :         return mp_find_frozen_module(path + frozen_path_prefix_len, NULL, NULL);
      81                 :            :     }
      82                 :            :     #endif
      83                 :      13197 :     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                 :       5909 : STATIC mp_import_stat_t stat_file_py_or_mpy(vstr_t *path) {
      89                 :       5909 :     mp_import_stat_t stat = stat_path_or_frozen(vstr_null_terminated_str(path));
      90         [ +  + ]:       5909 :     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                 :       5668 :     vstr_ins_byte(path, path->len - 2, 'm');
      97                 :       5668 :     stat = stat_path_or_frozen(vstr_null_terminated_str(path));
      98         [ +  + ]:       5668 :     if (stat == MP_IMPORT_STAT_FILE) {
      99                 :       1331 :         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                 :       6121 : STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {
     109                 :       6121 :     mp_import_stat_t stat = stat_path_or_frozen(vstr_null_terminated_str(path));
     110                 :       6121 :     DEBUG_printf("stat %s: %d\n", vstr_str(path), stat);
     111         [ +  + ]:       6121 :     if (stat == MP_IMPORT_STAT_DIR) {
     112                 :            :         return stat;
     113                 :            :     }
     114                 :            : 
     115                 :            :     // not a directory, add .py and try as a file
     116                 :       5821 :     vstr_add_str(path, ".py");
     117                 :       5821 :     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                 :       2976 : STATIC mp_import_stat_t stat_top_level_dir_or_file(qstr mod_name, vstr_t *dest) {
     123                 :       2976 :     DEBUG_printf("stat_top_level_dir_or_file: '%s'\n", qstr_str(mod_name));
     124                 :            :     #if MICROPY_PY_SYS
     125                 :       2976 :     size_t path_num;
     126                 :       2976 :     mp_obj_t *path_items;
     127                 :       2976 :     mp_obj_list_get(mp_sys_path, &path_num, &path_items);
     128                 :            : 
     129         [ +  - ]:       2976 :     if (path_num > 0) {
     130                 :            :         // go through each path looking for a directory or file
     131         [ +  + ]:       7307 :         for (size_t i = 0; i < path_num; i++) {
     132                 :       5998 :             vstr_reset(dest);
     133                 :       5998 :             size_t p_len;
     134                 :       5998 :             const char *p = mp_obj_str_get_data(path_items[i], &p_len);
     135         [ +  + ]:       5998 :             if (p_len > 0) {
     136                 :       4355 :                 vstr_add_strn(dest, p, p_len);
     137                 :       4355 :                 vstr_add_char(dest, PATH_SEP_CHAR[0]);
     138                 :            :             }
     139                 :       5998 :             vstr_add_str(dest, qstr_str(mod_name));
     140                 :       5998 :             mp_import_stat_t stat = stat_dir_or_file(dest);
     141         [ +  + ]:       5998 :             if (stat != MP_IMPORT_STAT_NO_EXIST) {
     142                 :       1667 :                 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                 :       1329 : STATIC void do_execute_raw_code(const mp_module_context_t *context, const mp_raw_code_t *rc, const char *source_name) {
     172                 :       1329 :     (void)source_name;
     173                 :            : 
     174                 :            :     #if MICROPY_PY___FILE__
     175                 :       1329 :     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                 :       1329 :     mp_obj_dict_t *mod_globals = context->module.globals;
     180                 :            : 
     181                 :            :     // save context
     182                 :       1329 :     mp_obj_dict_t *volatile old_globals = mp_globals_get();
     183                 :       1329 :     mp_obj_dict_t *volatile old_locals = mp_locals_get();
     184                 :            : 
     185                 :            :     // set new context
     186                 :       1329 :     mp_globals_set(mod_globals);
     187                 :       1329 :     mp_locals_set(mod_globals);
     188                 :            : 
     189                 :       1329 :     nlr_buf_t nlr;
     190         [ +  + ]:       1329 :     if (nlr_push(&nlr) == 0) {
     191                 :       1329 :         mp_obj_t module_fun = mp_make_function_from_raw_code(rc, context, NULL);
     192                 :       1329 :         mp_call_function_0(module_fun);
     193                 :            : 
     194                 :            :         // finish nlr block, restore context
     195                 :       1323 :         nlr_pop();
     196                 :       1323 :         mp_globals_set(old_globals);
     197                 :       1323 :         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                 :       1323 : }
     205                 :            : #endif
     206                 :            : 
     207                 :       1558 : 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                 :       1558 :     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                 :       1558 :     void *modref;
     216                 :       1558 :     int frozen_type;
     217                 :       1558 :     const int frozen_path_prefix_len = strlen(MP_FROZEN_PATH_PREFIX);
     218         [ +  + ]:       1558 :     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         [ +  + ]:       1538 :     if (file_str[file->len - 3] == 'm') {
     248                 :       1331 :         mp_compiled_module_t cm;
     249                 :       1331 :         cm.context = module_obj;
     250                 :       1331 :         mp_raw_code_load_file(file_str, &cm);
     251                 :       1315 :         do_execute_raw_code(cm.context, cm.rc, file_str);
     252                 :       1311 :         return;
     253                 :            :     }
     254                 :            :     #endif
     255                 :            : 
     256                 :            :     // If we can compile scripts then load the file and compile and execute it.
     257                 :            :     #if MICROPY_ENABLE_COMPILER
     258                 :            :     {
     259                 :        207 :         mp_lexer_t *lex = mp_lexer_new_from_file(file_str);
     260                 :        207 :         do_load_from_lexer(module_obj, lex);
     261                 :        207 :         return;
     262                 :            :     }
     263                 :            :     #else
     264                 :            :     // If we get here then the file was not frozen and we can't compile scripts.
     265                 :            :     mp_raise_msg(&mp_type_ImportError, MP_ERROR_TEXT("script compilation not supported"));
     266                 :            :     #endif
     267                 :            : }
     268                 :            : 
     269                 :            : // Convert a relative (to the current module) import, going up "level" levels,
     270                 :            : // into an absolute import.
     271                 :        106 : STATIC void evaluate_relative_import(mp_int_t level, const char **module_name, size_t *module_name_len) {
     272                 :            :     // What we want to do here is to take the name of the current module,
     273                 :            :     // remove <level> trailing components, and concatenate the passed-in
     274                 :            :     // module name.
     275                 :            :     // For example, level=3, module_name="foo.bar", __name__="a.b.c.d" --> "a.foo.bar"
     276                 :            :     // "Relative imports use a module's __name__ attribute to determine that
     277                 :            :     // module's position in the package hierarchy."
     278                 :            :     // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name
     279                 :            : 
     280                 :        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__));
     281         [ -  + ]:        106 :     assert(current_module_name_obj != MP_OBJ_NULL);
     282                 :            : 
     283                 :            :     #if MICROPY_MODULE_OVERRIDE_MAIN_IMPORT && MICROPY_CPYTHON_COMPAT
     284         [ +  + ]:        106 :     if (MP_OBJ_QSTR_VALUE(current_module_name_obj) == MP_QSTR___main__) {
     285                 :            :         // This is a module loaded by -m command-line switch (e.g. unix port),
     286                 :            :         // and so its __name__ has been set to "__main__". Get its real name
     287                 :            :         // that we stored during import in the __main__ attribute.
     288                 :          2 :         current_module_name_obj = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
     289                 :            :     }
     290                 :            :     #endif
     291                 :            : 
     292                 :            :     // If we have a __path__ in the globals dict, then we're a package.
     293                 :        104 :     bool is_pkg = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP);
     294                 :            : 
     295                 :            :     #if DEBUG_PRINT
     296                 :            :     DEBUG_printf("Current module/package: ");
     297                 :            :     mp_obj_print_helper(MICROPY_DEBUG_PRINTER, current_module_name_obj, PRINT_REPR);
     298                 :            :     DEBUG_printf(", is_package: %d", is_pkg);
     299                 :            :     DEBUG_printf("\n");
     300                 :            :     #endif
     301                 :            : 
     302                 :        104 :     size_t current_module_name_len;
     303                 :        104 :     const char *current_module_name = mp_obj_str_get_data(current_module_name_obj, &current_module_name_len);
     304                 :            : 
     305                 :        104 :     const char *p = current_module_name + current_module_name_len;
     306         [ +  + ]:        104 :     if (is_pkg) {
     307                 :            :         // If we're evaluating relative to a package, then take off one fewer
     308                 :            :         // level (i.e. the relative search starts inside the package, rather
     309                 :            :         // than as a sibling of the package).
     310                 :         75 :         --level;
     311                 :            :     }
     312                 :            : 
     313                 :            :     // Walk back 'level' dots (or run out of path).
     314         [ +  + ]:        387 :     while (level && p > current_module_name) {
     315         [ +  + ]:        283 :         if (*--p == '.') {
     316                 :         43 :             --level;
     317                 :            :         }
     318                 :            :     }
     319                 :            : 
     320                 :            :     // We must have some component left over to import from.
     321         [ +  + ]:        104 :     if (p == current_module_name) {
     322                 :          2 :         mp_raise_msg(&mp_type_ImportError, MP_ERROR_TEXT("can't perform relative import"));
     323                 :            :     }
     324                 :            : 
     325                 :            :     // New length is len("<chopped path>.<module_name>"). Note: might be one byte
     326                 :            :     // more than we need if module_name is empty (for the extra . we will
     327                 :            :     // append).
     328                 :        102 :     uint new_module_name_len = (size_t)(p - current_module_name) + 1 + *module_name_len;
     329                 :        102 :     char *new_mod = mp_local_alloc(new_module_name_len);
     330                 :        102 :     memcpy(new_mod, current_module_name, p - current_module_name);
     331                 :            : 
     332                 :            :     // Only append ".<module_name>" if there was one).
     333         [ +  + ]:        102 :     if (*module_name_len != 0) {
     334                 :         79 :         new_mod[p - current_module_name] = '.';
     335                 :         79 :         memcpy(new_mod + (p - current_module_name) + 1, *module_name, *module_name_len);
     336                 :            :     } else {
     337                 :            :         --new_module_name_len;
     338                 :            :     }
     339                 :            : 
     340                 :            :     // Copy into a QSTR.
     341                 :        102 :     qstr new_mod_q = qstr_from_strn(new_mod, new_module_name_len);
     342                 :        102 :     mp_local_free(new_mod);
     343                 :            : 
     344                 :        102 :     DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q));
     345                 :        102 :     *module_name = qstr_str(new_mod_q);
     346                 :        102 :     *module_name_len = new_module_name_len;
     347                 :        102 : }
     348                 :            : 
     349                 :            : // Load a module at the specified absolute path, possibly as a submodule of the given outer module.
     350                 :            : // full_mod_name:    The full absolute path to this module (e.g. "foo.bar.baz").
     351                 :            : // level_mod_name:   The final component of the path (e.g. "baz").
     352                 :            : // outer_module_obj: The parent module (we need to store this module as an
     353                 :            : //                   attribute on it) (or MP_OBJ_NULL for top-level).
     354                 :            : // path:             The filesystem path where we found the parent module
     355                 :            : //                   (or empty for a top level module).
     356                 :            : // override_main:    Whether to set the __name__ to "__main__" (and use __main__
     357                 :            : //                   for the actual path).
     358                 :       3099 : 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) {
     359                 :       3099 :     mp_import_stat_t stat = MP_IMPORT_STAT_NO_EXIST;
     360                 :            : 
     361                 :            :     // Exact-match of built-in (or already-loaded) takes priority.
     362                 :       3099 :     mp_obj_t module_obj = mp_module_get_loaded_or_builtin(full_mod_name);
     363                 :            : 
     364                 :            :     // Even if we find the module, go through the motions of searching for it
     365                 :            :     // because we may actually be in the process of importing a sub-module.
     366                 :            :     // So we need to (re-)find the correct path to be finding the sub-module
     367                 :            :     // on the next iteration of process_import_at_level.
     368                 :            : 
     369         [ +  + ]:       3099 :     if (outer_module_obj == MP_OBJ_NULL) {
     370                 :       2976 :         DEBUG_printf("Searching for top-level module\n");
     371                 :            : 
     372                 :            :         // First module in the dotted-name; search for a directory or file
     373                 :            :         // relative to all the locations in sys.path.
     374                 :       2976 :         stat = stat_top_level_dir_or_file(full_mod_name, path);
     375                 :            : 
     376                 :            :         // If the module "foo" doesn't exist on the filesystem, and it's not a
     377                 :            :         // builtin, try and find "ufoo" as a built-in. (This feature was
     378                 :            :         // formerly known as "weak links").
     379                 :            :         #if MICROPY_MODULE_WEAK_LINKS
     380         [ +  + ]:       2976 :         if (stat == MP_IMPORT_STAT_NO_EXIST && module_obj == MP_OBJ_NULL) {
     381                 :        244 :             qstr umodule_name = make_weak_link_name(path, level_mod_name);
     382                 :        244 :             module_obj = mp_module_get_builtin(umodule_name);
     383                 :            :         }
     384                 :            :         #elif MICROPY_PY_SYS
     385                 :            :         if (stat == MP_IMPORT_STAT_NO_EXIST && module_obj == MP_OBJ_NULL && level_mod_name == MP_QSTR_sys) {
     386                 :            :             module_obj = MP_OBJ_FROM_PTR(&mp_module_sys);
     387                 :            :         }
     388                 :            :         #endif
     389                 :            :     } else {
     390                 :        123 :         DEBUG_printf("Searching for sub-module\n");
     391                 :            : 
     392                 :            :         // Add the current part of the module name to the path.
     393                 :        123 :         vstr_add_char(path, PATH_SEP_CHAR[0]);
     394                 :        123 :         vstr_add_str(path, qstr_str(level_mod_name));
     395                 :            : 
     396                 :            :         // Because it's not top level, we already know which path the parent was found in.
     397                 :        123 :         stat = stat_dir_or_file(path);
     398                 :            :     }
     399                 :       3099 :     DEBUG_printf("Current path: %.*s\n", (int)vstr_len(path), vstr_str(path));
     400                 :            : 
     401         [ +  + ]:       3099 :     if (module_obj == MP_OBJ_NULL) {
     402                 :            :         // Not a built-in and not already-loaded.
     403                 :            : 
     404         [ +  + ]:       1584 :         if (stat == MP_IMPORT_STAT_NO_EXIST) {
     405                 :            :             // And the file wasn't found -- fail.
     406                 :            :             #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
     407                 :            :             mp_raise_msg(&mp_type_ImportError, MP_ERROR_TEXT("module not found"));
     408                 :            :             #else
     409                 :         20 :             mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("no module named '%q'"), full_mod_name);
     410                 :            :             #endif
     411                 :            :         }
     412                 :            : 
     413                 :            :         // Not a built-in but found on the filesystem, try and load it.
     414                 :            : 
     415                 :       1564 :         DEBUG_printf("Found path: %.*s\n", (int)vstr_len(path), vstr_str(path));
     416                 :            : 
     417                 :            :         // Prepare for loading from the filesystem. Create a new shell module.
     418                 :       1564 :         module_obj = mp_obj_new_module(full_mod_name);
     419                 :            : 
     420                 :            :         #if MICROPY_MODULE_OVERRIDE_MAIN_IMPORT
     421                 :            :         // If this module is being loaded via -m on unix, then
     422                 :            :         // override __name__ to "__main__". Do this only for *modules*
     423                 :            :         // however - packages never have their names replaced, instead
     424                 :            :         // they're -m'ed using a special __main__ submodule in them. (This all
     425                 :            :         // apparently is done to not touch the package name itself, which is
     426                 :            :         // important for future imports).
     427         [ +  + ]:       1564 :         if (override_main && stat != MP_IMPORT_STAT_DIR) {
     428                 :       1303 :             mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj);
     429                 :       1303 :             mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
     430                 :            :             #if MICROPY_CPYTHON_COMPAT
     431                 :            :             // Store module as "__main__" in the dictionary of loaded modules (returned by sys.modules).
     432                 :       1303 :             mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)), MP_OBJ_NEW_QSTR(MP_QSTR___main__), module_obj);
     433                 :            :             // Store real name in "__main__" attribute. Need this for
     434                 :            :             // resolving relative imports later. "__main__ was chosen
     435                 :            :             // semi-randonly, to reuse existing qstr's.
     436                 :       1303 :             mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___main__), MP_OBJ_NEW_QSTR(full_mod_name));
     437                 :            :             #endif
     438                 :            :         }
     439                 :            :         #endif // MICROPY_MODULE_OVERRIDE_MAIN_IMPORT
     440                 :            : 
     441         [ +  + ]:       1564 :         if (stat == MP_IMPORT_STAT_DIR) {
     442                 :            :             // Directory -- execute "path/__init__.py".
     443                 :         88 :             DEBUG_printf("%.*s is dir\n", (int)vstr_len(path), vstr_str(path));
     444                 :            :             // Store the __path__ attribute onto this module.
     445                 :            :             // https://docs.python.org/3/reference/import.html
     446                 :            :             // "Specifically, any module that contains a __path__ attribute is considered a package."
     447                 :         88 :             mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(path), vstr_len(path)));
     448                 :         88 :             size_t orig_path_len = path->len;
     449                 :         88 :             vstr_add_str(path, PATH_SEP_CHAR "__init__.py");
     450         [ +  + ]:         88 :             if (stat_file_py_or_mpy(path) == MP_IMPORT_STAT_FILE) {
     451                 :         82 :                 do_load(MP_OBJ_TO_PTR(module_obj), path);
     452                 :            :             } else {
     453                 :            :                 // No-op. Nothing to load.
     454                 :            :                 // mp_warning("%s is imported as namespace package", vstr_str(&path));
     455                 :         88 :             }
     456                 :            :             // Remove /__init__.py suffix.
     457                 :         88 :             path->len = orig_path_len;
     458                 :            :         } else { // MP_IMPORT_STAT_FILE
     459                 :            :             // File -- execute "path.(m)py".
     460                 :       1476 :             do_load(MP_OBJ_TO_PTR(module_obj), path);
     461                 :            :             // Note: This should be the last component in the import path.  If
     462                 :            :             // there are remaining components then it's an ImportError
     463                 :            :             // because the current path(the module that was just loaded) is
     464                 :            :             // not a package.  This will be caught on the next iteration
     465                 :            :             // because the file will not exist.
     466                 :            :         }
     467                 :            :     }
     468                 :            : 
     469         [ +  + ]:       3057 :     if (outer_module_obj != MP_OBJ_NULL) {
     470                 :            :         // If it's a sub-module (not a built-in one), then make it available on
     471                 :            :         // the parent module.
     472                 :        123 :         mp_store_attr(outer_module_obj, level_mod_name, module_obj);
     473                 :            :     }
     474                 :            : 
     475                 :       3057 :     return module_obj;
     476                 :            : }
     477                 :            : 
     478                 :       2992 : mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) {
     479                 :            :     #if DEBUG_PRINT
     480                 :            :     DEBUG_printf("__import__:\n");
     481                 :            :     for (size_t i = 0; i < n_args; i++) {
     482                 :            :         DEBUG_printf("  ");
     483                 :            :         mp_obj_print_helper(MICROPY_DEBUG_PRINTER, args[i], PRINT_REPR);
     484                 :            :         DEBUG_printf("\n");
     485                 :            :     }
     486                 :            :     #endif
     487                 :            : 
     488                 :            :     // This is the import path, with any leading dots stripped.
     489                 :            :     // "import foo.bar" --> module_name="foo.bar"
     490                 :            :     // "from foo.bar import baz" --> module_name="foo.bar"
     491                 :            :     // "from . import foo" --> module_name=""
     492                 :            :     // "from ...foo.bar import baz" --> module_name="foo.bar"
     493                 :       2992 :     mp_obj_t module_name_obj = args[0];
     494                 :            : 
     495                 :            :     // These are the imported names.
     496                 :            :     // i.e. "from foo.bar import baz, zap" --> fromtuple=("baz", "zap",)
     497                 :            :     // Note: There's a special case on the Unix port, where this is set to mp_const_false which means that it's __main__.
     498                 :       2992 :     mp_obj_t fromtuple = mp_const_none;
     499                 :            : 
     500                 :            :     // Level is the number of leading dots in a relative import.
     501                 :            :     // i.e. "from . import foo" --> level=1
     502                 :            :     // i.e. "from ...foo.bar import baz" --> level=3
     503                 :       2992 :     mp_int_t level = 0;
     504                 :            : 
     505         [ +  + ]:       2992 :     if (n_args >= 4) {
     506                 :       2944 :         fromtuple = args[3];
     507         [ +  + ]:       2944 :         if (n_args >= 5) {
     508                 :       1637 :             level = MP_OBJ_SMALL_INT_VALUE(args[4]);
     509         [ +  + ]:       1637 :             if (level < 0) {
     510                 :          2 :                 mp_raise_ValueError(NULL);
     511                 :            :             }
     512                 :            :         }
     513                 :            :     }
     514                 :            : 
     515                 :       2990 :     size_t module_name_len;
     516                 :       2990 :     const char *module_name = mp_obj_str_get_data(module_name_obj, &module_name_len);
     517                 :            : 
     518         [ +  + ]:       2988 :     if (level != 0) {
     519                 :            :         // Turn "foo.bar" into "<current module minus 3 components>.foo.bar".
     520                 :        106 :         evaluate_relative_import(level, &module_name, &module_name_len);
     521                 :            :     }
     522                 :            : 
     523         [ +  + ]:       2984 :     if (module_name_len == 0) {
     524                 :          2 :         mp_raise_ValueError(NULL);
     525                 :            :     }
     526                 :            : 
     527                 :       2982 :     DEBUG_printf("Starting module search for '%s'\n", module_name);
     528                 :            : 
     529                 :       2982 :     VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX)
     530                 :       2982 :     mp_obj_t top_module_obj = MP_OBJ_NULL;
     531                 :       2982 :     mp_obj_t outer_module_obj = MP_OBJ_NULL;
     532                 :            : 
     533                 :            :     // Search for the end of each component.
     534                 :       2982 :     size_t current_component_start = 0;
     535         [ +  + ]:      30665 :     for (size_t i = 1; i <= module_name_len; i++) {
     536   [ +  +  +  + ]:      27731 :         if (i == module_name_len || module_name[i] == '.') {
     537                 :            :             // The module name up to this depth (e.g. foo.bar.baz).
     538                 :       3105 :             qstr full_mod_name = qstr_from_strn(module_name, i);
     539                 :            :             // The current level name (e.g. baz).
     540                 :       3099 :             qstr level_mod_name = qstr_from_strn(module_name + current_component_start, i - current_component_start);
     541                 :            : 
     542                 :       3099 :             DEBUG_printf("Processing module: '%s' at level '%s'\n", qstr_str(full_mod_name), qstr_str(level_mod_name));
     543                 :       3099 :             DEBUG_printf("Previous path: =%.*s=\n", (int)vstr_len(&path), vstr_str(&path));
     544                 :            : 
     545                 :            :             #if MICROPY_MODULE_OVERRIDE_MAIN_IMPORT
     546                 :            :             // On unix, if this is being loaded via -m (magic mp_const_false),
     547                 :            :             // then handle that if it's the final component.
     548   [ +  +  +  + ]:       3099 :             bool override_main = (i == module_name_len && fromtuple == mp_const_false);
     549                 :            :             #else
     550                 :            :             bool override_main = false;
     551                 :            :             #endif
     552                 :            : 
     553                 :            :             // Import this module.
     554                 :       3099 :             mp_obj_t module_obj = process_import_at_level(full_mod_name, level_mod_name, outer_module_obj, &path, override_main);
     555                 :            : 
     556                 :            :             // Set this as the parent module, and remember the top-level module if it's the first.
     557                 :       3057 :             outer_module_obj = module_obj;
     558         [ +  + ]:       3057 :             if (top_module_obj == MP_OBJ_NULL) {
     559                 :       2934 :                 top_module_obj = module_obj;
     560                 :            :             }
     561                 :            : 
     562                 :       3057 :             current_component_start = i + 1;
     563                 :            :         }
     564                 :            :     }
     565                 :            : 
     566         [ +  + ]:       2934 :     if (fromtuple != mp_const_none) {
     567                 :            :         // If fromtuple is not empty, return leaf module
     568                 :            :         return outer_module_obj;
     569                 :            :     } else {
     570                 :            :         // Otherwise, we need to return top-level package
     571                 :       1175 :         return top_module_obj;
     572                 :            :     }
     573                 :            : }
     574                 :            : 
     575                 :            : #else // MICROPY_ENABLE_EXTERNAL_IMPORT
     576                 :            : 
     577                 :            : bool mp_obj_is_package(mp_obj_t module) {
     578                 :            :     return false;
     579                 :            : }
     580                 :            : 
     581                 :            : mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) {
     582                 :            :     // Check that it's not a relative import
     583                 :            :     if (n_args >= 5 && MP_OBJ_SMALL_INT_VALUE(args[4]) != 0) {
     584                 :            :         mp_raise_NotImplementedError(MP_ERROR_TEXT("relative import"));
     585                 :            :     }
     586                 :            : 
     587                 :            :     // Check if module already exists, and return it if it does
     588                 :            :     qstr module_name_qstr = mp_obj_str_get_qstr(args[0]);
     589                 :            :     mp_obj_t module_obj = mp_module_get_loaded_or_builtin(module_name_qstr);
     590                 :            :     if (module_obj != MP_OBJ_NULL) {
     591                 :            :         return module_obj;
     592                 :            :     }
     593                 :            : 
     594                 :            :     #if MICROPY_MODULE_WEAK_LINKS
     595                 :            :     // Check if there is a weak link to this module
     596                 :            :     VSTR_FIXED(umodule_path, MICROPY_ALLOC_PATH_MAX);
     597                 :            :     qstr umodule_name_qstr = make_weak_link_name(&umodule_path, module_name_qstr);
     598                 :            :     module_obj = mp_module_get_loaded_or_builtin(umodule_name_qstr);
     599                 :            :     if (module_obj != MP_OBJ_NULL) {
     600                 :            :         return module_obj;
     601                 :            :     }
     602                 :            :     #endif
     603                 :            : 
     604                 :            :     // Couldn't find the module, so fail
     605                 :            :     #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
     606                 :            :     mp_raise_msg(&mp_type_ImportError, MP_ERROR_TEXT("module not found"));
     607                 :            :     #else
     608                 :            :     mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("no module named '%q'"), module_name_qstr);
     609                 :            :     #endif
     610                 :            : }
     611                 :            : 
     612                 :            : #endif // MICROPY_ENABLE_EXTERNAL_IMPORT
     613                 :            : 
     614                 :            : MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj, 1, 5, mp_builtin___import__);

Generated by: LCOV version 1.15-5-g462f71d