Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] Pythagorean tree and Pythagorean forest widgets #1441

Merged
merged 12 commits into from
Jul 19, 2016
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
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
52 changes: 48 additions & 4 deletions Orange/misc/cache.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,60 @@
def single_cache(f):
"""Common caching methods, using `lru_cache` sometimes has its downsides."""
from functools import wraps, lru_cache
import weakref


def single_cache(func):
"""Cache with size 1."""
last_args = ()
last_kwargs = set()
last_result = None

def cached(*args, **kwargs):
@wraps(func)
def _cached(*args, **kwargs):
nonlocal last_args, last_kwargs, last_result
if len(last_args) != len(args) or \
not all(x is y for x, y in zip(args, last_args)) or \
last_kwargs != set(kwargs) or \
any(last_kwargs[k] != kwargs[k] for k in last_kwargs):
last_result = f(*args, **kwargs)
last_result = func(*args, **kwargs)
last_args, last_kwargs = args, kwargs
return last_result

return cached
return _cached


def memoize_method(*lru_args, **lru_kwargs):
"""Memoize methods without keeping reference to `self`.

Parameters
----------
lru_args
lru_kwargs

Returns
-------

See Also
--------
https://stackoverflow.com/questions/33672412/python-functools-lru-cache-with-class-methods-release-object

"""
def _decorator(func):

@wraps(func)
def _wrapped_func(self, *args, **kwargs):
self_weak = weakref.ref(self)
# We're storing the wrapped method inside the instance. If we had
# a strong reference to self the instance would never die.

@wraps(func)
@lru_cache(*lru_args, **lru_kwargs)
def _cached_method(*args, **kwargs):
return func(self_weak(), *args, **kwargs)

setattr(self, func.__name__, _cached_method)
return _cached_method(*args, **kwargs)

return _wrapped_func

return _decorator
30 changes: 30 additions & 0 deletions Orange/tests/test_misc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import unittest

from Orange.misc.cache import memoize_method, single_cache


class Calculator:
@memoize_method()
def my_sum(self, *nums):
return sum(nums)


@single_cache
def my_sum(*nums):
return sum(nums)


class TestCache(unittest.TestCase):

def test_single_cache(self):
self.assertEqual(my_sum(1, 2, 3, 4, 5), 15)
self.assertEqual(my_sum(1, 2, 3, 4, 5), 15)
# Make sure different args produce different results
self.assertEqual(my_sum(1, 2, 3, 4), 10)

def test_memoize_method(self):
calc = Calculator()
self.assertEqual(calc.my_sum(1, 2, 3, 4, 5), 15)
self.assertEqual(calc.my_sum(1, 2, 3, 4, 5), 15)
# Make sure different args produce different results
self.assertEqual(calc.my_sum(1, 2, 3, 4), 10)
22 changes: 22 additions & 0 deletions Orange/widgets/visualize/icons/PythagoreanForest.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions Orange/widgets/visualize/icons/PythagoreanTree.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading