Skip to content

Commit f2dc8f1

Browse files
authored
Merge pull request #1400 from losttech/cleanup/21-02-25
ImportHook cleanup + PyObject.Length exception
2 parents 5bcd708 + 908316f commit f2dc8f1

File tree

5 files changed

+29
-36
lines changed

5 files changed

+29
-36
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ when .NET expects an integer [#1342][i1342]
3636
- BREAKING: Methods with `ref` or `out` parameters and void return type return a tuple of only the `ref` and `out` parameters.
3737
- BREAKING: to call Python from .NET `Runtime.PythonDLL` property must be set to Python DLL name
3838
or the DLL must be loaded in advance. This must be done before calling any other Python.NET functions.
39+
- BREAKING: `PyObject.Length()` now raises a `PythonException` when object does not support a concept of length.
3940
- Sign Runtime DLL with a strong name
4041
- Implement loading through `clr_loader` instead of the included `ClrModule`, enables
4142
support for .NET Core

src/embed_tests/pyimport.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ public void SetUp()
3434
TestContext.Out.WriteLine(testPath);
3535

3636
IntPtr str = Runtime.Runtime.PyString_FromString(testPath);
37+
Assert.IsFalse(str == IntPtr.Zero);
3738
BorrowedReference path = Runtime.Runtime.PySys_GetObject("path");
39+
Assert.IsFalse(path.IsNull);
3840
Runtime.Runtime.PyList_Append(path, str);
3941
Runtime.Runtime.XDecref(str);
4042
}

src/runtime/importhook.cs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ static void RestoreImport()
6161
{
6262
IntPtr builtins = Runtime.GetBuiltins();
6363

64+
IntPtr existing = Runtime.PyObject_GetAttr(builtins, PyIdentifier.__import__);
65+
Runtime.XDecref(existing);
66+
if (existing != hook.ptr)
67+
{
68+
throw new NotSupportedException("Unable to restore original __import__.");
69+
}
70+
6471
int res = Runtime.PyObject_SetAttr(builtins, PyIdentifier.__import__, py_import);
6572
PythonException.ThrowIfIsNotZero(res);
6673
Runtime.XDecref(py_import);
@@ -88,7 +95,7 @@ internal static unsafe void Initialize()
8895

8996
// both dicts are borrowed references
9097
BorrowedReference mod_dict = Runtime.PyModule_GetDict(ClrModuleReference);
91-
BorrowedReference clr_dict = *Runtime._PyObject_GetDictPtr(root.ObjectReference);
98+
using var clr_dict = Runtime.PyObject_GenericGetDict(root.ObjectReference);
9299

93100
Runtime.PyDict_Update(mod_dict, clr_dict);
94101
BorrowedReference dict = Runtime.PyImport_GetModuleDict();
@@ -150,8 +157,10 @@ public static unsafe NewReference GetCLRModule(BorrowedReference fromList = defa
150157
// update the module dictionary with the contents of the root dictionary
151158
root.LoadNames();
152159
BorrowedReference py_mod_dict = Runtime.PyModule_GetDict(ClrModuleReference);
153-
BorrowedReference clr_dict = *Runtime._PyObject_GetDictPtr(root.ObjectReference);
154-
Runtime.PyDict_Update(py_mod_dict, clr_dict);
160+
using (var clr_dict = Runtime.PyObject_GenericGetDict(root.ObjectReference))
161+
{
162+
Runtime.PyDict_Update(py_mod_dict, clr_dict);
163+
}
155164

156165
// find any items from the from list and get them from the root if they're not
157166
// already in the module dictionary
@@ -250,7 +259,6 @@ public static IntPtr __import__(IntPtr self, IntPtr argsRaw, IntPtr kw)
250259
}
251260

252261
string realname = mod_name;
253-
string clr_prefix = null;
254262

255263
// 2010-08-15: Always seemed smart to let python try first...
256264
// This shaves off a few tenths of a second on test_module.py
@@ -308,10 +316,7 @@ public static IntPtr __import__(IntPtr self, IntPtr argsRaw, IntPtr kw)
308316
}
309317
return new NewReference(module).DangerousMoveToPointer();
310318
}
311-
if (clr_prefix != null)
312-
{
313-
return GetCLRModule(fromList).DangerousMoveToPointerOrNull();
314-
}
319+
315320
module = Runtime.PyDict_GetItemString(modules, names[0]);
316321
return new NewReference(module, canBeNull: true).DangerousMoveToPointer();
317322
}
@@ -351,12 +356,6 @@ public static IntPtr __import__(IntPtr self, IntPtr argsRaw, IntPtr kw)
351356

352357
// Add the module to sys.modules
353358
Runtime.PyDict_SetItemString(modules, tail.moduleName, tail.ObjectReference);
354-
355-
// If imported from CLR add clr.<modulename> to sys.modules as well
356-
if (clr_prefix != null)
357-
{
358-
Runtime.PyDict_SetItemString(modules, clr_prefix + tail.moduleName, tail.ObjectReference);
359-
}
360359
}
361360

362361
{
@@ -374,6 +373,8 @@ public static IntPtr __import__(IntPtr self, IntPtr argsRaw, IntPtr kw)
374373

375374
private static bool IsLoadAll(BorrowedReference fromList)
376375
{
376+
if (fromList == null) throw new ArgumentNullException(nameof(fromList));
377+
377378
if (CLRModule.preload)
378379
{
379380
return false;

src/runtime/pyobject.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -615,19 +615,15 @@ public virtual void DelItem(int index)
615615

616616

617617
/// <summary>
618-
/// Length Method
619-
/// </summary>
620-
/// <remarks>
621618
/// Returns the length for objects that support the Python sequence
622-
/// protocol, or 0 if the object does not support the protocol.
623-
/// </remarks>
619+
/// protocol.
620+
/// </summary>
624621
public virtual long Length()
625622
{
626-
var s = Runtime.PyObject_Size(obj);
623+
var s = Runtime.PyObject_Size(Reference);
627624
if (s < 0)
628625
{
629-
Runtime.PyErr_Clear();
630-
return 0;
626+
throw new PythonException();
631627
}
632628
return s;
633629
}

src/runtime/runtime.cs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,13 +1121,7 @@ internal static int PyObject_Compare(IntPtr value1, IntPtr value2)
11211121

11221122
internal static int PyObject_Not(IntPtr pointer) => Delegates.PyObject_Not(pointer);
11231123

1124-
internal static long PyObject_Size(IntPtr pointer)
1125-
{
1126-
return (long)_PyObject_Size(pointer);
1127-
}
1128-
1129-
1130-
private static IntPtr _PyObject_Size(IntPtr pointer) => Delegates._PyObject_Size(pointer);
1124+
internal static nint PyObject_Size(BorrowedReference pointer) => Delegates.PyObject_Size(pointer);
11311125

11321126

11331127
internal static nint PyObject_Hash(IntPtr op) => Delegates.PyObject_Hash(op);
@@ -2028,9 +2022,8 @@ internal static IntPtr PyType_GenericAlloc(IntPtr type, long n)
20282022

20292023
internal static int PyObject_GenericSetAttr(IntPtr obj, IntPtr name, IntPtr value) => Delegates.PyObject_GenericSetAttr(obj, name, value);
20302024

2031-
2032-
internal static BorrowedReference* _PyObject_GetDictPtr(BorrowedReference obj) => Delegates._PyObject_GetDictPtr(obj);
2033-
2025+
internal static NewReference PyObject_GenericGetDict(BorrowedReference o) => PyObject_GenericGetDict(o, IntPtr.Zero);
2026+
internal static NewReference PyObject_GenericGetDict(BorrowedReference o, IntPtr context) => Delegates.PyObject_GenericGetDict(o, context);
20342027

20352028
internal static void PyObject_GC_Del(IntPtr tp) => Delegates.PyObject_GC_Del(tp);
20362029

@@ -2323,7 +2316,7 @@ static Delegates()
23232316
PyCallable_Check = (delegate* unmanaged[Cdecl]<IntPtr, int>)GetFunctionByName(nameof(PyCallable_Check), GetUnmanagedDll(_PythonDll));
23242317
PyObject_IsTrue = (delegate* unmanaged[Cdecl]<BorrowedReference, int>)GetFunctionByName(nameof(PyObject_IsTrue), GetUnmanagedDll(_PythonDll));
23252318
PyObject_Not = (delegate* unmanaged[Cdecl]<IntPtr, int>)GetFunctionByName(nameof(PyObject_Not), GetUnmanagedDll(_PythonDll));
2326-
_PyObject_Size = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr>)GetFunctionByName("PyObject_Size", GetUnmanagedDll(_PythonDll));
2319+
PyObject_Size = (delegate* unmanaged[Cdecl]<BorrowedReference, nint>)GetFunctionByName("PyObject_Size", GetUnmanagedDll(_PythonDll));
23272320
PyObject_Hash = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr>)GetFunctionByName(nameof(PyObject_Hash), GetUnmanagedDll(_PythonDll));
23282321
PyObject_Repr = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr>)GetFunctionByName(nameof(PyObject_Repr), GetUnmanagedDll(_PythonDll));
23292322
PyObject_Str = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr>)GetFunctionByName(nameof(PyObject_Str), GetUnmanagedDll(_PythonDll));
@@ -2478,8 +2471,8 @@ static Delegates()
24782471
PyType_Ready = (delegate* unmanaged[Cdecl]<IntPtr, int>)GetFunctionByName(nameof(PyType_Ready), GetUnmanagedDll(_PythonDll));
24792472
_PyType_Lookup = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr>)GetFunctionByName(nameof(_PyType_Lookup), GetUnmanagedDll(_PythonDll));
24802473
PyObject_GenericGetAttr = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr>)GetFunctionByName(nameof(PyObject_GenericGetAttr), GetUnmanagedDll(_PythonDll));
2474+
PyObject_GenericGetDict = (delegate* unmanaged[Cdecl]<BorrowedReference, IntPtr, NewReference>)GetFunctionByName(nameof(PyObject_GenericGetDict), GetUnmanagedDll(PythonDLL));
24812475
PyObject_GenericSetAttr = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr, int>)GetFunctionByName(nameof(PyObject_GenericSetAttr), GetUnmanagedDll(_PythonDll));
2482-
_PyObject_GetDictPtr = (delegate* unmanaged[Cdecl]<BorrowedReference, BorrowedReference*>)GetFunctionByName(nameof(_PyObject_GetDictPtr), GetUnmanagedDll(_PythonDll));
24832476
PyObject_GC_Del = (delegate* unmanaged[Cdecl]<IntPtr, void>)GetFunctionByName(nameof(PyObject_GC_Del), GetUnmanagedDll(_PythonDll));
24842477
PyObject_GC_Track = (delegate* unmanaged[Cdecl]<IntPtr, void>)GetFunctionByName(nameof(PyObject_GC_Track), GetUnmanagedDll(_PythonDll));
24852478
PyObject_GC_UnTrack = (delegate* unmanaged[Cdecl]<IntPtr, void>)GetFunctionByName(nameof(PyObject_GC_UnTrack), GetUnmanagedDll(_PythonDll));
@@ -2595,7 +2588,7 @@ static Delegates()
25952588
internal static delegate* unmanaged[Cdecl]<IntPtr, int> PyCallable_Check { get; }
25962589
internal static delegate* unmanaged[Cdecl]<BorrowedReference, int> PyObject_IsTrue { get; }
25972590
internal static delegate* unmanaged[Cdecl]<IntPtr, int> PyObject_Not { get; }
2598-
internal static delegate* unmanaged[Cdecl]<IntPtr, IntPtr> _PyObject_Size { get; }
2591+
internal static delegate* unmanaged[Cdecl]<BorrowedReference, nint> PyObject_Size { get; }
25992592
internal static delegate* unmanaged[Cdecl]<IntPtr, IntPtr> PyObject_Hash { get; }
26002593
internal static delegate* unmanaged[Cdecl]<IntPtr, IntPtr> PyObject_Repr { get; }
26012594
internal static delegate* unmanaged[Cdecl]<IntPtr, IntPtr> PyObject_Str { get; }
@@ -2744,7 +2737,6 @@ static Delegates()
27442737
internal static delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr> _PyType_Lookup { get; }
27452738
internal static delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr> PyObject_GenericGetAttr { get; }
27462739
internal static delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr, int> PyObject_GenericSetAttr { get; }
2747-
internal static delegate* unmanaged[Cdecl]<BorrowedReference, BorrowedReference*> _PyObject_GetDictPtr { get; }
27482740
internal static delegate* unmanaged[Cdecl]<IntPtr, void> PyObject_GC_Del { get; }
27492741
internal static delegate* unmanaged[Cdecl]<IntPtr, void> PyObject_GC_Track { get; }
27502742
internal static delegate* unmanaged[Cdecl]<IntPtr, void> PyObject_GC_UnTrack { get; }
@@ -2781,6 +2773,7 @@ static Delegates()
27812773
internal static delegate* unmanaged[Cdecl]<IntPtr, IntPtr, void> PyException_SetCause { get; }
27822774
internal static delegate* unmanaged[Cdecl]<uint, IntPtr, int> PyThreadState_SetAsyncExcLLP64 { get; }
27832775
internal static delegate* unmanaged[Cdecl]<ulong, IntPtr, int> PyThreadState_SetAsyncExcLP64 { get; }
2776+
internal static delegate* unmanaged[Cdecl]<BorrowedReference, IntPtr, NewReference> PyObject_GenericGetDict { get; }
27842777
}
27852778
}
27862779

0 commit comments

Comments
 (0)