diff --git a/environment.yml b/environment.yml index 8c5d5d3b3..8f1e46b9f 100644 --- a/environment.yml +++ b/environment.yml @@ -14,6 +14,7 @@ dependencies: - pyshp>=2.3 - pyproj>=3.3.1 - packaging>=21 + - urllib3>=2.3 # The testing label has the proper version of freetype included - conda-forge/label/testing::matplotlib-base>=3.6 diff --git a/lib/cartopy/io/__init__.py b/lib/cartopy/io/__init__.py index 0a6a2c6dd..81bfa3e5b 100644 --- a/lib/cartopy/io/__init__.py +++ b/lib/cartopy/io/__init__.py @@ -13,9 +13,10 @@ import collections from pathlib import Path import string -from urllib.request import urlopen import warnings +from urllib3 import request + from cartopy import config @@ -227,6 +228,7 @@ def acquire_resource(self, target_path, format_dict): response = self._urlopen(url) target_path.write_bytes(response.read()) + response.release_conn() return target_path @@ -238,7 +240,7 @@ def _urlopen(self, url): """ warnings.warn(f'Downloading: {url}', DownloadWarning) - return urlopen(url) + return request('GET', url, preload_content=False) @staticmethod def from_config(specification, config_dict=None): diff --git a/lib/cartopy/io/img_tiles.py b/lib/cartopy/io/img_tiles.py index a9e92af38..ffa990a9b 100644 --- a/lib/cartopy/io/img_tiles.py +++ b/lib/cartopy/io/img_tiles.py @@ -202,7 +202,8 @@ def _image_url(self, tile): pass def get_image(self, tile): - from urllib.request import HTTPError, Request, URLError, urlopen + from urllib3 import request + from urllib3.exceptions import HTTPError if self.cache_path is not None: filename = "_".join([str(i) for i in tile]) + ".npy" @@ -215,13 +216,13 @@ def get_image(self, tile): else: url = self._image_url(tile) try: - request = Request(url, headers={"User-Agent": self.user_agent}) - fh = urlopen(request) - im_data = io.BytesIO(fh.read()) - fh.close() + r = request('GET', url, headers={"User-Agent": self.user_agent}, + preload_content=False) + im_data = io.BytesIO(r.read()) + r.release_conn() img = Image.open(im_data) - except (HTTPError, URLError) as err: + except HTTPError as err: print(err) img = Image.fromarray(np.full((256, 256, 3), (250, 250, 250), dtype=np.uint8)) diff --git a/lib/cartopy/io/ogc_clients.py b/lib/cartopy/io/ogc_clients.py index 4e463c0b0..613f06059 100644 --- a/lib/cartopy/io/ogc_clients.py +++ b/lib/cartopy/io/ogc_clients.py @@ -19,7 +19,6 @@ import io import math from pathlib import Path -from urllib.parse import urlparse import warnings import weakref from xml.etree import ElementTree @@ -27,6 +26,7 @@ import numpy as np from PIL import Image import shapely.geometry as sgeom +from urllib3.util import parse_url import cartopy @@ -753,7 +753,7 @@ def __init__(self, service, features, getfeature_extra_kwargs=None): # agroenvgeo.data.inra.fr from full address # http://mapserver.gis.umn.edu/mapserver # or https://agroenvgeo.data.inra.fr:443/geoserver/wfs - self.url = urlparse(service).hostname + self.url = parse_url(service).hostname # WebFeatureService of owslib service = WebFeatureService(service) else: diff --git a/lib/cartopy/io/shapereader.py b/lib/cartopy/io/shapereader.py index 704b29244..7f426284b 100644 --- a/lib/cartopy/io/shapereader.py +++ b/lib/cartopy/io/shapereader.py @@ -30,10 +30,10 @@ import io import itertools from pathlib import Path -from urllib.error import HTTPError import shapefile import shapely.geometry as sgeom +from urllib3.exceptions import HTTPError from cartopy import config from cartopy.io import Downloader diff --git a/lib/cartopy/io/srtm.py b/lib/cartopy/io/srtm.py index 1c88d1de5..0506adccc 100644 --- a/lib/cartopy/io/srtm.py +++ b/lib/cartopy/io/srtm.py @@ -401,10 +401,11 @@ def _create_srtm_mask(resolution, filename=None): # dependencies of cartopy. from bs4 import BeautifulSoup if filename is None: - from urllib.request import urlopen + from urllib3 import request url = SRTMDownloader._SRTM_BASE_URL.format(resolution=resolution) - with urlopen(url) as f: - html = f.read() + with request('GET', url, preload_content=False) as r: + html = r.read() + r.release_conn() else: html = Path(filename).read_text() diff --git a/pyproject.toml b/pyproject.toml index 7018e09eb..1385216d3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,6 +51,7 @@ dependencies = [ "packaging>=21", "pyshp>=2.3", "pyproj>=3.3.1", + "urllib3>=2.3" ] dynamic = ["version"]