|
1 | 1 | import json
|
2 | 2 | import lzma
|
| 3 | +import threading |
| 4 | + |
3 | 5 | from functools import lru_cache
|
4 | 6 | from pathlib import Path
|
5 | 7 | from typing import Any, Dict, Optional, Tuple
|
@@ -46,19 +48,54 @@ def gbox_css() -> str:
|
46 | 48 | return src.read()
|
47 | 49 |
|
48 | 50 |
|
| 51 | +class _CachedGeoDataFrame: |
| 52 | + _instance = None |
| 53 | + |
| 54 | + # Override in sub-classes |
| 55 | + _lock = threading.Lock() |
| 56 | + _data_url = "" |
| 57 | + |
| 58 | + def __init__(self): |
| 59 | + # Thread safe class-cached dataload |
| 60 | + if self._instance is None: |
| 61 | + with self._lock: |
| 62 | + if self._instance is None: |
| 63 | + self.__class__._instance = self._load_from_url() |
| 64 | + |
| 65 | + def _load_from_url(self): |
| 66 | + # pylint: disable=import-outside-toplevel |
| 67 | + import geopandas as gpd |
| 68 | + |
| 69 | + with catch_warnings(): |
| 70 | + filterwarnings("ignore", category=FutureWarning) |
| 71 | + df = gpd.read_file(self._data_url) |
| 72 | + return df |
| 73 | + |
| 74 | + |
| 75 | +class Countries(_CachedGeoDataFrame): |
| 76 | + """ |
| 77 | + Cache-wrapper around the Natural Earth low-res countries geodataset. |
| 78 | + """ |
| 79 | + |
| 80 | + _lock = threading.Lock() |
| 81 | + _data_url = ( |
| 82 | + "https://naciscdn.org/naturalearth/110m/cultural/ne_110m_admin_0_countries.zip" |
| 83 | + ) |
| 84 | + |
| 85 | + def frame_by_iso3(self, iso3): |
| 86 | + df = self._instance |
| 87 | + return df[df.ISO_A3 == iso3] |
| 88 | + |
| 89 | + |
49 | 90 | def country_geom(iso3: str, crs: MaybeCRS = None) -> Geometry:
|
50 | 91 | """
|
51 | 92 | Extract geometry for a country from geopandas sample data.
|
52 | 93 | """
|
53 | 94 | # pylint: disable=import-outside-toplevel
|
54 |
| - import geopandas as gpd |
55 |
| - |
56 | 95 | from ..converters import from_geopandas
|
57 | 96 |
|
58 |
| - with catch_warnings(): |
59 |
| - filterwarnings("ignore", category=FutureWarning) |
60 |
| - df = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")) |
61 |
| - (gg,) = from_geopandas(df[df.iso_a3 == iso3]) |
| 97 | + countries = Countries() |
| 98 | + (gg,) = from_geopandas(countries.frame_by_iso3(iso3)) |
62 | 99 | crs = norm_crs(crs)
|
63 | 100 | if crs is not None:
|
64 | 101 | gg = gg.to_crs(crs)
|
|
0 commit comments