[Python.NET] Re: Wrap in interface (#1240)

Victor “LOST” Milovanov <[email protected]> Mon, 8 Feb 2021 10:56:30 -0800
Newsgroups gmane.comp.python.dotnet
Message-ID <[email protected]>
--===============8220023346847500867==
Content-Type: multipart/related;
	boundary="_6CCED182-84FA-4A6B-B89F-23DF5A87480D_"

--_6CCED182-84FA-4A6B-B89F-23DF5A87480D_
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset="utf-8"

<html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-micr=
osoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" xmlns=3D"http:=
//www.w3.org/TR/REC-html40"><head><meta http-equiv=3DContent-Type content=
=3D"text/html; charset=3Dutf-8"><meta name=3DGenerator content=3D"Microsoft=
 Word 15 (filtered medium)"><!--[if !mso]><style>v\:* {behavior:url(#defaul=
t#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@font-face
	{font-family:"Cambria Math";
	panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
	{font-family:Calibri;
	panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
	{margin:0in;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
	{mso-style-priority:99;
	color:blue;
	text-decoration:underline;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
	{mso-style-priority:34;
	margin-top:0in;
	margin-right:0in;
	margin-bottom:0in;
	margin-left:.5in;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;}
p.xmsonormal, li.xmsonormal, div.xmsonormal
	{mso-style-name:x_msonormal;
	margin:0in;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;}
.MsoChpDefault
	{mso-style-type:export-only;}
@page WordSection1
	{size:8.5in 11.0in;
	margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
	{page:WordSection1;}
/* List Definitions */
@list l0
	{mso-list-id:1392969730;
	mso-list-type:hybrid;
	mso-list-template-ids:-406285992 -1 67698713 67698715 67698703 67698713 67=
698715 67698703 67698713 67698715;}
@list l0:level1
	{mso-level-tab-stop:none;
	mso-level-number-position:left;
	text-indent:-.25in;}
@list l0:level2
	{mso-level-number-format:alpha-lower;
	mso-level-tab-stop:none;
	mso-level-number-position:left;
	text-indent:-.25in;}
@list l0:level3
	{mso-level-number-format:roman-lower;
	mso-level-tab-stop:none;
	mso-level-number-position:right;
	text-indent:-9.0pt;}
@list l0:level4
	{mso-level-tab-stop:none;
	mso-level-number-position:left;
	text-indent:-.25in;}
@list l0:level5
	{mso-level-number-format:alpha-lower;
	mso-level-tab-stop:none;
	mso-level-number-position:left;
	text-indent:-.25in;}
@list l0:level6
	{mso-level-number-format:roman-lower;
	mso-level-tab-stop:none;
	mso-level-number-position:right;
	text-indent:-9.0pt;}
@list l0:level7
	{mso-level-tab-stop:none;
	mso-level-number-position:left;
	text-indent:-.25in;}
@list l0:level8
	{mso-level-number-format:alpha-lower;
	mso-level-tab-stop:none;
	mso-level-number-position:left;
	text-indent:-.25in;}
@list l0:level9
	{mso-level-number-format:roman-lower;
	mso-level-tab-stop:none;
	mso-level-number-position:right;
	text-indent:-9.0pt;}
ol
	{margin-bottom:0in;}
ul
	{margin-bottom:0in;}
--></style></head><body lang=3DEN-US link=3Dblue vlink=3D"#954F72" style=3D=
'word-wrap:break-word'><div class=3DWordSection1><p class=3DMsoNormal>A dum=
p of thoughts on the matter:</p><p class=3DMsoNormal><o:p>&nbsp;</o:p></p><=
ol style=3D'margin-top:0in' start=3D1 type=3D1><li class=3DMsoListParagraph=
 style=3D'margin-left:0in;mso-list:l0 level1 lfo1'>IronPython is Python 2 o=
nly, Python.NET 3.0+ is Python 3 only. Why not use 2.5.x until you are comf=
ortable to change API?</li><li class=3DMsoListParagraph style=3D'margin-lef=
t:0in;mso-list:l0 level1 lfo1'>Flag is possible, but I would not recommend =
that approach, because it makes combining multiple libraries that use diffe=
rent global flags problematic.</li><li class=3DMsoListParagraph style=3D'ma=
rgin-left:0in;mso-list:l0 level1 lfo1'>Perhaps we could allow codecs to han=
dle instances of wrapped interfaces (actually, isn=E2=80=99t that currently=
 allowed?)</li><li class=3DMsoListParagraph style=3D'margin-left:0in;mso-li=
st:l0 level1 lfo1'>IronPython apparently allows explicit interface implemen=
tations to be called (instead of returning interface-wrapped instances), if=
 there=E2=80=99s no conflict with regular methods. Perhaps we should consid=
er this as an option.</li><li class=3DMsoListParagraph style=3D'margin-left=
:0in;mso-list:l0 level1 lfo1'>Alternatively, we can keep wrapped instances,=
 but allow to resolve public members too if the method is not found in the =
interface. I like this option better than 4, because actual type of an elem=
ent in ISomething[] won=E2=80=99t change behavior of invoking interface mem=
ber. It might still affect `hasattr`, but this is somewhat expected.</li></=
ol><p class=3DMsoNormal><o:p>&nbsp;</o:p></p><p class=3DMsoNormal>Regards,<=
/p><p class=3DMsoNormal>Victor</p><p class=3DMsoNormal><o:p>&nbsp;</o:p></p=
><div style=3D'mso-element:para-border-div;border:none;border-top:solid #E1=
E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><p class=3DMsoNormal style=3D'border:=
none;padding:0in'><b>From: </b><a href=3D"mailto:[email protected]">=
Mohamed Koubaa</a><br><b>Sent: </b>Monday, February 8, 2021 8:34 AM<br><b>T=
o: </b><a href=3D"mailto:[email protected]">A list for users and develop=
ers of Python.NET</a><br><b>Subject: </b>[Python.NET] Re: Wrap in interface=
 (#1240)</p></div><p class=3DMsoNormal><o:p>&nbsp;</o:p></p><div><p class=
=3DMsoNormal><span style=3D'font-size:12.0pt;color:black'>Victor,<o:p></o:p=
></span></p></div><div><p class=3DMsoNormal><span style=3D'font-size:12.0pt=
;color:black'><o:p>&nbsp;</o:p></span></p></div><div><p class=3DMsoNormal><=
span style=3D'font-size:12.0pt;color:black'>Sorry for the late response.&nb=
sp; I think what I would need is some kind of flag in the python runtime to=
 choose the old behavior (without having to have my own branch).&nbsp; Of c=
ourse there is a workaround but we've invested a lot of time in designing t=
he API for both CPython &amp; IronPython and it would be ideal if they did =
not differ in this way.&nbsp;&nbsp;<o:p></o:p></span></p></div><div><p clas=
s=3DMsoNormal><span style=3D'font-size:12.0pt;color:black'><o:p>&nbsp;</o:p=
></span></p></div><div><p class=3DMsoNormal><span style=3D'font-size:12.0pt=
;color:black'>This could be a global flag on the runtime and/or an attribut=
e on a class/interface to decide on a granular level whether the specific c=
lass/interface will use interface method binding or instance method binding=
.<o:p></o:p></span></p></div><div><p class=3DMsoNormal><span style=3D'font-=
size:12.0pt;color:black'><o:p>&nbsp;</o:p></span></p></div><div><p class=3D=
MsoNormal><span style=3D'font-size:12.0pt;color:black'>Thoughts?<o:p></o:p>=
</span></p></div><div><p class=3DMsoNormal><span style=3D'font-size:12.0pt;=
color:black'><o:p>&nbsp;</o:p></span></p></div><div><p class=3DMsoNormal><s=
pan style=3D'font-size:12.0pt;color:black'>Thanks!<o:p></o:p></span></p></d=
iv><div><p class=3DMsoNormal><span style=3D'font-size:12.0pt;color:black'>M=
ohamed<o:p></o:p></span></p></div><p class=3DMsoNormal><img border=3D0 widt=
h=3D694 height=3D2 style=3D'width:7.2291in;height:.0208in' id=3D"Horizontal=
_x0020_Line_x0020_1" src=3D"cid:image001.png-CFHuyTl/[email protected]"><o:p></o:p>=
</p><div id=3DdivRplyFwdMsg><p class=3DMsoNormal><b><span style=3D'color:bl=
ack'>From:</span></b><span style=3D'color:black'> Victor =E2=80=9CLOST=E2=
=80=9D Milovanov &lt;[email protected]&gt;<br><b>Sent:</b> Monday, Nove=
mber 2, 2020 8:35 PM<br><b>To:</b> A list for users and developers of Pytho=
n.NET &lt;[email protected]&gt;<br><b>Subject:</b> [Python.NET] Re: Wrap=
 in interface (#1240)</span> <o:p></o:p></p><div><p class=3DMsoNormal>&nbsp=
;<o:p></o:p></p></div></div><div><div style=3D'border:solid #9C6500 1.0pt;p=
adding:2.0pt 2.0pt 2.0pt 2.0pt'><p style=3D'line-height:12.0pt;background:#=
FFEB9C'><b><span style=3D'font-size:10.0pt;color:red'>[External Sender]</sp=
an></b></p></div><div><div><p class=3Dxmsonormal>The original bug report de=
scribed a similar problem, except the behavior without defaulting to strict=
er interface types is very unintuitive. Imagine you have a well documented =
library, that exposes property <b>Prop</b> of type <b>IInterface</b>. When =
specific class implements some <b>Method</b> &nbsp;in <b>IInterface</b> exp=
licitly (which arguably is a very minor implementation detail), and you cal=
l <b>Prop.Method()</b> in Python, it can fail with AttributeError despite t=
he documentation claiming this method exists on the interface. This is very=
 confusing. IMHO, more confusing, than inability to get Length of an elemen=
t of <b>IShape[]</b>.</p><p class=3Dxmsonormal>&nbsp;</p><p class=3Dxmsonor=
mal>We could try to improve the situation for Python folks by allowing inte=
rface instance wrappers to fall back to the original class instance in case=
 the attribute is not found in the interface itself. I think this might sti=
ll be problematic, as it would make the behavior of hasattr and other simil=
ar functions a bit surprising.</p><p class=3Dxmsonormal>&nbsp;</p><p class=
=3Dxmsonormal>Regardless, there=E2=80=99s a workaround for the scenario you=
 described which is just doing <b>m.GetShape(1).__raw_implementation__.Leng=
th </b>or </p><p class=3Dxmsonormal><b>m.GetShape(1).__implementation__.Len=
gth </b>depending if you need an encoded instance.</p><p class=3Dxmsonormal=
>&nbsp;</p><p class=3Dxmsonormal>Regards,</p><p class=3Dxmsonormal>Victor M=
ilovanov</p><p class=3Dxmsonormal>&nbsp;</p><div style=3D'border:none;borde=
r-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><p class=3Dxmsonormal>=
<b>From: </b><a href=3D"mailto:[email protected]">Mohamed Koubaa</a>=
<br><b>Sent: </b>Monday, November 2, 2020 6:15 PM<br><b>To: </b><a href=3D"=
mailto:[email protected]">[email protected]</a><br><b>Subject: </b>[P=
ython.NET] Wrap in interface (#1240)</p></div><p class=3Dxmsonormal>&nbsp;<=
/p><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;color:black'>=
Hello,</span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:=
12.0pt;color:black'>&nbsp;</span></p></div><div><p class=3Dxmsonormal><span=
 style=3D'font-size:12.0pt;color:black'>This <a href=3D"https://nam10.safel=
inks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fgithub.com%2Fpythonnet%2Fp=
ythonnet%2Fpull%2F1240&amp;data=3D04%7C01%7Cmohamed.koubaa%40ansys.com%7C37=
b0dd3831f140993f6008d87fa1418f%7C34c6ce6715b84eff80e952da8be89706%7C0%7C0%7=
C637399677854765584%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2l=
uMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=3DtTftofPt0a7ds4g1qBjL=
IBXi7iFOgtygMW3Xa3WHF%2Fo%3D&amp;reserved=3D0" title=3D"https://github.com/=
pythonnet/pythonnet/pull/1240">PR</a>&nbsp;changed behavior of pythonnet to=
 use stricter typing when a method returns an interface.&nbsp; I'd like a w=
ay to opt-out of this behavior, and I'll share a representative use-case be=
low.&nbsp; The tl;dr is that python is a dynamic language and I expect the =
C# objects which pythonnet wraps to behave more like &quot;dynamic&quot; an=
d less like the static types on the interface.</span></p></div><div><p clas=
s=3Dxmsonormal><span style=3D'font-size:12.0pt;color:black'>&nbsp;</span></=
p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;color:bl=
ack'>**** C# code ****</span></p></div><div><p class=3Dxmsonormal><span sty=
le=3D'font-size:12.0pt;font-family:"Courier New";color:black'>namespace Exa=
mple1</span><span style=3D'font-size:12.0pt;color:black'> </span></p><div><=
p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier N=
ew";color:black'>{</span></p></div><div><p class=3Dxmsonormal><span style=
=3D'font-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nbsp; p=
ublic enum ShapeType</span></p></div><div><p class=3Dxmsonormal><span style=
=3D'font-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nbsp; {=
</span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt=
;font-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; Square,=
</span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt=
;font-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; Circle<=
/span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;=
font-family:"Courier New";color:black'>&nbsp; &nbsp; }</span></p></div><div=
><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier=
 New";color:black'>&nbsp; &nbsp; public interface IShape</span></p></div><d=
iv><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Couri=
er New";color:black'>&nbsp; &nbsp; {</span></p></div><div><p class=3Dxmsono=
rmal><span style=3D'font-size:12.0pt;font-family:"Courier New";color:black'=
>&nbsp; &nbsp; &nbsp; &nbsp; void Draw();</span></p></div><div><p class=3Dx=
msonormal><span style=3D'font-size:12.0pt;color:black'>&nbsp;</span></p></d=
iv><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"=
Courier New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; double Area { get; }<=
/span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;=
color:black'>&nbsp;</span></p></div><div><p class=3Dxmsonormal><span style=
=3D'font-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nbsp; &=
nbsp; &nbsp; ShapeType Type { get; }</span></p></div><div><p class=3Dxmsono=
rmal><span style=3D'font-size:12.0pt;font-family:"Courier New";color:black'=
>&nbsp; &nbsp; }</span></p></div><div><p class=3Dxmsonormal><span style=3D'=
font-size:12.0pt;color:black'>&nbsp;</span></p></div><div><p class=3Dxmsono=
rmal><span style=3D'font-size:12.0pt;font-family:"Courier New";color:black'=
>&nbsp; &nbsp; public class Square : IShape</span></p></div><div><p class=
=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier New";col=
or:black'>&nbsp; &nbsp; {</span></p></div><div><p class=3Dxmsonormal><span =
style=3D'font-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nb=
sp; &nbsp; &nbsp; public double Length { get; }</span></p></div><div><p cla=
ss=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier New";c=
olor:black'>&nbsp; &nbsp; &nbsp; &nbsp; public Square(double length)</span>=
</p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-f=
amily:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; {</span></p></=
div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:=
"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Length=
 =3D length;</span></p></div><div><p class=3Dxmsonormal><span style=3D'font=
-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &n=
bsp; }</span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:=
12.0pt;color:black'>&nbsp;</span></p></div><div><p class=3Dxmsonormal><span=
 style=3D'font-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &n=
bsp; &nbsp; &nbsp; public void Draw() {}</span></p></div><div><p class=3Dxm=
sonormal><span style=3D'font-size:12.0pt;font-family:"Courier New";color:bl=
ack'>&nbsp; &nbsp; &nbsp; &nbsp; public double Area { get { return Length *=
 Length; } }</span></p></div><div><p class=3Dxmsonormal><span style=3D'font=
-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &n=
bsp; public ShapeType Type { get { return ShapeType.Square; } }</span></p><=
/div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family=
:"Courier New";color:black'>&nbsp; &nbsp; }</span></p></div><div><p class=
=3Dxmsonormal><span style=3D'font-size:12.0pt;color:black'>&nbsp;</span></p=
></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-fami=
ly:"Courier New";color:black'>&nbsp; &nbsp; public class Circle : IShape</s=
pan></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;fo=
nt-family:"Courier New";color:black'>&nbsp; &nbsp; {</span></p></div><div><=
p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier N=
ew";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; public double Radius { get; }<=
/span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;=
font-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; public C=
ircle(double radius)</span></p></div><div><p class=3Dxmsonormal><span style=
=3D'font-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nbsp; &=
nbsp; &nbsp; {</span></p></div><div><p class=3Dxmsonormal><span style=3D'fo=
nt-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; =
&nbsp; &nbsp; &nbsp; Radius =3D radius;</span></p></div><div><p class=3Dxms=
onormal><span style=3D'font-size:12.0pt;font-family:"Courier New";color:bla=
ck'>&nbsp; &nbsp; &nbsp; &nbsp; }</span></p></div><div><p class=3Dxmsonorma=
l><span style=3D'font-size:12.0pt;color:black'>&nbsp;</span></p></div><div>=
<p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier =
New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; public void Draw() {}</span><=
/p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-fa=
mily:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; public double A=
rea { get { return Math.PI * Radius * Radius; } }</span></p></div><div><p c=
lass=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier New"=
;color:black'>&nbsp; &nbsp; &nbsp; &nbsp; public ShapeType Type { get { ret=
urn ShapeType.Circle; } }</span></p></div><div><p class=3Dxmsonormal><span =
style=3D'font-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nb=
sp; }</span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:1=
2.0pt;color:black'>&nbsp;</span></p></div><div><p class=3Dxmsonormal><span =
style=3D'font-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nb=
sp; public class ShapeDataModel</span></p></div><div><p class=3Dxmsonormal>=
<span style=3D'font-size:12.0pt;font-family:"Courier New";color:black'>&nbs=
p; &nbsp; {</span></p></div><div><p class=3Dxmsonormal><span style=3D'font-=
size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &nb=
sp; private Dictionary&lt;int, IShape&gt; _shapes =3D new Dictionary&lt;int=
, IShape&gt;();</span></p></div><div><p class=3Dxmsonormal><span style=3D'f=
ont-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp;=
 &nbsp; private int _nextId =3D 1;</span></p></div><div><p class=3Dxmsonorm=
al><span style=3D'font-size:12.0pt;color:black'>&nbsp;</span></p></div><div=
><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier=
 New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; public int AddShape(IShape s=
hape)</span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:1=
2.0pt;font-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; {<=
/span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;=
font-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &=
nbsp; int id =3D _nextId;</span></p></div><div><p class=3Dxmsonormal><span =
style=3D'font-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nb=
sp; &nbsp; &nbsp; &nbsp; &nbsp; _shapes[id] =3D shape;</span></p></div><div=
><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier=
 New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _nextId++;</sp=
an></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;fon=
t-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbs=
p; return id;</span></p></div><div><p class=3Dxmsonormal><span style=3D'fon=
t-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &=
nbsp; }</span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size=
:12.0pt;color:black'>&nbsp;</span></p></div><div><p class=3Dxmsonormal><spa=
n style=3D'font-size:12.0pt;font-family:"Courier New";color:black'>&nbsp; &=
nbsp; &nbsp; &nbsp; public IShape GetShape(int id)</span></p></div><div><p =
class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier New=
";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; {</span></p></div><div><p class=
=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier New";col=
or:black'>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return _shapes[id];</sp=
an></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;fon=
t-family:"Courier New";color:black'>&nbsp; &nbsp; &nbsp; &nbsp; }</span></p=
></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-fami=
ly:"Courier New";color:black'>&nbsp; &nbsp; }</span></p></div><div><p class=
=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier New";col=
or:black'>}</span></p></div><p class=3Dxmsonormal><span style=3D'font-size:=
12.0pt;color:black'>&nbsp;</span></p></div><div><p class=3Dxmsonormal><span=
 style=3D'font-size:12.0pt;color:black'>&nbsp;</span></p></div><div><p clas=
s=3Dxmsonormal><span style=3D'font-size:12.0pt;color:black;background:#181A=
1B'>**** Python code ****</span></p></div><div><p class=3Dxmsonormal><span =
style=3D'font-size:12.0pt;font-family:"Courier New";color:black;background:=
#131516'>&gt;&gt;&gt; import clr</span></p></div><div><p class=3Dxmsonormal=
><span style=3D'font-size:12.0pt;font-family:"Courier New";color:black;back=
ground:#131516'>&gt;&gt;&gt; clr.AddReference(&quot;Example1&quot;)</span><=
/p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-fa=
mily:"Courier New";color:black;background:#131516'>&gt;&gt;&gt; import Exam=
ple1</span></p></div><div><div><p class=3Dxmsonormal><span style=3D'font-si=
ze:12.0pt;font-family:"Courier New";color:black;background:#131516'>&gt;&gt=
;&gt; sq1 =3D Example1.Square(2.)</span></p></div><div><p class=3Dxmsonorma=
l><span style=3D'font-size:12.0pt;font-family:"Courier New";color:black;bac=
kground:#131516'>&gt;&gt;&gt; ci1 =3D Example1.Circle(1.3)</span></p></div>=
<div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Cou=
rier New";color:black;background:#131516'>&gt;&gt;&gt; sq2 =3D Example1.Squ=
are(2.5)</span></p></div><div><p class=3Dxmsonormal><span style=3D'font-siz=
e:12.0pt;font-family:"Courier New";color:black;background:#131516'>&gt;&gt;=
&gt; m =3D Example1.ShapeDataModel()</span></p></div><div><p class=3Dxmsono=
rmal><span style=3D'font-size:12.0pt;font-family:"Courier New";color:black;=
background:#131516'>&gt;&gt;&gt; m.AddShape(sq1)</span></p></div><div><p cl=
ass=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier New";=
color:black;background:#131516'>1</span></p></div><div><p class=3Dxmsonorma=
l><span style=3D'font-size:12.0pt;font-family:"Courier New";color:black;bac=
kground:#131516'>&gt;&gt;&gt; m.AddShape(sq2)</span></p></div><div><p class=
=3Dxmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier New";col=
or:black;background:#131516'>2</span></p></div><div><p class=3Dxmsonormal><=
span style=3D'font-size:12.0pt;font-family:"Courier New";color:black;backgr=
ound:#131516'>&gt;&gt;&gt; m.AddShape(ci1)</span></p></div><div><p class=3D=
xmsonormal><span style=3D'font-size:12.0pt;font-family:"Courier New";color:=
black;background:#131516'>3</span></p></div><div><p class=3Dxmsonormal><spa=
n style=3D'font-size:12.0pt;font-family:"Courier New";color:black;backgroun=
d:#131516'>&gt;&gt;&gt; m.GetShape(2)</span></p></div><div><p class=3Dxmson=
ormal><span style=3D'font-size:12.0pt;font-family:"Courier New";color:black=
;background:#131516'>&lt;Example1.IShape object at 0x000002A3448A09A0&gt;</=
span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;f=
ont-family:"Courier New";color:black;background:#131516'>&gt;&gt;&gt; m.Get=
Shape(2).Area</span></p></div><div><p class=3Dxmsonormal><span style=3D'fon=
t-size:12.0pt;font-family:"Courier New";color:black;background:#131516'>6.2=
5</span></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0p=
t;font-family:"Courier New";color:black;background:#131516'>&gt;&gt;&gt; m.=
GetShape(2).Length</span></p></div><div><p class=3Dxmsonormal><span style=
=3D'font-size:12.0pt;font-family:"Courier New";color:black;background:#1315=
16'>Traceback (most recent call last):</span></p></div><div><p class=3Dxmso=
normal><span style=3D'font-size:12.0pt;font-family:"Courier New";color:#ED5=
C57;background:#131516'>&nbsp; File &quot;&lt;stdin&gt;&quot;, line 1, in &=
lt;module&gt;</span></p></div><div><p class=3Dxmsonormal><span style=3D'fon=
t-size:12.0pt;font-family:"Courier New";color:#ED5C57;background:#131516'>A=
ttributeError: 'IShape' object has no attribute 'Length'</span></p></div></=
div><div><p class=3Dxmsonormal style=3D'margin-bottom:12.0pt'><o:p>&nbsp;</=
o:p></p></div><div><p class=3Dxmsonormal><span style=3D'font-size:12.0pt;co=
lor:black;background:#131516'>**** summary ****</span></p></div><div><p cla=
ss=3Dxmsonormal><span style=3D'font-size:12.0pt;color:black;background:#131=
516'>This factory and/or datamodel pattern is very common in my codebase an=
d probably also lots of object oriented systems.&nbsp; The mentioned PR bre=
aks this common design pattern in C# objects wrapped by pythonnet, and I wo=
uld like a way to opt-out of it.&nbsp; Maybe an attribute on the method whi=
ch returns an interface can be used, or maybe something global to switch th=
is behavior.&nbsp; I think perhaps the original bug might also have been fi=
xed in a different way.&nbsp;</span></p></div><div><p class=3Dxmsonormal st=
yle=3D'margin-bottom:12.0pt'><o:p>&nbsp;</o:p></p></div><p class=3Dxmsonorm=
al><span style=3D'font-size:12.0pt;color:black;background:#131516'>Thanks!<=
br>Mohamed</span></p></div></div></div><p class=3Dxmsonormal>&nbsp;</p><p c=
lass=3DMsoNormal><o:p>&nbsp;</o:p></p></div></body></html>=

--_6CCED182-84FA-4A6B-B89F-23DF5A87480D_
Content-Type: image/png; name="C081996CDAA945DBACD618306EE5771E.png"
Content-ID: <image001.png-CFHuyTl/[email protected]>
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename="C081996CDAA945DBACD618306EE5771E.png"

iVBORw0KGgoAAAANSUhEUgAAArYAAAACCAYAAACtx5+mAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
jwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAlSURBVFhH7cMBDQAABAAw/UtJIIEw5GD/9gAA
gBeyelRV9faeBRsQNwwY9nKzAAAAAElFTkSuQmCC

--_6CCED182-84FA-4A6B-B89F-23DF5A87480D_--

--===============8220023346847500867==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
PythonNet mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/pythonnet.python.org/
Member address: [email protected]

--===============8220023346847500867==--