Skip to content

Commit ffceeed

Browse files
authored
Merge branch 'master' into string-marshaling-cache
2 parents 88c9bc8 + 677281e commit ffceeed

27 files changed

+568
-361
lines changed

.travis.yml

-7
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ matrix:
2222
- dotnet-hostfxr-2.0.0
2323
- dotnet-runtime-2.0.0
2424
- dotnet-sdk-2.0.0
25-
- python: 3.3
26-
env: *xplat-env
27-
addons: *xplat-addons
28-
2925
- python: 3.4
3026
env: *xplat-env
3127
addons: *xplat-addons
@@ -47,9 +43,6 @@ matrix:
4743
- BUILD_OPTS=
4844
- NUNIT_PATH=./packages/NUnit.*/tools/nunit3-console.exe
4945

50-
- python: 3.3
51-
env: *classic-env
52-
5346
- python: 3.4
5447
env: *classic-env
5548

AUTHORS.md

+7
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212

1313
## Contributors
1414

15+
- Alexandre Catarino([@AlexCatarino](https://github.com/AlexCatarino))
1516
- Arvid JB ([@ArvidJB](https://github.com/ArvidJB))
1617
- Bradley Friedman ([@leith-bartrich](https://github.com/leith-bartrich))
18+
- Callum Noble ([@callumnoble](https://github.com/callumnoble))
1719
- Christian Heimes ([@tiran](https://github.com/tiran))
1820
- Christoph Gohlke ([@cgohlke](https://github.com/cgohlke))
1921
- Christopher Pow ([@christopherpow](https://github.com/christopherpow))
@@ -24,9 +26,11 @@
2426
- Dmitriy Se ([@dmitriyse](https://github.com/dmitriyse))
2527
- He-chien Tsai ([@t3476](https://github.com/t3476))
2628
-   Ivan Cronyn ([@cronan](https://github.com/cronan))
29+
- Jan Krivanek ([@jakrivan](https://github.com/jakrivan))
2730
-   Jeff Reback ([@jreback](https://github.com/jreback))
2831
- Joe Frayne ([@jfrayne](https://github.com/jfrayne))
2932
- John Burnett ([@johnburnett](https://github.com/johnburnett))
33+
- John Wilkes ([@jbw3](https://github.com/jbw3))
3034
- Luke Stratman ([@lstratman](https://github.com/lstratman))
3135
- Konstantin Posudevskiy ([@konstantin-posudevskiy](https://github.com/konstantin-posudevskiy))
3236
- Matthias Dittrich ([@matthid](https://github.com/matthid))
@@ -39,9 +43,12 @@
3943
- Ville M. Vainio ([@vivainio](https://github.com/vivainio))
4044
- Virgil Dupras ([@hsoft](https://github.com/hsoft))
4145
- Wenguang Yang ([@yagweb](https://github.com/yagweb))
46+
- William Sardar ([@williamsardar])(https://github.com/williamsardar)
4247
- Xavier Dupré ([@sdpython](https://github.com/sdpython))
4348
- Zane Purvis ([@zanedp](https://github.com/zanedp))
4449
- ([@bltribble](https://github.com/bltribble))
50+
- ([@civilx64](https://github.com/civilx64))
51+
- ([@GSPP](https://github.com/GSPP))
4552
- ([@omnicognate](https://github.com/omnicognate))
4653
- ([@rico-chet](https://github.com/rico-chet))
4754
- ([@rmadsen-ks](https://github.com/rmadsen-ks))

CHANGELOG.md

+183-81
Large diffs are not rendered by default.

appveyor.yml

+7-3
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,23 @@ environment:
1717
matrix:
1818
- PYTHON_VERSION: 2.7
1919
BUILD_OPTS: --xplat
20-
- PYTHON_VERSION: 3.3
21-
BUILD_OPTS: --xplat
2220
- PYTHON_VERSION: 3.4
2321
BUILD_OPTS: --xplat
2422
- PYTHON_VERSION: 3.5
2523
BUILD_OPTS: --xplat
2624
- PYTHON_VERSION: 3.6
2725
BUILD_OPTS: --xplat
2826
- PYTHON_VERSION: 2.7
29-
- PYTHON_VERSION: 3.3
3027
- PYTHON_VERSION: 3.4
3128
- PYTHON_VERSION: 3.5
3229
- PYTHON_VERSION: 3.6
3330

31+
matrix:
32+
allow_failures:
33+
- PYTHON_VERSION: 3.4
34+
BUILD_OPTS: --xplat
35+
- PYTHON_VERSION: 3.4
36+
3437
init:
3538
# Update Environment Variables based on matrix/platform
3639
- set PY_VER=%PYTHON_VERSION:.=%
@@ -41,6 +44,7 @@ init:
4144
- set PATH=%PYTHON%;%PYTHON%\Scripts;%PATH%
4245

4346
install:
47+
- python -m pip install -U pip
4448
- pip install --upgrade -r requirements.txt --quiet
4549

4650
# Install OpenCover. Can't put on `packages.config`, not Mono compatible

requirements.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# Requirements for both Travis and AppVeyor
22
pytest==3.2.5
33
coverage
4+
psutil
45

56
# Coverage upload
67
codecov
78

89
# Platform specific requirements
9-
pip; sys_platform == 'win32'
10+
# pip; sys_platform == 'win32'
1011
wheel; sys_platform == 'win32'
1112
pycparser; sys_platform != 'win32'

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ def _install_packages(self):
329329
self.debug_print("Updating NuGet: {0}".format(cmd))
330330
subprocess.check_call(cmd, shell=use_shell)
331331

332-
cmd = "{0} restore pythonnet.sln -o packages".format(nuget)
332+
cmd = "{0} restore pythonnet.sln -MSBuildVersion 14 -o packages".format(nuget)
333333
self.debug_print("Installing packages: {0}".format(cmd))
334334
subprocess.check_call(cmd, shell=use_shell)
335335

src/embed_tests/Python.EmbeddingTest.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
<Compile Include="TestPyList.cs" />
9494
<Compile Include="TestPyLong.cs" />
9595
<Compile Include="TestPyNumber.cs" />
96+
<Compile Include="TestPyObject.cs" />
9697
<Compile Include="TestPySequence.cs" />
9798
<Compile Include="TestPyString.cs" />
9899
<Compile Include="TestPythonException.cs" />

src/embed_tests/TestPyObject.cs

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using NUnit.Framework;
5+
using Python.Runtime;
6+
7+
namespace Python.EmbeddingTest
8+
{
9+
public class TestPyObject
10+
{
11+
[OneTimeSetUp]
12+
public void SetUp()
13+
{
14+
PythonEngine.Initialize();
15+
}
16+
17+
[OneTimeTearDown]
18+
public void Dispose()
19+
{
20+
PythonEngine.Shutdown();
21+
}
22+
23+
[Test]
24+
public void TestGetDynamicMemberNames()
25+
{
26+
List<string> expectedMemberNames = new List<string>
27+
{
28+
"add",
29+
"getNumber",
30+
"member1",
31+
"member2"
32+
};
33+
34+
PyDict locals = new PyDict();
35+
36+
PythonEngine.Exec(@"
37+
class MemberNamesTest(object):
38+
def __init__(self):
39+
self.member1 = 123
40+
self.member2 = 'Test string'
41+
42+
def getNumber(self):
43+
return 123
44+
45+
def add(self, x, y):
46+
return x + y
47+
48+
a = MemberNamesTest()
49+
", null, locals.Handle);
50+
51+
PyObject a = locals.GetItem("a");
52+
53+
IEnumerable<string> memberNames = a.GetDynamicMemberNames();
54+
55+
foreach (string expectedName in expectedMemberNames)
56+
{
57+
Assert.IsTrue(memberNames.Contains(expectedName), "Could not find member '{0}'.", expectedName);
58+
}
59+
}
60+
}
61+
}

src/runtime/Python.Runtime.csproj

-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@
151151
</ItemGroup>
152152
<ItemGroup Condition=" '$(PythonInteropFile)' == '' ">
153153
<Compile Include="interop27.cs" />
154-
<Compile Include="interop33.cs" />
155154
<Compile Include="interop34.cs" />
156155
<Compile Include="interop35.cs" />
157156
<Compile Include="interop36.cs" />

src/runtime/assemblymanager.cs

+11-101
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,16 @@ internal class AssemblyManager
1717
{
1818
// modified from event handlers below, potentially triggered from different .NET threads
1919
// therefore this should be a ConcurrentDictionary
20+
//
21+
// WARNING: Dangerous if cross-app domain usage is ever supported
22+
// Reusing the dictionary with assemblies accross multiple initializations is problematic.
23+
// Loading happens from CurrentDomain (see line 53). And if the first call is from AppDomain that is later unloaded,
24+
// than it can end up referring to assemblies that are already unloaded (default behavior after unload appDomain -
25+
// unless LoaderOptimization.MultiDomain is used);
26+
// So for multidomain support it is better to have the dict. recreated for each app-domain initialization
2027
private static ConcurrentDictionary<string, ConcurrentDictionary<Assembly, string>> namespaces =
2128
new ConcurrentDictionary<string, ConcurrentDictionary<Assembly, string>>();
29+
2230
//private static Dictionary<string, Dictionary<string, string>> generics;
2331
private static AssemblyLoadEventHandler lhandler;
2432
private static ResolveEventHandler rhandler;
@@ -27,7 +35,7 @@ internal class AssemblyManager
2735
private static Dictionary<string, int> probed = new Dictionary<string, int>(32);
2836

2937
// modified from event handlers below, potentially triggered from different .NET threads
30-
private static AssemblyList assemblies;
38+
private static ConcurrentQueue<Assembly> assemblies;
3139
internal static List<string> pypath;
3240

3341
private AssemblyManager()
@@ -58,7 +66,7 @@ internal static void Initialize()
5866
try
5967
{
6068
ScanAssembly(a);
61-
assemblies.Add(a);
69+
assemblies.Enqueue(a);
6270
}
6371
catch (Exception ex)
6472
{
@@ -89,7 +97,7 @@ internal static void Shutdown()
8997
private static void AssemblyLoadHandler(object ob, AssemblyLoadEventArgs args)
9098
{
9199
Assembly assembly = args.LoadedAssembly;
92-
assemblies.Add(assembly);
100+
assemblies.Enqueue(assembly);
93101
ScanAssembly(assembly);
94102
}
95103

@@ -459,103 +467,5 @@ public static Type LookupType(string qname)
459467
}
460468
return null;
461469
}
462-
463-
/// <summary>
464-
/// Wrapper around List&lt;Assembly&gt; for thread safe access
465-
/// </summary>
466-
private class AssemblyList : IEnumerable<Assembly>
467-
{
468-
private readonly List<Assembly> _list;
469-
private readonly ReaderWriterLockSlim _lock;
470-
471-
public AssemblyList(int capacity)
472-
{
473-
_list = new List<Assembly>(capacity);
474-
_lock = new ReaderWriterLockSlim();
475-
}
476-
477-
public int Count
478-
{
479-
get
480-
{
481-
_lock.EnterReadLock();
482-
try
483-
{
484-
return _list.Count;
485-
}
486-
finally
487-
{
488-
_lock.ExitReadLock();
489-
}
490-
}
491-
}
492-
493-
public void Add(Assembly assembly)
494-
{
495-
_lock.EnterWriteLock();
496-
try
497-
{
498-
_list.Add(assembly);
499-
}
500-
finally
501-
{
502-
_lock.ExitWriteLock();
503-
}
504-
}
505-
506-
public IEnumerator GetEnumerator()
507-
{
508-
return ((IEnumerable<Assembly>)this).GetEnumerator();
509-
}
510-
511-
/// <summary>
512-
/// Enumerator wrapping around <see cref="AssemblyList._list" />'s enumerator.
513-
/// Acquires and releases a read lock on <see cref="AssemblyList._lock" /> during enumeration
514-
/// </summary>
515-
private class Enumerator : IEnumerator<Assembly>
516-
{
517-
private readonly AssemblyList _assemblyList;
518-
519-
private readonly IEnumerator<Assembly> _listEnumerator;
520-
521-
public Enumerator(AssemblyList assemblyList)
522-
{
523-
_assemblyList = assemblyList;
524-
_assemblyList._lock.EnterReadLock();
525-
_listEnumerator = _assemblyList._list.GetEnumerator();
526-
}
527-
528-
public void Dispose()
529-
{
530-
_listEnumerator.Dispose();
531-
_assemblyList._lock.ExitReadLock();
532-
}
533-
534-
public bool MoveNext()
535-
{
536-
return _listEnumerator.MoveNext();
537-
}
538-
539-
public void Reset()
540-
{
541-
_listEnumerator.Reset();
542-
}
543-
544-
public Assembly Current
545-
{
546-
get { return _listEnumerator.Current; }
547-
}
548-
549-
object IEnumerator.Current
550-
{
551-
get { return Current; }
552-
}
553-
}
554-
555-
IEnumerator<Assembly> IEnumerable<Assembly>.GetEnumerator()
556-
{
557-
return new Enumerator(this);
558-
}
559-
}
560470
}
561471
}

src/runtime/constructorbinding.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public static IntPtr tp_descr_get(IntPtr op, IntPtr instance, IntPtr owner)
7575
return Exceptions.RaiseTypeError("How in the world could that happen!");
7676
}
7777
}*/
78-
Runtime.XIncref(self.pyHandle); // Decref'd by the interpreter.
78+
Runtime.XIncref(self.pyHandle);
7979
return self.pyHandle;
8080
}
8181

@@ -105,8 +105,6 @@ public static IntPtr mp_subscript(IntPtr op, IntPtr key)
105105
}
106106
var boundCtor = new BoundContructor(self.type, self.pyTypeHndl, self.ctorBinder, ci);
107107

108-
/* Since nothing is cached, do we need the increment???
109-
Runtime.XIncref(boundCtor.pyHandle); // Decref'd by the interpreter??? */
110108
return boundCtor.pyHandle;
111109
}
112110

src/runtime/converter.cs

+8
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,15 @@ internal static IntPtr ToPython(object value, Type type)
155155
var pyderived = value as IPythonDerivedType;
156156
if (null != pyderived)
157157
{
158+
#if NETSTANDARD
158159
return ClassDerivedObject.ToPython(pyderived);
160+
#else
161+
// if object is remote don't do this
162+
if (!System.Runtime.Remoting.RemotingServices.IsTransparentProxy(pyderived))
163+
{
164+
return ClassDerivedObject.ToPython(pyderived);
165+
}
166+
#endif
159167
}
160168

161169
// hmm - from Python, we almost never care what the declared

0 commit comments

Comments
 (0)