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

Commit21c5dcc

Browse files
committed
implemented dynamic equality and inequality for PyObject instances
fixed unhandled Python errors during comparison attemptsfixes#1848
1 parenta49f3a8 commit21c5dcc

File tree

4 files changed

+83
-41
lines changed

4 files changed

+83
-41
lines changed

‎CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ details about the cause of the failure
4545
able to access members that are part of the implementation class, but not the
4646
interface. Use the new`__implementation__` or`__raw_implementation__` properties to
4747
if you need to "downcast" to the implementation class.
48+
- BREAKING:`==` and`!=` operators on`PyObject` instances now use Python comparison
49+
(previously was equivalent to`object.ReferenceEquals(,)`)
4850
- BREAKING: Parameters marked with`ParameterAttributes.Out` are no longer returned in addition
4951
to the regular method return value (unless they are passed with`ref` or`out` keyword).
5052
- BREAKING: Drop support for the long-deprecated CLR.* prefix.

‎src/embed_tests/dynamic.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,28 @@ public void PassPyObjectInNet()
128128
Assert.IsTrue(sys.testattr1.Equals(sys.testattr2));
129129
}
130130

131+
// regression test for https://github.com/pythonnet/pythonnet/issues/1848
132+
[Test]
133+
publicvoidEnumEquality()
134+
{
135+
usingvarscope=Py.CreateScope();
136+
scope.Exec(@"
137+
import enum
138+
139+
class MyEnum(enum.IntEnum):
140+
OK = 1
141+
ERROR = 2
142+
143+
def get_status():
144+
return MyEnum.OK
145+
"
146+
);
147+
148+
dynamicMyEnum=scope.Get("MyEnum");
149+
dynamicstatus=scope.Get("get_status").Invoke();
150+
Assert.IsTrue(status==MyEnum.OK);
151+
}
152+
131153
// regression test for https://github.com/pythonnet/pythonnet/issues/1680
132154
[Test]
133155
publicvoidForEach()

‎src/runtime/PythonTypes/PyObject.cs

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,12 +1075,9 @@ public virtual bool Equals(PyObject? other)
10751075
{
10761076
returntrue;
10771077
}
1078-
intr=Runtime.PyObject_Compare(this,other);
1079-
if(Exceptions.ErrorOccurred())
1080-
{
1081-
throwPythonException.ThrowLastAsClrException();
1082-
}
1083-
returnr==0;
1078+
intresult=Runtime.PyObject_RichCompareBool(obj,other.obj,Runtime.Py_EQ);
1079+
if(result<0)throwPythonException.ThrowLastAsClrException();
1080+
returnresult!=0;
10841081
}
10851082

10861083

@@ -1304,6 +1301,18 @@ public override bool TryConvert(ConvertBinder binder, out object? result)
13041301
returnfalse;
13051302
}
13061303

1304+
privateboolTryCompare(PyObjectarg,intop,outobject@out)
1305+
{
1306+
intresult=Runtime.PyObject_RichCompareBool(this.obj,arg.obj,op);
1307+
@out=result!=0;
1308+
if(result<0)
1309+
{
1310+
Exceptions.Clear();
1311+
returnfalse;
1312+
}
1313+
returntrue;
1314+
}
1315+
13071316
publicoverrideboolTryBinaryOperation(BinaryOperationBinderbinder,objectarg,outobject?result)
13081317
{
13091318
usingvar_=Py.GIL();
@@ -1352,32 +1361,29 @@ public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg
13521361
res=Runtime.PyNumber_InPlaceXor(this.obj,((PyObject)arg).obj);
13531362
break;
13541363
caseExpressionType.GreaterThan:
1355-
result=Runtime.PyObject_Compare(this.obj,((PyObject)arg).obj)>0;
1356-
returntrue;
1364+
returnthis.TryCompare((PyObject)arg,Runtime.Py_GT,outresult);
13571365
caseExpressionType.GreaterThanOrEqual:
1358-
result=Runtime.PyObject_Compare(this.obj,((PyObject)arg).obj)>=0;
1359-
returntrue;
1366+
returnthis.TryCompare((PyObject)arg,Runtime.Py_GE,outresult);
13601367
caseExpressionType.LeftShift:
13611368
res=Runtime.PyNumber_Lshift(this.obj,((PyObject)arg).obj);
13621369
break;
13631370
caseExpressionType.LeftShiftAssign:
13641371
res=Runtime.PyNumber_InPlaceLshift(this.obj,((PyObject)arg).obj);
13651372
break;
13661373
caseExpressionType.LessThan:
1367-
result=Runtime.PyObject_Compare(this.obj,((PyObject)arg).obj)<0;
1368-
returntrue;
1374+
returnthis.TryCompare((PyObject)arg,Runtime.Py_LT,outresult);
13691375
caseExpressionType.LessThanOrEqual:
1370-
result=Runtime.PyObject_Compare(this.obj,((PyObject)arg).obj)<=0;
1371-
returntrue;
1376+
returnthis.TryCompare((PyObject)arg,Runtime.Py_LE,outresult);
13721377
caseExpressionType.Modulo:
13731378
res=Runtime.PyNumber_Remainder(this.obj,((PyObject)arg).obj);
13741379
break;
13751380
caseExpressionType.ModuloAssign:
13761381
res=Runtime.PyNumber_InPlaceRemainder(this.obj,((PyObject)arg).obj);
13771382
break;
13781383
caseExpressionType.NotEqual:
1379-
result=Runtime.PyObject_Compare(this.obj,((PyObject)arg).obj)!=0;
1380-
returntrue;
1384+
returnthis.TryCompare((PyObject)arg,Runtime.Py_NE,outresult);
1385+
caseExpressionType.Equal:
1386+
returnthis.TryCompare((PyObject)arg,Runtime.Py_EQ,outresult);
13811387
caseExpressionType.Or:
13821388
res=Runtime.PyNumber_Or(this.obj,((PyObject)arg).obj);
13831389
break;
@@ -1402,6 +1408,40 @@ public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg
14021408
returntrue;
14031409
}
14041410

1411+
publicstaticbooloperator==(PyObject?a,PyObject?b)
1412+
{
1413+
if(aisnull&&bisnull)
1414+
{
1415+
returntrue;
1416+
}
1417+
if(aisnull||bisnull)
1418+
{
1419+
returnfalse;
1420+
}
1421+
1422+
usingvar_=Py.GIL();
1423+
intresult=Runtime.PyObject_RichCompareBool(a.obj,b.obj,Runtime.Py_EQ);
1424+
if(result<0)throwPythonException.ThrowLastAsClrException();
1425+
returnresult!=0;
1426+
}
1427+
1428+
publicstaticbooloperator!=(PyObject?a,PyObject?b)
1429+
{
1430+
if(aisnull&&bisnull)
1431+
{
1432+
returnfalse;
1433+
}
1434+
if(aisnull||bisnull)
1435+
{
1436+
returntrue;
1437+
}
1438+
1439+
usingvar_=Py.GIL();
1440+
intresult=Runtime.PyObject_RichCompareBool(a.obj,b.obj,Runtime.Py_NE);
1441+
if(result<0)throwPythonException.ThrowLastAsClrException();
1442+
returnresult!=0;
1443+
}
1444+
14051445
// Workaround for https://bugzilla.xamarin.com/show_bug.cgi?id=41509
14061446
// See https://github.com/pythonnet/pythonnet/pull/219
14071447
internalstaticobject?CheckNone(PyObjectpyObj)
@@ -1436,14 +1476,17 @@ public override bool TryUnaryOperation(UnaryOperationBinder binder, out object?
14361476
caseExpressionType.Not:
14371477
r=Runtime.PyObject_Not(this.obj);
14381478
result=r==1;
1479+
if(r==-1)Exceptions.Clear();
14391480
returnr!=-1;
14401481
caseExpressionType.IsFalse:
14411482
r=Runtime.PyObject_IsTrue(this.obj);
14421483
result=r==0;
1484+
if(r==-1)Exceptions.Clear();
14431485
returnr!=-1;
14441486
caseExpressionType.IsTrue:
14451487
r=Runtime.PyObject_IsTrue(this.obj);
14461488
result=r==1;
1489+
if(r==-1)Exceptions.Clear();
14471490
returnr!=-1;
14481491
caseExpressionType.Decrement:
14491492
caseExpressionType.Increment:

‎src/runtime/Runtime.cs

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -962,31 +962,6 @@ internal static IntPtr PyObject_CallObject(IntPtr pointer, IntPtr args)
962962

963963
internalstaticintPyObject_RichCompareBool(BorrowedReferencevalue1,BorrowedReferencevalue2,intopid)=>Delegates.PyObject_RichCompareBool(value1,value2,opid);
964964

965-
internalstaticintPyObject_Compare(BorrowedReferencevalue1,BorrowedReferencevalue2)
966-
{
967-
intres;
968-
res=PyObject_RichCompareBool(value1,value2,Py_LT);
969-
if(-1==res)
970-
return-1;
971-
elseif(1==res)
972-
return-1;
973-
974-
res=PyObject_RichCompareBool(value1,value2,Py_EQ);
975-
if(-1==res)
976-
return-1;
977-
elseif(1==res)
978-
return0;
979-
980-
res=PyObject_RichCompareBool(value1,value2,Py_GT);
981-
if(-1==res)
982-
return-1;
983-
elseif(1==res)
984-
return1;
985-
986-
Exceptions.SetError(Exceptions.SystemError,"Error comparing objects");
987-
return-1;
988-
}
989-
990965

991966
internalstaticintPyObject_IsInstance(BorrowedReferenceob,BorrowedReferencetype)=>Delegates.PyObject_IsInstance(ob,type);
992967

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp