prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Backport NaturalEarth url change in release 0.18 and 0.19 ?
  It should be great, if possible, to backport the change of NaturalEarth url (done in this [commit](https://github.com/SciTools/cartopy/commit/af814c31829002acd7c1c49ba52cee530c6ac19a) ) in at least releases 0.18 (==> 0.18.1) and 0.19 (==> 0.19.1), and of course to release a new version with this change.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `tools/cartopy_feature_download.py`
  Content:
  ```
  1 #!/usr/bin/env python
  2 # Copyright Cartopy Contributors
  3 #
  4 # This file is part of Cartopy and is released under the LGPL license.
  5 # See COPYING and COPYING.LESSER in the root of the repository for full
  6 # licensing details.
  7 """
  8 This module provides a command-line tool for triggering the download of
  9 the data used by various Feature instances.
  10 
  11 For detail on how to use this tool, execute it with the `-h` option:
  12 
  13     python download.py -h
  14 
  15 """
  16 
  17 import argparse
  18 
  19 from cartopy import config
  20 from cartopy.feature import Feature, GSHHSFeature, NaturalEarthFeature
  21 from cartopy.io import Downloader
  22 
  23 
  24 ALL_SCALES = ('110m', '50m', '10m')
  25 
  26 
  27 FEATURE_DEFN_GROUPS = {
  28     # Only need one GSHHS resolution because they *all* get downloaded
  29     # from one file.
  30     'gshhs': GSHHSFeature(scale='f'),
  31     'physical': (
  32         ('physical', 'coastline', ALL_SCALES),
  33         ('physical', 'land', ALL_SCALES),
  34         ('physical', 'ocean', ALL_SCALES),
  35         ('physical', 'rivers_lake_centerlines', ALL_SCALES),
  36         ('physical', 'lakes', ALL_SCALES),
  37         ('physical', 'geography_regions_polys', ALL_SCALES),
  38         ('physical', 'geography_regions_points', ALL_SCALES),
  39         ('physical', 'geography_marine_polys', ALL_SCALES),
  40         ('physical', 'glaciated_areas', ALL_SCALES)
  41     ),
  42     'cultural': (
  43         ('cultural', 'admin_0_countries', ALL_SCALES),
  44         ('cultural', 'admin_0_countries_lakes', ALL_SCALES),
  45         ('cultural', 'admin_0_sovereignty', ALL_SCALES),
  46         ('cultural', 'admin_0_boundary_lines_land', ALL_SCALES),
  47 
  48         ('cultural', 'urban_areas', ('50m', '10m')),
  49 
  50         ('cultural', 'roads', '10m'),
  51         ('cultural', 'roads_north_america', '10m'),
  52         ('cultural', 'railroads', '10m'),
  53         ('cultural', 'railroads_north_america', '10m'),
  54     ),
  55     'cultural-extra': (
  56         ('cultural', 'admin_0_map_units', '110m'),
  57         ('cultural', 'admin_0_scale_rank', '110m'),
  58         ('cultural', 'admin_0_tiny_countries', '110m'),
  59         ('cultural', 'admin_0_pacific_groupings', '110m'),
  60         ('cultural', 'admin_1_states_provinces', '110m'),
  61         ('cultural', 'admin_1_states_provinces_lines', '110m'),
  62     ),
  63 }
  64 
  65 
  66 def download_features(group_names, dry_run=True):
  67     for group_name in group_names:
  68         feature_defns = FEATURE_DEFN_GROUPS[group_name]
  69         if isinstance(feature_defns, Feature):
  70             feature = feature_defns
  71             level = list(feature._levels)[0]
  72             downloader = Downloader.from_config(('shapefiles', 'gshhs',
  73                                                  feature._scale, level))
  74             format_dict = {'config': config, 'scale': feature._scale,
  75                            'level': level}
  76             if dry_run:
  77                 print('URL: {}'.format(downloader.url(format_dict)))
  78             else:
  79                 downloader.path(format_dict)
  80                 geoms = list(feature.geometries())
  81                 print('Feature {} length: {}'.format(feature, len(geoms)))
  82         else:
  83             for category, name, scales in feature_defns:
  84                 if not isinstance(scales, tuple):
  85                     scales = (scales,)
  86                 for scale in scales:
  87                     downloader = Downloader.from_config(('shapefiles',
  88                                                          'natural_earth',
  89                                                          scale, category,
  90                                                          name))
  91                     feature = NaturalEarthFeature(category, name, scale)
  92                     format_dict = {'config': config, 'category': category,
  93                                    'name': name, 'resolution': scale}
  94                     if dry_run:
  95                         print('URL: {}'.format(downloader.url(format_dict)))
  96                     else:
  97                         downloader.path(format_dict)
  98                         geoms = list(feature.geometries())
  99                         print('Feature {}, {}, {} length: {}'
  100                               ''.format(category, name, scale, len(geoms)))
  101 
  102 
  103 if __name__ == '__main__':
  104     parser = argparse.ArgumentParser(description='Download feature datasets.')
  105     parser.add_argument('group_names', nargs='+',
  106                         choices=FEATURE_DEFN_GROUPS,
  107                         metavar='GROUP_NAME',
  108                         help='Feature group name: %(choices)s')
  109     parser.add_argument('--output', '-o',
  110                         help='save datasets in the specified directory '
  111                              '(default: user cache directory)')
  112     parser.add_argument('--dry-run',
  113                         help='just print the URLs to download',
  114                         action='store_true')
  115     parser.add_argument('--ignore-repo-data', action='store_true',
  116                         help='ignore existing repo data when downloading')
  117     args = parser.parse_args()
  118 
  119     if args.output:
  120         config['pre_existing_data_dir'] = args.output
  121         config['data_dir'] = args.output
  122     if args.ignore_repo_data:
  123         config['repo_data_dir'] = config['data_dir']
  124     download_features(args.group_names, dry_run=args.dry_run)
  125
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/tools/cartopy_feature_download.py b/tools/cartopy_feature_download.py
  --- a/tools/cartopy_feature_download.py
  +++ b/tools/cartopy_feature_download.py
  @@ -10,19 +10,24 @@
   
   For detail on how to use this tool, execute it with the `-h` option:
   
  -    python download.py -h
  +    python cartopy_feature_download.py -h
   
   """
   
   import argparse
  +import pathlib
   
   from cartopy import config
   from cartopy.feature import Feature, GSHHSFeature, NaturalEarthFeature
  -from cartopy.io import Downloader
  +from cartopy.io import Downloader, DownloadWarning
   
   
   ALL_SCALES = ('110m', '50m', '10m')
   
  +# See https://github.com/SciTools/cartopy/pull/1833
  +URL_TEMPLATE = ('https://naturalearth.s3.amazonaws.com/{resolution}_'
  +                '{category}/ne_{resolution}_{name}.zip')
  +SHP_NE_SPEC = ('shapefiles', 'natural_earth')
   
   FEATURE_DEFN_GROUPS = {
       # Only need one GSHHS resolution because they *all* get downloaded
  @@ -114,11 +119,28 @@
                           action='store_true')
       parser.add_argument('--ignore-repo-data', action='store_true',
                           help='ignore existing repo data when downloading')
  +    parser.add_argument('--no-warn',
  +                        action='store_true',
  +                        help='ignore cartopy "DownloadWarning" warnings')
       args = parser.parse_args()
   
       if args.output:
  -        config['pre_existing_data_dir'] = args.output
  -        config['data_dir'] = args.output
  +        target_dir = pathlib.Path(args.output).expanduser().resolve()
  +        target_dir.mkdir(parents=True, exist_ok=True)
  +        config['pre_existing_data_dir'] = target_dir
  +        config['data_dir'] = target_dir
       if args.ignore_repo_data:
           config['repo_data_dir'] = config['data_dir']
  +    if args.no_warn:
  +        import warnings
  +        warnings.filterwarnings('ignore', category=DownloadWarning)
  +
  +    # Enforce use of stable AWS endpoint, regardless of cartopy version.
  +    # In doing so, this allows users to download this script and execute it
  +    # with any version of cartopy, thus taking advantage of the stable AWS
  +    # endpoint.
  +    # This removes the need to backport the associated fix
  +    # https://github.com/SciTools/cartopy/pull/1833.
  +    config['downloaders'][SHP_NE_SPEC].url_template = URL_TEMPLATE
  +
       download_features(args.group_names, dry_run=args.dry_run)
  
verification_info: {"golden_diff": "diff --git a/tools/cartopy_feature_download.py b/tools/cartopy_feature_download.py\n--- a/tools/cartopy_feature_download.py\n+++ b/tools/cartopy_feature_download.py\n@@ -10,19 +10,24 @@\n \n For detail on how to use this tool, execute it with the `-h` option:\n \n-    python download.py -h\n+    python cartopy_feature_download.py -h\n \n \"\"\"\n \n import argparse\n+import pathlib\n \n from cartopy import config\n from cartopy.feature import Feature, GSHHSFeature, NaturalEarthFeature\n-from cartopy.io import Downloader\n+from cartopy.io import Downloader, DownloadWarning\n \n \n ALL_SCALES = ('110m', '50m', '10m')\n \n+# See https://github.com/SciTools/cartopy/pull/1833\n+URL_TEMPLATE = ('https://naturalearth.s3.amazonaws.com/{resolution}_'\n+                '{category}/ne_{resolution}_{name}.zip')\n+SHP_NE_SPEC = ('shapefiles', 'natural_earth')\n \n FEATURE_DEFN_GROUPS = {\n     # Only need one GSHHS resolution because they *all* get downloaded\n@@ -114,11 +119,28 @@\n                         action='store_true')\n     parser.add_argument('--ignore-repo-data', action='store_true',\n                         help='ignore existing repo data when downloading')\n+    parser.add_argument('--no-warn',\n+                        action='store_true',\n+                        help='ignore cartopy \"DownloadWarning\" warnings')\n     args = parser.parse_args()\n \n     if args.output:\n-        config['pre_existing_data_dir'] = args.output\n-        config['data_dir'] = args.output\n+        target_dir = pathlib.Path(args.output).expanduser().resolve()\n+        target_dir.mkdir(parents=True, exist_ok=True)\n+        config['pre_existing_data_dir'] = target_dir\n+        config['data_dir'] = target_dir\n     if args.ignore_repo_data:\n         config['repo_data_dir'] = config['data_dir']\n+    if args.no_warn:\n+        import warnings\n+        warnings.filterwarnings('ignore', category=DownloadWarning)\n+\n+    # Enforce use of stable AWS endpoint, regardless of cartopy version.\n+    # In doing so, this allows users to download this script and execute it\n+    # with any version of cartopy, thus taking advantage of the stable AWS\n+    # endpoint.\n+    # This removes the need to backport the associated fix\n+    # https://github.com/SciTools/cartopy/pull/1833.\n+    config['downloaders'][SHP_NE_SPEC].url_template = URL_TEMPLATE\n+\n     download_features(args.group_names, dry_run=args.dry_run)\n", "issue": "Backport NaturalEarth url change in release 0.18 and 0.19 ?\nIt should be great, if possible, to backport the change of NaturalEarth url (done in this [commit](https://github.com/SciTools/cartopy/commit/af814c31829002acd7c1c49ba52cee530c6ac19a) ) in at least releases 0.18 (==> 0.18.1) and 0.19 (==> 0.19.1), and of course to release a new version with this change.\n", "before_files": [{"content": "#!/usr/bin/env python\n# Copyright Cartopy Contributors\n#\n# This file is part of Cartopy and is released under the LGPL license.\n# See COPYING and COPYING.LESSER in the root of the repository for full\n# licensing details.\n\"\"\"\nThis module provides a command-line tool for triggering the download of\nthe data used by various Feature instances.\n\nFor detail on how to use this tool, execute it with the `-h` option:\n\n    python download.py -h\n\n\"\"\"\n\nimport argparse\n\nfrom cartopy import config\nfrom cartopy.feature import Feature, GSHHSFeature, NaturalEarthFeature\nfrom cartopy.io import Downloader\n\n\nALL_SCALES = ('110m', '50m', '10m')\n\n\nFEATURE_DEFN_GROUPS = {\n    # Only need one GSHHS resolution because they *all* get downloaded\n    # from one file.\n    'gshhs': GSHHSFeature(scale='f'),\n    'physical': (\n        ('physical', 'coastline', ALL_SCALES),\n        ('physical', 'land', ALL_SCALES),\n        ('physical', 'ocean', ALL_SCALES),\n        ('physical', 'rivers_lake_centerlines', ALL_SCALES),\n        ('physical', 'lakes', ALL_SCALES),\n        ('physical', 'geography_regions_polys', ALL_SCALES),\n        ('physical', 'geography_regions_points', ALL_SCALES),\n        ('physical', 'geography_marine_polys', ALL_SCALES),\n        ('physical', 'glaciated_areas', ALL_SCALES)\n    ),\n    'cultural': (\n        ('cultural', 'admin_0_countries', ALL_SCALES),\n        ('cultural', 'admin_0_countries_lakes', ALL_SCALES),\n        ('cultural', 'admin_0_sovereignty', ALL_SCALES),\n        ('cultural', 'admin_0_boundary_lines_land', ALL_SCALES),\n\n        ('cultural', 'urban_areas', ('50m', '10m')),\n\n        ('cultural', 'roads', '10m'),\n        ('cultural', 'roads_north_america', '10m'),\n        ('cultural', 'railroads', '10m'),\n        ('cultural', 'railroads_north_america', '10m'),\n    ),\n    'cultural-extra': (\n        ('cultural', 'admin_0_map_units', '110m'),\n        ('cultural', 'admin_0_scale_rank', '110m'),\n        ('cultural', 'admin_0_tiny_countries', '110m'),\n        ('cultural', 'admin_0_pacific_groupings', '110m'),\n        ('cultural', 'admin_1_states_provinces', '110m'),\n        ('cultural', 'admin_1_states_provinces_lines', '110m'),\n    ),\n}\n\n\ndef download_features(group_names, dry_run=True):\n    for group_name in group_names:\n        feature_defns = FEATURE_DEFN_GROUPS[group_name]\n        if isinstance(feature_defns, Feature):\n            feature = feature_defns\n            level = list(feature._levels)[0]\n            downloader = Downloader.from_config(('shapefiles', 'gshhs',\n                                                 feature._scale, level))\n            format_dict = {'config': config, 'scale': feature._scale,\n                           'level': level}\n            if dry_run:\n                print('URL: {}'.format(downloader.url(format_dict)))\n            else:\n                downloader.path(format_dict)\n                geoms = list(feature.geometries())\n                print('Feature {} length: {}'.format(feature, len(geoms)))\n        else:\n            for category, name, scales in feature_defns:\n                if not isinstance(scales, tuple):\n                    scales = (scales,)\n                for scale in scales:\n                    downloader = Downloader.from_config(('shapefiles',\n                                                         'natural_earth',\n                                                         scale, category,\n                                                         name))\n                    feature = NaturalEarthFeature(category, name, scale)\n                    format_dict = {'config': config, 'category': category,\n                                   'name': name, 'resolution': scale}\n                    if dry_run:\n                        print('URL: {}'.format(downloader.url(format_dict)))\n                    else:\n                        downloader.path(format_dict)\n                        geoms = list(feature.geometries())\n                        print('Feature {}, {}, {} length: {}'\n                              ''.format(category, name, scale, len(geoms)))\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(description='Download feature datasets.')\n    parser.add_argument('group_names', nargs='+',\n                        choices=FEATURE_DEFN_GROUPS,\n                        metavar='GROUP_NAME',\n                        help='Feature group name: %(choices)s')\n    parser.add_argument('--output', '-o',\n                        help='save datasets in the specified directory '\n                             '(default: user cache directory)')\n    parser.add_argument('--dry-run',\n                        help='just print the URLs to download',\n                        action='store_true')\n    parser.add_argument('--ignore-repo-data', action='store_true',\n                        help='ignore existing repo data when downloading')\n    args = parser.parse_args()\n\n    if args.output:\n        config['pre_existing_data_dir'] = args.output\n        config['data_dir'] = args.output\n    if args.ignore_repo_data:\n        config['repo_data_dir'] = config['data_dir']\n    download_features(args.group_names, dry_run=args.dry_run)\n", "path": "tools/cartopy_feature_download.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# Copyright Cartopy Contributors\n#\n# This file is part of Cartopy and is released under the LGPL license.\n# See COPYING and COPYING.LESSER in the root of the repository for full\n# licensing details.\n\"\"\"\nThis module provides a command-line tool for triggering the download of\nthe data used by various Feature instances.\n\nFor detail on how to use this tool, execute it with the `-h` option:\n\n    python cartopy_feature_download.py -h\n\n\"\"\"\n\nimport argparse\nimport pathlib\n\nfrom cartopy import config\nfrom cartopy.feature import Feature, GSHHSFeature, NaturalEarthFeature\nfrom cartopy.io import Downloader, DownloadWarning\n\n\nALL_SCALES = ('110m', '50m', '10m')\n\n# See https://github.com/SciTools/cartopy/pull/1833\nURL_TEMPLATE = ('https://naturalearth.s3.amazonaws.com/{resolution}_'\n                '{category}/ne_{resolution}_{name}.zip')\nSHP_NE_SPEC = ('shapefiles', 'natural_earth')\n\nFEATURE_DEFN_GROUPS = {\n    # Only need one GSHHS resolution because they *all* get downloaded\n    # from one file.\n    'gshhs': GSHHSFeature(scale='f'),\n    'physical': (\n        ('physical', 'coastline', ALL_SCALES),\n        ('physical', 'land', ALL_SCALES),\n        ('physical', 'ocean', ALL_SCALES),\n        ('physical', 'rivers_lake_centerlines', ALL_SCALES),\n        ('physical', 'lakes', ALL_SCALES),\n        ('physical', 'geography_regions_polys', ALL_SCALES),\n        ('physical', 'geography_regions_points', ALL_SCALES),\n        ('physical', 'geography_marine_polys', ALL_SCALES),\n        ('physical', 'glaciated_areas', ALL_SCALES)\n    ),\n    'cultural': (\n        ('cultural', 'admin_0_countries', ALL_SCALES),\n        ('cultural', 'admin_0_countries_lakes', ALL_SCALES),\n        ('cultural', 'admin_0_sovereignty', ALL_SCALES),\n        ('cultural', 'admin_0_boundary_lines_land', ALL_SCALES),\n\n        ('cultural', 'urban_areas', ('50m', '10m')),\n\n        ('cultural', 'roads', '10m'),\n        ('cultural', 'roads_north_america', '10m'),\n        ('cultural', 'railroads', '10m'),\n        ('cultural', 'railroads_north_america', '10m'),\n    ),\n    'cultural-extra': (\n        ('cultural', 'admin_0_map_units', '110m'),\n        ('cultural', 'admin_0_scale_rank', '110m'),\n        ('cultural', 'admin_0_tiny_countries', '110m'),\n        ('cultural', 'admin_0_pacific_groupings', '110m'),\n        ('cultural', 'admin_1_states_provinces', '110m'),\n        ('cultural', 'admin_1_states_provinces_lines', '110m'),\n    ),\n}\n\n\ndef download_features(group_names, dry_run=True):\n    for group_name in group_names:\n        feature_defns = FEATURE_DEFN_GROUPS[group_name]\n        if isinstance(feature_defns, Feature):\n            feature = feature_defns\n            level = list(feature._levels)[0]\n            downloader = Downloader.from_config(('shapefiles', 'gshhs',\n                                                 feature._scale, level))\n            format_dict = {'config': config, 'scale': feature._scale,\n                           'level': level}\n            if dry_run:\n                print('URL: {}'.format(downloader.url(format_dict)))\n            else:\n                downloader.path(format_dict)\n                geoms = list(feature.geometries())\n                print('Feature {} length: {}'.format(feature, len(geoms)))\n        else:\n            for category, name, scales in feature_defns:\n                if not isinstance(scales, tuple):\n                    scales = (scales,)\n                for scale in scales:\n                    downloader = Downloader.from_config(('shapefiles',\n                                                         'natural_earth',\n                                                         scale, category,\n                                                         name))\n                    feature = NaturalEarthFeature(category, name, scale)\n                    format_dict = {'config': config, 'category': category,\n                                   'name': name, 'resolution': scale}\n                    if dry_run:\n                        print('URL: {}'.format(downloader.url(format_dict)))\n                    else:\n                        downloader.path(format_dict)\n                        geoms = list(feature.geometries())\n                        print('Feature {}, {}, {} length: {}'\n                              ''.format(category, name, scale, len(geoms)))\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(description='Download feature datasets.')\n    parser.add_argument('group_names', nargs='+',\n                        choices=FEATURE_DEFN_GROUPS,\n                        metavar='GROUP_NAME',\n                        help='Feature group name: %(choices)s')\n    parser.add_argument('--output', '-o',\n                        help='save datasets in the specified directory '\n                             '(default: user cache directory)')\n    parser.add_argument('--dry-run',\n                        help='just print the URLs to download',\n                        action='store_true')\n    parser.add_argument('--ignore-repo-data', action='store_true',\n                        help='ignore existing repo data when downloading')\n    parser.add_argument('--no-warn',\n                        action='store_true',\n                        help='ignore cartopy \"DownloadWarning\" warnings')\n    args = parser.parse_args()\n\n    if args.output:\n        target_dir = pathlib.Path(args.output).expanduser().resolve()\n        target_dir.mkdir(parents=True, exist_ok=True)\n        config['pre_existing_data_dir'] = target_dir\n        config['data_dir'] = target_dir\n    if args.ignore_repo_data:\n        config['repo_data_dir'] = config['data_dir']\n    if args.no_warn:\n        import warnings\n        warnings.filterwarnings('ignore', category=DownloadWarning)\n\n    # Enforce use of stable AWS endpoint, regardless of cartopy version.\n    # In doing so, this allows users to download this script and execute it\n    # with any version of cartopy, thus taking advantage of the stable AWS\n    # endpoint.\n    # This removes the need to backport the associated fix\n    # https://github.com/SciTools/cartopy/pull/1833.\n    config['downloaders'][SHP_NE_SPEC].url_template = URL_TEMPLATE\n\n    download_features(args.group_names, dry_run=args.dry_run)\n", "path": "tools/cartopy_feature_download.py"}]}