Replace memory-leak-prone Uniq with @uniq_wrapper

master
pictuga 2020-10-03 19:43:55 +02:00
parent 8cb7002fe6
commit 2514fabd38
1 changed files with 32 additions and 20 deletions

View File

@ -626,33 +626,41 @@ class ParserJSON(ParserBase):
return out.replace('\n', '<br/>') if out else out return out.replace('\n', '<br/>') if out else out
class Uniq(object): def wrap_uniq(wrapper_fn_name):
_map = {} " Wraps the output of the function with the specified function "
_id = None # This is called when parsing "wrap_uniq('wrap_item')"
def __new__(cls, *args, **kwargs): def decorator(func):
# check if a wrapper was already created for it # This is called when parsing "@wrap_uniq('wrap_item')"
# if so, reuse it
# if not, create a new one
# note that the item itself (the tree node) is created beforehands
tmp_id = cls._gen_id(*args, **kwargs) def wrapped_func(self, *args, **kwargs):
if tmp_id in cls._map: # This is called when the wrapped function is called
return cls._map[tmp_id]
output = func(self, *args, **kwargs)
output_id = id(output)
try:
return self._map[output_id]
except (KeyError, AttributeError):
if not hasattr(self, '_map'):
self._map = {}
wrapper_fn = getattr(self, wrapper_fn_name)
obj = wrapper_fn(output)
self._map[output_id] = obj
else:
obj = object.__new__(cls) #, *args, **kwargs)
cls._map[tmp_id] = obj
return obj return obj
return wrapped_func
return decorator
class Feed(object): class Feed(object):
itemsClass = property(lambda x: Item) # because Item is define below, i.e. afterwards itemsClass = property(lambda x: Item) # because Item is define below, i.e. afterwards
dic = ('title', 'desc', 'items') dic = ('title', 'desc', 'items')
def wrap_items(self, items):
return [self.itemsClass(x, self.rules, self) for x in items]
title = property( title = property(
lambda f: f.get('title'), lambda f: f.get('title'),
lambda f,x: f.set('title', x), lambda f,x: f.set('title', x),
@ -681,8 +689,12 @@ class Feed(object):
return item return item
def wrap_item(self, item):
return self.itemsClass(item, self.rules, self)
@wrap_uniq('wrap_item')
def __getitem__(self, key): def __getitem__(self, key):
return self.wrap_items(self.get_raw('items'))[key] return self.get_raw('items')[key]
def __delitem__(self, key): def __delitem__(self, key):
self[key].remove() self[key].remove()
@ -691,7 +703,7 @@ class Feed(object):
return len(self.get_raw('items')) return len(self.get_raw('items'))
class Item(Uniq): class Item(object):
dic = ('title', 'link', 'desc', 'content', 'time', 'updated') dic = ('title', 'link', 'desc', 'content', 'time', 'updated')
def __init__(self, xml=None, rules=None, parent=None): def __init__(self, xml=None, rules=None, parent=None):