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
This repository was archived by the owner on Jul 22, 2023. It is now read-only.
/pythonnetPublic archive
forked frompythonnet/pythonnet

Commit4a9457f

Browse files
koubaafilmor
authored andcommitted
Provide hook to implement __repr__ (pythonnet#808)
Provide hook to implement __repr__
1 parent60e6045 commit4a9457f

File tree

9 files changed

+244
-6
lines changed

9 files changed

+244
-6
lines changed

‎AUTHORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
- Luke Stratman ([@lstratman](https://github.com/lstratman))
4242
- Konstantin Posudevskiy ([@konstantin-posudevskiy](https://github.com/konstantin-posudevskiy))
4343
- Matthias Dittrich ([@matthid](https://github.com/matthid))
44+
- Mohamed Koubaa ([@koubaa](https://github.com/koubaa))
4445
- Patrick Stewart ([@patstew](https://github.com/patstew))
4546
- Raphael Nestler ([@rnestler](https://github.com/rnestler))
4647
- Rickard Holmberg ([@rickardraysearch](https://github.com/rickardraysearch))

‎CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
4646
- Added PyObject finalizer support, Python objects referred by C# can be auto collect now ([#692][p692]).
4747
- Added detailed comments about aproaches and dangers to handle multi-app-domains ([#625][p625])
4848
- Python 3.7 support, builds and testing added. Defaults changed from Python 3.6 to 3.7 ([#698][p698])
49+
- Added support for C# types to provide`__repr__` ([#680][p680])
4950

5051
###Changed
5152

‎src/runtime/classbase.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,44 @@ public static IntPtr tp_str(IntPtr ob)
246246
}
247247
}
248248

249+
publicstaticIntPtrtp_repr(IntPtrob)
250+
{
251+
varco=GetManagedObject(ob)asCLRObject;
252+
if(co==null)
253+
{
254+
returnExceptions.RaiseTypeError("invalid object");
255+
}
256+
try
257+
{
258+
//if __repr__ is defined, use it
259+
varinstType=co.inst.GetType();
260+
System.Reflection.MethodInfomethodInfo=instType.GetMethod("__repr__");
261+
if(methodInfo!=null&&methodInfo.IsPublic)
262+
{
263+
varreprString=methodInfo.Invoke(co.inst,null)asstring;
264+
returnRuntime.PyString_FromString(reprString);
265+
}
266+
267+
//otherwise use the standard object.__repr__(inst)
268+
IntPtrargs=Runtime.PyTuple_New(1);
269+
Runtime.PyTuple_SetItem(args,0,ob);
270+
IntPtrreprFunc=Runtime.PyObject_GetAttrString(Runtime.PyBaseObjectType,"__repr__");
271+
varoutput=Runtime.PyObject_Call(reprFunc,args,IntPtr.Zero);
272+
Runtime.XDecref(args);
273+
Runtime.XDecref(reprFunc);
274+
returnoutput;
275+
}
276+
catch(Exceptione)
277+
{
278+
if(e.InnerException!=null)
279+
{
280+
e=e.InnerException;
281+
}
282+
Exceptions.SetError(e);
283+
returnIntPtr.Zero;
284+
}
285+
}
286+
249287

250288
/// <summary>
251289
/// Standard dealloc implementation for instances of reflected types.

‎src/runtime/exceptions.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,29 @@ internal static Exception ToException(IntPtr ob)
3636
returne;
3737
}
3838

39+
/// <summary>
40+
/// Exception __repr__ implementation
41+
/// </summary>
42+
publicnewstaticIntPtrtp_repr(IntPtrob)
43+
{
44+
Exceptione=ToException(ob);
45+
if(e==null)
46+
{
47+
returnExceptions.RaiseTypeError("invalid object");
48+
}
49+
stringname=e.GetType().Name;
50+
stringmessage;
51+
if(e.Message!=String.Empty)
52+
{
53+
message=String.Format("{0}('{1}')",name,e.Message);
54+
}
55+
else
56+
{
57+
message=String.Format("{0}()",name);
58+
}
59+
returnRuntime.PyUnicode_FromString(message);
60+
}
61+
3962
/// <summary>
4063
/// Exception __str__ implementation
4164
/// </summary>

‎src/testing/Python.Test.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
<CompileInclude="threadtest.cs" />
9292
<CompileInclude="doctest.cs" />
9393
<CompileInclude="subclasstest.cs" />
94+
<CompileInclude="ReprTest.cs" />
9495
</ItemGroup>
9596
<ItemGroup>
9697
<ReferenceInclude="Microsoft.CSharp" />
@@ -111,4 +112,4 @@
111112
<CopySourceFiles="$(TargetAssembly)"DestinationFolder="$(SolutionDir)\src\tests\fixtures" />
112113
<!--Copy SourceFiles="$(TargetAssemblyPdb)" Condition="Exists('$(TargetAssemblyPdb)')" DestinationFolder="$(PythonBuildDir)" /-->
113114
</Target>
114-
</Project>
115+
</Project>

‎src/testing/ReprTest.cs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
usingSystem;
2+
usingSystem.Text;
3+
4+
namespacePython.Test
5+
{
6+
/// <summary>
7+
/// Supports repr unit tests.
8+
/// </summary>
9+
publicclassReprTest
10+
{
11+
publicclassPoint
12+
{
13+
publicPoint(doublex,doubley)
14+
{
15+
X=x;
16+
Y=y;
17+
}
18+
19+
publicdoubleX{get;set;}
20+
publicdoubleY{get;set;}
21+
22+
publicoverridestringToString()
23+
{
24+
returnbase.ToString()+": X="+X.ToString()+", Y="+Y.ToString();
25+
}
26+
27+
publicstring__repr__()
28+
{
29+
return"Point("+X.ToString()+","+Y.ToString()+")";
30+
}
31+
}
32+
33+
publicclassFoo
34+
{
35+
publicstring__repr__()
36+
{
37+
return"I implement __repr__() but not ToString()!";
38+
}
39+
}
40+
41+
publicclassBar
42+
{
43+
publicoverridestringToString()
44+
{
45+
return"I implement ToString() but not __repr__()!";
46+
}
47+
}
48+
49+
publicclassBazBase
50+
{
51+
publicoverridestringToString()
52+
{
53+
return"Base class implementing ToString()!";
54+
}
55+
}
56+
57+
publicclassBazMiddle:BazBase
58+
{
59+
publicoverridestringToString()
60+
{
61+
return"Middle class implementing ToString()!";
62+
}
63+
}
64+
65+
//implements ToString via BazMiddle
66+
publicclassBaz:BazMiddle
67+
{
68+
69+
}
70+
71+
publicclassQuux
72+
{
73+
publicstringToString(stringformat)
74+
{
75+
return"I implement ToString() with an argument!";
76+
}
77+
}
78+
79+
publicclassQuuzBase
80+
{
81+
protectedstring__repr__()
82+
{
83+
return"I implement __repr__ but it isn't public!";
84+
}
85+
}
86+
87+
publicclassQuuz:QuuzBase
88+
{
89+
90+
}
91+
92+
publicclassCorge
93+
{
94+
publicstring__repr__(inti)
95+
{
96+
return"__repr__ implemention with input parameter!";
97+
}
98+
}
99+
100+
publicclassGrault
101+
{
102+
publicint__repr__()
103+
{
104+
return"__repr__ implemention with wrong return type!".Length;
105+
}
106+
}
107+
}
108+
}

‎src/tests/test_exceptions.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -282,11 +282,8 @@ def test_python_compat_of_managed_exceptions():
282282

283283
asserte.args== (msg,)
284284
assertisinstance(e.args,tuple)
285-
ifPY3:
286-
strexp="OverflowException('Simple message"
287-
assertrepr(e)[:len(strexp)]==strexp
288-
elifPY2:
289-
assertrepr(e)=="OverflowException(u'Simple message',)"
285+
strexp="OverflowException('Simple message"
286+
assertrepr(e)[:len(strexp)]==strexp
290287

291288

292289
deftest_exception_is_instance_of_system_object():

‎src/tests/test_repr.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""Test __repr__ output"""
4+
5+
importSystem
6+
importpytest
7+
fromPython.TestimportReprTest
8+
9+
deftest_basic():
10+
"""Test Point class which implements both ToString and __repr__ without inheritance"""
11+
ob=ReprTest.Point(1,2)
12+
# point implements ToString() and __repr__()
13+
assertob.__repr__()=="Point(1,2)"
14+
assertstr(ob)=="Python.Test.ReprTest+Point: X=1, Y=2"
15+
16+
deftest_system_string():
17+
"""Test system string"""
18+
ob=System.String("hello")
19+
assertstr(ob)=="hello"
20+
assert"<System.String object at "inob.__repr__()
21+
22+
deftest_str_only():
23+
"""Test class implementing ToString() but not __repr__()"""
24+
ob=ReprTest.Bar()
25+
assertstr(ob)=="I implement ToString() but not __repr__()!"
26+
assert"<Python.Test.Bar object at "inob.__repr__()
27+
28+
deftest_hierarchy1():
29+
"""Test inheritance heirarchy with base & middle class implementing ToString"""
30+
ob1=ReprTest.BazBase()
31+
assertstr(ob1)=="Base class implementing ToString()!"
32+
assert"<Python.Test.BazBase object at "inob1.__repr__()
33+
34+
ob2=ReprTest.BazMiddle()
35+
assertstr(ob2)=="Middle class implementing ToString()!"
36+
assert"<Python.Test.BazMiddle object at "inob2.__repr__()
37+
38+
ob3=ReprTest.Baz()
39+
assertstr(ob3)=="Middle class implementing ToString()!"
40+
assert"<Python.Test.Baz object at "inob3.__repr__()
41+
42+
defbad_tostring():
43+
"""Test ToString that can't be used by str()"""
44+
ob=ReprTest.Quux()
45+
assertstr(ob)=="Python.Test.ReprTest+Quux"
46+
assert"<Python.Test.Quux object at "inob.__repr__()
47+
48+
defbad_repr():
49+
"""Test incorrect implementation of repr"""
50+
ob1=ReprTest.QuuzBase()
51+
assertstr(ob1)=="Python.Test.ReprTest+QuuzBase"
52+
assert"<Python.Test.QuuzBase object at "inob.__repr__()
53+
54+
ob2=ReprTest.Quuz()
55+
assertstr(ob2)=="Python.Test.ReprTest+Quuz"
56+
assert"<Python.Test.Quuz object at "inob.__repr__()
57+
58+
ob3=ReprTest.Corge()
59+
withpytest.raises(Exception):
60+
str(ob3)
61+
withpytest.raises(Exception):
62+
ob3.__repr__()
63+
64+
ob4=ReprTest.Grault()
65+
withpytest.raises(Exception):
66+
str(ob4)
67+
withpytest.raises(Exception):
68+
ob4.__repr__()

‎src/tests/tests.pyproj

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp