Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit187b5dd

Browse files
committed
implemented __signature__ and __name__ on methodbinding
1 parentf64194c commit187b5dd

File tree

7 files changed

+137
-5
lines changed

7 files changed

+137
-5
lines changed

‎CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
1515
- Ability to implement delegates with`ref` and`out` parameters in Python, by returning the modified parameter values in a tuple. ([#1355][i1355])
1616
-`PyType` - a wrapper for Python type objects, that also permits creating new heap types from`TypeSpec`
1717
- Improved exception handling:
18-
- exceptions can now be converted with codecs
19-
-`InnerException` and`__cause__` are propagated properly
18+
* exceptions can now be converted with codecs
19+
*`InnerException` and`__cause__` are propagated properly
20+
-`__name__` and`__signature__` to reflected .NET methods
2021
- .NET collection types now implement standard Python collection interfaces from`collections.abc`.
2122
See[Mixins/collections.py](src/runtime/Mixins/collections.py).
2223
- .NET arrays implement Python buffer protocol

‎src/embed_tests/Inspect.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,30 @@ public void InstancePropertiesVisibleOnClass()
3030
varpyProp=(PropertyObject)ManagedType.GetManagedObject(property.Reference);
3131
Assert.AreEqual(nameof(Uri.AbsoluteUri),pyProp.info.Value.Name);
3232
}
33+
34+
[Test]
35+
publicvoidBoundMethodsAreInspectable()
36+
{
37+
usingvarscope=Py.CreateScope();
38+
try
39+
{
40+
scope.Import("inspect");
41+
}
42+
catch(PythonException)
43+
{
44+
Assert.Inconclusive("Python build does not include inspect module");
45+
return;
46+
}
47+
48+
varobj=newClass();
49+
scope.Set(nameof(obj),obj);
50+
usingvarspec=scope.Eval($"inspect.getfullargspec({nameof(obj)}.{nameof(Class.Method)})");
51+
}
52+
53+
classClass
54+
{
55+
publicvoidMethod(inta,intb=10){}
56+
publicvoidMethod(inta,objectb){}
57+
}
3358
}
3459
}

‎src/runtime/exceptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ public static variables on the Exceptions class filled in from
420420
publicstaticIntPtrIOError;
421421
publicstaticIntPtrOSError;
422422
publicstaticIntPtrImportError;
423+
publicstaticIntPtrModuleNotFoundError;
423424
publicstaticIntPtrIndexError;
424425
publicstaticIntPtrKeyError;
425426
publicstaticIntPtrKeyboardInterrupt;

‎src/runtime/methodbinding.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
usingSystem;
22
usingSystem.Collections.Generic;
3+
usingSystem.Linq;
34
usingSystem.Reflection;
45

56
namespacePython.Runtime
@@ -65,6 +66,65 @@ public static IntPtr mp_subscript(IntPtr tp, IntPtr idx)
6566
returnmb.pyHandle;
6667
}
6768

69+
PyObjectSignature
70+
{
71+
get
72+
{
73+
varinfos=this.info.Valid?new[]{this.info.Value}:this.m.info;
74+
Typetype=infos.Select(i=>i.DeclaringType)
75+
.OrderByDescending(t=>t,newTypeSpecificityComparer())
76+
.First();
77+
infos=infos.Where(info=>info.DeclaringType==type).ToArray();
78+
// this is a primitive version
79+
// the overload with the maximum number of parameters should be used
80+
MethodInfoprimary=infos.OrderByDescending(i=>i.GetParameters().Length).First();
81+
varprimaryParameters=primary.GetParameters();
82+
PyObjectsignatureClass=Runtime.InspectModule.GetAttr("Signature");
83+
varprimaryReturn=primary.ReturnParameter;
84+
85+
usingvarparameters=newPyList();
86+
usingvarparameterClass=primaryParameters.Length>0?Runtime.InspectModule.GetAttr("Parameter"):null;
87+
usingvarpositionalOrKeyword=parameterClass?.GetAttr("POSITIONAL_OR_KEYWORD");
88+
for(inti=0;i<primaryParameters.Length;i++)
89+
{
90+
varparameter=primaryParameters[i];
91+
varalternatives=infos.Select(info=>
92+
{
93+
ParameterInfo[]altParamters=info.GetParameters();
94+
returni<altParamters.Length?altParamters[i]:null;
95+
}).Where(p=>p!=null);
96+
usingvardefaultValue=alternatives
97+
.Select(alternative=>alternative.DefaultValue!=DBNull.Value?alternative.DefaultValue.ToPython():null)
98+
.FirstOrDefault(v=>v!=null)??parameterClass.GetAttr("empty");
99+
100+
if(alternatives.Any(alternative=>alternative.Name!=parameter.Name))
101+
{
102+
returnsignatureClass.Invoke();
103+
}
104+
105+
usingvarargs=newPyTuple(new[]{parameter.Name.ToPython(),positionalOrKeyword});
106+
usingvarkw=newPyDict();
107+
if(defaultValueis notnull)
108+
{
109+
kw["default"]=defaultValue;
110+
}
111+
usingvarparameterInfo=parameterClass.Invoke(args:args,kw:kw);
112+
parameters.Append(parameterInfo);
113+
}
114+
115+
// TODO: add return annotation
116+
returnsignatureClass.Invoke(parameters);
117+
}
118+
}
119+
120+
structTypeSpecificityComparer:IComparer<Type>{
121+
publicintCompare(Typea,Typeb){
122+
if(a==b)return0;
123+
if(a.IsSubclassOf(b))return1;
124+
if(b.IsSubclassOf(a))return-1;
125+
thrownewNotSupportedException();
126+
}
127+
}
68128

69129
/// <summary>
70130
/// MethodBinding __getattribute__ implementation.
@@ -91,6 +151,15 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
91151
case"Overloads":
92152
varom=newOverloadMapper(self.m,self.target);
93153
returnom.pyHandle;
154+
case"__signature__"whenRuntime.InspectModuleis notnull:
155+
varsig=self.Signature;
156+
if(sigisnull)
157+
{
158+
returnRuntime.PyObject_GenericGetAttr(ob,key);
159+
}
160+
returnsig.NewReferenceOrNull().DangerousMoveToPointerOrNull();
161+
case"__name__":
162+
returnself.m.GetName().DangerousMoveToPointerOrNull();
94163
default:
95164
returnRuntime.PyObject_GenericGetAttr(ob,key);
96165
}

‎src/runtime/methodobject.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
usingSystem;
22
usingSystem.Collections.Generic;
3-
usingSystem.Reflection;
43
usingSystem.Linq;
4+
usingSystem.Reflection;
55

66
namespacePython.Runtime
77
{
@@ -101,6 +101,16 @@ internal IntPtr GetDocString()
101101
returndoc;
102102
}
103103

104+
internalNewReferenceGetName()
105+
{
106+
varnames=newHashSet<string>(binder.GetMethods().Select(m=>m.Name));
107+
if(names.Count!=1){
108+
Exceptions.SetError(Exceptions.AttributeError,"a method has no name");
109+
returndefault;
110+
}
111+
returnNewReference.DangerousFromPointer(Runtime.PyString_FromString(names.First()));
112+
}
113+
104114

105115
/// <summary>
106116
/// This is a little tricky: a class can actually have a static method

‎src/runtime/pymodule.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#nullable enable
12
usingSystem;
23

34
namespacePython.Runtime
@@ -6,7 +7,7 @@ public class PyModule : PyScope
67
{
78
internalPyModule(refNewReferencereference):base(refreference,PyScopeManager.Global){}
89
publicPyModule(PyObjecto):base(o.Reference,PyScopeManager.Global){}
9-
publicPyModule(stringname,stringfilename=null):this(Create(name,filename)){}
10+
publicPyModule(stringname,string?filename=null):this(Create(name,filename)){}
1011

1112
/// <summary>
1213
/// Given a module or package name, import the module and return the resulting object.
@@ -19,6 +20,28 @@ public static PyObject Import(string name)
1920
returnIsModule(op)?newPyModule(refop):op.MoveToPyObject();
2021
}
2122

23+
/// <summary>
24+
/// Given a module or package name, import the module and return the resulting object.
25+
/// Returns <c>null</c> when module was not found (Python 3.6+).
26+
/// </summary>
27+
/// <param name="name">Fully-qualified module or package name</param>
28+
publicstaticPyObject?TryImport(stringname)
29+
{
30+
NewReferenceop=Runtime.PyImport_ImportModule(name);
31+
if(op.IsNull())
32+
{
33+
if(Exceptions.ModuleNotFoundError==IntPtr.Zero
34+
||!PythonException.CurrentMatches(Exceptions.ModuleNotFoundError))
35+
{
36+
throwPythonException.ThrowLastAsClrException();
37+
}
38+
39+
Exceptions.Clear();
40+
returnnull;
41+
}
42+
returnIsModule(op)?newPyModule(refop):op.MoveToPyObject();
43+
}
44+
2245
/// <summary>
2346
/// Reloads the module, and returns the updated object
2447
/// </summary>
@@ -38,7 +61,7 @@ public static PyModule FromString(string name, string code)
3861
returnnewPyModule(refm);
3962
}
4063

41-
privatestaticPyModuleCreate(stringname,stringfilename=null)
64+
privatestaticPyModuleCreate(stringname,string?filename=null)
4265
{
4366
if(string.IsNullOrWhiteSpace(name))
4467
{

‎src/runtime/runtime.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ internal static void Initialize(bool initSigs = false, ShutdownMode mode = Shutd
180180
AssemblyManager.UpdatePath();
181181

182182
clrInterop=GetModuleLazy("clr.interop");
183+
inspect=GetModuleLazy("inspect");
183184
}
184185

185186
privatestaticvoidInitPyMembers()
@@ -581,6 +582,8 @@ private static void MoveClrInstancesOnwershipToPython()
581582
internalstaticIntPtrPyNone;
582583
internalstaticIntPtrError;
583584

585+
privatestaticLazy<PyObject>inspect;
586+
internalstaticPyObjectInspectModule=>inspect.Value;
584587
privatestaticLazy<PyObject>clrInterop;
585588
internalstaticPyObjectInteropModule=>clrInterop.Value;
586589

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp