1 # This file is part of Indico.
2 # Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
4 # Indico is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3 of the
7 # License, or (at your option) any later version.
9 # Indico is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Indico; if not, see <http://www.gnu.org/licenses/>.
17 from functools
import wraps
19 from flask
import has_request_context
, g
, current_app
22 def make_hashable(obj
):
23 if isinstance(obj
, list):
25 elif isinstance(obj
, dict):
26 return frozenset((k
, make_hashable(v
)) for k
, v
in obj
.iteritems())
27 elif hasattr(obj
, 'getId'):
28 return obj
.__class
__.__name
__, obj
.getId()
32 # http://wiki.python.org/moin/PythonDecoratorLibrary#Alternate_memoize_as_nested_functions
33 # Not thread-safe. Don't use it in places where thread-safety is important!
38 def memoizer(*args
, **kwargs
):
39 key
= (make_hashable(args
), make_hashable(kwargs
))
41 cache
[key
] = obj(*args
, **kwargs
)
46 def memoize_request(f
):
47 """Memoizes a function during the current request"""
49 def memoizer(*args
, **kwargs
):
50 if not has_request_context() or current_app
.config
['TESTING']:
51 # No memoization outside request context
52 return f(*args
, **kwargs
)
55 cache
= g
.memoize_cache
56 except AttributeError:
57 g
.memoize_cache
= cache
= {}
59 key
= (f
.__name
__, make_hashable(args
), make_hashable(kwargs
))
61 cache
[key
] = f(*args
, **kwargs
)