8000 merged method selections and fixes from the trunk · pythonnet/pythonnet@4e2a3bd · GitHub
[go: up one dir, main page]

Skip to content

Commit 4e2a3bd

Browse files
committed
merged method selections and fixes from the trunk
1 parent 804cd51 commit 4e2a3bd

15 files changed

+823
-11
lines changed

pythonnet/src/runtime/arrayobject.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,18 @@ internal override bool CanSubclass() {
2929
}
3030

3131
[CallConvCdecl()]
32-
public static IntPtr tp_new(IntPtr ob, IntPtr args, IntPtr kw) {
32+
public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) {
33+
ArrayObject self = GetManagedObject(tp) as ArrayObject;
34+
if (Runtime.PyTuple_Size(args) != 1) {
35+
return Exceptions.RaiseTypeError("array expects 1 argument");
36+
}
37+
IntPtr op = Runtime.PyTuple_GetItem(args, 0);
38+
Object result;
39+
40+
if (!Converter.ToManaged(op, self.type, out result, true)) {
41+
return IntPtr.Zero;
42+
}
43+
return CLRObject.GetInstHandle(result, tp);
3344
string message = "cannot instantiate array wrapper";
3445
return Exceptions.RaiseTypeError(message);
3546
}

pythonnet/src/runtime/classbase.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ public static int tp_init(IntPtr ob, IntPtr args, IntPtr kw) {
5050
return 0;
5151
}
5252

53+
54+
//====================================================================
55+
// Default implementation of [] semantics for reflected types.
56+
//====================================================================
57+
58+
public virtual IntPtr type_subscript(IntPtr ob, IntPtr idx) {
59+
return Exceptions.RaiseTypeError("unsubscriptable object");
60+
}
61+
62+
5363
//====================================================================
5464
// Standard comparison implementation for instances of reflected types.
5565
//====================================================================

pythonnet/src/runtime/classobject.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,32 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) {
126126
}
127127

128128

129+
//====================================================================
130+
// Implementation of [] semantics for reflected types. This mainly
131+
// exists to implement the Array[int] syntax for creating arrays.
132+
//====================================================================
133+
134+
public override IntPtr type_subscript(IntPtr ob, IntPtr idx) {
135+
if ((this.type) != typeof(Array)) {
136+
return Exceptions.RaiseTypeError("unsubscriptable object");
137+
}
138+
139+
if (Runtime.PyTuple_Check(idx)) {
140+
return Exceptions.RaiseTypeError("expected single type");
141+
}
142+
143+
ClassBase c = GetManagedObject(idx) as ClassBase;
144+
Type t = (c != null) ? c.type : Converter.GetTypeByAlias(idx);
145+
if (t == null) {
146+
return Exceptions.RaiseTypeError("type expected");
147+
}
148+
Array a = Array.CreateInstance(t, 0);
149+
c = ClassManager.GetClass(a.GetType());
150+
Runtime.Incref(c.pyHandle);
151+
return c.pyHandle;
152+
}
153+
154+
129155
//====================================================================
130156
// Implements __getitem__ for reflected classes and value types.
131157
//====================================================================

pythonnet/src/runtime/constructorbinder.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ internal ConstructorBinder () : base() {}
3333
// Python type to use when wrapping the result (may be a subclass).
3434
//====================================================================
3535

36-
internal object InvokeRaw(IntPtr inst, IntPtr args, IntPtr kw) {
36+
internal object InvokeRaw(IntPtr inst, IntPtr args, IntPtr kw) {
37+
return this.InvokeRaw(inst, args, kw, null);
38+
}
39+
40+
internal object InvokeRaw(IntPtr inst, IntPtr args, IntPtr kw,
41+
MethodBase info) {
3742
Binding binding = this.Bind(inst, args, kw);
3843
Object result;
3944

pythonnet/src/runtime/converter.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ private Converter() {}
2828
static NumberFormatInfo nfi;
2929
static Type objectType;
3030
static Type stringType;
31+
static Type doubleType;
3132
static Type int32Type;
3233
static Type int64Type;
3334
static Type flagsType;
@@ -40,12 +41,38 @@ static Converter () {
4041
stringType = typeof(String);
4142
int32Type = typeof(Int32);
4243
int64Type = typeof(Int64);
44+
doubleType = typeof(Double);
4345
flagsType = typeof(FlagsAttribute);
4446
boolType = typeof(Boolean);
4547
typeType = typeof(Type);
4648
}
4749

4850

51+
//====================================================================
52+
// Given a builtin Python type, return the corresponding CLR type.
53+
//====================================================================
54+
55+
internal static Type GetTypeByAlias(IntPtr op) {
56+
if ((op == Runtime.PyStringType) ||
57+
(op == Runtime.PyUnicodeType)) {
58+
return stringType;
59+
}
60+
else if (op == Runtime.PyIntType) {
61+
return int32Type;
62+
}
63+
else if (op == Runtime.PyLongType) {
64+
return int64Type;
65+
}
66+
else if (op == Runtime.PyFloatType) {
67+
return doubleType;
68+
}
69+
else if (op == Runtime.PyBoolType) {
70+
return boolType;
71+
}
72+
return null;
73+
}
74+
75+
4976
//====================================================================
5077
// Return a Python object for the given native object, converting
5178
// basic types (string, int, etc.) into equivalent Python objects.
@@ -177,7 +204,6 @@ internal static bool ToManaged(IntPtr value, Type type,
177204

178205
internal static bool ToManagedValue(IntPtr value, Type obType,
179206
out Object result, bool setError) {
180-
181207
// Common case: if the Python value is a wrapped managed object
182208
// instance, just return the wrapped object.
183209
ManagedType mt = ManagedType.GetManagedObject(value);
@@ -199,6 +225,12 @@ internal static bool ToManagedValue(IntPtr value, Type obType,
199225
mt = ManagedType.GetManagedObject(value);
200226
}
201227
}
228+
IntPtr c = Exceptions.UnwrapExceptionClass(value);
229+
if ((c != IntPtr.Zero) && (c != value)) {
230+
value = c;
231+
Runtime.Decref(c);
232+
mt = ManagedType.GetManagedObject(value);
233+
}
202234
}
203235
}
204236

@@ -601,6 +633,8 @@ static bool ToArray(IntPtr value, Type obType, out Object result,
601633

602634
Array items = Array.CreateInstance(elementType, size);
603635

636+
// XXX - is there a better way to unwrap this if it is a real
637+
// array?
604638
for (int i = 0; i < size; i++) {
605639
Object obj = null;
606640
IntPtr item = Runtime.PySequence_GetItem(value, i);

pythonnet/src/runtime/exceptions.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,23 @@ internal static IntPtr GetExceptionInstanceWrapper(IntPtr real) {
192192
return op;
193193
}
194194

195+
internal static IntPtr UnwrapExceptionClass(IntPtr op) {
196+
// In some cases its necessary to recognize an exception *class*,
197+
// and obtain the inner (wrapped) exception class. This method
198+
// returns the inner class if found, or a null pointer.
199+
200+
IntPtr d = Runtime.PyObject_GetAttrString(op, "__dict__");
201+
if (d == IntPtr.Zero) {
202+
Exceptions.Clear();
203+
return IntPtr.Zero;
204+
}
205+
IntPtr c = Runtime.PyDict_GetItemString(d, "_class");
206+
Runtime.Decref(d);
207+
if (c == IntPtr.Zero) {
208+
Exceptions.Clear();
209+
}
210+
return c;
211+
}
195212

196213

197214
/// <summary>

pythonnet/src/runtime/managedtype.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ internal static ManagedType GetManagedObject(IntPtr ob) {
4646
GCHandle gc = (GCHandle)op;
4747
return (ManagedType)gc.Target;
4848
}
49+
50+
// In certain situations, we need to recognize a wrapped
51+
// exception class and be willing to unwrap the class :(
52+
53+
if (Runtime.wrap_exceptions) {
54+
IntPtr e = Exceptions.UnwrapExceptionClass(ob);
55+
if ((e != IntPtr.Zero) && (e != ob)) {
56+
ManagedType m = GetManagedObject(e);
57+
Runtime.Decref(e);
58+
return m;
59+
}
60+
}
4961
}
5062
return null;
5163
}

pythonnet/src/runtime/metatype.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,20 @@ public static int tp_setattro(IntPtr tp, IntPtr name, IntPtr value) {
220220
return 0;
221221
}
222222

223+
//====================================================================
224+
// The metatype has to implement [] semantics for generic types, so
225+
// here we just delegate to the generic type def implementation. Its
226+
// own mp_subscript
227+
//====================================================================
228+
229+
[CallConvCdecl()]
230+
public static IntPtr mp_subscript(IntPtr tp, IntPtr idx) {
231+
ClassBase cb = GetManagedObject(tp) as ClassBase;
232+
if (cb != null) {
233+
return cb.type_subscript(tp, idx);
234+
}
235+
return Exceptions.RaiseTypeError("unsubscriptable object");
236+
}
223237

224238
//====================================================================
225239
// Dealloc implementation. This is called when a Python type generated

pythonnet/src/runtime/methodbinder.cs

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,60 @@ internal static int ArgPrecedence(Type t) {
114114
}
115115

116116

117+
internal static MethodInfo MatchByTypeSig(MethodInfo[] msig,
118+
IntPtr psig) {
119+
IntPtr args = psig;
120+
bool free = false;
121+
122+
if (!Runtime.PyTuple_Check(psig)) {
123+
args = Runtime.PyTuple_New(1);
124+
Runtime.Incref(psig);
125+
Runtime.PyTuple_SetItem(args, 0, psig);
126+
free = true;
127+
}
128+
129+
int plen = Runtime.PyTuple_Size(args);
130+
MethodInfo match = null;
131+
132+
// XXX: what about out args, etc.?
133+
134+
for (int i = 0; i < msig.Length; i++) {
135+
ParameterInfo[] pi = msig[i].GetParameters();
136+
if (pi.Length != plen) {
137+
continue;
138+
}
139+
bool matched = true;
140+
for (int n = 0; n < pi.Length; n++) {
141+
IntPtr p = Runtime.PyTuple_GetItem(args, n);
142+
if (p == IntPtr.Zero) {
143+
Exceptions.Clear();
144+
break;
145+
}
146+
ClassBase c = ManagedType.GetManagedObject(p) as ClassBase;
147+
Type t = (c != null) ? c.type :
148+
Converter.GetTypeByAlias(p);
149+
150+
if (t == null) {
151+
break;
152+
}
153+
if (t != pi[n].ParameterType) {
154+
matched = false;
155+
break;
156+
}
157+
}
158+
if (matched) {
159+
match = msig[i];
160+
break;
161+
}
162+
}
163+
164+
if (free) {
165+
Runtime.Decref(args);
166+
}
167+
168+
return match;
169+
}
170+
117171

118172
//====================================================================
119173
// Bind the given Python instance and arguments to a particular method
@@ -122,12 +176,26 @@ internal static int ArgPrecedence(Type t) {
122176
//====================================================================
123177

124178
internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw) {
179+
return this.Bind(inst, args, kw, null);
180+
}
181+
182+
internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw,
183+
MethodBase info) {
125184
// loop to find match, return invoker w/ or /wo error
185+
MethodBase[] _methods = null;
126186
int nargs = Runtime.PyTuple_Size(args);
127187
object arg;
128188

129-
MethodBase[] _methods = GetMethods();
130-
189+
if (info != null) {
190+
_methods = (MethodBase[])Array.CreateInstance(
191+
typeof(MethodBase), 1
192+
);
193+
_methods.SetValue(info, 0);
194+
}
195+
else {
196+
_methods = GetMethods();
197+
}
198+
131199
for (int i = 0; i < _methods.Length; i++) {
132200
MethodBase mi = _methods[i];
133201
ParameterInfo[] pi = mi.GetParameters();
@@ -171,9 +239,14 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw) {
171239
return null;
172240
}
173241

174-
175242
internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw) {
176-
Binding binding = this.Bind(inst, args, kw);
243+
return this.Invoke(inst, args, kw, null);
244+
245+
}
246+
247+
internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw,
248+
MethodBase info) {
249+
Binding binding = this.Bind(inst, args, kw, info);
177250
Object result;
178251

179252
if (binding == null) {

pythonnet/src/runtime/methodbinding.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// ==========================================================================
99

1010
using System;
11+
using System.Reflection;
1112

1213
namespace Python.Runtime {
1314

@@ -19,16 +20,38 @@ namespace Python.Runtime {
1920

2021
internal class MethodBinding : ExtensionType {
2122

23+
MethodInfo info;
2224
MethodObject m;
2325
IntPtr target;
2426

2527
public MethodBinding(MethodObject m, IntPtr target) : base() {
2628
Runtime.Incref(target);
2729
this.target = target;
30+
this.info = null;
2831
this.m = m;
2932
}
3033

3134

35+
//====================================================================
36+
// Implement explicit overload selection using subscript syntax ([]).
37+
//====================================================================
38+
39+
[CallConvCdecl()]
40+
public static IntPtr mp_subscript(IntPtr tp, IntPtr idx) {
41+
MethodBinding self = (MethodBinding)GetManagedObject(tp);
42+
MethodInfo sig = MethodBinder.MatchByTypeSig(self.m.info, idx);
43+
if (sig == null) {
44+
return Exceptions.RaiseTypeError(
45+
"No match found for signature"
46+
);
47+
}
48+
MethodBinding mb = new MethodBinding(self.m, self.target);
49+
mb.info = sig;
50+
Runtime.Incref(mb.pyHandle);
51+
return mb.pyHandle;
52+
}
53+
54+
3255
//====================================================================
3356
// MethodBinding __getattribute__ implementation.
3457
//====================================================================
@@ -77,12 +100,13 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) {
77100
IntPtr uargs = Runtime.PyTuple_GetSlice(args, 1, len);
78101
IntPtr inst = Runtime.PyTuple_GetItem(args, 0);
79102
Runtime.Incref(inst);
80-
IntPtr r = self.m.Invoke(inst, uargs, kw);
103+
IntPtr r = self.m.Invoke(inst, uargs, kw, self.info);
81104
Runtime.Decref(inst);
105+
Runtime.Decref(uargs);
82106
return r;
83107
}
84108

85-
return self.m.Invoke(self.target, args, kw);
109+
return self.m.Invoke(self.target, args, kw, self.info);
86110
}
87111

88112

0 commit comments

Comments
 (0)
0