comparison oct-py-types.cc @ 411:3613ffbd52b2

Overhaul implicit conversion of arguments and return values * oct-py-types.cc, oct-py-types.h (pytave::py_implicitly_convert_argument, pytave::py_implicitly_convert_return_value): New functions. * __py_struct_from_dict__.cc, oct-py-eval.cc, pycall.cc, pyeval.cc, pyexec.cc: Use them instead of legacy conversion functions. Add necessary #includes, remove #includes of legacy header files. * @pyobject/subsasgn.m, @pyobject/subsref.m: Change %!tests that depend on NumPy implicit conversion into %!xtests. * octave_to_python.cc, octave_to_python.h, python_to_octave.cc, python_to_octave.h: Delete, no longer used. * Makefile.am (COMMON_SOURCE_FILES, PYTAVE_HEADER_FILES): Remove the files.
author Mike Miller <mtmiller@octave.org>
date Wed, 03 May 2017 16:30:45 -0700
parents f833e29b2c12
children 9bf8ba050122
comparison
equal deleted inserted replaced
410:95c6ad0be828 411:3613ffbd52b2
26 26
27 #include <limits> 27 #include <limits>
28 #include <octave/Cell.h> 28 #include <octave/Cell.h>
29 #include <octave/oct-map.h> 29 #include <octave/oct-map.h>
30 #include <octave/quit.h> 30 #include <octave/quit.h>
31 #include <octave/ov-null-mat.h>
31 32
32 #include "exceptions.h" 33 #include "exceptions.h"
33 #include "oct-py-eval.h" 34 #include "oct-py-eval.h"
34 #include "oct-py-object.h" 35 #include "oct-py-object.h"
35 #include "oct-py-types.h" 36 #include "oct-py-types.h"
36 37 #include "oct-py-util.h"
37 // FIXME: only here to bootstrap nested conversions needed in this file 38
38 #include "octave_to_python.h" 39 // FIXME: only here for exception types still used in this file
39 #include "python_to_octave.h" 40 #include <boost/python/errors.hpp>
40 41
41 namespace pytave 42 namespace pytave
42 { 43 {
43 44
44 PyObject * 45 PyObject *
309 310
310 throw value_convert_exception ("unhandled Octave numeric vector type"); 311 throw value_convert_exception ("unhandled Octave numeric vector type");
311 return 0; 312 return 0;
312 } 313 }
313 314
314 inline PyObject *
315 wrap_octvalue_to_pyobj (const octave_value& value)
316 {
317 boost::python::object obj;
318 octvalue_to_pyobj (obj, value);
319 PyObject *ptr = obj.ptr ();
320 Py_INCREF (ptr);
321 return ptr;
322 }
323
324 inline octave_value
325 wrap_pyobj_to_octvalue (PyObject *obj)
326 {
327 boost::python::object objref
328 { boost::python::handle<> (boost::python::borrowed (obj)) };
329 octave_value value;
330 pyobj_to_octvalue (value, objref);
331 return value;
332 }
333
334 octave_scalar_map 315 octave_scalar_map
335 extract_py_scalar_map (PyObject *obj) 316 extract_py_scalar_map (PyObject *obj)
336 { 317 {
337 if (! obj) 318 if (! obj)
338 error ("unable to convert to an Octave struct, invalid Python object"); 319 error ("unable to convert to an Octave struct, invalid Python object");
351 if (! PyBytes_Check (py_key) && ! PyUnicode_Check (py_key)) 332 if (! PyBytes_Check (py_key) && ! PyUnicode_Check (py_key))
352 error ("unable to convert Python dict to Octave struct, " 333 error ("unable to convert Python dict to Octave struct, "
353 "all keys in the dict must be strings"); 334 "all keys in the dict must be strings");
354 335
355 std::string key = extract_py_str (py_key); 336 std::string key = extract_py_str (py_key);
356 octave_value value = wrap_pyobj_to_octvalue (py_value); 337 octave_value value = py_implicitly_convert_return_value (py_value);
357 map.setfield (key, value); 338 map.setfield (key, value);
358 } 339 }
359 340
360 return map; 341 return map;
361 } 342 }
371 { 352 {
372 PyObject *key = make_py_str (map.key (p)); 353 PyObject *key = make_py_str (map.key (p));
373 if (! key) 354 if (! key)
374 octave_throw_bad_alloc (); 355 octave_throw_bad_alloc ();
375 356
376 PyObject *item = wrap_octvalue_to_pyobj (map.contents (p)); 357 PyObject *item = py_implicitly_convert_argument (map.contents (p));
377 358
378 if (PyDict_SetItem (dict, key, item) < 0) 359 if (PyDict_SetItem (dict, key, item) < 0)
379 throw boost::python::error_already_set (); 360 throw boost::python::error_already_set ();
380 } 361 }
381 362
462 if (! tuple) 443 if (! tuple)
463 octave_throw_bad_alloc (); 444 octave_throw_bad_alloc ();
464 445
465 for (octave_idx_type i = 0; i < size; ++i) 446 for (octave_idx_type i = 0; i < size; ++i)
466 { 447 {
467 PyObject *item = wrap_octvalue_to_pyobj (cell.xelem (i)); 448 PyObject *item = py_implicitly_convert_argument (cell.xelem (i));
468 PyTuple_SET_ITEM (tuple, i, item); 449 PyTuple_SET_ITEM (tuple, i, item);
469 } 450 }
470 451
471 return tuple; 452 return tuple;
472 } 453 }
505 #else 486 #else
506 return PyString_FromStringAndSize (str.data (), str.size ()); 487 return PyString_FromStringAndSize (str.data (), str.size ());
507 #endif 488 #endif
508 } 489 }
509 490
491 PyObject *
492 py_implicitly_convert_argument (const octave_value& value)
493 {
494 if (value.is_object () && value.class_name () == "pyobject")
495 return pyobject_unwrap_object (value);
496 else if (value.is_string () && value.rows () > 1)
497 error ("unable to convert multirow char array to a Python object");
498 else if (value.is_string ())
499 return make_py_str (value.string_value ());
500 else if (value.is_scalar_type ())
501 return make_py_numeric_value (value);
502 else if (value.is_cell ())
503 return make_py_tuple (value.cell_value ());
504 else if (value.is_numeric_type () && value.ndims () == 2
505 && (value.columns () <= 1 || value.rows () <= 1))
506 return make_py_array (value);
507 else if (value.is_map () && value.numel () == 1)
508 return make_py_dict (value.scalar_map_value ());
509 else
510 error ("unable to convert unhandled Octave type to a Python object");
511
512 return nullptr;
513 }
514
515 octave_value
516 py_implicitly_convert_return_value (PyObject *obj)
517 {
518 if (PyBool_Check (obj))
519 return octave_value {extract_py_bool (obj)};
520 #if PY_VERSION_HEX < 0x03000000
521 else if (PyInt_Check (obj))
522 return octave_value {octave_int64 (extract_py_int64 (obj))};
523 #endif
524 else if (PyComplex_Check (obj))
525 return octave_value {extract_py_complex (obj)};
526 else if (PyFloat_Check (obj))
527 return octave_value {extract_py_float (obj)};
528 else
529 return pyobject_wrap_object (obj);
530 }
531
510 } 532 }