Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions contextily/place.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ class Place(object):
`rasterio` and all bands are loaded into the basemap.
IMPORTANT: tiles are assumed to be in the Spherical Mercator
projection (EPSG:3857), unless the `crs` keyword is specified.
headers : dict[str, str] or None
[Optional. Default: None]
Headers to include with requests to the tile server.
geocoder : geopy.geocoders
[Optional. Default: geopy.geocoders.Nominatim()] Geocoder method to process `search`

Expand Down Expand Up @@ -77,12 +80,14 @@ def __init__(
path=None,
zoom_adjust=None,
source=None,
headers: dict[str, str] | None = None,
geocoder=gp.geocoders.Nominatim(user_agent=_default_user_agent),
):
self.path = path
if source is None:
source = providers.OpenStreetMap.HOT
self.source = source
self.headers = headers
self.zoom_adjust = zoom_adjust

# Get geocoded values
Expand Down Expand Up @@ -119,6 +124,8 @@ def _get_map(self):
kwargs = {"ll": True}
if self.source is not None:
kwargs["source"] = self.source
if self.headers is not None:
kwargs["headers"] = self.headers

try:
if isinstance(self.path, str):
Expand Down
5 changes: 5 additions & 0 deletions contextily/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def add_basemap(
ax,
zoom=ZOOM,
source=None,
headers=None,
interpolation=INTERPOLATION,
attribution=None,
attribution_size=ATTRIBUTION_SIZE,
Expand Down Expand Up @@ -50,6 +51,9 @@ def add_basemap(
the file is read with `rasterio` and all bands are loaded into the basemap.
IMPORTANT: tiles are assumed to be in the Spherical Mercator projection
(EPSG:3857), unless the `crs` keyword is specified.
headers : dict or None
[Optional. Default: None]
Headers to include with requests to the tile server.
interpolation : str
[Optional. Default='bilinear'] Interpolation algorithm to be passed
to `imshow`. See `matplotlib.pyplot.imshow` for further details.
Expand Down Expand Up @@ -138,6 +142,7 @@ def add_basemap(
top,
zoom=zoom,
source=source,
headers=headers,
ll=False,
zoom_adjust=zoom_adjust,
)
Expand Down
29 changes: 23 additions & 6 deletions contextily/tile.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def bounds2raster(
path,
zoom="auto",
source=None,
headers: dict[str, str] | None = None,
ll=False,
wait=0,
max_retries=2,
Expand Down Expand Up @@ -106,6 +107,9 @@ def bounds2raster(
`rasterio` and all bands are loaded into the basemap.
IMPORTANT: tiles are assumed to be in the Spherical Mercator
projection (EPSG:3857), unless the `crs` keyword is specified.
headers : dict[str, str] or None
[Optional. Default: None]
Headers to include with requests to the tile server.
ll : Boolean
[Optional. Default: False] If True, `w`, `s`, `e`, `n` are
assumed to be lon/lat as opposed to Spherical Mercator.
Expand Down Expand Up @@ -136,6 +140,9 @@ def bounds2raster(
extent : tuple
Bounding box [minX, maxX, minY, maxY] of the returned image
"""
if headers is None:
headers = {}

if not ll:
# Convert w, s, e, n into lon/lat
w, s = _sm2ll(w, s)
Expand All @@ -148,6 +155,7 @@ def bounds2raster(
n,
zoom=zoom,
source=source,
headers=headers,
ll=True,
n_connections=n_connections,
use_cache=use_cache,
Expand Down Expand Up @@ -187,6 +195,7 @@ def bounds2img(
n,
zoom="auto",
source=None,
headers: dict[str, str] | None = None,
ll=False,
wait=0,
max_retries=2,
Expand Down Expand Up @@ -219,6 +228,9 @@ def bounds2img(
`rasterio` and all bands are loaded into the basemap.
IMPORTANT: tiles are assumed to be in the Spherical Mercator
projection (EPSG:3857), unless the `crs` keyword is specified.
headers : dict[str, str] or None
[Optional. Default: None]
Headers to include with requests to the tile server.
ll : Boolean
[Optional. Default: False] If True, `w`, `s`, `e`, `n` are
assumed to be lon/lat as opposed to Spherical Mercator.
Expand Down Expand Up @@ -253,6 +265,9 @@ def bounds2img(
extent : tuple
Bounding box [minX, maxX, minY, maxY] of the returned image
"""
if headers is None:
headers = {}

if not ll:
# Convert w, s, e, n into lon/lat
w, s = _sm2ll(w, s)
Expand Down Expand Up @@ -281,7 +296,7 @@ def bounds2img(
)
fetch_tile_fn = memory.cache(_fetch_tile) if use_cache else _fetch_tile
arrays = Parallel(n_jobs=n_connections, prefer=preferred_backend)(
delayed(fetch_tile_fn)(tile_url, wait, max_retries) for tile_url in tile_urls
delayed(fetch_tile_fn)(tile_url, wait, max_retries, headers) for tile_url in tile_urls
)
# merge downloaded tiles
merged, extent = _merge_tiles(tiles, arrays)
Expand Down Expand Up @@ -309,8 +324,8 @@ def _process_source(source):
return provider


def _fetch_tile(tile_url, wait, max_retries):
array = _retryer(tile_url, wait, max_retries)
def _fetch_tile(tile_url, wait, max_retries, headers: dict[str, str]):
array = _retryer(tile_url, wait, max_retries, headers)
return array


Expand Down Expand Up @@ -428,7 +443,7 @@ def _warper(img, transform, s_crs, t_crs, resampling):
return img, bounds, transform


def _retryer(tile_url, wait, max_retries):
def _retryer(tile_url, wait, max_retries, headers: dict[str, str]):
"""
Retry a url many times in attempt to get a tile and read the image

Expand All @@ -443,13 +458,15 @@ def _retryer(tile_url, wait, max_retries):
max_retries : int
total number of rejected requests allowed before contextily
will stop trying to fetch more tiles from a rate-limited API.
headers: dict[str, str]
headers to include with request.

Returns
-------
array of the tile
"""
try:
request = requests.get(tile_url, headers={"user-agent": USER_AGENT})
request = requests.get(tile_url, headers={"user-agent": USER_AGENT, **headers})
request.raise_for_status()
with io.BytesIO(request.content) as image_stream:
image = Image.open(image_stream).convert("RGBA")
Expand All @@ -468,7 +485,7 @@ def _retryer(tile_url, wait, max_retries):
if max_retries > 0:
time.sleep(wait)
max_retries -= 1
request = _retryer(tile_url, wait, max_retries)
request = _retryer(tile_url, wait, max_retries, headers)
else:
raise requests.HTTPError("Connection reset by peer too many times. "
f"Last message was: {request.status_code} "
Expand Down
Loading
Loading