docs: def gdf_from_place(query, gdf_name=None, which_result=1, buffer_dist=None):
      """
      Create a GeoDataFrame from a single place name query.
  
      Parameters
      ----------
      query : string or dict
          query string or structured query dict to geocode/download
      gdf_name : string
          name attribute metadata for GeoDataFrame (this is used to save shapefile
          later)
      which_result : int
          max number of results to return and which to process upon receipt
      buffer_dist : float
          distance to buffer around the place geometry, in meters
  
      Returns
      -------
      GeoDataFrame
      """
      # if no gdf_name is passed, just use the query
      assert (isinstance(query, dict) or isinstance(query, str)), 'query must be a dict or a string'
      if (gdf_name is None) and isinstance(query, dict):
          gdf_name = ', '.join(list(query.values()))
      elif (gdf_name is None) and isinstance(query, str):
          gdf_name = query
  
      # get the data from OSM
      data = osm_polygon_download(query, limit=which_result)
      if len(data) >= which_result:
  
          # extract data elements from the JSON response
          result = data[which_result - 1]
          bbox_south, bbox_north, bbox_west, bbox_east = [float(x) for x in result['boundingbox']]
          geometry = result['geojson']
          place = result['display_name']
          features = [{'type': 'Feature',
                       'geometry': geometry,
                       'properties': {'place_name': place,
                                      'bbox_north': bbox_north,
                                      'bbox_south': bbox_south,
                                      'bbox_east': bbox_east,
                                      'bbox_west': bbox_west}}]
  
          # if we got an unexpected geometry type (like a point), log a warning
          if geometry['type'] not in ['Polygon', 'MultiPolygon']:
              log('OSM returned a {} as the geometry.'.format(geometry['type']), level=lg.WARNING)
  
          # create the GeoDataFrame, name it, and set its original CRS to default_crs
          gdf = gpd.GeoDataFrame.from_features(features)
          gdf.gdf_name = gdf_name
          gdf.crs = settings.default_crs
  
          # if buffer_dist was passed in, project the geometry to UTM, buffer it
          # in meters, then project it back to lat-long
          if buffer_dist is not None:
              gdf_utm = project_gdf(gdf)
              gdf_utm['geometry'] = gdf_utm['geometry'].buffer(buffer_dist)
              gdf = project_gdf(gdf_utm, to_latlong=True)
              log('Buffered the GeoDataFrame "{}" to {} meters'.format(gdf.gdf_name, buffer_dist))
  
          # return the gdf
          log('Created GeoDataFrame with {} row for query "{}"'.format(len(gdf), query))
          return gdf
      else:
          # if there was no data returned (or fewer results than which_result
          # specified)
          log('OSM returned no results (or fewer than which_result) for query "{}"'.format(query), level=lg.WARNING)
          gdf = gpd.GeoDataFrame()
          gdf.gdf_name = gdf_name
          return gdf