diff --git a/lib/cartopy/__init__.py b/lib/cartopy/__init__.py index a2b0b4589..44eba759d 100644 --- a/lib/cartopy/__init__.py +++ b/lib/cartopy/__init__.py @@ -4,6 +4,8 @@ # See COPYING and COPYING.LESSER in the root of the repository for full # licensing details. +import tempfile + from ._version import get_versions __version__ = get_versions()['version'] del get_versions @@ -19,9 +21,11 @@ _writable_dir = os.path.join(os.path.expanduser('~'), '.local', 'share') _data_dir = os.path.join(os.environ.get("XDG_DATA_HOME", _writable_dir), 'cartopy') +_cache_dir = os.path.join(tempfile.gettempdir(), 'cartopy_cache_dir') config = {'pre_existing_data_dir': '', 'data_dir': _data_dir, + 'cache_dir': _cache_dir, 'repo_data_dir': os.path.join(os.path.dirname(__file__), 'data'), 'downloaders': {}, } @@ -69,6 +73,7 @@ del _data_dir del _writable_dir +del _cache_dir # Try importing a siteconfig file which exposes an update_config function, diff --git a/lib/cartopy/io/img_tiles.py b/lib/cartopy/io/img_tiles.py index e8381dba2..40fa1c8dc 100644 --- a/lib/cartopy/io/img_tiles.py +++ b/lib/cartopy/io/img_tiles.py @@ -41,7 +41,7 @@ class GoogleWTS(metaclass=ABCMeta): _MAX_THREADS = 24 def __init__(self, desired_tile_form='RGB', - user_agent='CartoPy/' + cartopy.__version__, cache_path=None): + user_agent='CartoPy/' + cartopy.__version__, cache=False): self.imgs = [] self.crs = ccrs.Mercator.GOOGLE self.desired_tile_form = desired_tile_form @@ -49,7 +49,12 @@ def __init__(self, desired_tile_form='RGB', # some providers like osm need a user_agent in the request issue #1341 # osm may reject requests if there are too many of them, in which case # a change of user_agent may fix the issue. - self.cache_path = cache_path + if cache is True: + self.cache_path = cartopy.config["cache_dir"] + elif cache is False: + self.cache_path = None + else: + self.cache_path = cache self.cache = set({}) self._load_cache() @@ -225,7 +230,7 @@ class GoogleTiles(GoogleWTS): def __init__(self, desired_tile_form='RGB', style="street", url=('https://mts0.google.com/vt/lyrs={style}' '@177000000&hl=en&src=api&x={x}&y={y}&z={z}&s=G'), - cache_path=None): + cache=False): """ Parameters ---------- @@ -257,7 +262,7 @@ def __init__(self, desired_tile_form='RGB', style="street", msg = "The '%s' style requires pillow with jpeg decoding support." raise ValueError(msg % self.style) return super().__init__(desired_tile_form=desired_tile_form, - cache_path=cache_path) + cache=cache) def _image_url(self, tile): style_dict = { @@ -332,9 +337,9 @@ class Stamen(GoogleWTS): """ def __init__(self, style='toner', - desired_tile_form='RGB', cache_path=None): + desired_tile_form='RGB', cache=False): super().__init__(desired_tile_form=desired_tile_form, - cache_path=cache_path) + cache=cache) self.style = style def _image_url(self, tile): @@ -367,7 +372,7 @@ class StamenTerrain(Stamen): """ - def __init__(self, cache_path=None): + def __init__(self, cache=False): warnings.warn( "The StamenTerrain class was deprecated in v0.17. " "Please use Stamen('terrain-background') instead.", @@ -378,7 +383,7 @@ def __init__(self, cache_path=None): # No further Stamen subclasses will be accepted as # they can easily be created in user code with Stamen(style_name). return super().__init__(style='terrain-background', - cache_path=cache_path) + cache=cache) class MapboxTiles(GoogleWTS): @@ -388,7 +393,7 @@ class MapboxTiles(GoogleWTS): For terms of service, see https://www.mapbox.com/tos/. """ - def __init__(self, access_token, map_id, cache_path=None): + def __init__(self, access_token, map_id, cache=False): """ Set up a new Mapbox tiles instance. @@ -406,7 +411,7 @@ def __init__(self, access_token, map_id, cache_path=None): """ self.access_token = access_token self.map_id = map_id - super().__init__(cache_path=cache_path) + super().__init__(cache=cache) def _image_url(self, tile): x, y, z = tile @@ -426,7 +431,7 @@ class MapboxStyleTiles(GoogleWTS): For terms of service, see https://www.mapbox.com/tos/. """ - def __init__(self, access_token, username, map_id, cache_path=None): + def __init__(self, access_token, username, map_id, cache=False): """ Set up a new instance to retrieve tiles from a Mapbox style. @@ -449,7 +454,7 @@ def __init__(self, access_token, username, map_id, cache_path=None): self.access_token = access_token self.username = username self.map_id = map_id - super().__init__(cache_path=cache_path) + super().__init__(cache=cache) def _image_url(self, tile): x, y, z = tile @@ -568,7 +573,7 @@ def __init__(self, apikey, layer='Road', desired_tile_form='RGB', - cache_path=None): + cache=False): """ Parameters ---------- @@ -585,7 +590,7 @@ def __init__(self, Defaults to 'RGB'. """ super().__init__(desired_tile_form=desired_tile_form, - cache_path=cache_path) + cache=cache) self.apikey = apikey if layer not in ['Outdoor', 'Road', 'Light', 'Night', 'Leisure']: diff --git a/lib/cartopy/tests/test_img_tiles.py b/lib/cartopy/tests/test_img_tiles.py index f00356135..350d401b6 100644 --- a/lib/cartopy/tests/test_img_tiles.py +++ b/lib/cartopy/tests/test_img_tiles.py @@ -13,6 +13,7 @@ import pytest import shapely.geometry as sgeom +from cartopy import config import cartopy.crs as ccrs import cartopy.io.img_tiles as cimgt @@ -289,11 +290,18 @@ def test_ordnance_survey_get_image(): @pytest.mark.network -def test_cache(tmpdir): - tmpdir_str = tmpdir.strpath +@pytest.mark.parametrize('cache_dir', ["tmpdir", True, False]) +def test_cache(cache_dir, tmpdir): + if cache_dir == "tmpdir": + tmpdir_str = tmpdir.strpath + else: + tmpdir_str = cache_dir + + if cache_dir is True: + config["cache_dir"] = tmpdir.strpath # Fetch tiles and save them in the cache - gt = cimgt.GoogleTiles(cache_path=tmpdir_str) + gt = cimgt.GoogleTiles(cache=tmpdir_str) gt._image_url = types.MethodType(GOOGLE_IMAGE_URL_REPLACEMENT, gt) ll_target_domain = sgeom.box(-10, 50, 10, 60) @@ -302,6 +310,11 @@ def test_cache(tmpdir): img_init, _, _ = gt.image_for_domain(target_domain, 6) + # Do not check the result if the cache is disabled + if cache_dir is False: + assert gt.cache_path is None + return + # Define expected results x_y_z_f_h = [ (30, 18, 6, '30_18_6.npy', '545db25f1aa348ad85e1f437fd0db0d9'), @@ -323,12 +336,12 @@ def test_cache(tmpdir): ] # Check the results - cache_dir = os.path.join(tmpdir_str, "GoogleTiles") - files = [i for i in os.listdir(cache_dir)] + cache_dir_res = os.path.join(gt.cache_path, "GoogleTiles") + files = [i for i in os.listdir(cache_dir_res)] hashes = { f: hashlib.md5( - np.load(os.path.join(cache_dir, f), allow_pickle=True).data + np.load(os.path.join(cache_dir_res, f), allow_pickle=True).data ).hexdigest() for f in files } @@ -342,12 +355,12 @@ def test_cache(tmpdir): # Update images in cache (all white) for f in files: - filename = os.path.join(cache_dir, f) + filename = os.path.join(cache_dir_res, f) img = np.load(filename, allow_pickle=True) img.fill(255) np.save(filename, img, allow_pickle=True) - gt_cache = cimgt.GoogleTiles(cache_path=tmpdir_str) + gt_cache = cimgt.GoogleTiles(cache=tmpdir_str) gt_cache._image_url = types.MethodType( GOOGLE_IMAGE_URL_REPLACEMENT, gt_cache) img_cache, _, _ = gt_cache.image_for_domain(target_domain, 6)