8000 add codec tests · pythonnet/pythonnet@0e37fbc · GitHub
[go: up one dir, main page]

Skip to content

Commit 0e37fbc

Browse files
committed
add codec tests
1 parent c8ac68a commit 0e37fbc

File tree

9 files changed

+308
-144
lines changed

9 files changed

+308
-144
lines changed

src/embed_tests/Codecs.cs

Lines changed: 167 additions & 134 deletions
Large diffs are not rendered by default.

src/runtime/Codecs/IterableDecoder.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ internal static bool IsIterable(Type targetType)
1919

2020
internal static bool IsIterable(PyObject objectType)
2121
{
22-
//TODO - do I need to decref iterObject?
23-
IntPtr iterObject = Runtime.PyObject_GetIter(objectType.Handle);
24-
return iterObject != IntPtr.Zero;
22+
return objectType.HasAttr("__iter__");
2523
}
2624

2725
public bool CanDecode(PyObject objectType, Type targetType)

src/runtime/Codecs/ListDecoder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ private static bool IsList(PyObject objectType)
1818
//must implement sequence protocol to fully implement list protocol
1919
if (!SequenceDecoder.IsSequence(objectType)) return false;
2020

21-
//returns wheter it implements the list protocol
22-
return Runtime.PyList_Check(objectType.Handle);
21+
//returns wheter the type is a list.
22+
return objectType.Handle == Runtime.PyListType;
2323
}
2424

2525
public bool CanDecode(PyObject objectType, Type targetType)

src/runtime/Codecs/SequenceDecoder.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ internal static bool IsSequence(PyObject objectType)
1818
//must implement iterable protocol to fully implement sequence protocol
1919
if (!IterableDecoder.IsIterable(objectType)) return false;
2020

21-
//returns wheter it implements the sequence protocol
22-
return Runtime.PySequence_Check(objectType.Handle);
21+
//returns wheter it implements the sequence protocol
22+
//according to python doc this needs to exclude dict subclasses
23+
//but I don't know how to look for that given the objectType
24+
//rather than the instance.
25+
return objectType.HasAttr("__getitem__");
2326
}
2427

2528
public bool CanDecode(PyObject objectType, Type targetType)

src/runtime/CollectionWrappers/IterableWrapper.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,21 @@ IEnumerator IEnumerable.GetEnumerator()
4747
public IEnumerator<T> GetEnumerator()
4848
{
4949
if (pyObject == null) yield break;
50-
PyObject iterObject = new PyObject(Runtime.PyObject_GetIter(pyObject.Handle));
51-
IntPtr item;
52-
while ((item = Runtime.PyIter_Next(iterObject.Handle)) != IntPtr.Zero)
50+
PyObject iterObject = null;
51+
using (Py.GIL())
5352
{
53+
iterObject = new PyObject(Runtime.PyObject_GetIter(pyObject.Handle));
54+
}
55+
56+
while (true)
57+
{
58+
IntPtr item = IntPtr.Zero;
59+
using (Py.GIL())
60+
{
61+
item = Runtime.PyIter_Next(iterObject.Handle);
62+
}
63+
if (item == IntPtr.Zero) break;
64+
5465
object obj = null;
5566
if (!Converter.ToManaged(item, typeof(T), out obj, true))
5667
{

src/testing/CodecTest.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace Python.Test
7+
{
8+
public class ListMember
9+
{
10+
public ListMember(int value, string name)
11+
{
12+
Value = value;
13+
Name = name;
14+
}
15+
16+
public int Value { get; set; }
17+
public string Name { get; set; }
18+
}
19+
20+
public class ListConversionTester
21+
{
22+
public int GetLength(IEnumerable<object> o)
23+
{
24+
return o.Count();
25+
}
26+
public int GetLength(ICollection<object> o)
27+
{
28+
return o.Count;
29+
}
30+
public int GetLength(IList<object> o)
31+
{
32+
return o.Count;
33+
}
34+
public int GetLength2(IEnumerable<ListMember> o)
35+
{
36+
return o.Count();
37+
}
38+
public int GetLength2(ICollection<ListMember> o)
39+
{
40+
return o.Count;
41+
}
42+
public int GetLength2(IList<ListMember> o)
43+
{
44+
return o.Count;
45+
}
46+
}
47+
}

src/testing/Python.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
<Compile Include="threadtest.cs" />
9292
<Compile Include="doctest.cs" />
9393
<Compile Include="subclasstest.cs" />
94+
<Compile Include="CodecTest.cs" />
9495
<Compile Include="ReprTest.cs" />
9596
<Compile Include="mp_lengthtest.cs" />
9697
</ItemGroup>

src/tests/test_codec.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""Test conversions using codecs from client python code"""
4+
import clr
5+
import System
6+
import pytest
7+
import Python.Runtime
8+
from Python.Test import ListConversionTester, ListMember
9+
10+
class int_iterable():
11+
def __init__(self):
12+
self.counter = 0
13+
def __iter__(self):
14+
return self
15+
def __next__(self):
16+
if self.counter == 3:
17+
raise StopIteration
18+
self.counter = self.counter + 1
19+
return self.counter
20+
21+
class obj_iterable():
22+
def __init__(self):
23+
self.counter = 0
24+
def __iter__(self):
25+
return self
26+
def __next__(self):
27+
if self.counter == 3:
28+
raise StopIteration
29+
self.counter = self.counter + 1
30+
return ListMember(self.counter, "Number " + str(self.counter))
31+
32+
def test_iterable():
33+
"""Test that a python iterable can be passed into a function that takes an IEnumerable<object>"""
34+
35+
#Python.Runtime.Codecs.ListDecoder.Register()
36+
#Python.Runtime.Codecs.SequenceDecoder.Register()
37+
Python.Runtime.Codecs.IterableDecoder.Register()
38+
ob = ListConversionTester()
39+
40+
iterable = int_iterable()
41+
assert 3 == ob.GetLength(iterable)
42+
43+
iterable2 = obj_iterable()
44+
assert 3 == ob.GetLength2(iterable2)
45+
46+
Python.Runtime.PyObjectConversions.Reset()
47+
48+
def test_sequence():
49+
Python.Runtime.Codecs.SequenceDecoder.Register()
50+
ob = ListConversionTester()
51+
52+
tup = (1,2,3)
53+
assert 3 == ob.GetLength(tup)
54+
55+
tup2 = (ListMember(1, "one"), ListMember(2, "two"), ListMember(3, "three"))
56+
assert 3 == ob.GetLength(tup2)
57+
58+
Python.Runtime.PyObjectConversions.Reset()
59+
60+
def test_list():
61+
Python.Runtime.Codecs.SequenceDecoder.Register()
62+
ob = ListConversionTester()
63+
64+
l = [1,2,3]
65+
assert 3 == ob.GetLength(l)
66+
67+
l2 = [ListMember(1, "one"), ListMember(2, "two"), ListMember(3, "three")]
68+
assert 3 == ob.GetLength(l2)
69+
70+
Python.Runtime.PyObjectConversions.Reset()

src/tests/tests.pyproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
<Compile Include="test_recursive_types.py" />
6060
<Compile Include="test_subclass.py" />
6161
<Compile Include="test_thread.py" />
62+
<Compile Include="test_codec.py" />
6263
<Compile Include="test_repr.py" />
6364
<Compile Include="utils.py" />
6465
<Compile Include="fixtures\argv-fixture.py" />

0 commit comments

Comments
0 (0)
0