gee-community/geemap

adding support type hinting for geemap

slowy07 opened this issue · 6 comments

Description

type hinting in Python allows you to indicate the anticipated types of variables, function parameters, and return values. It serves as a means to provide suggestions or annotations regarding the desired data types to be utilized in your code. Although type hints are not enforced during runtime, they offer valuable insights to developers, static type checkers, and code analysis tools.

example type hinting on function and variable

def calculation(num_first: int, num_second: int) -> int:
 return num_first + num_second
phi: float = 3.14
name: str = "geemap"

type hints enhance code readability, enhance documentation quality, and enable static type checking tools to identify possible errors and enhance code reliability. They are not mandatory in Python and do not impact the runtime behavior of the code.

Source code

type hinting was implemented on some function but not applied for all. for example we can find on
geemap/report.py

import scooby
from typing import Optional


class Report(scooby.Report):
    def __init__(
        self,
        additional: Optional[dict] = None,
        ncol: int = 3,
        text_width: int = 80,
        sort: bool = False,
    ):
        """Initiate a scooby.Report instance."""
        core = [
            "geemap",
            "ee",
            "ipyleaflet",
            "folium",
            "jupyterlab",
            "notebook",
            "ipyevents",
        ]
        optional = ["geopandas", "localtileserver"]

        scooby.Report.__init__(
            self,
            additional=additional,
            core=core,
            optional=optional,
            ncol=ncol,
            text_width=text_width,
            sort=sort

The statement from __future__ import annotations is used in Python to enable more advanced Type Hinting features. In Python 3.7 and below, Type Hinting only supports the use of strings in type annotations, such as def my_function(param: str) -> int. However, by using the from __future__ import annotations statement at the beginning of your code, you can use type annotations as normal expressions, such as def my_function(param: str) -> int.

i think, by removing the unnecessaryif conditions for checking the modulo of the coordinates seems good. cause in Python, when applying the modulo operator % to a number, the result will be zero if the number is already divisible by the divisor. Therefore, the conditions can be omitted, and the calculations can be performed directly.

geemap/geemap/cartoee.py

here's if can build more simple and more efficiency

def _buffer_box(bbox: list[float], interval: float) -> tuple[float, float, float, float]:
    """Helper function to buffer a bounding box to the nearest multiple of interval

    args:
        bbox (list[float]): list of float values specifying coordinates, expects order to be [W,E,S,N]
        interval (float): float specifying multiple at which to buffer coordianates to

    returns:
        extent (tuple[float]): returns tuple of buffered coordinates rounded to interval in order of [W,E,S,N]
    """
    xmin = bbox[0] - (bbox[0] % interval)
    xmax = bbox[1] + (interval - (bbox[1] % interval))
    ymin = bbox[2] - (bbox[2] % interval)
    ymax = bbox[3] + (interval - (bbox[3] % interval))

    return xmin, xmax, ymin, ymax
giswqs commented

Good suggestion. Ideally, we want to have type hints for all functions and classes. I haven't had time to work on this yet. Contributions are welcome.

excuse me sir @giswqs ,sorry for mention, i got some miss documentation on function local_tile_pixel_value on common.py

def local_tile_pixel_value(
    lon,
    lat,
    tile_client,
    verbose=True,
    **kwargs,
):
    """Get pixel value from COG.

    Args:
        lon (float): Longitude of the pixel.
        lat (float): Latitude of the pixel.
        url (str): HTTP URL to a COG, e.g., 'https://opendata.digitalglobe.com/events/california-fire-2020/pre-event/2018-02-16/pine-gulch-fire20/1030010076004E00.tif'
        bidx (str, optional): Dataset band indexes (e.g bidx=1, bidx=1&bidx=2&bidx=3). Defaults to None.
        titiler_endpoint (str, optional): Titiler endpoint, e.g., "https://titiler.xyz", "planetary-computer", "pc". Defaults to None.
        verbose (bool, optional): Print status messages. Defaults to True.

    Returns:
        list: A dictionary of band info.
    """

    r = tile_client.pixel(lat, lon, units="EPSG:4326", **kwargs)
    if "bands" in r:
        return r["bands"]
    else:
        if verbose:
            print("No pixel value found.")
        return None

where docstring arguments are different from parameter

giswqs commented

Thank you for reporting. Please feel free to fix it as you see fit. Thanks

adding information on function IS_GCS to

"""
Checks if a shapefile is in a geographic coordinate system (GCS).

    Args:
        in_shp (str): Path to the input shapefile.

    Returns:
        bool: True if the shapefile is in a GCS, False otherwise.

    Raises:
        FileNotFoundError: If the input shapefile could not be found.
        TypeError: If the input shapefile is invalid.
"""

close issue, reference from #1565