From 2e997555713fd0aa9d320f1865af3103dcbd14b4 Mon Sep 17 00:00:00 2001 From: Chris Gorman Date: Wed, 11 May 2022 10:33:34 -0400 Subject: [PATCH 1/5] Make PyEval_CallObjectWithKeywords and PyObject_Call conditional - make PyEval_CallObjectWithKeywords called if python is less than 3.8 and for everything else use PyObject_Call. - Fixes issue #91 --- src/oct-py-eval.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/oct-py-eval.cc b/src/oct-py-eval.cc index b8ff922..bab5c50 100644 --- a/src/oct-py-eval.cc +++ b/src/oct-py-eval.cc @@ -84,7 +84,12 @@ namespace pythonic PyObject * py_call_function (PyObject *callable, PyObject *args, PyObject *kwargs) { +#if PY_VERSION_HEX <= 0x03080000 python_object retval = PyEval_CallObjectWithKeywords (callable, args, kwargs); +#else + python_object retval = PyObject_Call (callable, args, kwargs); +#endif + if (! retval) error_python_exception (); -- GitLab From 981fb598316505517c7f13da423c6134e85b71cd Mon Sep 17 00:00:00 2001 From: Chris Gorman Date: Wed, 11 May 2022 11:48:30 -0400 Subject: [PATCH 2/5] Change Callable and Sequence calls to abc.Callable and abc.Sequence - in python 3.10 the calling of collections.abc.Callable and collections.abc.Sequence using the collections module alone is deprecated, (it requires collections.abc.) This change was deprecated in python 3.3, so we should have good coverage with this change. - changed all instances of collections.Callable and collections.sequence to collections.abc.callable and collections.abc.sequence respectively. - this is needed in python3.10 becaues of commit c47c78b878ff617164b2b94ff711a6103e781753 bpo-37324: Remove ABC aliases from collections (GH-23754) --- inst/@py/subsref.m | 2 +- inst/@pyobject/subsasgn.m | 2 +- inst/@pyobject/subsref.m | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/inst/@py/subsref.m b/inst/@py/subsref.m index 9316b67..9312f67 100644 --- a/inst/@py/subsref.m +++ b/inst/@py/subsref.m @@ -61,7 +61,7 @@ function varargout = subsref (x, idx) ## is a Python callable, then call it with no arguments to be compatible ## with how Octave functions are evaluated. if (idx(end).type == ".") - if (isa (y, "py.collections.Callable")) + if (isa (y, "py.collections.abc.Callable")) y = pycall (y); endif endif diff --git a/inst/@pyobject/subsasgn.m b/inst/@pyobject/subsasgn.m index 7bc5e85..70ceeb6 100644 --- a/inst/@pyobject/subsasgn.m +++ b/inst/@pyobject/subsasgn.m @@ -51,7 +51,7 @@ function r = subsasgn(x, idx, rhs) ## XXX: doesn't support slices or anything like that yet ## Subtract one from index: do this for lists, numpy arrays, etc - x_is_sequence = any (isa (x, {"py.collections.Sequence", ... + x_is_sequence = any (isa (x, {"py.collections.abc.Sequence", ... "py.numpy.ndarray"})); for i = 1:length (idx.subs) j = idx.subs{i}; diff --git a/inst/@pyobject/subsref.m b/inst/@pyobject/subsref.m index 5b5ae11..ee19609 100644 --- a/inst/@pyobject/subsref.m +++ b/inst/@pyobject/subsref.m @@ -43,8 +43,8 @@ function varargout = subsref (x, idx) case "()" ## Determine the types and protocols that we are able to index into - x_is_callable = __py_isinstance__ (x, "py.collections.Callable"); - x_is_sequence = __py_isinstance__ (x, "py.collections.Sequence") ... + x_is_callable = __py_isinstance__ (x, "py.collections.abc.Callable"); + x_is_sequence = __py_isinstance__ (x, "py.collections.abc.Sequence") ... | __py_isinstance__ (x, "py.array.array") ... | __py_isinstance__ (x, "py.numpy.ndarray"); @@ -61,7 +61,7 @@ function varargout = subsref (x, idx) case "{}" ## Determine the types and protocols that we are able to index into x_is_mapping = __py_isinstance__ (x, "py.collections.Mapping"); - x_is_sequence = __py_isinstance__ (x, "py.collections.Sequence") ... + x_is_sequence = __py_isinstance__ (x, "py.collections.abc.Sequence") ... | __py_isinstance__ (x, "py.array.array") ... | __py_isinstance__ (x, "py.numpy.ndarray"); -- GitLab From d9ef0ae38f4ede58cd506d2f8bc1758aa2f4a2fd Mon Sep 17 00:00:00 2001 From: Chris Gorman Date: Thu, 12 May 2022 14:33:50 -0400 Subject: [PATCH 3/5] Make conditional for using collections.abc or collections - collections.abc was introduced in python3.3 and is the prefered way of accessing Sequence or Callable in python3. Accessing Callable or Sequence types from python3 has been available through collections until python3.10. From 3.10 onward they must be accessed via collections.abc - create a conditional to execute collections on python2 and collections.abc on python3 for calls to Callable and Sequence - part 1 of 2, there is a Callable in inst/@py/subsref.m that I have hacked at fixing, but am not happy with the look of. Have passed it on to @mtmiller to see if he can offer a suggestion. - partial fix for issue #95. --- inst/@pyobject/subsasgn.m | 9 +++++++-- inst/@pyobject/subsref.m | 27 ++++++++++++++++++++------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/inst/@pyobject/subsasgn.m b/inst/@pyobject/subsasgn.m index 70ceeb6..908b850 100644 --- a/inst/@pyobject/subsasgn.m +++ b/inst/@pyobject/subsasgn.m @@ -51,8 +51,13 @@ function r = subsasgn(x, idx, rhs) ## XXX: doesn't support slices or anything like that yet ## Subtract one from index: do this for lists, numpy arrays, etc - x_is_sequence = any (isa (x, {"py.collections.abc.Sequence", ... - "py.numpy.ndarray"})); + if (double (py.sys.hexversion) > 34018032) + x_is_sequence = any (isa (x, {"py.collections.abc.Sequence", ... + "py.numpy.ndarray"})); + else + x_is_sequence = any (isa (x, {"py.collections.Sequence", ... + "py.numpy.ndarray"})); + endif for i = 1:length (idx.subs) j = idx.subs{i}; if (x_is_sequence && isindex (j) && isnumeric (j)) diff --git a/inst/@pyobject/subsref.m b/inst/@pyobject/subsref.m index ee19609..6ea2902 100644 --- a/inst/@pyobject/subsref.m +++ b/inst/@pyobject/subsref.m @@ -42,11 +42,18 @@ function varargout = subsref (x, idx) r = pycall ("getattr", x, t.subs); case "()" - ## Determine the types and protocols that we are able to index into - x_is_callable = __py_isinstance__ (x, "py.collections.abc.Callable"); - x_is_sequence = __py_isinstance__ (x, "py.collections.abc.Sequence") ... - | __py_isinstance__ (x, "py.array.array") ... - | __py_isinstance__ (x, "py.numpy.ndarray"); + if (double (py.sys.hexversion) > 34018032) + ## Determine the types and protocols that we are able to index into + x_is_callable = __py_isinstance__ (x, "py.collections.abc.Callable"); + x_is_sequence = __py_isinstance__ (x, "py.collections.abc.Sequence") ... + | __py_isinstance__ (x, "py.array.array") ... + | __py_isinstance__ (x, "py.numpy.ndarray"); + else + x_is_callable = __py_isinstance__ (x, "py.collections.Callable"); + x_is_sequence = __py_isinstance__ (x, "py.collections.Sequence") ... + | __py_isinstance__ (x, "py.array.array") ... + | __py_isinstance__ (x, "py.numpy.ndarray"); + endif if (! (x_is_callable || x_is_sequence)) error ("subsref: cannot index Python object, not sequence or callable"); @@ -59,11 +66,17 @@ function varargout = subsref (x, idx) r = pycall (x, t.subs{:}); case "{}" - ## Determine the types and protocols that we are able to index into x_is_mapping = __py_isinstance__ (x, "py.collections.Mapping"); - x_is_sequence = __py_isinstance__ (x, "py.collections.abc.Sequence") ... + if (double (py.sys.hexversion) > 34018032) + ## Determine the types and protocols that we are able to index into + x_is_sequence = __py_isinstance__ (x, "py.collections.abc.Sequence") ... | __py_isinstance__ (x, "py.array.array") ... | __py_isinstance__ (x, "py.numpy.ndarray"); + else + x_is_sequence = __py_isinstance__ (x, "py.collections.Sequence") ... + | __py_isinstance__ (x, "py.array.array") ... + | __py_isinstance__ (x, "py.numpy.ndarray"); + endif if (! (x_is_mapping || x_is_sequence)) error ("subsref: cannot index Python object, not sequence or mapping"); -- GitLab From 202eda96987b10ac94a1ceb6a9185ff689dd659d Mon Sep 17 00:00:00 2001 From: Chris Gorman Date: Fri, 13 May 2022 20:18:43 -0400 Subject: [PATCH 4/5] make call to collections or collections.abc depending on python version - part 2 of 2 (Should really be 4 of 4 as there are more than two commits that address issue #95.) - allong with commits d9ef0ae38f4ede58cd506d2f8bc1758aa2f4a2fd, 981fb598316505517c7f13da423c6134e85b71cd and 981fb598316505517c7f13da423c6134e85b71cd fixes issue #95 --- inst/@py/subsref.m | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/inst/@py/subsref.m b/inst/@py/subsref.m index 9312f67..d79ed1c 100644 --- a/inst/@py/subsref.m +++ b/inst/@py/subsref.m @@ -60,9 +60,16 @@ function varargout = subsref (x, idx) ## If the *last* indexing operation is ".name", and the object returned ## is a Python callable, then call it with no arguments to be compatible ## with how Octave functions are evaluated. + pyexec("import sys"); if (idx(end).type == ".") - if (isa (y, "py.collections.abc.Callable")) - y = pycall (y); + if (double (pyeval("sys.hexversion")) > 34018032) + if (isa (y, "py.collections.abc.Callable")) + y = pycall (y); + endif + else + if (isa (y, "py.collections.Callable")) + y = pycall (y); + endif endif endif -- GitLab From 760d124f501b4721503386a76f6da0ad15837c23 Mon Sep 17 00:00:00 2001 From: Chris Gorman Date: Fri, 13 May 2022 21:45:09 -0400 Subject: [PATCH 5/5] Changed to use version for python3.3 which introduced abc - use version number 50528496 (python 3.3.0) instead of 34018032 (python 2.7.18) --- inst/@py/subsref.m | 3 ++- inst/@pyobject/subsasgn.m | 2 +- inst/@pyobject/subsref.m | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/inst/@py/subsref.m b/inst/@py/subsref.m index d79ed1c..9e24a8c 100644 --- a/inst/@py/subsref.m +++ b/inst/@py/subsref.m @@ -62,7 +62,8 @@ function varargout = subsref (x, idx) ## with how Octave functions are evaluated. pyexec("import sys"); if (idx(end).type == ".") - if (double (pyeval("sys.hexversion")) > 34018032) + # use hexversion of python 3.3 which introduced abc + if (double (pyeval("sys.hexversion")) >= 50528496) if (isa (y, "py.collections.abc.Callable")) y = pycall (y); endif diff --git a/inst/@pyobject/subsasgn.m b/inst/@pyobject/subsasgn.m index 908b850..67dde47 100644 --- a/inst/@pyobject/subsasgn.m +++ b/inst/@pyobject/subsasgn.m @@ -51,7 +51,7 @@ function r = subsasgn(x, idx, rhs) ## XXX: doesn't support slices or anything like that yet ## Subtract one from index: do this for lists, numpy arrays, etc - if (double (py.sys.hexversion) > 34018032) + if (double (py.sys.hexversion) >= 50528496) x_is_sequence = any (isa (x, {"py.collections.abc.Sequence", ... "py.numpy.ndarray"})); else diff --git a/inst/@pyobject/subsref.m b/inst/@pyobject/subsref.m index 6ea2902..7da2b99 100644 --- a/inst/@pyobject/subsref.m +++ b/inst/@pyobject/subsref.m @@ -67,7 +67,7 @@ function varargout = subsref (x, idx) case "{}" x_is_mapping = __py_isinstance__ (x, "py.collections.Mapping"); - if (double (py.sys.hexversion) > 34018032) + if (double (py.sys.hexversion) >= 50528496) ## Determine the types and protocols that we are able to index into x_is_sequence = __py_isinstance__ (x, "py.collections.abc.Sequence") ... | __py_isinstance__ (x, "py.array.array") ... -- GitLab