Skip to content

common module

The common module contains common functions and classes used by the other modules.

check_qgis()

Check if QGIS is available and raise an error if not.

Exceptions:

Type Description
ImportError

If QGIS libraries are not available.

Source code in qgis_map/common.py
def check_qgis() -> None:
    """Check if QGIS is available and raise an error if not.

    Raises:
        ImportError: If QGIS libraries are not available.
    """
    if not is_qgis_available():
        raise ImportError(
            "QGIS libraries are not available. "
            "Please run this code within QGIS or install PyQGIS."
        )

download_file(url, output_path=None, overwrite=False, **kwargs)

Download a file from a URL.

Parameters:

Name Type Description Default
url str

The URL to download from.

required
output_path Optional[str]

The output file path. If None, uses a temp file.

None
overwrite bool

Whether to overwrite existing files. Defaults to False.

False
**kwargs

Additional keyword arguments for urllib.request.urlretrieve.

{}

Returns:

Type Description
str

The path to the downloaded file.

Exceptions:

Type Description
Exception

If the download fails.

Source code in qgis_map/common.py
def download_file(
    url: str,
    output_path: Optional[str] = None,
    overwrite: bool = False,
    **kwargs,
) -> str:
    """Download a file from a URL.

    Args:
        url: The URL to download from.
        output_path: The output file path. If None, uses a temp file.
        overwrite: Whether to overwrite existing files. Defaults to False.
        **kwargs: Additional keyword arguments for urllib.request.urlretrieve.

    Returns:
        The path to the downloaded file.

    Raises:
        Exception: If the download fails.
    """
    import urllib.request
    import tempfile

    if output_path is None:
        suffix = os.path.splitext(url.split("?")[0])[1]
        with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp:
            output_path = tmp.name

    if os.path.exists(output_path) and not overwrite:
        return output_path

    try:
        urllib.request.urlretrieve(url, output_path)
        return output_path
    except Exception as e:
        raise Exception(f"Failed to download {url}: {e}")

get_color_ramp(name, n_colors=5, reverse=False)

Get QGIS color ramp by name.

Parameters:

Name Type Description Default
name str

Color ramp name (e.g., "Spectral", "YlOrRd", "RdYlGn").

required
n_colors int

Number of colors in the ramp. Defaults to 5.

5
reverse bool

Whether to reverse the color ramp. Defaults to False.

False

Returns:

Type Description
Any

QgsColorRamp object, or None if not available.

Exceptions:

Type Description
ImportError

If QGIS is not available.

Source code in qgis_map/common.py
def get_color_ramp(
    name: str,
    n_colors: int = 5,
    reverse: bool = False,
) -> Any:
    """Get QGIS color ramp by name.

    Args:
        name: Color ramp name (e.g., "Spectral", "YlOrRd", "RdYlGn").
        n_colors: Number of colors in the ramp. Defaults to 5.
        reverse: Whether to reverse the color ramp. Defaults to False.

    Returns:
        QgsColorRamp object, or None if not available.

    Raises:
        ImportError: If QGIS is not available.
    """
    try:
        from qgis.core import QgsStyle, QgsGradientColorRamp, QgsColorRampShader
    except ImportError:
        raise ImportError("QGIS libraries required for color ramps")

    # Get default style
    style = QgsStyle.defaultStyle()

    # Try to get color ramp by name
    color_ramp = style.colorRamp(name)

    if color_ramp is None:
        # If not found, try common variations
        variations = [
            name,
            name.lower(),
            name.upper(),
            name.title(),
        ]

        for variant in variations:
            color_ramp = style.colorRamp(variant)
            if color_ramp:
                break

    # If still not found, return a default gradient
    if color_ramp is None:
        print(f"Color ramp '{name}' not found, using default gradient")
        color_ramp = QgsGradientColorRamp()

    # Reverse if requested
    if reverse and hasattr(color_ramp, "invert"):
        color_ramp.invert()

    return color_ramp

get_file_extension(filepath)

Get the file extension from a filepath.

Parameters:

Name Type Description Default
filepath str

The file path.

required

Returns:

Type Description
str

The file extension (lowercase, without the dot).

Source code in qgis_map/common.py
def get_file_extension(filepath: str) -> str:
    """Get the file extension from a filepath.

    Args:
        filepath: The file path.

    Returns:
        The file extension (lowercase, without the dot).
    """
    return os.path.splitext(filepath)[1].lower().lstrip(".")

get_sample_data(name='countries')

Get a path to sample data.

Parameters:

Name Type Description Default
name str

The name of the sample dataset. Options: - "countries": Natural Earth countries - "cities": Natural Earth populated places - "rivers": Natural Earth rivers

'countries'

Returns:

Type Description
str

The path to the sample data file.

Source code in qgis_map/common.py
def get_sample_data(name: str = "countries") -> str:
    """Get a path to sample data.

    Args:
        name: The name of the sample dataset. Options:
            - "countries": Natural Earth countries
            - "cities": Natural Earth populated places
            - "rivers": Natural Earth rivers

    Returns:
        The path to the sample data file.
    """
    samples = {
        "countries": "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_110m_admin_0_countries.geojson",
        "cities": "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_110m_populated_places.geojson",
        "rivers": "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_110m_rivers_lake_centerlines.geojson",
    }

    if name not in samples:
        raise ValueError(
            f"Unknown sample data: {name}. Options: {list(samples.keys())}"
        )

    url = samples[name]
    return download_file(url)

hello_world()

Prints "Hello World!" to the console.

Source code in qgis_map/common.py
def hello_world():
    """Prints "Hello World!" to the console."""
    print("Hello World!")

hex_to_rgb(hex_color)

Convert a hex color string to RGB tuple.

Parameters:

Name Type Description Default
hex_color str

A hex color string (e.g., "#ff0000" or "ff0000").

required

Returns:

Type Description
Tuple[int, int, int]

A tuple of (R, G, B) values.

Source code in qgis_map/common.py
def hex_to_rgb(hex_color: str) -> Tuple[int, int, int]:
    """Convert a hex color string to RGB tuple.

    Args:
        hex_color: A hex color string (e.g., "#ff0000" or "ff0000").

    Returns:
        A tuple of (R, G, B) values.
    """
    hex_color = hex_color.lstrip("#")
    if len(hex_color) != 6:
        raise ValueError(
            f"Invalid hex color '{hex_color}': expected 6 hexadecimal characters."
        )
    if not all(c in "0123456789abcdefABCDEF" for c in hex_color):
        raise ValueError(
            f"Invalid hex color '{hex_color}': contains non-hexadecimal characters."
        )
    return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4))

is_qgis_available()

Check if QGIS libraries are available.

Returns:

Type Description
bool

True if QGIS is available, False otherwise.

Source code in qgis_map/common.py
def is_qgis_available() -> bool:
    """Check if QGIS libraries are available.

    Returns:
        True if QGIS is available, False otherwise.
    """
    try:
        from qgis.core import QgsApplication

        return True
    except ImportError:
        return False

is_raster_file(filepath)

Check if a file is a raster format.

Parameters:

Name Type Description Default
filepath str

The file path.

required

Returns:

Type Description
bool

True if the file is a raster format, False otherwise.

Source code in qgis_map/common.py
def is_raster_file(filepath: str) -> bool:
    """Check if a file is a raster format.

    Args:
        filepath: The file path.

    Returns:
        True if the file is a raster format, False otherwise.
    """
    raster_extensions = {
        "tif",
        "tiff",
        "geotiff",
        "img",
        "jp2",
        "png",
        "jpg",
        "jpeg",
        "gif",
        "bmp",
        "ecw",
        "sid",
        "nc",
        "hdf",
        "hdf4",
        "hdf5",
        "grd",
        "asc",
        "dem",
        "dt0",
        "dt1",
        "dt2",
        "vrt",
    }
    return get_file_extension(filepath) in raster_extensions

is_vector_file(filepath)

Check if a file is a vector format.

Parameters:

Name Type Description Default
filepath str

The file path.

required

Returns:

Type Description
bool

True if the file is a vector format, False otherwise.

Source code in qgis_map/common.py
def is_vector_file(filepath: str) -> bool:
    """Check if a file is a vector format.

    Args:
        filepath: The file path.

    Returns:
        True if the file is a vector format, False otherwise.
    """
    vector_extensions = {
        "shp",
        "geojson",
        "json",
        "gpkg",
        "kml",
        "kmz",
        "gml",
        "tab",
        "mif",
        "mid",
        "dgn",
        "dxf",
        "dwg",
        "gpx",
        "csv",
        "xlsx",
        "xls",
        "ods",
        "parquet",
        "feather",
        "gdb",
    }
    return get_file_extension(filepath) in vector_extensions

parse_point_data(data, x, y, encoding='utf-8')

Parse CSV file or DataFrame to extract coordinates and attributes.

Parameters:

Name Type Description Default
data Union[str, Any]

Path to CSV file or pandas DataFrame.

required
x str

Column name for x-coordinate (longitude).

required
y str

Column name for y-coordinate (latitude).

required
encoding str

Encoding for CSV file. Defaults to "utf-8".

'utf-8'

Returns:

Type Description
Tuple[Any, List[str]]

A tuple of (DataFrame, list of attribute column names).

Exceptions:

Type Description
ImportError

If pandas is not available.

FileNotFoundError

If CSV file doesn't exist.

ValueError

If required columns are not found.

Source code in qgis_map/common.py
def parse_point_data(
    data: Union[str, Any],
    x: str,
    y: str,
    encoding: str = "utf-8",
) -> Tuple[Any, List[str]]:
    """Parse CSV file or DataFrame to extract coordinates and attributes.

    Args:
        data: Path to CSV file or pandas DataFrame.
        x: Column name for x-coordinate (longitude).
        y: Column name for y-coordinate (latitude).
        encoding: Encoding for CSV file. Defaults to "utf-8".

    Returns:
        A tuple of (DataFrame, list of attribute column names).

    Raises:
        ImportError: If pandas is not available.
        FileNotFoundError: If CSV file doesn't exist.
        ValueError: If required columns are not found.
    """
    try:
        import pandas as pd
    except ImportError:
        raise ImportError("pandas is required for parsing point data")

    # Load data
    if isinstance(data, str):
        if not os.path.exists(data):
            raise FileNotFoundError(f"File not found: {data}")
        df = pd.read_csv(data, encoding=encoding)
    else:
        df = data

    # Validate required columns
    if x not in df.columns:
        raise ValueError(
            f"Column '{x}' not found in data. Available: {list(df.columns)}"
        )
    if y not in df.columns:
        raise ValueError(
            f"Column '{y}' not found in data. Available: {list(df.columns)}"
        )

    # Get attribute columns (all except x and y)
    attr_columns = [col for col in df.columns if col not in [x, y]]

    return df, attr_columns

random_string(length=8)

Generate a random string of specified length.

Parameters:

Name Type Description Default
length int

The length of the random string. Defaults to 8.

8

Returns:

Type Description
str

A random string.

Source code in qgis_map/common.py
def random_string(length: int = 8) -> str:
    """Generate a random string of specified length.

    Args:
        length: The length of the random string. Defaults to 8.

    Returns:
        A random string.
    """
    import random
    import string

    return "".join(random.choices(string.ascii_lowercase + string.digits, k=length))

rgb_to_hex(r, g, b)

Convert RGB values to a hex color string.

Parameters:

Name Type Description Default
r int

Red component (0-255).

required
g int

Green component (0-255).

required
b int

Blue component (0-255).

required

Returns:

Type Description
str

A hex color string (e.g., "#ff0000").

Source code in qgis_map/common.py
def rgb_to_hex(r: int, g: int, b: int) -> str:
    """Convert RGB values to a hex color string.

    Args:
        r: Red component (0-255).
        g: Green component (0-255).
        b: Blue component (0-255).

    Returns:
        A hex color string (e.g., "#ff0000").
    """
    return "#{:02x}{:02x}{:02x}".format(r, g, b)