1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4#
5# Copyright 2017, Data61
6# Commonwealth Scientific and Industrial Research Organisation (CSIRO)
7# ABN 41 687 119 230.
8#
9# This software may be distributed and modified according to the terms of
10# the BSD 2-Clause license. Note that NO WARRANTY is provided.
11# See "LICENSE_BSD2.txt" for details.
12#
13# @TAG(DATA61_BSD)
14#
15
16'''Caching infrastructure for function calls. Nothing in here is CAmkES-
17specific. Note that this memoization implementation is not complete. If you are
18using it, you are expected to understand its limitations.
19'''
20
21from __future__ import absolute_import, division, print_function, \
22    unicode_literals
23from camkes.internal.seven import cmp, filter, map, zip
24import functools, six
25
26if six.PY3:
27    # Python 3 has memoization support in functools.
28    assert hasattr(functools, 'lru_cache'), '`functools.lru_cache` ' \
29        'unexpectedly missing (unsupported Python 3 minor version?)'
30    memoize = functools.lru_cache # pylint: disable=E1101
31
32else:
33    # Python 2 has no built-in memoization support, so we need to roll our own.
34    # See also https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize.
35    class memoized(object):
36        '''Decorator. Cache a function's return value each time it is called. If
37        called later with the same arguments, the cached value is returned (not
38        reevaluated).'''
39
40        def __init__(self, func):
41            self.func = func
42            self.cache = {}
43
44        def __call__(self, *args, **kwargs):
45            key = str(args) + str(kwargs)
46            if key not in self.cache:
47                self.cache[key] = self.func(*args, **kwargs)
48            return self.cache[key]
49
50        def __repr__(self):
51            '''Return the function's docstring.'''
52            return self.func.__doc__
53
54    def memoize():
55        return memoized
56