OLD | NEW |
1 __metaclass__ = type | 1 __metaclass__ = type |
2 | 2 |
3 from datetime import ( | 3 from datetime import ( |
4 datetime, | 4 datetime, |
5 timedelta, | 5 timedelta, |
6 ) | 6 ) |
7 from email.utils import parseaddr | 7 from email.utils import parseaddr |
8 from inspect import getargspec | 8 from inspect import getargspec |
9 from os.path import ( | 9 from os.path import ( |
10 join, | 10 join, |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 self._format_related(payload['data'], payload['weight']) | 188 self._format_related(payload['data'], payload['weight']) |
189 for payload in value] | 189 for payload in value] |
190 f_provides = {} | 190 f_provides = {} |
191 for key, value in r_provides.items(): | 191 for key, value in r_provides.items(): |
192 f_provides[key] = [ | 192 f_provides[key] = [ |
193 self._format_related(payload['data'], payload['weight']) | 193 self._format_related(payload['data'], payload['weight']) |
194 for payload in value] | 194 for payload in value] |
195 return f_requires, f_provides | 195 return f_requires, f_provides |
196 | 196 |
197 @classmethod | 197 @classmethod |
198 def _format_charm(cls, charm, extra_data={}): | 198 def _format_charm(cls, charm, annotations=None): |
199 """Format the charm for API consumers.""" | 199 """Format the charm for API consumers.""" |
200 mapping = { | 200 mapping = { |
201 'summary': 'summary', | 201 'summary': 'summary', |
202 'name': 'name', | 202 'name': 'name', |
203 'description': 'description', | 203 'description': 'description', |
204 'owner': 'owner', | 204 'owner': 'owner', |
205 'downloads': 'downloads', | 205 'downloads': 'downloads', |
206 'downloads_in_past_30_days': 'downloads_in_past_30_days', | 206 'downloads_in_past_30_days': 'downloads_in_past_30_days', |
207 'distro_series': 'series', | 207 'distro_series': 'series', |
208 'revision': 'revision', | 208 'revision': 'revision', |
(...skipping 30 matching lines...) Expand all Loading... |
239 'provides': charm.provides, | 239 'provides': charm.provides, |
240 'requires': charm.requires, | 240 'requires': charm.requires, |
241 }, | 241 }, |
242 'options': charm.options, | 242 'options': charm.options, |
243 'files': [join(entry['subdir'], entry['filename']) | 243 'files': [join(entry['subdir'], entry['filename']) |
244 for entry in charm.files.values()], | 244 for entry in charm.files.values()], |
245 'is_approved': charm.promulgated, | 245 'is_approved': charm.promulgated, |
246 'tested_providers': tested_providers, | 246 'tested_providers': tested_providers, |
247 'is_subordinate': charm.subordinate | 247 'is_subordinate': charm.subordinate |
248 }) | 248 }) |
249 annotations = extra_data.get('annotations') | |
250 if annotations is not None: | 249 if annotations is not None: |
251 output.update({'annotations': annotations}) | 250 output.update({'annotations': annotations}) |
252 return output | 251 return output |
253 | 252 |
254 @classmethod | 253 @classmethod |
255 def _format_related(cls, charm_data, weight, _now=None): | 254 def _format_related(cls, charm_data, weight, _now=None): |
256 if _now is None: | 255 if _now is None: |
257 now = datetime.utcnow() | 256 now = datetime.utcnow() |
258 else: | 257 else: |
259 now = _now | 258 now = _now |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 mongo_bundle = db.bundles.find_one({'_id': bundle.id}) | 444 mongo_bundle = db.bundles.find_one({'_id': bundle.id}) |
446 mongo_services = mongo_bundle['data']['services'] | 445 mongo_services = mongo_bundle['data']['services'] |
447 service_data = bundle_dict.get('data') | 446 service_data = bundle_dict.get('data') |
448 # Now load the charm information we require for the services in the | 447 # Now load the charm information we require for the services in the |
449 # bundle. | 448 # bundle. |
450 for service, data in bundle.data['services'].iteritems(): | 449 for service, data in bundle.data['services'].iteritems(): |
451 description = BundledCharmDescription( | 450 description = BundledCharmDescription( |
452 service, data, service_data.get('series')) | 451 service, data, service_data.get('series')) |
453 charm = resolve_charm_from_description(db, description) | 452 charm = resolve_charm_from_description(db, description) |
454 if charm: | 453 if charm: |
| 454 annotations = mongo_services[service].get('annotations') |
455 formatted = cls._format_charm( | 455 formatted = cls._format_charm( |
456 Charm(charm), mongo_services[service]) | 456 Charm(charm), annotations=annotations) |
457 bundle_dict['charm_metadata'][service] = formatted | 457 bundle_dict['charm_metadata'][service] = formatted |
458 | 458 if 'annotations' not in data: |
| 459 data['annotations'] = annotations |
459 return bundle_dict | 460 return bundle_dict |
460 | 461 |
461 def _find_bundle(self, path): | 462 def _find_bundle(self, path): |
462 try: | 463 try: |
463 bundle_id, trailing, bundle_bits = self._parse_bundle_id(path) | 464 bundle_id, trailing, bundle_bits = self._parse_bundle_id(path) |
464 except ValueError: | 465 except ValueError: |
465 bundle = bundle_id = trailing = bundle_bits = None | 466 bundle = bundle_id = trailing = bundle_bits = None |
466 else: | 467 else: |
467 if bundle_bits['owner'] and bundle_bits['version']: | 468 if bundle_bits['owner'] and bundle_bits['version']: |
468 # We have all 4 parts needed, just use the ID. | 469 # We have all 4 parts needed, just use the ID. |
469 query = {'_id': bundle_id} | 470 query = {'_id': bundle_id} |
470 elif bundle_bits['owner']: | 471 elif bundle_bits['owner']: |
471 # This URL includes the owner, basket name, and bundle name. | 472 # This URL includes the owner, basket name, and bundle name. |
472 # The specified bundle may be promulgated or not. | 473 # The specified bundle may be promulgated or not. |
473 owner = bundle_bits['owner'][1:] # Strip the tilde. | 474 owner = bundle_bits['owner'][1:] # Strip the tilde. |
474 query = { | 475 query = { |
475 'owner': owner, | 476 'owner': owner, |
476 'basket_name': bundle_bits['basket'], | 477 'basket_name': bundle_bits['basket'], |
477 'name': bundle_bits['bundle'] | 478 'name': bundle_bits['bundle'], |
478 } | 479 } |
479 else: | 480 else: |
480 query = { | 481 query = { |
481 'basket_name': bundle_bits['basket'], | 482 'basket_name': bundle_bits['basket'], |
482 'name': bundle_bits['bundle'], | 483 'name': bundle_bits['bundle'], |
483 'promulgated': True | 484 'promulgated': True, |
484 } | 485 } |
485 | 486 |
486 bundle = Bundle.from_query(query, self.request.db) | 487 bundle = Bundle.from_query(query, self.request.db) |
487 return bundle_id, trailing, bundle | 488 return bundle_id, trailing, bundle |
488 | 489 |
489 def charm(self, path=None, **kwargs): | 490 def charm(self, path=None, **kwargs): |
490 """Retrieve a charm according to its API ID (the path prefix).""" | 491 """Retrieve a charm according to its API ID (the path prefix).""" |
491 if path is None: | 492 if path is None: |
492 raise HTTPNotFound(self.request.path) | 493 raise HTTPNotFound(self.request.path) |
493 charm_id, trailing, charm_data = self._find_charm(path) | 494 charm_id, trailing, charm_data = self._find_charm(path) |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 'series': series, | 832 'series': series, |
832 'name': name, | 833 'name': name, |
833 }, sort=[('store_data.revision', pymongo.DESCENDING)]) | 834 }, sort=[('store_data.revision', pymongo.DESCENDING)]) |
834 if charm is not None: | 835 if charm is not None: |
835 api_id = self._get_api_id(Charm(charm)) | 836 api_id = self._get_api_id(Charm(charm)) |
836 # Charm ID should match up to, but not including the revision. | 837 # Charm ID should match up to, but not including the revision. |
837 revisionless_charm_id = charm_id.split('-', 1)[0] | 838 revisionless_charm_id = charm_id.split('-', 1)[0] |
838 if not api_id.startswith(revisionless_charm_id): | 839 if not api_id.startswith(revisionless_charm_id): |
839 charm = None | 840 charm = None |
840 return charm_id, trailing, charm | 841 return charm_id, trailing, charm |
OLD | NEW |