changeset 224:7feece80fbfa

pyobject: Octave-style formatting, minor edits * @pyobject/pyobject.m: reformat, add test * @pyobject/dummy.m: reformat, xfail a test * @pyobject/display.m: reformat
author Colin Macdonald <cbm@m.fsf.org>
date Fri, 17 Jun 2016 22:15:28 -0700
parents 06835a3e3384
children 0c6f7ae8a95b
files @pyobject/display.m @pyobject/dummy.m @pyobject/pyobject.m
diffstat 3 files changed, 231 insertions(+), 223 deletions(-) [+]
line wrap: on
line diff
--- a/@pyobject/display.m	Fri Jun 17 22:13:54 2016 -0700
+++ b/@pyobject/display.m	Fri Jun 17 22:15:28 2016 -0700
@@ -1,62 +1,61 @@
-%% Copyright (C) 2016 Colin B. Macdonald
-%%
-%% This file is part of PyTave.
-%%
-%% OctSymPy 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/>.
+## Copyright (C) 2016 Colin B. Macdonald
+##
+## This file is part of PyTave.
+##
+## OctSymPy 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
-%% @defmethod @@pyobject display (@var{x})
-%% Custom display for pyobjects.
-%%
-%% Example:
-%% @example
-%% @group
-%% pyexec('import sys')
-%% sysmodule = pyeval('sys')
-%%   @result{} sysmodule = [pyobject ...]
-%%
-%%       <module 'sys' (built-in)>
-%%
-%% @end group
-%% @end example
-%%
-%% @seealso{@@pyobject/disp}
-%% @end defmethod
+## -*- texinfo -*-
+## @documentencoding UTF-8
+## @defmethod @@pyobject display (@var{x})
+## Custom display for pyobjects.
+##
+## Example:
+## @example
+## @group
+## pyexec('import sys')
+## sysmodule = pyeval('sys')
+##   @result{} sysmodule = [pyobject ...]
+##
+##       <module 'sys' (built-in)>
+##
+## @end group
+## @end example
+##
+## @seealso{@@pyobject/disp}
+## @end defmethod
 
 
 function display (x)
 
-  loose = eval('! __compactformat__ ()');
+  loose = ! __compactformat__ ();
 
-  printf ('%s = [pyobject %s]\n', inputname (1), getid (x));
+  printf ("%s = [pyobject %s]\n", inputname (1), getid (x));
   s = disp (x);
   s = make_indented (s);
-  if (loose), printf('\n'); end
-  disp(s)
-  if (loose), printf('\n'); end
+  if (loose), printf("\n"); endif
+  disp (s)
+  if (loose), printf("\n"); endif
 
-end
+endfunction
 
 
 function s = make_indented(s, n)
   if (nargin == 1)
     n = 2;
-  end
-  pad = char (double (' ')*ones (1,n));
-  newl = sprintf('\n');
-  s = strrep (s, newl, [newl pad]);
-  s = [pad s];  % first line
-end
+  endif
+  pad = char (double (" ")*ones (1,n));
+  s = strrep (s, "\n", ["\n" pad]);
+  s = [pad s];  # first line
+endfunction
--- a/@pyobject/dummy.m	Fri Jun 17 22:13:54 2016 -0700
+++ b/@pyobject/dummy.m	Fri Jun 17 22:15:28 2016 -0700
@@ -1,130 +1,131 @@
-%% Copyright (C) 2016 Colin B. Macdonald
-%%
-%% This file is part of PyTave.
-%%
-%% OctSymPy 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/>.
+## Copyright (C) 2016 Colin B. Macdonald
+##
+## This file is part of PyTave.
+##
+## OctSymPy 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
-%% @defmethod @@pyobject dummy (@var{x})
-%% Does nothing, stores doctests for now.
-%%
-%%
-%% Simple example:
-%% @example
-%% @group
-%% pyexec('g = 6')
-%% g = pyobject.fromPythonVarName('g');
-%%
-%% sort(whatmethods(g))
-%%   @result{} ans =
-%%     @{
-%%       [1,1] = bit_length
-%%       [1,2] = conjugate
-%%       [1,3] = denominator
-%%       [1,4] = imag
-%%       [1,5] = numerator
-%%       [1,6] = real
-%%      @}
-%%
-%% g.numerator
-%%   @result{} ans =  6
-%% g.denominator
-%%   @result{} ans =  1
-%% @end group
-%% @end example
-%%
-%%
-%% You can delete an object in Python and it will persist:
-%% @example
-%% @group
-%% pyexec('d = dict(one=1, two=2)')
-%% x = pyobject.fromPythonVarName('d')
-%%   @result{} x = [pyobject ...]
-%%       @{'two': 2, 'one': 1@}
-%%
-%% % oops, overwrote d in Python:
-%% pyexec('d = 42')
-%%
-%% % but have no fear, we still have a reference to it:
-%% x
-%%   @result{} x = [pyobject ...]
-%%       @{'two': 2, 'one': 1@}
-%% @end group
-%% @end example
-%%
-%% We can accesss ``callables'' (methods) of objects:
-%% @example
-%% @group
-%% x.keys()
-%%   @result{} ans =
-%%       @{
-%%         [1,1] = two
-%%         [1,2] = one
-%%       @}
-%% @end group
-%% @end example
-%%
-%% @code{pyeval} returns a @@pyobject for things it cannot convert to
-%% Octave-native objects:
-%% @example
-%% @group
-%% pyexec('import sys')
-%% sysmodule = pyeval('sys')
-%%   @result{} sysmodule = [pyobject ...]
-%%       <module 'sys' (built-in)>
-%% @end group
-%% @end example
-%%
-%% After you have the object, you can access its properties:
-%% @example
-%% @group
-%% sysmodule.version
-%%   @result{} ans = ...
-%% @end group
-%% @end example
-%%
-%%
-%% TODO: this should return a cell array with a double, a string,
-%% and an @@pyobject in it:
-%% @example
-%% @group
-%% pyeval('[42, "hello", sys]')         % doctest: +XFAIL
-%%   @result{} ans =
-%%       @{
-%%         [1,1] =  42
-%%         [1,2] = hello
-%%         [1,3] =
-%%           [PyObject id ...]
-%%           <module 'sys' (built-in)>
-%%       @}
-%% @end group
-%% @end example
-%%
-%% A @@pyobject can be passed back to Python.  This does not make
-%% a copy but rather a reference to the original object.
-%% For example:
-%% @example
-%% @group
-%% pycall('__builtin__.print', sysmodule)
-%%   @print{} <module 'sys' (built-in)>
-%% @end group
-%% @end example
-%%
-%% @seealso{pyobject}
-%% @end defmethod
+## -*- texinfo -*-
+## @documentencoding UTF-8
+## @defmethod @@pyobject dummy (@var{x})
+## Does nothing, stores doctests for now.
+##
+##
+## Simple example:
+## @example
+## @group
+## pyexec ("g = 6")
+## g = pyobject.fromPythonVarName ("g");
+##
+## sort (methods (g))
+##   @result{} ans =
+##     @{
+##       [1,1] = bit_length
+##       [1,2] = conjugate
+##       [1,3] = denominator
+##       [1,4] = imag
+##       [1,5] = numerator
+##       [1,6] = real
+##      @}
+##
+## g.numerator
+##   @result{} ans =  6
+## g.denominator
+##   @result{} ans =  1
+## @end group
+## @end example
+##
+##
+## You can delete an object in Python and it will persist:
+## @example
+## @group
+## pyexec ("d = dict(one=1, two=2)")
+## x = pyobject.fromPythonVarName ("d")
+##   @result{} x = [pyobject ...]
+##       @{'two': 2, 'one': 1@}
+##
+## # oops, overwrote d in Python:
+## pyexec ("d = 42")
+##
+## # but have no fear, we still have a reference to it:
+## x
+##   @result{} x = [pyobject ...]
+##       @{'two': 2, 'one': 1@}
+## @end group
+## @end example
+##
+## We can accesss ``callables'' (methods) of objects:
+## @example
+## @group
+## x.keys()
+##   @result{} ans =
+##       @{
+##         [1,1] = two
+##         [1,2] = one
+##       @}
+## @end group
+## @end example
+##
+## @code{pyeval} returns a @@pyobject for things it cannot convert to
+## Octave-native objects:
+## @example
+## @group
+## pyexec ("import sys")
+## sysmodule = pyeval ("sys")
+##   @result{} sysmodule = [pyobject ...]
+##       <module 'sys' (built-in)>
+## @end group
+## @end example
+##
+## After you have the object, you can access its properties:
+## @example
+## @group
+## sysmodule.version
+##   @result{} ans = ...
+## @end group
+## @end example
+##
+##
+## TODO: this should return a cell array with a double, a string,
+## and an @@pyobject in it:
+## @example
+## @group
+## pyeval ("[42, 'hello', sys]")         # doctest: +XFAIL
+##   @result{} ans =
+##       @{
+##         [1,1] =  42
+##         [1,2] = hello
+##         [1,3] =
+##           [PyObject id ...]
+##           <module 'sys' (built-in)>
+##       @}
+## @end group
+## @end example
+##
+## A @@pyobject can be passed back to Python.  This does not make
+## a copy but rather a reference to the original object.
+## For example:
+## @example
+## @group
+## pycall ("__builtin__.print", sysmodule)   # doctest: +XFAIL
+##   @print{} <module 'sys' (built-in)>
+## @end group
+## @end example
+## (FIXME: I think this failure may correspond to an existing doctest issue).
+##
+## @seealso{pyobject}
+## @end defmethod
 
 function dummy (x)
 
--- a/@pyobject/pyobject.m	Fri Jun 17 22:13:54 2016 -0700
+++ b/@pyobject/pyobject.m	Fri Jun 17 22:15:28 2016 -0700
@@ -1,30 +1,31 @@
-%% Copyright (C) 2016 Colin B. Macdonald
-%%
-%% This file is part of PyTave.
-%%
-%% OctSymPy 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/>.
+## Copyright (C) 2016 Colin B. Macdonald
+##
+## This file is part of PyTave.
+##
+## OctSymPy 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
-%% @defun  pyobject (@var{s})
-%% Wrap a Python object.
-%%
-%% TODO: where/how to document classdef classes?
-%%
-%% @seealso{pyexec, pyeval}
-%% @end defun
+## -*- texinfo -*-
+## @documentencoding UTF-8
+## @defun  pyobject (@var{s})
+## Wrap a Python object.
+##
+## TODO: where/how to document classdef classes?
+##
+## @seealso{pyexec, pyeval}
+## @end defun
+
 
 classdef pyobject < handle
   properties
@@ -33,13 +34,14 @@
 
   methods (Static)
     function x = fromPythonVarName (pyvarname)
-      % if @var{pyvarname} is a string, its assumed to be a variable
-      % name, e.g., previously created with pyexec.  This must exist
-      % at the time of construction but it can disappear later (we
-      % will keep track of the reference).
-      if (! ischar(pyvarname))
-        error('pyobject: currently we only take variable names as input')
-      end
+      # Warning: just for testing, may be removed without notice!
+      # If @var{pyvarname} is a string, its assumed to be a variable
+      # name, e.g., previously created with pyexec.  This must exist
+      # at the time of construction but it can disappear later (we
+      # will keep track of the reference).
+      if (! ischar (pyvarname))
+        error("pyobject: currently we only take variable names as input")
+      endif
       cmd = sprintf ([ ...
         'if not ("__InOct__" in vars() or "__InOct__" in globals()):\n' ...
         '    __InOct__ = dict()\n' ...
@@ -49,10 +51,10 @@
         '__InOct__[hex(id(%s))] = %s' ], ...
         pyvarname, pyvarname);
       pyexec (cmd);
-      id = pyeval (['hex(id(' pyvarname '))']);
+      id = pyeval (["hex(id(" pyvarname "))"]);
       x = pyobject (id);
-    end
-  end
+    endfunction
+  endmethods
 
 
   methods
@@ -60,7 +62,7 @@
       % warning: not intended for casual use: you must also insert
       % the object into the Python `__InOct__` dict with key `id`.
       x.id = id;
-    end
+    endfunction
 
     function delete (x)
       # Called on clear of the last reference---for subclasses of
@@ -83,38 +85,44 @@
       # throws KeyError if it wasn't in there for some reason
       cmd = sprintf ("__InOct__.pop('%s')", x.id);
       pyexec (cmd)
-    end
+    endfunction
 
+    # methods defined in external files
     dummy (x)
     display (x)
     subsref (x, idx)
 
     function r = getid (x)
       r = x.id;
-    end
+    endfunction
 
     function varargout = disp (x)
-      s = pyeval (sprintf ('str(__InOct__["%s"])', x.id));
+      s = pyeval (sprintf ("str(__InOct__['%s'])", x.id));
       if (nargout == 0)
         disp (s)
       else
         varargout = {s};
-      end
-    end
+      endif
+    endfunction
 
     function s = whatclass (x)
-      s = pyeval (sprintf ('str(__InOct__["%s"].__class__)', x.id));
-    end
+      s = pyeval (sprintf ("str(__InOct__['%s'].__class__)", x.id));
+    endfunction
 
     function vargout = help (x)
-      idx = struct ('type', '.', 'subs', '__doc__');
+      idx = struct ("type", ".", "subs", "__doc__");
       s = subsref (x, idx);
       if (nargout == 0)
         disp (s)
       else
         vargout = {s};
-      end
-    end
+      endif
+    endfunction
+  endmethods
+endclassdef
 
-  end
-end
+
+%!test
+%! pyexec ("import sys")
+%! A = pyeval ("sys");
+%! assert (isa (A, "pyobject"))