Mercurial > pytave
changeset 332:b8128a2e0e70
pyargs: New function to construct keyword arguments (see issue #45)
* pyargs.m: New function to construct a type containing keyword arguments.
author | Mike Miller <mtmiller@octave.org> |
---|---|
date | Mon, 15 Aug 2016 12:43:51 -0700 |
parents | cee203ea6245 |
children | 96b78e78a235 |
files | pyargs.m |
diffstat | 1 files changed, 99 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyargs.m Mon Aug 15 12:43:51 2016 -0700 @@ -0,0 +1,99 @@ +## Copyright (C) 2016 Mike Miller +## +## 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. +## +## Pytave 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 Pytave; see the file COPYING. If not, see +## <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {} {} pyargs (@var{name}, @var{value}) +## @deftypefnx {} {} pyargs (@var{name}, @var{value}, @dots{}) +## Construct a set of Python keyword arguments suitable for passing to +## a Python function. +## +## Python keyword arguments are similar to optional named parameters accepted +## by some Octave functions such as @code{cellfun} or @code{set}. +## +## For example, a dictionary can be initialized with +## +## @example +## @group +## py.dict (pyargs ("one", 1, "two", 2)) +## @result{} [pyobject ...] +## @{...@} +## sort (cell (py.list (ans.keys ()))) +## @result{} +## @{ +## [1,1] = one +## [1,2] = two +## @} +## @end group +## @end example +## +## And a list can be sorted in reverse order with the @code{reverse} keyword +## +## @example +## @group +## x = py.list (num2cell (int32 ([1, 2, 3]))); +## x.sort (pyargs ("reverse", true)); +## x +## @result{} x = [pyobject ...] +## [3, 2, 1] +## @end group +## @end example +## @end deftypefn + +function args = pyargs (varargin) + + if (mod (nargin, 2) != 0) + error ("pyargs: must be called with NAME, VALUE pairs of arguments"); + endif + + keys_vals = {}; + for i = 1:(nargin / 2) + k = varargin{2*i - 1}; + v = varargin{2*i}; + if (! (ischar (k) && isrow (k))) + error ("pyargs: NAME %d must be a string", i); + endif + try + v = pyobject (v); + catch + error ("pyargs: VALUE %d must be convertible to a Python object", i); + end_try_catch + + keys_vals{i} = {k, v}; + endfor + + ## This function needs to return a Python mapping object that will be + ## recognized by other functions as containing keyword arguments. + ## Define the class using a type specifier so it can be defined and + ## instantiated as a single expression. + class_name = "_OctaveKwargs"; + props = "{'is_kwargs_argument': False}"; + args = pyeval (sprintf ("type('%s', (dict,), %s)()", class_name, props)); + args.update (keys_vals); + args.is_kwargs_argument = true; + +endfunction + + +%!assert (isa (pyargs (), "pyobject")) +%!assert (sort (cell (py.list (py.dict (pyargs ()).keys ()))), cell (1, 0)) +%!xtest assert (sort (cell (py.list (py.dict (pyargs ("one", 1)).keys ()))), {"one"}) +%!assert (sort (cell (py.list (py.dict (pyargs ("one", 1, "two", 2)).keys ()))), {"one", "two"}) + +%!error pyargs (1) +%!error pyargs (1, 2) +%!error pyargs ("one")