@@ -126,7 +126,7 @@ public Object doForeignObjectSlice(Object object, PSlice idxSlice,
126126 try {
127127 mslice = materializeSlice (idxSlice , object , lib );
128128 } catch (UnsupportedMessageException e ) {
129- throw raise ( AttributeError , "%s instance has no attribute '__getitem__'" , object );
129+ throw raiseAttributeError ( object );
130130 }
131131 Object [] values = new Object [mslice .length ];
132132 for (int i = mslice .start , j = 0 ; i < mslice .stop ; i += mslice .step , j ++) {
@@ -138,17 +138,19 @@ public Object doForeignObjectSlice(Object object, PSlice idxSlice,
138138 @ Specialization
139139 public Object doForeignKey (Object object , String key ,
140140 @ CachedLibrary (limit = "3" ) InteropLibrary lib ) {
141- try {
142- return lib .readMember (object , key );
143- } catch (UnsupportedMessageException e ) {
144- if (lib .hasArrayElements (object )) {
145- throw raise (TypeError , "'%p' object cannot be interpreted as an integer" , key );
146- } else {
147- throw raise (AttributeError , "%s instance has no attribute '__getitem__'" , object );
141+ if (lib .hasMembers (object )) {
142+ if (lib .isMemberReadable (object , key )) {
143+ try {
144+ return lib .readMember (object , key );
145+ } catch (UnsupportedMessageException e ) {
146+ throw raiseAttributeErrorDisambiguated (object , key , lib );
147+ } catch (UnknownIdentifierException e ) {
148+ // fall through
149+ }
148150 }
149- } catch (UnknownIdentifierException e ) {
150151 throw raise (KeyError , key );
151152 }
153+ throw raiseAttributeErrorDisambiguated (object , key , lib );
152154 }
153155
154156 @ Specialization (guards = {"!isSlice(idx)" , "!isString(idx)" })
@@ -158,14 +160,36 @@ public Object doForeignObject(Object object, Object idx,
158160 return readForeignValue (object , castIndex .execute (idx ), lib );
159161 }
160162
163+ private PException raiseAttributeErrorDisambiguated (Object object , String key , InteropLibrary lib ) {
164+ if (lib .hasArrayElements (object )) {
165+ throw raise (TypeError , "'%p' object cannot be interpreted as an integer" , key );
166+ } else {
167+ throw raiseAttributeError (object );
168+ }
169+ }
170+
161171 private Object readForeignValue (Object object , long index , InteropLibrary lib ) {
162- try {
163- return getToPythonNode ().executeConvert (lib .readArrayElement (object , index ));
164- } catch (UnsupportedMessageException ex ) {
165- throw raise (AttributeError , "%s instance has no attribute '__getitem__'" , object );
166- } catch (InvalidArrayIndexException ex ) {
167- throw raise (IndexError , "invalid index %s" , index );
172+ if (lib .hasArrayElements (object )) {
173+ if (lib .isArrayElementReadable (object , index )) {
174+ try {
175+ return getToPythonNode ().executeConvert (lib .readArrayElement (object , index ));
176+ } catch (UnsupportedMessageException ex ) {
177+ throw raiseAttributeError (object );
178+ } catch (InvalidArrayIndexException ex ) {
179+ throw raiseIndexError (index );
180+ }
181+ }
182+ throw raiseIndexError (index );
168183 }
184+ throw raiseAttributeError (object );
185+ }
186+
187+ private PException raiseIndexError (long index ) {
188+ return raise (IndexError , "invalid index %s" , index );
189+ }
190+
191+ private PException raiseAttributeError (Object object ) {
192+ return raise (AttributeError , "%s instance has no attribute '__getitem__'" , object );
169193 }
170194
171195 private PForeignToPTypeNode getToPythonNode () {
@@ -207,22 +231,40 @@ public Object doForeignObjectSlice(VirtualFrame frame, Object object, PSlice idx
207231 @ Specialization
208232 public Object doForeignKey (Object object , String key , Object value ,
209233 @ CachedLibrary (limit = "3" ) InteropLibrary lib ) {
210- try {
211- lib .writeMember (object , key , value );
212- return PNone .NONE ;
213- } catch (UnsupportedMessageException e ) {
214- if (lib .hasArrayElements (object )) {
215- throw raise (TypeError , "'%p' object cannot be interpreted as an integer" , key );
216- } else {
217- throw raise (AttributeError , "attribute %s is read-only" , key );
234+ if (lib .hasMembers (object )) {
235+ if (lib .isMemberWritable (object , key )) {
236+ try {
237+ lib .writeMember (object , key , value );
238+ return PNone .NONE ;
239+ } catch (UnsupportedMessageException e ) {
240+ throw raiseAttributeReadOnlyDisambiguated (object , key , lib );
241+ } catch (UnknownIdentifierException e ) {
242+ throw raiseAttributeError (key );
243+ } catch (UnsupportedTypeException e ) {
244+ throw raiseAttributeReadOnly (key );
245+ }
218246 }
219- } catch (UnknownIdentifierException e ) {
220- throw raise (AttributeError , "foreign object has no attribute '%s'" , key );
221- } catch (UnsupportedTypeException e ) {
222- throw raise (AttributeError , "attribute %s is read-only" , key );
247+ throw raiseAttributeReadOnlyDisambiguated (object , key , lib );
248+ }
249+ throw raiseAttributeError (key );
250+ }
251+
252+ private PException raiseAttributeReadOnlyDisambiguated (Object object , String key , InteropLibrary lib ) {
253+ if (lib .hasArrayElements (object )) {
254+ throw raise (TypeError , "'%p' object cannot be interpreted as an integer" , key );
255+ } else {
256+ throw raiseAttributeReadOnly (key );
223257 }
224258 }
225259
260+ private PException raiseAttributeReadOnly (String key ) {
261+ return raise (AttributeError , "attribute %s is read-only" , key );
262+ }
263+
264+ private PException raiseAttributeError (String key ) {
265+ return raise (AttributeError , "foreign object has no attribute '%s'" , key );
266+ }
267+
226268 @ Specialization (guards = {"!isSlice(idx)" , "!isString(idx)" })
227269 public Object doForeignObject (Object object , Object idx , Object value ,
228270 @ CachedLibrary (limit = "3" ) InteropLibrary lib ,
@@ -239,13 +281,16 @@ public Object doForeignObject(Object object, Object idx, Object value,
239281 }
240282
241283 private void writeForeignValue (Object object , int idx , Object value , InteropLibrary lib ) throws UnsupportedMessageException , UnsupportedTypeException {
242- if (lib .isArrayElementModifiable (object , idx )) {
243- try {
244- lib .writeArrayElement (object , idx , value );
245- return ;
246- } catch (InvalidArrayIndexException ex ) {
247- throw raise (IndexError , "invalid index %s" , idx );
284+ if (lib .hasArrayElements (object )) {
285+ if (lib .isArrayElementWritable (object , idx )) {
286+ try {
287+ lib .writeArrayElement (object , idx , value );
288+ return ;
289+ } catch (InvalidArrayIndexException ex ) {
290+ // fall through
291+ }
248292 }
293+ throw raise (IndexError , "invalid index %s" , idx );
249294 }
250295 throw raise (AttributeError , "%s instance has no attribute '__setitem__'" , object );
251296 }
@@ -270,37 +315,58 @@ public Object doForeignObjectSlice(Object object, PSlice idxSlice,
270315 }
271316 return PNone .NONE ;
272317 } catch (UnsupportedMessageException e ) {
273- throw raise ( AttributeError , "%s instance has no attribute '__delitem__'" , object );
318+ throw raiseAttributeError ( object );
274319 }
275320 }
276321
277322 @ Specialization
278323 public Object doForeignKey (Object object , String key ,
279324 @ CachedLibrary (limit = "3" ) InteropLibrary lib ) {
280- try {
281- lib .removeMember (object , key );
282- return PNone .NONE ;
283- } catch (UnsupportedMessageException e ) {
284- if (lib .hasArrayElements (object )) {
285- throw raise (TypeError , "'%p' object cannot be interpreted as an integer" , key );
286- } else {
287- throw raise (AttributeError , "attribute %s is read-only" , key );
325+ if (lib .hasMembers (object )) {
326+ if (lib .isMemberRemovable (object , key )) {
327+ try {
328+ lib .removeMember (object , key );
329+ return PNone .NONE ;
330+ } catch (UnsupportedMessageException e ) {
331+ throw raiseAttributeReadOnlyDisambiguated (object , key , lib );
332+ } catch (UnknownIdentifierException e ) {
333+ throw raiseAttributeError (key );
334+ }
288335 }
289- } catch (UnknownIdentifierException e ) {
290- throw raise (AttributeError , "foreign object has no attribute '%s'" , key );
336+ throw raiseAttributeReadOnlyDisambiguated (object , key , lib );
337+ }
338+ throw raiseAttributeError (key );
339+ }
340+
341+ private PException raiseAttributeError (String key ) {
342+ return raise (AttributeError , "foreign object has no attribute '%s'" , key );
343+ }
344+
345+ private PException raiseAttributeReadOnlyDisambiguated (Object object , String key , InteropLibrary lib ) {
346+ if (lib .hasArrayElements (object )) {
347+ throw raise (TypeError , "'%p' object cannot be interpreted as an integer" , key );
348+ } else {
349+ throw raise (AttributeError , "attribute %s is read-only" , key );
291350 }
292351 }
293352
294353 @ Specialization (guards = "!isSlice(idx)" )
295354 public Object doForeignObject (Object object , Object idx ,
296355 @ Cached CastToIndexNode castIndex ,
297356 @ CachedLibrary (limit = "3" ) InteropLibrary lib ) {
298- try {
299- int convertedIdx = castIndex .execute (idx );
300- return removeForeignValue (object , convertedIdx , lib );
301- } catch (UnsupportedMessageException e ) {
302- throw raise (AttributeError , "%s instance has no attribute '__delitem__'" , object );
357+ if (lib .hasArrayElements (object )) {
358+ try {
359+ int convertedIdx = castIndex .execute (idx );
360+ return removeForeignValue (object , convertedIdx , lib );
361+ } catch (UnsupportedMessageException e ) {
362+ // fall through
363+ }
303364 }
365+ throw raiseAttributeError (object );
366+ }
367+
368+ private PException raiseAttributeError (Object object ) {
369+ return raise (AttributeError , "%s instance has no attribute '__delitem__'" , object );
304370 }
305371
306372 private Object removeForeignValue (Object object , int idx , InteropLibrary lib ) throws UnsupportedMessageException {
@@ -311,7 +377,7 @@ private Object removeForeignValue(Object object, int idx, InteropLibrary lib) th
311377 throw raise (IndexError , "invalid index %s" , idx );
312378 }
313379 }
314- throw raise ( AttributeError , "%s instance has no attribute '__delitem__'" , object );
380+ throw raiseAttributeError ( object );
315381 }
316382
317383 public static RemoveForeignItemNode create () {
0 commit comments