@db.non_transactional
  def get_bucket(self,
                 bucketpath,
                 prefix,
                 marker,
                 max_keys,
                 delimiter):
    common.validate_bucket_path(bucketpath)
    q = _AE_GCSFileInfo_.all(namespace='')
    fully_qualified_prefix = '/'.join([bucketpath, prefix])
    if marker:
      q.filter('filename >', '/'.join([bucketpath, marker]))
    else:
      q.filter('filename >=', fully_qualified_prefix)

    result = set()
    name = None
    first = True
    first_dir = None
    for info in q.run():

      if not info.filename.startswith(fully_qualified_prefix):
        break
      if len(result) == max_keys:
        break


      info = db.get(info.key())
      if not info:
        continue

      name = info.filename
      if delimiter:

        start_index = name.find(delimiter, len(fully_qualified_prefix))
        if start_index != -1:
          name = name[:start_index + len(delimiter)]


          if marker and (first or name == first_dir):
            first = False
            first_dir = name

          else:
            result.add(common.GCSFileStat(name, st_size=None,
                                          st_ctime=None, etag=None,
                                          is_dir=True))
          continue


      if info.finalized:
        first = False
        result.add(common.GCSFileStat(
            filename=name,
            st_size=info.size,
            st_ctime=calendar.timegm(info.creation.utctimetuple()),
            etag=info.etag))

    def is_truncated():
      """Check if there are more results satisfying the query."""
      if not result:
        return False
      q = _AE_GCSFileInfo_.all(namespace='')
      q.filter('filename >', name)
      info = None

      if delimiter and name.endswith(delimiter):

        for info in q.run():
          if not info.filename.startswith(name):
            break
        if info is not None and info.filename.startswith(name):
          info = None
      else:
        info = q.get()
      if info is None or not info.filename.startswith(fully_qualified_prefix):
        return False
      return True

    result = list(result)
    result.sort()
    truncated = is_truncated()
    next_marker = name if truncated else None

    return result, next_marker, truncated
Get bucket listing with a GET.
dataset/ETHPy150Open GoogleCloudPlatform/python-compat-runtime/appengine-compat/exported_appengine_sdk/google/appengine/ext/cloudstorage/cloudstorage_stub.py/CloudStorageStub.get_bucket