docs: def read(self, path, ext=None, start=None, stop=None, recursive=False, npartitions=None):
          """
          Sets up Spark RDD across S3 or GS objects specified by dataPath.
  
          Returns RDD of <string bucket keyname, string buffer> k/v pairs.
          """
          from .utils import connection_with_anon, connection_with_gs
  
          path = addextension(path, ext)
          scheme, bucket_name, keylist = self.getfiles(
              path, start=start, stop=stop, recursive=recursive)
  
          if not keylist:
              raise FileNotFoundError("No objects found for '%s'" % path)
  
          credentials = self.credentials
  
          self.nfiles = len(keylist)
  
          if spark and isinstance(self.engine, spark):
  
              def getsplit(kvIter):
                  if scheme == 's3' or scheme == 's3n':
                      conn = connection_with_anon(credentials)
                      bucket = conn.get_bucket(bucket_name)
                  elif scheme == 'gs':
                      conn = boto.storage_uri(bucket_name, 'gs')
                      bucket = conn.get_bucket()
                  else:
                      raise NotImplementedError("No file reader implementation for URL scheme " + scheme)
  
                  for kv in kvIter:
                      idx, keyname = kv
                      key = bucket.get_key(keyname)
                      buf = key.get_contents_as_string()
                      yield idx, buf, keyname
  
              npartitions = min(npartitions, self.nfiles) if npartitions else self.nfiles
              rdd = self.engine.parallelize(enumerate(keylist), npartitions)
              return rdd.mapPartitions(getsplit)
  
          else:
  
              if scheme == 's3' or scheme == 's3n':
                  conn = connection_with_anon(credentials)
                  bucket = conn.get_bucket(bucket_name)
              elif scheme == 'gs':
                  conn = connection_with_gs(bucket_name)
                  bucket = conn.get_bucket()
              else:
                  raise NotImplementedError("No file reader implementation for URL scheme " + scheme)
  
              def getsplit(kv):
                  idx, keyName = kv
                  key = bucket.get_key(keyName)
                  buf = key.get_contents_as_string()
                  return idx, buf, keyName
  
              return [getsplit(kv) for kv in enumerate(keylist)]