forked from platformio/platformio-core
Improve cache logic for lookup operations
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
# Copyright (C) Ivan Kravets <me@ikravets.com>
|
||||
# See LICENSE for details.
|
||||
|
||||
import collections
|
||||
import functools
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
@@ -53,6 +55,39 @@ class AsyncPipe(Thread):
|
||||
self.join()
|
||||
|
||||
|
||||
class memoized(object):
|
||||
'''
|
||||
Decorator. Caches a function's return value each time it is called.
|
||||
If called later with the same arguments, the cached value is returned
|
||||
(not reevaluated).
|
||||
https://wiki.python.org/moin/PythonDecoratorLibrary#Memoize
|
||||
'''
|
||||
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
self.cache = {}
|
||||
|
||||
def __call__(self, *args):
|
||||
if not isinstance(args, collections.Hashable):
|
||||
# uncacheable. a list, for instance.
|
||||
# better to not cache than blow up.
|
||||
return self.func(*args)
|
||||
if args in self.cache:
|
||||
return self.cache[args]
|
||||
else:
|
||||
value = self.func(*args)
|
||||
self.cache[args] = value
|
||||
return value
|
||||
|
||||
def __repr__(self):
|
||||
'''Return the function's docstring.'''
|
||||
return self.func.__doc__
|
||||
|
||||
def __get__(self, obj, objtype):
|
||||
'''Support instance methods.'''
|
||||
return functools.partial(self.__call__, obj)
|
||||
|
||||
|
||||
def get_systype():
|
||||
data = uname()
|
||||
return ("%s_%s" % (data[0], data[4])).lower()
|
||||
@@ -239,22 +274,24 @@ def get_api_result(path, params=None, data=None):
|
||||
return result
|
||||
|
||||
|
||||
def get_boards(type_=None):
|
||||
@memoized
|
||||
def _lookup_boards():
|
||||
boards = {}
|
||||
try:
|
||||
boards = get_boards._cache # pylint: disable=W0212
|
||||
except AttributeError:
|
||||
bdirs = [join(get_source_dir(), "boards")]
|
||||
if isdir(join(get_home_dir(), "boards")):
|
||||
bdirs.append(join(get_home_dir(), "boards"))
|
||||
bdirs = [join(get_source_dir(), "boards")]
|
||||
if isdir(join(get_home_dir(), "boards")):
|
||||
bdirs.append(join(get_home_dir(), "boards"))
|
||||
|
||||
for bdir in bdirs:
|
||||
for json_file in os.listdir(bdir):
|
||||
if not json_file.endswith(".json"):
|
||||
continue
|
||||
with open(join(bdir, json_file)) as f:
|
||||
boards.update(json.load(f))
|
||||
get_boards._cache = boards # pylint: disable=W0212
|
||||
for bdir in bdirs:
|
||||
for json_file in os.listdir(bdir):
|
||||
if not json_file.endswith(".json"):
|
||||
continue
|
||||
with open(join(bdir, json_file)) as f:
|
||||
boards.update(json.load(f))
|
||||
return boards
|
||||
|
||||
|
||||
def get_boards(type_=None):
|
||||
boards = _lookup_boards()
|
||||
|
||||
if type_ is None:
|
||||
return boards
|
||||
@@ -264,33 +301,34 @@ def get_boards(type_=None):
|
||||
return boards[type_]
|
||||
|
||||
|
||||
def get_frameworks(type_=None):
|
||||
@memoized
|
||||
def _lookup_frameworks():
|
||||
frameworks = {}
|
||||
frameworks_path = join(
|
||||
get_source_dir(), "builder", "scripts", "frameworks")
|
||||
|
||||
try:
|
||||
frameworks = get_frameworks._cache # pylint: disable=W0212
|
||||
except AttributeError:
|
||||
frameworks_path = join(
|
||||
get_source_dir(), "builder", "scripts", "frameworks")
|
||||
frameworks_list = [f[:-3] for f in os.listdir(frameworks_path)
|
||||
if not f.startswith("__") and f.endswith(".py")]
|
||||
for _type in frameworks_list:
|
||||
script_path = join(frameworks_path, "%s.py" % _type)
|
||||
with open(script_path) as f:
|
||||
fcontent = f.read()
|
||||
assert '"""' in fcontent
|
||||
_doc_start = fcontent.index('"""') + 3
|
||||
fdoc = fcontent[
|
||||
_doc_start:fcontent.index('"""', _doc_start)].strip()
|
||||
doclines = [l.strip() for l in fdoc.splitlines() if l.strip()]
|
||||
frameworks[_type] = {
|
||||
"name": doclines[0],
|
||||
"description": " ".join(doclines[1:-1]),
|
||||
"url": doclines[-1],
|
||||
"script": script_path
|
||||
}
|
||||
return frameworks
|
||||
|
||||
frameworks_list = [f[:-3] for f in os.listdir(frameworks_path)
|
||||
if not f.startswith("__") and f.endswith(".py")]
|
||||
for _type in frameworks_list:
|
||||
script_path = join(frameworks_path, "%s.py" % _type)
|
||||
with open(script_path) as f:
|
||||
fcontent = f.read()
|
||||
assert '"""' in fcontent
|
||||
_doc_start = fcontent.index('"""') + 3
|
||||
fdoc = fcontent[
|
||||
_doc_start:fcontent.index('"""', _doc_start)].strip()
|
||||
doclines = [l.strip() for l in fdoc.splitlines() if l.strip()]
|
||||
frameworks[_type] = {
|
||||
"name": doclines[0],
|
||||
"description": " ".join(doclines[1:-1]),
|
||||
"url": doclines[-1],
|
||||
"script": script_path
|
||||
}
|
||||
get_frameworks._cache = frameworks # pylint: disable=W0212
|
||||
|
||||
def get_frameworks(type_=None):
|
||||
frameworks = _lookup_frameworks()
|
||||
|
||||
if type_ is None:
|
||||
return frameworks
|
||||
|
Reference in New Issue
Block a user