Merge lp:~lifeless/python-oops-datedir-repo/extraction into lp:python-oops-datedir-repo
- extraction
- Merge into trunk
Proposed by
Robert Collins
Status: | Merged |
---|---|
Merged at revision: | 7 |
Proposed branch: | lp:~lifeless/python-oops-datedir-repo/extraction |
Merge into: | lp:python-oops-datedir-repo |
Diff against target: |
327 lines (+114/-45) 4 files modified
oops_datedir_repo/__init__.py (+1/-1) oops_datedir_repo/serializer_rfc822.py (+43/-33) oops_datedir_repo/tests/test_serializer_rfc822.py (+69/-10) setup.py (+1/-1) |
To merge this branch: | bzr merge lp:~lifeless/python-oops-datedir-repo/extraction |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Steve Kowalik (community) | code | Approve | |
Review via email: mp+71795@code.launchpad.net |
Commit message
Description of the change
This handles the new topic and reporter keys (mapping pageid to topic on in-out for compat with oops-tools (until oops-tools uses this library :P)), and takes more encoding responsibility so that callers can relax a little (given the definition we're aiming at of 'bson serializable is all we need).
To post a comment you must log in.
Revision history for this message
Steve Kowalik (stevenk) : | # |
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'oops_datedir_repo/__init__.py' | |||
2 | --- oops_datedir_repo/__init__.py 2011-08-16 02:21:20 +0000 | |||
3 | +++ oops_datedir_repo/__init__.py 2011-08-17 01:17:24 +0000 | |||
4 | @@ -25,7 +25,7 @@ | |||
5 | 25 | # established at this point, and setup.py will use a version of next-$(revno). | 25 | # established at this point, and setup.py will use a version of next-$(revno). |
6 | 26 | # If the releaselevel is 'final', then the tarball will be major.minor.micro. | 26 | # If the releaselevel is 'final', then the tarball will be major.minor.micro. |
7 | 27 | # Otherwise it is major.minor.micro~$(revno). | 27 | # Otherwise it is major.minor.micro~$(revno). |
9 | 28 | __version__ = (0, 0, 2, 'beta', 0) | 28 | __version__ = (0, 0, 3, 'beta', 0) |
10 | 29 | 29 | ||
11 | 30 | __all__ = [ | 30 | __all__ = [ |
12 | 31 | 'DateDirRepo', | 31 | 'DateDirRepo', |
13 | 32 | 32 | ||
14 | === modified file 'oops_datedir_repo/serializer_rfc822.py' | |||
15 | --- oops_datedir_repo/serializer_rfc822.py 2011-08-15 05:30:39 +0000 | |||
16 | +++ oops_datedir_repo/serializer_rfc822.py 2011-08-17 01:17:24 +0000 | |||
17 | @@ -19,13 +19,16 @@ | |||
18 | 19 | This style of OOPS format is very web server specific, not extensible - it | 19 | This style of OOPS format is very web server specific, not extensible - it |
19 | 20 | should be considered deprecated. | 20 | should be considered deprecated. |
20 | 21 | 21 | ||
22 | 22 | The reports this serializer handles always have the following variables: | 22 | The reports this serializer handles always have the following variables (See |
23 | 23 | the python-oops api docs for more information about these variables): | ||
24 | 23 | 24 | ||
25 | 24 | * id: The name of this error report. | 25 | * id: The name of this error report. |
26 | 25 | * type: The type of the exception that occurred. | 26 | * type: The type of the exception that occurred. |
27 | 26 | * value: The value of the exception that occurred. | 27 | * value: The value of the exception that occurred. |
28 | 27 | * time: The time at which the exception occurred. | 28 | * time: The time at which the exception occurred. |
30 | 28 | * pageid: The identifier for the template/script that oopsed. | 29 | * reporter: The reporting program. |
31 | 30 | * topic: The identifier for the template/script that oopsed. | ||
32 | 31 | [this is written as Page-Id for compatibility with as yet unported tools.] | ||
33 | 29 | * branch_nick: The branch nickname. | 32 | * branch_nick: The branch nickname. |
34 | 30 | * revno: The revision number of the branch. | 33 | * revno: The revision number of the branch. |
35 | 31 | * tb_text: A text version of the traceback. | 34 | * tb_text: A text version of the traceback. |
36 | @@ -37,6 +40,9 @@ | |||
37 | 37 | * revno: The revision that the branch was at. | 40 | * revno: The revision that the branch was at. |
38 | 38 | * Informational: A flag, True if the error wasn't fatal- if it was | 41 | * Informational: A flag, True if the error wasn't fatal- if it was |
39 | 39 | 'informational'. | 42 | 'informational'. |
40 | 43 | [Deprecated - this is no longer part of the oops report conventions. Existing | ||
41 | 44 | reports with it set are still read, but the key is only present if it was | ||
42 | 45 | truely in the report.] | ||
43 | 40 | """ | 46 | """ |
44 | 41 | 47 | ||
45 | 42 | 48 | ||
46 | @@ -67,13 +73,16 @@ | |||
47 | 67 | date =iso8601.parse_date(msg.getheader('date')) | 73 | date =iso8601.parse_date(msg.getheader('date')) |
48 | 68 | else: | 74 | else: |
49 | 69 | date = None | 75 | date = None |
51 | 70 | pageid = msg.getheader('page-id') | 76 | topic = msg.getheader('topic') |
52 | 77 | if topic is None: | ||
53 | 78 | topic = msg.getheader('page-id') | ||
54 | 71 | username = msg.getheader('user') | 79 | username = msg.getheader('user') |
55 | 72 | url = msg.getheader('url') | 80 | url = msg.getheader('url') |
56 | 73 | duration = int(float(msg.getheader('duration', '-1'))) | 81 | duration = int(float(msg.getheader('duration', '-1'))) |
57 | 74 | informational = msg.getheader('informational') | 82 | informational = msg.getheader('informational') |
58 | 75 | branch_nick = msg.getheader('branch') | 83 | branch_nick = msg.getheader('branch') |
59 | 76 | revno = msg.getheader('revision') | 84 | revno = msg.getheader('revision') |
60 | 85 | reporter = msg.getheader('oops-reporter') | ||
61 | 77 | 86 | ||
62 | 78 | # Explicitly use an iterator so we can process the file | 87 | # Explicitly use an iterator so we can process the file |
63 | 79 | # sequentially. In most instances the iterator will actually | 88 | # sequentially. In most instances the iterator will actually |
64 | @@ -109,10 +118,15 @@ | |||
65 | 109 | # The rest is traceback. | 118 | # The rest is traceback. |
66 | 110 | tb_text = ''.join(lines) | 119 | tb_text = ''.join(lines) |
67 | 111 | 120 | ||
70 | 112 | return dict(id=id, type=exc_type, value=exc_value, time=date, | 121 | result = dict(id=id, type=exc_type, value=exc_value, time=date, |
71 | 113 | pageid=pageid, tb_text=tb_text, username=username, url=url, | 122 | topic=topic, tb_text=tb_text, username=username, url=url, |
72 | 114 | duration=duration, req_vars=req_vars, db_statements=statements, | 123 | duration=duration, req_vars=req_vars, db_statements=statements, |
74 | 115 | informational=informational, branch_nick=branch_nick, revno=revno) | 124 | branch_nick=branch_nick, revno=revno) |
75 | 125 | if informational is not None: | ||
76 | 126 | result['informational'] = informational | ||
77 | 127 | if reporter is not None: | ||
78 | 128 | result['reporter'] = reporter | ||
79 | 129 | return result | ||
80 | 116 | 130 | ||
81 | 117 | 131 | ||
82 | 118 | def _normalise_whitespace(s): | 132 | def _normalise_whitespace(s): |
83 | @@ -151,45 +165,41 @@ | |||
84 | 151 | def to_chunks(report): | 165 | def to_chunks(report): |
85 | 152 | """Returns a list of bytestrings making up the serialized oops.""" | 166 | """Returns a list of bytestrings making up the serialized oops.""" |
86 | 153 | chunks = [] | 167 | chunks = [] |
94 | 154 | chunks.append('Oops-Id: %s\n' % _normalise_whitespace(report['id'])) | 168 | def header(label, key, optional=True): |
95 | 155 | if 'type' in report: | 169 | if optional and key not in report: |
96 | 156 | chunks.append( | 170 | return |
97 | 157 | 'Exception-Type: %s\n' % _normalise_whitespace(report['type'])) | 171 | value = _safestr(report[key]) |
98 | 158 | if 'value' in report: | 172 | value = _normalise_whitespace(value) |
99 | 159 | chunks.append( | 173 | chunks.append('%s: %s\n' % (label, value)) |
100 | 160 | 'Exception-Value: %s\n' % _normalise_whitespace(report['value'])) | 174 | header('Oops-Id', 'id', optional=False) |
101 | 175 | header('Exception-Type', 'type') | ||
102 | 176 | header('Exception-Value', 'value') | ||
103 | 161 | if 'time' in report: | 177 | if 'time' in report: |
104 | 162 | chunks.append('Date: %s\n' % report['time'].isoformat()) | 178 | chunks.append('Date: %s\n' % report['time'].isoformat()) |
121 | 163 | if 'pageid' in report: | 179 | header('Page-Id', 'topic') |
122 | 164 | chunks.append( | 180 | header('Branch', 'branch_nick') |
123 | 165 | 'Page-Id: %s\n' % _normalise_whitespace(report['pageid'])) | 181 | header('Revision', 'revno') |
124 | 166 | if 'branch_nick' in report: | 182 | header('User', 'username') |
125 | 167 | chunks.append('Branch: %s\n' % _safestr(report['branch_nick'])) | 183 | header('URL', 'url') |
126 | 168 | if 'revno' in report: | 184 | header('Duration', 'duration') |
127 | 169 | chunks.append('Revision: %s\n' % report['revno']) | 185 | header('Informational', 'informational') |
128 | 170 | if 'username' in report: | 186 | header('Oops-Reporter', 'reporter') |
113 | 171 | chunks.append( | ||
114 | 172 | 'User: %s\n' % _normalise_whitespace(report['username'])) | ||
115 | 173 | if 'url' in report: | ||
116 | 174 | chunks.append('URL: %s\n' % _normalise_whitespace(report['url'])) | ||
117 | 175 | if 'duration' in report: | ||
118 | 176 | chunks.append('Duration: %s\n' % report['duration']) | ||
119 | 177 | if 'informational' in report: | ||
120 | 178 | chunks.append('Informational: %s\n' % report['informational']) | ||
129 | 179 | chunks.append('\n') | 187 | chunks.append('\n') |
130 | 180 | safe_chars = ';/\\?:@&+$, ()*!' | 188 | safe_chars = ';/\\?:@&+$, ()*!' |
131 | 181 | if 'req_vars' in report: | 189 | if 'req_vars' in report: |
132 | 182 | for key, value in report['req_vars']: | 190 | for key, value in report['req_vars']: |
135 | 183 | chunks.append('%s=%s\n' % (urllib.quote(key, safe_chars), | 191 | chunks.append('%s=%s\n' % ( |
136 | 184 | urllib.quote(value, safe_chars))) | 192 | urllib.quote(_safestr(key), safe_chars), |
137 | 193 | urllib.quote(_safestr(value), safe_chars))) | ||
138 | 185 | chunks.append('\n') | 194 | chunks.append('\n') |
139 | 186 | if 'db_statements' in report: | 195 | if 'db_statements' in report: |
140 | 187 | for (start, end, database_id, statement) in report['db_statements']: | 196 | for (start, end, database_id, statement) in report['db_statements']: |
141 | 188 | chunks.append('%05d-%05d@%s %s\n' % ( | 197 | chunks.append('%05d-%05d@%s %s\n' % ( |
143 | 189 | start, end, database_id, _normalise_whitespace(statement))) | 198 | start, end, _safestr(database_id), |
144 | 199 | _safestr(_normalise_whitespace(statement)))) | ||
145 | 190 | chunks.append('\n') | 200 | chunks.append('\n') |
146 | 191 | if 'tb_text' in report: | 201 | if 'tb_text' in report: |
148 | 192 | chunks.append(report['tb_text']) | 202 | chunks.append(_safestr(report['tb_text'])) |
149 | 193 | return chunks | 203 | return chunks |
150 | 194 | 204 | ||
151 | 195 | 205 | ||
152 | 196 | 206 | ||
153 | === modified file 'oops_datedir_repo/tests/test_serializer_rfc822.py' | |||
154 | --- oops_datedir_repo/tests/test_serializer_rfc822.py 2011-08-15 05:30:39 +0000 | |||
155 | +++ oops_datedir_repo/tests/test_serializer_rfc822.py 2011-08-17 01:17:24 +0000 | |||
156 | @@ -41,7 +41,7 @@ | |||
157 | 41 | Exception-Type: NotFound | 41 | Exception-Type: NotFound |
158 | 42 | Exception-Value: error message | 42 | Exception-Value: error message |
159 | 43 | Date: 2005-04-01T00:00:00+00:00 | 43 | Date: 2005-04-01T00:00:00+00:00 |
161 | 44 | Page-Id: IFoo:+foo-template | 44 | Topic: IFoo:+foo-template |
162 | 45 | User: Sample User | 45 | User: Sample User |
163 | 46 | URL: http://localhost:9000/foo | 46 | URL: http://localhost:9000/foo |
164 | 47 | Duration: 42 | 47 | Duration: 42 |
165 | @@ -60,7 +60,7 @@ | |||
166 | 60 | self.assertEqual(report['value'], 'error message') | 60 | self.assertEqual(report['value'], 'error message') |
167 | 61 | self.assertEqual( | 61 | self.assertEqual( |
168 | 62 | report['time'], datetime.datetime(2005, 4, 1, tzinfo=utc)) | 62 | report['time'], datetime.datetime(2005, 4, 1, tzinfo=utc)) |
170 | 63 | self.assertEqual(report['pageid'], 'IFoo:+foo-template') | 63 | self.assertEqual(report['topic'], 'IFoo:+foo-template') |
171 | 64 | self.assertEqual(report['tb_text'], 'traceback-text') | 64 | self.assertEqual(report['tb_text'], 'traceback-text') |
172 | 65 | self.assertEqual(report['username'], 'Sample User') | 65 | self.assertEqual(report['username'], 'Sample User') |
173 | 66 | self.assertEqual(report['url'], 'http://localhost:9000/foo') | 66 | self.assertEqual(report['url'], 'http://localhost:9000/foo') |
174 | @@ -86,7 +86,7 @@ | |||
175 | 86 | Exception-Type: NotFound | 86 | Exception-Type: NotFound |
176 | 87 | Exception-Value: error message | 87 | Exception-Value: error message |
177 | 88 | Date: 2005-04-01T00:00:00+00:00 | 88 | Date: 2005-04-01T00:00:00+00:00 |
179 | 89 | Page-Id: IFoo:+foo-template | 89 | Topic: IFoo:+foo-template |
180 | 90 | User: Sample User | 90 | User: Sample User |
181 | 91 | URL: http://localhost:9000/foo | 91 | URL: http://localhost:9000/foo |
182 | 92 | Duration: 42 | 92 | Duration: 42 |
183 | @@ -105,7 +105,7 @@ | |||
184 | 105 | self.assertEqual(report['value'], 'error message') | 105 | self.assertEqual(report['value'], 'error message') |
185 | 106 | self.assertEqual( | 106 | self.assertEqual( |
186 | 107 | report['time'], datetime.datetime(2005, 4, 1, tzinfo=utc)) | 107 | report['time'], datetime.datetime(2005, 4, 1, tzinfo=utc)) |
188 | 108 | self.assertEqual(report['pageid'], 'IFoo:+foo-template') | 108 | self.assertEqual(report['topic'], 'IFoo:+foo-template') |
189 | 109 | self.assertEqual(report['tb_text'], 'traceback-text') | 109 | self.assertEqual(report['tb_text'], 'traceback-text') |
190 | 110 | self.assertEqual(report['username'], 'Sample User') | 110 | self.assertEqual(report['username'], 'Sample User') |
191 | 111 | self.assertEqual(report['url'], 'http://localhost:9000/foo') | 111 | self.assertEqual(report['url'], 'http://localhost:9000/foo') |
192 | @@ -119,7 +119,6 @@ | |||
193 | 119 | self.assertEqual(len(report['db_statements']), 2) | 119 | self.assertEqual(len(report['db_statements']), 2) |
194 | 120 | self.assertEqual(report['db_statements'][0], (1, 5, None, 'SELECT 1')) | 120 | self.assertEqual(report['db_statements'][0], (1, 5, None, 'SELECT 1')) |
195 | 121 | self.assertEqual(report['db_statements'][1], (5, 10, None, 'SELECT 2')) | 121 | self.assertEqual(report['db_statements'][1], (5, 10, None, 'SELECT 2')) |
196 | 122 | self.assertFalse(report['informational']) | ||
197 | 123 | 122 | ||
198 | 124 | def test_read_branch_nick_revno(self): | 123 | def test_read_branch_nick_revno(self): |
199 | 125 | """Test ErrorReport.read().""" | 124 | """Test ErrorReport.read().""" |
200 | @@ -128,7 +127,6 @@ | |||
201 | 128 | Exception-Type: NotFound | 127 | Exception-Type: NotFound |
202 | 129 | Exception-Value: error message | 128 | Exception-Value: error message |
203 | 130 | Date: 2005-04-01T00:00:00+00:00 | 129 | Date: 2005-04-01T00:00:00+00:00 |
204 | 131 | Page-Id: IFoo:+foo-template | ||
205 | 132 | User: Sample User | 130 | User: Sample User |
206 | 133 | URL: http://localhost:9000/foo | 131 | URL: http://localhost:9000/foo |
207 | 134 | Duration: 42 | 132 | Duration: 42 |
208 | @@ -147,6 +145,45 @@ | |||
209 | 147 | self.assertEqual(report['branch_nick'], 'mybranch') | 145 | self.assertEqual(report['branch_nick'], 'mybranch') |
210 | 148 | self.assertEqual(report['revno'], '45') | 146 | self.assertEqual(report['revno'], '45') |
211 | 149 | 147 | ||
212 | 148 | def test_read_reporter(self): | ||
213 | 149 | """Test ErrorReport.read().""" | ||
214 | 150 | fp = StringIO.StringIO(dedent("""\ | ||
215 | 151 | Oops-Id: OOPS-A0001 | ||
216 | 152 | Oops-Reporter: foo/bar | ||
217 | 153 | |||
218 | 154 | """)) | ||
219 | 155 | report = read(fp) | ||
220 | 156 | self.assertEqual(report['reporter'], 'foo/bar') | ||
221 | 157 | |||
222 | 158 | def test_read_pageid_to_topic(self): | ||
223 | 159 | """Test ErrorReport.read().""" | ||
224 | 160 | fp = StringIO.StringIO(dedent("""\ | ||
225 | 161 | Oops-Id: OOPS-A0001 | ||
226 | 162 | Page-Id: IFoo:+foo-template | ||
227 | 163 | |||
228 | 164 | """)) | ||
229 | 165 | report = read(fp) | ||
230 | 166 | self.assertEqual(report['topic'], 'IFoo:+foo-template') | ||
231 | 167 | |||
232 | 168 | def test_read_informational_read(self): | ||
233 | 169 | """Test ErrorReport.read().""" | ||
234 | 170 | fp = StringIO.StringIO(dedent("""\ | ||
235 | 171 | Oops-Id: OOPS-A0001 | ||
236 | 172 | Informational: True | ||
237 | 173 | |||
238 | 174 | """)) | ||
239 | 175 | report = read(fp) | ||
240 | 176 | self.assertEqual('True', report['informational']) | ||
241 | 177 | |||
242 | 178 | def test_read_no_informational_no_key(self): | ||
243 | 179 | """Test ErrorReport.read().""" | ||
244 | 180 | fp = StringIO.StringIO(dedent("""\ | ||
245 | 181 | Oops-Id: OOPS-A0001 | ||
246 | 182 | |||
247 | 183 | """)) | ||
248 | 184 | report = read(fp) | ||
249 | 185 | self.assertFalse('informational' in report) | ||
250 | 186 | |||
251 | 150 | def test_minimal_oops(self): | 187 | def test_minimal_oops(self): |
252 | 151 | # If we get a crazy-small oops, we can read it sensibly. Because there | 188 | # If we get a crazy-small oops, we can read it sensibly. Because there |
253 | 152 | # is existing legacy code, all keys are filled in with None, [] rather | 189 | # is existing legacy code, all keys are filled in with None, [] rather |
254 | @@ -159,14 +196,13 @@ | |||
255 | 159 | self.assertEqual(report['type'], None) | 196 | self.assertEqual(report['type'], None) |
256 | 160 | self.assertEqual(report['value'], None) | 197 | self.assertEqual(report['value'], None) |
257 | 161 | self.assertEqual(report['time'], None) | 198 | self.assertEqual(report['time'], None) |
259 | 162 | self.assertEqual(report['pageid'], None) | 199 | self.assertEqual(report['topic'], None) |
260 | 163 | self.assertEqual(report['tb_text'], '') | 200 | self.assertEqual(report['tb_text'], '') |
261 | 164 | self.assertEqual(report['username'], None) | 201 | self.assertEqual(report['username'], None) |
262 | 165 | self.assertEqual(report['url'], None) | 202 | self.assertEqual(report['url'], None) |
263 | 166 | self.assertEqual(report['duration'], -1) | 203 | self.assertEqual(report['duration'], -1) |
264 | 167 | self.assertEqual(len(report['req_vars']), 0) | 204 | self.assertEqual(len(report['req_vars']), 0) |
265 | 168 | self.assertEqual(len(report['db_statements']), 0) | 205 | self.assertEqual(len(report['db_statements']), 0) |
266 | 169 | self.assertFalse(report['informational']) | ||
267 | 170 | self.assertEqual(report['branch_nick'], None) | 206 | self.assertEqual(report['branch_nick'], None) |
268 | 171 | self.assertEqual(report['revno'], None) | 207 | self.assertEqual(report['revno'], None) |
269 | 172 | 208 | ||
270 | @@ -180,7 +216,7 @@ | |||
271 | 180 | 'type': 'NotFound', | 216 | 'type': 'NotFound', |
272 | 181 | 'value': 'error message', | 217 | 'value': 'error message', |
273 | 182 | 'time': datetime.datetime(2005, 04, 01, 00, 00, 00, tzinfo=utc), | 218 | 'time': datetime.datetime(2005, 04, 01, 00, 00, 00, tzinfo=utc), |
275 | 183 | 'pageid': 'IFoo:+foo-template', | 219 | 'topic': 'IFoo:+foo-template', |
276 | 184 | 'tb_text': 'traceback-text', | 220 | 'tb_text': 'traceback-text', |
277 | 185 | 'username': 'Sample User', | 221 | 'username': 'Sample User', |
278 | 186 | 'url': 'http://localhost:9000/foo', | 222 | 'url': 'http://localhost:9000/foo', |
279 | @@ -223,7 +259,7 @@ | |||
280 | 223 | 'type': 'NotFound', | 259 | 'type': 'NotFound', |
281 | 224 | 'value': 'error message', | 260 | 'value': 'error message', |
282 | 225 | 'time': datetime.datetime(2005, 04, 01, 00, 00, 00, tzinfo=utc), | 261 | 'time': datetime.datetime(2005, 04, 01, 00, 00, 00, tzinfo=utc), |
284 | 226 | 'pageid': 'IFoo:+foo-template', | 262 | 'topic': 'IFoo:+foo-template', |
285 | 227 | 'tb_text': 'traceback-text', | 263 | 'tb_text': 'traceback-text', |
286 | 228 | 'username': 'Sample User', | 264 | 'username': 'Sample User', |
287 | 229 | 'url': 'http://localhost:9000/foo', | 265 | 'url': 'http://localhost:9000/foo', |
288 | @@ -269,3 +305,26 @@ | |||
289 | 269 | "Oops-Id: OOPS-1234\n", | 305 | "Oops-Id: OOPS-1234\n", |
290 | 270 | "\n" | 306 | "\n" |
291 | 271 | ], to_chunks(report)) | 307 | ], to_chunks(report)) |
292 | 308 | |||
293 | 309 | def test_reporter(self): | ||
294 | 310 | report = {'reporter': 'foo', 'id': 'bar'} | ||
295 | 311 | self.assertEqual([ | ||
296 | 312 | "Oops-Id: bar\n", | ||
297 | 313 | "Oops-Reporter: foo\n", | ||
298 | 314 | "\n", | ||
299 | 315 | ], to_chunks(report)) | ||
300 | 316 | |||
301 | 317 | def test_bad_strings(self): | ||
302 | 318 | # Because of the rfc822 limitations, not all strings can be supported | ||
303 | 319 | # in this format - particularly in headers... so all header strings are | ||
304 | 320 | # passed through an escape process. | ||
305 | 321 | report = {'id': u'\xeafoo'} | ||
306 | 322 | self.assertEqual([ | ||
307 | 323 | "Oops-Id: \\xeafoo\n", | ||
308 | 324 | "\n", | ||
309 | 325 | ], to_chunks(report)) | ||
310 | 326 | report = {'id': '\xeafoo'} | ||
311 | 327 | self.assertEqual([ | ||
312 | 328 | "Oops-Id: \\xeafoo\n", | ||
313 | 329 | "\n", | ||
314 | 330 | ], to_chunks(report)) | ||
315 | 272 | 331 | ||
316 | === modified file 'setup.py' | |||
317 | --- setup.py 2011-08-16 02:21:20 +0000 | |||
318 | +++ setup.py 2011-08-17 01:17:24 +0000 | |||
319 | @@ -22,7 +22,7 @@ | |||
320 | 22 | description = file(os.path.join(os.path.dirname(__file__), 'README'), 'rb').read() | 22 | description = file(os.path.join(os.path.dirname(__file__), 'README'), 'rb').read() |
321 | 23 | 23 | ||
322 | 24 | setup(name="oops_datedir_repo", | 24 | setup(name="oops_datedir_repo", |
324 | 25 | version="0.0.2", | 25 | version="0.0.3", |
325 | 26 | description="OOPS disk serialisation and repository management.", | 26 | description="OOPS disk serialisation and repository management.", |
326 | 27 | long_description=description, | 27 | long_description=description, |
327 | 28 | maintainer="Launchpad Developers", | 28 | maintainer="Launchpad Developers", |