Mercurial > pytave
comparison @pyobject/subsref.m @ 260:daf1aff501f1
indexing: fix off-by-one with dicts (fixes issue #10)
Also, dogfood pyobject a bit more instead of just generating strings
of code and using pyexec.
* @pyobject/subsref.m: Improve {} indexing.
author | Colin Macdonald <cbm@m.fsf.org> |
---|---|
date | Tue, 26 Jul 2016 20:32:24 -0700 |
parents | 2e4c9ce0c83c |
children | 0a8983533192 |
comparison
equal
deleted
inserted
replaced
251:c8da556b6793 | 260:daf1aff501f1 |
---|---|
42 case "." | 42 case "." |
43 assert (ischar (t.subs)) | 43 assert (ischar (t.subs)) |
44 r = pycall ("getattr", x, t.subs); | 44 r = pycall ("getattr", x, t.subs); |
45 | 45 |
46 case "{}" | 46 case "{}" |
47 subsstrs = {}; | 47 ## Subtract one from index: do this for lists, numpy arrays, etc |
48 for j = 1:length (t.subs) | 48 pyexec ("import collections") |
49 thissub = t.subs{j}; | 49 pyexec ("import numpy") |
50 if (ischar (thissub) && strcmp (thissub, ":")) | 50 x_is_list = pycall (pyeval ( |
51 subsstrs{j} = ":"; | 51 "lambda (x): isinstance(x, (collections.Sequence, numpy.ndarray))"), |
52 elseif (ischar (thissub)) | 52 x); |
53 subsstrs{j} = ["'" thissub "'"]; | 53 for i = 1:length(t.subs) |
54 elseif (isnumeric (thissub) && isscalar (thissub)) | 54 j = t.subs{i}; |
55 ## note: python indexed from 0 | 55 if (isindex (j) && isnumeric (j) && x_is_list) |
56 subsstrs{j} = num2str (thissub - 1); | 56 t.subs{i} = cast (j, class (sizemax ())) - 1; |
57 else | |
58 thissub | |
59 error ("@pyobject/subsref: subs not supported") | |
60 endif | 57 endif |
61 endfor | 58 endfor |
62 s = ["[" strjoin(subsstrs, ", ") "]"]; | 59 |
63 ## XXX: can we use .__getitem__ here? | 60 if (isscalar (t.subs)) |
64 r = pyeval (sprintf ("__InOct__['%s']%s", x.id, s)); | 61 ind = t.subs{1}; |
62 else | |
63 ## XXX: after #26, #27, I think its just: | |
64 #ind = pycall ("tuple", t.subs); | |
65 pyexec (["global _temp\n" ... | |
66 "def pystoretemp(x):\n" ... | |
67 " global _temp\n" ... | |
68 " _temp = x"]); | |
69 pycall ("pystoretemp", t.subs); | |
70 pyexec ("_temp = tuple(_temp[0])"); | |
71 ind = pyobject.fromPythonVarName ("_temp"); | |
72 endif | |
73 gi = pycall ("getattr", x, "__getitem__"); # x.__getitem__ | |
74 r = pycall (gi, ind); | |
65 | 75 |
66 otherwise | 76 otherwise |
67 t | 77 t |
68 error ("@pyobject/subsref: not implemented") | 78 error ("@pyobject/subsref: not implemented") |
69 endswitch | 79 endswitch |
86 %! pyexec ("L = [10, 20]") | 96 %! pyexec ("L = [10, 20]") |
87 %! L = pyobject.fromPythonVarName ("L"); | 97 %! L = pyobject.fromPythonVarName ("L"); |
88 %! assert (L{1}, 10) | 98 %! assert (L{1}, 10) |
89 %! assert (L{2}, 20) | 99 %! assert (L{2}, 20) |
90 | 100 |
91 %!test | 101 %!xtest |
92 %! % list indexing | 102 %! % list indexing, slice |
93 %! pyexec ("L = [10, 20, [30, 40]]") | 103 %! pyexec ("L = [10, 20, [30, 40]]") |
94 %! L = pyobject.fromPythonVarName ("L"); | 104 %! L = pyobject.fromPythonVarName ("L"); |
95 %! L2 = L{:}; | 105 %! L2 = L{:}; |
96 %! assert (L2{1}, 10) | 106 %! assert (L2{1}, 10) |
97 %! assert (L2{2}, 20) | 107 %! assert (L2{2}, 20) |
125 %! % dict: integer key access | 135 %! % dict: integer key access |
126 %! pyexec ("d = {5:42, 6:42}") | 136 %! pyexec ("d = {5:42, 6:42}") |
127 %! d = pyobject.fromPythonVarName ("d"); | 137 %! d = pyobject.fromPythonVarName ("d"); |
128 %! assert (d{6}, 42) | 138 %! assert (d{6}, 42) |
129 | 139 |
130 %!xtest | 140 %!test |
131 %! % dict: integer key should not subtract one (FIXME: Issue #10) | 141 %! % dict: integer key should not subtract one |
132 %! pyexec ("d = {5:40, 6:42}") | 142 %! pyexec ("d = {5:40, 6:42}") |
133 %! d = pyobject.fromPythonVarName ("d"); | 143 %! d = pyobject.fromPythonVarName ("d"); |
134 %! assert (d{6}, 42) | 144 %! assert (d{6}, 42) |
145 | |
146 %!test | |
147 %! % dict: floating point keys should work | |
148 %! pyexec ("d = {5.5:'ok'}") | |
149 %! d = pyobject.fromPythonVarName ("d"); | |
150 %! assert (d{5.5}, "ok") | |
151 | |
152 %!test | |
153 %! % dict: make sure key ":" doesn't break anything | |
154 %! pyexec ("d = {'a':1, ':':2}") | |
155 %! d = pyobject.fromPythonVarName ("d"); | |
156 %! assert (d{'a'}, 1) | |
157 %! assert (d{':'}, 2) | |
135 | 158 |
136 %!test | 159 %!test |
137 %! % method call with args | 160 %! % method call with args |
138 %! s = pyeval ("set({1, 2})"); | 161 %! s = pyeval ("set({1, 2})"); |
139 %! s.add (42) | 162 %! s.add (42) |