Skip to content

Commit 577729d

Browse files
committed
Allow version specific NE
1 parent 1a36e4e commit 577729d

File tree

5 files changed

+26
-15
lines changed

5 files changed

+26
-15
lines changed

lib/cartopy/feature/__init__.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,13 @@ class NaturalEarthFeature(Feature):
235235
"""
236236
A simple interface to Natural Earth shapefiles.
237237
238-
See https://www.naturalearthdata.com/
238+
See https://www.naturalearthdata.com/ for an overview of the data
239+
and https://github.com/nvkelso/natural-earth-vector/releases for recent
240+
version information.
239241
240242
"""
241243

242-
def __init__(self, category, name, scale, **kwargs):
244+
def __init__(self, category, name, scale, version=None, **kwargs):
243245
"""
244246
Parameters
245247
----------
@@ -251,6 +253,8 @@ def __init__(self, category, name, scale, **kwargs):
251253
The dataset scale, i.e. one of '10m', '50m', or '110m',
252254
or Scaler object. Dataset scales correspond to 1:10,000,000,
253255
1:50,000,000, and 1:110,000,000 respectively.
256+
version: optional
257+
The specific dataset version to use, e.g. '5.1.0'.
254258
255259
Other Parameters
256260
----------------
@@ -261,6 +265,7 @@ def __init__(self, category, name, scale, **kwargs):
261265
super().__init__(cartopy.crs.PlateCarree(), **kwargs)
262266
self.category = category
263267
self.name = name
268+
self.version = version
264269

265270
# Cast the given scale to a (constant) Scaler if a string is passed.
266271
if isinstance(scale, str):
@@ -286,11 +291,12 @@ def geometries(self):
286291
Returns an iterator of (shapely) geometries for this feature.
287292
288293
"""
289-
key = (self.name, self.category, self.scale)
294+
key = (self.name, self.category, self.scale, self.version)
290295
if key not in _NATURAL_EARTH_GEOM_CACHE:
291296
path = shapereader.natural_earth(resolution=self.scale,
292297
category=self.category,
293-
name=self.name)
298+
name=self.name,
299+
version=self.version)
294300
geometries = tuple(shapereader.Reader(path).geometries())
295301
_NATURAL_EARTH_GEOM_CACHE[key] = geometries
296302
else:
@@ -321,7 +327,7 @@ def with_scale(self, new_scale):
321327
322328
"""
323329
return NaturalEarthFeature(self.category, self.name, new_scale,
324-
**self.kwargs)
330+
self.version, **self.kwargs)
325331

326332

327333
class GSHHSFeature(Feature):

lib/cartopy/io/shapereader.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,12 @@ def records(self):
275275
"""
276276

277277

278-
def natural_earth(resolution='110m', category='physical', name='coastline'):
278+
def natural_earth(resolution='110m', category='physical',
279+
name='coastline', version=None):
279280
"""
280281
Return the path to the requested natural earth shapefile,
281-
downloading and unzipping if necessary.
282+
downloading and unzipping if necessary. If version is not specified,
283+
the latest available version will be downloaded.
282284
283285
To identify valid components for this function, either browse
284286
NaturalEarthData.com, or if you know what you are looking for, go to
@@ -299,10 +301,11 @@ def natural_earth(resolution='110m', category='physical', name='coastline'):
299301
# get hold of the Downloader (typically a NEShpDownloader instance)
300302
# which we can then simply call its path method to get the appropriate
301303
# shapefile (it will download if necessary)
304+
_version_string = "" if version is None else "{version}/"
302305
ne_downloader = Downloader.from_config(('shapefiles', 'natural_earth',
303-
resolution, category, name))
304-
format_dict = {'config': config, 'category': category,
305-
'name': name, 'resolution': resolution}
306+
resolution, category, name))
307+
format_dict = {'config': config, 'category': category, 'name': name,
308+
'resolution': resolution, 'version': _version_string}
306309
return ne_downloader.path(format_dict)
307310

308311

@@ -321,7 +324,7 @@ class NEShpDownloader(Downloader):
321324
# Define the NaturalEarth URL template. Shapefiles are hosted on AWS since
322325
# 2021: https://github.com/nvkelso/natural-earth-vector/issues/445
323326
_NE_URL_TEMPLATE = ('https://naturalearth.s3.amazonaws.com/'
324-
'{resolution}_{category}/ne_{resolution}_{name}.zip')
327+
'{version}{resolution}_{category}/ne_{resolution}_{name}.zip')
325328

326329
def __init__(self,
327330
url_template=_NE_URL_TEMPLATE,
@@ -386,7 +389,7 @@ def default_downloader():
386389
ne_{resolution}_{name}.shp
387390
388391
"""
389-
default_spec = ('shapefiles', 'natural_earth', '{category}',
392+
default_spec = ('shapefiles', 'natural_earth', '{category}', '{version}',
390393
'ne_{resolution}_{name}.shp')
391394
ne_path_template = str(
392395
Path('{config[data_dir]}').joinpath(*default_spec))

lib/cartopy/tests/io/test_downloaders.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ def test_natural_earth_downloader(tmp_path):
139139
# isn't important - it is the download mechanism that is.
140140
format_dict = {'category': 'physical',
141141
'name': 'rivers_lake_centerlines',
142-
'resolution': '110m'}
142+
'resolution': '110m',
143+
'version': ''}
143144

144145
dnld_item = NEShpDownloader(target_path_template=shp_path_template)
145146

lib/cartopy/tests/mpl/test_features.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def test_natural_earth():
3737
@pytest.mark.mpl_image_compare(filename='natural_earth_custom.png')
3838
def test_natural_earth_custom():
3939
ax = plt.axes(projection=ccrs.PlateCarree())
40-
feature = cfeature.NaturalEarthFeature('physical', 'coastline', '50m',
40+
feature = cfeature.NaturalEarthFeature('physical', 'coastline', '50m', '5.1.0',
4141
edgecolor='black',
4242
facecolor='none')
4343
ax.add_feature(feature)

lib/cartopy/tests/test_shapereader.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ class TestRivers:
8383
def setup_class(self):
8484
RIVERS_PATH = shp.natural_earth(resolution='110m',
8585
category='physical',
86-
name='rivers_lake_centerlines')
86+
name='rivers_lake_centerlines',
87+
version='5.0.0')
8788
self.reader = shp.Reader(RIVERS_PATH)
8889
names = [record.attributes['name'] for record in self.reader.records()]
8990
# Choose a nice small river

0 commit comments

Comments
 (0)