aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Doan <andy.doan@linaro.org>2015-08-06 10:37:06 -0500
committerAndy Doan <andy.doan@linaro.org>2015-08-06 14:00:02 -0500
commitdc2e671b6a666a8f22812c3ab03ceb350c405a35 (patch)
tree52bcacb8051312a1063284e62a3de368cb7a7bb1
parenta16b5d76e6a37f1ddc945c12389a4c29a5226bca (diff)
downloadlinaro-license-protection-dc2e671b6a666a8f22812c3ab03ceb350c405a35.tar.gz
break Artifact logic out of common.py
Now that we have things refactored, lets break this specific content into its own module. This will then allow us to simply add an "s3.py" artifact Change-Id: I6f31911d36b33b5e7da4e3875dc00e674ff86b13
-rw-r--r--license_protected_downloads/artifact/__init__.py2
-rw-r--r--license_protected_downloads/artifact/base.py264
-rw-r--r--license_protected_downloads/artifact/local.py91
-rw-r--r--license_protected_downloads/common.py341
-rw-r--r--license_protected_downloads/tests/test_common.py22
-rw-r--r--license_protected_downloads/tests/test_views.py6
6 files changed, 375 insertions, 351 deletions
diff --git a/license_protected_downloads/artifact/__init__.py b/license_protected_downloads/artifact/__init__.py
new file mode 100644
index 0000000..fbdd24a
--- /dev/null
+++ b/license_protected_downloads/artifact/__init__.py
@@ -0,0 +1,2 @@
+from .base import Artifact # NOQA
+from .local import LocalArtifact # NOQA
diff --git a/license_protected_downloads/artifact/base.py b/license_protected_downloads/artifact/base.py
new file mode 100644
index 0000000..2619e6d
--- /dev/null
+++ b/license_protected_downloads/artifact/base.py
@@ -0,0 +1,264 @@
+import datetime
+import hashlib
+import logging
+import os
+import re
+import traceback
+
+from BeautifulSoup import BeautifulSoup
+from django.conf import settings
+
+from license_protected_downloads import(
+ buildinfo,
+ models,
+)
+
+log = logging.getLogger("llp.views")
+
+
+def _sizeof_fmt(num):
+ ''' Returns in human readable format for num.
+ '''
+ if num < 1024 and num > -1024:
+ return str(num)
+ num /= 1024.0
+ for x in ['K', 'M', 'G']:
+ if num < 1024.0 and num > -1024.0:
+ return "%3.1f%s" % (num, x)
+ num /= 1024.0
+ 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
+
+
+def _insert_license_into_db(digest, text, theme):
+ if not models.License.objects.filter(digest=digest):
+ l = models.License(digest=digest, text=text, theme=theme)
+ l.save()
+
+
+class Artifact(object):
+ LINARO_INCLUDE_FILE_RE = re.compile(
+ r'<linaro:include file="(?P<file_name>.*)"[ ]*/>')
+ LINARO_INCLUDE_FILE_RE1 = re.compile(
+ r'<linaro:include file="(?P<file_name>.*)">(.*)</linaro:include>')
+
+ def __init__(self, urlbase, file_name, size, mtime, human_readable):
+ self.urlbase = urlbase
+ self.file_name = file_name
+ self.size = size
+ self.mtime = mtime
+ self.human_readable = human_readable
+
+ if human_readable:
+ self.size = _sizeof_fmt(size)
+ if type(mtime) == float:
+ mtime = datetime.datetime.fromtimestamp(mtime)
+ self.mtime = mtime.strftime('%d-%b-%Y %H:%M')
+
+ def isdir(self):
+ raise RuntimeError()
+
+ def hidden(self):
+ hidden_files = ["BUILD-INFO.txt", "EULA.txt", "HEADER.html",
+ "HOWTO_", "textile", ".htaccess", "licenses",
+ ".s3_linked_from"]
+ for pattern in hidden_files:
+ if re.search(pattern, self.file_name):
+ return True
+ return False
+
+ def url(self):
+ url = self.urlbase
+ if url:
+ if url[0] != '/':
+ url = '/' + url
+ if url[-1] != '/':
+ url += '/'
+ else:
+ url = '/'
+ url = url + self.file_name
+ if self.isdir() and url[-1] != '/':
+ url += '/'
+ return url
+
+ def get_type(self):
+ raise NotImplementedError()
+
+ def get_eulas(self):
+ raise NotImplementedError()
+
+ def get_file_download_response(self):
+ raise NotImplementedError()
+
+ def get_textile_files(self):
+ raise NotImplementedError()
+
+ def get_build_info(self):
+ buf = self.build_info_buffer
+ if buf:
+ # directory listings are handled specially, the build-info logic
+ # will get license-digests for *all* files iff you pass no
+ # file-name to its constructor
+ if self.isdir():
+ return buildinfo.BuildInfoBase('', buf)
+ return buildinfo.BuildInfoBase(self.file_name, buf)
+
+ def get_listing(self):
+ if self.isdir():
+ ldl = []
+ else:
+ try:
+ ldl = self.get_license_digests()
+ except Exception as e:
+ print("Invalid BUILD-INFO.txt for %s: %s" % (
+ self.full_path, repr(e)))
+ traceback.print_exc()
+ ldl = "INVALID"
+ ll = models.License.objects.all_with_hashes(ldl)
+ return {
+ 'name': self.file_name,
+ 'size': self.size,
+ 'mtime': self.mtime,
+ 'license_digest_list': ldl,
+ 'license_list': ll,
+ 'type': self.get_type(),
+ 'url': self.url(),
+ }
+
+ def get_digest(self, lic_type, lic_text, theme, auth_groups):
+ if lic_type == 'open' or (auth_groups and not lic_text):
+ return 'OPEN'
+
+ if not lic_text:
+ log.info('No license text or auth groups found: check the '
+ 'BUILD-INFO file.')
+ return
+
+ digest = hashlib.md5(lic_text).hexdigest()
+ _insert_license_into_db(digest, lic_text, theme)
+ return digest
+
+ def get_build_info_digests(self, bi):
+ digests = []
+
+ lic_type = bi.get('license-type')
+ auth_groups = bi.get('auth-groups')
+ for i in range(bi.max_index):
+ lic_txt = bi.get('license-text', i)
+ theme = bi.get('theme', i)
+ d = self.get_digest(lic_type, lic_txt, theme, auth_groups)
+ if d == 'OPEN':
+ return d
+ elif d:
+ digests.append(d)
+ return digests
+
+ def get_eula_digests(self):
+ path = self.urlbase + self.file_name
+ theme = 'linaro'
+ if 'snowball' in path:
+ theme = 'stericsson'
+ elif 'origen' in path:
+ theme = 'samsung'
+ lic_type = 'protected'
+ lic_file = os.path.join(
+ settings.PROJECT_ROOT, 'templates/licenses/' + theme + '.txt')
+ with open(lic_file) as f:
+ lic_txt = f.read()
+ return [self.get_digest(lic_type, lic_txt, theme, None)]
+
+ def get_license_digests(self):
+ bi = self.get_build_info()
+ if bi:
+ return self.get_build_info_digests(bi)
+
+ eulas = self.get_eulas()
+
+ if self.has_open_eula(eulas):
+ return 'OPEN'
+
+ if self.has_eula(eulas):
+ return self.get_eula_digests()
+
+ theme = self.get_eula_per_file_theme(eulas)
+ if theme:
+ lic_file = os.path.join(settings.PROJECT_ROOT,
+ 'templates/licenses/' + theme + '.txt')
+ with open(lic_file) as f:
+ lic_txt = f.read()
+ return [self.get_digest('protected', lic_txt, theme, None)]
+
+ if self.has_per_file_eulas(eulas):
+ return 'OPEN'
+
+ return []
+
+ def has_open_eula(self, eulas):
+ for x in eulas:
+ if 'OPEN-EULA.txt' in x:
+ return True
+
+ def has_eula(self, eulas):
+ for x in eulas:
+ if x == 'EULA.txt':
+ return True
+
+ def get_eula_per_file_theme(self, eulas):
+ eula_pat = os.path.basename(self.file_name) + '.EULA.txt'
+ for x in eulas:
+ if eula_pat in x:
+ vendor = os.path.splitext(x)[1]
+ return vendor[1:]
+
+ def has_per_file_eulas(self, eulas):
+ return len(eulas) > 0
+
+ def get_file_contents(self, fname):
+ raise NotImplementedError
+
+ def _process_include_tags(self, content):
+ """Replaces <linaro:include file="README" /> or
+ <linaro:include file="README">text to show</linaro:include> tags
+ with content of README file or empty string if file not found or
+ not allowed.
+ """
+ def read_func(matchobj):
+ fname = matchobj.group('file_name')
+ if os.path.normpath(fname) == os.path.basename(fname):
+ return self.get_file_contents(fname)
+
+ content = re.sub(self.LINARO_INCLUDE_FILE_RE, read_func, content)
+ content = re.sub(self.LINARO_INCLUDE_FILE_RE1, read_func, content)
+ return content
+
+ def get_header_html(self):
+ """Read HEADER.html in current directory
+
+ If exists and return contents of <div id="content"> block
+ """
+ assert self.isdir()
+
+ content = ''
+ body = self.get_file_contents('HEADER.html')
+ if body:
+ body = self._process_include_tags(body)
+ soup = BeautifulSoup(body)
+ for chunk in soup.findAll(id='content'):
+ content += chunk.prettify().decode('utf-8')
+
+ content = '\n'.join(content.split('\n')[1:-1])
+ return content
+
+ def get_annotated_manifest(self):
+ assert self.isdir()
+ return self.get_file_contents(settings.ANNOTATED_XML)
diff --git a/license_protected_downloads/artifact/local.py b/license_protected_downloads/artifact/local.py
new file mode 100644
index 0000000..c307a42
--- /dev/null
+++ b/license_protected_downloads/artifact/local.py
@@ -0,0 +1,91 @@
+import glob
+import mimetypes
+import os
+
+from django.http import HttpResponse
+from django.utils.encoding import smart_str
+
+from license_protected_downloads import(
+ buildinfo,
+ render_text_files,
+)
+from license_protected_downloads.artifact.base import (
+ Artifact,
+ cached_prop,
+)
+
+
+class LocalArtifact(Artifact):
+ '''An artifact that lives on the local filesystem'''
+ 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
+ # ensure the file we are looking at exists (not broken symlink)
+ if os.path.exists(self.full_path):
+ size = os.path.getsize(self.full_path)
+ mtime = os.path.getmtime(self.full_path)
+ super(LocalArtifact, self).__init__(
+ urlbase, file_name, size, mtime, human_readable)
+
+ def get_type(self):
+ if self.isdir():
+ return 'folder'
+ else:
+ mtype = mimetypes.guess_type(self.full_path)[0]
+ if self.human_readable:
+ if mtype is None:
+ mtype = 'other'
+ elif mtype.split('/')[0] == 'text':
+ mtype = 'text'
+ return mtype
+
+ def get_file_download_response(self):
+ "Return HttpResponse which will send path to user's browser."
+ assert not self.isdir()
+ file_name = os.path.basename(self.full_path)
+ mime = mimetypes.guess_type(file_name)[0]
+ if mime is None:
+ mime = "application/force-download"
+ response = HttpResponse(mimetype=mime)
+ response['Content-Disposition'] = ('attachment; filename=%s' %
+ smart_str(file_name))
+ response['X-Sendfile'] = smart_str(self.full_path)
+ return response
+
+ @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():
+ path = self.full_path
+ else:
+ path = os.path.dirname(self.full_path)
+ eulas = glob.glob(path + '/*EULA.txt*')
+ return [os.path.basename(x) for x in eulas]
+
+ def get_file_contents(self, fname):
+ fname = os.path.join(self.full_path, fname)
+ if os.path.isfile(fname) and not os.path.islink(fname):
+ with open(fname, 'r') as f:
+ return f.read()
+
+ def get_textile_files(self):
+ assert self.isdir()
+ files = render_text_files.RenderTextFiles.find_relevant_files(
+ self.full_path)
+ for f in files:
+ with open(f) as fd:
+ yield f, fd
+
+ def isdir(self):
+ return os.path.isdir(self.full_path)
diff --git a/license_protected_downloads/common.py b/license_protected_downloads/common.py
index 94e05ec..3c982d8 100644
--- a/license_protected_downloads/common.py
+++ b/license_protected_downloads/common.py
@@ -1,27 +1,16 @@
import fnmatch
-import glob
-import hashlib
-import logging
-import mimetypes
import os
-import re
-import traceback
-from datetime import datetime
-from BeautifulSoup import BeautifulSoup
from django.conf import settings
-from django.http import Http404, HttpResponse
-from django.utils.encoding import smart_str
+from django.http import Http404
from license_protected_downloads import(
- buildinfo,
models,
- render_text_files,
)
-
-
-log = logging.getLogger("llp.views")
+from license_protected_downloads.artifact import(
+ LocalArtifact,
+)
def safe_path_join(base_path, *paths):
@@ -42,12 +31,6 @@ def safe_path_join(base_path, *paths):
return target_path
-def _insert_license_into_db(digest, text, theme):
- if not models.License.objects.filter(digest=digest):
- l = models.License(digest=digest, text=text, theme=theme)
- l.save()
-
-
def _handle_wildcard(request, fullpath):
path, name = os.path.split(fullpath)
@@ -120,322 +103,6 @@ def _sort_artifacts(a, b):
return cmp(a, b)
-def _sizeof_fmt(num):
- ''' Returns in human readable format for num.
- '''
- if num < 1024 and num > -1024:
- return str(num)
- num /= 1024.0
- for x in ['K', 'M', 'G']:
- if num < 1024.0 and num > -1024.0:
- return "%3.1f%s" % (num, x)
- num /= 1024.0
- 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):
- LINARO_INCLUDE_FILE_RE = re.compile(
- r'<linaro:include file="(?P<file_name>.*)"[ ]*/>')
- LINARO_INCLUDE_FILE_RE1 = re.compile(
- r'<linaro:include file="(?P<file_name>.*)">(.*)</linaro:include>')
-
- def __init__(self, urlbase, file_name, size, mtime, human_readable):
- self.urlbase = urlbase
- self.file_name = file_name
- self.size = size
- self.mtime = mtime
- self.human_readable = human_readable
-
- if human_readable:
- self.size = _sizeof_fmt(size)
- mtime = datetime.fromtimestamp(mtime)
- self.mtime = mtime.strftime('%d-%b-%Y %H:%M')
-
- def isdir(self):
- raise RuntimeError()
-
- def hidden(self):
- hidden_files = ["BUILD-INFO.txt", "EULA.txt", "HEADER.html",
- "HOWTO_", "textile", ".htaccess", "licenses"]
- for pattern in hidden_files:
- if re.search(pattern, self.file_name):
- return True
- return False
-
- def url(self):
- url = self.urlbase
- if url:
- if url[0] != '/':
- url = '/' + url
- if url[-1] != '/':
- url += '/'
- else:
- url = '/'
- url = url + self.file_name
- if self.isdir() and url[-1] != '/':
- url += '/'
- return url
-
- def get_type(self):
- raise NotImplementedError()
-
- def get_eulas(self):
- raise NotImplementedError()
-
- def get_file_download_response(self):
- raise NotImplementedError()
-
- def get_textile_files(self):
- raise NotImplementedError()
-
- def get_build_info(self):
- buf = self.build_info_buffer
- if buf:
- # directory listings are handled specially, the build-info logic
- # will get license-digests for *all* files iff you pass no
- # file-name to its constructor
- if self.isdir():
- return buildinfo.BuildInfoBase('', buf)
- return buildinfo.BuildInfoBase(self.file_name, buf)
-
- def get_listing(self):
- if self.isdir():
- ldl = []
- else:
- try:
- ldl = self.get_license_digests()
- except Exception as e:
- print("Invalid BUILD-INFO.txt for %s: %s" % (
- self.full_path, repr(e)))
- traceback.print_exc()
- ldl = "INVALID"
- ll = models.License.objects.all_with_hashes(ldl)
- return {
- 'name': self.file_name,
- 'size': self.size,
- 'mtime': self.mtime,
- 'license_digest_list': ldl,
- 'license_list': ll,
- 'type': self.get_type(),
- 'url': self.url(),
- }
-
- def get_digest(self, lic_type, lic_text, theme, auth_groups):
- if lic_type == 'open' or (auth_groups and not lic_text):
- return 'OPEN'
-
- if not lic_text:
- log.info('No license text or auth groups found: check the '
- 'BUILD-INFO file.')
- return
-
- digest = hashlib.md5(lic_text).hexdigest()
- _insert_license_into_db(digest, lic_text, theme)
- return digest
-
- def get_build_info_digests(self, bi):
- digests = []
-
- lic_type = bi.get('license-type')
- auth_groups = bi.get('auth-groups')
- for i in range(bi.max_index):
- lic_txt = bi.get('license-text', i)
- theme = bi.get('theme', i)
- d = self.get_digest(lic_type, lic_txt, theme, auth_groups)
- if d == 'OPEN':
- return d
- elif d:
- digests.append(d)
- return digests
-
- def get_eula_digests(self):
- path = self.urlbase + self.file_name
- theme = 'linaro'
- if 'snowball' in path:
- theme = 'stericsson'
- elif 'origen' in path:
- theme = 'samsung'
- lic_type = 'protected'
- lic_file = os.path.join(
- settings.PROJECT_ROOT, 'templates/licenses/' + theme + '.txt')
- with open(lic_file) as f:
- lic_txt = f.read()
- return [self.get_digest(lic_type, lic_txt, theme, None)]
-
- def get_license_digests(self):
- bi = self.get_build_info()
- if bi:
- return self.get_build_info_digests(bi)
-
- eulas = self.get_eulas()
-
- if self.has_open_eula(eulas):
- return 'OPEN'
-
- if self.has_eula(eulas):
- return self.get_eula_digests()
-
- theme = self.get_eula_per_file_theme(eulas)
- if theme:
- lic_file = os.path.join(settings.PROJECT_ROOT,
- 'templates/licenses/' + theme + '.txt')
- with open(lic_file) as f:
- lic_txt = f.read()
- return [self.get_digest('protected', lic_txt, theme, None)]
-
- if self.has_per_file_eulas(eulas):
- return 'OPEN'
-
- return []
-
- def has_open_eula(self, eulas):
- for x in eulas:
- if 'OPEN-EULA.txt' in x:
- return True
-
- def has_eula(self, eulas):
- for x in eulas:
- if x == 'EULA.txt':
- return True
-
- def get_eula_per_file_theme(self, eulas):
- eula_pat = os.path.basename(self.file_name) + '.EULA.txt'
- for x in eulas:
- if eula_pat in x:
- vendor = os.path.splitext(x)[1]
- return vendor[1:]
-
- def has_per_file_eulas(self, eulas):
- return len(eulas) > 0
-
- def get_file_contents(self, fname):
- raise NotImplementedError
-
- def _process_include_tags(self, content):
- """Replaces <linaro:include file="README" /> or
- <linaro:include file="README">text to show</linaro:include> tags
- with content of README file or empty string if file not found or
- not allowed.
- """
- def read_func(matchobj):
- fname = matchobj.group('file_name')
- if os.path.normpath(fname) == os.path.basename(fname):
- return self.get_file_contents(fname)
-
- content = re.sub(self.LINARO_INCLUDE_FILE_RE, read_func, content)
- content = re.sub(self.LINARO_INCLUDE_FILE_RE1, read_func, content)
- return content
-
- def get_header_html(self):
- """Read HEADER.html in current directory
-
- If exists and return contents of <div id="content"> block
- """
- assert self.isdir()
-
- content = ''
- body = self.get_file_contents('HEADER.html')
- if body:
- body = self._process_include_tags(body)
- soup = BeautifulSoup(body)
- for chunk in soup.findAll(id='content'):
- content += chunk.prettify().decode('utf-8')
-
- content = '\n'.join(content.split('\n')[1:-1])
- return content
-
- def get_annotated_manifest(self):
- assert self.isdir()
- return self.get_file_contents(settings.ANNOTATED_XML)
-
-
-class LocalArtifact(Artifact):
- '''An artifact that lives on the local filesystem'''
- 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
- # ensure the file we are looking at exists (not broken symlink)
- if os.path.exists(self.full_path):
- size = os.path.getsize(self.full_path)
- mtime = os.path.getmtime(self.full_path)
- super(LocalArtifact, self).__init__(
- urlbase, file_name, size, mtime, human_readable)
-
- def get_type(self):
- if self.isdir():
- return 'folder'
- else:
- mtype = mimetypes.guess_type(self.full_path)[0]
- if self.human_readable:
- if mtype is None:
- mtype = 'other'
- elif mtype.split('/')[0] == 'text':
- mtype = 'text'
- return mtype
-
- def get_file_download_response(self):
- "Return HttpResponse which will send path to user's browser."
- assert not self.isdir()
- file_name = os.path.basename(self.full_path)
- mime = mimetypes.guess_type(file_name)[0]
- if mime is None:
- mime = "application/force-download"
- response = HttpResponse(mimetype=mime)
- response['Content-Disposition'] = ('attachment; filename=%s' %
- smart_str(file_name))
- response['X-Sendfile'] = smart_str(self.full_path)
- return response
-
- @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():
- path = self.full_path
- else:
- path = os.path.dirname(self.full_path)
- eulas = glob.glob(path + '/*EULA.txt*')
- return [os.path.basename(x) for x in eulas]
-
- def get_file_contents(self, fname):
- fname = os.path.join(self.full_path, fname)
- if os.path.isfile(fname) and not os.path.islink(fname):
- with open(fname, 'r') as f:
- return f.read()
-
- def get_textile_files(self):
- assert self.isdir()
- files = render_text_files.RenderTextFiles.find_relevant_files(
- self.full_path)
- for f in files:
- with open(f) as fd:
- yield f, fd
-
- def isdir(self):
- return os.path.isdir(self.full_path)
-
-
def dir_list(artifact, human_readable=True):
path = artifact.full_path
url = artifact.url()
diff --git a/license_protected_downloads/tests/test_common.py b/license_protected_downloads/tests/test_common.py
index 28acbc3..4465c3b 100644
--- a/license_protected_downloads/tests/test_common.py
+++ b/license_protected_downloads/tests/test_common.py
@@ -4,17 +4,19 @@ import os
import tempfile
import unittest
-from license_protected_downloads import common
+from license_protected_downloads.artifact import LocalArtifact
+from license_protected_downloads.artifact.base import _sizeof_fmt, cached_prop
+from license_protected_downloads.common import _sort_artifacts
from license_protected_downloads.tests.test_views import TESTSERVER_ROOT
class CommonTests(unittest.TestCase):
def test_sizeof_fmt(self):
- self.assertEqual(common._sizeof_fmt(1), '1')
- self.assertEqual(common._sizeof_fmt(1234), '1.2K')
- self.assertEqual(common._sizeof_fmt(1234567), '1.2M')
- self.assertEqual(common._sizeof_fmt(1234567899), '1.1G')
- self.assertEqual(common._sizeof_fmt(1234567899999), '1.1T')
+ self.assertEqual(_sizeof_fmt(1), '1')
+ self.assertEqual(_sizeof_fmt(1234), '1.2K')
+ self.assertEqual(_sizeof_fmt(1234567), '1.2M')
+ self.assertEqual(_sizeof_fmt(1234567899), '1.1G')
+ self.assertEqual(_sizeof_fmt(1234567899999), '1.1T')
def test_sort_artifacts(self):
patterns = [
@@ -23,9 +25,9 @@ class CommonTests(unittest.TestCase):
(['10', 'foo', '100', 'latest'], ['latest', '10', '100', 'foo']),
]
for files, expected in patterns:
- artifacts = [common.LocalArtifact(None, '', x, True, '')
+ artifacts = [LocalArtifact(None, '', x, True, '')
for x in files]
- artifacts.sort(common._sort_artifacts)
+ artifacts.sort(_sort_artifacts)
self.assertEqual(expected, [x.file_name for x in artifacts])
def test_cached_property(self):
@@ -33,7 +35,7 @@ class CommonTests(unittest.TestCase):
def __init__(self):
self.count = 0
- @common.cached_prop
+ @cached_prop
def bar(self):
v = self.count
self.count += 1
@@ -46,7 +48,7 @@ class CommonTests(unittest.TestCase):
class ArtifactTests(unittest.TestCase):
def setUp(self):
- self.artifact = common.LocalArtifact(
+ self.artifact = LocalArtifact(
None, '/', 'readme', False, TESTSERVER_ROOT)
def make_temporary_file(self, data, root=None):
diff --git a/license_protected_downloads/tests/test_views.py b/license_protected_downloads/tests/test_views.py
index 0074595..fdd8e8c 100644
--- a/license_protected_downloads/tests/test_views.py
+++ b/license_protected_downloads/tests/test_views.py
@@ -12,10 +12,8 @@ from django.test import Client, TestCase
from django.http import HttpResponse
from license_protected_downloads.buildinfo import BuildInfo
-from license_protected_downloads.common import (
- _insert_license_into_db,
- LocalArtifact,
-)
+from license_protected_downloads.artifact import LocalArtifact
+from license_protected_downloads.artifact.base import _insert_license_into_db
from license_protected_downloads.config import INTERNAL_HOSTS
from license_protected_downloads.tests.helpers import temporary_directory
from license_protected_downloads import views