builtinimport.c 13.7 KB
Newer Older
1
2
3
4
5
6
/*
 * This file is part of the Micro Python project, http://micropython.org/
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2013, 2014 Damien P. George
7
 * Copyright (c) 2014 Paul Sokolovsky
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

28
29
30
31
32
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

33
#include "mpconfig.h"
34
35
#include "nlr.h"
#include "misc.h"
36
#include "qstr.h"
37
38
39
40
#include "lexer.h"
#include "lexerunix.h"
#include "parse.h"
#include "obj.h"
41
#include "objmodule.h"
42
#include "parsehelper.h"
43
#include "compile.h"
44
45
46
#include "runtime0.h"
#include "runtime.h"
#include "builtin.h"
47
#include "builtintables.h"
48

49
50
51
52
#if 0 // print debugging info
#define DEBUG_PRINT (1)
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
53
#define DEBUG_PRINT (0)
54
55
56
#define DEBUG_printf(...) (void)0
#endif

57
58
#define PATH_SEP_CHAR '/'

59
60
61
62
63
64
bool mp_obj_is_package(mp_obj_t module) {
    mp_obj_t dest[2];
    mp_load_method_maybe(module, MP_QSTR___path__, dest);
    return dest[0] != MP_OBJ_NULL;
}

Damien George's avatar
Damien George committed
65
STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {
66
67
68
69
    //printf("stat %s\n", vstr_str(path));
    mp_import_stat_t stat = mp_import_stat(vstr_str(path));
    if (stat == MP_IMPORT_STAT_DIR) {
        return stat;
70
    }
71
72
73
74
    vstr_add_str(path, ".py");
    stat = mp_import_stat(vstr_str(path));
    if (stat == MP_IMPORT_STAT_FILE) {
        return stat;
75
    }
76
77
    return MP_IMPORT_STAT_NO_EXIST;
}
78

Damien George's avatar
Damien George committed
79
STATIC mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *dest) {
80
#if MICROPY_PY_SYS
81
    // extract the list of paths
82
    mp_uint_t path_num;
83
    mp_obj_t *path_items;
84
    mp_obj_list_get(mp_sys_path, &path_num, &path_items);
85
86

    if (path_num == 0) {
87
#endif
Damien George's avatar
Damien George committed
88
        // mp_sys_path is empty, so just use the given file name
89
90
        vstr_add_strn(dest, file_str, file_len);
        return stat_dir_or_file(dest);
91
#if MICROPY_PY_SYS
92
    } else {
93
        // go through each path looking for a directory or file
94
        for (mp_uint_t i = 0; i < path_num; i++) {
95
            vstr_reset(dest);
96
            mp_uint_t p_len;
97
            const char *p = mp_obj_str_get_data(path_items[i], &p_len);
98
            if (p_len > 0) {
99
                vstr_add_strn(dest, p, p_len);
100
                vstr_add_char(dest, PATH_SEP_CHAR);
101
            }
102
103
104
105
            vstr_add_strn(dest, file_str, file_len);
            mp_import_stat_t stat = stat_dir_or_file(dest);
            if (stat != MP_IMPORT_STAT_NO_EXIST) {
                return stat;
106
107
            }
        }
108
109
110

        // could not find a directory or file
        return MP_IMPORT_STAT_NO_EXIST;
111
    }
112
#endif
113
114
}

Damien George's avatar
Damien George committed
115
STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
116
117
    // create the lexer
    mp_lexer_t *lex = mp_lexer_new_from_file(vstr_str(file));
118

119
    if (lex == NULL) {
120
        // we verified the file exists using stat, but lexer could still fail
121
122
123
124
125
126
        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
            nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "module not found"));
        } else {
            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
                "no module named '%s'", vstr_str(file)));
        }
127
128
    }

129
    #if MICROPY_PY___FILE__
130
    qstr source_name = lex->source_name;
131
    mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
132
    #endif
133

134
135
136
    // parse, compile and execute the module in its context
    mp_obj_dict_t *mod_globals = mp_obj_module_get_globals(module_obj);
    mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals);
137
138
}

139
mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) {
140
#if DEBUG_PRINT
141
    DEBUG_printf("__import__:\n");
142
    for (mp_uint_t i = 0; i < n_args; i++) {
143
        DEBUG_printf("  ");
144
        mp_obj_print(args[i], PRINT_REPR);
145
        DEBUG_printf("\n");
146
    }
147
#endif
148

149
    mp_obj_t module_name = args[0];
150
    mp_obj_t fromtuple = mp_const_none;
151
    mp_int_t level = 0;
152
153
    if (n_args >= 4) {
        fromtuple = args[3];
154
155
156
157
158
        if (n_args >= 5) {
            level = MP_OBJ_SMALL_INT_VALUE(args[4]);
        }
    }

159
160
    mp_uint_t mod_len;
    const char *mod_str = mp_obj_str_get_data(module_name, &mod_len);
161

162
    if (level != 0) {
163
164
165
166
167
168
169
170
171
172
        // What we want to do here is to take name of current module,
        // chop <level> trailing components, and concatenate with passed-in
        // module name, thus resolving relative import name into absolue.
        // This even appears to be correct per
        // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name
        // "Relative imports use a module's __name__ attribute to determine that
        // module's position in the package hierarchy."
        mp_obj_t this_name_q = mp_obj_dict_get(mp_globals_get(), MP_OBJ_NEW_QSTR(MP_QSTR___name__));
        assert(this_name_q != MP_OBJ_NULL);
#if DEBUG_PRINT
173
        DEBUG_printf("Current module: ");
174
        mp_obj_print(this_name_q, PRINT_REPR);
175
        DEBUG_printf("\n");
176
#endif
177

178
179
        mp_uint_t this_name_l;
        const char *this_name = mp_obj_str_get_data(this_name_q, &this_name_l);
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222

        uint dots_seen = 0;
        const char *p = this_name + this_name_l - 1;
        while (p > this_name) {
            if (*p == '.') {
                dots_seen++;
                if (--level == 0) {
                    break;
                }
            }
            p--;
        }

        if (dots_seen == 0 && level == 1) {
            // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name
            // "If the module's name does not contain any package information
            // (e.g. it is set to '__main__') then relative imports are
            // resolved as if the module were a top level module, regardless
            // of where the module is actually located on the file system."
            // Supposedly this if catches this condition and resolve it properly
            // TODO: But nobody knows for sure. This condition happens when
            // package's __init__.py does something like "import .submod". So,
            // maybe we should check for package here? But quote above doesn't
            // talk about packages, it talks about dot-less module names.
            p = this_name + this_name_l;
        } else if (level != 0) {
            nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "Invalid relative import"));
        }

        uint new_mod_l = (mod_len == 0 ? p - this_name : p - this_name + 1 + mod_len);
        char *new_mod = alloca(new_mod_l);
        memcpy(new_mod, this_name, p - this_name);
        if (mod_len != 0) {
            new_mod[p - this_name] = '.';
            memcpy(new_mod + (p - this_name) + 1, mod_str, mod_len);
        }

        qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l);
        DEBUG_printf("Resolved relative name: %s\n", qstr_str(new_mod_q));
        module_name = MP_OBJ_NEW_QSTR(new_mod_q);
        mod_str = new_mod;
        mod_len = new_mod_l;
    }
223

224
    // check if module already exists
225
    mp_obj_t module_obj = mp_module_get(mp_obj_str_get_qstr(module_name));
226
    if (module_obj != MP_OBJ_NULL) {
227
        DEBUG_printf("Module already loaded\n");
228
229
230
231
232
        // If it's not a package, return module right away
        char *p = strchr(mod_str, '.');
        if (p == NULL) {
            return module_obj;
        }
233
234
235
236
        // If fromlist is not empty, return leaf module
        if (fromtuple != mp_const_none) {
            return module_obj;
        }
237
238
        // Otherwise, we need to return top-level package
        qstr pkg_name = qstr_from_strn(mod_str, p - mod_str);
239
        return mp_module_get(pkg_name);
240
    }
241
    DEBUG_printf("Module not yet loaded\n");
242
243

    uint last = 0;
244
    VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX)
245
    module_obj = MP_OBJ_NULL;
246
247
    mp_obj_t top_module_obj = MP_OBJ_NULL;
    mp_obj_t outer_module_obj = MP_OBJ_NULL;
248
249
250
251
252
    uint i;
    for (i = 1; i <= mod_len; i++) {
        if (i == mod_len || mod_str[i] == '.') {
            // create a qstr for the module name up to this depth
            qstr mod_name = qstr_from_strn(mod_str, i);
253
            DEBUG_printf("Processing module: %s\n", qstr_str(mod_name));
254
            DEBUG_printf("Previous path: %s\n", vstr_str(&path));
255
256
257

            // find the file corresponding to the module name
            mp_import_stat_t stat;
258
            if (vstr_len(&path) == 0) {
259
                // first module in the dotted-name; search for a directory or file
260
                stat = find_file(mod_str, i, &path);
261
262
            } else {
                // latter module in the dotted-name; append to path
263
264
265
                vstr_add_char(&path, PATH_SEP_CHAR);
                vstr_add_strn(&path, mod_str + last, i - last);
                stat = stat_dir_or_file(&path);
266
            }
267
            DEBUG_printf("Current path: %s\n", vstr_str(&path));
268
269

            if (stat == MP_IMPORT_STAT_NO_EXIST) {
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
                #if MICROPY_MODULE_WEAK_LINKS
                // check if there is a weak link to this module
                if (i == mod_len) {
                    mp_map_elem_t *el = mp_map_lookup((mp_map_t*)&mp_builtin_module_weak_links_dict_obj.map, MP_OBJ_NEW_QSTR(mod_name), MP_MAP_LOOKUP);
                    if (el == NULL) {
                        goto no_exist;
                    }
                    // found weak linked module
                    module_obj = el->value;
                } else {
                    no_exist:
                #else
                {
                #endif
                    // couldn't find the file, so fail
285
286
287
288
289
290
                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
                        nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "module not found"));
                    } else {
                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
                            "no module named '%s'", qstr_str(mod_name)));
                    }
291
292
293
294
                }
            } else {
                // found the file, so get the module
                module_obj = mp_module_get(mod_name);
295
296
297
298
299
300
301
            }

            if (module_obj == MP_OBJ_NULL) {
                // module not already loaded, so load it!

                module_obj = mp_obj_new_module(mod_name);

302
303
304
305
306
307
308
309
                // if args[3] (fromtuple) has magic value False, set up
                // this module for command-line "-m" option (set module's
                // name to __main__ instead of real name).
                if (i == mod_len && fromtuple == mp_const_false) {
                    mp_obj_module_t *o = module_obj;
                    mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
                }

310
                if (stat == MP_IMPORT_STAT_DIR) {
311
                    DEBUG_printf("%s is dir\n", vstr_str(&path));
312
                    // https://docs.python.org/3/reference/import.html
313
                    // "Specifically, any module that contains a __path__ attribute is considered a package."
314
                    mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path), false));
315
316
                    vstr_add_char(&path, PATH_SEP_CHAR);
                    vstr_add_str(&path, "__init__.py");
317
                    if (mp_import_stat(vstr_str(&path)) != MP_IMPORT_STAT_FILE) {
318
                        vstr_cut_tail_bytes(&path, sizeof("/__init__.py") - 1); // cut off /__init__.py
319
320
321
                        printf("Notice: %s is imported as namespace package\n", vstr_str(&path));
                    } else {
                        do_load(module_obj, &path);
322
                        vstr_cut_tail_bytes(&path, sizeof("/__init__.py") - 1); // cut off /__init__.py
323
324
                    }
                } else { // MP_IMPORT_STAT_FILE
325
                    do_load(module_obj, &path);
326
327
328
329
                    // TODO: We cannot just break here, at the very least, we must execute
                    // trailer code below. But otherwise if there're remaining components,
                    // that would be (??) object path within module, not modules path within FS.
                    // break;
330
331
                }
            }
332
333
            if (outer_module_obj != MP_OBJ_NULL) {
                qstr s = qstr_from_strn(mod_str + last, i - last);
Damien George's avatar
Damien George committed
334
                mp_store_attr(outer_module_obj, s, module_obj);
335
336
337
338
339
340
            }
            outer_module_obj = module_obj;
            if (top_module_obj == MP_OBJ_NULL) {
                top_module_obj = module_obj;
            }
            last = i + 1;
341
342
343
344
345
346
347
348
349
        }
    }

    if (i < mod_len) {
        // we loaded a package, now need to load objects from within that package
        // TODO
        assert(0);
    }

350
351
352
353
354
    // If fromlist is not empty, return leaf module
    if (fromtuple != mp_const_none) {
        return module_obj;
    }
    // Otherwise, we need to return top-level package
355
    return top_module_obj;
356
}
357
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj, 1, 5, mp_builtin___import__);