# HG changeset patch # User Mike Miller # Date 1472000957 25200 # Node ID d41fc23d4b9ffe9e3fdd62af2dfeb781c23e04b5 # Parent ebd83497ebda21adbf538356210dfb521b829cd1 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. diff -r ebd83497ebda -r d41fc23d4b9f @pyobject/pyobject.m --- 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)) diff -r ebd83497ebda -r d41fc23d4b9f __py_struct_from_dict__.cc --- 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\