Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Jul 22, 2023. It is now read-only.
/pythonnetPublic archive
forked frompythonnet/pythonnet

Commit00c22a5

Browse files
danabrlostmsu
authored andcommitted
Make indexers work for interface objects
Makes the following work instead of throwing an exception:```pythonfrom System.Collections.Generic import Dictionary, IDictionaryd = IDictionary[str, str](Dictionary[str, str]())d["one"] = "1"assert d["one"] == "1"```
1 parent03cf4ac commit00c22a5

File tree

5 files changed

+135
-128
lines changed

5 files changed

+135
-128
lines changed

‎CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ details about the cause of the failure
2929
- Fixed a bug where all .NET class instances were considered Iterable
3030
- Fix incorrect choice of method to invoke when using keyword arguments.
3131
- Fix non-delegate types incorrectly appearing as callable.
32+
- Indexers can now be used with interface objects
3233

3334
##[2.5.0][] - 2020-06-14
3435

‎src/runtime/arrayobject.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
4040
/// <summary>
4141
/// Implements __getitem__ for array types.
4242
/// </summary>
43-
publicstaticIntPtrmp_subscript(IntPtrob,IntPtridx)
43+
publicnewstaticIntPtrmp_subscript(IntPtrob,IntPtridx)
4444
{
4545
varobj=(CLRObject)GetManagedObject(ob);
4646
vararrObj=(ArrayObject)GetManagedObjectType(ob);
@@ -133,7 +133,7 @@ public static IntPtr mp_subscript(IntPtr ob, IntPtr idx)
133133
/// <summary>
134134
/// Implements __setitem__ for array types.
135135
/// </summary>
136-
publicstaticintmp_ass_subscript(IntPtrob,IntPtridx,IntPtrv)
136+
publicstaticnewintmp_ass_subscript(IntPtrob,IntPtridx,IntPtrv)
137137
{
138138
varobj=(CLRObject)GetManagedObject(ob);
139139
varitems=obj.instasArray;

‎src/runtime/classbase.cs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,5 +302,129 @@ public static void tp_dealloc(IntPtr ob)
302302
Runtime.XDecref(self.tpHandle);
303303
self.gcHandle.Free();
304304
}
305+
306+
307+
/// <summary>
308+
/// Implements __getitem__ for reflected classes and value types.
309+
/// </summary>
310+
publicstaticIntPtrmp_subscript(IntPtrob,IntPtridx)
311+
{
312+
IntPtrtp=Runtime.PyObject_TYPE(ob);
313+
varcls=(ClassBase)GetManagedObject(tp);
314+
315+
if(cls.indexer==null||!cls.indexer.CanGet)
316+
{
317+
Exceptions.SetError(Exceptions.TypeError,"unindexable object");
318+
returnIntPtr.Zero;
319+
}
320+
321+
// Arg may be a tuple in the case of an indexer with multiple
322+
// parameters. If so, use it directly, else make a new tuple
323+
// with the index arg (method binders expect arg tuples).
324+
IntPtrargs=idx;
325+
varfree=false;
326+
327+
if(!Runtime.PyTuple_Check(idx))
328+
{
329+
args=Runtime.PyTuple_New(1);
330+
Runtime.XIncref(idx);
331+
Runtime.PyTuple_SetItem(args,0,idx);
332+
free=true;
333+
}
334+
335+
IntPtrvalue;
336+
337+
try
338+
{
339+
value=cls.indexer.GetItem(ob,args);
340+
}
341+
finally
342+
{
343+
if(free)
344+
{
345+
Runtime.XDecref(args);
346+
}
347+
}
348+
returnvalue;
349+
}
350+
351+
352+
/// <summary>
353+
/// Implements __setitem__ for reflected classes and value types.
354+
/// </summary>
355+
publicstaticintmp_ass_subscript(IntPtrob,IntPtridx,IntPtrv)
356+
{
357+
IntPtrtp=Runtime.PyObject_TYPE(ob);
358+
varcls=(ClassBase)GetManagedObject(tp);
359+
360+
if(cls.indexer==null||!cls.indexer.CanSet)
361+
{
362+
Exceptions.SetError(Exceptions.TypeError,"object doesn't support item assignment");
363+
return-1;
364+
}
365+
366+
// Arg may be a tuple in the case of an indexer with multiple
367+
// parameters. If so, use it directly, else make a new tuple
368+
// with the index arg (method binders expect arg tuples).
369+
IntPtrargs=idx;
370+
varfree=false;
371+
372+
if(!Runtime.PyTuple_Check(idx))
373+
{
374+
args=Runtime.PyTuple_New(1);
375+
Runtime.XIncref(idx);
376+
Runtime.PyTuple_SetItem(args,0,idx);
377+
free=true;
378+
}
379+
380+
// Get the args passed in.
381+
vari=Runtime.PyTuple_Size(args);
382+
IntPtrdefaultArgs=cls.indexer.GetDefaultArgs(args);
383+
varnumOfDefaultArgs=Runtime.PyTuple_Size(defaultArgs);
384+
vartemp=i+numOfDefaultArgs;
385+
IntPtrreal=Runtime.PyTuple_New(temp+1);
386+
for(varn=0;n<i;n++)
387+
{
388+
IntPtritem=Runtime.PyTuple_GetItem(args,n);
389+
Runtime.XIncref(item);
390+
Runtime.PyTuple_SetItem(real,n,item);
391+
}
392+
393+
// Add Default Args if needed
394+
for(varn=0;n<numOfDefaultArgs;n++)
395+
{
396+
IntPtritem=Runtime.PyTuple_GetItem(defaultArgs,n);
397+
Runtime.XIncref(item);
398+
Runtime.PyTuple_SetItem(real,n+i,item);
399+
}
400+
// no longer need defaultArgs
401+
Runtime.XDecref(defaultArgs);
402+
i=temp;
403+
404+
// Add value to argument list
405+
Runtime.XIncref(v);
406+
Runtime.PyTuple_SetItem(real,i,v);
407+
408+
try
409+
{
410+
cls.indexer.SetItem(ob,real);
411+
}
412+
finally
413+
{
414+
Runtime.XDecref(real);
415+
416+
if(free)
417+
{
418+
Runtime.XDecref(args);
419+
}
420+
}
421+
422+
if(Exceptions.ErrorOccurred())
423+
{
424+
return-1;
425+
}
426+
427+
return0;
428+
}
305429
}
306430
}

‎src/runtime/classobject.cs

Lines changed: 0 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -152,131 +152,5 @@ public override IntPtr type_subscript(IntPtr idx)
152152
}
153153
returnExceptions.RaiseTypeError("unsubscriptable object");
154154
}
155-
156-
157-
/// <summary>
158-
/// Implements __getitem__ for reflected classes and value types.
159-
/// </summary>
160-
publicstaticIntPtrmp_subscript(IntPtrob,IntPtridx)
161-
{
162-
//ManagedType self = GetManagedObject(ob);
163-
IntPtrtp=Runtime.PyObject_TYPE(ob);
164-
varcls=(ClassBase)GetManagedObject(tp);
165-
166-
if(cls.indexer==null||!cls.indexer.CanGet)
167-
{
168-
Exceptions.SetError(Exceptions.TypeError,"unindexable object");
169-
returnIntPtr.Zero;
170-
}
171-
172-
// Arg may be a tuple in the case of an indexer with multiple
173-
// parameters. If so, use it directly, else make a new tuple
174-
// with the index arg (method binders expect arg tuples).
175-
IntPtrargs=idx;
176-
varfree=false;
177-
178-
if(!Runtime.PyTuple_Check(idx))
179-
{
180-
args=Runtime.PyTuple_New(1);
181-
Runtime.XIncref(idx);
182-
Runtime.PyTuple_SetItem(args,0,idx);
183-
free=true;
184-
}
185-
186-
IntPtrvalue;
187-
188-
try
189-
{
190-
value=cls.indexer.GetItem(ob,args);
191-
}
192-
finally
193-
{
194-
if(free)
195-
{
196-
Runtime.XDecref(args);
197-
}
198-
}
199-
returnvalue;
200-
}
201-
202-
203-
/// <summary>
204-
/// Implements __setitem__ for reflected classes and value types.
205-
/// </summary>
206-
publicstaticintmp_ass_subscript(IntPtrob,IntPtridx,IntPtrv)
207-
{
208-
//ManagedType self = GetManagedObject(ob);
209-
IntPtrtp=Runtime.PyObject_TYPE(ob);
210-
varcls=(ClassBase)GetManagedObject(tp);
211-
212-
if(cls.indexer==null||!cls.indexer.CanSet)
213-
{
214-
Exceptions.SetError(Exceptions.TypeError,"object doesn't support item assignment");
215-
return-1;
216-
}
217-
218-
// Arg may be a tuple in the case of an indexer with multiple
219-
// parameters. If so, use it directly, else make a new tuple
220-
// with the index arg (method binders expect arg tuples).
221-
IntPtrargs=idx;
222-
varfree=false;
223-
224-
if(!Runtime.PyTuple_Check(idx))
225-
{
226-
args=Runtime.PyTuple_New(1);
227-
Runtime.XIncref(idx);
228-
Runtime.PyTuple_SetItem(args,0,idx);
229-
free=true;
230-
}
231-
232-
// Get the args passed in.
233-
vari=Runtime.PyTuple_Size(args);
234-
IntPtrdefaultArgs=cls.indexer.GetDefaultArgs(args);
235-
varnumOfDefaultArgs=Runtime.PyTuple_Size(defaultArgs);
236-
vartemp=i+numOfDefaultArgs;
237-
IntPtrreal=Runtime.PyTuple_New(temp+1);
238-
for(varn=0;n<i;n++)
239-
{
240-
IntPtritem=Runtime.PyTuple_GetItem(args,n);
241-
Runtime.XIncref(item);
242-
Runtime.PyTuple_SetItem(real,n,item);
243-
}
244-
245-
// Add Default Args if needed
246-
for(varn=0;n<numOfDefaultArgs;n++)
247-
{
248-
IntPtritem=Runtime.PyTuple_GetItem(defaultArgs,n);
249-
Runtime.XIncref(item);
250-
Runtime.PyTuple_SetItem(real,n+i,item);
251-
}
252-
// no longer need defaultArgs
253-
Runtime.XDecref(defaultArgs);
254-
i=temp;
255-
256-
// Add value to argument list
257-
Runtime.XIncref(v);
258-
Runtime.PyTuple_SetItem(real,i,v);
259-
260-
try
261-
{
262-
cls.indexer.SetItem(ob,real);
263-
}
264-
finally
265-
{
266-
Runtime.XDecref(real);
267-
268-
if(free)
269-
{
270-
Runtime.XDecref(args);
271-
}
272-
}
273-
274-
if(Exceptions.ErrorOccurred())
275-
{
276-
return-1;
277-
}
278-
279-
return0;
280-
}
281155
}
282156
}

‎src/tests/test_indexer.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,3 +595,11 @@ def test_indexer_abuse():
595595

596596
withpytest.raises(AttributeError):
597597
delob.__setitem__
598+
599+
600+
deftest_indexer_accessed_through_interface():
601+
"""Test that indexers can be accessed through interfaces"""
602+
fromSystem.Collections.GenericimportDictionary,IDictionary
603+
d=IDictionary[str,str](Dictionary[str,str]())
604+
d["one"]="1"
605+
assertd["one"]=="1"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp