OLD | NEW |
---|---|
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import copy | 5 import copy |
6 import hashlib | 6 import hashlib |
7 import json | 7 import json |
8 import sys | 8 import sys |
9 | 9 |
10 MANIFEST_VERSION = 2 | 10 MANIFEST_VERSION = 2 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
99 """Generic error/exception for manifest_util module""" | 99 """Generic error/exception for manifest_util module""" |
100 pass | 100 pass |
101 | 101 |
102 | 102 |
103 class Archive(dict): | 103 class Archive(dict): |
104 """A placeholder for sdk archive information. We derive Archive from | 104 """A placeholder for sdk archive information. We derive Archive from |
105 dict so that it is easily serializable. """ | 105 dict so that it is easily serializable. """ |
106 | 106 |
107 def __init__(self, host_os_name): | 107 def __init__(self, host_os_name): |
108 """ Create a new archive for the given host-os name. """ | 108 """ Create a new archive for the given host-os name. """ |
109 super(Archive, self).__init__() | |
109 self['host_os'] = host_os_name | 110 self['host_os'] = host_os_name |
110 | 111 |
111 def CopyFrom(self, src): | 112 def CopyFrom(self, src): |
112 """Update the content of the archive by copying values from the given | 113 """Update the content of the archive by copying values from the given |
113 dictionary. | 114 dictionary. |
114 | 115 |
115 Args: | 116 Args: |
116 src: The dictionary whose values must be copied to the archive.""" | 117 src: The dictionary whose values must be copied to the archive.""" |
117 for key, value in src.items(): | 118 for key, value in src.items(): |
118 self[key] = value | 119 self[key] = value |
(...skipping 15 matching lines...) Expand all Loading... | |
134 if not self.get('size', None): | 135 if not self.get('size', None): |
135 raise Error('Archive "%s" has no size' % host_os) | 136 raise Error('Archive "%s" has no size' % host_os) |
136 checksum = self.get('checksum', None) | 137 checksum = self.get('checksum', None) |
137 if not checksum: | 138 if not checksum: |
138 raise Error('Archive "%s" has no checksum' % host_os) | 139 raise Error('Archive "%s" has no checksum' % host_os) |
139 elif not isinstance(checksum, dict): | 140 elif not isinstance(checksum, dict): |
140 raise Error('Archive "%s" has a checksum, but it is not a dict' % host_os) | 141 raise Error('Archive "%s" has a checksum, but it is not a dict' % host_os) |
141 elif not len(checksum): | 142 elif not len(checksum): |
142 raise Error('Archive "%s" has an empty checksum dict' % host_os) | 143 raise Error('Archive "%s" has an empty checksum dict' % host_os) |
143 # Verify that all key names are valid. | 144 # Verify that all key names are valid. |
144 for key, val in self.iteritems(): | 145 for key in self.iterkeys(): |
145 if key not in VALID_ARCHIVE_KEYS: | 146 if key not in VALID_ARCHIVE_KEYS: |
146 raise Error('Archive "%s" has invalid attribute "%s"' % (host_os, key)) | 147 raise Error('Archive "%s" has invalid attribute "%s"' % (host_os, key)) |
147 | 148 |
148 def __getattr__(self, name): | 149 def __getattr__(self, name): |
149 """Retrieve values from this dict using attributes. | 150 """Retrieve values from this dict using attributes. |
150 | 151 |
151 This allows for foo.bar instead of foo['bar']. | 152 This allows for foo.bar instead of foo['bar']. |
152 | 153 |
153 Args: | 154 Args: |
154 name: the name of the key, 'bar' in the example above. | 155 name: the name of the key, 'bar' in the example above. |
(...skipping 15 matching lines...) Expand all Loading... | |
170 name: The name of the key, 'bar' in the example above. | 171 name: The name of the key, 'bar' in the example above. |
171 value: The value to associate with that key.""" | 172 value: The value to associate with that key.""" |
172 if name not in VALID_ARCHIVE_KEYS: | 173 if name not in VALID_ARCHIVE_KEYS: |
173 raise AttributeError(name) | 174 raise AttributeError(name) |
174 # special case, self.checksum returns the sha1, not the checksum dict. | 175 # special case, self.checksum returns the sha1, not the checksum dict. |
175 if name == 'checksum': | 176 if name == 'checksum': |
176 self.setdefault('checksum', {})['sha1'] = value | 177 self.setdefault('checksum', {})['sha1'] = value |
177 return | 178 return |
178 return self.__setitem__(name, value) | 179 return self.__setitem__(name, value) |
179 | 180 |
180 def GetChecksum(self, type='sha1'): | 181 def GetChecksum(self, hash_type='sha1'): |
181 """Returns a given cryptographic checksum of the archive""" | 182 """Returns a given cryptographic checksum of the archive""" |
182 return self['checksum'][type] | 183 return self['checksum'][hash_type] |
183 | 184 |
184 | 185 |
185 class Bundle(dict): | 186 class Bundle(dict): |
186 """A placeholder for sdk bundle information. We derive Bundle from | 187 """A placeholder for sdk bundle information. We derive Bundle from |
187 dict so that it is easily serializable.""" | 188 dict so that it is easily serializable.""" |
188 | 189 |
189 def __init__(self, obj): | 190 def __init__(self, obj): |
190 """ Create a new bundle with the given bundle name.""" | 191 """ Create a new bundle with the given bundle name.""" |
191 if isinstance(obj, str) or isinstance(obj, unicode): | 192 if isinstance(obj, str) or isinstance(obj, unicode): |
192 dict.__init__(self, [(ARCHIVES_KEY, []), (NAME_KEY, obj)]) | 193 dict.__init__(self, [(ARCHIVES_KEY, []), (NAME_KEY, obj)]) |
(...skipping 27 matching lines...) Expand all Loading... | |
220 | 221 |
221 def LoadDataFromString(self, json_string): | 222 def LoadDataFromString(self, json_string): |
222 """Load a JSON bundle string. Raises an exception if json_string | 223 """Load a JSON bundle string. Raises an exception if json_string |
223 is not well-formed JSON. | 224 is not well-formed JSON. |
224 | 225 |
225 Args: | 226 Args: |
226 json_string: a JSON-formatted string containing the bundle | 227 json_string: a JSON-formatted string containing the bundle |
227 """ | 228 """ |
228 self.CopyFrom(json.loads(json_string)) | 229 self.CopyFrom(json.loads(json_string)) |
229 | 230 |
230 def CopyFrom(self, dict): | 231 def CopyFrom(self, source): |
231 """Update the content of the bundle by copying values from the given | 232 """Update the content of the bundle by copying values from the given |
232 dictionary. | 233 dictionary. |
233 | 234 |
234 Args: | 235 Args: |
235 dict: The dictionary whose values must be copied to the bundle.""" | 236 source: The dictionary whose values must be copied to the bundle.""" |
236 for key, value in dict.items(): | 237 for key, value in source.items(): |
237 if key == ARCHIVES_KEY: | 238 if key == ARCHIVES_KEY: |
238 archives = [] | 239 archives = [] |
239 for a in value: | 240 for a in value: |
240 new_archive = Archive(a['host_os']) | 241 new_archive = Archive(a['host_os']) |
241 new_archive.CopyFrom(a) | 242 new_archive.CopyFrom(a) |
242 archives.append(new_archive) | 243 archives.append(new_archive) |
243 self[ARCHIVES_KEY] = archives | 244 self[ARCHIVES_KEY] = archives |
244 else: | 245 else: |
245 self[key] = value | 246 self[key] = value |
246 | 247 |
(...skipping 16 matching lines...) Expand all Loading... | |
263 self[NAME_KEY]) | 264 self[NAME_KEY]) |
264 # Check specific values | 265 # Check specific values |
265 if self['stability'] not in STABILITY_LITERALS: | 266 if self['stability'] not in STABILITY_LITERALS: |
266 raise Error('Bundle "%s" has invalid stability field: "%s"' % | 267 raise Error('Bundle "%s" has invalid stability field: "%s"' % |
267 (self[NAME_KEY], self['stability'])) | 268 (self[NAME_KEY], self['stability'])) |
268 if self['recommended'] not in YES_NO_LITERALS: | 269 if self['recommended'] not in YES_NO_LITERALS: |
269 raise Error( | 270 raise Error( |
270 'Bundle "%s" has invalid recommended field: "%s"' % | 271 'Bundle "%s" has invalid recommended field: "%s"' % |
271 (self[NAME_KEY], self['recommended'])) | 272 (self[NAME_KEY], self['recommended'])) |
272 # Verify that all key names are valid. | 273 # Verify that all key names are valid. |
273 for key, val in self.iteritems(): | 274 for key in self: |
binji
2012/09/08 17:45:13
you used self.iterkeys() above. Is one better than
Sam Clegg
2012/09/10 17:19:17
iterkeys() is redundant. Will remove.
| |
274 if key not in VALID_BUNDLES_KEYS: | 275 if key not in VALID_BUNDLES_KEYS: |
275 raise Error('Bundle "%s" has invalid attribute "%s"' % | 276 raise Error('Bundle "%s" has invalid attribute "%s"' % |
276 (self[NAME_KEY], key)) | 277 (self[NAME_KEY], key)) |
277 # Validate the archives | 278 # Validate the archives |
278 for archive in self[ARCHIVES_KEY]: | 279 for archive in self[ARCHIVES_KEY]: |
279 archive.Validate() | 280 archive.Validate() |
280 | 281 |
281 def GetArchive(self, host_os_name): | 282 def GetArchive(self, host_os_name): |
282 """Retrieve the archive for the given host os. | 283 """Retrieve the archive for the given host os. |
283 | 284 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
386 "bundles": [], | 387 "bundles": [], |
387 } | 388 } |
388 | 389 |
389 def Validate(self): | 390 def Validate(self): |
390 """Validate the Manifest file and raises an exception for problems""" | 391 """Validate the Manifest file and raises an exception for problems""" |
391 # Validate the manifest top level | 392 # Validate the manifest top level |
392 if self._manifest_data["manifest_version"] > MANIFEST_VERSION: | 393 if self._manifest_data["manifest_version"] > MANIFEST_VERSION: |
393 raise Error("Manifest version too high: %s" % | 394 raise Error("Manifest version too high: %s" % |
394 self._manifest_data["manifest_version"]) | 395 self._manifest_data["manifest_version"]) |
395 # Verify that all key names are valid. | 396 # Verify that all key names are valid. |
396 for key, val in self._manifest_data.iteritems(): | 397 for key in self._manifest_data: |
binji
2012/09/08 17:45:13
same here
Sam Clegg
2012/09/10 17:19:17
done
| |
397 if key not in VALID_MANIFEST_KEYS: | 398 if key not in VALID_MANIFEST_KEYS: |
398 raise Error('Manifest has invalid attribute "%s"' % key) | 399 raise Error('Manifest has invalid attribute "%s"' % key) |
399 # Validate each bundle | 400 # Validate each bundle |
400 for bundle in self._manifest_data[BUNDLES_KEY]: | 401 for bundle in self._manifest_data[BUNDLES_KEY]: |
401 bundle.Validate() | 402 bundle.Validate() |
402 | 403 |
403 def GetBundle(self, name): | 404 def GetBundle(self, name): |
404 """Get a bundle from the array of bundles. | 405 """Get a bundle from the array of bundles. |
405 | 406 |
406 Args: | 407 Args: |
407 name: the name of the bundle to return. | 408 name: the name of the bundle to return. |
408 Return: | 409 Return: |
409 The first bundle with the given name, or None if it is not found.""" | 410 The first bundle with the given name, or None if it is not found.""" |
410 if not BUNDLES_KEY in self._manifest_data: | 411 if not BUNDLES_KEY in self._manifest_data: |
411 return None | 412 return None |
412 bundles = [bundle for bundle in self._manifest_data[BUNDLES_KEY] | 413 bundles = [bundle for bundle in self._manifest_data[BUNDLES_KEY] |
413 if bundle[NAME_KEY] == name] | 414 if bundle[NAME_KEY] == name] |
414 if len(bundles) > 1: | 415 if len(bundles) > 1: |
415 WarningPrint("More than one bundle with name '%s' exists." % name) | 416 sys.stderr.write("WARNING: More than one bundle with name" |
417 "'%s' exists.\n" % name) | |
416 return bundles[0] if len(bundles) > 0 else None | 418 return bundles[0] if len(bundles) > 0 else None |
417 | 419 |
418 def GetBundles(self): | 420 def GetBundles(self): |
419 """Return all the bundles in the manifest.""" | 421 """Return all the bundles in the manifest.""" |
420 return self._manifest_data[BUNDLES_KEY] | 422 return self._manifest_data[BUNDLES_KEY] |
421 | 423 |
422 def SetBundle(self, new_bundle): | 424 def SetBundle(self, new_bundle): |
423 """Replace named bundle. Add if absent. | 425 """Replace named bundle. Add if absent. |
424 | 426 |
425 Args: | 427 Args: |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
513 new_bundle.CopyFrom(b) | 515 new_bundle.CopyFrom(b) |
514 bundles.append(new_bundle) | 516 bundles.append(new_bundle) |
515 self._manifest_data[key] = bundles | 517 self._manifest_data[key] = bundles |
516 else: | 518 else: |
517 self._manifest_data[key] = value | 519 self._manifest_data[key] = value |
518 self.Validate() | 520 self.Validate() |
519 | 521 |
520 def GetDataAsString(self): | 522 def GetDataAsString(self): |
521 """Returns the current JSON manifest object, pretty-printed""" | 523 """Returns the current JSON manifest object, pretty-printed""" |
522 return DictToJSON(self._manifest_data) | 524 return DictToJSON(self._manifest_data) |
OLD | NEW |