Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(93)

Side by Side Diff: translate/storage/test_pypo.py

Issue 65: xliff2po & po2xliff should handle context SVN Base: https://translate.svn.sourceforge.net/svnroot/translate/src/trunk/
Patch Set: A more complete patch, supporting CPO and pypo Created 1 year, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 3
4 from translate.storage import test_po 4 from translate.storage import test_po
5 from translate.storage import pypo 5 from translate.storage import pypo
6 from translate.misc.multistring import multistring 6 from translate.misc.multistring import multistring
7 from translate.misc import wStringIO 7 from translate.misc import wStringIO
8 from py.test import raises 8 from py.test import raises
9 9
10 class TestPYPOUnit(test_po.TestPOUnit): 10 class TestPYPOUnit(test_po.TestPOUnit):
11 UnitClass = pypo.pounit 11 UnitClass = pypo.pounit
12 12
13 def test_plurals(self): 13 def test_plurals(self):
14 """Tests that plurals are handled correctly.""" 14 """Tests that plurals are handled correctly."""
15 unit = self.UnitClass("Cow") 15 unit = self.UnitClass("Cow")
16 unit.msgid_plural = ['"Cows"'] 16 unit.msgid_plural = ['"Cows"']
17 assert isinstance(unit.source, multistring) 17 assert isinstance(unit.source, multistring)
18 assert unit.source.strings == ["Cow", "Cows"] 18 assert unit.source.strings == ["Cow", "Cows"]
19 assert unit.source == "Cow" 19 assert unit.source == "Cow"
20 20
21 unit.target = ["Koei", "Koeie"] 21 unit.target = ["Koei", "Koeie"]
22 assert isinstance(unit.target, multistring) 22 assert isinstance(unit.target, multistring)
23 assert unit.target.strings == ["Koei", "Koeie"] 23 assert unit.target.strings == ["Koei", "Koeie"]
24 assert unit.target == "Koei" 24 assert unit.target == "Koei"
25 25
26 unit.target = {0:"Koei", 3:"Koeie"} 26 unit.target = {0:"Koei", 3:"Koeie"}
27 assert isinstance(unit.target, multistring) 27 assert isinstance(unit.target, multistring)
28 assert unit.target.strings == ["Koei", "Koeie"] 28 assert unit.target.strings == ["Koei", "Koeie"]
29 assert unit.target == "Koei" 29 assert unit.target == "Koei"
30 30
31 unit.target = [u"Sk\u00ear", u"Sk\u00eare"] 31 unit.target = [u"Sk\u00ear", u"Sk\u00eare"]
32 assert isinstance(unit.target, multistring) 32 assert isinstance(unit.target, multistring)
33 assert unit.target.strings == [u"Sk\u00ear", u"Sk\u00eare"] 33 assert unit.target.strings == [u"Sk\u00ear", u"Sk\u00eare"]
34 assert unit.target.strings == [u"Sk\u00ear", u"Sk\u00eare"] 34 assert unit.target.strings == [u"Sk\u00ear", u"Sk\u00eare"]
35 assert unit.target == u"Sk\u00ear" 35 assert unit.target == u"Sk\u00ear"
36 36
37 def test_plural_reduction(self): 37 def test_plural_reduction(self):
38 """checks that reducing the number of plurals supplied works""" 38 """checks that reducing the number of plurals supplied works"""
39 unit = self.UnitClass("Tree") 39 unit = self.UnitClass("Tree")
40 unit.msgid_plural = ['"Trees"'] 40 unit.msgid_plural = ['"Trees"']
41 assert isinstance(unit.source, multistring) 41 assert isinstance(unit.source, multistring)
42 assert unit.source.strings == ["Tree", "Trees"] 42 assert unit.source.strings == ["Tree", "Trees"]
43 unit.target = multistring(["Boom", "Bome", "Baie Bome"]) 43 unit.target = multistring(["Boom", "Bome", "Baie Bome"])
44 assert isinstance(unit.source, multistring) 44 assert isinstance(unit.source, multistring)
45 assert unit.target.strings == ["Boom", "Bome", "Baie Bome"] 45 assert unit.target.strings == ["Boom", "Bome", "Baie Bome"]
46 unit.target = multistring(["Boom", "Bome"]) 46 unit.target = multistring(["Boom", "Bome"])
47 assert unit.target.strings == ["Boom", "Bome"] 47 assert unit.target.strings == ["Boom", "Bome"]
48 unit.target = "Boom" 48 unit.target = "Boom"
49 # FIXME: currently assigning the target to the same as the first string won't change anything 49 # FIXME: currently assigning the target to the same as the first string won't change anything
50 # we need to verify that this is the desired behaviour... 50 # we need to verify that this is the desired behaviour...
51 assert unit.target.strings == ["Boom", "Bome"] 51 assert unit.target.strings == ["Boom", "Bome"]
52 unit.target = "Een Boom" 52 unit.target = "Een Boom"
53 assert unit.target.strings == ["Een Boom"] 53 assert unit.target.strings == ["Een Boom"]
54 54
55 def test_notes(self): 55 def test_notes(self):
56 """tests that the generic notes API works""" 56 """tests that the generic notes API works"""
57 unit = self.UnitClass("File") 57 unit = self.UnitClass("File")
58 unit.addnote("Which meaning of file?") 58 unit.addnote("Which meaning of file?")
59 assert str(unit) == '# Which meaning of file?\nmsgid "File"\nmsgstr ""\n ' 59 assert str(unit) == '# Which meaning of file?\nmsgid "File"\nmsgstr ""\n '
60 unit.addnote("Verb", origin="programmer") 60 unit.addnote("Verb", origin="programmer")
61 assert str(unit) == '# Which meaning of file?\n#. Verb\nmsgid "File"\nms gstr ""\n' 61 assert str(unit) == '# Which meaning of file?\n#. Verb\nmsgid "File"\nms gstr ""\n'
62 unit.addnote("Thank you", origin="translator") 62 unit.addnote("Thank you", origin="translator")
63 assert str(unit) == '# Which meaning of file?\n# Thank you\n#. Verb\nmsg id "File"\nmsgstr ""\n' 63 assert str(unit) == '# Which meaning of file?\n# Thank you\n#. Verb\nmsg id "File"\nmsgstr ""\n'
64 64
65 assert unit.getnotes("developer") == "Verb" 65 assert unit.getnotes("developer") == "Verb"
66 assert unit.getnotes("translator") == "Which meaning of file?\nThank you " 66 assert unit.getnotes("translator") == "Which meaning of file?\nThank you "
67 assert unit.getnotes() == "Which meaning of file?\nThank you\nVerb" 67 assert unit.getnotes() == "Which meaning of file?\nThank you\nVerb"
68 assert raises(ValueError, unit.getnotes, "devteam") 68 assert raises(ValueError, unit.getnotes, "devteam")
69 69
70 def test_notes_withcomments(self): 70 def test_notes_withcomments(self):
71 """tests that when we add notes that look like comments that we treat th em properly""" 71 """tests that when we add notes that look like comments that we treat th em properly"""
72 unit = self.UnitClass("File") 72 unit = self.UnitClass("File")
73 unit.addnote("# Double commented comment") 73 unit.addnote("# Double commented comment")
74 assert str(unit) == '# # Double commented comment\nmsgid "File"\nmsgstr ""\n' 74 assert str(unit) == '# # Double commented comment\nmsgid "File"\nmsgstr ""\n'
75 assert unit.getnotes() == "# Double commented comment" 75 assert unit.getnotes() == "# Double commented comment"
76 76
77 def test_wrap_firstlines(self): 77 def test_wrap_firstlines(self):
78 '''tests that we wrap the first line correctly a first line if longer th en 71 chars 78 '''tests that we wrap the first line correctly a first line if longer th en 71 chars
79 as at 71 chars we should align the text on the left and preceed with wit h a msgid ""''' 79 as at 71 chars we should align the text on the left and preceed with wit h a msgid ""'''
80 # longest before we wrap text 80 # longest before we wrap text
81 str_max = "123456789 123456789 123456789 123456789 123456789 123456789 1 23456789 1" 81 str_max = "123456789 123456789 123456789 123456789 123456789 123456789 1 23456789 1"
82 unit = self.UnitClass(str_max) 82 unit = self.UnitClass(str_max)
83 expected = 'msgid "%s"\nmsgstr ""\n' % str_max 83 expected = 'msgid "%s"\nmsgstr ""\n' % str_max
84 print expected, str(unit) 84 print expected, str(unit)
85 assert str(unit) == expected 85 assert str(unit) == expected
86 # at this length we wrap 86 # at this length we wrap
87 str_wrap = str_max + '2' 87 str_wrap = str_max + '2'
88 unit = self.UnitClass(str_wrap) 88 unit = self.UnitClass(str_wrap)
89 expected = 'msgid ""\n"%s"\nmsgstr ""\n' % str_wrap 89 expected = 'msgid ""\n"%s"\nmsgstr ""\n' % str_wrap
90 print expected, str(unit) 90 print expected, str(unit)
91 assert str(unit) == expected 91 assert str(unit) == expected
92 92
93 def test_wrap_on_newlines(self): 93 def test_wrap_on_newlines(self):
94 """test that we wrap newlines on a real \n""" 94 """test that we wrap newlines on a real \n"""
95 string = "123456789\n" * 3 95 string = "123456789\n" * 3
96 postring = ('"123456789\\n"\n' * 3)[:-1] 96 postring = ('"123456789\\n"\n' * 3)[:-1]
97 unit = self.UnitClass(string) 97 unit = self.UnitClass(string)
98 expected = 'msgid ""\n%s\nmsgstr ""\n' % postring 98 expected = 'msgid ""\n%s\nmsgstr ""\n' % postring
99 print expected, str(unit) 99 print expected, str(unit)
100 assert str(unit) == expected 100 assert str(unit) == expected
101 101
102 # Now check for long newlines segments 102 # Now check for long newlines segments
103 longstring = ("123456789 " * 10 + "\n") * 3 103 longstring = ("123456789 " * 10 + "\n") * 3
104 expected = r'''msgid "" 104 expected = r'''msgid ""
105 "123456789 123456789 123456789 123456789 123456789 123456789 123456789 " 105 "123456789 123456789 123456789 123456789 123456789 123456789 123456789 "
106 "123456789 123456789 123456789 \n" 106 "123456789 123456789 123456789 \n"
107 "123456789 123456789 123456789 123456789 123456789 123456789 123456789 " 107 "123456789 123456789 123456789 123456789 123456789 123456789 123456789 "
108 "123456789 123456789 123456789 \n" 108 "123456789 123456789 123456789 \n"
109 "123456789 123456789 123456789 123456789 123456789 123456789 123456789 " 109 "123456789 123456789 123456789 123456789 123456789 123456789 123456789 "
110 "123456789 123456789 123456789 \n" 110 "123456789 123456789 123456789 \n"
111 msgstr "" 111 msgstr ""
112 ''' 112 '''
113 unit = self.UnitClass(longstring) 113 unit = self.UnitClass(longstring)
114 print expected, str(unit) 114 print expected, str(unit)
115 assert str(unit) == expected 115 assert str(unit) == expected
116 116
117 def test_wrap_on_max_line_length(self): 117 def test_wrap_on_max_line_length(self):
118 """test that we wrap all lines on the maximum line length""" 118 """test that we wrap all lines on the maximum line length"""
119 string = "1 3 5 7 N " * 11 119 string = "1 3 5 7 N " * 11
120 expected = 'msgid ""\n%s\nmsgstr ""\n' % '"1 3 5 7 N 1 3 5 7 N 1 3 5 7 N 1 3 5 7 N 1 3 5 7 N 1 3 5 7 N 1 3 5 7 N 1 3 5 "\n"7 N 1 3 5 7 N 1 3 5 7 N 1 3 5 7 N "' 120 expected = 'msgid ""\n%s\nmsgstr ""\n' % '"1 3 5 7 N 1 3 5 7 N 1 3 5 7 N 1 3 5 7 N 1 3 5 7 N 1 3 5 7 N 1 3 5 7 N 1 3 5 "\n"7 N 1 3 5 7 N 1 3 5 7 N 1 3 5 7 N "'
121 unit = self.UnitClass(string) 121 unit = self.UnitClass(string)
122 print "Expected:" 122 print "Expected:"
123 print expected 123 print expected
124 print "Actual:" 124 print "Actual:"
125 print str(unit) 125 print str(unit)
126 assert str(unit) == expected 126 assert str(unit) == expected
127 127
128 def test_spacing_max_line(self): 128 def test_spacing_max_line(self):
129 """Test that the spacing of text is done the same as msgcat.""" 129 """Test that the spacing of text is done the same as msgcat."""
130 idstring = "Creates a new document using an existing template iiiiiiiiii iiiiiiiiiiiii or " 130 idstring = "Creates a new document using an existing template iiiiiiiiii iiiiiiiiiiiii or "
131 idstring += "opens a sample document." 131 idstring += "opens a sample document."
132 expected = '''msgid "" 132 expected = '''msgid ""
133 "Creates a new document using an existing template iiiiiiiiiiiiiiiiiiiiiii or " 133 "Creates a new document using an existing template iiiiiiiiiiiiiiiiiiiiiii or "
134 "opens a sample document." 134 "opens a sample document."
135 msgstr "" 135 msgstr ""
136 ''' 136 '''
137 unit = self.UnitClass(idstring) 137 unit = self.UnitClass(idstring)
138 print "Expected:" 138 print "Expected:"
139 print expected 139 print expected
140 print "Actual:" 140 print "Actual:"
141 print str(unit) 141 print str(unit)
142 assert str(unit) == expected 142 assert str(unit) == expected
143
144 def test_context(self):
145 """test context message"""
146 unit = self.UnitClass("Test")
147 #XXX: getcontext() also returns other comments, this is will not be
148 # tested here
149 assert unit.getcontext() == ''
150
151 unit.setcontext("test context")
152 assert unit.getcontext() == "test context"
153
154 unit.setcontext("")
155 assert unit.getcontext() == ""
156
143 157
144 class TestPYPOFile(test_po.TestPOFile): 158 class TestPYPOFile(test_po.TestPOFile):
145 StoreClass = pypo.pofile 159 StoreClass = pypo.pofile
146 def test_combine_msgidcomments(self): 160 def test_combine_msgidcomments(self):
147 """checks that we don't get duplicate msgid comments""" 161 """checks that we don't get duplicate msgid comments"""
148 posource = 'msgid "test me"\nmsgstr ""' 162 posource = 'msgid "test me"\nmsgstr ""'
149 pofile = self.poparse(posource) 163 pofile = self.poparse(posource)
150 thepo = pofile.units[0] 164 thepo = pofile.units[0]
151 thepo.msgidcomments.append('"_: first comment\\n"') 165 thepo.msgidcomments.append('"_: first comment\\n"')
152 thepo.msgidcomments.append('"_: second comment\\n"') 166 thepo.msgidcomments.append('"_: second comment\\n"')
153 regenposource = str(pofile) 167 regenposource = str(pofile)
154 assert regenposource.count("_:") == 1 168 assert regenposource.count("_:") == 1
155 169
156 def test_merge_duplicates_msgctxt(self): 170 def test_merge_duplicates_msgctxt(self):
157 """checks that merging duplicates works for msgctxt""" 171 """checks that merging duplicates works for msgctxt"""
158 posource = '#: source1\nmsgid "test me"\nmsgstr ""\n\n#: source2\nmsgid "test me"\nmsgstr ""\n' 172 posource = '#: source1\nmsgid "test me"\nmsgstr ""\n\n#: source2\nmsgid "test me"\nmsgstr ""\n'
159 pofile = self.poparse(posource) 173 pofile = self.poparse(posource)
160 assert len(pofile.units) == 2 174 assert len(pofile.units) == 2
161 pofile.removeduplicates("msgctxt") 175 pofile.removeduplicates("msgctxt")
162 print pofile 176 print pofile
163 assert len(pofile.units) == 2 177 assert len(pofile.units) == 2
164 assert str(pofile.units[0]).count("source1") == 2 178 assert str(pofile.units[0]).count("source1") == 2
165 assert str(pofile.units[1]).count("source2") == 2 179 assert str(pofile.units[1]).count("source2") == 2
166 180
167 def test_merge_blanks(self): 181 def test_merge_blanks(self):
168 """checks that merging adds msgid_comments to blanks""" 182 """checks that merging adds msgid_comments to blanks"""
169 posource = '#: source1\nmsgid ""\nmsgstr ""\n\n#: source2\nmsgid ""\nmsg str ""\n' 183 posource = '#: source1\nmsgid ""\nmsgstr ""\n\n#: source2\nmsgid ""\nmsg str ""\n'
170 pofile = self.poparse(posource) 184 pofile = self.poparse(posource)
171 assert len(pofile.units) == 2 185 assert len(pofile.units) == 2
172 pofile.removeduplicates("merge") 186 pofile.removeduplicates("merge")
173 assert len(pofile.units) == 2 187 assert len(pofile.units) == 2
174 print pofile.units[0].msgidcomments 188 print pofile.units[0].msgidcomments
175 print pofile.units[1].msgidcomments 189 print pofile.units[1].msgidcomments
176 assert pypo.unquotefrompo(pofile.units[0].msgidcomments) == "_: source1\ n" 190 assert pypo.unquotefrompo(pofile.units[0].msgidcomments) == "_: source1\ n"
177 assert pypo.unquotefrompo(pofile.units[1].msgidcomments) == "_: source2\ n" 191 assert pypo.unquotefrompo(pofile.units[1].msgidcomments) == "_: source2\ n"
178 192
179 def test_msgid_comment(self): 193 def test_msgid_comment(self):
180 """checks that when adding msgid_comments we place them on a newline""" 194 """checks that when adding msgid_comments we place them on a newline"""
181 posource = '#: source0\nmsgid "Same"\nmsgstr ""\n\n#: source1\nmsgid "Sa me"\nmsgstr ""\n' 195 posource = '#: source0\nmsgid "Same"\nmsgstr ""\n\n#: source1\nmsgid "Sa me"\nmsgstr ""\n'
182 pofile = self.poparse(posource) 196 pofile = self.poparse(posource)
183 assert len(pofile.units) == 2 197 assert len(pofile.units) == 2
184 pofile.removeduplicates("msgid_comment") 198 pofile.removeduplicates("msgid_comment")
185 assert len(pofile.units) == 2 199 assert len(pofile.units) == 2
186 assert pypo.unquotefrompo(pofile.units[0].msgidcomments) == "_: source0\ n" 200 assert pypo.unquotefrompo(pofile.units[0].msgidcomments) == "_: source0\ n"
187 assert pypo.unquotefrompo(pofile.units[1].msgidcomments) == "_: source1\ n" 201 assert pypo.unquotefrompo(pofile.units[1].msgidcomments) == "_: source1\ n"
188 # Now lets check for formating 202 # Now lets check for formating
189 for i in (0, 1): 203 for i in (0, 1):
190 expected = '''#: source%d\nmsgid ""\n"_: source%d\\n"\n"Same"\nmsgst r ""\n''' % (i, i) 204 expected = '''#: source%d\nmsgid ""\n"_: source%d\\n"\n"Same"\nmsgst r ""\n''' % (i, i)
191 assert pofile.units[i].__str__() == expected 205 assert pofile.units[i].__str__() == expected
192 206
193 def test_keep_blanks(self): 207 def test_keep_blanks(self):
194 """checks that keeping keeps blanks and doesn't add msgid_comments""" 208 """checks that keeping keeps blanks and doesn't add msgid_comments"""
195 posource = '#: source1\nmsgid ""\nmsgstr ""\n\n#: source2\nmsgid ""\nmsg str ""\n' 209 posource = '#: source1\nmsgid ""\nmsgstr ""\n\n#: source2\nmsgid ""\nmsg str ""\n'
196 pofile = self.poparse(posource) 210 pofile = self.poparse(posource)
197 assert len(pofile.units) == 2 211 assert len(pofile.units) == 2
198 pofile.removeduplicates("keep") 212 pofile.removeduplicates("keep")
199 assert len(pofile.units) == 2 213 assert len(pofile.units) == 2
200 # check we don't add msgidcomments 214 # check we don't add msgidcomments
201 assert pypo.unquotefrompo(pofile.units[0].msgidcomments) == "" 215 assert pypo.unquotefrompo(pofile.units[0].msgidcomments) == ""
202 assert pypo.unquotefrompo(pofile.units[1].msgidcomments) == "" 216 assert pypo.unquotefrompo(pofile.units[1].msgidcomments) == ""
203 217
204 def test_output_str_unicode(self): 218 def test_output_str_unicode(self):
205 """checks that we can str(element) which is in unicode""" 219 """checks that we can str(element) which is in unicode"""
206 posource = u'''#: nb\nmsgid "Norwegian Bokm\xe5l"\nmsgstr ""\n''' 220 posource = u'''#: nb\nmsgid "Norwegian Bokm\xe5l"\nmsgstr ""\n'''
207 pofile = self.StoreClass(wStringIO.StringIO(posource.encode("UTF-8")), e ncoding="UTF-8") 221 pofile = self.StoreClass(wStringIO.StringIO(posource.encode("UTF-8")), e ncoding="UTF-8")
208 assert len(pofile.units) == 1 222 assert len(pofile.units) == 1
209 print str(pofile) 223 print str(pofile)
210 thepo = pofile.units[0] 224 thepo = pofile.units[0]
211 assert str(thepo) == posource.encode("UTF-8") 225 assert str(thepo) == posource.encode("UTF-8")
212 # extra test: what if we set the msgid to a unicode? this happens in pro p2po etc 226 # extra test: what if we set the msgid to a unicode? this happens in pro p2po etc
213 thepo.source = u"Norwegian Bokm\xe5l" 227 thepo.source = u"Norwegian Bokm\xe5l"
214 assert str(thepo) == posource.encode("UTF-8") 228 assert str(thepo) == posource.encode("UTF-8")
215 # Now if we set the msgstr to Unicode 229 # Now if we set the msgstr to Unicode
216 # this is an escaped half character (1/2) 230 # this is an escaped half character (1/2)
217 halfstr = "\xbd ...".decode("latin-1") 231 halfstr = "\xbd ...".decode("latin-1")
218 thepo.target = halfstr 232 thepo.target = halfstr
219 assert halfstr in str(thepo).decode("UTF-8") 233 assert halfstr in str(thepo).decode("UTF-8")
220 thepo.target = halfstr.encode("UTF-8") 234 thepo.target = halfstr.encode("UTF-8")
221 assert halfstr.encode("UTF-8") in str(thepo) 235 assert halfstr.encode("UTF-8") in str(thepo)
222 236
223 def test_posections(self): 237 def test_posections(self):
224 """checks the content of all the expected sections of a PO message""" 238 """checks the content of all the expected sections of a PO message"""
225 posource = '# other comment\n#. automatic comment\n#: source comment\n#, fuzzy\nmsgid "One"\nmsgstr "Een"\n' 239 posource = '# other comment\n#. automatic comment\n#: source comment\n#, fuzzy\nmsgid "One"\nmsgstr "Een"\n'
226 pofile = self.poparse(posource) 240 pofile = self.poparse(posource)
227 print pofile 241 print pofile
228 assert len(pofile.units) == 1 242 assert len(pofile.units) == 1
229 assert str(pofile) == posource 243 assert str(pofile) == posource
230 assert pofile.units[0].othercomments == ["# other comment\n"] 244 assert pofile.units[0].othercomments == ["# other comment\n"]
231 assert pofile.units[0].automaticcomments == ["#. automatic comment\n"] 245 assert pofile.units[0].automaticcomments == ["#. automatic comment\n"]
232 assert pofile.units[0].sourcecomments == ["#: source comment\n"] 246 assert pofile.units[0].sourcecomments == ["#: source comment\n"]
233 assert pofile.units[0].typecomments == ["#, fuzzy\n"] 247 assert pofile.units[0].typecomments == ["#, fuzzy\n"]
234 248
235 def test_unassociated_comments(self): 249 def test_unassociated_comments(self):
236 """tests behaviour of unassociated comments.""" 250 """tests behaviour of unassociated comments."""
237 oldsource = '# old lonesome comment\n\nmsgid "one"\nmsgstr "een"\n' 251 oldsource = '# old lonesome comment\n\nmsgid "one"\nmsgstr "een"\n'
238 oldfile = self.poparse(oldsource) 252 oldfile = self.poparse(oldsource)
239 print "__str__", str(oldfile) 253 print "__str__", str(oldfile)
240 assert len(oldfile.units) == 2 254 assert len(oldfile.units) == 2
241 assert str(oldfile).find("# old lonesome comment\n\n") >= 0 255 assert str(oldfile).find("# old lonesome comment\n\n") >= 0
242 256
OLDNEW

Powered by Google App Engine
This is Rietveld r159