old_contents: # Copyright 2011 the Melange authors.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #   http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  """Organization (Model) query functions."""
  
  
  import datetime
  
  from google.appengine.api import memcache
  
  # TODO(nathaniel): eliminate or better describe this.
  _BATCH_SIZE = 5
  
  
  def _orgsWithLogoForQuery(query, batch_size):
    """Return the org entities for the given query and batch size which have
    Logo URL set.
  
    Args:
      query: Appengine query for which the entities must be fetched
      batch_size: number of entities that needs to be fetched
    """
    orgs = []
    for org in query:
      if org.logo_url:
        orgs.append(org)
        if batch_size <= len(orgs):
          break
  
    return orgs
  
  
  def _orgWithLogoQuery(model, program):
    """Returns a query for Organizations in the specified program with logo.
    """
    q = model.all()
    q.filter('scope', program)
    q.filter('status', 'active')
    q.filter('logo_url >=', '')
  
    return q
  
  
  def participating(model, program, org_count=None):
    """Return a list of organizations to display on program homepage.
  
    Args:
      program: program entity for which the orgs need to be fetched.
      org_count: The number of organizations to return (if possible).
    """
    org_count = org_count or _BATCH_SIZE
  
    # expiry time to fetch the new organization entities
    # the current expiry time is 30 minutes.
    expiry_time = datetime.timedelta(seconds=1800)
  
    q = _orgWithLogoQuery(model, program)
  
    # the cache stores a 3-tuple in the order list of org entities,
    # cursor and the last time the cache was updated
  
    key = '%s_participating_orgs_for_%s' % (org_count, program.key().name())
    po_cache = memcache.get(key)
  
    if po_cache:
      cached_orgs, cached_cursor, cached_time = po_cache
      if not datetime.datetime.now() > cached_time + expiry_time:
        return cached_orgs
      else:
        q.with_cursor(cached_cursor)
  
    orgs = _orgsWithLogoForQuery(q, org_count)
  
    if len(orgs) < org_count:
      q = _orgWithLogoQuery(model, program)
      extra_orgs = _orgsWithLogoForQuery(q, org_count - len(orgs))
  
      # add only those orgs which are not already in the list
      orgs_keys = [o.key() for o in orgs]
      for org in extra_orgs:
        if org.key() not in orgs_keys:
          orgs.append(org)
  
    # Only cache "good" results (those that found at least org_count orgs).
    if org_count <= len(orgs):
      memcache.set(key, value=(orgs, q.cursor(), datetime.datetime.now()))
  
    return orgs
  
new_contents: # Copyright 2011 the Melange authors.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #   http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  """Organization (Model) query functions."""
  
  
  import datetime
  
  from google.appengine.api import memcache
  
  # TODO(nathaniel): eliminate or better describe this.
  _BATCH_SIZE = 5
  
  
  def _orgsWithLogoForQuery(query, batch_size):
    """Return the org entities for the given query and batch size which have
    Logo URL set.
  
    Args:
      query: Appengine query for which the entities must be fetched
      batch_size: number of entities that needs to be fetched
    """
    orgs = []
    for org in query:
      if org.logo_url:
        orgs.append(org)
        if batch_size <= len(orgs):
          break
  
    return orgs
  
  
  def _orgWithLogoQuery(model, program):
    """Returns a query for Organizations in the specified program with logo.
    """
    q = model.all()
    q.filter('scope', program)
    q.filter('status', 'active')
    q.filter('logo_url >=', '')
  
    return q
  
  
  def participating(model, program, org_count=None):
    """Return a list of organizations to display on program homepage.
  
    Args:
      program: program entity for which the orgs need to be fetched.
      org_count: The number of organizations to return (if possible).
    """
    org_count = org_count or _BATCH_SIZE
  
    # expiry time to fetch the new organization entities
    # the current expiry time is 30 minutes.
    expiry_time = datetime.timedelta(seconds=1800)
  
    q = _orgWithLogoQuery(model, program)
  
    # the cache stores a 3-tuple in the order list of org entities,
    # cursor and the last time the cache was updated
  
    key = '%s_participating_orgs_for_%s' % (org_count, program.key().name())
    po_cache = memcache.get(key)
  
    if po_cache:
      cached_orgs, cached_cursor, cached_time = po_cache
      if not datetime.datetime.now() > cached_time + expiry_time:
        return cached_orgs
      else:
        q.with_cursor(cached_cursor)
  
    orgs = _orgsWithLogoForQuery(q, org_count)
  
    # The previous query returns the organizations starting from the point
    # of the cursor upto org_count organizations. But if there are fewer
    # orgs the query returns just those. So in that case we restart the query
    # here from the beginning without the cursor to fill up the remaining slots
    # until we have org_count organizations.
    if len(orgs) < org_count:
      q = _orgWithLogoQuery(model, program)
      extra_orgs = _orgsWithLogoForQuery(q, org_count - len(orgs))
  
      # add only those orgs which are not already in the list
      orgs_keys = [o.key() for o in orgs]
      for org in extra_orgs:
        if org.key() not in orgs_keys:
          orgs.append(org)
  
    # Only cache "good" results (those that found at least org_count orgs).
    if org_count <= len(orgs):
      memcache.set(key, value=(orgs, q.cursor(), datetime.datetime.now()))
  
    return orgs
  
subject: Comment about why we restart the query when there aren't org_count organizations in the previous query.