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

Commit266ee3f

Browse files
committed
implemented __signature__ and __name__ on methodbinding
1 parent1e32d8c commit266ee3f

File tree

7 files changed

+129
-7
lines changed

7 files changed

+129
-7
lines changed

‎CHANGELOG.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
1414
- Add GetPythonThreadID and Interrupt methods in PythonEngine
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`
17-
- Improved exception handling:
18-
- exceptions can now be converted with codecs
19-
-`InnerException` and`__cause__` are propagated properly
17+
- Improved exception handling:
18+
- exceptions can now be converted with codecs
19+
-`__name__` and`__signature__` to reflected .NET methods
20+
-`InnerException` and`__cause__` are propagated properly
2021

2122
###Changed
2223
- Drop support for Python 2, 3.4, and 3.5

‎src/embed_tests/Inspect.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,21 @@ 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+
varobj=newClass();
38+
usingvarscope=Py.CreateScope();
39+
scope.Import("inspect");
40+
scope.Set(nameof(obj),obj);
41+
varspec=scope.Eval($"inspect.getfullargspec({nameof(obj)}.{nameof(Class.Method)})");
42+
}
43+
44+
classClass
45+
{
46+
publicvoidMethod(inta,intb=10){}
47+
publicvoidMethod(inta,objectb){}
48+
}
3349
}
3450
}

‎src/runtime/exceptions.cs

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

‎src/runtime/methodbinding.cs

Lines changed: 63 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,59 @@ public static IntPtr mp_subscript(IntPtr tp, IntPtr idx)
6566
returnmb.pyHandle;
6667
}
6768

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

69123
/// <summary>
70124
/// MethodBinding __getattribute__ implementation.
@@ -91,6 +145,15 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
91145
case"Overloads":
92146
varom=newOverloadMapper(self.m,self.target);
93147
returnom.pyHandle;
148+
case"__signature__"whenRuntime.InspectModuleis notnull:
149+
varsig=self.Signature;
150+
if(sigisnull)
151+
{
152+
returnRuntime.PyObject_GenericGetAttr(ob,key);
153+
}
154+
returnsig.NewReferenceOrNull().DangerousMoveToPointerOrNull();
155+
case"__name__":
156+
returnself.m.GetName().DangerousMoveToPointerOrNull();
94157
default:
95158
returnRuntime.PyObject_GenericGetAttr(ob,key);
96159
}

‎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: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ internal static void Initialize(bool initSigs = false, ShutdownMode mode = Shutd
178178
}
179179
XDecref(item);
180180
AssemblyManager.UpdatePath();
181+
182+
inspect=GetInspectModuleLazy();
181183
}
182184

183185
privatestaticvoidInitPyMembers()
@@ -291,6 +293,9 @@ private static IntPtr Get_PyObject_NextNotImplemented()
291293
returniternext;
292294
}
293295

296+
privatestaticLazy<PyObject?>GetInspectModuleLazy()
297+
=>newLazy<PyObject?>(()=>PyModule.TryImport("inspect"),isThreadSafe:false);
298+
294299
/// <summary>
295300
/// Tries to downgrade the shutdown mode, if possible.
296301
/// The only possibles downgrades are:
@@ -586,6 +591,9 @@ public static PyObject None
586591
}
587592
}
588593

594+
privatestaticLazy<PyObject?>inspect;
595+
internalstaticPyObject?InspectModule=>inspect.Value;
596+
589597
/// <summary>
590598
/// Check if any Python Exceptions occurred.
591599
/// If any exist throw new PythonException.
@@ -2038,7 +2046,7 @@ internal static bool PyType_IsSameAsOrSubtype(BorrowedReference type, BorrowedRe
20382046
internalstaticNewReferencePyType_FromSpecWithBases(inNativeTypeSpecspec,BorrowedReferencebases)=>Delegates.PyType_FromSpecWithBases(inspec,bases);
20392047

20402048
/// <summary>
2041-
/// Finalize a type object. This should be called on all type objects to finish their initialization. This function is responsible for adding inherited slots from a types base class. Return 0 on success, or return -1 and sets an exception on error.
2049+
/// Finalize a type object. This should be called on all type objects to finish their initialization. This function is responsible for adding inherited slots from a type's base class. Return 0 on success, or return -1 and sets an exception on error.
20422050
/// </summary>
20432051

20442052
internalstaticintPyType_Ready(IntPtrtype)=>Delegates.PyType_Ready(type);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp