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

Commit21ca6e2

Browse files
committed
Add function of passing an arbitrary .NET object as the value of an
attribute of PyObject by dynamic type
1 parent3995130 commit21ca6e2

File tree

6 files changed

+233
-11
lines changed

6 files changed

+233
-11
lines changed

‎AUTHORS.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
- Sean Freitag ([@cowboygneox](https://github.com/cowboygneox))
3030
- Serge Weinstock ([@sweinst](https://github.com/sweinst))
3131
- Virgil Dupras ([@hsoft](https://github.com/hsoft))
32+
- Wenguang Yang ([@yagweb](https://github.com/yagweb))
3233
- Xavier Dupré ([@sdpython](https://github.com/sdpython))
3334
- Zane Purvis ([@zanedp](https://github.com/zanedp))
3435
- ([@ArvidJB](https://github.com/ArvidJB))
@@ -39,3 +40,4 @@
3940
- ([@rico-chet](https://github.com/rico-chet))
4041
- ([@rmadsen-ks](https://github.com/rmadsen-ks))
4142
- ([@stonebig](https://github.com/stonebig))
43+
- Wenguang Yang ([@yagweb](https://github.com/yagweb))

‎CHANGELOG.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
1313
- Added`pysetargv` (#347)
1414
- Added XML Documentation (#349)
1515
- Added Embedded tests on Appveyor (#353)
16-
- Added PY3 settings to configuration-manager (#346)
16+
-   Added PY3 settings to configuration-manager (#346)
17+
- Added function of passing an arbitrary .NET object as the value of an attribute of PyObject (#370)(#373)
1718

1819
###Changed
1920

‎src/embed_tests/Python.EmbeddingTest.csproj‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<ProjectDefaultTargets="Build"xmlns="http://schemas.microsoft.com/developer/msbuild/2003"ToolsVersion="4.0">
33
<PropertyGroup>
44
<ConfigurationCondition=" '$(Configuration)' == ''">Debug</Configuration>
@@ -30,7 +30,8 @@
3030
<DebugType>full</DebugType>
3131
</PropertyGroup>
3232
<PropertyGroupCondition=" '$(Configuration)' == 'ReleaseMono'">
33-
<DefineConstantsCondition="'$(DefineConstants)' == ''"></DefineConstants>
33+
<DefineConstantsCondition="'$(DefineConstants)' == ''">
34+
</DefineConstants>
3435
<Optimize>true</Optimize>
3536
<DebugType>pdbonly</DebugType>
3637
</PropertyGroup>
@@ -40,7 +41,8 @@
4041
<DebugType>full</DebugType>
4142
</PropertyGroup>
4243
<PropertyGroupCondition=" '$(Configuration)' == 'ReleaseWin'">
43-
<DefineConstantsCondition="'$(DefineConstants)' == ''"></DefineConstants>
44+
<DefineConstantsCondition="'$(DefineConstants)' == ''">
45+
</DefineConstants>
4446
<Optimize>true</Optimize>
4547
<DebugType>pdbonly</DebugType>
4648
</PropertyGroup>
@@ -50,7 +52,8 @@
5052
<DebugType>full</DebugType>
5153
</PropertyGroup>
5254
<PropertyGroupCondition=" '$(Configuration)' == 'ReleaseMonoPY3'">
53-
<DefineConstantsCondition="'$(DefineConstants)' == ''"></DefineConstants>
55+
<DefineConstantsCondition="'$(DefineConstants)' == ''">
56+
</DefineConstants>
5457
<Optimize>true</Optimize>
5558
<DebugType>pdbonly</DebugType>
5659
</PropertyGroup>
@@ -60,11 +63,13 @@
6063
<DebugType>full</DebugType>
6164
</PropertyGroup>
6265
<PropertyGroupCondition=" '$(Configuration)' == 'ReleaseWinPY3'">
63-
<DefineConstantsCondition="'$(DefineConstants)' == ''"></DefineConstants>
66+
<DefineConstantsCondition="'$(DefineConstants)' == ''">
67+
</DefineConstants>
6468
<Optimize>true</Optimize>
6569
<DebugType>pdbonly</DebugType>
6670
</PropertyGroup>
6771
<ItemGroup>
72+
<ReferenceInclude="Microsoft.CSharp" />
6873
<ReferenceInclude="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
6974
<HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
7075
</Reference>
@@ -76,6 +81,7 @@
7681
</ItemGroup>
7782
<ItemGroup>
7883
<CompileInclude="InitializeTest.cs" />
84+
<CompileInclude="dynamic.cs" />
7985
<CompileInclude="pyimport.cs" />
8086
<CompileInclude="pyiter.cs" />
8187
<CompileInclude="pylong.cs" />
@@ -100,4 +106,4 @@
100106
<CopySourceFiles="$(TargetAssembly)"DestinationFolder="$(PythonBuildDir)" />
101107
<CopySourceFiles="$(TargetAssemblyPdb)"Condition="Exists('$(TargetAssemblyPdb)')"DestinationFolder="$(PythonBuildDir)" />
102108
</Target>
103-
</Project>
109+
</Project>

‎src/embed_tests/dynamic.cs‎

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
usingNUnit.Framework;
2+
usingPython.Runtime;
3+
usingSystem;
4+
usingSystem.Collections.Generic;
5+
usingSystem.Linq;
6+
usingSystem.Text;
7+
8+
namespacePython.EmbeddingTest
9+
{
10+
[TestFixture]
11+
publicclassdynamicTest
12+
{
13+
privateIntPtrgs;
14+
privateoutstreamstream;
15+
16+
[SetUp]
17+
publicvoidSetUp()
18+
{
19+
PythonEngine.Initialize();
20+
gs=PythonEngine.AcquireLock();
21+
22+
/* redirect sys.stdout to a .NET object */
23+
this.stream=newoutstream();
24+
}
25+
26+
[TearDown]
27+
publicvoidTearDown()
28+
{
29+
PythonEngine.ReleaseLock(gs);
30+
PythonEngine.Shutdown();
31+
}
32+
33+
/// <summary>
34+
/// Set the attribute of a pyobject to null.
35+
/// </summary>
36+
[Test]
37+
publicvoidAssignNone()
38+
{
39+
dynamicsys=Py.Import("sys");
40+
sys.stderr=null;
41+
Assert.IsNull(sys.stderr);
42+
}
43+
44+
/// <summary>
45+
/// Set the attribute of a pyobject with a .NET object.
46+
/// </summary>
47+
[Test]
48+
publicvoidAssignObject()
49+
{
50+
dynamicsys=Py.Import("sys");
51+
sys.stdout=this.stream;
52+
// Check whether there are the same object.
53+
Assert.AreEqual(sys.stdout,stream);
54+
55+
this.stream.clear();
56+
PythonEngine.RunSimpleString("print('Hello!')");
57+
Assert.AreEqual(stream.getvalue(),"Hello!\n");
58+
}
59+
60+
/// <summary>
61+
/// When the .NET object was created and used in Python side.
62+
/// </summary>
63+
[Test]
64+
//[Explicit]
65+
[Ignore]
66+
publicvoidAssignObjectInPython()
67+
{
68+
PythonEngine.RunSimpleString(@"
69+
import sys
70+
from Python.EmbeddingTest import outstream
71+
sys.stdout = outstream()
72+
");
73+
dynamicsys=Py.Import("sys");
74+
varobj=sys.stdout;
75+
Assert.IsTrue(objisoutstream);
76+
}
77+
78+
/// <summary>
79+
/// Check whether we can get the attr of a python object when the value of attr is a PyObject.
80+
/// </summary>
81+
[Test]
82+
publicvoidAssignPyObject()
83+
{
84+
dynamicsys=Py.Import("sys");
85+
dynamicio=Py.Import("io");
86+
sys.stderr=io.StringIO();
87+
varbb=sys.stderr;//Get the PyObject
88+
bb.write("Hello!");
89+
Assert.AreEqual(bb.getvalue().ToString(),"Hello!");
90+
}
91+
92+
/// <summary>
93+
/// Pass the .NET object in Python side.
94+
/// </summary>
95+
[Test]
96+
publicvoidPassObjectInPython()
97+
{
98+
dynamicsys=Py.Import("sys");
99+
sys.stdout=this.stream;
100+
101+
//Pass the .NET object in Python side
102+
PythonEngine.RunSimpleString("import sys\n"+
103+
"from io import StringIO\n"+
104+
"sys.stderr = sys.stdout\n");
105+
106+
//Compare in Python
107+
this.stream.clear();
108+
PythonEngine.RunSimpleString("import sys\n"+
109+
"print((sys.stderr is sys.stdout))");
110+
Assert.AreEqual(this.stream.getvalue(),"True\n");
111+
112+
//compare in .NET
113+
Assert.AreEqual(sys.stdout,sys.stderr);
114+
}
115+
116+
/// <summary>
117+
/// Pass the PyObject in .NET side
118+
/// </summary>
119+
[Test]
120+
publicvoidPassPyObjectInNet()
121+
{
122+
dynamicsys=Py.Import("sys");
123+
sys.stdout=this.stream;
124+
sys.stderr=sys.stdout;
125+
126+
//Compare in Python
127+
varres=PythonEngine.RunString("import sys\n"+
128+
"print(sys.stderr is sys.stdout)");
129+
Assert.AreEqual(sys.stdout.getvalue().ToString(),"False\n");
130+
131+
//compare in .NET
132+
Assert.AreEqual(sys.stdout,sys.stderr);
133+
}
134+
}
135+
136+
/// <summary>
137+
/// Implement the interface of the sys.stdout redirection
138+
/// </summary>
139+
publicclassoutstream
140+
{
141+
publicoutstream()
142+
{
143+
this.buffer=newStringBuilder();
144+
}
145+
privateStringBuilderbuffer;
146+
publicvoidwrite(Stringstr)
147+
{
148+
this.buffer.Append(str);
149+
}
150+
publicvoidflush(){}
151+
publicvoidclose(){}
152+
153+
publicvoidclear()
154+
{
155+
this.buffer.Clear();
156+
}
157+
publicstringgetvalue()
158+
{
159+
returnthis.buffer.ToString();
160+
}
161+
}
162+
}

‎src/runtime/Python.Runtime.csproj‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<ProjectDefaultTargets="Build"xmlns="http://schemas.microsoft.com/developer/msbuild/2003"ToolsVersion="4.0">
33
<PropertyGroup>
44
<ConfigurationCondition=" '$(Configuration)' == ''">Debug</Configuration>
@@ -69,6 +69,12 @@
6969
<Optimize>false</Optimize>
7070
<DebugType>full</DebugType>
7171
</PropertyGroup>
72+
<PropertyGroupCondition="'$(Configuration)|$(Platform)' == 'DebugWinPY3|x64'">
73+
<DefineConstants>TRACE;DEBUG;PYTHON3;PYTHON35;UCS2</DefineConstants>
74+
</PropertyGroup>
75+
<PropertyGroupCondition="'$(Configuration)|$(Platform)' == 'DebugMono|x64'">
76+
<DefineConstants>TRACE;DEBUG;PYTHON3;PYTHON35;UCS2</DefineConstants>
77+
</PropertyGroup>
7278
<ItemGroup>
7379
<ReferenceInclude="System" />
7480
</ItemGroup>
@@ -158,4 +164,4 @@
158164
<CopySourceFiles="$(TargetAssembly)"DestinationFolder="$(PythonBuildDir)" />
159165
<CopySourceFiles="$(TargetAssemblyPdb)"Condition="Exists('$(TargetAssemblyPdb)')"DestinationFolder="$(PythonBuildDir)" />
160166
</Target>
161-
</Project>
167+
</Project>

‎src/runtime/pyobject.cs‎

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,31 @@ public bool HasAttr(PyObject name)
183183
}
184184

185185

186+
/// <summary>
187+
/// GetAttr Method For Dynamic Type
188+
/// </summary>
189+
/// <remarks>
190+
/// Returns the named attribute of the Python object, or raises a
191+
/// PythonException if the attribute access fails.
192+
/// </remarks>
193+
publicobjectGetAttrDynamic(stringname)
194+
{
195+
IntPtrop=Runtime.PyObject_GetAttrString(obj,name);
196+
if(op==IntPtr.Zero)
197+
{
198+
thrownewPythonException();
199+
}
200+
if(ManagedType.IsManagedType(op))
201+
{
202+
ManagedTypemanagedMethod=ManagedType.GetManagedObject(op);
203+
if(managedMethodisCLRObject)
204+
{
205+
return((CLRObject)managedMethod).inst;
206+
}
207+
}
208+
returnCheckNone(newPyObject(op));
209+
}
210+
186211
/// <summary>
187212
/// GetAttr Method
188213
/// </summary>
@@ -275,6 +300,26 @@ public void SetAttr(string name, PyObject value)
275300
}
276301
}
277302

303+
publicvoidSetAttrDynamic(stringname,objectvalue)
304+
{
305+
if(value==null)
306+
{
307+
intr=Runtime.PyObject_SetAttrString(obj,name,Runtime.PyNone);
308+
if(r<0)
309+
{
310+
thrownewPythonException();
311+
}
312+
}
313+
elseif(valueisPyObject)
314+
{
315+
this.SetAttr(name,(PyObject)value);
316+
}
317+
else
318+
{
319+
varptr=CLRObject.GetInstHandle(value,value.GetType());
320+
this.SetAttr(name,newPyObject(ptr));
321+
}
322+
}
278323

279324
/// <summary>
280325
/// SetAttr Method
@@ -891,7 +936,7 @@ public override bool TryGetMember(GetMemberBinder binder, out object result)
891936
{
892937
if(this.HasAttr(binder.Name))
893938
{
894-
result=CheckNone(this.GetAttr(binder.Name));
939+
result=this.GetAttrDynamic(binder.Name);
895940
returntrue;
896941
}
897942
else
@@ -904,7 +949,7 @@ public override bool TrySetMember(SetMemberBinder binder, object value)
904949
{
905950
if(this.HasAttr(binder.Name))
906951
{
907-
this.SetAttr(binder.Name,(PyObject)value);
952+
this.SetAttrDynamic(binder.Name,value);
908953
returntrue;
909954
}
910955
else

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp