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

Multiple fixes related to Dictionary.Keys bug#1786

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
lostmsu merged 5 commits intopythonnet:masterfromlosttech:bugs/KeyCollection
May 20, 2022
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletionsCHANGELOG.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,6 +21,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
- `__name__` and `__signature__` to reflected .NET methods
- .NET collection types now implement standard Python collection interfaces from `collections.abc`.
See [Mixins/collections.py](src/runtime/Mixins/collections.py).
- you can cast objects to generic .NET interfaces without specifying generic arguments as long as there is no ambiguity.
- .NET arrays implement Python buffer protocol
- Python integer interoperability with `System.Numerics.BigInteger`
- Python.NET will correctly resolve .NET methods, that accept `PyList`, `PyInt`,
Expand Down
2 changes: 1 addition & 1 deletionsrc/runtime/ClassManager.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -133,7 +133,7 @@ internal static void RestoreRuntimeData(ClassManagerState storage)
/// Return the ClassBase-derived instance that implements a particular
/// reflected managed type, creating it if it doesn't yet exist.
/// </summary>
internal staticReflectedClrType GetClass(Type type) => ReflectedClrType.GetOrCreate(type);
internal staticBorrowedReference GetClass(Type type) => ReflectedClrType.GetOrCreate(type);

internal static ClassBase GetClassImpl(Type type)
{
Expand Down
13 changes: 11 additions & 2 deletionssrc/runtime/Mixins/collections.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,11 @@

class IteratorMixin(col.Iterator):
def close(self):
self.Dispose()
if hasattr(self, 'Dispose'):
self.Dispose()
else:
from System import IDisposable
IDisposable(self).Dispose()

class IterableMixin(col.Iterable):
pass
Expand All@@ -16,7 +20,12 @@ class SizedMixin(col.Sized):
def __len__(self): return self.Count

class ContainerMixin(col.Container):
def __contains__(self, item): return self.Contains(item)
def __contains__(self, item):
if hasattr('self', 'Contains'):
return self.Contains(item)
else:
from System.Collections.Generic import ICollection
return ICollection(self).Contains(item)

try:
abc_Collection = col.Collection
Expand Down
17 changes: 17 additions & 0 deletionssrc/runtime/TypeManager.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -217,6 +217,23 @@ static void GetPythonTypeName(Type clrType, System.Text.StringBuilder target)
}

target.Append(']');

int nestedStart = fullName.IndexOf('+');
while (nestedStart >= 0)
{
target.Append('.');
int nextNested = fullName.IndexOf('+', nestedStart + 1);
if (nextNested < 0)
{
target.Append(fullName.Substring(nestedStart + 1));
}
else
{
target.Append(fullName.Substring(nestedStart + 1, length: nextNested - nestedStart - 1));
}
nestedStart = nextNested;
}

return;
}
}
Expand Down
2 changes: 1 addition & 1 deletionsrc/runtime/Types/ClassObject.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -236,7 +236,7 @@ public override NewReference type_subscript(BorrowedReference idx)
return Exceptions.RaiseTypeError("type expected");
}
Type a = t.MakeArrayType();
PyType o = ClassManager.GetClass(a);
BorrowedReference o = ClassManager.GetClass(a);
return new NewReference(o);
}

Expand Down
4 changes: 2 additions & 2 deletionssrc/runtime/Types/ClrObject.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,13 +43,13 @@ internal static NewReference GetReference(object ob, BorrowedReference pyType)

internal static NewReference GetReference(object ob, Type type)
{
PyType cc = ClassManager.GetClass(type);
BorrowedReference cc = ClassManager.GetClass(type);
return Create(ob, cc);
}

internal static NewReference GetReference(object ob)
{
PyType cc = ClassManager.GetClass(ob.GetType());
BorrowedReference cc = ClassManager.GetClass(ob.GetType());
return Create(ob, cc);
}

Expand Down
49 changes: 49 additions & 0 deletionssrc/runtime/Types/GenericType.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;

namespace Python.Runtime
{
Expand All@@ -20,10 +21,58 @@ internal GenericType(Type tp) : base(tp)
/// </summary>
public static NewReference tp_new(BorrowedReference tp, BorrowedReference args, BorrowedReference kw)
{
var self = (GenericType)GetManagedObject(tp)!;
if (!self.type.Valid)
{
return Exceptions.RaiseTypeError(self.type.DeletedMessage);
}
var type = self.type.Value;

if (type.IsInterface && !type.IsConstructedGenericType)
{
var nargs = Runtime.PyTuple_Size(args);
if (nargs == 1)
{
var instance = Runtime.PyTuple_GetItem(args, 0);
return AsGenericInterface(instance, type);
}
}

Exceptions.SetError(Exceptions.TypeError, "cannot instantiate an open generic type");

return default;
}

static NewReference AsGenericInterface(BorrowedReference instance, Type targetType)
{
if (GetManagedObject(instance) is not CLRObject obj)
{
return Exceptions.RaiseTypeError("only .NET objects can be cast to .NET interfaces");
}

Type[] supportedInterfaces = obj.inst.GetType().GetInterfaces();
Type[] constructedInterfaces = supportedInterfaces
.Where(i => i.IsConstructedGenericType && i.GetGenericTypeDefinition() == targetType)
.ToArray();

if (constructedInterfaces.Length == 1)
{
BorrowedReference pythonic = ClassManager.GetClass(constructedInterfaces[0]);
using var args = Runtime.PyTuple_New(1);
Runtime.PyTuple_SetItem(args.Borrow(), 0, instance);
return Runtime.PyObject_CallObject(pythonic, args.Borrow());
}

if (constructedInterfaces.Length > 1)
{
string interfaces = string.Join(", ", constructedInterfaces.Select(TypeManager.GetPythonTypeName));
return Exceptions.RaiseTypeError("Ambiguous cast to .NET interface. "
+ $"Object implements: {interfaces}");
}

return Exceptions.RaiseTypeError("object does not implement "
+ TypeManager.GetPythonTypeName(targetType));
}

/// <summary>
/// Implements __call__ for reflected generic types.
Expand Down
2 changes: 1 addition & 1 deletionsrc/runtime/Types/MethodObject.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -191,7 +191,7 @@ public static NewReference tp_descr_get(BorrowedReference ds, BorrowedReference
&& obj.inst is IPythonDerivedType
&& self.type.Value.IsInstanceOfType(obj.inst))
{
var basecls =ClassManager.GetClass(self.type.Value);
var basecls =ReflectedClrType.GetOrCreate(self.type.Value);
return new MethodBinding(self, new PyObject(ob), basecls).Alloc();
}

Expand Down
1 change: 1 addition & 0 deletionssrc/runtime/Types/ReflectedClrType.cs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,6 +12,7 @@ internal sealed class ReflectedClrType : PyType
{
private ReflectedClrType(StolenReference reference) : base(reference, prevalidated: true) { }
internal ReflectedClrType(ReflectedClrType original) : base(original, prevalidated: true) { }
internal ReflectedClrType(BorrowedReference original) : base(original) { }
ReflectedClrType(SerializationInfo info, StreamingContext context) : base(info, context) { }

internal ClassBase Impl => (ClassBase)ManagedType.GetManagedObject(this)!;
Expand Down
7 changes: 7 additions & 0 deletionstests/test_collection_mixins.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,3 +14,10 @@ def test_dict_items():
k,v = items[0]
assert k == 42
assert v == "a"

# regression test for https://github.com/pythonnet/pythonnet/issues/1785
def test_dict_in_keys():
d = C.Dictionary[str, int]()
d["a"] = 42
assert "a" in d.Keys
assert "b" not in d.Keys

[8]ページ先頭

©2009-2025 Movatter.jp