diff --git a/pythran/tests/test_normalize_methods.py b/pythran/tests/test_normalize_methods.py index 9af98d7b7..241aa2a97 100644 --- a/pythran/tests/test_normalize_methods.py +++ b/pythran/tests/test_normalize_methods.py @@ -1,3 +1,4 @@ +import pythran from pythran.tests import TestEnv import numpy @@ -124,6 +125,16 @@ def test_dispatch_update(self): {1}, {1:1}, dispatch_update=[Set[int], Dict[int,int]]) + def test_invalid_method_call(self): + code = ''' +def np_asarray7(sRate=44100): + import numpy as np + x = np.expand_dims(np.ones(sRate),-1) + x = np.maximum(np.minimum(x,.5),-.5).asarray() # asarray is not a method + return x''' + with self.assertRaises(pythran.syntax.PythranSyntaxError): + self.run_test(code, 30, np_asarray7=[int]) + def test_capture_bound_method(self): code = ''' def capture_bound_method(fname, r): diff --git a/pythran/transformations/normalize_method_calls.py b/pythran/transformations/normalize_method_calls.py index 5e721ad0b..4af1e47d1 100644 --- a/pythran/transformations/normalize_method_calls.py +++ b/pythran/transformations/normalize_method_calls.py @@ -27,7 +27,8 @@ class NormalizeMethodCalls(Transformation): def __init__(self): Transformation.__init__(self, Globals, Ancestors) - self.imports = {'builtins': 'builtins'} + self.imports = {'builtins': 'builtins', + mangle('__dispatch__'): '__dispatch__'} self.to_import = set() def visit_Module(self, node): @@ -156,6 +157,7 @@ def visit_Attribute(self, node): self.update = True mod = methods[node.attr][0] self.to_import.add(mangle(mod[0])) + self.to_import.add(mangle('functools')) func = self.attr_to_func(node) z = ast.Call( ast.Attribute( @@ -250,7 +252,16 @@ def visit_Call(self, node): self.to_import.add(mangle(mod[0])) node.func = self.attr_to_func(node.func) # else methods have been called using function syntax - if node.func.attr in methods or node.func.attr in functions: + + ismethod = node.func.attr in methods + isfunction = node.func.attr in functions + if ismethod or isfunction: # i.e. if it's callable + if not ismethod and self.baseobj(node.func.value): + raise PythranSyntaxError( + "'{}' called as a method while it's a function" + .format(node.func.attr), + node) + # Now, methods and function have both function syntax def rec(path, cur_module): """