docs: def geocode(self, pq):
          """
          :arg PlaceQuery pq: PlaceQuery instance
          :rtype: tuple
          :returns: post-processed list of Candidate objects and
                    and UpstreamResponseInfo object if an API call was made.
  
                    Examples:
  
                    Preprocessor throws out request::
  
                        ([], None)
  
                    Postprocessor throws out some candidates::
  
                        ([<Candidate obj>, <Candidate obj>, ...], <UpstreamResponseInfo obj>)
  
                    Postprocessor throws out all candidates::
  
                        ([], <UpstreamResponseInfo obj>)
  
                    An exception occurs while making the API call::
  
                        ([], <UpstreamResponseInfo obj>)
  
          """
          processed_pq = copy.copy(pq)
          for p in self._preprocessors:
              processed_pq = p.process(processed_pq)
              if not processed_pq:
                  return [], None
          upstream_response_info = UpstreamResponseInfo(self.get_service_name(),
                                                        processed_pq)
          try:
              start = datetime.now()
              candidates = self._geocode(processed_pq)
              end = datetime.now()
              response_time_sec = (end - start).total_seconds()
              upstream_response_info.set_response_time(1000 * response_time_sec)
          except Exception:
              upstream_response_info.set_success(False)
              upstream_response_info.errors.append(format_exc())
              return [], upstream_response_info
          if len(candidates) > 0:
              for p in self._postprocessors:  # apply universal candidate postprocessing
                  candidates = p.process(candidates)  # merge lists
          return candidates, upstream_response_info