123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- import collections
- import logging
- import requests
- # Google API key, with access to Street View Static API
- google_api_key = "AIzaSyAqjCYR6Szph0X0H_iD6O1HenFhL9jySOo"
- metadata_url = "https://maps.googleapis.com/maps/api/streetview/metadata"
- logger = logging.getLogger(__name__)
- def point_has_streetview(lat, lng):
- """
- Returns True if the streetview metadata endpoint says a given point has
- data available, and False otherwise.
- This function calls the streetview metadata endpoint - there is no quota consumed.
- """
- return requests.get(metadata_url, params={
- "key": google_api_key,
- "location": f"{lat},{lng}",
- }).json()["status"] == "OK"
- class PointSource:
- """
- Base class to handle the logic of managing a cache of (lat, lng) points.
- """
- def __init__(self, stock_target):
- self.stock = collections.deque()
- self.stock_target = stock_target
- def _restock_impl(self, n):
- """
- Returns a list of new points to add to the stock.
- Implementations of this method should try to return at least n points for performance.
- """
- raise NotImplementedError("Subclasses must implement this")
-
- def restock(self, n=None):
- """
- Restock at least n points into this source.
- If n is not provided, it will default to stock_target, as set during the
- construction of this point source.
- """
- n = n if n is not None else self.stock_target - len(self.stock)
- if n > 0:
- logger.info(f"Restocking {type(self).__name__} with {n} points")
- pts = self._restock_impl(n)
- self.stock.extend(pts)
- diff = n - len(pts)
- if diff > 0:
- # if implementations of _restock_impl are well behaved, this will
- # never actually need to recurse to finish the job.
- self.restock(n=diff)
- logger.info(f"Finished restocking {type(self).__name__}")
- def get_points(self, n=1):
- """
- Pull n points from the current stock.
- It is recommended to call PointSource.restock after this, to ensure the
- stock is not depleted. If possible, calling restock in another thread is
- recommended, as it can be a long operation depending on implementation.
- """
- if len(self.stock) >= n:
- pts = []
- for _ in range(n):
- pts.append(self.stock.popleft())
- return pts
- self.restock(n=n)
- # this is safe as long as restock does actually add enough new points.
- # unless this object is being rapidly drained by another thread,
- # this will recur at most once.
- return self.get_points(n=n)
|