Merge lp:~abentley/workspace-runner/upload-mime-type into lp:workspace-runner

Proposed by Aaron Bentley
Status: Merged
Merged at revision: 22
Proposed branch: lp:~abentley/workspace-runner/upload-mime-type
Merge into: lp:workspace-runner
Diff against target: 116 lines (+66/-4)
2 files modified
workspace_runner/tests/test_upload_artifacts.py (+37/-1)
workspace_runner/upload_artifacts.py (+29/-3)
To merge this branch: bzr merge lp:~abentley/workspace-runner/upload-mime-type
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
Review via email: mp+263414@code.launchpad.net

This proposal supersedes a proposal from 2015-06-30.

Commit message

Set content-types for uploads.

Description of the change

In this branch, the upload script can now use file extension to determine Content-Type header.

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Thank you. I have a question inline.

review: Needs Information (code)
Revision history for this message
Curtis Hovey (sinzui) wrote :

We spoke on irc. The mimetypes modules could reduce the number of lines, but we will still need to register some of the special types we have. Can you make sure that I can read *.changes and *.dsc in my browser?

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'workspace_runner/tests/test_upload_artifacts.py'
--- workspace_runner/tests/test_upload_artifacts.py 2015-06-29 19:19:16 +0000
+++ workspace_runner/tests/test_upload_artifacts.py 2015-06-30 20:28:44 +0000
@@ -1,4 +1,5 @@
1from argparse import Namespace1from argparse import Namespace
2import errno
2import json3import json
3import os4import os
4from tempfile import NamedTemporaryFile5from tempfile import NamedTemporaryFile
@@ -12,6 +13,7 @@
12 parse_args,13 parse_args,
13 resolve_rules,14 resolve_rules,
14 upload_artifacts,15 upload_artifacts,
16 upload_file,
15 )17 )
1618
1719
@@ -75,9 +77,42 @@
75 def __init__(self, path):77 def __init__(self, path):
76 self.contents = None78 self.contents = None
77 self.path = path79 self.path = path
80 self.headers = None
7881
79 def set_contents_from_file(self, fp):82 def set_contents_from_file(self, fp, headers=None):
80 self.contents = fp.read()83 self.contents = fp.read()
84 self.headers = headers
85
86
87class TestUploadFile(TestCase):
88
89 def ct_test(self, mime_type, extension=None, filename=None):
90 bucket = FakeBucket()
91 with temp_dir() as files_dir:
92 if filename is None:
93 filename = 'foo.{}'.format(extension)
94 file_path = os.path.join(files_dir, filename)
95 parent = os.path.dirname(file_path)
96 try:
97 os.makedirs(parent)
98 except OSError as e:
99 if e.errno != errno.EEXIST:
100 raise
101 open(file_path, 'w').close()
102 upload_file(file_path, 'foo', 'bar', bucket)
103 self.assertEqual(bucket.keys[0].headers,
104 {'Content-Type': mime_type})
105
106 def test_content_type(self):
107 self.ct_test('application/gzip', 'tar.gz')
108 self.ct_test('application/gzip', 'tgz')
109 self.ct_test('application/json', 'json')
110 self.ct_test('text/plain', 'txt')
111 self.ct_test('application/octet-stream', 'foo')
112 self.ct_test('text/x-yaml; charset=utf-8', 'jenv')
113 self.ct_test('application/zip', 'zip')
114 self.ct_test('text/plain', 'log')
115 self.ct_test('text/plain', filename='foo/consoleText')
81116
82117
83class TestUploadArtifacts(TestCase):118class TestUploadArtifacts(TestCase):
@@ -109,6 +144,7 @@
109 key = bucket.keys[0]144 key = bucket.keys[0]
110 self.assertEqual(key.path, 'prefix1/text-files/foo.txt')145 self.assertEqual(key.path, 'prefix1/text-files/foo.txt')
111 self.assertEqual(key.contents, 'foo file')146 self.assertEqual(key.contents, 'foo file')
147 self.assertEqual(key.headers, {'Content-Type': 'text/plain'})
112148
113149
114class TestMain(TestCase):150class TestMain(TestCase):
115151
=== modified file 'workspace_runner/upload_artifacts.py'
--- workspace_runner/upload_artifacts.py 2015-06-30 18:37:21 +0000
+++ workspace_runner/upload_artifacts.py 2015-06-30 20:28:44 +0000
@@ -27,13 +27,39 @@
27 return result27 return result
2828
2929
30def get_media_type(source_name):
31 """Determine a media type from a filename."""
32 basename = os.path.basename(source_name)
33 if basename == 'consoleText':
34 return 'text/plain'
35 split_name = basename.rsplit('.', 1)
36 if len(split_name) == 1:
37 return 'application/octet-stream'
38 else:
39 extension = split_name[-1]
40 return {
41 'gz': 'application/gzip',
42 'jenv': 'text/x-yaml; charset=utf-8',
43 'json': 'application/json',
44 'log': 'text/plain',
45 'tgz': 'application/gzip',
46 'txt': 'text/plain',
47 'zip': 'application/zip',
48 }.get(extension, 'application/octet-stream')
49
50
51def upload_file(source_name, prefix, dest, bucket):
52 media_type = get_media_type(source_name)
53 key = bucket.new_key('/'.join((prefix, dest)))
54 with open(source_name) as source:
55 key.set_contents_from_file(source, {'Content-Type': media_type})
56
57
30def upload_artifacts(root, settings, s3_factory=S3Connection):58def upload_artifacts(root, settings, s3_factory=S3Connection):
31 connection = s3_factory(settings['access_key'], settings['secret_key'])59 connection = s3_factory(settings['access_key'], settings['secret_key'])
32 bucket = connection.get_bucket(settings['bucket'])60 bucket = connection.get_bucket(settings['bucket'])
33 for source_name, dest in resolve_rules(root, settings['files']):61 for source_name, dest in resolve_rules(root, settings['files']):
34 key = bucket.new_key('/'.join((settings['prefix'], dest)))62 upload_file(source_name, settings['prefix'], dest, bucket)
35 with open(source_name) as source:
36 key.set_contents_from_file(source)
3763
3864
39def main(argv=None):65def main(argv=None):

Subscribers

People subscribed via source and target branches