Merge lp:~allenap/convoy/python3-clean-up into lp:convoy

Proposed by Gavin Panella
Status: Merged
Merged at revision: 38
Proposed branch: lp:~allenap/convoy/python3-clean-up
Merge into: lp:convoy
Prerequisite: lp:~allenap/convoy/python3
Diff against target: 347 lines (+89/-65)
5 files modified
convoy/combo.py (+11/-5)
convoy/meta.py (+15/-16)
convoy/tests/test_combo.py (+54/-39)
convoy/tests/test_meta.py (+8/-4)
setup.py (+1/-1)
To merge this branch: bzr merge lp:~allenap/convoy/python3-clean-up
Reviewer Review Type Date Requested Status
Fabrice Matrat (community) Approve
Review via email: mp+277292@code.launchpad.net

Commit message

Tidy up after the Python 3 porting effort.

To post a comment you must log in.
Revision history for this message
Fabrice Matrat (fabricematrat) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'convoy/combo.py'
--- convoy/combo.py 2015-11-11 19:53:19 +0000
+++ convoy/combo.py 2015-11-11 19:53:19 +0000
@@ -15,13 +15,17 @@
15# along with this program. If not, see <http://www.gnu.org/licenses/>.15# along with this program. If not, see <http://www.gnu.org/licenses/>.
1616
1717
18import cgi
19import logging18import logging
20import os.path19import os.path
21import re20import re
22import sys21import sys
2322
24try:23try:
24 from urllib.parse import parse_qsl
25except ImportError:
26 from cgi import parse_qsl
27
28try:
25 import urllib.parse as urlparse29 import urllib.parse as urlparse
26except ImportError:30except ImportError:
27 import urlparse31 import urlparse
@@ -56,7 +60,7 @@
5660
57 Returns the list of arguments in the original order.61 Returns the list of arguments in the original order.
58 """62 """
59 params = cgi.parse_qsl(query, keep_blank_values=True)63 params = parse_qsl(query, keep_blank_values=True)
60 return tuple([param for param, value in params])64 return tuple([param for param, value in params])
6165
6266
@@ -124,12 +128,13 @@
124 parts = relative_parts + url.split(b"/")128 parts = relative_parts + url.split(b"/")
125 result = []129 result = []
126 for part in parts:130 for part in parts:
127 if part == b".." and result and result[-1] != b"..":131 if part == b".." and result[-1:] != [b".."]:
128 result.pop(-1)132 result.pop(-1)
129 continue133 continue
130 result.append(part)134 result.append(part)
131 return b"url(x)".replace(b"x", b"/".join(135 return b"url(x)".replace(b"x", b"/".join(
132 part for part in [resource_prefix] + result if part))136 part for part in [resource_prefix] + result
137 if part))
133138
134 file_content = URL_RE.sub(fix_relative_url, file_content)139 file_content = URL_RE.sub(fix_relative_url, file_content)
135 yield file_content140 yield file_content
@@ -143,7 +148,8 @@
143 yield chunk148 yield chunk
144149
145150
146def combo_app(root, resource_prefix="", rewrite_urls=True, additional_headers=None):151def combo_app(
152 root, resource_prefix="", rewrite_urls=True, additional_headers=None):
147 """A simple YUI Combo Service WSGI app.153 """A simple YUI Combo Service WSGI app.
148154
149 Serves any files under C{root}, setting an appropriate155 Serves any files under C{root}, setting an appropriate
150156
=== modified file 'convoy/meta.py'
--- convoy/meta.py 2015-11-11 19:53:19 +0000
+++ convoy/meta.py 2015-11-11 19:53:19 +0000
@@ -170,11 +170,10 @@
170 return match.group(1) + literals_map[literal] + match.group(3)170 return match.group(1) + literals_map[literal] + match.group(3)
171 return match.group(0)171 return match.group(0)
172172
173
174 linebreak = ",\n "173 linebreak = ",\n "
175 variables_decl = "var SKIN_SAM_PREFIX = 'skin-sam-'" + linebreak174 variables_decl = "var SKIN_SAM_PREFIX = 'skin-sam-'" + linebreak
176 if self.prefix:175 if self.prefix:
177 variables_decl += "PREFIX = '%s'%s" % (self.prefix, linebreak)176 variables_decl += "PREFIX = '%s'%s" % (self.prefix, linebreak)
178 extra_variables = []177 extra_variables = []
179 for literal, variable in sorted(literals_map.items()):178 for literal, variable in sorted(literals_map.items()):
180 extra_variable = "%s = %s" % (179 extra_variable = "%s = %s" % (
@@ -220,8 +219,8 @@
220 # It's easy to think that doing 'CORE_CSS + %(values)s'219 # It's easy to think that doing 'CORE_CSS + %(values)s'
221 # instead of using concat would work, but it doesn't;220 # instead of using concat would work, but it doesn't;
222 # you'll end up with a string instead of a list.221 # you'll end up with a string instead of a list.
223 module_decl.append("after_list = CORE_CSS");222 module_decl.append("after_list = CORE_CSS")
224 module_decl.append("after_list.concat(%s)" % value);223 module_decl.append("after_list.concat(%s)" % value)
225 value = "after_list"224 value = "after_list"
226 if key == "path":225 if key == "path":
227 value = value.replace(226 value = value.replace(
@@ -369,15 +368,15 @@
369368
370369
371def main():370def main():
372 options, args = get_options()371 options, args = get_options()
373 if options.src_dir is None:372 if options.src_dir is None:
374 options.src_dir = os.getcwd()373 options.src_dir = os.getcwd()
375 Builder(374 Builder(
376 name=options.name,375 name=options.name,
377 src_dir=os.path.abspath(options.src_dir),376 src_dir=os.path.abspath(options.src_dir),
378 output=options.output,377 output=options.output,
379 prefix=options.prefix,378 prefix=options.prefix,
380 exclude_regex=options.exclude_regex,379 exclude_regex=options.exclude_regex,
381 ext=options.ext,380 ext=options.ext,
382 include_skin=not options.no_skin,381 include_skin=not options.no_skin,
383 ).do_build()382 ).do_build()
384383
=== modified file 'convoy/tests/test_combo.py'
--- convoy/tests/test_combo.py 2015-11-11 19:53:19 +0000
+++ convoy/tests/test_combo.py 2015-11-11 19:53:19 +0000
@@ -88,10 +88,11 @@
88 "/* event-custom/event-custom-min.js */",88 "/* event-custom/event-custom-min.js */",
89 "** event-custom-min **"))89 "** event-custom-min **"))
90 self.assertEqual(90 self.assertEqual(
91 b"".join(combine_files(["yui/yui-min.js",91 b"".join(combine_files(
92 "oop/oop-min.js",92 ["yui/yui-min.js",
93 "event-custom/event-custom-min.js"],93 "oop/oop-min.js",
94 root=test_dir)).strip(),94 "event-custom/event-custom-min.js"],
95 root=test_dir)).strip(),
95 expected.encode("ascii"))96 expected.encode("ascii"))
9697
97 def test_combine_files_yields_only_byte_strings(self):98 def test_combine_files_yields_only_byte_strings(self):
@@ -144,9 +145,10 @@
144 }145 }
145 """146 """
146 self.assertTextEquals(147 self.assertTextEquals(
147 b"".join(combine_files(["widget/assets/skins/sam/widget.css",148 b"".join(combine_files(
148 "editor/assets/skins/sam/editor.css"],149 ["widget/assets/skins/sam/widget.css",
149 root=test_dir)).strip(),150 "editor/assets/skins/sam/editor.css"],
151 root=test_dir)).strip(),
150 expected)152 expected)
151153
152 def test_combine_css_leaves_absolute_urls_untouched(self):154 def test_combine_css_leaves_absolute_urls_untouched(self):
@@ -189,9 +191,10 @@
189 }191 }
190 """192 """
191 self.assertTextEquals(193 self.assertTextEquals(
192 b"".join(combine_files(["widget/assets/skins/sam/widget.css",194 b"".join(combine_files(
193 "editor/assets/skins/sam/editor.css"],195 ["widget/assets/skins/sam/widget.css",
194 root=test_dir)).strip(),196 "editor/assets/skins/sam/editor.css"],
197 root=test_dir)).strip(),
195 expected)198 expected)
196199
197 def test_combine_css_leaves_data_uris_untouched(self):200 def test_combine_css_leaves_data_uris_untouched(self):
@@ -234,9 +237,10 @@
234 }237 }
235 """238 """
236 self.assertTextEquals(239 self.assertTextEquals(
237 b"".join(combine_files(["widget/assets/skins/sam/widget.css",240 b"".join(combine_files(
238 "editor/assets/skins/sam/editor.css"],241 ["widget/assets/skins/sam/widget.css",
239 root=test_dir)).strip(),242 "editor/assets/skins/sam/editor.css"],
243 root=test_dir)).strip(),
240 expected)244 expected)
241245
242 def test_no_parent_hack(self):246 def test_no_parent_hack(self):
@@ -336,10 +340,10 @@
336 }340 }
337 """341 """
338 self.assertTextEquals(342 self.assertTextEquals(
339 b"".join(combine_files(["widget/assets/skins/sam/widget.css",343 b"".join(combine_files(
340 "editor/assets/skins/sam/editor.css"],344 ["widget/assets/skins/sam/widget.css",
341 root=test_dir,345 "editor/assets/skins/sam/editor.css"],
342 resource_prefix="/static/")).strip(),346 root=test_dir, resource_prefix="/static/")).strip(),
343 expected)347 expected)
344348
345 def test_combine_css_adds_custom_prefix_minified(self):349 def test_combine_css_adds_custom_prefix_minified(self):
@@ -367,20 +371,18 @@
367 def test_rewrite_url_normalizes_parent_references(self):371 def test_rewrite_url_normalizes_parent_references(self):
368 """URL references in CSS files get normalized for parent dirs."""372 """URL references in CSS files get normalized for parent dirs."""
369 test_dir = self.makeDir()373 test_dir = self.makeDir()
370 files = [374 self.makeSampleFile(
371 self.makeSampleFile(375 test_dir, os.path.join("yui", "base", "base.css"),
372 test_dir,376 ".foo{background-image:url(../../img.png)}"),
373 os.path.join("yui", "base", "base.css"),
374 ".foo{background-image:url(../../img.png)}"),
375 ]
376377
377 expected = """378 expected = """
378 /* yui/base/base.css */379 /* yui/base/base.css */
379 .foo{background-image:url(img.png)}380 .foo{background-image:url(img.png)}
380 """381 """
381 self.assertTextEquals(382 self.assertTextEquals(
382 b"".join(combine_files(["yui/base/base.css"],383 b"".join(combine_files(
383 root=test_dir)).strip(),384 ["yui/base/base.css"],
385 root=test_dir)).strip(),
384 expected)386 expected)
385387
386388
@@ -437,8 +439,10 @@
437 ["yui/yui-min.js",439 ["yui/yui-min.js",
438 "oop/oop-min.js",440 "oop/oop-min.js",
439 "event-custom/event-custom-min.js"]), status=200)441 "event-custom/event-custom-min.js"]), status=200)
440 self.assertEqual(res.headers, [("Content-Type", "text/javascript"),442 self.assertEqual(res.headers, [
441 ("X-Content-Type-Options", "nosniff")])443 ("Content-Type", "text/javascript"),
444 ("X-Content-Type-Options", "nosniff"),
445 ])
442 self.assertEqual(res.body.strip(), expected.encode("ascii"))446 self.assertEqual(res.body.strip(), expected.encode("ascii"))
443447
444 def test_combo_app_sets_content_type_for_css(self):448 def test_combo_app_sets_content_type_for_css(self):
@@ -452,8 +456,10 @@
452456
453 res = self.app.get("/?" + "&".join(457 res = self.app.get("/?" + "&".join(
454 ["widget/skin/sam/widget.css"]), status=200)458 ["widget/skin/sam/widget.css"]), status=200)
455 self.assertEqual(res.headers, [("Content-Type", "text/css"),459 self.assertEqual(res.headers, [
456 ("X-Content-Type-Options", "nosniff")])460 ("Content-Type", "text/css"),
461 ("X-Content-Type-Options", "nosniff"),
462 ])
457 self.assertEqual(res.body.strip(), expected.encode("ascii"))463 self.assertEqual(res.body.strip(), expected.encode("ascii"))
458464
459 def test_no_filename_gives_404(self):465 def test_no_filename_gives_404(self):
@@ -467,12 +473,16 @@
467 Content-Type and X-Content-Type-Options headers set for473 Content-Type and X-Content-Type-Options headers set for
468 non-existent files.474 non-existent files.
469 """475 """
470 res = self.app.get("/?" + "&".join(476 res = self.app.get(
471 ["foo/bar/baz",477 "/?" + "&".join([
472 "<html><script>alert(document.domain)</script></html>"]),478 "foo/bar/baz",
473 status=400)479 "<html><script>alert(document.domain)</script></html>",
474 self.assertEqual(res.headers, [("Content-Type", "text/plain"),480 ]),
475 ("X-Content-Type-Options", "nosniff")])481 status=400)
482 self.assertEqual(res.headers, [
483 ("Content-Type", "text/plain"),
484 ("X-Content-Type-Options", "nosniff"),
485 ])
476486
477 def test_js_comment_escape_hack(self):487 def test_js_comment_escape_hack(self):
478 """Attacks to break out of the JS comment will get a 400 error."""488 """Attacks to break out of the JS comment will get a 400 error."""
@@ -528,9 +538,14 @@
528 app.get("/../etc?yui-min&passwd", status=400)538 app.get("/../etc?yui-min&passwd", status=400)
529539
530 def test_cache_headers_set(self):540 def test_cache_headers_set(self):
531 app = TestApp(combo_app(self.root, additional_headers=[('Cache-Control', 'max-age=3600, public')]))541 app = TestApp(combo_app(
542 self.root, additional_headers=[
543 ('Cache-Control', 'max-age=3600, public'),
544 ]))
532 res = app.get("/?" + "&".join(545 res = app.get("/?" + "&".join(
533 ["widget/skin/sam/widget.css"]), status=400)546 ["widget/skin/sam/widget.css"]), status=400)
534 self.assertEqual(res.headers, [("Content-Type", "text/css"),547 self.assertEqual(res.headers, [
535 ("X-Content-Type-Options", "nosniff"),548 ("Content-Type", "text/css"),
536 ('Cache-Control', 'max-age=3600, public')])549 ("X-Content-Type-Options", "nosniff"),
550 ('Cache-Control', 'max-age=3600, public'),
551 ])
537552
=== modified file 'convoy/tests/test_meta.py'
--- convoy/tests/test_meta.py 2015-11-11 19:53:19 +0000
+++ convoy/tests/test_meta.py 2015-11-11 19:53:19 +0000
@@ -126,7 +126,8 @@
126 metadata = extract_metadata("""\126 metadata = extract_metadata("""\
127 YUI.add('lazr.anim', function(Y){127 YUI.add('lazr.anim', function(Y){
128 Y.log('Hello World');128 Y.log('Hello World');
129 }, '0.1', {"use": ["dom"], "requires": [ "node" ,"anim" , "event" ]});129 }, '0.1', {"use": ["dom"], "requires": [
130 "node" ,"anim" , "event" ]});
130 """)131 """)
131132
132 self.assertEqual(len(metadata), 1)133 self.assertEqual(len(metadata), 1)
@@ -141,7 +142,8 @@
141 metadata = extract_metadata("""\142 metadata = extract_metadata("""\
142 YUI.add('lazr.anim', function(Y){143 YUI.add('lazr.anim', function(Y){
143 Y.log('Hello World');144 Y.log('Hello World');
144 }, '0.1', {"requires": [ "node" ,"anim" , "event" ], "use": ["dom"]});145 }, '0.1', {"requires": [ "node" ,"anim" , "event" ],
146 "use": ["dom"]});
145 """)147 """)
146148
147 self.assertEqual(len(metadata), 1)149 self.assertEqual(len(metadata), 1)
@@ -177,7 +179,9 @@
177 """179 """
178 metadata = extract_metadata("""180 metadata = extract_metadata("""
179 YUI.add('test', function(Y) {181 YUI.add('test', function(Y) {
180 this._dds[h[i]] = new YAHOO.util.DragDrop(this._handles[h[i]], this.get('id') + '-handle-' + h, { useShim: this.get('useShim') });182 this._dds[h[i]] = new YAHOO.util.DragDrop(
183 this._handles[h[i]], this.get('id') + '-handle-' + h, {
184 useShim: this.get('useShim') });
181 }, '1.0', {requires: ['dom']});185 }, '1.0', {requires: ['dom']});
182 """)186 """)
183187
@@ -205,7 +209,6 @@
205 self.assertEqual(metadata[0]["requires"], ["node", "anim", "event"])209 self.assertEqual(metadata[0]["requires"], ["node", "anim", "event"])
206 self.assertEqual(metadata[0]["use"], ["dom"])210 self.assertEqual(metadata[0]["use"], ["dom"])
207211
208
209 def test_extract_has_no_quotes(self):212 def test_extract_has_no_quotes(self):
210 """213 """
211 If the javascript is using object literals, we should adjust for214 If the javascript is using object literals, we should adjust for
@@ -312,6 +315,7 @@
312 self.assertEqual(metadata[0]["supersedes"], ["old-anim"])315 self.assertEqual(metadata[0]["supersedes"], ["old-anim"])
313 self.assertEqual(metadata[0]["after"], ["lazr.base"])316 self.assertEqual(metadata[0]["after"], ["lazr.base"])
314317
318
315class GenerateMetadataTest(ConvoyTestCase):319class GenerateMetadataTest(ConvoyTestCase):
316320
317 def readFile(self, path):321 def readFile(self, path):
318322
=== modified file 'setup.py'
--- setup.py 2015-11-11 19:53:19 +0000
+++ setup.py 2015-11-11 19:53:19 +0000
@@ -1,5 +1,5 @@
1# Convoy is a WSGI app for loading multiple files in the same request.1# Convoy is a WSGI app for loading multiple files in the same request.
2# Copyright (C) 2010-2015 Canonical, Ltd.2# Copyright (C) 2011-2015 Canonical, Ltd.
3#3#
4# This program is free software: you can redistribute it and/or modify4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as5# it under the terms of the GNU Affero General Public License as

Subscribers

People subscribed via source and target branches

to all changes: