-
Notifications
You must be signed in to change notification settings - Fork 52
/
_pyeval.m
113 lines (93 loc) · 2.98 KB
/
_pyeval.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
function _pyeval(input_file, output_file)
% _PYEVAL: Load a request from an input file, execute the request, and save
% the response to the output file.
%
% This allows you to run any Octave code. req should be a struct with the
% following fields:
% dname: The name of a directory to add to the runtime path before attempting to run the code.
% func_name: The name of a function to invoke.
% func_args: An array of arguments to send to the function.
% nout: An int specifying how many output arguments are expected.
% ref_indices: The indices of in the func_args that should
% be replaced by the value represented by their name.
% store_as: Optional name to store the return value in the base
% workspace, instead of returing a value.
%
% Should save a file containing the result object.
%
% Based on Max Jaderberg's web_feval
sentinel = { '__no_value__' };
result = { sentinel };
err = '';
try
% Store the simple response in case we don't make it through the script.
save('-v6', '-mat-binary', output_file, 'result', 'err');
req = load(input_file);
% Add function path to current path.
if req.dname
addpath(req.dname);
end
% Replace the names at the specified indices with their values.
for idx=1:length(req.ref_indices)
ref_index = req.ref_indices(idx);
var_name = req.func_args{ref_index};
req.func_args{ref_index} = evalin('base', var_name);
end
assignin('base', 'ans', sentinel);
% Use the `ans` response if no output arguments are expected.
if req.nout == 0
if length(req.func_args)
feval(req.func_name, req.func_args{:});
else
feval(req.func_name)
end
result = get_ans(sentinel);
elseif length(req.func_args)
try
[result{1:req.nout}] = feval(req.func_name, req.func_args{:});
catch ME
if (strcmp(ME.message, 'element number 1 undefined in return list') != 1 ||
length(ME.stack) != 1)
rethrow(ME);
else
result = get_ans(sentinel);
end
end
else
try
[result{1:req.nout}] = feval(req.func_name);
catch ME
rethrow(ME);
if (strcmp(ME.message, 'element number 1 undefined in return list') != 1 ||
length(ME.stack) != 1)
rethrow(ME);
end
end
end
if req.store_as
assignin('base', req.store_as, result{1});
result = { sentinel };
end
if ((strcmp(get(0, 'defaultfigurevisible'), 'on') == 1) &&
length(get(0, 'children')))
drawnow('expose');
end
catch ME
err = ME;
end
% Save the output to a file.
try
save('-v6', '-mat-binary', output_file, 'result', 'err');
catch ME
result = { sentinel };
err = ME;
save('-v6', '-mat-binary', output_file, 'result', 'err');
end
end % function
function result = get_ans(sentinel)
try
[result{1}] = evalin('base', 'ans');
catch
result = { sentinel };
end
end