Commit 58e151e5 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Make 'from a import b' throw ImportErrors

Before was throwing AttributeError, since we were just translating it to:
import a
b = a.b

Now there's a special importFrom runtime function that does essentially
the same thing, but throws the proper exception.
parent 5312cb01
......@@ -1453,7 +1453,11 @@ private:
const std::string& name = alias->name;
const std::string& asname = alias->asname.size() ? alias->asname : alias->name;
CompilerVariable* v = module->getattr(emitter, getEmptyOpInfo(exc_info), &name, false);
// TODO add patchpoints to this?
llvm::Value* r = emitter.createCall2(exc_info, g.funcs.importFrom, module->getValue(),
embedConstantPtr(&name, g.llvm_str_type_ptr)).getInstruction();
CompilerVariable* v = new ConcreteCompilerVariable(UNKNOWN, r, true);
_doSet(asname, v, exc_info);
v->decvref(emitter);
}
......
......@@ -182,6 +182,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(getclsattr);
GET(unaryop);
GET(import);
GET(importFrom);
GET(repr);
GET(isinstance);
......
......@@ -34,7 +34,7 @@ struct GlobalFuncs {
*boxInstanceMethod, *boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice,
*createUserClass, *createClosure;
llvm::Value* getattr, *setattr, *print, *nonzero, *binop, *compare, *augbinop, *unboxedLen, *getitem, *getclsattr,
*getGlobal, *setitem, *delitem, *unaryop, *import, *repr, *isinstance;
*getGlobal, *setitem, *delitem, *unaryop, *import, *importFrom, *repr, *isinstance;
llvm::Value* checkUnpackingLength, *raiseAttributeError, *raiseAttributeErrorStr, *raiseNotIterableError,
*assertNameDefined, *assertFail;
......
......@@ -74,6 +74,7 @@ void force() {
FORCE(delitem);
FORCE(unaryop);
FORCE(import);
FORCE(importFrom);
FORCE(repr);
FORCE(isinstance);
......
......@@ -2959,4 +2959,16 @@ extern "C" Box* import(const std::string* name) {
raiseExcHelper(ImportError, "No module named %s", name->c_str());
}
extern "C" Box* importFrom(Box* _m, const std::string* name) {
assert(_m->cls == module_cls);
BoxedModule* m = static_cast<BoxedModule*>(_m);
Box* r = m->getattr(*name, NULL, NULL);
if (r)
return r;
raiseExcHelper(ImportError, "cannot import name %s", name->c_str());
}
}
......@@ -41,6 +41,7 @@ extern "C" const std::string* getNameOfClass(BoxedClass* cls);
// TODO sort this
extern "C" void my_assert(bool b);
extern "C" Box* importFrom(Box* obj, const std::string* attr);
extern "C" Box* getattr(Box* obj, const char* attr);
extern "C" void setattr(Box* obj, const char* attr, Box* attr_val);
extern "C" bool nonzero(Box* obj);
......
# expected: fail
# - currently throws an AttributeError if we imported the module but the name didn't exist
try:
import non_existent_module
assert 0, "shouldn't get here"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment