/// <summary> /// Return a dict that maps slot names to slot values, but only include slots that have been assigned to. /// Looks up slots in base types as well as the current type. /// /// Sort-of Python equivalent (doesn't look up base slots, while the real code does): /// return dict([(slot, getattr(self, slot)) for slot in type(self).__slots__ if hasattr(self, slot)]) /// /// Return null if the object has no __slots__, or empty dict if it has __slots__ but none are initialized. /// </summary> private static PythonDictionary GetInitializedSlotValues(object obj) { PythonDictionary initializedSlotValues = new PythonDictionary(); IList<PythonType> mro = DynamicHelpers.GetPythonType(obj).ResolutionOrder; object slots; object slotValue; foreach (object type in mro) { if (PythonOps.TryGetBoundAttr(type, Symbols.Slots, out slots)) { List<string> slotNames = NewTypeMaker.SlotsToList(slots); foreach (string slotName in slotNames) { if (slotName == "__dict__") continue; // don't reassign same-named slots from types earlier in the MRO if (initializedSlotValues.__contains__(slotName)) continue; if (PythonOps.TryGetBoundAttr(obj, SymbolTable.StringToId(slotName), out slotValue)) { initializedSlotValues[slotName] = slotValue; } } } } if (initializedSlotValues.__len__() == 0) return null; return initializedSlotValues; }