From 2910800eb6f04fbe1fc70645b8c1820e6e192369 Mon Sep 17 00:00:00 2001 From: Victor Nova Date: Fri, 6 May 2022 23:59:33 -0700 Subject: [PATCH 1/5] type name generator ignored names of nested classes --- src/runtime/TypeManager.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/runtime/TypeManager.cs b/src/runtime/TypeManager.cs index d9ca184f6..217b4820e 100644 --- a/src/runtime/TypeManager.cs +++ b/src/runtime/TypeManager.cs @@ -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; } } From cf8823fa941842cfd19ad808f04bc6aa6d0b7970 Mon Sep 17 00:00:00 2001 From: Victor Nova Date: Sat, 7 May 2022 10:03:50 -0700 Subject: [PATCH 2/5] added regression test for "in Dictionary.Keys" check --- tests/test_collection_mixins.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/test_collection_mixins.py b/tests/test_collection_mixins.py index 2f74e93ab..0ac040038 100644 --- a/tests/test_collection_mixins.py +++ b/tests/test_collection_mixins.py @@ -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 From f48d7a96f76cf1e44411c3d19ad036e96b9adaf0 Mon Sep 17 00:00:00 2001 From: Victor Nova Date: Sat, 7 May 2022 10:05:36 -0700 Subject: [PATCH 3/5] ClassGeneric.GetClass now returns BorrowedReference to indicate that the value should not be disposed --- src/runtime/ClassManager.cs | 2 +- src/runtime/Types/ClassObject.cs | 2 +- src/runtime/Types/ClrObject.cs | 4 ++-- src/runtime/Types/MethodObject.cs | 2 +- src/runtime/Types/ReflectedClrType.cs | 1 + 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/runtime/ClassManager.cs b/src/runtime/ClassManager.cs index 6379f51de..6c5558f3a 100644 --- a/src/runtime/ClassManager.cs +++ b/src/runtime/ClassManager.cs @@ -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. /// - internal static ReflectedClrType GetClass(Type type) => ReflectedClrType.GetOrCreate(type); + internal static BorrowedReference GetClass(Type type) => ReflectedClrType.GetOrCreate(type); internal static ClassBase GetClassImpl(Type type) { diff --git a/src/runtime/Types/ClassObject.cs b/src/runtime/Types/ClassObject.cs index 04613afa5..474e9dd7b 100644 --- a/src/runtime/Types/ClassObject.cs +++ b/src/runtime/Types/ClassObject.cs @@ -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); } diff --git a/src/runtime/Types/ClrObject.cs b/src/runtime/Types/ClrObject.cs index db6e99121..4cf9062cb 100644 --- a/src/runtime/Types/ClrObject.cs +++ b/src/runtime/Types/ClrObject.cs @@ -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); } diff --git a/src/runtime/Types/MethodObject.cs b/src/runtime/Types/MethodObject.cs index 0bdd11ac2..55ad06e2d 100644 --- a/src/runtime/Types/MethodObject.cs +++ b/src/runtime/Types/MethodObject.cs @@ -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(); } diff --git a/src/runtime/Types/ReflectedClrType.cs b/src/runtime/Types/ReflectedClrType.cs index 15ea5c2b2..2e8f95924 100644 --- a/src/runtime/Types/ReflectedClrType.cs +++ b/src/runtime/Types/ReflectedClrType.cs @@ -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)!; From 537ddf4b7fc938bca461b1ffb532a136af7b7d67 Mon Sep 17 00:00:00 2001 From: Victor Nova Date: Sat, 7 May 2022 10:15:16 -0700 Subject: [PATCH 4/5] allow casting objects to generic .NET interfaces without specifying generic arguments as long as there is no ambiguity --- CHANGELOG.md | 1 + src/runtime/Types/GenericType.cs | 49 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea0f1f7bb..afd2f58c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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`, diff --git a/src/runtime/Types/GenericType.cs b/src/runtime/Types/GenericType.cs index 6b537931e..380ca8875 100644 --- a/src/runtime/Types/GenericType.cs +++ b/src/runtime/Types/GenericType.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; namespace Python.Runtime { @@ -20,10 +21,58 @@ internal GenericType(Type tp) : base(tp) /// 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)); + } /// /// Implements __call__ for reflected generic types. From d8543321a32535b90789770219f0d7c1ff0265de Mon Sep 17 00:00:00 2001 From: Victor Nova Date: Sat, 7 May 2022 10:16:43 -0700 Subject: [PATCH 5/5] a few collection mixins now properly handle private interface implementations fixes https://github.com/pythonnet/pythonnet/issues/1785 --- src/runtime/Mixins/collections.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/runtime/Mixins/collections.py b/src/runtime/Mixins/collections.py index a82032472..3203ad96f 100644 --- a/src/runtime/Mixins/collections.py +++ b/src/runtime/Mixins/collections.py @@ -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 @@ -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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy