Skip to content
Permalink
Browse files

move `serve_file_download` to utility (#319)

- We have the similar function at multiple places serving the same purpose.
- It is made available in the utility module and can be accessed anywhere.
  • Loading branch information...
thealphadollar authored and canihavesomecoffee committed Jul 11, 2019
1 parent b187fb2 commit cae4449c95e5b10d467bdc9466d2b65280ce0e5d
@@ -13,6 +13,7 @@
from mod_regression.models import (Category, InputType, OutputType,
RegressionTest, RegressionTestOutput)
from mod_sample.models import Sample
from utility import serve_file_download

mod_regression = Blueprint('regression', __name__)

@@ -187,32 +188,7 @@ def test_result_file(regression_test_output_id):
rto = RegressionTestOutput.query.filter(RegressionTestOutput.id == regression_test_output_id).first()
if rto is None:
abort(404)
return serve_file_download(rto.filename_correct)


def serve_file_download(file_name, content_type='application/octet-stream') -> Any:
"""
Endpoint to serve file download.
:param file_name: name of the file
:type file_name: str
:param content_type: content type of the file, defaults to 'application/octet-stream'
:type content_type: str, optional
:return: response, the file download
:rtype: Flask response
"""
from run import config

file_path = os.path.join(config.get('SAMPLE_REPOSITORY', ''), 'TestResults', file_name)
response = make_response()
response.headers['Content-Description'] = 'File Transfer'
response.headers['Cache-Control'] = 'no-cache'
response.headers['Content-Type'] = content_type
response.headers['Content-Disposition'] = 'attachment; filename={name}'.format(name=file_name)
response.headers['Content-Length'] = os.path.getsize(file_path)
response.headers['X-Accel-Redirect'] = '/' + os.path.join('regression-download', file_name)

return response
return serve_file_download(rto.filename_correct, 'TestResults', 'regression-download')


@mod_regression.route('/test/new', methods=['GET', 'POST'])
@@ -28,6 +28,7 @@
from mod_sample.models import ExtraFile, ForbiddenExtension, Issue, Sample
from mod_test.models import Test, TestResult, TestResultFile
from mod_upload.models import Platform
from utility import serve_file_download

mod_sample = Blueprint('sample', __name__) # type: ignore

@@ -188,32 +189,6 @@ def sample_by_hash(sample_hash):
raise SampleNotFoundException('Sample with hash {hash} not found.'.format(hash=sample_hash))


def serve_file_download(file_name, sub_folder='', content_type='application/octet-stream') -> Any:
"""
Serve sample file for download.
:param file_name: name of the sample file
:type file_name: str
:param sub_folder: name of the subfolder, defaults to ''
:type sub_folder: str, optional
:param content_type: type of the content, defaults to 'application/octet-stream'
:type content_type: str, optional
:return: sample file
:rtype: Flask response
"""
from run import config

file_path = os.path.join(config.get('SAMPLE_REPOSITORY', ''), 'TestFiles', sub_folder, file_name)
response = make_response()
response.headers['Content-Description'] = 'File Transfer'
response.headers['Cache-Control'] = 'no-cache'
response.headers['Content-Type'] = content_type
response.headers['Content-Disposition'] = 'attachment; filename={file_name}'.format(file_name=file_name)
response.headers['Content-Length'] = os.path.getsize(file_path)
response.headers['X-Accel-Redirect'] = '/' + os.path.join('media-download', sub_folder, file_name)
return response


@mod_sample.route('/download/<sample_id>') # type: ignore
def download_sample(sample_id):
"""
@@ -227,7 +202,7 @@ def download_sample(sample_id):
"""
sample = Sample.query.filter(Sample.id == sample_id).first()
if sample is not None:
return serve_file_download(sample.filename)
return serve_file_download(sample.filename, 'TestFiles', 'media-download')
raise SampleNotFoundException('Sample not found')


@@ -250,7 +225,7 @@ def download_sample_media_info(sample_id):
media_info_path = os.path.join(
config.get('SAMPLE_REPOSITORY', ''), 'TestFiles', 'media', sample.sha + '.xml')
if os.path.isfile(media_info_path):
return serve_file_download(sample.sha + '.xml', 'media', 'text/xml')
return serve_file_download(sample.sha + '.xml', 'TestFiles', 'media-download', 'media', 'text/xml')

raise SampleNotFoundException('Media information for sample {id} not found'.format(id=sample.id))

@@ -276,7 +251,7 @@ def download_sample_additional(sample_id, additional_id):
# Fetch additional info
extra = ExtraFile.query.filter(ExtraFile.id == additional_id).first()
if extra is not None:
return serve_file_download(extra.filename, 'extra')
return serve_file_download(extra.filename, 'TestFiles', 'media-download', 'extra')
raise SampleNotFoundException('Extra file {a_id} for sample {s_id} not found'.format(
a_id=additional_id, s_id=sample.id))
raise SampleNotFoundException('Sample with id {id} not found'.format(id=sample_id))
@@ -26,6 +26,7 @@
regressionTestLinkTable)
from mod_test.models import (Fork, Test, TestPlatform, TestProgress,
TestResult, TestResultFile, TestStatus, TestType)
from utility import serve_file_download

mod_test = Blueprint('test', __name__) # type: ignore

@@ -362,31 +363,6 @@ def generate_diff(test_id: int, regression_test_id: int, output_id: int, to_view
abort(404)


def serve_file_download(file_name, content_type='application/octet-stream') -> Any:
"""
Endpoint to serve file download.
:param file_name: name of the file
:type file_name: str
:param content_type: content type of the file, defaults to 'application/octet-stream'
:type content_type: str, optional
:return: response, the file download
:rtype: Flask response
"""
from run import config

file_path = os.path.join(config.get('SAMPLE_REPOSITORY', ''), 'LogFiles', file_name)
response = make_response()
response.headers['Content-Description'] = 'File Transfer'
response.headers['Cache-Control'] = 'no-cache'
response.headers['Content-Type'] = content_type
response.headers['Content-Disposition'] = 'attachment; filename={name}'.format(name=file_name)
response.headers['Content-Length'] = os.path.getsize(file_path)
response.headers['X-Accel-Redirect'] = '/' + os.path.join('logfile-download', file_name)

return response


@mod_test.route('/log-files/<test_id>') # type: ignore
def download_build_log_file(test_id):
"""
@@ -407,7 +383,7 @@ def download_build_log_file(test_id):
log_file_path = os.path.join(config.get('SAMPLE_REPOSITORY', ''), 'LogFiles', test_id + '.txt')

if os.path.isfile(log_file_path):
return serve_file_download(test_id + '.txt', 'text/plain')
return serve_file_download(test_id + '.txt', 'LogFiles', 'logfile-download', 'text/plain')

raise TestNotFoundException('Build log for Test {id} not found'.format(id=test_id))

@@ -0,0 +1,19 @@
from unittest import mock

from tests.base import BaseTestCase


class TestUtility(BaseTestCase):

@mock.patch('utility.path')
def test_serve_file_download(self, mock_path):
"""
Test function serve_file_download.
"""
from utility import serve_file_download

response = serve_file_download('to_download', 'folder', 'accl_folder')

self.assert200(response)
self.assertEqual(2, mock_path.join.call_count)
mock_path.getsize.assert_called_once_with(mock_path.join())
@@ -66,19 +66,6 @@ def test_download_result_file(self, mock_regression_output, mock_serve):
mock_regression_output.query.filter.assert_called_once_with(mock_regression_output.id == 1)
mock_serve.assert_called_once()

@mock.patch('mod_regression.controllers.os')
def test_serve_file_download(self, mock_os):
"""
Test function serve_file_download.
"""
from mod_regression.controllers import serve_file_download

response = serve_file_download('to_download')

self.assert200(response)
self.assertEqual(2, mock_os.path.join.call_count)
mock_os.path.getsize.assert_called_once_with(mock_os.path.join())

def test_regression_test_deletion_Without_login(self):
response = self.app.test_client().get('/regression/test/9432/delete')
self.assertEqual(response.status_code, 302)
@@ -68,19 +68,6 @@ def test_sample_id(self):
self.assertEqual(response.status_code, 200)
self.assert_template_used('sample/sample_info.html')

@mock.patch('mod_sample.controllers.os')
def test_serve_file_download(self, mock_os):
"""
Test function serve_file_download.
"""
from mod_sample.controllers import serve_file_download

response = serve_file_download('to_download')

self.assert200(response)
self.assertEqual(2, mock_os.path.join.call_count)
mock_os.path.getsize.assert_called_once_with(mock_os.path.join())

@mock.patch('mod_sample.controllers.serve_file_download')
@mock.patch('mod_sample.controllers.Sample')
def test_download_sample(self, mock_sample, mock_serve_download):
@@ -219,19 +219,6 @@ def test_generate_diff_download(self, mock_response, mock_request, mock_test_res

self.assertTrue(response, mock_response())

@mock.patch('mod_test.controllers.os')
def test_serve_file_download(self, mock_os):
"""
Test function serve_file_download.
"""
from mod_test.controllers import serve_file_download

response = serve_file_download('to_download')

self.assert200(response)
self.assertEqual(2, mock_os.path.join.call_count)
mock_os.path.getsize.assert_called_once_with(mock_os.path.join())

@mock.patch('mod_test.controllers.Test')
def test_download_build_log_file_test_not_found(self, mock_test):
"""
@@ -1,5 +1,34 @@
"""provide common utility attributes such as root path."""

from os import path
from typing import Any

from flask import make_response

ROOT_DIR = path.dirname(path.abspath(__file__))


def serve_file_download(file_name, file_folder, xaccel_folder,
subfolder='', content_type='application/octet-stream') -> Any:
"""
Endpoint to serve file download.
:param file_name: name of the file
:type file_name: str
:param content_type: content type of the file, defaults to 'application/octet-stream'
:type content_type: str, optional
:return: response, the file download
:rtype: Flask response
"""
from run import config

file_path = path.join(config.get('SAMPLE_REPOSITORY', ''), file_folder, subfolder, file_name)
response = make_response()
response.headers['Content-Description'] = 'File Transfer'
response.headers['Cache-Control'] = 'no-cache'
response.headers['Content-Type'] = content_type
response.headers['Content-Disposition'] = 'attachment; filename={name}'.format(name=file_name)
response.headers['Content-Length'] = path.getsize(file_path)
response.headers['X-Accel-Redirect'] = '/' + path.join(xaccel_folder, subfolder, file_name)

return response

0 comments on commit cae4449

Please sign in to comment.
You can’t perform that action at this time.