Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5130aaa
Overload operators except for bit shifts and default args.
christabella Dec 16, 2020
0d0ca87
Remove params array tests since they are unrelated to operator overlo…
christabella Dec 17, 2020
253f9c7
Fix type bug; rename variables pynargs etc.
christabella Dec 17, 2020
8cdb61c
Remove unused variables and add comments.
christabella Dec 17, 2020
c26e589
Add comments and remove unused in operatormethod.cs
christabella Dec 18, 2020
3222a54
Address review by @lostmsu; Add forward operator test.
christabella Dec 20, 2020
550ff31
Add forward operator tests (OpObj, int).
christabella Dec 21, 2020
eab8edc
Address @amos402's comment on raising branch.
christabella Dec 21, 2020
c2be3f1
Add operator overload and rename pynargs, clrnargs
christabella Dec 21, 2020
581a047
Revert variable renames
christabella Dec 22, 2020
e11327f
Update AUTHORS and CHANGELOG
christabella Dec 22, 2020
35be4bc
Revert rename to pynargs
christabella Dec 23, 2020
f19c281
Address @tminka's comments.
christabella Dec 23, 2020
d7f52d2
Remove whitespace
christabella Dec 23, 2020
5855a1b
Fix nits
christabella Dec 24, 2020
e7da0bc
Support reverse binary operations
christabella Dec 28, 2020
a376838
Use reverse instead of forward (semantics)
christabella Dec 29, 2020
6923a78
Address @tminka's comments
christabella Dec 30, 2020
4c992d8
Support unary neg and pos operators
christabella Dec 30, 2020
8cce61d
Remove isOperator from MatchesArgumentCount (simplify), add test.
christabella Jan 4, 2021
09a2047
Revert "Remove isOperator from MatchesArgumentCount (simplify)"
christabella Jan 4, 2021
41bd07f
Properly remove isOperator from MatchesArgumentCount (@tminka comment)
christabella Jan 4, 2021
10ccf1e
Update changelog.
christabella Jan 4, 2021
5682e0c
Add ones complement and modulo tests (@tminka comment)
christabella Jan 4, 2021
5f45c70
Merge branch 'master' into feat/operator-overloads
lostmsu Jan 5, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add comments and remove unused in operatormethod.cs
Also move fixupslots before pytype_ready.
Also apply access violation fix in classderived.
  • Loading branch information
christabella committed Dec 23, 2020
commit c26e5892996cf3463a5cd4512ef5d9fde118740f
7 changes: 6 additions & 1 deletion src/runtime/classderived.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ internal ClassDerivedObject(Type tp) : base(tp)
public new static void tp_dealloc(IntPtr ob)
{
var self = (CLRObject)GetManagedObject(ob);

// Amos's fix https://github.com/pythonnet/pythonnet/pull/1260#issuecomment-726719595
if (self.tpHandle == IntPtr.Zero)
{
ClassBase.tp_dealloc(ob);
return;
}
Comment thread
christabella marked this conversation as resolved.
Outdated
// don't let the python GC destroy this object
Runtime.PyObject_GC_UnTrack(self.pyHandle);

Expand Down
34 changes: 19 additions & 15 deletions src/runtime/operatormethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ namespace Python.Runtime
{
internal static class OperatorMethod
{
// Maps the compiled method name in .NET CIL (e.g. op_Addition) to
// the equivalent Python operator (e.g. __add__) as well as the offset
// that identifies that operator's slot (e.g. nb_add) in heap space.
public static Dictionary<string, Tuple<string, int>> OpMethodMap { get; private set; }
Comment thread
christabella marked this conversation as resolved.
Outdated
Comment thread
christabella marked this conversation as resolved.
Outdated

private static Dictionary<string, string> _pyOpNames;
private static PyObject _opType;

static OperatorMethod()
Expand All @@ -35,12 +37,6 @@ static OperatorMethod()
["op_Modulus"] = Tuple.Create("__mod__", TypeOffset.nb_remainder),
["op_OneComplement"] = Tuple.Create("__invert__", TypeOffset.nb_invert)
};

_pyOpNames = new Dictionary<string, string>();
foreach (string name in OpMethodMap.Keys)
{
_pyOpNames.Add(GetPyMethodName(name), name);
}
}

public static void Initialize()
Expand All @@ -62,11 +58,6 @@ public static bool IsOperatorMethod(string methodName)
return OpMethodMap.ContainsKey(methodName);
}

public static bool IsPyOperatorMethod(string pyMethodName)
{
return _pyOpNames.ContainsKey(pyMethodName);
}

public static bool IsOperatorMethod(MethodBase method)
{
if (!method.IsSpecialName)
Expand All @@ -75,7 +66,12 @@ public static bool IsOperatorMethod(MethodBase method)
}
return OpMethodMap.ContainsKey(method.Name);
}

/// <summary>
/// For the operator methods of a CLR type, set the special slots of the
/// corresponding Python type's operator methods.
/// </summary>
/// <param name="pyType"></param>
/// <param name="clrType"></param>
public static void FixupSlots(IntPtr pyType, Type clrType)
{
const BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
Expand All @@ -86,10 +82,16 @@ public static void FixupSlots(IntPtr pyType, Type clrType)
{
continue;
}
var slotdef = OpMethodMap[method.Name];
int offset = slotdef.Item2;
int offset = OpMethodMap[method.Name].Item2;
// Copy the default implementation of e.g. the nb_add slot,
// which simply calls __add__ on the type.
IntPtr func = Marshal.ReadIntPtr(_opType.Handle, offset);
// Write the slot definition of the target Python type, so
// that we can later modify __add___ and it will be called
// when used with a Python operator.
// https://tenthousandmeters.com/blog/python-behind-the-scenes-6-how-python-object-system-works/
Marshal.WriteIntPtr(pyType, offset, func);

}
}

Expand All @@ -116,7 +118,9 @@ private static PyObject GetOperatorType()
{
// A hack way for getting typeobject.c::slotdefs
string code = GenerateDummyCode();
// The resulting OperatorMethod class is stored in a PyDict.
PythonEngine.Exec(code, null, locals.Handle);
// Return the class itself, which is a type.
return locals.GetItem("OperatorMethod");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/typemanager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
| TypeFlags.HaveGC;
Util.WriteCLong(type, TypeOffset.tp_flags, flags);

OperatorMethod.FixupSlots(type, clrType);
// Leverage followup initialization from the Python runtime. Note
// that the type of the new type must PyType_Type at the time we
// call this, else PyType_Ready will skip some slot initialization.
Expand All @@ -281,7 +282,6 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
{
throw new PythonException();
}
OperatorMethod.FixupSlots(type, clrType);

IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
string mn = clrType.Namespace ?? "";
Expand Down