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

Commit77bdf6d

Browse files
committed
implemented __delitem__ for IDictionary<K,V> and IList<T>
fixed crash for all other types (now properly throws TypeError)fixes#2530
1 parentac605fd commit77bdf6d

File tree

7 files changed

+119
-0
lines changed

7 files changed

+119
-0
lines changed

‎CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
88
##Unreleased
99

1010
###Added
11+
12+
- Support`del obj[...]` for types derived from`IList<T>` and`IDictionary<K, V>`
13+
1114
###Changed
1215
###Fixed
1316

17+
- Fixed crash when trying to`del clrObj[...]` for non-arrays
1418
- ci: properly exclude job (#2542)
1519

1620
##[3.0.5](https://github.com/pythonnet/pythonnet/releases/tag/v3.0.5) - 2024-12-13

‎src/runtime/ClassManager.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ internal static void InitClassBase(Type type, ClassBase impl, ReflectedClrType p
213213
ClassInfoinfo=GetClassInfo(type,impl);
214214

215215
impl.indexer=info.indexer;
216+
impl.del=info.del;
216217
impl.richcompare.Clear();
217218

218219

@@ -538,6 +539,21 @@ private static ClassInfo GetClassInfo(Type type, ClassBase impl)
538539

539540
ob=newMethodObject(type,name,mlist);
540541
ci.members[name]=ob.AllocObject();
542+
if(name==nameof(IDictionary<int,int>.Remove)
543+
&&mlist.Any(m=>m.DeclaringType?.GetInterfaces()
544+
.Any(i=>i.TryGetGenericDefinition()==typeof(IDictionary<,>))istrue))
545+
{
546+
ci.del=new();
547+
ci.del.AddRange(mlist.Where(m=>!m.IsStatic));
548+
}
549+
elseif(name==nameof(IList<int>.RemoveAt)
550+
&&mlist.Any(m=>m.DeclaringType?.GetInterfaces()
551+
.Any(i=>i.TryGetGenericDefinition()==typeof(IList<>))istrue))
552+
{
553+
ci.del=new();
554+
ci.del.AddRange(mlist.Where(m=>!m.IsStatic));
555+
}
556+
541557
if(mlist.Any(OperatorMethod.IsOperatorMethod))
542558
{
543559
stringpyName=OperatorMethod.GetPyMethodName(name);
@@ -581,6 +597,7 @@ private static ClassInfo GetClassInfo(Type type, ClassBase impl)
581597
privateclassClassInfo
582598
{
583599
publicIndexer?indexer;
600+
publicMethodBinder?del;
584601
publicreadonlyDictionary<string,PyObject>members=new();
585602

586603
internalClassInfo()

‎src/runtime/MethodBinder.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ internal void AddMethod(MethodBase m)
5454
list.Add(m);
5555
}
5656

57+
internalvoidAddRange(IEnumerable<MethodBase>methods)
58+
{
59+
list.AddRange(methods.Select(m=>newMaybeMethodBase(m)));
60+
}
61+
5762
/// <summary>
5863
/// Given a sequence of MethodInfo and a sequence of types, return the
5964
/// MethodInfo that matches the signature represented by those types.

‎src/runtime/Types/ArrayObject.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,12 @@ public static NewReference mp_subscript(BorrowedReference ob, BorrowedReference
247247
/// </summary>
248248
publicstaticintmp_ass_subscript(BorrowedReferenceob,BorrowedReferenceidx,BorrowedReferencev)
249249
{
250+
if(v.IsNull)
251+
{
252+
Exceptions.RaiseTypeError("'System.Array' object does not support item deletion");
253+
return-1;
254+
}
255+
250256
varobj=(CLRObject)GetManagedObject(ob)!;
251257
varitems=(Array)obj.inst;
252258
TypeitemType=obj.inst.GetType().GetElementType();

‎src/runtime/Types/ClassBase.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ internal class ClassBase : ManagedType, IDeserializationCallback
2525
[NonSerialized]
2626
internalList<string>dotNetMembers=new();
2727
internalIndexer?indexer;
28+
internalMethodBinder?del;
2829
internalreadonlyDictionary<int,MethodObject>richcompare=new();
2930
internalMaybeTypetype;
3031

@@ -465,6 +466,11 @@ static int mp_ass_subscript_impl(BorrowedReference ob, BorrowedReference idx, Bo
465466
// with the index arg (method binders expect arg tuples).
466467
NewReferenceargsTuple=default;
467468

469+
if(v.IsNull)
470+
{
471+
returnDelImpl(ob,idx,cls);
472+
}
473+
468474
if(!Runtime.PyTuple_Check(idx))
469475
{
470476
argsTuple=Runtime.PyTuple_New(1);
@@ -501,6 +507,44 @@ static int mp_ass_subscript_impl(BorrowedReference ob, BorrowedReference idx, Bo
501507
returnresult.IsNull()?-1:0;
502508
}
503509

510+
/// Implements __delitem__ (del x[...]) for IList&lt;T&gt; and IDictionary&lt;TKey, TValue&gt;.
511+
privatestaticintDelImpl(BorrowedReferenceob,BorrowedReferenceidx,ClassBasecls)
512+
{
513+
if(cls.delisnull)
514+
{
515+
Exceptions.SetError(Exceptions.TypeError,"object does not support item deletion");
516+
return-1;
517+
}
518+
519+
if(Runtime.PyTuple_Check(idx))
520+
{
521+
Exceptions.SetError(Exceptions.TypeError,"multi-index deletion not supported");
522+
return-1;
523+
}
524+
525+
usingvarargsTuple=Runtime.PyTuple_New(1);
526+
Runtime.PyTuple_SetItem(argsTuple.Borrow(),0,idx);
527+
usingvarresult=cls.del.Invoke(ob,argsTuple.Borrow(),kw:null);
528+
if(result.IsNull())
529+
return-1;
530+
531+
if(Runtime.PyBool_CheckExact(result.Borrow()))
532+
{
533+
if(Runtime.PyObject_IsTrue(result.Borrow())!=0)
534+
return0;
535+
536+
Exceptions.SetError(Exceptions.KeyError,"key not found");
537+
return-1;
538+
}
539+
540+
if(!result.IsNone())
541+
{
542+
Exceptions.warn("unsupported return type for __delitem__",Exceptions.TypeError);
543+
}
544+
545+
return0;
546+
}
547+
504548
staticNewReferencetp_call_impl(BorrowedReferenceob,BorrowedReferenceargs,BorrowedReferencekw)
505549
{
506550
BorrowedReferencetp=Runtime.PyObject_TYPE(ob);

‎src/runtime/Util/ReflectionUtil.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,11 @@ public static BindingFlags GetBindingFlags(this PropertyInfo property)
5353
flags|=accessor.IsPublic?BindingFlags.Public:BindingFlags.NonPublic;
5454
returnflags;
5555
}
56+
57+
publicstaticType?TryGetGenericDefinition(thisTypetype)
58+
{
59+
if(typeisnull)thrownewArgumentNullException(nameof(type));
60+
61+
returntype.IsConstructedGenericType?type.GetGenericTypeDefinition():null;
62+
}
5663
}

‎tests/test_indexer.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,3 +668,39 @@ def test_public_inherited_overloaded_indexer():
668668

669669
withpytest.raises(TypeError):
670670
ob[[]]
671+
672+
deftest_del_indexer_dict():
673+
"""Test deleting indexers (__delitem__)."""
674+
fromSystem.Collections.GenericimportDictionary,KeyNotFoundException
675+
d=Dictionary[str,str]()
676+
d["delme"]="1"
677+
withpytest.raises(KeyError):
678+
deld["nonexistent"]
679+
deld["delme"]
680+
withpytest.raises(KeyError):
681+
deld["delme"]
682+
683+
deftest_del_indexer_list():
684+
"""Test deleting indexers (__delitem__)."""
685+
fromSystemimportArgumentOutOfRangeException
686+
fromSystem.Collections.GenericimportList
687+
l=List[str]()
688+
l.Add("1")
689+
withpytest.raises(ArgumentOutOfRangeException):
690+
dell[3]
691+
dell[0]
692+
assertlen(l)==0
693+
694+
deftest_del_indexer_array():
695+
"""Test deleting indexers (__delitem__)."""
696+
fromSystemimportArray
697+
l=Array[str](0)
698+
withpytest.raises(TypeError):
699+
dell[0]
700+
701+
deftest_del_indexer_absent():
702+
"""Test deleting indexers (__delitem__)."""
703+
fromSystemimportUri
704+
l=Uri("http://www.example.com")
705+
withpytest.raises(TypeError):
706+
dell[0]

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp