Utils - Snailz Docs

Skip to content

# Utils

Utilities.

## `UnquotedDatabase`

Bases: `Database`

Patch sqlite-utils database to avoid quoting.

Source code in `src/snailz/_utils.py`

    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    class UnquotedDatabase(Database):
        """Patch sqlite-utils database to avoid quoting."""

        def execute(self, sql: str, parameters: Any = None) -> Any:
            """
            Rewrite `CREATE` statements to remove quoting.

            Args:
                sql: SQL text.
                parameters: Extra arguments.

            Returns:
                A result.
            """

            if sql.strip().upper().startswith("CREATE"):
                sql = sql.replace('"', "")
            return super().execute(sql, parameters)

### `execute(sql, parameters=None)`

Rewrite `CREATE` statements to remove quoting.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`sql` | `str` | SQL text. | required
`parameters` | `Any` | Extra arguments. | `None`

Returns:

Type | Description
--- | ---
`Any` | A result.

Source code in `src/snailz/_utils.py`

    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    def execute(self, sql: str, parameters: Any = None) -> Any:
        """
        Rewrite `CREATE` statements to remove quoting.

        Args:
            sql: SQL text.
            parameters: Extra arguments.

        Returns:
            A result.
        """

        if sql.strip().upper().startswith("CREATE"):
            sql = sql.replace('"', "")
        return super().execute(sql, parameters)

## `id_generator(stem, digits)`

Generate unique IDs of the form 'stemDDDD'.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`stem` | `str` | Distinguishing prefix. | required
`digits` | `int` | Number of digits in IDs. | required

Returns:

Type | Description
--- | ---
`str` | Sequence of IDs.

Source code in `src/snailz/_utils.py`

    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    def id_generator(stem: str, digits: int) -> str:
        """
        Generate unique IDs of the form 'stemDDDD'.

        Args:
            stem: Distinguishing prefix.
            digits: Number of digits in IDs.

        Returns:
            Sequence of IDs.
        """

        i = 1
        while True:
            temp = str(i)
            assert len(temp) <= digits, f"ID generation overflow {stem}: {i}"
            yield f"{stem}{temp.zfill(digits)}"
            i += 1

## `lat_lon(lat0, lon0, x_offset_m, y_offset_m)`

Calculate latitude and longitude from a base point with offsets.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`lat0` | `float` | Reference latitude. | required
`lon0` | `float` | Reference longitude. | required
`x_offset_m` | `float` | X offset (m). | required
`y_offset_m` | `float` | Y offset (m). | required

Returns:

Type | Description
--- | ---
`tuple[float, float]` | `(lat, lon)` pair.

Source code in `src/snailz/_utils.py`

    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    def lat_lon(
        lat0: float, lon0: float, x_offset_m: float, y_offset_m: float
    ) -> tuple[float, float]:
        """
        Calculate latitude and longitude from a base point with offsets.

        Args:
            lat0: Reference latitude.
            lon0: Reference longitude.
            x_offset_m: X offset (m).
            y_offset_m: Y offset (m).

        Returns:
            `(lat, lon)` pair.
        """

        lat = lat0 + y_offset_m / METERS_PER_DEGREE_LAT
        m_per_deg_lon = METERS_PER_DEGREE_LAT * math.cos(math.radians(lat0))
        lon = lon0 + x_offset_m / m_per_deg_lon
        return round(lat, LAT_LON_PRECISION), round(lon, LAT_LON_PRECISION)

## `random_date(min_date, max_date)`

Select random date in range (inclusive).

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`min_date` | `date` | Start of range. | required
`max_date` | `date` | End of range. | required

Returns:

Type | Description
--- | ---
`date` | Random date in range.

Source code in `src/snailz/_utils.py`

    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    def random_date(min_date: date, max_date: date) -> date:
        """
        Select random date in range (inclusive).

        Args:
            min_date: Start of range.
            max_date: End of range.

        Returns:
            Random date in range.
        """

        days = (max_date - min_date).days
        return min_date + timedelta(days=random.randint(0, days))

## `validate(cond, msg)`

Validate a condition.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`cond` | `bool` | What to check. | required
`msg` | `str` | What to report if condition is untrue. | required

Raises:

Type | Description
--- | ---
`ValueError` | If condition is untrue.

Source code in `src/snailz/_utils.py`

     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    def validate(cond: bool, msg: str):
        """
        Validate a condition.

        Args:
            cond: What to check.
            msg: What to report if condition is untrue.

        Raises:
            ValueError: If condition is untrue.
        """

        if not cond:
            raise ValueError(msg)

## `validate_lat_lon(caller, lat, lon)`

Validate latitude and longitude.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`caller` | `str` | Name of calling function. | required
`lat` | `float` | Latitude. | required
`lon` | `float` | Longitude. | required

Raises:

Type | Description
--- | ---
`ValueError` | If `(lat, lon)` pair is invalid.

Source code in `src/snailz/_utils.py`

    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    def validate_lat_lon(caller: str, lat: float, lon: float):
        """
        Validate latitude and longitude.

        Args:
            caller: Name of calling function.
            lat: Latitude.
            lon: Longitude.

        Raises:
            ValueError: If `(lat, lon)` pair is invalid.
        """

        validate(-90.0 <= lat <= 90.0, f"invalid {caller} latitutde {lat}")
        validate(-180.0 <= lon <= 180.0, f"invalid {caller} longitude {lon}")