diff --git a/geemap/common.py b/geemap/common.py
index 116f1e2c67..83df132c43 100644
--- a/geemap/common.py
+++ b/geemap/common.py
@@ -24,6 +24,7 @@
import json
import math
import os
+import pathlib
import re
import shutil
import subprocess
@@ -53,6 +54,7 @@
import plotly.express as px
import requests
+from . import colormaps
from .coreutils import *
from . import coreutils
@@ -1883,7 +1885,7 @@ def check_git_install() -> bool:
"""Checks if Git is installed.
Returns:
- bool: Returns True if Git is installed, otherwise returns False.
+ Returns True if Git is installed, otherwise returns False.
"""
cmd = "git --version"
output = os.popen(cmd).read()
@@ -2339,7 +2341,7 @@ def edit_download_html(
basename = os.path.basename(filename)
- # Create and assign html to widget
+ # Create and assign html to widget.
html = '{title}'
htmlWidget.value = html.format(
payload=payload, title=title + basename, filename=basename
@@ -9234,7 +9236,7 @@ def extract_pixel_values(
def list_vars(var_type=None):
- """Lists all defined avariables.
+ """Lists all defined variables.
Args:
var_type (object, optional): The object type of variables to list. Defaults to None.
@@ -11020,21 +11022,20 @@ def bbox_to_gdf(bbox, crs="EPSG:4326"):
return gdf
-def check_dir(dir_path, make_dirs=True):
+def check_dir(dir_path: str, make_dirs: bool = True) -> str:
"""Checks if a directory exists and creates it if it does not.
Args:
- dir_path ([str): The path to the directory.
- make_dirs (bool, optional): Whether to create the directory if it does not exist. Defaults to True.
+ dir_path: The path to the directory.
+ make_dirs: Whether to create the directory if it does not exist. Defaults to True.
Raises:
FileNotFoundError: If the directory could not be found.
TypeError: If the input directory path is not a string.
Returns:
- str: The path to the directory.
+ The path to the directory.
"""
-
if isinstance(dir_path, str):
if dir_path.startswith("~"):
dir_path = os.path.expanduser(dir_path)
@@ -11052,19 +11053,19 @@ def check_dir(dir_path, make_dirs=True):
raise TypeError("The provided directory path must be a string.")
-def check_file_path(file_path, make_dirs=True):
+def check_file_path(file_path: str, make_dirs: bool = True) -> str:
"""Gets the absolute file path.
Args:
- file_path ([str): The path to the file.
- make_dirs (bool, optional): Whether to create the directory if it does not exist. Defaults to True.
+ file_path: The path to the file.
+ make_dirs: Whether to create the directory if it does not exist. Defaults to True.
Raises:
FileNotFoundError: If the directory could not be found.
TypeError: If the input directory path is not a string.
Returns:
- str: The absolute path to the file.
+ The absolute path to the file.
"""
if isinstance(file_path, str):
if file_path.startswith("~"):
@@ -14054,14 +14055,14 @@ def arc_add_layer(url, name=None, shown=True, opacity=1.0):
layer.transparency = 100 - (opacity * 100)
-def arc_zoom_to_extent(xmin, ymin, xmax, ymax):
+def arc_zoom_to_extent(xmin: float, ymin: float, xmax: float, ymax: float) -> None:
"""Zoom to an extent in ArcGIS Pro.
Args:
- xmin (float): The minimum x value of the extent.
- ymin (float): The minimum y value of the extent.
- xmax (float): The maximum x value of the extent.
- ymax (float): The maximum y value of the extent.
+ xmin: The minimum x value of the extent.
+ ymin: The minimum y value of the extent.
+ xmax: The maximum x value of the extent.
+ ymax: The maximum y value of the extent.
"""
if is_arcpy():
import arcpy
@@ -14078,32 +14079,27 @@ def arc_zoom_to_extent(xmin, ymin, xmax, ymax):
)
)
- # if isinstance(zoom, int):
- # scale = 156543.04 * math.cos(0) / math.pow(2, zoom)
- # view.camera.scale = scale # Not working properly
-
-def get_current_year():
- """Get the current year.
+def get_current_year() -> int:
+ """Returns the current year."""
+ return datetime.date.today().year
- Returns:
- int: The current year.
- """
- today = datetime.date.today()
- return today.year
-
-def html_to_gradio(html, width="100%", height="500px", **kwargs):
+def html_to_gradio(
+ html: str | list[str], width: str = "100%", height: str = "500px", **kwargs
+) -> str:
"""Converts the map to an HTML string that can be used in Gradio. Removes unsupported elements, such as
attribution and any code blocks containing functions. See https://github.com/gradio-app/gradio/issues/3190
Args:
- width (str, optional): The width of the map. Defaults to '100%'.
- height (str, optional): The height of the map. Defaults to '500px'.
+ html: The HTML string or list of strings to convert.
+ width: The width of the map. Defaults to '100%'.
+ height: The height of the map. Defaults to '500px'.
Returns:
- str: The HTML string to use in Gradio.
+ The HTML string to use in Gradio.
"""
+ del kwargs # Unused.
if isinstance(width, int):
width = f"{width}px"
@@ -14175,11 +14171,11 @@ def image_client(image, **kwargs):
return client
-def image_center(image, **kwargs):
+def image_center(image: str, **kwargs):
"""Get the center of an image.
Args:
- image (str): The input image filepath or URL.
+ image: The input image filepath or URL.
Returns:
tuple: A tuple of (latitude, longitude).
@@ -14193,17 +14189,17 @@ def image_center(image, **kwargs):
return client.center()
-def image_bounds(image, **kwargs):
+def image_bounds(image: str, **kwargs) -> list[tuple[float, float]]:
"""Get the bounds of an image.
Args:
- image (str): The input image filepath or URL.
+ image: The input image filepath or URL.
Returns:
- list: A list of bounds in the form of [(south, west), (north, east)].
+ A list of bounds in the form of [(south, west), (north, east)].
"""
-
image_check(image)
+
if isinstance(image, str):
_, client = get_local_tile_layer(image, return_client=True, **kwargs)
else:
@@ -14212,14 +14208,14 @@ def image_bounds(image, **kwargs):
return [(bounds[0], bounds[2]), (bounds[1], bounds[3])]
-def image_metadata(image, **kwargs):
+def image_metadata(image: str, **kwargs) -> dict[str, Any]:
"""Get the metadata of an image.
Args:
- image (str): The input image filepath or URL.
+ image: The input image filepath or URL.
Returns:
- dict: A dictionary of image metadata.
+ A dictionary of image metadata.
"""
image_check(image)
@@ -14230,16 +14226,15 @@ def image_metadata(image, **kwargs):
return client.metadata()
-def image_bandcount(image, **kwargs):
+def image_bandcount(image: str, **kwargs) -> int:
"""Get the number of bands in an image.
Args:
- image (str): The input image filepath or URL.
+ image: The input image filepath or URL.
Returns:
- int: The number of bands in the image.
+ The number of bands in the image.
"""
-
image_check(image)
if isinstance(image, str):
@@ -14249,14 +14244,14 @@ def image_bandcount(image, **kwargs):
return len(client.metadata()["bands"])
-def image_size(image, **kwargs):
+def image_size(image: str, **kwargs) -> tuple[int, int]:
"""Get the size (width, height) of an image.
Args:
- image (str): The input image filepath or URL.
+ image: The input image filepath or URL.
Returns:
- tuple: A tuple of (width, height).
+ A tuple of (width, height).
"""
image_check(image)
@@ -14269,14 +14264,14 @@ def image_size(image, **kwargs):
return metadata["sourceSizeX"], metadata["sourceSizeY"]
-def image_projection(image, **kwargs):
+def image_projection(image: str, **kwargs) -> str:
"""Get the projection of an image.
Args:
- image (str): The input image filepath or URL.
+ image: The input image filepath or URL.
Returns:
- str: The projection of the image.
+ The projection of the image.
"""
image_check(image)
@@ -14287,14 +14282,13 @@ def image_projection(image, **kwargs):
return client.metadata()["Projection"]
-def image_set_crs(image, epsg):
+def image_set_crs(image: str, epsg: int) -> None:
"""Define the CRS of an image.
Args:
- image (str): The input image filepath
- epsg (int): The EPSG code of the CRS to set.
+ image: The input image filepath
+ epsg: The EPSG code of the CRS to set.
"""
-
from rasterio.crs import CRS
import rasterio
@@ -14302,14 +14296,14 @@ def image_set_crs(image, epsg):
rds.crs = CRS.from_epsg(epsg)
-def image_geotransform(image, **kwargs):
+def image_geotransform(image: str, **kwargs) -> list[float]:
"""Get the geotransform of an image.
Args:
- image (str): The input image filepath or URL.
+ image: The input image filepath or URL.
Returns:
- list: A list of geotransform values.
+ A list of geotransform values.
"""
image_check(image)
@@ -14320,14 +14314,14 @@ def image_geotransform(image, **kwargs):
return client.metadata()["GeoTransform"]
-def image_resolution(image, **kwargs):
+def image_resolution(image: str, **kwargs) -> float:
"""Get the resolution of an image.
Args:
- image (str): The input image filepath or URL.
+ image: The input image filepath or URL.
Returns:
- float: The resolution of the image.
+ The resolution of the image.
"""
image_check(image)
@@ -14338,23 +14332,20 @@ def image_resolution(image, **kwargs):
return client.metadata()["GeoTransform"][1]
-def find_files(input_dir, ext=None, fullpath=True, recursive=True):
- """Find files in a directory.
+def find_files(
+ input_dir: str,
+ ext: str | None = None,
+ fullpath: bool = True,
+ recursive: bool = True,
+) -> list[str]:
+ """Return a list of matching files in a directory.
Args:
- input_dir (str): The input directory.
- ext (str, optional): The file extension to match. Defaults to None.
- fullpath (bool, optional): Whether to return the full path. Defaults to True.
- recursive (bool, optional): Whether to search recursively. Defaults to True.
-
- Returns:
- list: A list of matching files.
+ input_dir: The input directory.
+ ext: The file extension to match. Defaults to None.
+ fullpath: Whether to return the full path. Defaults to True.
+ recursive: Whether to search recursively. Defaults to True.
"""
-
- from pathlib import Path
-
- files = []
-
if ext is None:
ext = "*"
else:
@@ -14362,44 +14353,48 @@ def find_files(input_dir, ext=None, fullpath=True, recursive=True):
ext = f"*.{ext}"
+ files: list[str]
+
+ path = pathlib.Path(input_dir)
if recursive:
if fullpath:
- files = [str(path.joinpath()) for path in Path(input_dir).rglob(ext)]
+ files = [str(path.joinpath()) for path in path.rglob(ext)]
else:
- files = [str(path.name) for path in Path(input_dir).rglob(ext)]
+ files = [str(path.name) for path in path.rglob(ext)]
else:
if fullpath:
- files = [str(path.joinpath()) for path in Path(input_dir).glob(ext)]
+ files = [str(path.joinpath()) for path in path.glob(ext)]
else:
- files = [path.name for path in Path(input_dir).glob(ext)]
+ files = [path.name for path in path.glob(ext)]
return files
-def zoom_level_resolution(zoom, latitude=0):
+def zoom_level_resolution(zoom: int, latitude: float = 0.0) -> float:
"""Returns the approximate pixel scale based on zoom level and latutude.
- See https://blogs.bing.com/maps/2006/02/25/map-control-zoom-levels-gt-resolution
+
+ See https://blogs.bing.com/maps/2006/02/25/map-control-zoom-levels-gt-resolution
Args:
- zoom (int): The zoom level.
- latitude (float, optional): The latitude. Defaults to 0.
+ zoom: The zoom level.
+ latitude: The latitude. Defaults to 0.0.
Returns:
- float: Map resolution in meters.
+ Map resolution in meters.
"""
resolution = 156543.04 * math.cos(latitude) / math.pow(2, zoom)
return abs(resolution)
-def lnglat_to_meters(longitude, latitude):
+def lnglat_to_meters(longitude: float, latitude: float) -> tuple[float, float]:
"""coordinate conversion between lat/lon in decimal degrees to web mercator
Args:
- longitude (float): The longitude.
- latitude (float): The latitude.
+ longitude: The longitude.
+ latitude: The latitude.
Returns:
- tuple: A tuple of (x, y) in meters.
+ A tuple of (x, y) in meters.
"""
origin_shift = np.pi * 6378137
easting = longitude * origin_shift / 180.0
@@ -14417,18 +14412,18 @@ def lnglat_to_meters(longitude, latitude):
else:
northing = -20048966
- return (easting, northing)
+ return easting, northing
-def meters_to_lnglat(x, y):
+def meters_to_lnglat(x: float, y: float) -> tuple[float, float]:
"""coordinate conversion between web mercator to lat/lon in decimal degrees
Args:
- x (float): The x coordinate.
- y (float): The y coordinate.
+ x: The x coordinate.
+ y: The y coordinate.
Returns:
- tuple: A tuple of (longitude, latitude) in decimal degrees.
+ A tuple of (longitude, latitude) in decimal degrees.
"""
origin_shift = np.pi * 6378137
longitude = (x / origin_shift) * 180.0
@@ -14436,19 +14431,18 @@ def meters_to_lnglat(x, y):
latitude = (
180 / np.pi * (2 * np.arctan(np.exp(latitude * np.pi / 180.0)) - np.pi / 2.0)
)
- return (longitude, latitude)
+ return longitude, latitude
-def bounds_to_xy_range(bounds):
+def bounds_to_xy_range(bounds) -> tuple[tuple[float, float], tuple[float, float]]:
"""Convert bounds to x and y range to be used as input to bokeh map.
Args:
bounds (list): A list of bounds in the form [(south, west), (north, east)] or [xmin, ymin, xmax, ymax].
Returns:
- tuple: A tuple of (x_range, y_range).
+ A tuple of (x_range, y_range).
"""
-
if isinstance(bounds, tuple):
bounds = list(bounds)
elif not isinstance(bounds, list):
@@ -14459,25 +14453,28 @@ def bounds_to_xy_range(bounds):
elif len(bounds) == 2:
south, west = bounds[0]
north, east = bounds[1]
+ else:
+ raise ValueError("bounds must be a list of length 4 or 2")
xmin, ymin = lnglat_to_meters(west, south)
xmax, ymax = lnglat_to_meters(east, north)
- x_range = (xmin, xmax)
- y_range = (ymin, ymax)
+ x_range = xmin, xmax
+ y_range = ymin, ymax
return x_range, y_range
-def center_zoom_to_xy_range(center, zoom):
+def center_zoom_to_xy_range(
+ center: tuple[float, float], zoom: int
+) -> tuple[tuple[float, float], tuple[float, float]]:
"""Convert center and zoom to x and y range to be used as input to bokeh map.
Args:
- center (tuple): A tuple of (latitude, longitude).
- zoom (int): The zoom level.
+ center: A tuple of (latitude, longitude).
+ zoom: The zoom level.
Returns:
- tuple: A tuple of (x_range, y_range).
+ A tuple of (x_range, y_range).
"""
-
if isinstance(center, tuple) or isinstance(center, list):
pass
else:
@@ -14509,16 +14506,17 @@ def center_zoom_to_xy_range(center, zoom):
return x_range, y_range
-def get_geometry_coords(row, geom, coord_type, shape_type, mercator=False):
- """
- Returns the coordinates ('x' or 'y') of edges of a Polygon exterior.
+def get_geometry_coords(
+ row, geom: str, coord_type: str, shape_type: str, mercator: bool = False
+) -> float | list[float]:
+ """Returns the coordinates ('x' or 'y') of edges of a Polygon exterior.
- :param: (GeoPandas Series) row : The row of each of the GeoPandas DataFrame.
- :param: (str) geom : The column name.
- :param: (str) coord_type : Whether it's 'x' or 'y' coordinate.
- :param: (str) shape_type
+ row (GeoPandas Series): The row of each of the GeoPandas DataFrame.
+ geom: The column name.
+ coord_type: Whether it's 'x' or 'y' coordinate.
+ shape_type: The shape type of the geometry.
+ mercator: Whether to convert to Web Mercator coordinates.
"""
-
# Parse the exterior of the coordinate
if shape_type.lower() in ["polygon", "multipolygon"]:
exterior = row[geom].geoms[0].exterior
@@ -14566,19 +14564,22 @@ def get_geometry_coords(row, geom, coord_type, shape_type, mercator=False):
return coords
-def landsat_scaling(image, thermal_bands=True, apply_fmask=False):
- """Apply scaling factors to a Landsat image. See an example at
+def landsat_scaling(
+ image, thermal_bands: bool = True, apply_fmask: bool = False
+) -> ee.Image:
+ """Apply scaling factors to a Landsat image.
+
+ Example
https://developers.google.com/earth-engine/datasets/catalog/LANDSAT_LC09_C02_T1_L2
Args:
image (ee.Image): The input Landsat image.
- thermal_bands (bool, optional): Whether to apply scaling to thermal bands. Defaults to True.
- apply_fmask (bool, optional): Whether to apply Fmask cloud mask. Defaults to False.
+ thermal_bands: Whether to apply scaling to thermal bands. Defaults to True.
+ apply_fmask: Whether to apply Fmask cloud mask. Defaults to False.
Returns:
- ee.Image: The scaled Landsat image.
+ The scaled Landsat image.
"""
-
# Apply the scaling factors to the appropriate bands.
opticalBands = image.select("SR_B.").multiply(0.0000275).add(-0.2)
if thermal_bands:
@@ -14638,7 +14639,6 @@ def tms_to_geotiff(
"""
from PIL import Image
-
from osgeo import gdal, osr
gdal.UseExceptions()
@@ -14915,7 +14915,6 @@ def ee_to_geotiff(
crs (str, optional): The CRS of the output image. Defaults to "EPSG:3857".
to_cog (bool, optional): Whether to convert the image to Cloud Optimized GeoTIFF. Defaults to False.
quiet (bool, optional): Whether to hide the download progress bar. Defaults to False.
-
"""
image = None
@@ -14985,19 +14984,21 @@ def ee_to_geotiff(
tms_to_geotiff(output, bbox, zoom, resolution, url, crs, to_cog, quiet, **kwargs)
-def create_grid(ee_object, scale, proj=None):
+def create_grid(
+ ee_object: ee.Image | ee.Geometry | ee.FeatureCollection,
+ scale: float | Any,
+ proj: str | Any | None = None,
+) -> ee.FeatureCollection:
"""Create a grid covering an Earth Engine object.
Args:
- ee_object (ee.Image | ee.Geometry | ee.FeatureCollection): The Earth Engine object.
- scale (float): The grid cell size.
- proj (str, optional): The projection. Defaults to None.
-
+ ee_object: The Earth Engine object.
+ scale: The grid cell size.
+ proj: The projection. Defaults to None.
Returns:
- ee.FeatureCollection: The grid as a feature collection.
+ The grid as a feature collection.
"""
-
if isinstance(ee_object, ee.FeatureCollection) or isinstance(ee_object, ee.Image):
geometry = ee_object.geometry()
elif isinstance(ee_object, ee.Geometry):
@@ -15015,13 +15016,10 @@ def create_grid(ee_object, scale, proj=None):
return grid
-def jslink_slider_label(slider, label):
- """Link a slider and a label.
-
- Args:
- slider (ipywidgets.IntSlider | ipywidgets.FloatSlider): The slider.
- label (ipywidgets.Label): The label.
- """
+def jslink_slider_label(
+ slider: widgets.IntSlider | widgets.FloatSlider, label: widgets.Label
+) -> None:
+ """Link a slider and a label."""
def update_label(change):
if change["name"]:
@@ -15030,14 +15028,14 @@ def update_label(change):
slider.observe(update_label, "value")
-def check_basemap(basemap):
+def check_basemap(basemap: str) -> str:
"""Check Google basemaps
Args:
- basemap (str): The basemap name.
+ basemap: The basemap name.
Returns:
- str: The basemap name.
+ The basemap name.
"""
if isinstance(basemap, str):
map_dict = {
@@ -15073,39 +15071,33 @@ def get_ee_token():
def geotiff_to_image(image: str, output: str) -> None:
- """
- Converts a GeoTIFF file to a JPEG/PNG image.
+ """Converts a GeoTIFF file to a JPEG/PNG image.
Args:
- image (str): The path to the input GeoTIFF file.
- output (str): The path to save the output JPEG/PNG file.
+ image: The path to the input GeoTIFF file.
+ output: The path to save the output JPEG/PNG file.
Returns:
None
"""
-
import rasterio
from PIL import Image
- # Open the GeoTIFF file
with rasterio.open(image) as dataset:
- # Read the image data
data = dataset.read()
- # Convert the image data to 8-bit format (assuming it's not already)
+ # Convert the image data to 8-bit format (assuming it's not already).
if dataset.dtypes[0] != "uint8":
data = (data / data.max() * 255).astype("uint8")
- # Convert the image data to RGB format if it's a single band image
+ # Convert the image data to RGB format if it's a single band image.
if dataset.count == 1:
data = data.squeeze()
data = data.reshape((1, data.shape[0], data.shape[1]))
data = data.repeat(3, axis=0)
- # Create a PIL Image object from the image data
image = Image.fromarray(data.transpose(1, 2, 0))
- # Save the image as a JPEG file
image.save(output)
@@ -15120,8 +15112,7 @@ def xee_to_image(
quiet: bool = False,
**kwargs,
) -> None:
- """
- Convert xarray Dataset to georeferenced images.
+ """Convert xarray Dataset to georeferenced images.
Args:
xds (xr.Dataset): The xarray Dataset to convert to images.
@@ -15142,7 +15133,6 @@ def xee_to_image(
Raises:
ValueError: If the number of filenames doesn't match the number of time steps in the Dataset.
-
"""
try:
import rioxarray
@@ -15466,49 +15456,41 @@ def array_to_image(
dst.write(array[:, :, i], i + 1)
-def is_studio_lab():
- """Check if the current notebook is running on Studio Lab.
-
- Returns:
- bool: True if the notebook is running on Studio Lab.
- """
-
+def is_studio_lab() -> bool:
+ """Returns True if the notebook is running on Studio Lab."""
import psutil
- output = psutil.Process().parent().cmdline()
+ parent = psutil.Process().parent()
+ assert parent # For pytype.
+ output = parent.cmdline()
- on_studio_lab = False
for item in output:
if "studiolab/bin" in item:
- on_studio_lab = True
- return on_studio_lab
-
+ return True
+ return False
-def is_on_aws():
- """Check if the current notebook is running on AWS.
-
- Returns:
- bool: True if the notebook is running on AWS.
- """
+def is_on_aws() -> bool:
+ """Returns True if the notebook is running on AWS."""
import psutil
- output = psutil.Process().parent().cmdline()
+ parent = psutil.Process().parent()
+ assert parent # For pytype.
+ output = parent.cmdline()
- on_aws = False
for item in output:
if item.endswith(".aws") or "ec2-user" in item:
- on_aws = True
- return on_aws
+ return True
+ return False
-def xarray_to_raster(dataset, filename: str, **kwargs: dict[str, Any]) -> None:
+def xarray_to_raster(dataset, filename: str, **kwargs) -> None:
"""Convert an xarray Dataset to a raster file.
Args:
dataset (xr.Dataset): The input xarray Dataset to be converted.
- filename (str): The output filename for the raster file.
- **kwargs (dict[str, Any]): Additional keyword arguments passed to the `rio.to_raster()` method.
+ filename: The output filename for the raster file.
+ **kwargs: Additional keyword arguments passed to the `rio.to_raster()` method.
See https://corteva.github.io/rioxarray/stable/examples/convert_to_raster.html for more info.
Returns:
@@ -15541,17 +15523,16 @@ def xarray_to_raster(dataset, filename: str, **kwargs: dict[str, Any]) -> None:
def hex_to_rgba(hex_color: str, opacity: float) -> str:
- """
- Converts a hex color code to an RGBA color string.
+ """Converts a hex color code to an RGBA color string.
Args:
- hex_color (str): The hex color code to convert. It can be in the format
- '#RRGGBB' or 'RRGGBB'.
- opacity (float): The opacity value for the RGBA color. It should be a
+ hex_color: The hex color code to convert. It can be in the format
+ '#RRGGBB' or 'RRGGBB'. Does not support alpha or 'RGB'.
+ opacity: The opacity value for the RGBA color. It should be a
float between 0.0 (completely transparent) and 1.0 (completely opaque).
Returns:
- str: The RGBA color string in the format 'rgba(R, G, B, A)'.
+ The RGBA color string in the format 'rgba(R, G, B, A)'.
"""
hex_color = hex_color.lstrip("#")
h_len = len(hex_color)
@@ -15578,11 +15559,10 @@ def replace_top_level_hyphens(d: dict | Any) -> dict | Any:
def replace_hyphens_in_keys(d: dict | list | Any) -> dict | list | Any:
- """
- Recursively replaces hyphens with underscores in dictionary keys.
+ """Recursively replaces hyphens with underscores in dictionary keys.
Args:
- d (dict | list | Any): The input dictionary, list or any other data type.
+ d: The input dictionary, list, or any other data type.
Returns:
The modified dictionary or list with keys having hyphens replaced with underscores,
@@ -15597,26 +15577,22 @@ def replace_hyphens_in_keys(d: dict | list | Any) -> dict | list | Any:
def remove_port_from_string(data: str) -> str:
- """
- Removes the port number from all URLs in the given string.
+ """Removes the port number from all URLs in the given string.
Args::
- data (str): The input string containing URLs.
+ data: The input string containing URLs.
Returns:
- str: The string with port numbers removed from all URLs.
+ The string with port numbers removed from all URLs.
"""
- # Regular expression to match URLs with port numbers
+ # Match URLs with port numbers.
url_with_port_pattern = re.compile(r"(http://[\d\w.]+):\d+")
- # Function to remove the port from the matched URLs
+ # Function to remove the port from the matched URLs.
def remove_port(match):
return match.group(1)
- # Substitute the URLs with ports removed
- result = url_with_port_pattern.sub(remove_port, data)
-
- return result
+ return url_with_port_pattern.sub(remove_port, data)
def pmtiles_metadata(input_file: str) -> dict[str, str | int | list[str]]:
@@ -15655,7 +15631,7 @@ def pmtiles_metadata(input_file: str) -> dict[str, str | int | list[str]]:
return
# ignore uri parameters when checking file suffix
- if not urlparse(input_file).path.endswith(".pmtiles"):
+ if not urllib.parse.urlparse(input_file).path.endswith(".pmtiles"):
raise ValueError("Input file must be a .pmtiles file.")
header = pmtiles_header(input_file)
@@ -15698,7 +15674,6 @@ def pmtiles_style(
circle_radius: int = 5,
line_width: int = 1,
attribution: str = "PMTiles",
- **kwargs,
):
"""
Generates a Mapbox style JSON for rendering PMTiles data.
@@ -15741,9 +15716,7 @@ def pmtiles_style(
elif isinstance(cmap, list):
palette = cmap
else:
- from .colormaps import get_palette
-
- palette = ["#" + c for c in get_palette(cmap, n_class)]
+ palette = ["#" + c for c in colormaps.get_palette(cmap, n_class)]
n_class = len(palette)
@@ -15815,7 +15788,7 @@ def pmtiles_style(
return style
-def check_html_string(html_string):
+def check_html_string(html_string: str) -> str:
"""Check if an HTML string contains local images and convert them to base64.
Args:
@@ -15828,12 +15801,11 @@ def check_html_string(html_string):
img_regex = r'
]+src\s*=\s*["\']([^"\':]+)["\'][^>]*>'
for match in re.findall(img_regex, html_string):
- with open(match, "rb") as img_file:
- img_data = img_file.read()
- base64_data = base64.b64encode(img_data).decode("utf-8")
- html_string = html_string.replace(
- f'src="{match}"',
- 'src="data:image/png;base64,' + base64_data + '"',
- )
+ img_data = pathlib.Path(match).read_bytes()
+ base64_data = base64.b64encode(img_data).decode("utf-8")
+ html_string = html_string.replace(
+ 'src="{}"'.format(match),
+ 'src="data:image/png;base64,' + base64_data + '"',
+ )
return html_string