Merge lp:~wgrant/launchpad/refactor-nuf-creation into lp:launchpad
- refactor-nuf-creation
- Merge into devel
Proposed by
William Grant
Status: | Merged |
---|---|
Approved by: | Jelmer Vernooij |
Approved revision: | no longer in the source branch. |
Merged at revision: | 11275 |
Proposed branch: | lp:~wgrant/launchpad/refactor-nuf-creation |
Merge into: | lp:launchpad |
Diff against target: |
315 lines (+124/-53) 4 files modified
lib/lp/archiveuploader/changesfile.py (+58/-47) lib/lp/archiveuploader/tests/test_changesfile.py (+54/-0) lib/lp/archiveuploader/tests/test_utils.py (+5/-0) lib/lp/archiveuploader/utils.py (+7/-6) |
To merge this branch: | bzr merge lp:~wgrant/launchpad/refactor-nuf-creation |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jelmer Vernooij (community) | code | Approve | |
Review via email: mp+30851@code.launchpad.net |
Commit message
Factor out and test part of ChangesFile.
Description of the change
This branch factors out and tests part of ChangesFile.
To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) : | # |
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/archiveuploader/changesfile.py' | |||
2 | --- lib/lp/archiveuploader/changesfile.py 2009-10-12 09:55:31 +0000 | |||
3 | +++ lib/lp/archiveuploader/changesfile.py 2010-08-01 07:06:04 +0000 | |||
4 | @@ -10,21 +10,30 @@ | |||
5 | 10 | __metaclass__ = type | 10 | __metaclass__ = type |
6 | 11 | 11 | ||
7 | 12 | __all__ = [ | 12 | __all__ = [ |
9 | 13 | 'ChangesFile' | 13 | 'CannotDetermineFileTypeError', |
10 | 14 | 'ChangesFile', | ||
11 | 15 | 'determine_file_class_and_name', | ||
12 | 14 | ] | 16 | ] |
13 | 15 | 17 | ||
14 | 16 | import os | 18 | import os |
15 | 17 | 19 | ||
16 | 18 | from lp.archiveuploader.dscfile import DSCFile, SignableTagFile | 20 | from lp.archiveuploader.dscfile import DSCFile, SignableTagFile |
17 | 19 | from lp.archiveuploader.nascentuploadfile import ( | 21 | from lp.archiveuploader.nascentuploadfile import ( |
19 | 20 | BaseBinaryUploadFile, CustomUploadFile, DdebBinaryUploadFile, | 22 | BaseBinaryUploadFile, CustomUploadFile, DdebBinaryUploadFile, |
20 | 21 | DebBinaryUploadFile, SourceUploadFile, UdebBinaryUploadFile, | 23 | DebBinaryUploadFile, SourceUploadFile, UdebBinaryUploadFile, |
21 | 22 | UploadError, UploadWarning, splitComponentAndSection) | 24 | UploadError, UploadWarning, splitComponentAndSection) |
22 | 23 | from lp.archiveuploader.utils import ( | 25 | from lp.archiveuploader.utils import ( |
23 | 26 | determine_binary_file_type, determine_source_file_type, | ||
24 | 24 | re_isadeb, re_issource, re_changes_file_name) | 27 | re_isadeb, re_issource, re_changes_file_name) |
25 | 25 | from lp.archiveuploader.tagfiles import ( | 28 | from lp.archiveuploader.tagfiles import ( |
26 | 26 | parse_tagfile, TagFileParseError) | 29 | parse_tagfile, TagFileParseError) |
28 | 27 | from canonical.launchpad.interfaces import SourcePackageUrgency | 30 | from lp.registry.interfaces.sourcepackage import (SourcePackageFileType, |
29 | 31 | SourcePackageUrgency) | ||
30 | 32 | from lp.soyuz.interfaces.binarypackagerelease import BinaryPackageFileType | ||
31 | 33 | |||
32 | 34 | |||
33 | 35 | class CannotDetermineFileTypeError(Exception): | ||
34 | 36 | """The type of the given file could not be determined.""" | ||
35 | 28 | 37 | ||
36 | 29 | 38 | ||
37 | 30 | class ChangesFile(SignableTagFile): | 39 | class ChangesFile(SignableTagFile): |
38 | @@ -42,7 +51,7 @@ | |||
39 | 42 | "medium": SourcePackageUrgency.MEDIUM, | 51 | "medium": SourcePackageUrgency.MEDIUM, |
40 | 43 | "high": SourcePackageUrgency.HIGH, | 52 | "high": SourcePackageUrgency.HIGH, |
41 | 44 | "critical": SourcePackageUrgency.EMERGENCY, | 53 | "critical": SourcePackageUrgency.EMERGENCY, |
43 | 45 | "emergency": SourcePackageUrgency.EMERGENCY | 54 | "emergency": SourcePackageUrgency.EMERGENCY, |
44 | 46 | } | 55 | } |
45 | 47 | 56 | ||
46 | 48 | dsc = None | 57 | dsc = None |
47 | @@ -103,7 +112,7 @@ | |||
48 | 103 | 112 | ||
49 | 104 | def checkFileName(self): | 113 | def checkFileName(self): |
50 | 105 | """Make sure the changes file name is well-formed. | 114 | """Make sure the changes file name is well-formed. |
52 | 106 | 115 | ||
53 | 107 | Please note: for well-formed changes file names the `filename_archtag` | 116 | Please note: for well-formed changes file names the `filename_archtag` |
54 | 108 | property will be set appropriately. | 117 | property will be set appropriately. |
55 | 109 | """ | 118 | """ |
56 | @@ -152,8 +161,9 @@ | |||
57 | 152 | def processFiles(self): | 161 | def processFiles(self): |
58 | 153 | """Build objects for each file mentioned in this changesfile. | 162 | """Build objects for each file mentioned in this changesfile. |
59 | 154 | 163 | ||
62 | 155 | This method is an error generator, i.e, it returns an iterator over all | 164 | This method is an error generator, i.e, it returns an iterator over |
63 | 156 | exceptions that are generated while processing all mentioned files. | 165 | all exceptions that are generated while processing all mentioned |
64 | 166 | files. | ||
65 | 157 | """ | 167 | """ |
66 | 158 | files = [] | 168 | files = [] |
67 | 159 | for fileline in self._dict['files'].strip().split("\n"): | 169 | for fileline in self._dict['files'].strip().split("\n"): |
68 | @@ -161,8 +171,6 @@ | |||
69 | 161 | # CHECKSUM SIZE [COMPONENT/]SECTION PRIORITY FILENAME | 171 | # CHECKSUM SIZE [COMPONENT/]SECTION PRIORITY FILENAME |
70 | 162 | digest, size, component_and_section, priority_name, filename = ( | 172 | digest, size, component_and_section, priority_name, filename = ( |
71 | 163 | fileline.strip().split()) | 173 | fileline.strip().split()) |
72 | 164 | source_match = re_issource.match(filename) | ||
73 | 165 | binary_match = re_isadeb.match(filename) | ||
74 | 166 | filepath = os.path.join(self.dirname, filename) | 174 | filepath = os.path.join(self.dirname, filename) |
75 | 167 | try: | 175 | try: |
76 | 168 | if self.isCustom(component_and_section): | 176 | if self.isCustom(component_and_section): |
77 | @@ -172,42 +180,22 @@ | |||
78 | 172 | file_instance = CustomUploadFile( | 180 | file_instance = CustomUploadFile( |
79 | 173 | filepath, digest, size, component_and_section, | 181 | filepath, digest, size, component_and_section, |
80 | 174 | priority_name, self.policy, self.logger) | 182 | priority_name, self.policy, self.logger) |
89 | 175 | elif source_match: | 183 | else: |
90 | 176 | package = source_match.group(1) | 184 | try: |
91 | 177 | if filename.endswith("dsc"): | 185 | package, cls = determine_file_class_and_name(filename) |
92 | 178 | file_instance = DSCFile( | 186 | except CannotDetermineFileTypeError: |
93 | 179 | filepath, digest, size, component_and_section, | 187 | yield UploadError( |
94 | 180 | priority_name, package, self.version, self, | 188 | "Unable to identify file %s (%s) in changes." |
95 | 181 | self.policy, self.logger) | 189 | % (filename, component_and_section)) |
96 | 182 | # Store the DSC because it is very convenient | 190 | continue |
97 | 191 | |||
98 | 192 | file_instance = cls( | ||
99 | 193 | filepath, digest, size, component_and_section, | ||
100 | 194 | priority_name, package, self.version, self, | ||
101 | 195 | self.policy, self.logger) | ||
102 | 196 | |||
103 | 197 | if cls == DSCFile: | ||
104 | 183 | self.dsc = file_instance | 198 | self.dsc = file_instance |
105 | 184 | else: | ||
106 | 185 | file_instance = SourceUploadFile( | ||
107 | 186 | filepath, digest, size, component_and_section, | ||
108 | 187 | priority_name, package, self.version, self, | ||
109 | 188 | self.policy, self.logger) | ||
110 | 189 | elif binary_match: | ||
111 | 190 | package = binary_match.group(1) | ||
112 | 191 | if filename.endswith("udeb"): | ||
113 | 192 | file_instance = UdebBinaryUploadFile( | ||
114 | 193 | filepath, digest, size, component_and_section, | ||
115 | 194 | priority_name, package, self.version, self, | ||
116 | 195 | self.policy, self.logger) | ||
117 | 196 | elif filename.endswith("ddeb"): | ||
118 | 197 | file_instance = DdebBinaryUploadFile( | ||
119 | 198 | filepath, digest, size, component_and_section, | ||
120 | 199 | priority_name, package, self.version, self, | ||
121 | 200 | self.policy, self.logger) | ||
122 | 201 | else: | ||
123 | 202 | file_instance = DebBinaryUploadFile( | ||
124 | 203 | filepath, digest, size, component_and_section, | ||
125 | 204 | priority_name, package, self.version, self, | ||
126 | 205 | self.policy, self.logger) | ||
127 | 206 | else: | ||
128 | 207 | yield UploadError( | ||
129 | 208 | "Unable to identify file %s (%s) in changes." | ||
130 | 209 | % (filename, component_and_section)) | ||
131 | 210 | continue | ||
132 | 211 | except UploadError, error: | 199 | except UploadError, error: |
133 | 212 | yield error | 200 | yield error |
134 | 213 | else: | 201 | else: |
135 | @@ -218,8 +206,8 @@ | |||
136 | 218 | def verify(self): | 206 | def verify(self): |
137 | 219 | """Run all the verification checks on the changes data. | 207 | """Run all the verification checks on the changes data. |
138 | 220 | 208 | ||
141 | 221 | This method is an error generator, i.e, it returns an iterator over all | 209 | This method is an error generator, i.e, it returns an iterator over |
142 | 222 | exceptions that are generated while verifying the changesfile | 210 | all exceptions that are generated while verifying the changesfile |
143 | 223 | consistency. | 211 | consistency. |
144 | 224 | """ | 212 | """ |
145 | 225 | self.logger.debug("Verifying the changes file.") | 213 | self.logger.debug("Verifying the changes file.") |
146 | @@ -228,7 +216,7 @@ | |||
147 | 228 | yield UploadError("No files found in the changes") | 216 | yield UploadError("No files found in the changes") |
148 | 229 | 217 | ||
149 | 230 | raw_urgency = self._dict['urgency'].lower() | 218 | raw_urgency = self._dict['urgency'].lower() |
151 | 231 | if not self.urgency_map.has_key(raw_urgency): | 219 | if raw_urgency not in self.urgency_map: |
152 | 232 | yield UploadWarning( | 220 | yield UploadWarning( |
153 | 233 | "Unable to grok urgency %s, overriding with 'low'" | 221 | "Unable to grok urgency %s, overriding with 'low'" |
154 | 234 | % (raw_urgency)) | 222 | % (raw_urgency)) |
155 | @@ -362,3 +350,26 @@ | |||
156 | 362 | return self.changes_comment + changes_author | 350 | return self.changes_comment + changes_author |
157 | 363 | 351 | ||
158 | 364 | 352 | ||
159 | 353 | def determine_file_class_and_name(filename): | ||
160 | 354 | """Determine the name and PackageUploadFile subclass for the filename.""" | ||
161 | 355 | source_match = re_issource.match(filename) | ||
162 | 356 | binary_match = re_isadeb.match(filename) | ||
163 | 357 | if source_match: | ||
164 | 358 | package = source_match.group(1) | ||
165 | 359 | if (determine_source_file_type(filename) == | ||
166 | 360 | SourcePackageFileType.DSC): | ||
167 | 361 | cls = DSCFile | ||
168 | 362 | else: | ||
169 | 363 | cls = SourceUploadFile | ||
170 | 364 | elif binary_match: | ||
171 | 365 | package = binary_match.group(1) | ||
172 | 366 | cls = { | ||
173 | 367 | BinaryPackageFileType.DEB: DebBinaryUploadFile, | ||
174 | 368 | BinaryPackageFileType.DDEB: DdebBinaryUploadFile, | ||
175 | 369 | BinaryPackageFileType.UDEB: UdebBinaryUploadFile, | ||
176 | 370 | }[determine_binary_file_type(filename)] | ||
177 | 371 | else: | ||
178 | 372 | raise CannotDetermineFileTypeError( | ||
179 | 373 | "Could not determine the type of %r" % filename) | ||
180 | 374 | |||
181 | 375 | return package, cls | ||
182 | 365 | 376 | ||
183 | === added file 'lib/lp/archiveuploader/tests/test_changesfile.py' | |||
184 | --- lib/lp/archiveuploader/tests/test_changesfile.py 1970-01-01 00:00:00 +0000 | |||
185 | +++ lib/lp/archiveuploader/tests/test_changesfile.py 2010-08-01 07:06:04 +0000 | |||
186 | @@ -0,0 +1,54 @@ | |||
187 | 1 | # Copyright 2010 Canonical Ltd. This software is licensed under the | ||
188 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
189 | 3 | |||
190 | 4 | """Test ChangesFile functionality.""" | ||
191 | 5 | |||
192 | 6 | __metaclass__ = type | ||
193 | 7 | |||
194 | 8 | from testtools import TestCase | ||
195 | 9 | |||
196 | 10 | from lp.archiveuploader.changesfile import (CannotDetermineFileTypeError, | ||
197 | 11 | determine_file_class_and_name) | ||
198 | 12 | from lp.archiveuploader.dscfile import DSCFile | ||
199 | 13 | from lp.archiveuploader.nascentuploadfile import ( | ||
200 | 14 | DebBinaryUploadFile, DdebBinaryUploadFile, SourceUploadFile, | ||
201 | 15 | UdebBinaryUploadFile) | ||
202 | 16 | |||
203 | 17 | |||
204 | 18 | class TestDetermineFileClassAndName(TestCase): | ||
205 | 19 | |||
206 | 20 | def testSourceFile(self): | ||
207 | 21 | # A non-DSC source file is a SourceUploadFile. | ||
208 | 22 | self.assertEquals( | ||
209 | 23 | ('foo', SourceUploadFile), | ||
210 | 24 | determine_file_class_and_name('foo_1.0.diff.gz')) | ||
211 | 25 | |||
212 | 26 | def testDSCFile(self): | ||
213 | 27 | # A DSC is a DSCFile, since they're special. | ||
214 | 28 | self.assertEquals( | ||
215 | 29 | ('foo', DSCFile), | ||
216 | 30 | determine_file_class_and_name('foo_1.0.dsc')) | ||
217 | 31 | |||
218 | 32 | def testDEBFile(self): | ||
219 | 33 | # A binary file is the appropriate PackageUploadFile subclass. | ||
220 | 34 | self.assertEquals( | ||
221 | 35 | ('foo', DebBinaryUploadFile), | ||
222 | 36 | determine_file_class_and_name('foo_1.0_all.deb')) | ||
223 | 37 | self.assertEquals( | ||
224 | 38 | ('foo', DdebBinaryUploadFile), | ||
225 | 39 | determine_file_class_and_name('foo_1.0_all.ddeb')) | ||
226 | 40 | self.assertEquals( | ||
227 | 41 | ('foo', UdebBinaryUploadFile), | ||
228 | 42 | determine_file_class_and_name('foo_1.0_all.udeb')) | ||
229 | 43 | |||
230 | 44 | def testUnmatchingFile(self): | ||
231 | 45 | # Files with unknown extensions or none at all are not | ||
232 | 46 | # identified. | ||
233 | 47 | self.assertRaises( | ||
234 | 48 | CannotDetermineFileTypeError, | ||
235 | 49 | determine_file_class_and_name, | ||
236 | 50 | 'foo_1.0.notdsc') | ||
237 | 51 | self.assertRaises( | ||
238 | 52 | CannotDetermineFileTypeError, | ||
239 | 53 | determine_file_class_and_name, | ||
240 | 54 | 'foo') | ||
241 | 0 | 55 | ||
242 | === modified file 'lib/lp/archiveuploader/tests/test_utils.py' | |||
243 | --- lib/lp/archiveuploader/tests/test_utils.py 2010-07-24 05:41:31 +0000 | |||
244 | +++ lib/lp/archiveuploader/tests/test_utils.py 2010-08-01 07:06:04 +0000 | |||
245 | @@ -75,6 +75,11 @@ | |||
246 | 75 | determine_binary_file_type('foo_1.0-1_all.deb'), | 75 | determine_binary_file_type('foo_1.0-1_all.deb'), |
247 | 76 | BinaryPackageFileType.DEB) | 76 | BinaryPackageFileType.DEB) |
248 | 77 | 77 | ||
249 | 78 | # .ddeb -> DDEB | ||
250 | 79 | self.assertEquals( | ||
251 | 80 | determine_binary_file_type('foo_1.0-1_all.ddeb'), | ||
252 | 81 | BinaryPackageFileType.DDEB) | ||
253 | 82 | |||
254 | 78 | # .udeb -> UDEB | 83 | # .udeb -> UDEB |
255 | 79 | self.assertEquals( | 84 | self.assertEquals( |
256 | 80 | determine_binary_file_type('foo_1.0-1_all.udeb'), | 85 | determine_binary_file_type('foo_1.0-1_all.udeb'), |
257 | 81 | 86 | ||
258 | === modified file 'lib/lp/archiveuploader/utils.py' | |||
259 | --- lib/lp/archiveuploader/utils.py 2009-12-10 13:53:30 +0000 | |||
260 | +++ lib/lp/archiveuploader/utils.py 2010-08-01 07:06:04 +0000 | |||
261 | @@ -98,6 +98,8 @@ | |||
262 | 98 | return BinaryPackageFileType.DEB | 98 | return BinaryPackageFileType.DEB |
263 | 99 | elif filename.endswith(".udeb"): | 99 | elif filename.endswith(".udeb"): |
264 | 100 | return BinaryPackageFileType.UDEB | 100 | return BinaryPackageFileType.UDEB |
265 | 101 | elif filename.endswith(".ddeb"): | ||
266 | 102 | return BinaryPackageFileType.DDEB | ||
267 | 101 | else: | 103 | else: |
268 | 102 | return None | 104 | return None |
269 | 103 | 105 | ||
270 | @@ -128,7 +130,7 @@ | |||
271 | 128 | return (section, component) | 130 | return (section, component) |
272 | 129 | 131 | ||
273 | 130 | 132 | ||
275 | 131 | def build_file_list(tagfile, is_dsc = False, default_component="main" ): | 133 | def build_file_list(tagfile, is_dsc = False, default_component="main"): |
276 | 132 | files = {} | 134 | files = {} |
277 | 133 | 135 | ||
278 | 134 | if "files" not in tagfile: | 136 | if "files" not in tagfile: |
279 | @@ -170,7 +172,7 @@ | |||
280 | 170 | "size": size, | 172 | "size": size, |
281 | 171 | "section": section, | 173 | "section": section, |
282 | 172 | "priority": priority, | 174 | "priority": priority, |
284 | 173 | "component": component | 175 | "component": component, |
285 | 174 | } | 176 | } |
286 | 175 | 177 | ||
287 | 176 | return files | 178 | return files |
288 | @@ -185,7 +187,7 @@ | |||
289 | 185 | unicode(s, 'utf-8') | 187 | unicode(s, 'utf-8') |
290 | 186 | return s | 188 | return s |
291 | 187 | except UnicodeError: | 189 | except UnicodeError: |
293 | 188 | latin1_s = unicode(s,'iso8859-1') | 190 | latin1_s = unicode(s, 'iso8859-1') |
294 | 189 | return latin1_s.encode('utf-8') | 191 | return latin1_s.encode('utf-8') |
295 | 190 | 192 | ||
296 | 191 | 193 | ||
297 | @@ -221,11 +223,11 @@ | |||
298 | 221 | 223 | ||
299 | 222 | def __init__(self, message): | 224 | def __init__(self, message): |
300 | 223 | Exception.__init__(self) | 225 | Exception.__init__(self) |
302 | 224 | self.args = (message,) | 226 | self.args = (message, ) |
303 | 225 | self.message = message | 227 | self.message = message |
304 | 226 | 228 | ||
305 | 227 | 229 | ||
307 | 228 | def fix_maintainer (maintainer, field_name="Maintainer"): | 230 | def fix_maintainer(maintainer, field_name="Maintainer"): |
308 | 229 | """Parses a Maintainer or Changed-By field and returns: | 231 | """Parses a Maintainer or Changed-By field and returns: |
309 | 230 | 232 | ||
310 | 231 | (1) an RFC822 compatible version, | 233 | (1) an RFC822 compatible version, |
311 | @@ -290,4 +292,3 @@ | |||
312 | 290 | content = ascii_smash(content) | 292 | content = ascii_smash(content) |
313 | 291 | 293 | ||
314 | 292 | return fix_maintainer(content, fieldname) | 294 | return fix_maintainer(content, fieldname) |
315 | 293 |
Nice work.
Rather than returning None it seems more sensible to me to raise some sort of exception. With that change, r=me.