FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
pythonnet/src/runtime/constructorbinding.cs at drop-python2 · filmor/pythonnet · GitHub
filmor
/
pythonnet
Public
forked from
pythonnet/pythonnet
Notifications
You must be signed in to change notification settings
Fork
1
Star
1
Code
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
pythonnet
/
src
/
runtime
/
constructorbinding.cs
Copy path
More file actions
More file actions
Latest commit
History
History
History
237 lines (223 loc) · 9.96 KB
Breadcrumbs
pythonnet
/
src
/
runtime
/
constructorbinding.cs
Copy path
File metadata and controls
237 lines (223 loc) · 9.96 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
using
System
;
using
System
.
Reflection
;
namespace
Python
.
Runtime
{
/// <summary>
/// Implements a Python type that wraps a CLR ctor call. Constructor objects
/// support a .Overloads[] syntax to allow explicit ctor overload selection.
/// </summary>
/// <remarks>
/// ClassManager stores a ConstructorBinding instance in the class's __dict__['Overloads']
/// SomeType.Overloads[Type, ...] works like this:
/// 1) Python retrieves the Overloads attribute from this ClassObject's dictionary normally
/// and finds a non-null tp_descr_get slot which is called by the interpreter
/// and returns an IncRef()ed pyHandle to itself.
/// 2) The ConstructorBinding object handles the [] syntax in its mp_subscript by matching
/// the Type object parameters to a constructor overload using Type.GetConstructor()
/// [NOTE: I don't know why method overloads are not searched the same way.]
/// and creating the BoundContructor object which contains ContructorInfo object.
/// 3) In tp_call, if ctorInfo is not null, ctorBinder.InvokeRaw() is called.
/// </remarks>
internal
class
ConstructorBinding
:
ExtensionType
{
private
Type
type
;
// The managed Type being wrapped in a ClassObject
private
IntPtr
pyTypeHndl
;
// The python type tells GetInstHandle which Type to create.
private
ConstructorBinder
ctorBinder
;
private
IntPtr
repr
;
public
ConstructorBinding
(
Type
type
,
IntPtr
pyTypeHndl
,
ConstructorBinder
ctorBinder
)
{
this
.
type
=
type
;
Runtime
.
XIncref
(
pyTypeHndl
)
;
this
.
pyTypeHndl
=
pyTypeHndl
;
this
.
ctorBinder
=
ctorBinder
;
repr
=
IntPtr
.
Zero
;
}
/// <summary>
/// Descriptor __get__ implementation.
/// Implements a Python type that wraps a CLR ctor call that requires the use
/// of a .Overloads[pyTypeOrType...] syntax to allow explicit ctor overload
/// selection.
/// </summary>
/// <param name="op"> PyObject* to a Constructors wrapper </param>
/// <param name="instance">
/// the instance that the attribute was accessed through,
/// or None when the attribute is accessed through the owner
/// </param>
/// <param name="owner"> always the owner class </param>
/// <returns>
/// a CtorMapper (that borrows a reference to this python type and the
/// ClassObject's ConstructorBinder) wrapper.
/// </returns>
/// <remarks>
/// Python 2.6.5 docs:
/// object.__get__(self, instance, owner)
/// Called to get the attribute of the owner class (class attribute access)
/// or of an instance of that class (instance attribute access).
/// owner is always the owner class, while instance is the instance that
/// the attribute was accessed through, or None when the attribute is accessed through the owner.
/// This method should return the (computed) attribute value or raise an AttributeError exception.
/// </remarks>
public
static
IntPtr
tp_descr_get
(
IntPtr
op
,
IntPtr
instance
,
IntPtr
owner
)
{
var
self
=
(
ConstructorBinding
)
GetManagedObject
(
op
)
;
if
(
self
==
null
)
{
return
IntPtr
.
Zero
;
}
// It doesn't seem to matter if it's accessed through an instance (rather than via the type).
/*if (instance != IntPtr.Zero) {
// This is ugly! PyObject_IsInstance() returns 1 for true, 0 for false, -1 for error...
if (Runtime.PyObject_IsInstance(instance, owner) < 1) {
return Exceptions.RaiseTypeError("How in the world could that happen!");
}
}*/
Runtime
.
XIncref
(
self
.
pyHandle
)
;
return
self
.
pyHandle
;
}
/// <summary>
/// Implement explicit overload selection using subscript syntax ([]).
/// </summary>
/// <remarks>
/// ConstructorBinding.GetItem(PyObject *o, PyObject *key)
/// Return element of o corresponding to the object key or NULL on failure.
/// This is the equivalent of the Python expression o[key].
/// </remarks>
public
static
IntPtr
mp_subscript
(
IntPtr
op
,
IntPtr
key
)
{
var
self
=
(
ConstructorBinding
)
GetManagedObject
(
op
)
;
Type
[
]
types
=
Runtime
.
PythonArgsToTypeArray
(
key
)
;
if
(
types
==
null
)
{
return
Exceptions
.
RaiseTypeError
(
"type(s) expected"
)
;
}
//MethodBase[] methBaseArray = self.ctorBinder.GetMethods();
//MethodBase ci = MatchSignature(methBaseArray, types);
ConstructorInfo
ci
=
self
.
type
.
GetConstructor
(
types
)
;
if
(
ci
==
null
)
{
return
Exceptions
.
RaiseTypeError
(
"No match found for constructor signature"
)
;
}
var
boundCtor
=
new
BoundContructor
(
self
.
type
,
self
.
pyTypeHndl
,
self
.
ctorBinder
,
ci
)
;
return
boundCtor
.
pyHandle
;
}
/// <summary>
/// ConstructorBinding __repr__ implementation [borrowed from MethodObject].
/// </summary>
public
static
IntPtr
tp_repr
(
IntPtr
ob
)
{
var
self
=
(
ConstructorBinding
)
GetManagedObject
(
ob
)
;
if
(
self
.
repr
!=
IntPtr
.
Zero
)
{
Runtime
.
XIncref
(
self
.
repr
)
;
return
self
.
repr
;
}
MethodBase
[
]
methods
=
self
.
ctorBinder
.
GetMethods
(
)
;
string
name
=
self
.
type
.
FullName
;
var
doc
=
""
;
foreach
(
MethodBase
t
in
methods
)
{
if
(
doc
.
Length
>
0
)
{
doc
+=
"
\n
"
;
}
string
str
=
t
.
ToString
(
)
;
int
idx
=
str
.
IndexOf
(
"("
)
;
doc
+=
string
.
Format
(
"{0}{1}"
,
name
,
str
.
Substring
(
idx
)
)
;
}
self
.
repr
=
Runtime
.
PyString_FromString
(
doc
)
;
Runtime
.
XIncref
(
self
.
repr
)
;
return
self
.
repr
;
}
/// <summary>
/// ConstructorBinding dealloc implementation.
/// </summary>
public
new
static
void
tp_dealloc
(
IntPtr
ob
)
{
var
self
=
(
ConstructorBinding
)
GetManagedObject
(
ob
)
;
Runtime
.
XDecref
(
self
.
repr
)
;
Runtime
.
XDecref
(
self
.
pyTypeHndl
)
;
ExtensionType
.
FinalizeObject
(
self
)
;
}
}
/// <summary>
/// Implements a Python type that constructs the given Type given a particular ContructorInfo.
/// </summary>
/// <remarks>
/// Here mostly because I wanted a new __repr__ function for the selected constructor.
/// An earlier implementation hung the __call__ on the ContructorBinding class and
/// returned an Incref()ed self.pyHandle from the __get__ function.
/// </remarks>
internal
class
BoundContructor
:
ExtensionType
{
private
Type
type
;
// The managed Type being wrapped in a ClassObject
private
IntPtr
pyTypeHndl
;
// The python type tells GetInstHandle which Type to create.
private
ConstructorBinder
ctorBinder
;
private
ConstructorInfo
ctorInfo
;
private
IntPtr
repr
;
public
BoundContructor
(
Type
type
,
IntPtr
pyTypeHndl
,
ConstructorBinder
ctorBinder
,
ConstructorInfo
ci
)
{
this
.
type
=
type
;
Runtime
.
XIncref
(
pyTypeHndl
)
;
this
.
pyTypeHndl
=
pyTypeHndl
;
this
.
ctorBinder
=
ctorBinder
;
ctorInfo
=
ci
;
repr
=
IntPtr
.
Zero
;
}
/// <summary>
/// BoundContructor.__call__(PyObject *callable_object, PyObject *args, PyObject *kw)
/// </summary>
/// <param name="op"> PyObject *callable_object </param>
/// <param name="args"> PyObject *args </param>
/// <param name="kw"> PyObject *kw </param>
/// <returns> A reference to a new instance of the class by invoking the selected ctor(). </returns>
public
static
IntPtr
tp_call
(
IntPtr
op
,
IntPtr
args
,
IntPtr
kw
)
{
var
self
=
(
BoundContructor
)
GetManagedObject
(
op
)
;
// Even though a call with null ctorInfo just produces the old behavior
/*if (self.ctorInfo == null) {
string msg = "Usage: Class.Overloads[CLR_or_python_Type, ...]";
return Exceptions.RaiseTypeError(msg);
}*/
// Bind using ConstructorBinder.Bind and invoke the ctor providing a null instancePtr
// which will fire self.ctorInfo using ConstructorInfo.Invoke().
object
obj
=
self
.
ctorBinder
.
InvokeRaw
(
IntPtr
.
Zero
,
args
,
kw
,
self
.
ctorInfo
)
;
if
(
obj
==
null
)
{
// XXX set an error
return
IntPtr
.
Zero
;
}
// Instantiate the python object that wraps the result of the method call
// and return the PyObject* to it.
return
CLRObject
.
GetInstHandle
(
obj
,
self
.
pyTypeHndl
)
;
}
/// <summary>
/// BoundContructor __repr__ implementation [borrowed from MethodObject].
/// </summary>
public
static
IntPtr
tp_repr
(
IntPtr
ob
)
{
var
self
=
(
BoundContructor
)
GetManagedObject
(
ob
)
;
if
(
self
.
repr
!=
IntPtr
.
Zero
)
{
Runtime
.
XIncref
(
self
.
repr
)
;
return
self
.
repr
;
}
string
name
=
self
.
type
.
FullName
;
string
str
=
self
.
ctorInfo
.
ToString
(
)
;
int
idx
=
str
.
IndexOf
(
"("
)
;
str
=
string
.
Format
(
"returns a new {0}{1}"
,
name
,
str
.
Substring
(
idx
)
)
;
self
.
repr
=
Runtime
.
PyString_FromString
(
str
)
;
Runtime
.
XIncref
(
self
.
repr
)
;
return
self
.
repr
;
}
/// <summary>
/// ConstructorBinding dealloc implementation.
/// </summary>
public
new
static
void
tp_dealloc
(
IntPtr
ob
)
{
var
self
=
(
BoundContructor
)
GetManagedObject
(
ob
)
;
Runtime
.
XDecref
(
self
.
repr
)
;
Runtime
.
XDecref
(
self
.
pyTypeHndl
)
;
FinalizeObject
(
self
)
;
}
}
}
Back
|
FazBrowse Home
|
New Git URL