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
IdGeneratorType

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) -> IdGeneratorType:
    """
    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}")