def attrs(self, *args, **kwargs): """Return attributes for this entity. (filters whole attribute list as opposed to querying the db directly) """ merge_container_attrs = kwargs.pop('merge_container_attrs', False) ignore_memcache = kwargs.pop('ignore_memcache', False) if clusto.SESSION.memcache and not ignore_memcache: logging.debug('Pulling info from memcache when possible for %s' % self.name) k = None if 'key' in kwargs: k = kwargs['key'] else: if len(args) > 1: k = args[0] if k: # This is hackish, need to find another way to know if we should cache things or not if not k.startswith('_'): if 'subkey' in kwargs and kwargs['subkey'] is not None: memcache_key = str('%s.%s.%s' % (self.name, k, kwargs['subkey'])) else: memcache_key = str('%s.%s' % (self.name, k)) logging.debug('memcache key: %s' % memcache_key) attrs = clusto.SESSION.memcache.get(memcache_key) if not attrs: attrs = self.attr_filter(self.entity.attrs, *args, **kwargs) if attrs: clusto.SESSION.memcache.set(memcache_key, attrs) else: attrs = self.attr_filter(self.entity.attrs, *args, **kwargs) else: logging.debug('We cannot cache attrs without a key at least') attrs = self.attr_filter(self.entity.attrs, *args, **kwargs) else: attrs = self.attr_filter(self.entity.attrs, *args, **kwargs) if merge_container_attrs: kwargs['merge_container_attrs'] = merge_container_attrs kwargs['ignore_memcache'] = ignore_memcache parent_entity_ids = [parent.entity.entity_id for parent in self.parents()] while parent_entity_ids: parent_attrs = Attribute.query().filter( Attribute.entity_id.in_(parent_entity_ids)).all() attrs.extend(parent_attrs) grandparent_contains_attributes = Attribute.query().filter( Attribute.relation_id.in_(parent_entity_ids)).filter( Attribute.key == '_contains').all() parent_entity_ids = [a.entity_id for a in grandparent_contains_attributes] kwargs.pop('merge_container_attrs') kwargs.pop('ignore_memcache') attrs = self.attr_filter(attrs, *args, **kwargs) return attrs
def contents(self, *args, **kwargs): """Return the contents of this Entity. Such that: >>> A.insert(B) >>> A.insert(C) >>> A.contents() [B, C] """ if 'search_children' in kwargs: search_children = kwargs.pop('search_children') else: search_children = False contents = self._get_contents(*args, **kwargs) if search_children: # We want to prune our search so that children that do not have children do not need to # be searched. To do so, we query for children that have a _contains attribute, and only # call .contents() on those children. children = self._get_contents() children_entity_ids = [child.entity.entity_id for child in children] if children_entity_ids: contains_attributes = Attribute.query().filter( Attribute.key == '_contains').filter( Attribute.entity_id.in_(children_entity_ids)).all() else: contains_attributes = [] child_entity_ids_to_search = set([attr.entity_id for attr in contains_attributes]) children_to_search = [child for child in children if child.entity.entity_id in child_entity_ids_to_search] for child in children_to_search: kwargs['search_children'] = search_children contents.extend(child.contents(*args, **kwargs)) return contents
def do_attr_query(cls, key=(), value=(), number=(), start_timestamp=(), end_timestamp=(), subkey=(), ignore_hidden=True, sort_by_keys=False, glob=False, count=False, querybase=None, return_query=False, entity=None): """Does queries against all Attributes using the DB.""" clusto.flush() if querybase: query = querybase else: query = Attribute.query() ### This is bunk, gotta fix it if isinstance(cls, Driver): query = query.filter(and_(Attribute.entity_id == Entity.entity_id, Entity.driver == cls._driver_name, Entity.type == cls._clusto_type)) if start_timestamp != () and end_timestamp != (): query = query.filter(and_((Attribute.datetime_value >= start_timestamp))) query = query.filter(and_(Attribute.datetime_value <= end_timestamp)) if entity: query = query.filter_by(entity_id=entity.entity_id) if key is not (): key = unicode(key) if glob: query = query.filter(Attribute.key.like(key.replace('*', '%'))) else: query = query.filter_by(key=key) if subkey is not (): if subkey is not None: subkey = unicode(subkey) if glob and subkey: query = query.filter(Attribute.subkey.like(subkey.replace('*', '%'))) else: query = query.filter_by(subkey=subkey) if value is not (): typename = Attribute.get_type(value) if typename == 'relation': if isinstance(value, Driver): value = value.entity.entity_id query = query.filter_by(relation_id=value) else: if typename == 'json': typename = 'string' value = json.dumps(value) if typename == 'string': value = unicode(value) query = query.filter_by(**{typename+'_value': value}) if number is not (): if isinstance(number, bool) or number is None: if number: query = query.filter(Attribute.number != None) # noqa else: query = query.filter(Attribute.number == None) # noqa elif isinstance(number, (int, long)): query = query.filter_by(number=number) else: raise TypeError("number must be either a boolean or an integer.") if ignore_hidden and ((key and not key.startswith('_')) or key is ()): query = query.filter(not_(Attribute.key.like(u'@_%', escape=u'@'))) if sort_by_keys: query = query.order_by(Attribute.key) if count: return query.count() if return_query: return query return query.all()