Merge branch 'master' of github.com:micropython/micropython

pull/469/merge
Damien George 2014-04-11 23:26:18 +01:00
commit c42e4b6c53
7 zmienionych plików z 84 dodań i 31 usunięć

Wyświetl plik

@ -19,6 +19,13 @@
#include "runtime.h"
#include "builtin.h"
#if 0 // print debugging info
#define DEBUG_PRINT (1)
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
#define DEBUG_printf(...) (void)0
#endif
#define PATH_SEP_CHAR '/'
mp_obj_t mp_sys_path;
@ -129,14 +136,14 @@ void do_load(mp_obj_t module_obj, vstr_t *file) {
}
mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args) {
/*
printf("import:\n");
#if DEBUG_PRINT
printf("__import__:\n");
for (int i = 0; i < n_args; i++) {
printf(" ");
mp_obj_print(args[i], PRINT_REPR);
printf("\n");
}
*/
#endif
mp_obj_t fromtuple = mp_const_none;
int level = 0;
@ -158,6 +165,7 @@ mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args) {
// check if module already exists
mp_obj_t module_obj = mp_module_get(mp_obj_str_get_qstr(args[0]));
if (module_obj != MP_OBJ_NULL) {
DEBUG_printf("Module already loaded\n");
// If it's not a package, return module right away
char *p = strchr(mod_str, '.');
if (p == NULL) {
@ -171,6 +179,7 @@ mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args) {
qstr pkg_name = qstr_from_strn(mod_str, p - mod_str);
return mp_module_get(pkg_name);
}
DEBUG_printf("Module not yet loaded\n");
uint last = 0;
VSTR_FIXED(path, MICROPY_PATH_MAX)
@ -182,6 +191,7 @@ mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args) {
if (i == mod_len || mod_str[i] == '.') {
// create a qstr for the module name up to this depth
qstr mod_name = qstr_from_strn(mod_str, i);
DEBUG_printf("Processing module: %s\n", qstr_str(mod_name));
// find the file corresponding to the module name
mp_import_stat_t stat;
@ -207,6 +217,7 @@ mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args) {
module_obj = mp_obj_new_module(mod_name);
if (stat == MP_IMPORT_STAT_DIR) {
DEBUG_printf("%s is dir\n", vstr_str(&path));
vstr_add_char(&path, PATH_SEP_CHAR);
vstr_add_str(&path, "__init__.py");
if (mp_import_stat(vstr_str(&path)) != MP_IMPORT_STAT_FILE) {
@ -217,6 +228,9 @@ mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args) {
}
do_load(module_obj, &path);
vstr_cut_tail_bytes(&path, sizeof("/__init__.py") - 1); // cut off /__init__.py
// https://docs.python.org/3.3/reference/import.html
// "Specifically, any module that contains a __path__ attribute is considered a package."
mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str((byte*)vstr_str(&path), vstr_len(&path), false));
} else { // MP_IMPORT_STAT_FILE
do_load(module_obj, &path);
// TODO: We cannot just break here, at the very least, we must execute

Wyświetl plik

@ -26,10 +26,10 @@ def compute_hash(qstr):
def do_work(infiles):
# read the qstrs in from the input files
qstrs = {}
cpp_header_blocks = 3
for infile in infiles:
with open(infile, 'rt') as f:
line_number = 0
conditional = None
for line in f:
line_number += 1
line = line.strip()
@ -38,17 +38,13 @@ def do_work(infiles):
if len(line) == 0 or line.startswith('//'):
continue
if line[0] == '#':
if conditional == "<endif>":
assert line == "#endif"
conditional = None
else:
assert conditional is None
conditional = line
# We'll have 3 line-number lines for py/qstrdefs.h - initial, leaving it to
# go into other headers, and returning to it.
if line.startswith('# ') and 'py/qstrdefs.h' in line:
cpp_header_blocks -= 1
continue
if cpp_header_blocks != 0:
continue
if conditional == "<endif>":
assert False, "#endif expected before '%s'" % line
# verify line is of the correct form
match = re.match(r'Q\((.+)\)$', line)
@ -65,21 +61,15 @@ def do_work(infiles):
continue
# add the qstr to the list, with order number to retain original order in file
qstrs[ident] = (len(qstrs), ident, qstr, conditional)
if conditional is not None:
conditional = "<endif>"
qstrs[ident] = (len(qstrs), ident, qstr)
# process the qstrs, printing out the generated C header file
print('// This file was automatically generated by makeqstrdata.py')
print('')
for order, ident, qstr, conditional in sorted(qstrs.values(), key=lambda x: x[0]):
for order, ident, qstr in sorted(qstrs.values(), key=lambda x: x[0]):
qhash = compute_hash(qstr)
qlen = len(qstr)
if conditional:
print(conditional)
print('Q({}, (const byte*)"\\x{:02x}\\x{:02x}\\x{:02x}\\x{:02x}" "{}")'.format(ident, qhash & 0xff, (qhash >> 8) & 0xff, qlen & 0xff, (qlen >> 8) & 0xff, qstr))
if conditional:
print('#endif')
return True

Wyświetl plik

@ -104,9 +104,10 @@ $(PY_BUILD)/py-version.h: FORCE
# Adding an order only dependency on $(PY_BUILD) causes $(PY_BUILD) to get
# created before we run the script to generate the .h
$(PY_BUILD)/qstrdefs.generated.h: | $(PY_BUILD)/
$(PY_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(PY_SRC)/makeqstrdata.py
$(PY_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(PY_SRC)/makeqstrdata.py mpconfigport.h $(PY_SRC)/mpconfig.h
$(ECHO) "makeqstrdata $(PY_QSTR_DEFS) $(QSTR_DEFS)"
$(Q)$(PYTHON) $(PY_SRC)/makeqstrdata.py $(PY_QSTR_DEFS) $(QSTR_DEFS) > $@
$(CPP) $(CFLAGS) $(PY_QSTR_DEFS) -o $(PY_BUILD)/qstrdefs.preprocessed.h
$(Q)$(PYTHON) $(PY_SRC)/makeqstrdata.py $(PY_BUILD)/qstrdefs.preprocessed.h $(QSTR_DEFS) > $@
# We don't know which source files actually need the generated.h (since
# it is #included from str.h). The compiler generated dependencies will cause

Wyświetl plik

@ -1,6 +1,6 @@
#include "mpconfig.h"
// All the qstr definitions in this file are available as constants.
// That is, they are in ROM and you can reference them simply as MP_QSTR_xxxx.
// TODO make it so we can use #defines here to select only those words that will be used
Q(__build_class__)
Q(__class__)
@ -13,6 +13,7 @@ Q(__module__)
Q(__name__)
Q(__next__)
Q(__qualname__)
Q(__path__)
Q(__repl_print__)
Q(__bool__)

Wyświetl plik

@ -1043,13 +1043,45 @@ mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) {
mp_obj_t mp_import_from(mp_obj_t module, qstr name) {
DEBUG_printf("import from %p %s\n", module, qstr_str(name));
mp_obj_t x = mp_load_attr(module, name);
/* TODO convert AttributeError to ImportError
if (fail) {
(ImportError, "cannot import name %s", qstr_str(name), NULL)
mp_obj_t dest[2];
mp_load_method_maybe(module, name, dest);
if (dest[1] != MP_OBJ_NULL) {
// Hopefully we can't import bound method from an object
import_error:
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "Cannot import name '%s'", qstr_str(name)));
}
*/
return x;
if (dest[0] != MP_OBJ_NULL) {
return dest[0];
}
// See if it's a package, then can try FS import
mp_load_method_maybe(module, MP_QSTR___path__, dest);
if (dest[0] == MP_OBJ_NULL) {
goto import_error;
}
mp_load_method_maybe(module, MP_QSTR___name__, dest);
uint pkg_name_len;
const char *pkg_name = mp_obj_str_get_data(dest[0], &pkg_name_len);
char dot_name[pkg_name_len + 1 + qstr_len(name)];
memcpy(dot_name, pkg_name, pkg_name_len);
dot_name[pkg_name_len] = '.';
memcpy(dot_name + pkg_name_len + 1, qstr_str(name), qstr_len(name));
qstr dot_name_q = qstr_from_strn(dot_name, sizeof(dot_name));
mp_obj_t args[5];
args[0] = MP_OBJ_NEW_QSTR(dot_name_q);
args[1] = mp_const_none; // TODO should be globals
args[2] = mp_const_none; // TODO should be locals
args[3] = mp_const_true; // Pass sentinel "non empty" value to force returning of leaf module
args[4] = 0;
// TODO lookup __import__ and call that instead of going straight to builtin implementation
return mp_builtin___import__(5, args);
}
void mp_import_all(mp_obj_t module) {

Wyświetl plik

@ -101,11 +101,20 @@ void mp_byte_code_print(const byte *ip, int len) {
printf("LOAD_CONST_ID %s", qstr_str(qstr));
break;
case MP_BC_LOAD_CONST_BYTES:
DECODE_QSTR;
printf("LOAD_CONST_BYTES %s", qstr_str(qstr));
break;
case MP_BC_LOAD_CONST_STRING:
DECODE_QSTR;
printf("LOAD_CONST_STRING %s", qstr_str(qstr));
break;
case MP_BC_LOAD_NULL:
printf("LOAD_NULL");
break;
case MP_BC_LOAD_FAST_0:
printf("LOAD_FAST_0");
break;

Wyświetl plik

@ -0,0 +1,6 @@
from pkg import mod
print(mod.foo())
import pkg.mod
print(mod is pkg.mod)