Merge lp:~ricardokirkner/convoy/open-non-ascii-files into lp:convoy

Proposed by Ricardo Kirkner
Status: Needs review
Proposed branch: lp:~ricardokirkner/convoy/open-non-ascii-files
Merge into: lp:convoy
Diff against target: 136 lines (+71/-6)
2 files modified
convoy/combo.py (+6/-4)
convoy/tests/test_combo.py (+65/-2)
To merge this branch: bzr merge lp:~ricardokirkner/convoy/open-non-ascii-files
Reviewer Review Type Date Requested Status
James Tait (community) Approve
Fabián Ezequiel Gallina (community) Approve
Review via email: mp+224865@code.launchpad.net

Commit message

handle non-ascii data in files to be combined

To post a comment you must log in.
Revision history for this message
Fabián Ezequiel Gallina (fgallina) wrote :

LGTM

review: Approve
Revision history for this message
James Tait (jamestait) wrote :

Yep, seems sensible.

review: Approve
26. By Ricardo Kirkner

handle non-ascii data in files to be combined

27. By Ricardo Kirkner

proper fix for handled non-ascii data in files to combine

as data is decoded into unicode as soon as it's read, data should be encoded into bytes
just before returning from the function and everything should be treated internally as unicode

28. By Ricardo Kirkner

modified tests to ensure regex code is being involved

29. By Ricardo Kirkner

removed lingering pdb

Unmerged revisions

29. By Ricardo Kirkner

removed lingering pdb

28. By Ricardo Kirkner

modified tests to ensure regex code is being involved

27. By Ricardo Kirkner

proper fix for handled non-ascii data in files to combine

as data is decoded into unicode as soon as it's read, data should be encoded into bytes
just before returning from the function and everything should be treated internally as unicode

26. By Ricardo Kirkner

handle non-ascii data in files to be combined

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'convoy/combo.py'
2--- convoy/combo.py 2013-08-20 14:48:24 +0000
3+++ convoy/combo.py 2014-06-27 19:30:26 +0000
4@@ -16,6 +16,7 @@
5
6
7 import cgi
8+import codecs
9 import os
10 import re
11 import urlparse
12@@ -54,7 +55,8 @@
13 return tuple([param for param, value in params])
14
15
16-def combine_files(fnames, root, resource_prefix="", rewrite_urls=True):
17+def combine_files(fnames, root, resource_prefix="", rewrite_urls=True,
18+ encoding="utf-8"):
19 """Combine many files into one.
20
21 Returns an iterator with the combined content of all the
22@@ -71,7 +73,7 @@
23 if not full.startswith(root) or not os.path.exists(full):
24 yield "/* [missing] */\n"
25 else:
26- with open(full, "r") as f:
27+ with codecs.open(full, "r", encoding=encoding) as f:
28 if file_ext == ".css" and rewrite_urls:
29 file_content = f.read()
30 src_dir = os.path.dirname(full)
31@@ -96,7 +98,7 @@
32 return "url(%s)" % "/".join(
33 filter(None, [resource_prefix] + result))
34 file_content = URL_RE.sub(fix_relative_url, file_content)
35- yield file_content
36+ yield file_content.encode(encoding)
37 yield "\n"
38 else:
39 while True:
40@@ -104,7 +106,7 @@
41 if not chunk:
42 yield "\n"
43 break
44- yield chunk
45+ yield chunk.encode(encoding)
46
47
48 def combo_app(root, resource_prefix="", rewrite_urls=True):
49
50=== modified file 'convoy/tests/test_combo.py'
51--- convoy/tests/test_combo.py 2013-08-20 14:48:24 +0000
52+++ convoy/tests/test_combo.py 2014-06-27 19:30:26 +0000
53@@ -1,3 +1,4 @@
54+# coding=utf-8
55 # Convoy is a WSGI app for loading multiple files in the same request.
56 # Copyright (C) 2010-2012 Canonical, Ltd.
57 #
58@@ -30,8 +31,8 @@
59
60 class ComboTestBase(object):
61
62- def makeSampleFile(self, root, fname, content):
63- content = textwrap.dedent(content).strip()
64+ def makeSampleFile(self, root, fname, content, encoding="utf-8"):
65+ content = textwrap.dedent(content).strip().encode(encoding)
66 full = os.path.join(root, fname)
67 parent = os.path.dirname(full)
68 if not os.path.exists(parent):
69@@ -373,6 +374,68 @@
70 root=test_dir)).strip(),
71 expected)
72
73+ def test_open_non_ascii_file(self):
74+ """Reading files with non-ascii characters should be handled properly.
75+
76+ Expect files to be encoded in a utf-8 compatible encoding.
77+ """
78+ # include some non-ascii data
79+ data = u"ŸÛÌ"
80+ content = ('.foo{background-image: url("some/url");'
81+ 'content: "%s";}' % data)
82+ test_dir = self.makeDir()
83+ files = [
84+ self.makeSampleFile(
85+ test_dir,
86+ os.path.join("yui", "base", "base.css"),
87+ content),
88+ ]
89+
90+ expected_content = (
91+ '.foo{background-image: url(yui/base/some/url);'
92+ 'content: "%s";}' % data.encode("utf-8"))
93+ expected = """
94+ /* yui/base/base.css */
95+ %s
96+ """ % expected_content
97+ self.assertTextEquals(
98+ "".join(combine_files(["yui/base/base.css"],
99+ root=test_dir)).strip(),
100+ expected)
101+
102+ def test_open_with_custom_encoding(self):
103+ """Reading files with non-ascii characters should be handled properly.
104+
105+ Handle explicit encoding when provided.
106+ """
107+ encoding = 'iso-8859-1'
108+ # include some non-ascii data
109+ data = u"fóöbâr"
110+ content = ('.foo{background-image: url("some/url");'
111+ 'content: "%s";}' % data)
112+ test_dir = self.makeDir()
113+ files = [
114+ self.makeSampleFile(
115+ test_dir,
116+ os.path.join("yui", "base", "base.css"),
117+ content,
118+ encoding=encoding),
119+ ]
120+
121+ expected_content = (
122+ '.foo{background-image: url(yui/base/some/url);'
123+ 'content: "%s";}' % data.encode(encoding))
124+ expected = """
125+ /* yui/base/base.css */
126+ %s
127+ """ % expected_content
128+ self.assertTextEquals(
129+ "".join(combine_files(["yui/base/base.css"],
130+ root=test_dir,
131+ encoding=encoding)).strip(),
132+ expected)
133+
134+
135
136 class WSGIComboTest(ComboTestBase, mocker.MockerTestCase):
137

Subscribers

People subscribed via source and target branches

to all changes: