Skip to content

Commit

Permalink
fix all typing errors
Browse files Browse the repository at this point in the history
  • Loading branch information
benbovy committed Dec 6, 2024
1 parent e39d258 commit 20a5836
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 39 deletions.
13 changes: 9 additions & 4 deletions src/generate_spherely_vfunc_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
import string
from pathlib import Path

from spherely import EARTH_RADIUS_METERS


VFUNC_TYPE_SPECS = {
"_VFunc_Nin1_Nout1": {"n_in": 1},
"_VFunc_Nin2_Nout1": {"n_in": 2},
"_VFunc_Nin2optradius_Nout1": {"n_in": 2, "radius": "float"},
"_VFunc_Nin1optradius_Nout1": {"n_in": 1, "radius": "float"},
"_VFunc_Nin2optradius_Nout1": {"n_in": 2, "radius": ("float", EARTH_RADIUS_METERS)},
"_VFunc_Nin1optradius_Nout1": {"n_in": 1, "radius": ("float", EARTH_RADIUS_METERS)},
"_VFunc_Nin1optprecision_Nout1": {"n_in": 1, "precision": ("int", 6)},
}

STUB_FILE_PATH = Path(__file__).parent / "spherely.pyi"
Expand Down Expand Up @@ -51,10 +55,11 @@ def _vfunctype_factory(class_name, n_in, **optargs):
"",
]
optarg_str = ", ".join(
f"{arg_name}: {arg_type} = ..." for arg_name, arg_type in optargs.items()
f"{arg_name}: {arg_type} = {arg_value}"
for arg_name, (arg_type, arg_value) in optargs.items()
)

geog_types = ["Geography", "npt.ArrayLike"]
geog_types = ["Geography", "Iterable[Geography]"]
for arg_types in itertools.product(geog_types, repeat=n_in):
arg_str = ", ".join(
f"{arg_name}: {arg_type}"
Expand Down
92 changes: 64 additions & 28 deletions src/spherely.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ from typing import (
Literal,
Protocol,
Sequence,
Tuple,
TypeVar,
overload,
)
Expand Down Expand Up @@ -66,7 +65,7 @@ class Projection:
@staticmethod
def lnglat() -> Projection: ...
@staticmethod
def speudo_mercator() -> Projection: ...
def pseudo_mercator() -> Projection: ...
@staticmethod
def orthographic(longitude: float, latitude: float) -> Projection: ...

Expand All @@ -76,6 +75,11 @@ _NameType = TypeVar("_NameType", bound=str)
_ScalarReturnType = TypeVar("_ScalarReturnType", bound=Any)
_ArrayReturnDType = TypeVar("_ArrayReturnDType", bound=Any)

# TODO: npt.NDArray[Geography] not supported yet
# (see https://github.com/numpy/numpy/issues/24738)
# (unless Geography is passed via Generic[...], see VFunc below)
T_NDArray_Geography = npt.NDArray[Any]

# The following types are auto-generated. Please don't edit them by hand.
# Instead, update the generate_spherely_vfunc_types.py script and run it
# to update the types.
Expand All @@ -87,7 +91,9 @@ class _VFunc_Nin1_Nout1(Generic[_NameType, _ScalarReturnType, _ArrayReturnDType]
@overload
def __call__(self, geography: Geography) -> _ScalarReturnType: ...
@overload
def __call__(self, geography: npt.ArrayLike) -> npt.NDArray[_ArrayReturnDType]: ...
def __call__(
self, geography: Iterable[Geography]
) -> npt.NDArray[_ArrayReturnDType]: ...

class _VFunc_Nin2_Nout1(Generic[_NameType, _ScalarReturnType, _ArrayReturnDType]):
@property
Expand All @@ -96,15 +102,15 @@ class _VFunc_Nin2_Nout1(Generic[_NameType, _ScalarReturnType, _ArrayReturnDType]
def __call__(self, a: Geography, b: Geography) -> _ScalarReturnType: ...
@overload
def __call__(
self, a: Geography, b: npt.ArrayLike
self, a: Geography, b: Iterable[Geography]
) -> npt.NDArray[_ArrayReturnDType]: ...
@overload
def __call__(
self, a: npt.ArrayLike, b: Geography
self, a: Iterable[Geography], b: Geography
) -> npt.NDArray[_ArrayReturnDType]: ...
@overload
def __call__(
self, a: npt.ArrayLike, b: npt.ArrayLike
self, a: Iterable[Geography], b: Iterable[Geography]
) -> npt.NDArray[_ArrayReturnDType]: ...

class _VFunc_Nin2optradius_Nout1(
Expand All @@ -114,19 +120,19 @@ class _VFunc_Nin2optradius_Nout1(
def __name__(self) -> _NameType: ...
@overload
def __call__(
self, a: Geography, b: Geography, radius: float = ...
self, a: Geography, b: Geography, radius: float = 6371010.0
) -> _ScalarReturnType: ...
@overload
def __call__(
self, a: Geography, b: npt.ArrayLike, radius: float = ...
self, a: Geography, b: Iterable[Geography], radius: float = 6371010.0
) -> npt.NDArray[_ArrayReturnDType]: ...
@overload
def __call__(
self, a: npt.ArrayLike, b: Geography, radius: float = ...
self, a: Iterable[Geography], b: Geography, radius: float = 6371010.0
) -> npt.NDArray[_ArrayReturnDType]: ...
@overload
def __call__(
self, a: npt.ArrayLike, b: npt.ArrayLike, radius: float = ...
self, a: Iterable[Geography], b: Iterable[Geography], radius: float = 6371010.0
) -> npt.NDArray[_ArrayReturnDType]: ...

class _VFunc_Nin1optradius_Nout1(
Expand All @@ -135,10 +141,24 @@ class _VFunc_Nin1optradius_Nout1(
@property
def __name__(self) -> _NameType: ...
@overload
def __call__(self, a: Geography, radius: float = ...) -> _ScalarReturnType: ...
def __call__(
self, a: Geography, radius: float = 6371010.0
) -> _ScalarReturnType: ...
@overload
def __call__(
self, a: Iterable[Geography], radius: float = 6371010.0
) -> npt.NDArray[_ArrayReturnDType]: ...

class _VFunc_Nin1optprecision_Nout1(
Generic[_NameType, _ScalarReturnType, _ArrayReturnDType]
):
@property
def __name__(self) -> _NameType: ...
@overload
def __call__(self, a: Geography, precision: int = 6) -> _ScalarReturnType: ...
@overload
def __call__(
self, a: npt.ArrayLike, radius: float = ...
self, a: Iterable[Geography], precision: int = 6
) -> npt.NDArray[_ArrayReturnDType]: ...

# /// End types
Expand Down Expand Up @@ -188,12 +208,9 @@ def create_collection(geographies: Iterable[Geography]) -> GeometryCollection: .

# Geography creation (vectorized)

@overload
def points(
longitude: npt.ArrayLike, latitude: npt.ArrayLike
) -> npt.NDArray[np.object_]: ...
@overload
def points(longitude: float, latitude: float) -> PointGeography: ... # type: ignore[misc]
) -> PointGeography | T_NDArray_Geography: ...

# Geography utils

Expand Down Expand Up @@ -234,42 +251,61 @@ boundary: _VFunc_Nin1_Nout1[Literal["boundary"], Geography, Geography]
convex_hull: _VFunc_Nin1_Nout1[
Literal["convex_hull"], PolygonGeography, PolygonGeography
]
distance: _VFunc_Nin2optradius_Nout1[Literal["distance"], float, float]
area: _VFunc_Nin1optradius_Nout1[Literal["area"], float, float]
length: _VFunc_Nin1optradius_Nout1[Literal["length"], float, float]
perimeter: _VFunc_Nin1optradius_Nout1[Literal["perimeter"], float, float]
distance: _VFunc_Nin2optradius_Nout1[Literal["distance"], float, np.float64]
area: _VFunc_Nin1optradius_Nout1[Literal["area"], float, np.float64]
length: _VFunc_Nin1optradius_Nout1[Literal["length"], float, np.float64]
perimeter: _VFunc_Nin1optradius_Nout1[Literal["perimeter"], float, np.float64]

# io functions

to_wkt: _VFunc_Nin1_Nout1[Literal["to_wkt"], str, object]
to_wkt: _VFunc_Nin1optprecision_Nout1[Literal["to_wkt"], str, object]
to_wkb: _VFunc_Nin1_Nout1[Literal["to_wkb"], bytes, object]

@overload
def from_wkt(
a: str,
oriented: bool = False,
planar: bool = False,
tessellate_tolerance: float = 100.0,
) -> Geography: ...
@overload
def from_wkt(
a: Iterable[str],
a: list[str] | npt.NDArray[np.str_],
oriented: bool = False,
planar: bool = False,
tessellate_tolerance: float = 100.0,
) -> npt.NDArray[Any]: ...
) -> T_NDArray_Geography: ...
@overload
def from_wkb(
a: bytes,
oriented: bool = False,
planar: bool = False,
tessellate_tolerance: float = 100.0,
) -> Geography: ...
@overload
def from_wkb(
a: Iterable[bytes],
oriented: bool = False,
planar: bool = False,
tessellate_tolerance: float = 100.0,
) -> npt.NDArray[Any]: ...
) -> T_NDArray_Geography: ...

class ArrowSchemaExportable(Protocol):
def __arrow_c_schema__(self) -> object: ...

class ArrowArrayExportable(Protocol):
def __arrow_c_array__(
self, requested_schema: object | None = None
) -> Tuple[object, object]: ...
) -> tuple[object, object]: ...

class ArrowArrayHolder:
def __arrow_c_array__(self) -> tuple[object, object]: ...

def to_geoarrow(
input: npt.ArrayLike,
input: Geography | T_NDArray_Geography,
/,
*,
output_schema: ArrowSchemaExportable | None = None,
output_schema: ArrowSchemaExportable | str | None = None,
projection: Projection = Projection.lnglat(),
planar: bool = False,
tessellate_tolerance: float = 100.0,
Expand All @@ -284,4 +320,4 @@ def from_geoarrow(
tessellate_tolerance: float = 100.0,
projection: Projection = Projection.lnglat(),
geometry_encoding: str | None = None,
) -> npt.NDArray[Any]: ...
) -> T_NDArray_Geography: ...
8 changes: 3 additions & 5 deletions tests/test_geoarrow.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from packaging.version import Version

import numpy as np

import pytest
Expand Down Expand Up @@ -78,13 +76,13 @@ def test_from_geoarrow_oriented() -> None:
def test_from_wkt_planar() -> None:
arr = ga.as_geoarrow(["LINESTRING (-64 45, 0 45)"])
result = spherely.from_geoarrow(arr)
assert spherely.distance(result, spherely.create_point(-30.1, 45)) > 10000
assert spherely.distance(result, spherely.create_point(-30.1, 45)) > 10000.0

result = spherely.from_geoarrow(arr, planar=True)
assert spherely.distance(result, spherely.create_point(-30.1, 45)) < 100
assert spherely.distance(result, spherely.create_point(-30.1, 45)) < 100.0

result = spherely.from_geoarrow(arr, planar=True, tessellate_tolerance=10)
assert spherely.distance(result, spherely.create_point(-30.1, 45)) < 10
assert spherely.distance(result, spherely.create_point(-30.1, 45)) < 10.0


def test_from_geoarrow_projection() -> None:
Expand Down
4 changes: 2 additions & 2 deletions tests/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ def test_from_wkb_point_empty() -> None:
expected = spherely.from_wkt(["POINT (1 1)", "POINT EMPTY", "POINT EMPTY"])
assert spherely.equals(result, expected).all()

result = spherely.from_wkb(GEOMETRYCOLLECTION_NAN_WKB)
assert str(result) == "GEOMETRYCOLLECTION (POINT EMPTY)"
result2 = spherely.from_wkb(GEOMETRYCOLLECTION_NAN_WKB)
assert str(result2) == "GEOMETRYCOLLECTION (POINT EMPTY)"


def test_from_wkb_invalid() -> None:
Expand Down

0 comments on commit 20a5836

Please sign in to comment.