196
194
def construct_charm_id(charm_data, use_revision=True):
197
# This creates an ID for a charm, but is not yet used to construct the _id
198
# value for charm documents.
199
195
elements = [charm_data['owner'], charm_data['series'], charm_data['name']]
201
197
elements.append('%d' % charm_data['store_data']['revision'])
202
198
return '~' + '/'.join(elements)
205
class FeaturedSource:
206
"""Charms and Bundles can be featured; that state is represented here."""
208
def __init__(self, collection):
209
# The collection that stores the featured state.
210
self.collection = collection
213
def from_db(cls, db):
214
"""Create a source of charm feature data from a database."""
215
return cls(db.featured)
218
def _make_query(item_data, doctype):
219
"""Create a query that finds a featured item."""
221
'name': item_data['name'],
222
'owner': item_data['owner'],
224
if doctype != 'bundle':
225
# Bundles do not have a series.
226
result['series'] = item_data['series']
230
def _make_document(cls, item_data, doctype):
231
"""Create a document that describes a featured item."""
232
result = cls._make_query(item_data, doctype)
233
result['doctype'] = doctype
236
def set_featured(self, item_data, doctype):
237
"""Add an item from the featured collection."""
238
featured_document = self._make_document(item_data, doctype)
239
self.collection.update(
240
featured_document, featured_document, upsert=True)
242
def clear_featured(self, item_data, doctype):
243
"""Remove an item from the featured collection."""
244
self.collection.remove(self._make_document(item_data, doctype))
246
def is_featured(self, item_data, doctype):
247
return bool(self.collection.find_one(
248
self._make_document(item_data, doctype)))
250
def _make_featured_query(self, doctype):
251
"""Construct a query that will search a collection for featured items.
254
for featured in self.collection.find({'doctype': doctype}):
255
ors.append(self._make_query(featured, doctype))
256
# If there are no featured items, then there can be no query to find
262
def get_featured(self, collection, doctype):
263
# TODO Add support for fetching featured bundles when bundles become
265
assert doctype == 'charm', 'only charms can be featured at the moment'
266
query = self._make_featured_query(doctype)
267
# There is no query, so there are no featured items.
270
items = list(collection.find(self._make_featured_query(doctype)))
271
# Order by identity (as defined by _make_document) and then revision
272
# (this works because sort is stable).
273
items.sort(key=lambda data: data['store_data']['revision'])
274
identity = functools.partial(self._make_document, doctype=doctype)
275
items.sort(key=identity)
276
# Keep only the latest revision of each item.
278
g.next() for k, g in itertools.groupby(items, key=identity)]
283
202
"""A model to access a charm representation.
916
843
if magic.from_buffer(file_content, mime=True) != 'image/svg+xml':
917
844
logger.warn("File is not an SVG: %s" % file_path)
919
# Check if the icon has viewBox set. If not, set it.
920
root = ElementTree.fromstring(file_content)
921
if root.get('viewBox') is None:
922
width = root.get('width')
923
height = root.get('height')
924
if width is None or height is None:
925
logger.warn("SVG is malformed: "
926
+ "width or height attributes not set")
928
root.attrib['viewBox'] = "0 0 {0} {1}".format(width, height)
929
file_content = ElementTree.tostring(root, encoding='UTF-8')
930
846
charm_file.save(file_content)
931
847
return charm_file
1419
1325
index_client = ElasticSearchClient.from_settings(settings)
1421
1327
# Augment the deployer_config with additional information for indexing.
1329
config_copy = copy.deepcopy(deployer_config)
1330
for key in config_copy:
1331
ids[key] = Bundle.construct_id(owner, basket_id, key)
1332
config_copy[key]['id'] = ids[key]
1333
config_copy[key]['owner'] = owner
1334
config_copy[key]['name'] = key
1335
config_copy[key]['basket'] = basket_id
1337
index_client.index_bundles(config_copy.values())
1338
if collection is None:
1423
1340
for key in deployer_config:
1424
1341
data = get_flattened_deployment(deployer_config, key)
1425
_id = Bundle.construct_id(owner, basket_id, key)
1429
1345
'owner': owner,
1430
1346
'basket': basket_id,
1434
index_data[key] = bundle_doc
1436
if collection is not None:
1437
collection.save(bundle_doc)
1439
index_client.index_bundles(index_data.values())
1349
collection.save(bundle_doc)
1442
1352
def slurp_files(fs, tree, entry_source=None):