aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Doan <andy.doan@linaro.org>2015-06-08 10:20:17 -0500
committerAndy Doan <andy.doan@linaro.org>2015-07-07 08:31:27 -0500
commit8f2768db323a3462c6d4963cead5aa8029f37f5b (patch)
treee6008a3cc47607e81faef86b5cc484e53e74af80
parentc5a1adcdb82f15f5e1b5541c5e6a9faa861d8815 (diff)
move more build-info handling into artifact base
This allows us to make the logic smart enough to cache the build-info buffer for a given directory listing. This is more efficient locally, and will be required for S3 to perform well. Change-Id: I8c28c35dde535a56ec40fcc7e0cafa561f2703c6
-rw-r--r--license_protected_downloads/common.py40
-rw-r--r--license_protected_downloads/tests/test_common.py18
2 files changed, 49 insertions, 9 deletions
diff --git a/license_protected_downloads/common.py b/license_protected_downloads/common.py
index 5790f9b..23aff14 100644
--- a/license_protected_downloads/common.py
+++ b/license_protected_downloads/common.py
@@ -87,12 +87,12 @@ def find_artifact(request, path):
if fullpath is None:
raise Http404
if os.path.isfile(fullpath) or os.path.isdir(fullpath):
- return LocalArtifact('', path, False, basepath)
+ return LocalArtifact(None, '', path, False, basepath)
fullpath = _handle_wildcard(request, fullpath)
if fullpath:
basepath, path = os.path.split(fullpath)
- return LocalArtifact('', path, False, basepath)
+ return LocalArtifact(None, '', path, False, basepath)
raise Http404
@@ -130,6 +130,17 @@ def _sizeof_fmt(num):
return "%3.1f%s" % (num, 'T')
+def cached_prop(fn):
+ attr_name = '_cached_' + fn.__name__
+
+ @property
+ def _cached_prop(self):
+ if not hasattr(self, attr_name):
+ setattr(self, attr_name, fn(self))
+ return getattr(self, attr_name)
+ return _cached_prop
+
+
class Artifact(object):
def __init__(self, urlbase, file_name, size, mtime, human_readable):
self.urlbase = urlbase
@@ -172,7 +183,12 @@ class Artifact(object):
raise NotImplementedError()
def get_build_info(self):
- raise NotImplementedError()
+ buf = self.build_info_buffer
+ if buf:
+ sp = fn = self.urlbase[1:]
+ if not self.isdir():
+ fn = sp + '/' + self.file_name
+ return buildinfo.BuildInfoBase(fn, sp, buf)
def get_listing(self):
if self.isdir():
@@ -287,7 +303,8 @@ class Artifact(object):
class LocalArtifact(Artifact):
'''An artifact that lives on the local filesystem'''
- def __init__(self, urlbase, file_name, human_readable, path):
+ def __init__(self, parent, urlbase, file_name, human_readable, path):
+ self.parent = parent
self.full_path = os.path.join(path, file_name)
size = mtime = 0
@@ -310,9 +327,16 @@ class LocalArtifact(Artifact):
mtype = 'text'
return mtype
- def get_build_info(self):
- if buildinfo.BuildInfo.build_info_exists(self.full_path):
- return buildinfo.BuildInfo(self.full_path)
+ @cached_prop
+ def build_info_buffer(self):
+ if self.parent and not self.isdir():
+ return self.parent.build_info_buffer
+
+ p = buildinfo.BuildInfo.get_search_path(self.full_path)
+ p = os.path.join(p, 'BUILD-INFO.txt')
+ if os.path.exists(p):
+ with open(p) as f:
+ return f.read()
def get_eulas(self):
if self.isdir():
@@ -329,7 +353,7 @@ class LocalArtifact(Artifact):
def dir_list(artifact, human_readable=True):
path = artifact.full_path
url = artifact.url()
- artifacts = [LocalArtifact(url, x, human_readable, path)
+ artifacts = [LocalArtifact(artifact, url, x, human_readable, path)
for x in os.listdir(path)]
artifacts.sort(_sort_artifacts)
diff --git a/license_protected_downloads/tests/test_common.py b/license_protected_downloads/tests/test_common.py
index eec6b3d..b8b070a 100644
--- a/license_protected_downloads/tests/test_common.py
+++ b/license_protected_downloads/tests/test_common.py
@@ -20,9 +20,25 @@ class CommonTests(unittest.TestCase):
(['10', 'foo', '100', 'latest'], ['latest', '10', '100', 'foo']),
]
for files, expected in patterns:
- artifacts = [common.LocalArtifact('', x, True, '') for x in files]
+ artifacts = [common.LocalArtifact(None, '', x, True, '')
+ for x in files]
artifacts.sort(common._sort_artifacts)
self.assertEqual(expected, [x.file_name for x in artifacts])
+ def test_cached_property(self):
+ class Foo(object):
+ def __init__(self):
+ self.count = 0
+
+ @common.cached_prop
+ def bar(self):
+ v = self.count
+ self.count += 1
+ return v
+
+ f = Foo()
+ self.assertEqual(0, f.bar)
+ self.assertEqual(0, f.bar)
+
if __name__ == '__main__':
unittest.main()