Mercurial > pytave
changeset 268:15666fdcbb45
Merged in macdonald/pytave (pull request #21)
pyobject: support indexed assignment (fixes issue #17)
author | Mike Miller <mtmiller@octave.org> |
---|---|
date | Fri, 29 Jul 2016 12:39:07 -0700 |
parents | 0fc1a58d7e89 (current diff) c7a7d94a142f (diff) |
children | 8c543a859ba2 |
files | |
diffstat | 1 files changed, 113 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/@pyobject/subsasgn.m Fri Jul 29 12:39:07 2016 -0700 @@ -0,0 +1,113 @@ +## Copyright (C) 2016 Colin B. Macdonald +## +## This file is part of Pytave. +## +## Pytave is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; either version 3 of the License, +## or (at your option) any later version. +## +## This software is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +## the GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public +## License along with this software; see the file COPYING. +## If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @documentencoding UTF-8 +## @defop Method @@pyobject subsasgn (@var{x}, @var{idx}, @var{rhs}) +## @defopx Operator @@pyobject {@var{x}.@var{property} =} {@var{rhs}} +## @defopx Operator @@pyobject {@var{x}@{@var{i}@} =} {@var{rhs}} +## @defopx Operator @@pyobject {@var{x}@{@var{i}, @var{j}, @dots{}@} =} {@var{rhs}} +## @defopx Operator @@pyobject {@var{x}@{@var{a}@} =} {@var{rhs}} +## Indexed assignment to Python objects. +## +## @seealso{@@pyobject/subsref} +## @end defop + +function r = subsasgn(x, idx, rhs) + + switch idx.type + case "." + assert (ischar (idx.subs)) + pycall ("setattr", x, idx.subs, rhs); + r = x; + + case "{}" + ## XXX: doesn't support slices or anything like that yet + + ## Subtract one from index: do this for lists, numpy arrays, etc + pyexec ("import collections") + pyexec ("import numpy") + x_is_list = pycall (pyeval ( + "lambda (x): isinstance(x, (collections.Sequence, numpy.ndarray))"), + x); + for i = 1:length (idx.subs) + j = idx.subs{i}; + if (x_is_list && isindex (j) && isnumeric (j)) + idx.subs{i} = cast (j, class (sizemax ())) - 1; + endif + endfor + + if (isscalar (idx.subs)) + ind = idx.subs{1}; + else + error ("not implemented, waiting on #26, #27") + endif + + xsi = pycall ("getattr", x, "__setitem__"); # x.__setitem__ + pycall (xsi, ind, rhs); + r = x; + + otherwise + idx + rhs + error ("@pyobject/subsasgn: not implemented") + endswitch +endfunction + + +%!test +%! pyexec ("class MyClass: a = 1") +%! t = pyeval ("MyClass()"); +%! t.b = 6; +%! assert (t.b, 6) + +%!test +%! % list indexing +%! pyexec ("L = [10, 20]") +%! L = pyobject.fromPythonVarName ("L"); +%! L{2} = "Octave"; +%! assert (length (L) == 2) +%! assert (L{1}, 10) +%! assert (L{2}, "Octave") + +%!test +%! % dict assignment, adding new keys +%! pyexec ("d = dict()") +%! d = pyobject.fromPythonVarName ("d"); +%! d{"a"} = 3; +%! d{"b"} = 4; +%! assert (d{"a"}, 3) +%! assert (d{"b"}, 4) + +%!test +%! % dict assignment, update existing key +%! pyexec ("d = {'a':1}") +%! d = pyobject.fromPythonVarName ("d"); +%! d{"a"} = 3; +%! assert (d{"a"}, 3) + +%!test +%! % dict assignment, other keys (e.g., Issue #10). +%! pyexec ("d = dict()") +%! d = pyobject.fromPythonVarName ("d"); +%! d{"5"} = 10; +%! d{5.5} = 11; +%! d{5} = 12; +%! assert (d{"5"}, 10) +%! assert (d{5.5}, 11) +%! assert (d{5}, 12)