changeset 358:d41fc23d4b9f

pyobject.isa: New overload method to handle Python types (fixes issue #49) * __py_struct_from_dict__.cc (F__py_isinstance__): New function to check whether a pyobject is an instance of a named type. * @pyobject/pyobject.m (pyobject.isa): New method. Add %!tests.
author Mike Miller <mtmiller@octave.org>
date Tue, 23 Aug 2016 18:09:17 -0700
parents ebd83497ebda
children 4c2b748eaea0
files @pyobject/pyobject.m __py_struct_from_dict__.cc
diffstat 2 files changed, 81 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/@pyobject/pyobject.m	Tue Aug 23 17:37:08 2016 -0700
+++ b/@pyobject/pyobject.m	Tue Aug 23 18:09:17 2016 -0700
@@ -142,6 +142,16 @@
       y = __py_int64_scalar_value__ (x);
     endfunction
 
+    function y = isa (x, typestr)
+      assert (nargin == 2);
+      assert (ischar (typestr));
+      if ((numel (typestr) > 3) && (typestr(1:3) == "py."))
+        y = __py_isinstance__ (x, typestr);
+      else
+        y = builtin ("isa", x, typestr);
+      endif
+    endfunction
+
     function y = struct (x)
       y = __py_struct_from_dict__ (x);
     endfunction
@@ -348,6 +358,20 @@
 %!error double (pyobject ())
 %!error double (pyeval ("[1, 2, 3]"))
 
+## Test class type check method pyobject.isa
+%!assert (isa (pyobject (), "handle"))
+%!assert (isa (pyobject (), "pyobject"))
+%!assert (! isa (pyobject (), "py.None"))
+%!assert (isa (pyobject (0), "handle"))
+%!assert (isa (pyobject (0), "pyobject"))
+%!assert (isa (pyobject (0), "py.float"))
+%!assert (isa (pyobject (int32 (0)), "py.int"))
+%!assert (isa (pyobject (true), "py.bool"))
+%!assert (isa (pyobject ("a string"), "py.str"))
+%!assert (isa (pyobject (struct ()), "py.dict"))
+%!assert (isa (pyobject (cell ()), "py.tuple"))
+%!assert (isa (pyobject ([1, 2, 3, 4]), "py.array.array"))
+
 ## Test conversion method pyobject.int64
 %!assert (int64 (pyobject (int8 (0))), int64 (0))
 %!assert (int64 (pyobject (int64 (42))), int64 (42))
--- a/__py_struct_from_dict__.cc	Tue Aug 23 17:37:08 2016 -0700
+++ b/__py_struct_from_dict__.cc	Tue Aug 23 18:09:17 2016 -0700
@@ -31,6 +31,7 @@
 #include "arrayobjectdefs.h"
 #include "exceptions.h"
 #include "oct-py-types.h"
+#include "oct-py-util.h"
 #include "octave_to_python.h"
 
 DEFUN_DLD (__py_int64_scalar_value__, args, nargout,
@@ -77,6 +78,62 @@
   return retval;
 }
 
+DEFUN_DLD (__py_isinstance__, args, nargout,
+           "-*- texinfo -*-\n\
+@deftypefn  {} {} __py_isinstance__ (@var{x})\n\
+Check whether the Python object @var{obj} is an instance of a Python type\n\
+specified by the string @var{type}.\n\
+\n\
+This is a private internal function not intended for direct use.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  int nargin = args.length ();
+  if (nargin != 2)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  if (! (args(0).is_object () && args(0).class_name () == "pyobject"))
+    error ("pyobject.isa: OBJ must be a Python object");
+
+  if (! args(1).is_string ())
+    error ("pyobject.isa: TYPE must be a string naming a Python type (py.*)");
+
+  std::string typestr = args(1).string_value ();
+  if (! ((typestr.size () > 3) && (typestr.compare (0, 3, "py.") == 0)))
+    error ("pyobject.isa: TYPE must be a string naming a Python type (py.*)");
+
+  typestr = typestr.substr (3);
+
+  Py_Initialize ();
+
+  try
+    {
+      // FIXME: PyObject *obj = look up stored pyobject reference (args(0));
+      boost::python::object arg;
+      pytave::octvalue_to_pyobj (arg, args(0));
+      PyObject *obj = arg.ptr ();
+
+      PyObject *type = pytave::py_find_type (typestr);
+      retval(0) = pytave::py_isinstance (obj, type);
+      Py_XDECREF (type);
+    }
+  catch (pytave::object_convert_exception const &)
+    {
+      error ("pyobject.isa: error in return value type conversion");
+    }
+  catch (boost::python::error_already_set const &)
+    {
+      std::string message = pytave::fetch_exception_message ();
+      error ("pyobject.isa: %s", message.c_str ());
+    }
+
+  return retval;
+}
+
 DEFUN_DLD (__py_struct_from_dict__, args, nargout,
            "-*- texinfo -*-\n\
 @deftypefn  {} {} __py_struct_from_dict__ (@var{dict})\n\