Skip to content

Commit 4f79045

Browse files
author
Barton Cline
committed
I've been adding pieces to the UnitTest classes.
This addition tests embedding nested imports. The Python parts are in the tests directory and the managed parts are in the embed_tests directroy as are the nunit parts. This test also demonstrates some neat tricks that can be done when embedding a python interpreter in managed code by using reflection to call internal members of the Python.Runtime. The project settings file is VS2008, which means that it's probably time to go ahead and bring the rest of the project files up to a more recent version of Visual Studio.
1 parent 5d90263 commit 4f79045

File tree

7 files changed

+140
-39
lines changed

7 files changed

+140
-39
lines changed
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
<NUnitProject>
2-
<Settings activeconfig="Debug" />
3-
<Config name="Debug" binpathtype="Auto">
4-
<assembly path="bin\Release\Python.EmbeddingTest.dll" />
5-
</Config>
6-
<Config name="Release" binpathtype="Auto" />
1+
<NUnitProject>
2+
<Settings activeconfig="Debug" />
3+
<Config name="Debug" binpathtype="Auto">
4+
<assembly path="bin\Debug\Python.EmbeddingTest.dll" />
5+
</Config>
6+
<Config name="Release" binpathtype="Auto" />
77
</NUnitProject>

pythonnet/src/embed_tests/Python.EmbeddingTest.csproj

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
1+
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
22
<PropertyGroup>
33
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
44
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -8,6 +8,26 @@
88
<AssemblyName>Python.EmbeddingTest</AssemblyName>
99
<RootNamespace>Python.Runtime</RootNamespace>
1010
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
11+
<FileUpgradeFlags>
12+
</FileUpgradeFlags>
13+
<UpgradeBackupLocation>
14+
</UpgradeBackupLocation>
15+
<OldToolsVersion>2.0</OldToolsVersion>
16+
<PublishUrl>publish\</PublishUrl>
17+
<Install>true</Install>
18+
<InstallFrom>Disk</InstallFrom>
19+
<UpdateEnabled>false</UpdateEnabled>
20+
<UpdateMode>Foreground</UpdateMode>
21+
<UpdateInterval>7</UpdateInterval>
22+
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
23+
<UpdatePeriodically>false</UpdatePeriodically>
24+
<UpdateRequired>false</UpdateRequired>
25+
<MapFileExtensions>true</MapFileExtensions>
26+
<ApplicationRevision>0</ApplicationRevision>
27+
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
28+
<IsWebBootstrapper>false</IsWebBootstrapper>
29+
<UseApplicationTrust>false</UseApplicationTrust>
30+
<BootstrapperEnabled>true</BootstrapperEnabled>
1131
</PropertyGroup>
1232
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1333
<DebugSymbols>true</DebugSymbols>
@@ -37,14 +57,17 @@
3757
<PlatformTarget>AnyCPU</PlatformTarget>
3858
</PropertyGroup>
3959
<ItemGroup>
40-
<Reference Include="nunit.framework, Version=2.4.1.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
60+
<Reference Include="nunit.framework, Version=2.5.5.10112, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
4161
<Reference Include="System" />
4262
</ItemGroup>
4363
<ItemGroup>
4464
<None Include="Embeddingtest.nunit" />
4565
</ItemGroup>
4666
<ItemGroup>
47-
<Compile Include="pyiter.cs" />
67+
<Compile Include="pyimport.cs" />
68+
<Compile Include="pyiter.cs">
69+
<SubType>Code</SubType>
70+
</Compile>
4871
<Compile Include="pyobject.cs" />
4972
<Compile Include="pythonexception.cs" />
5073
</ItemGroup>
@@ -54,6 +77,23 @@
5477
<Name>Python.Runtime</Name>
5578
</ProjectReference>
5679
</ItemGroup>
80+
<ItemGroup>
81+
<BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
82+
<Visible>False</Visible>
83+
<ProductName>.NET Framework 2.0 %28x86%29</ProductName>
84+
<Install>true</Install>
85+
</BootstrapperPackage>
86+
<BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
87+
<Visible>False</Visible>
88+
<ProductName>.NET Framework 3.0 %28x86%29</ProductName>
89+
<Install>false</Install>
90+
</BootstrapperPackage>
91+
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
92+
<Visible>False</Visible>
93+
<ProductName>.NET Framework 3.5</ProductName>
94+
<Install>false</Install>
95+
</BootstrapperPackage>
96+
</ItemGroup>
5797
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
5898
<ProjectExtensions>
5999
<VisualStudio AllowExistingFolder="true" />
@@ -63,4 +103,4 @@
63103
copy "$(TargetDir)*.pdb" "$(SolutionDir)"
64104
</PostBuildEvent>
65105
</PropertyGroup>
66-
</Project>
106+
</Project>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using System;
2+
using System.Reflection;
3+
using System.Collections.Generic;
4+
using NUnit.Framework;
5+
using Python.Runtime;
6+
7+
namespace Python.EmbeddingTest
8+
{
9+
[TestFixture]
10+
public class PyImportTest
11+
{
12+
private IntPtr gs;
13+
14+
[SetUp]
15+
public void SetUp()
16+
{
17+
PythonEngine.Initialize();
18+
gs = PythonEngine.AcquireLock();
19+
20+
//string here = Environment.CurrentDirectory;
21+
// trunk\pythonnet\src\embed_tests\bin\Debug
22+
23+
/*
24+
* Append the tests directory to sys.path
25+
* using reflection to circumvent the private modifires placed on most Runtime methods.
26+
*/
27+
string s = @"..\..\..\tests";
28+
29+
Type RTClass = typeof(Runtime.Runtime);
30+
31+
/* pyStrPtr = PyString_FromString(s); */
32+
MethodInfo PyString_FromString = RTClass.GetMethod("PyString_FromString", BindingFlags.NonPublic | BindingFlags.Static);
33+
object[] funcArgs = new object[1];
34+
funcArgs[0] = s;
35+
IntPtr pyStrPtr = (IntPtr)PyString_FromString.Invoke(null, funcArgs);
36+
37+
/* SysDotPath = sys.path */
38+
MethodInfo PySys_GetObject = RTClass.GetMethod("PySys_GetObject", BindingFlags.NonPublic | BindingFlags.Static);
39+
funcArgs[0] = "path";
40+
IntPtr SysDotPath = (IntPtr)PySys_GetObject.Invoke(null, funcArgs);
41+
42+
/* SysDotPath.append(*pyStrPtr) */
43+
MethodInfo PyList_Append = RTClass.GetMethod("PyList_Append", BindingFlags.NonPublic | BindingFlags.Static);
44+
funcArgs = new object[2];
45+
funcArgs[0] = SysDotPath;
46+
funcArgs[1] = pyStrPtr;
47+
int r = (int)PyList_Append.Invoke(null, funcArgs);
48+
}
49+
50+
[TearDown]
51+
public void TearDown()
52+
{
53+
PythonEngine.ReleaseLock(gs);
54+
PythonEngine.Shutdown();
55+
}
56+
57+
/// <summary>
58+
/// Test subdirectory import
59+
/// </summary>
60+
/// <remarks>
61+
/// The required directory structure was added to the \trunk\pythonnet\src\tests directory:
62+
///
63+
/// PyImportTest/
64+
/// __init__.py
65+
/// test/
66+
/// __init__.py
67+
/// one.py
68+
/// </remarks>
69+
[Test]
70+
public void TestDottedName()
71+
{
72+
PyObject module;
73+
module = PythonEngine.ImportModule("PyImportTest.test.one");
74+
Assert.IsNotNull(module, ">>> import PyImportTest.test.one # FAILED");
75+
}
76+
}
77+
}

pythonnet/src/runtime/assemblymanager.cs

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,13 @@ public static Assembly LoadAssemblyPath(string name) {
210210
// an assembly named after each of A.B.C.D, A.B.C, A.B, A. This
211211
// will only actually probe for the assembly once for each unique
212212
// namespace. Returns true if any assemblies were loaded.
213+
// TODO item 3 "* Deprecate implicit loading of assemblies"
213214
//===================================================================
214215

215-
public static bool LoadImplicit(string name) {
216+
public static bool LoadImplicit(string name, out bool fromFile) {
217+
// 2010-08-16: Deprecation support
218+
// Added out param to detect fully qualified name load
219+
fromFile = false;
216220
string[] names = name.Split('.');
217221
bool loaded = false;
218222
string s = "";
@@ -221,9 +225,17 @@ public static bool LoadImplicit(string name) {
221225
if (!probed.ContainsKey(s)) {
222226
if (LoadAssemblyPath(s) != null){
223227
loaded = true;
228+
// 2010-08-16: Deprecation support
229+
if (s == name) {
230+
fromFile = true;
231+
}
224232
}
225233
else if (LoadAssembly(s) != null) {
226234
loaded = true;
235+
// 2010-08-16: Deprecation support
236+
if (s == name) {
237+
fromFile = true;
238+
}
227239
}
228240
probed[s] = 1;
229241
}
@@ -268,35 +280,7 @@ static void ScanAssembly(Assembly assembly) {
268280

269281
if (t.IsGenericTypeDefinition) {
270282
GenericUtil.Register(t);
271-
// Dictionary<string, string> map = null;
272-
// generics.TryGetValue(t.Namespace, out map);
273-
// if (map == null) {
274-
// map = new Dictionary<string, string>();
275-
// generics[t.Namespace] = map;
276-
// }
277-
// string bname = t.Name;
278-
// string mapped = null;
279-
// int tick = bname.IndexOf("`");
280-
// if (tick > -1) {
281-
// bname = bname.Substring(0, tick);
282-
// }
283-
// map.TryGetValue(bname, out mapped);
284-
// if (mapped == null) {
285-
// map[bname] = t.Name;
286-
// }
287283
}
288-
289-
// if (t.IsGenericTypeDefinition) {
290-
// List<string> snames = null;
291-
// special.TryGetValue(t.Namespace, out snames);
292-
// if (snames == null) {
293-
// snames = new List<string>(8);
294-
// special[t.Namespace] = snames;
295-
// }
296-
// snames.Add(t.Name);
297-
// }
298-
299-
300284
}
301285
}
302286

pythonnet/src/tests/PyImportTest/__init__.py

Whitespace-only changes.

pythonnet/src/tests/PyImportTest/test/__init__.py

Whitespace-only changes.

pythonnet/src/tests/PyImportTest/test/one.py

Whitespace-only changes.

0 commit comments

Comments
 (0)