8000 merge latest master · pythonnet/pythonnet@67bd1c2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 67bd1c2

Browse files
committed
merge latest master
2 parents 6679d1c + 21169db commit 67bd1c2

35 files changed

+548
-765
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jobs:
66
build-test:
77
name: Build and Test
88
runs-on: ${{ matrix.os }}-latest
9-
timeout-minutes: 5
9+
timeout-minutes: 7
1010

1111
strategy:
1212
fail-fast: false

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ build-backend = "setuptools.build_meta"
55
[tool.pytest.ini_options]
66
xfail_strict = true
77
testpaths = [
8-
"tests",
8+
"tests"
99
]

pythonnet.sln

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.Test", "src\testing\
1212
EndProject
1313
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.PerformanceTests", "src\perf_tests\Python.PerformanceTests.csproj", "{4F2EA4A1-7ECA-48B5-8077-7A3C366F9931}"
1414
EndProject
15-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.DomainReloadTests", "src\domain_tests\Python.DomainReloadTests.csproj", "{F2FB6DA3-318E-4F30-9A1F-932C667E38C5}"
15+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Python.DomainReloadTests", "tests\domain_tests\Python.DomainReloadTests.csproj", "{F2FB6DA3-318E-4F30-9A1F-932C667E38C5}"
1616
EndProject
1717
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repo", "Repo", "{441A0123-F4C6-4EE4-9AEE-315FD79BE2D5}"
1818
ProjectSection(SolutionItems) = preProject

pythonnet/__init__.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ def load():
2929
if _LOADED:
3030
return
3131

32-
from .find_libpython import linked_libpython
3332
from os.path import join, dirname
3433

3534
if _RUNTIME is None:
@@ -38,21 +37,11 @@ def load():
3837
set_default_runtime()
3938

4039
dll_path = join(dirname(__file__), "runtime", "Python.Runtime.dll")
41-
libpython = linked_libpython()
42-
43-
if libpython and _FFI is None and sys.platform != "win32":
44-
# Load and leak libpython handle s.t. the .NET runtime doesn't dlcloses
45-
# it
46-
import posix
47-
48-
import cffi
49-
_FFI = cffi.FFI()
50-
_FFI.dlopen(libpython, posix.RTLD_NODELETE | posix.RTLD_LOCAL)
51-
40+
5241
_LOADER_ASSEMBLY = _RUNTIME.get_assembly(dll_path)
5342

5443
func = _LOADER_ASSEMBLY["Python.Runtime.Loader.Initialize"]
55-
if func(f"{libpython or ''}".encode("utf8")) != 0:
44+
if func(''.encode("utf8")) != 0:
5645
raise RuntimeError("Failed to initialize Python.Runtime.dll")
5746

5847
import atexit

src/domain_tests/conftest.py

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/embed_tests/TestPyType.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Runtime.InteropServices;
12
using System.Text;
23

34
using NUnit.Framework;
@@ -30,7 +31,7 @@ public void CanCreateHeapType()
3031
using var doc = new StrPtr(docStr, Encoding.UTF8);
3132
var spec = new TypeSpec(
3233
name: name,
33-
basicSize: ObjectOffset.Size(Runtime.Runtime.PyTypeType),
34+
basicSize: Marshal.ReadInt32(Runtime.Runtime.PyBaseObjectType, TypeOffset.tp_basicsize),
3435
slots: new TypeSpec.Slot[] {
3536
new (TypeSlotID.tp_doc, doc.RawPointer),
3637
},

src/embed_tests/TestRuntime.cs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Collections.Generic;
33
using NUnit.Framework;
44
using Python.Runtime;
5-
using Python.Runtime.Platform;
65

76
namespace Python.EmbeddingTest
87
{
@@ -92,27 +91,29 @@ public static void PyCheck_Iter_PyObject_IsIterable_ThreadingLock_Test()
9291
{
9392
Runtime.Runtime.Py_Initialize();
9493

95-
// Create an instance of threading.Lock, which is one of the very few types that does not have the
96-
// TypeFlags.HaveIter set in Python 2. This tests a different code path in PyObject_IsIterable and PyIter_Check.
97-
var threading = Runtime.Runtime.PyImport_ImportModule("threading");
98-
Exceptions.ErrorCheck(threading);
99-
var threadingDict = Runtime.Runtime.PyModule_GetDict(threading);
100-
Exceptions.ErrorCheck(threadingDict);
101-
var lockType = Runtime.Runtime.PyDict_GetItemString(threadingDict, "Lock");
102-
if (lockType.IsNull)
103-
throw new KeyNotFoundException("class 'Lock' was not found in 'threading'");
104-
105-
var args = Runtime.Runtime.PyTuple_New(0);
106-
var lockInstance = Runtime.Runtime.PyObject_CallObject(lockType.DangerousGetAddress(), args);
107-
Runtime.Runtime.XDecref(args);
108-
Exceptions.ErrorCheck(lockInstance);
109-
110-
Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(lockInstance));
111-
Assert.IsFalse(Runtime.Runtime.PyIter_Check(lockInstance));
112-
113-
threading.Dispose();
114-
115-
Runtime.Runtime.Py_Finalize();
94+
try
95+
{
96+
// Create an instance of threading.Lock, which is one of the very few types that does not have the
97+
// TypeFlags.HaveIter set in Python 2. This tests a different code path in PyObject_IsIterable and PyIter_Check.
98+
using var threading = Runtime.Runtime.PyImport_ImportModule("threading");
99+
Exceptions.ErrorCheck(threading);
100+
var threadingDict = Runtime.Runtime.PyModule_GetDict(threading);
101+
Exceptions.ErrorCheck(threadingDict);
102+
var lockType = Runtime.Runtime.PyDict_GetItemString(threadingDict, "Lock");
103+
if (lockType.IsNull)
104+
throw PythonException.ThrowLastAsClrException();
105+
106+
using var args = NewReference.DangerousFromPointer(Runtime.Runtime.PyTuple_New(0));
107+
using var lockInstance = Runtime.Runtime.PyObject_CallObject(lockType, args);
108+
Exceptions.ErrorCheck(lockInstance);
109+
110+
Assert.IsFalse(Runtime.Runtime.PyObject_IsIterable(lockInstance));
111+
Assert.IsFalse(Runtime.Runtime.PyIter_Check(lockInstance));
112+
}
113+
finally
114+
{
115+
Runtime.Runtime.Py_Finalize();
116+
}
116117
}
117118
}
118119
}

src/runtime/classbase.cs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4-
using System.Diagnostics;
5-
using System.Runtime.InteropServices;
6-
using System.Runtime.Serialization;
74

85
namespace Python.Runtime
96
{
@@ -355,26 +352,28 @@ public static void tp_dealloc(IntPtr ob)
355352
{
356353
ManagedType self = GetManagedObject(ob);
357354
tp_clear(ob);
358-
Runtime.PyObject_GC_UnTrack(self.pyHandle);
359-
Runtime.PyObject_GC_Del(self.pyHandle);
360-
self.FreeGCHandle();
355+
Runtime.PyObject_GC_UnTrack(ob);
356+
Runtime.PyObject_GC_Del(ob);
357+
self?.FreeGCHandle();
361358
}
362359

363360
public static int tp_clear(IntPtr ob)
364361
{
365362
ManagedType self = GetManagedObject(ob);
366-
if (!self.IsTypeObject())
363+
364+
bool isTypeObject = Runtime.PyObject_TYPE(ob) == Runtime.PyCLRMetaType;
365+
if (!isTypeObject)
367366
{
368367
ClearObjectDict(ob);
369368
}
370-
self.tpHandle = IntPtr.Zero;
369+
if (self is not null) self.tpHandle = IntPtr.Zero;
371370
return 0;
372371
}
373372

374373
protected override void OnSave(InterDomainContext context)
375374
{
376375
base.OnSave(context);
377-
if (pyHandle != tpHandle)
376+
if (!this.IsClrMetaTypeInstance())
378377
{
379378
IntPtr dict = GetObjectDict(pyHandle);
380379
Runtime.XIncref(dict);
@@ -385,13 +384,13 @@ protected override void OnSave(InterDomainContext context)
385384
protected override void OnLoad(InterDomainContext context)
386385
{
387386
base.OnLoad(context);
388-
if (pyHandle != tpHandle)
387+
if (!this.IsClrMetaTypeInstance())
389388
{
390389
IntPtr dict = context.Storage.GetValue<IntPtr>("dict");
391390
SetObjectDict(pyHandle, dict);
392391
}
393392
gcHandle = AllocGCHandle();
394-
Marshal.WriteIntPtr(pyHandle, TypeOffset.magic(), (IntPtr)gcHandle);
393+
SetGCHandle(ObjectReference, gcHandle);
395394
}
396395

397396

src/runtime/classderived.cs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics;
34
using System.Linq;
45
using System.Reflection;
56
using System.Reflection.Emit;
@@ -75,8 +76,8 @@ internal ClassDerivedObject(Type tp) : base(tp)
7576
// So we don't call PyObject_GC_Del here and instead we set the python
7677
// reference to a weak reference so that the C# object can be collected.
7778
GCHandle gc = GCHandle.Alloc(self, GCHandleType.Weak);
78-
int gcOffset = ObjectOffset.magic(Runtime.PyObject_TYPE(self.pyHandle));
79-
Marshal.WriteIntPtr(self.pyHandle, gcOffset, (IntPtr)gc);
79+
Debug.Assert(self.TypeReference == Runtime.PyObject_TYPE(self.ObjectReference));
80+
SetGCHandle(self.ObjectReference, self.TypeReference, gc);
8081
self.gcHandle.Free();
8182
self.gcHandle = gc;
8283
}
@@ -101,12 +102,9 @@ internal static IntPtr ToPython(IPythonDerivedType obj)
101102
// collected while Python still has a reference to it.
102103
if (Runtime.Refcount(self.pyHandle) == 1)
103104
{
104-
105-
#if PYTHON_WITH_PYDEBUG
106-
Runtime._Py_NewReference(self.pyHandle);
107-
#endif
105+
Runtime._Py_NewReference(self.ObjectReference);
108106
GCHandle gc = GCHandle.Alloc(self, GCHandleType.Normal);
109-
Marshal.WriteIntPtr(self.pyHandle, ObjectOffset.magic(self.tpHandle), (IntPtr)gc);
107+
SetGCHandle(self.ObjectReference, self.TypeReference, gc);
110108
self.gcHandle.Free();
111109
self.gcHandle = gc;
112110

@@ -124,11 +122,13 @@ internal static IntPtr ToPython(IPythonDerivedType obj)
124122
/// </summary>
125123
internal static Type CreateDerivedType(string name,
126124
Type baseType,
127-
IntPtr py_dict,
125+
BorrowedReference dictRef,
128126
string namespaceStr,
129127
string assemblyName,
130128
string moduleName = "Python.Runtime.Dynamic.dll")
131129
{
130+
// TODO: clean up
131+
IntPtr py_dict = dictRef.DangerousGetAddress();
132132
if (null != namespaceStr)
133133
{
134134
name = namespaceStr + "." + name;
@@ -826,7 +826,7 @@ public static void InvokeCtor(IPythonDerivedType obj, string origCtorName, objec
826826
try
827827
{
828828
// create the python object
829-
IntPtr type = TypeManager.GetTypeHandle(obj.GetType());
829+
BorrowedReference type = TypeManager.GetTypeReference(obj.GetType());
830830
self = new CLRObject(obj, type);
831831

832832
// set __pyobj__ to self and deref the python object which will allow this
@@ -883,11 +883,6 @@ public static void Finalize(IPythonDerivedType obj)
883883
// the C# object is being destroyed which must mean there are no more
884884
// references to the Python object as well so now we can dealloc the
885885
// python object.
886-
IntPtr dict = Marshal.ReadIntPtr(self.pyHandle, ObjectOffset.TypeDictOffset(self.tpHandle));
887-
if (dict != IntPtr.Zero)
888-
{
889-
Runtime.XDecref(dict);
890-
}
891886
Runtime.PyObject_GC_Del(self.pyHandle);
892887
self.gcHandle.Free();
893888
}

src/runtime/classmanager.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ internal static void SaveRuntimeData(RuntimeDataStorage storage)
117117
// Python object's dictionary tool; thus raising an AttributeError
118118
// instead of a TypeError.
119119
// Classes are re-initialized on in RestoreRuntimeData.
120-
var dict = new BorrowedReference(Marshal.ReadIntPtr(cls.Value.tpHandle, TypeOffset.tp_dict));
120+
using var dict = Runtime.PyObject_GenericGetDict(cls.Value.TypeReference);
121121
foreach (var member in cls.Value.dotNetMembers)
122122
{
123123
// No need to decref the member, the ClassBase instance does
@@ -135,7 +135,7 @@ internal static void SaveRuntimeData(RuntimeDataStorage storage)
135135
}
136136
}
137137
// We modified the Type object, notify it we did.
138-
Runtime.PyType_Modified(cls.Value.tpHandle);
138+
Runtime.PyType_Modified(cls.Value.TypeReference);
139139
}
140140
}
141141

@@ -155,7 +155,7 @@ internal static Dictionary<ManagedType, InterDomainContext> RestoreRuntimeData(R
155155
// re-init the class
156156
InitClassBase(pair.Key.Value, pair.Value);
157157
// We modified the Type object, notify it we did.
158-
Runtime.PyType_Modified(pair.Value.tpHandle);
158+
Runtime.PyType_Modified(pair.Value.TypeReference);
159159
var context = contexts[pair.Value.pyHandle];
160160
pair.Value.Load(context);
161161
loadedObjs.Add(pair.Value, context);
@@ -266,10 +266,10 @@ private static void InitClassBase(Type type, ClassBase impl)
266266
// point to the managed methods providing the implementation.
267267

268268

269-
IntPtr tp = TypeManager.GetTypeHandle(impl, type);
269+
var pyType = TypeManager.GetType(impl, type);
270270

271271
// Finally, initialize the class __dict__ and return the object.
272-
var dict = new BorrowedReference(Marshal.ReadIntPtr(tp, TypeOffset.tp_dict));
272+
using var dict = Runtime.PyObject_GenericGetDict(pyType.Reference);
273273

274274

275275
if (impl.dotNetMembers == null)
@@ -312,7 +312,7 @@ private static void InitClassBase(Type type, ClassBase impl)
312312
// Implement Overloads on the class object
313313
if (!CLRModule._SuppressOverloads)
314314
{
315-
var ctors = new ConstructorBinding(type, tp, co.binder);
315+
var ctors = new ConstructorBinding(type, pyType, co.binder);
316316
// ExtensionType types are untracked, so don't Incref() them.
317317
// TODO: deprecate __overloads__ soon...
318318
Runtime.PyDict_SetItem(dict, PyIdentifier.__overloads__, ctors.ObjectReference);
@@ -332,7 +332,7 @@ private static void InitClassBase(Type type, ClassBase impl)
332332

333333
// The type has been modified after PyType_Ready has been called
334334
// Refresh the type
335-
Runtime.PyType_Modified(tp);
335+
Runtime.PyType_Modified(pyType.Reference);
336336
}
337337

338338
internal static bool ShouldBindMethod(MethodBase mb)

src/runtime/clrobject.cs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,20 @@ internal CLRObject(object ob, IntPtr tp)
1414
System.Diagnostics.Debug.Assert(tp != IntPtr.Zero);
1515
IntPtr py = Runtime.PyType_GenericAlloc(tp, 0);
16 741A 16

17-
var flags = (TypeFlags)Util.ReadCLong(tp, TypeOffset.tp_flags);
18-
if ((flags & TypeFlags.Subclass) != 0)
19-
{
20-
IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.TypeDictOffset(tp));
21-
if (dict == IntPtr.Zero)
22-
{
23-
dict = Runtime.PyDict_New();
24-
Marshal.WriteIntPtr(py, ObjectOffset.TypeDictOffset(tp), dict);
25-
}
26-
}
27-
28-
GCHandle gc = AllocGCHandle(TrackTypes.Wrapper);
29-
Marshal.WriteIntPtr(py, ObjectOffset.magic(tp), (IntPtr)gc);
3017
tpHandle = tp;
3118
pyHandle = py;
3219
inst = ob;
3320

21+
GCHandle gc = AllocGCHandle(TrackTypes.Wrapper);
22+
InitGCHandle(ObjectReference, type: TypeReference, gc);
23+
3424
// Fix the BaseException args (and __cause__ in case of Python 3)
3525
// slot if wrapping a CLR exception
36-
Exceptions.SetArgsAndCause(ObjectReference);
26+
if (ob is Exception e) Exceptions.SetArgsAndCause(ObjectReference, e);
3727
}
3828

29+
internal CLRObject(object ob, BorrowedReference tp) : this(ob, tp.DangerousGetAddress()) { }
30+
3931
protected CLRObject()
4032
{
4133
}
@@ -104,7 +96,7 @@ protected override void OnLoad(InterDomainContext context)
10496
{
10597
base.OnLoad(context);
10698
GCHandle gc = AllocGCHandle(TrackTypes.Wrapper);
107-
Marshal.WriteIntPtr(pyHandle, ObjectOffset.magic(tpHandle), (IntPtr)gc);
99+
SetGCHandle(ObjectReference, TypeReference, gc);
108100
}
109101
}
110102
}

0 commit comments

Comments
 (0)
0