From 44b8e3b1d210b3a44df2756c2e742f702c80e65b Mon Sep 17 00:00:00 2001 From: Rossen Georgiev Date: Sun, 8 May 2016 00:22:35 +0100 Subject: [PATCH] added WeakRefKeyDict * stores a value for a key (can be unhashable) * value is destroyed once the key is garbage collected --- steam/util/__init__.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/steam/util/__init__.py b/steam/util/__init__.py index 65cedef..bf294d8 100644 --- a/steam/util/__init__.py +++ b/steam/util/__init__.py @@ -1,6 +1,6 @@ """Utility package with various useful functions """ - +import weakref import struct import socket @@ -54,3 +54,34 @@ def clear_proto_bit(emsg): return int(emsg) & ~protobuf_mask +class WeakRefKeyDict(object): + """Pretends to be a dictionary. + Use any object (even unhashable) as key and store a value. + Once the object is garbage collected, the entry is destroyed automatically. + """ + def __init__(self): + self.refs = {} + + def __setitem__(self, obj, value): + key = id(obj) + + if key not in self.refs: + wr = weakref.ref(obj, WeakRefCallback(self.refs, key)) + self.refs[key] = [wr, None] + self.refs[key][1] = value + + def __getitem__(self, obj): + key = id(obj) + return self.refs[key][1] + + def __contains__(self, obj): + return id(obj) in self.refs + + def __len__(self): + return len(self.refs) + +class WeakRefCallback(object): + def __init__(self, refs, key): + self.__dict__.update(locals()) + def __call__(self, wr): + del self.refs[self.key]