Commit e80012b0 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Support __getattr__ overloading for old style classes

parent 67a8482a
...@@ -155,7 +155,11 @@ static Box* _instanceGetattribute(Box* _inst, Box* _attr, bool raise_on_missing) ...@@ -155,7 +155,11 @@ static Box* _instanceGetattribute(Box* _inst, Box* _attr, bool raise_on_missing)
static const std::string getattr_str("__getattr__"); static const std::string getattr_str("__getattr__");
Box* getattr = classLookup(inst->inst_cls, getattr_str); Box* getattr = classLookup(inst->inst_cls, getattr_str);
RELEASE_ASSERT(getattr == NULL, "unimplemented");
if (getattr) {
getattr = processDescriptor(getattr, inst, inst->inst_cls);
return runtimeCall(getattr, ArgPassSpec(1), _attr, NULL, NULL, NULL, NULL);
}
if (!raise_on_missing) if (!raise_on_missing)
return NULL; return NULL;
......
...@@ -2136,6 +2136,17 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa ...@@ -2136,6 +2136,17 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa
return chosen_cf; return chosen_cf;
} }
static std::string getFunctionName(CLFunction* f) {
if (f->source)
return f->source->getName();
else if (f->versions.size()) {
std::ostringstream oss;
oss << "<function at " << f->versions[0]->code << ">";
return oss.str();
}
return "<unknown function>";
}
static void placeKeyword(const std::vector<AST_expr*>& arg_names, std::vector<bool>& params_filled, static void placeKeyword(const std::vector<AST_expr*>& arg_names, std::vector<bool>& params_filled,
const std::string& kw_name, Box* kw_val, Box*& oarg1, Box*& oarg2, Box*& oarg3, Box** oargs, const std::string& kw_name, Box* kw_val, Box*& oarg1, Box*& oarg2, Box*& oarg3, Box** oargs,
BoxedDict* okwargs) { BoxedDict* okwargs) {
...@@ -2316,17 +2327,9 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -2316,17 +2327,9 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
Box* ovarargs = new BoxedTuple(unused_positional); Box* ovarargs = new BoxedTuple(unused_positional);
getArg(varargs_idx, oarg1, oarg2, oarg3, oargs) = ovarargs; getArg(varargs_idx, oarg1, oarg2, oarg3, oargs) = ovarargs;
} else if (unused_positional.size()) { } else if (unused_positional.size()) {
std::string name = "<unknown function>"; raiseExcHelper(TypeError, "%s() takes at most %d argument%s (%d given)", getFunctionName(f).c_str(),
if (f->source) f->num_args, (f->num_args == 1 ? "" : "s"),
name = f->source->getName(); argspec.num_args + argspec.num_keywords + varargs.size());
else if (f->versions.size()) {
std::ostringstream oss;
oss << "<function at " << f->versions[0]->code << ">";
name = oss.str();
}
raiseExcHelper(TypeError, "%s() takes at most %d argument%s (%d given)", name.c_str(), f->num_args,
(f->num_args == 1 ? "" : "s"), argspec.num_args + argspec.num_keywords + varargs.size());
} }
//// ////
...@@ -2341,7 +2344,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -2341,7 +2344,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
const std::vector<AST_expr*>* arg_names = f->source ? f->source->arg_names.args : NULL; const std::vector<AST_expr*>* arg_names = f->source ? f->source->arg_names.args : NULL;
if (arg_names == nullptr && argspec.num_keywords && !f->takes_kwargs) { if (arg_names == nullptr && argspec.num_keywords && !f->takes_kwargs) {
raiseExcHelper(TypeError, "<function @%p>() doesn't take keyword arguments", f->versions[0]->code); raiseExcHelper(TypeError, "%s() doesn't take keyword arguments", getFunctionName(f).c_str());
} }
if (argspec.num_keywords) if (argspec.num_keywords)
...@@ -2374,7 +2377,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -2374,7 +2377,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
for (auto& p : d_kwargs->d) { for (auto& p : d_kwargs->d) {
if (p.first->cls != str_cls) if (p.first->cls != str_cls)
raiseExcHelper(TypeError, "<function>() keywords must be strings"); raiseExcHelper(TypeError, "%s() keywords must be strings", getFunctionName(f).c_str());
BoxedString* s = static_cast<BoxedString*>(p.first); BoxedString* s = static_cast<BoxedString*>(p.first);
...@@ -2385,8 +2388,8 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -2385,8 +2388,8 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
Box*& v = okwargs->d[p.first]; Box*& v = okwargs->d[p.first];
if (v) { if (v) {
raiseExcHelper(TypeError, "<function>() got multiple values for keyword argument '%s'", raiseExcHelper(TypeError, "%s() got multiple values for keyword argument '%s'",
s->s.c_str()); getFunctionName(f).c_str(), s->s.c_str());
} }
v = p.second; v = p.second;
} }
...@@ -2399,7 +2402,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -2399,7 +2402,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
if (params_filled[i]) if (params_filled[i])
continue; continue;
// TODO not right error message // TODO not right error message
raiseExcHelper(TypeError, "<function>() did not get a value for positional argument %d", i); raiseExcHelper(TypeError, "%s() did not get a value for positional argument %d", getFunctionName(f).c_str(), i);
} }
RewriterVar* r_defaults_array = NULL; RewriterVar* r_defaults_array = NULL;
......
...@@ -111,3 +111,13 @@ print issubclass(OldStyleClass, object) ...@@ -111,3 +111,13 @@ print issubclass(OldStyleClass, object)
print isinstance(OldStyleClass(), OldStyleClass) print isinstance(OldStyleClass(), OldStyleClass)
print issubclass(OldStyleClass, OldStyleClass) print issubclass(OldStyleClass, OldStyleClass)
class GetattrTest:
def __getattr__(self, attr):
print "getattr", attr
return 1
g = GetattrTest()
g.b = 2
print g.a
print g.b
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