-
Notifications
You must be signed in to change notification settings - Fork 308
Description
This used to work on .NET:
import clr
import pickle
clr.AddReference("System.Text.Json")
clr.AddReference("Microsoft.Scripting")
import System.Text.Json
import Microsoft.Scripting
data = [
System.DayOfWeek.Wednesday, # still works
System.Text.Json.JsonValueKind.Object, # nested namespace
Microsoft.Scripting.Severity.Warning, # different namespace than System
]
for value in data:
print(pickle.dumps(value))It does not work on .NET 8.0 and higher.
It was relying on clr.Deserialize, which was included if IronPython was compiled with FEATURE_SERIALIZATION (on by default). The implementation was using BinaryFormatter, which is now unsupported. With clr.Deserialize and clr.Serialize gone, pickling relies on a generic object __reduce_ex__ implementation. It fails for types that are placed in nested namespaces, because __module__ attribute on those object is not the actual module as in imported sys.modules but the complete dotted-path namespace.
Two ideas come to mind on how to resolve this regression:
-
Tweak
pickle.pyin StdLib to be more mindful of IronPython namespaces; for instance a translation of (module, name) from e.g.(System.Text.Json, JsonValueKind)to(System, Text.Json.JsonValueKind)is simple and would do the trick, but it will require using pickle protocol >= 4, which allows for dotted (nested) type names. -
Capture the resolution of
__reduce_ex__inOneOffRTesolverlike it used to be whenFEATURE_SERIALIZATIONwas defined, and redirect toEnumOps.SerializeReduce. This will handle all enums, but not other types that may have worked in case of option 1, OTOH, StdLib is untouched.
(or the combination of the two).
Both options make objects pickled by IronPython/.NET 6.0 not unpicklable (not loadable) on .NET 8.0 and higher, but that is the consequence of BinaryFormatter being gone. AFAIK, pickle file format is not meant to be binary-portable across Python versions, so one can argue that this is better than the alternative of not being able to pickle at all. Universal pickling of an arbitrary .NET object is probably not feasible, but it is feasible and desirable for simple built-in types. For user types for which pickle support is needed, the developer can implement their own __reduce_ex__.
See also #29