Skip to content

Commit

Permalink
Refactor Python module API to prefer methods over constructors (#26695)
Browse files Browse the repository at this point in the history
Refactors the Python module API to prefer methods over constructors. The
old constructors are still available and still useful in some places,
but for the most part users should prefer the new API.

Old style

```chapel
var interp = new Interpreter();
var mod = new Module(interp, 'mod');
var func = new Function(mod, 'myfunc');
```

New style

```chapel
var interp = new Interpreter();
var mod = interp.importModule('mod');
var func = mod.get('myfunc');
```

This PR also makes a few other changes

- renamed the internal `.get` to `.getPyObject`
- renamed `getAttr`/`setAttr` to `get`/`set`
- renamed `getIdx`/`setIdx` to `get`/`set`
- added support for passing kwargs to `.call`
- made a variety of doc cleanups/reordered code for better clarity


- [x] `st test/library/packages/Python`
- [x] `st test/library/packages/Python` with GASNet

[Reviewed by @lydia-duncan]
  • Loading branch information
jabraham17 authored Feb 12, 2025
2 parents 8bd732c + 9dc61a9 commit 0d1eb5f
Show file tree
Hide file tree
Showing 28 changed files with 449 additions and 208 deletions.
397 changes: 282 additions & 115 deletions modules/packages/Python.chpl

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions test/library/packages/Python/correctness/argPassingTest.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use IO;

proc test_no_args(mod: borrowed Module) {
const funcName = "no_args";
var func = new Function(mod, funcName);
var func = mod.get(funcName);

func(NoneType);
func();
Expand All @@ -21,7 +21,7 @@ proc test_no_args(mod: borrowed Module) {
}
proc test_one_arg(mod: borrowed Module) {
const funcName = "one_arg";
var func = new Function(mod, funcName);
var func = mod.get(funcName);

func(NoneType, 1);
func(2);
Expand All @@ -38,7 +38,7 @@ proc test_one_arg(mod: borrowed Module) {
}
proc test_two_args(mod: borrowed Module) {
const funcName = "two_args";
var func = new Function(mod, funcName);
var func = mod.get(funcName);

func(NoneType, 1, 2);
func("hello", "world");
Expand All @@ -51,13 +51,13 @@ proc test_two_args(mod: borrowed Module) {
}
proc test_three_args(mod: borrowed Module) {
const funcName = "three_args";
var func = new Function(mod, funcName);
var func = mod.get(funcName);

func(NoneType, 1, 2, 3);
}
proc test_varargs(mod: borrowed Module) {
const funcName = "varargs";
var func = new Function(mod, funcName);
var func = mod.get(funcName);

func(NoneType);
func(1);
Expand All @@ -70,7 +70,7 @@ proc test_varargs(mod: borrowed Module) {
}
proc test_one_arg_with_default(mod: borrowed Module) {
const funcName = "one_arg_with_default";
var func = new Function(mod, funcName);
var func = mod.get(funcName);

func(NoneType);
func(NoneType, 7);
Expand All @@ -79,7 +79,7 @@ proc test_one_arg_with_default(mod: borrowed Module) {
}
proc test_three_args_with_default(mod: borrowed Module) {
const funcName = "three_args_with_default";
var func = new Function(mod, funcName);
var func = mod.get(funcName);

func(NoneType, 8);
func(NoneType, 8, 9);
Expand All @@ -89,7 +89,7 @@ proc test_three_args_with_default(mod: borrowed Module) {
}
proc test_three_args_with_default_and_kwargs(mod: borrowed Module) {
const funcName = "three_args_with_default_and_kwargs";
var func = new Function(mod, funcName);
var func = mod.get(funcName);

func(NoneType, 8);
func(NoneType, 8, 9);
Expand All @@ -99,7 +99,7 @@ proc test_three_args_with_default_and_kwargs(mod: borrowed Module) {
}
proc test_varargs_and_kwargs(mod: borrowed Module) {
const funcName = "varargs_and_kwargs";
var func = new Function(mod, funcName);
var func = mod.get(funcName);

func(NoneType);
func(NoneType, 1);
Expand All @@ -115,7 +115,7 @@ proc main() {
var interp = new Interpreter();

var modName = Reflection.getModuleName();
var m = new Module(interp, modName);
var m = interp.importModule(modName);

test_no_args(m);
test_one_arg(m);
Expand Down
6 changes: 3 additions & 3 deletions test/library/packages/Python/correctness/arrays/gradient.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ def grad(arr):

proc main() {
var interp = new Interpreter();
var mod = new Module(interp, '__empty__', code);
var gradModifyArg = new Function(mod, 'gradModifyArg');
var grad = new Function(mod, 'grad');
var mod = interp.importModule('__empty__', code);
var gradModifyArg = mod.get('gradModifyArg');
var grad = mod.get('grad');

var arr = [1, 2, 4, 7, 11, 16];
var pyArr = new Array(interp, arr);
Expand Down
12 changes: 6 additions & 6 deletions test/library/packages/Python/correctness/arrays/myArray.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@ proc testArray(type t, const testArr) {

var pyArr = new Array(interp, arr);
writeln("python: ", pyArr);
pyArr.setItem(0, 17:t);
writeln("at 2: ", pyArr.getItem(2));
writeln("at -1: ", pyArr.getItem(-1));
pyArr.setItem(-2, 42:t);
pyArr.set(0, 17:t);
writeln("at 2: ", pyArr.get(2));
writeln("at -1: ", pyArr.get(-1));
pyArr.set(-2, 42:t);
writeln("size: ", pyArr.size);
writeln("chapel: ", arr);
IO.stdout.flush();

writeln("from python");
IO.stdout.flush();
var pyCode = new Module(interp, '__empty__', pythonCode);
var func = new Function(pyCode, 'loop');
var pyCode = interp.importModule('__empty__', pythonCode);
var func = pyCode.get('loop');
func(pyArr);
IO.stdout.flush();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ proc main() {
var interp = new Interpreter();

var pyArr = new Array(interp, arr);
var pyCode = new Module(interp, '__empty__', pythonCode);
var func = new Function(pyCode, 'returnSelf');
var pyCode = interp.importModule('__empty__', pythonCode);
var func = pyCode.get('returnSelf');
var newArr = func(owned Array, pyArr);
writeln("from chapel: ", newArr);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
$CHPL_HOME/modules/packages/Python.chpl:nnnn: In method 'callInternal':
$CHPL_HOME/modules/packages/Python.chpl:nnnn: error: Cannot create an Array from an existing PyObject
$CHPL_HOME/modules/packages/Python.chpl:nnnn: called as Value.callInternal(type retType = owned Array(nothing), pyArg: c_ptr(PyObject), kwargs: nothing) from method 'this'
$CHPL_HOME/modules/packages/Python.chpl:nnnn: called as Value.callInternal(type retType = owned Array(nothing), pyFunc: c_ptr(PyObject), pyArg: c_ptr(PyObject), kwargs: nothing) from method 'this'
myArrayReturnArray.chpl:16: called as Value.this(type retType = owned Array(nothing), args(0): owned Array(int(64)))
20 changes: 10 additions & 10 deletions test/library/packages/Python/correctness/arrays/myList.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,28 @@ proc main() {

var interp = new Interpreter();

var pyCodeModule = new Module(interp, '__empty__', pyCode);
var getListFunc = new Function(pyCodeModule, 'getList');
var pyCodeModule = interp.importModule('__empty__', pyCode);
var getListFunc = pyCodeModule.get('getList');

var lst = getListFunc(owned PyList);
writeln("lst ", lst);
writeln("size ", lst.size);
writeln("lst[0] ", lst.getItem(int, 0));
writeln("lst[1] ", lst.getItem(int, 1));
writeln("lst[2] ", lst.getItem(string, 2));
writeln("lst[lst.size-1] ", lst.getItem(int, lst.size-1));
writeln("lst[-3] ", lst.getItem(owned Value, -3));
writeln("lst[-3] ", lst.getItem(-3));
writeln("lst[0] ", lst.get(int, 0));
writeln("lst[1] ", lst.get(int, 1));
writeln("lst[2] ", lst.get(string, 2));
writeln("lst[lst.size-1] ", lst.get(int, lst.size-1));
writeln("lst[-3] ", lst.get(owned Value, -3));
writeln("lst[-3] ", lst.get(-3));

try {
write("lst[lst.size] ");
writeln(lst.getItem(int, lst.size));
writeln(lst.get(int, lst.size));
} catch e: PythonException {
writeln("Caught exception: ", e);
} catch e{
writeln("Caught unknown exception: ", e);
}

lst.setItem(0, 100);
lst.set(0, 100);
writeln("lst ", lst);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use Python;
proc main() {

var interp = new Interpreter();
var m = new Module(interp, 'nestedArrays');
var strNested = new Function(m, "strNested");
var m = interp.importModule('nestedArrays');
var strNested = m.get("strNested");

{
var input = [[1, 2], [3, 4]];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ def numpyAssign(arr):
proc main() {

var interp = new Interpreter();
var m = new Module(interp, '__empty__', code);
var saxpy = new Function(m, 'saxpy');
var numpyAssign = new Function(m, 'numpyAssign');
var m = interp.importModule('__empty__', code);
var saxpy = m.get('saxpy');
var numpyAssign = m.get('numpyAssign');

{
var x = [1, 2, 3];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use Python;

proc main() {
var interp = new Interpreter();
var mod = new Module(interp, "usePythonArray");
var doit = new Function(mod, 'doit');
var mod = interp.importModule("usePythonArray");
var doit = mod.get('doit');


var pyRes = doit(owned PyArray(int), 10, 11, 12, 13);
Expand Down
12 changes: 6 additions & 6 deletions test/library/packages/Python/correctness/basicTypes.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ proc roundTripClass(clsType: borrowed) {
var obj = clsType(value);
if print then writeln(" obj: ", obj);

res = obj.getAttr(t, "value");
res = obj.get(t, "value");
if print then writeln(" obj.value: ", res);
assert(res == value);

obj.setAttr("value", other);
obj.set("value", other);
res = obj.call(t, "getter");
if print then writeln(" obj.getter(): ", res);
assert(res == other);

obj.call("setter", value);
res = obj.getAttr(t, "value");
res = obj.get(t, "value");
if print then writeln(" obj.value: ", res);
assert(res == value);

Expand Down Expand Up @@ -83,14 +83,14 @@ proc main() {
var interp = new Interpreter();

var modName = Reflection.getModuleName();
var m = new Module(interp, modName);
var m = interp.importModule(modName);
if print then writeln("module: ", m);

var func = new Function(m, "round_trip");
var func = m.get("round_trip");
if print then writeln("func: ", func);
roundTripFunction(func);

var clsType = new Class(m, "RoundTrip");
var clsType = m.get("RoundTrip");
if print then writeln("class: ", clsType);
roundTripClass(clsType);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ proc parallelPythonApplySubInterp(interp: borrowed, type t, arr, l) {
proc init(parent: borrowed, s) {
init this;
interp = try! (new SubInterpreter(parent));
func = try! (new Function(interp!, s));
func = try! (interp!.compileLambda(s));
}
inline proc this(type t, a) throws {
return func!(t, a);
Expand Down
10 changes: 5 additions & 5 deletions test/library/packages/Python/correctness/customType.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ record myRec {
}

class myRecConverter: TypeConverter {
var pyClsType: borrowed Class;
var pyClsType: borrowed Value;
override proc handlesType(type T): bool {
return T == myRec;
}
Expand All @@ -22,7 +22,7 @@ class myRecConverter: TypeConverter {
type T, obj: Python.CPythonInterface.PyObjectPtr): T throws {
if T != myRec then halt("Expected myRec");
var cls = new Value(interpreter, obj);
var res = new myRec(cls.getAttr(int, "x"), cls.getAttr(string, "y"));
var res = new myRec(cls.get(int, "x"), cls.get(string, "y"));
return res;
}
}
Expand All @@ -31,13 +31,13 @@ proc main() {
var interp = new Interpreter();

var modName = Reflection.getModuleName();
var m = new Module(interp, modName);
var m = interp.importModule(modName);

var pyClsType = new Class(m, "MyRec");
var pyClsType = m.get("MyRec");
interp.registerConverter(new myRecConverter(pyClsType));

IO.stdout.flush();
var printAndReturn = new Function(m, "printAndReturn");
var printAndReturn = m.get("printAndReturn");
var fromPy = printAndReturn(myRec, new myRec(42, "hello"));
writeln(fromPy);
}
8 changes: 4 additions & 4 deletions test/library/packages/Python/correctness/defaultType.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ def pass_through(x):
""";

var interp = new Interpreter();
var mod = new Module(interp, '__empty__', code);
var do_nothing = new Function(mod, 'do_nothing');
var get_int = new Function(mod, 'get_int');
var pass_through = new Function(mod, 'pass_through');
var mod = interp.importModule('__empty__', code);
var do_nothing = mod.get('do_nothing');
var get_int = mod.get('get_int');
var pass_through = mod.get('pass_through');

{
writeln("do_nothing()");
Expand Down
46 changes: 46 additions & 0 deletions test/library/packages/Python/correctness/directCalls.chpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

use Python;

var code = """
class C:
def __init__(self):
self.x = 17
def foo(self):
return self.x
def bar():
return 18
""";

var interp = new Interpreter();
var mod = interp.importModule('__empty__', code);

{
var res1 = mod.call('bar');

var bar = mod.get('bar');
var res2 = bar();

var res3 = mod.get('bar')();

// these are all the same
writeln("mod.call('bar'): ", res1);
writeln("bar(): ", res2);
writeln("mod.get('bar')(): ", res3);
}

{
var C = mod.get('C');
var c = C();
var res1 = c.call('foo');

var foo = c.get('foo');
var res2 = foo();

var res3 = mod.get('C')().call('foo');

// these are all the same
writeln("c.call('foo'): ", res1);
writeln("foo(): ", res2);
writeln("mod.get('C')().call('foo'): ", res3);
}
6 changes: 6 additions & 0 deletions test/library/packages/Python/correctness/directCalls.good
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
mod.call('bar'): 18
bar(): 18
mod.get('bar')(): 18
c.call('foo'): 17
foo(): 17
mod.get('C')().call('foo'): 17
2 changes: 1 addition & 1 deletion test/library/packages/Python/correctness/iteratorTest.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ proc main() {
var interp = new Interpreter();

var modName = Reflection.getModuleName();
var m = new Module(interp, modName);
var m = interp.importModule(modName);

var myiter = new Function(m, "myiter");
test(myiter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use Python;
var interp = new Interpreter();
var modBytes = interp.loadPycFile(pycPath);

var mod = new Module(interp, "mod", modBytes);
var mod = interp.importModule("mod", modBytes);
// get MyClass and my_function
var MyClass = new Class(mod, "MyClass");
var my_function = new Function(mod, "my_function");
var MyClass = mod.get("MyClass");
var my_function = mod.get("my_function");

// run my_function
var v = my_function();
Expand Down
Loading

0 comments on commit 0d1eb5f

Please sign in to comment.