From a26435efc479fcf9d492d968ebedaa5226639a7c Mon Sep 17 00:00:00 2001
From: Benoit Bovy <benbovy@gmail.com>
Date: Mon, 9 Dec 2024 17:06:55 +0100
Subject: [PATCH 01/11] sphinx conf: remove invalid options

---
 docs/conf.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/docs/conf.py b/docs/conf.py
index f75c6c6..6f3311e 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -61,8 +61,6 @@
     use_repository_button=True,
     use_issues_button=True,
     home_page_in_toc=False,
-    extra_navbar="",
-    navbar_footer_text="",
 )
 
 html_static_path = ["_static"]

From c59675e82d612d9bcadd677540dd260a4c7ad9ee Mon Sep 17 00:00:00 2001
From: Benoit Bovy <benbovy@gmail.com>
Date: Mon, 9 Dec 2024 17:08:03 +0100
Subject: [PATCH 02/11] disable pybind11 generated docstring signatures

Add them manually instead, without type hints. It is a bit more tedious
to maintain but the result is more consistent and readable.

- Pybind11 type hints not always reliable (e.g., non-vectorized
arguments of py::vectorize functions show as numpy.ndarray, too generic
return type)

- didn't work with sphinx's ``autodoc_typehints = "none"``, which seemed
to be ignored for some reason. Adding type hints in the function
signatures in the API documentation makes those signature less readable
and doesn't add much information (type hints already in the parameter
and return description sections)

Also add "Returns" sections in docstrings more globally.
---
 docs/conf.py               | 11 ++++++
 src/accessors-geog.cpp     | 77 +++++++++++++++++++++++++++++++++-----
 src/boolean-operations.cpp | 31 +++++++++++++--
 src/creation.cpp           | 65 +++++++++++++++++++++++++++-----
 src/geoarrow.cpp           | 57 +++++++++++++++++-----------
 src/geography.cpp          | 37 ++++++++++++------
 src/io.cpp                 | 35 +++++++++++++++--
 src/predicates.cpp         | 27 +++++++++----
 8 files changed, 273 insertions(+), 67 deletions(-)

diff --git a/docs/conf.py b/docs/conf.py
index 6f3311e..a504411 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -20,6 +20,8 @@
     "shapely": ("https://shapely.readthedocs.io/en/latest/", None),
 }
 
+# TODO: seem to have no effect
+# (see https://github.com/sphinx-doc/sphinx/issues/10235)
 autodoc_typehints = "none"
 
 napoleon_google_docstring = False
@@ -28,8 +30,17 @@
 napoleon_use_rtype = False
 napoleon_preprocess_types = True
 napoleon_type_aliases = {
+    # general terms
+    "sequence": ":term:`sequence`",
+    "iterable": ":term:`iterable`",
+    # numpy terms
     "array_like": ":term:`array_like`",
     "array-like": ":term:`array-like <array_like>`",
+    # objects without namespace: spherely
+    "EARTH_RADIUS_METERS": "spherely.EARTH_RADIUS_METERS",
+    # objects without namespace: numpy
+    "ndarray": "~numpy.ndarray",
+    "array": ":term:`array`",
 }
 
 # source_suffix = ['.rst', '.md']
diff --git a/src/accessors-geog.cpp b/src/accessors-geog.cpp
index 3e489b1..c0255c0 100644
--- a/src/accessors-geog.cpp
+++ b/src/accessors-geog.cpp
@@ -63,12 +63,16 @@ double perimeter(PyObjectGeography a, double radius = numeric_constants::EARTH_R
 }
 
 void init_accessors(py::module& m) {
+    py::options options;
+    options.disable_function_signatures();
+
     m.attr("EARTH_RADIUS_METERS") = py::float_(numeric_constants::EARTH_RADIUS_METERS);
 
     m.def("centroid",
           py::vectorize(&centroid),
           py::arg("a"),
-          R"pbdoc(
+          R"pbdoc(centroid(a)
+
         Computes the centroid of each geography.
 
         Parameters
@@ -76,12 +80,18 @@ void init_accessors(py::module& m) {
         a : :py:class:`Geography` or array_like
             Geography object
 
+        Returns
+        -------
+        Geography or array
+            A single or an array of POINT geography object(s).
+
     )pbdoc");
 
     m.def("boundary",
           py::vectorize(&boundary),
           py::arg("a"),
-          R"pbdoc(
+          R"pbdoc(boundary(a)
+
         Computes the boundary of each geography.
 
         Parameters
@@ -89,12 +99,19 @@ void init_accessors(py::module& m) {
         a : :py:class:`Geography` or array_like
             Geography object
 
+        Returns
+        -------
+        Geography or array
+            A single or an array of either (MULTI)POINT or (MULTI)LINESTRING
+            geography object(s).
+
     )pbdoc");
 
     m.def("convex_hull",
           py::vectorize(&convex_hull),
           py::arg("a"),
-          R"pbdoc(
+          R"pbdoc(convex_hull(a)
+
         Computes the convex hull of each geography.
 
         Parameters
@@ -102,12 +119,18 @@ void init_accessors(py::module& m) {
         a : :py:class:`Geography` or array_like
             Geography object
 
+        Returns
+        -------
+        Geography or array
+            A single or an array of POLYGON geography object(s).
+
     )pbdoc");
 
     m.def("get_x",
           py::vectorize(&get_x),
           py::arg("a"),
-          R"pbdoc(
+          R"pbdoc(get_x(a)
+
         Returns the longitude value of the Point (in degrees).
 
         Parameters
@@ -115,12 +138,18 @@ void init_accessors(py::module& m) {
         a: :py:class:`Geography` or array_like
             Geography object(s).
 
+        Returns
+        -------
+        float or array
+            Longitude coordinate value(s).
+
     )pbdoc");
 
     m.def("get_y",
           py::vectorize(&get_y),
           py::arg("a"),
-          R"pbdoc(
+          R"pbdoc(get_y(a)
+
         Returns the latitude value of the Point (in degrees).
 
         Parameters
@@ -128,6 +157,11 @@ void init_accessors(py::module& m) {
         a: :py:class:`Geography` or array_like
             Geography object(s).
 
+        Returns
+        -------
+        float or array
+            Latitude coordinate value(s).
+
     )pbdoc");
 
     m.def("distance",
@@ -135,7 +169,8 @@ void init_accessors(py::module& m) {
           py::arg("a"),
           py::arg("b"),
           py::arg("radius") = numeric_constants::EARTH_RADIUS_METERS,
-          R"pbdoc(
+          R"pbdoc(distance(a, b, radius=spherely.EARTH_RADIUS_METERS)
+
         Calculate the distance between two geographies.
 
         Parameters
@@ -147,13 +182,19 @@ void init_accessors(py::module& m) {
         radius : float, optional
             Radius of Earth in meters, default 6,371,010
 
+        Returns
+        -------
+        float or array
+            Distance value(s), in meters.
+
     )pbdoc");
 
     m.def("area",
           py::vectorize(&area),
           py::arg("a"),
           py::arg("radius") = numeric_constants::EARTH_RADIUS_METERS,
-          R"pbdoc(
+          R"pbdoc(area(a, radius=spherely.EARTH_RADIUS_METERS)
+
         Calculate the area of the geography.
 
         Parameters
@@ -163,13 +204,19 @@ void init_accessors(py::module& m) {
         radius : float, optional
             Radius of Earth in meters, default 6,371,010
 
+        Returns
+        -------
+        float or array
+            Area value(s), in square meters.
+
     )pbdoc");
 
     m.def("length",
           py::vectorize(&length),
           py::arg("a"),
           py::arg("radius") = numeric_constants::EARTH_RADIUS_METERS,
-          R"pbdoc(
+          R"pbdoc(length(a, radius=spherely.EARTH_RADIUS_METERS)
+
         Calculates the length of a line geography, returning zero for other types.
 
         Parameters
@@ -179,13 +226,19 @@ void init_accessors(py::module& m) {
         radius : float, optional
             Radius of Earth in meters, default 6,371,010
 
+        Returns
+        -------
+        float or array
+            Length value(s), in meters.
+
    )pbdoc");
 
     m.def("perimeter",
           py::vectorize(&perimeter),
           py::arg("a"),
           py::arg("radius") = numeric_constants::EARTH_RADIUS_METERS,
-          R"pbdoc(
+          R"pbdoc(perimeter(a, radius=spherely.EARTH_RADIUS_METERS)
+
         Calculates the perimeter of a polygon geography, returning zero for other types.
 
         Parameters
@@ -194,5 +247,11 @@ void init_accessors(py::module& m) {
             Geography object
         radius : float, optional
             Radius of Earth in meters, default 6,371,010
+
+        Returns
+        -------
+        float or array
+            Perimeter value(s), in meters.
+
     )pbdoc");
 }
diff --git a/src/boolean-operations.cpp b/src/boolean-operations.cpp
index aad4cb6..014c956 100644
--- a/src/boolean-operations.cpp
+++ b/src/boolean-operations.cpp
@@ -33,11 +33,15 @@ class BooleanOp {
 };
 
 void init_boolean_operations(py::module& m) {
+    py::options options;
+    options.disable_function_signatures();
+
     m.def("union",
           py::vectorize(BooleanOp(S2BooleanOperation::OpType::UNION)),
           py::arg("a"),
           py::arg("b"),
-          R"pbdoc(
+          R"pbdoc(union(a, b)
+
         Computes the union of both geographies.
 
         Parameters
@@ -45,13 +49,18 @@ void init_boolean_operations(py::module& m) {
         a, b : :py:class:`Geography` or array_like
             Geography object
 
+        Returns
+        -------
+        Geography or array
+
     )pbdoc");
 
     m.def("intersection",
           py::vectorize(BooleanOp(S2BooleanOperation::OpType::INTERSECTION)),
           py::arg("a"),
           py::arg("b"),
-          R"pbdoc(
+          R"pbdoc(intersection(a, b)
+
         Computes the intersection of both geographies.
 
         Parameters
@@ -59,13 +68,18 @@ void init_boolean_operations(py::module& m) {
         a, b : :py:class:`Geography` or array_like
             Geography object
 
+        Returns
+        -------
+        Geography or array
+
     )pbdoc");
 
     m.def("difference",
           py::vectorize(BooleanOp(S2BooleanOperation::OpType::DIFFERENCE)),
           py::arg("a"),
           py::arg("b"),
-          R"pbdoc(
+          R"pbdoc(difference(a, b)
+
         Computes the difference of both geographies.
 
         Parameters
@@ -73,13 +87,18 @@ void init_boolean_operations(py::module& m) {
         a, b : :py:class:`Geography` or array_like
             Geography object
 
+        Returns
+        -------
+        Geography or array
+
     )pbdoc");
 
     m.def("symmetric_difference",
           py::vectorize(BooleanOp(S2BooleanOperation::OpType::SYMMETRIC_DIFFERENCE)),
           py::arg("a"),
           py::arg("b"),
-          R"pbdoc(
+          R"pbdoc(symmetric_difference(a, b)
+
         Computes the symmetric difference of both geographies.
 
         Parameters
@@ -87,5 +106,9 @@ void init_boolean_operations(py::module& m) {
         a, b : :py:class:`Geography` or array_like
             Geography object
 
+        Returns
+        -------
+        Geography or array
+
     )pbdoc");
 }
diff --git a/src/creation.cpp b/src/creation.cpp
index 4a92e16..000e296 100644
--- a/src/creation.cpp
+++ b/src/creation.cpp
@@ -302,7 +302,8 @@ void init_creation(py::module &m) {
         },
         py::arg("longitude") = py::none(),
         py::arg("latitude") = py::none(),
-        R"pbdoc(create_point(longitude: float | None = None, latitude: float | None = None) -> Geography
+        R"pbdoc(create_point(longitude=None, latitude=None)
+
         Create a POINT geography.
 
         Parameters
@@ -312,12 +313,18 @@ void init_creation(py::module &m) {
         latitude : float, optional
             latitude coordinate, in degrees.
 
+        Returns
+        -------
+        point : Geography
+            A new POINT geography object.
+
     )pbdoc");
 
     m.def("create_multipoint",
           &create_multipoint<std::pair<double, double>>,
           py::arg("points"),
-          R"pbdoc(create_multipoint(points: Sequence) -> Geography
+          R"pbdoc(create_multipoint(points)
+
         Create a MULTIPOINT geography.
 
         Parameters
@@ -326,6 +333,12 @@ void init_creation(py::module &m) {
             A sequence of (longitude, latitude) coordinates (in degrees) or
             POINT :class:`~spherely.Geography` objects.
 
+        Returns
+        -------
+        multipoint : Geography
+            A new MULTIPOINT (or POINT if a single point is passed)
+            geography object.
+
     )pbdoc")
         .def("create_multipoint", &create_multipoint<Geography *>, py::arg("points"));
 
@@ -333,7 +346,8 @@ void init_creation(py::module &m) {
          "create_linestring",
          [](py::none) { return make_geography(std::make_unique<s2geog::PolylineGeography>()); },
          py::arg("vertices") = py::none(),
-         R"pbdoc(create_linestring(vertices: Sequence | None = None) -> Geography
+         R"pbdoc(create_linestring(vertices=None)
+
         Create a LINESTRING geography.
 
         Parameters
@@ -342,6 +356,11 @@ void init_creation(py::module &m) {
             A sequence of (longitude, latitude) coordinates (in degrees) or
             POINT :class:`~spherely.Geography` objects.
 
+        Returns
+        -------
+        linestring : Geography
+            A new LINESTRING geography object.
+
         )pbdoc")
         .def(
             "create_linestring", &create_linestring<std::pair<double, double>>, py::arg("vertices"))
@@ -350,7 +369,8 @@ void init_creation(py::module &m) {
     m.def("create_multilinestring",
           &create_multilinestring<std::pair<double, double>>,
           py::arg("lines"),
-          R"pbdoc(create_multilinestring(lines: Sequence) -> Geography
+          R"pbdoc(create_multilinestring(lines)
+
         Create a MULTILINESTRING geography.
 
         Parameters
@@ -360,6 +380,12 @@ void init_creation(py::module &m) {
             a sequence of sequences of POINT :class:`~spherely.Geography` objects or
             a sequence of LINESTRING :class:`~spherely.Geography` objects.
 
+        Returns
+        -------
+        multilinestring : Geography
+            A new MULTILINESTRING (or LINESTRING if a single line is passed)
+            geography object.
+
     )pbdoc")
         .def("create_multilinestring", &create_multilinestring<Geography *>, py::arg("lines"))
         .def(
@@ -378,7 +404,8 @@ void init_creation(py::module &m) {
          },
          py::arg("shell") = py::none(),
          py::arg("holes") = py::none(),
-         R"pbdoc(create_polygon(shell: Sequence | None = None, holes: Sequence | None = None) -> Geography
+         R"pbdoc(create_polygon(shell=None, holes=None)
+
         Create a POLYGON geography.
 
         Parameters
@@ -390,6 +417,11 @@ void init_creation(py::module &m) {
             A list of sequences of objects where each sequence satisfies the same
             requirements as the ``shell`` argument.
 
+        Returns
+        -------
+        polygon : Geography
+            A new POLYGON geography object.
+
     )pbdoc")
         .def("create_polygon",
              &create_polygon<std::pair<double, double>>,
@@ -403,7 +435,8 @@ void init_creation(py::module &m) {
     m.def("create_multipolygon",
           &create_multipolygon,
           py::arg("polygons"),
-          R"pbdoc(create_multipolygon(polygons: Sequence) -> Geography
+          R"pbdoc(create_multipolygon(polygons)
+
         Create a MULTIPOLYGON geography.
 
         Parameters
@@ -411,12 +444,19 @@ void init_creation(py::module &m) {
         polygons : sequence
             A sequence of POLYGON :class:`~spherely.Geography` objects.
 
+        Returns
+        -------
+        multipolygon : Geography
+            A new MULTIPOLYGON (or POLYGON if a single polygon is passed)
+            geography object.
+
     )pbdoc");
 
     m.def("create_collection",
           &create_collection,
           py::arg("geographies"),
-          R"pbdoc(create_collection(geographies: Sequence) -> Geography
+          R"pbdoc(create_collection(geographies)
+
         Create a GEOMETRYCOLLECTION geography from arbitrary geographies.
 
         Parameters
@@ -424,6 +464,11 @@ void init_creation(py::module &m) {
         geographies : sequence
             A sequence of :class:`~spherely.Geography` objects.
 
+        Returns
+        -------
+        collection : Geography
+            A new GEOMETRYCOLLECTION geography object.
+
     )pbdoc");
 
     // ----- vectorized Geography creation functions
@@ -432,7 +477,8 @@ void init_creation(py::module &m) {
           py::vectorize(&point),
           py::arg("longitude"),
           py::arg("latitude"),
-          R"pbdoc(
+          R"pbdoc(points(longitude, latitude)
+
         Create an array of points.
 
         Parameters
@@ -447,7 +493,8 @@ void init_creation(py::module &m) {
     m.def("points",
           &points,
           py::arg("coords"),
-          R"pbdoc(
+          R"pbdoc(points(coords)
+
         Create an array of points.
 
         Parameters
diff --git a/src/geoarrow.cpp b/src/geoarrow.cpp
index aac0562..f91a520 100644
--- a/src/geoarrow.cpp
+++ b/src/geoarrow.cpp
@@ -255,20 +255,25 @@ ArrowArrayHolder to_geoarrow(py::array_t<PyObjectGeography> input,
 }
 
 void init_geoarrow(py::module& m) {
+    py::options options;
+    options.disable_function_signatures();
+
     py::class_<ArrowArrayHolder>(m, "ArrowArrayHolder")
         .def("__arrow_c_array__", &ArrowArrayHolder::return_capsules);
 
-    m.def("from_geoarrow",
-          &from_geoarrow,
-          py::arg("input"),
-          py::pos_only(),
-          py::kw_only(),
-          py::arg("oriented") = false,
-          py::arg("planar") = false,
-          py::arg("tessellate_tolerance") = 100.0,
-          py::arg("projection") = Projection::lnglat(),
-          py::arg("geometry_encoding") = py::none(),
-          R"pbdoc(
+    m.def(
+        "from_geoarrow",
+        &from_geoarrow,
+        py::arg("input"),
+        py::pos_only(),
+        py::kw_only(),
+        py::arg("oriented") = false,
+        py::arg("planar") = false,
+        py::arg("tessellate_tolerance") = 100.0,
+        py::arg("projection") = Projection::lnglat(),
+        py::arg("geometry_encoding") = py::none(),
+        R"pbdoc(from_geoarrow(input, /, *, oriented=False, planar=False, tessellate_tolerance=100.0, projection=Projection.lnglat(), geometry_encoding=None)
+
         Create an array of geographies from an Arrow array object with a GeoArrow
         extension type.
 
@@ -315,19 +320,27 @@ void init_geoarrow(py::module& m) {
             Arrow array without geoarrow type but with a plain string or
             binary type, if specifying this keyword with "WKT" or "WKB",
             respectively.
+
+        Returns
+        -------
+        Geography or array
+            An array of geography objects.
+
     )pbdoc");
 
-    m.def("to_geoarrow",
-          &to_geoarrow,
-          py::arg("input"),
-          py::pos_only(),
-          py::kw_only(),
-          py::arg("output_schema") = py::none(),
-          py::arg("projection") = Projection::lnglat(),
-          py::arg("planar") = false,
-          py::arg("tessellate_tolerance") = 100.0,
-          py::arg("precision") = 6,
-          R"pbdoc(
+    m.def(
+        "to_geoarrow",
+        &to_geoarrow,
+        py::arg("input"),
+        py::pos_only(),
+        py::kw_only(),
+        py::arg("output_schema") = py::none(),
+        py::arg("projection") = Projection::lnglat(),
+        py::arg("planar") = false,
+        py::arg("tessellate_tolerance") = 100.0,
+        py::arg("precision") = 6,
+        R"pbdoc(to_geoarrow(input, /, *, output_schema=None, projection=Projection.lnglat(), planar=False, tessellate_tolerance=100.0, precision=6)
+
         Convert an array of geographies to an Arrow array object with a GeoArrow
         extension type.
 
diff --git a/src/geography.cpp b/src/geography.cpp
index bd527fc..e118e60 100644
--- a/src/geography.cpp
+++ b/src/geography.cpp
@@ -269,9 +269,9 @@ void init_geography(py::module &m) {
     pygeography_types.value("POINT", GeographyType::Point);
     pygeography_types.value("LINESTRING", GeographyType::LineString);
     pygeography_types.value("POLYGON", GeographyType::Polygon);
-    pygeography_types.value("MULTIPOLYGON", GeographyType::MultiPolygon);
     pygeography_types.value("MULTIPOINT", GeographyType::MultiPoint);
     pygeography_types.value("MULTILINESTRING", GeographyType::MultiLineString);
+    pygeography_types.value("MULTIPOLYGON", GeographyType::MultiPolygon);
     pygeography_types.value("GEOMETRYCOLLECTION", GeographyType::GeometryCollection);
 
     // Geography classes
@@ -318,26 +318,37 @@ void init_geography(py::module &m) {
     pygeography.def(py::pickle([](Geography &geog) { return geog.encode(); },
                                [](py::tuple &encoded) { return Geography::decode(encoded); }));
 
+    py::options options;
+    options.disable_function_signatures();
+
     // Geography properties
 
     m.def("get_type_id",
           py::vectorize(&get_type_id),
           py::arg("geography"),
-          R"pbdoc(
-        Returns the type ID of a geography.
+          R"pbdoc(get_type_id(geography)
 
-        - None (missing) is -1
-        - POINT is 0
-        - LINESTRING is 1
+        Returns the type ID of a geography.
 
         Parameters
         ----------
         geography : :py:class:`Geography` or array_like
             Geography object(s).
 
+        Returns
+        -------
+        type_id : int or array
+            The type id(s) of the input geography object(s). None (missing) is -1,
+            POINT is 0, LINESTRING is 1, etc. See the ``value`` property of the
+            :py:class:`GeographyType` enumeration.
+
     )pbdoc");
 
-    m.def("get_dimensions", py::vectorize(&get_dimensions), py::arg("geography"), R"pbdoc(
+    m.def("get_dimensions",
+          py::vectorize(&get_dimensions),
+          py::arg("geography"),
+          R"pbdoc(get_dimensions(geography)
+
         Returns the inherent dimensionality of a geography.
 
         The inherent dimension is 0 for points, 1 for linestrings and 2 for
@@ -356,7 +367,8 @@ void init_geography(py::module &m) {
     m.def("is_geography",
           py::vectorize(&is_geography),
           py::arg("obj"),
-          R"pbdoc(
+          R"pbdoc(is_geography(obj)
+
         Returns True if the object is a :py:class:`Geography`, False otherwise.
 
         Parameters
@@ -371,7 +383,8 @@ void init_geography(py::module &m) {
     m.def("is_prepared",
           py::vectorize(&is_prepared),
           py::arg("geography"),
-          R"pbdoc(
+          R"pbdoc(is_prepared(geography)
+
         Returns True if the geography object is "prepared", False otherwise.
 
         A prepared geography is a normal geography with added information such as
@@ -396,7 +409,8 @@ void init_geography(py::module &m) {
     m.def("prepare",
           py::vectorize(&prepare),
           py::arg("geography"),
-          R"pbdoc(
+          R"pbdoc(prepare(geography)
+
         Prepare a geography, improving performance of other operations.
 
         A prepared geography is a normal geography with added information such as
@@ -422,7 +436,8 @@ void init_geography(py::module &m) {
     m.def("destroy_prepared",
           py::vectorize(&destroy_prepared),
           py::arg("geography"),
-          R"pbdoc(
+          R"pbdoc(destroy_prepared(geography)
+
         Destroy the prepared part of a geography, freeing up memory.
 
         Note that the prepared geography will always be cleaned up if the
diff --git a/src/io.cpp b/src/io.cpp
index 2f88a48..0732933 100644
--- a/src/io.cpp
+++ b/src/io.cpp
@@ -82,6 +82,9 @@ class ToWKB {
 };
 
 void init_io(py::module& m) {
+    py::options options;
+    options.disable_function_signatures();
+
     m.def(
         "from_wkt",
         [](py::array_t<py::str> a, bool oriented, bool planar, float tessellate_tolerance) {
@@ -91,7 +94,8 @@ void init_io(py::module& m) {
         py::arg("oriented") = false,
         py::arg("planar") = false,
         py::arg("tessellate_tolerance") = 100.0,
-        R"pbdoc(
+        R"pbdoc(from_wkt(a, oriented=False, planar=False, tessellate_tolerance=100.0)
+
         Creates geographies from the Well-Known Text (WKT) representation.
 
         Parameters
@@ -116,6 +120,11 @@ void init_io(py::module& m) {
             satisfy the planar edge constraint. This is only used if `planar`
             is set to True.
 
+        Returns
+        -------
+        Geography or array
+            A single or an array of geography objects.
+
     )pbdoc");
 
     m.def(
@@ -125,7 +134,8 @@ void init_io(py::module& m) {
         },
         py::arg("a"),
         py::arg("precision") = 6,
-        R"pbdoc(
+        R"pbdoc(to_wkt(a, precision=6)
+
         Returns the WKT representation of each geography.
 
         Parameters
@@ -135,6 +145,11 @@ void init_io(py::module& m) {
         precision : int, default 6
             The number of decimal places to include in the output.
 
+        Returns
+        -------
+        str or array
+            A string or an array of strings.
+
     )pbdoc");
 
     m.def(
@@ -146,7 +161,8 @@ void init_io(py::module& m) {
         py::arg("oriented") = false,
         py::arg("planar") = false,
         py::arg("tessellate_tolerance") = 100.0,
-        R"pbdoc(
+        R"pbdoc(from_wkb(a, oriented=False, planar=False, tessellate_tolerance=100.0)
+
         Creates geographies from the Well-Known Bytes (WKB) representation.
 
         Parameters
@@ -171,12 +187,18 @@ void init_io(py::module& m) {
             satisfy the planar edge constraint. This is only used if `planar`
             is set to True.
 
+        Returns
+        -------
+        Geography or array
+            A single or an array of geography objects.
+
     )pbdoc");
 
     m.def("to_wkb",
           py::vectorize(ToWKB()),
           py::arg("a"),
-          R"pbdoc(
+          R"pbdoc(to_wkb(a)
+
         Returns the WKB representation of each geography.
 
         Parameters
@@ -184,5 +206,10 @@ void init_io(py::module& m) {
         a : :py:class:`Geography` or array_like
             Geography object(s)
 
+        Returns
+        -------
+        bytes or array
+            A bytes object or an array of bytes.
+
     )pbdoc");
 }
diff --git a/src/predicates.cpp b/src/predicates.cpp
index 38b46c0..ea416bc 100644
--- a/src/predicates.cpp
+++ b/src/predicates.cpp
@@ -65,11 +65,15 @@ class TouchesPredicate {
 };
 
 void init_predicates(py::module& m) {
+    py::options options;
+    options.disable_function_signatures();
+
     m.def("intersects",
           py::vectorize(Predicate(s2geog::s2_intersects)),
           py::arg("a"),
           py::arg("b"),
-          R"pbdoc(
+          R"pbdoc(intersects(a, b)
+
         Returns True if A and B share any portion of space.
 
         Intersects implies that overlaps, touches and within are True.
@@ -85,7 +89,8 @@ void init_predicates(py::module& m) {
           py::vectorize(Predicate(s2geog::s2_equals)),
           py::arg("a"),
           py::arg("b"),
-          R"pbdoc(
+          R"pbdoc(equals(a, b)
+
         Returns True if A and B are spatially equal.
 
         If A is within B and B is within A, A and B are considered equal. The
@@ -102,7 +107,8 @@ void init_predicates(py::module& m) {
           py::vectorize(Predicate(s2geog::s2_contains)),
           py::arg("a"),
           py::arg("b"),
-          R"pbdoc(
+          R"pbdoc(contains(a, b)
+
         Returns True if B is completely inside A.
 
         Parameters
@@ -120,7 +126,8 @@ void init_predicates(py::module& m) {
           })),
           py::arg("a"),
           py::arg("b"),
-          R"pbdoc(
+          R"pbdoc(within(a, b)
+
         Returns True if A is completely inside B.
 
         Parameters
@@ -138,7 +145,8 @@ void init_predicates(py::module& m) {
           })),
           py::arg("a"),
           py::arg("b"),
-          R"pbdoc(
+          R"pbdoc(disjoint(a, b)
+
         Returns True if A boundaries and interior does not intersect at all
         with those of B.
 
@@ -153,7 +161,8 @@ void init_predicates(py::module& m) {
           py::vectorize(TouchesPredicate()),
           py::arg("a"),
           py::arg("b"),
-          R"pbdoc(
+          R"pbdoc(touches(a, b)
+
         Returns True if A and B intersect, but their interiors do not intersect.
 
         A and B must have at least one point in common, where the common point
@@ -180,7 +189,8 @@ void init_predicates(py::module& m) {
               closed_options)),
           py::arg("a"),
           py::arg("b"),
-          R"pbdoc(
+          R"pbdoc(covers(a, b)
+
         Returns True if every point in B lies inside the interior or boundary of A.
 
         Parameters
@@ -206,7 +216,8 @@ void init_predicates(py::module& m) {
               closed_options)),
           py::arg("a"),
           py::arg("b"),
-          R"pbdoc(
+          R"pbdoc(covered_by(a, b)
+
         Returns True if every point in A lies inside the interior or boundary of B.
 
         Parameters

From bccbce740c6ff4badf9be4f41fb34df60def0a44 Mon Sep 17 00:00:00 2001
From: Benoit Bovy <benbovy@gmail.com>
Date: Tue, 10 Dec 2024 09:49:25 +0100
Subject: [PATCH 03/11] fix get_dimensions()

Return values that are consistent with shapely for collections.
---
 src/geography.cpp       | 18 +++++++++++++-----
 tests/test_geography.py | 20 ++++++++++++++++++++
 2 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/src/geography.cpp b/src/geography.cpp
index e118e60..4727dfa 100644
--- a/src/geography.cpp
+++ b/src/geography.cpp
@@ -8,6 +8,7 @@
 #include <s2/s2point.h>
 #include <s2/s2polygon.h>
 #include <s2/util/coding/coder.h>
+#include <s2geography/accessors.h>
 #include <s2geography/geography.h>
 #include <s2geography/predicates.h>
 #include <s2geography/wkt-writer.h>
@@ -228,7 +229,11 @@ std::int8_t get_type_id(PyObjectGeography obj) {
 }
 
 int get_dimensions(PyObjectGeography obj) {
-    return obj.as_geog_ptr()->dimension();
+    // note: in case of a collection with features of different dimensions:
+    // - Geography::dimension() returns -1
+    // - s2geography::s2_dimension(geog) returns the max value found in collection
+    // => we want the latter here.
+    return s2geog::s2_dimension(obj.as_geog_ptr()->geog());
 }
 
 /*
@@ -351,15 +356,18 @@ void init_geography(py::module &m) {
 
         Returns the inherent dimensionality of a geography.
 
-        The inherent dimension is 0 for points, 1 for linestrings and 2 for
-        polygons. For geometrycollections it is the max of the containing elements.
-        Empty collections and None values return -1.
-
         Parameters
         ----------
         geography : :py:class:`Geography` or array_like
             Geography object(s)
 
+        Returns
+        -------
+        dimensions : int or array
+            The inherent dimension is 0 for points, 1 for linestrings and 2 for
+            polygons. For geometrycollections it is either the max of the containing
+            elements or -1 for empty collections.
+
     )pbdoc");
 
     // Geography utils
diff --git a/tests/test_geography.py b/tests/test_geography.py
index 6713141..930bef5 100644
--- a/tests/test_geography.py
+++ b/tests/test_geography.py
@@ -85,6 +85,26 @@ def test_get_dimensions() -> None:
     assert spherely.get_dimensions(spherely.create_point(5, 40)) == 0
 
 
+@pytest.mark.parametrize(
+    "empty_geog, expected",
+    [
+        (spherely.create_point(), 0),
+        (spherely.create_linestring(), 1),
+        (spherely.create_polygon(), 2),
+        (spherely.create_collection([]), -1),
+    ],
+)
+def test_get_dimensions_empty(empty_geog, expected) -> None:
+    assert spherely.get_dimensions(empty_geog) == expected
+
+
+def test_get_dimensions_collection() -> None:
+    geog = spherely.create_collection(
+        [spherely.create_point(0, 0), spherely.create_polygon([(0, 0), (1, 1), (2, 0)])]
+    )
+    assert spherely.get_dimensions(geog) == 2
+
+
 def test_prepare() -> None:
     # test array
     geog = np.array(

From 6c12e6c1775cce03feb1005d0f53e56a1b69fae5 Mon Sep 17 00:00:00 2001
From: Benoit Bovy <benbovy@gmail.com>
Date: Tue, 10 Dec 2024 10:02:31 +0100
Subject: [PATCH 04/11] add more Returns sections in docstrings

---
 src/accessors-geog.cpp     |  6 +++---
 src/boolean-operations.cpp |  5 +++++
 src/geography.cpp          | 10 ++++++++++
 src/predicates.cpp         | 41 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/src/accessors-geog.cpp b/src/accessors-geog.cpp
index c0255c0..8bda46e 100644
--- a/src/accessors-geog.cpp
+++ b/src/accessors-geog.cpp
@@ -83,7 +83,7 @@ void init_accessors(py::module& m) {
         Returns
         -------
         Geography or array
-            A single or an array of POINT geography object(s).
+            A single or an array of POINT Geography object(s).
 
     )pbdoc");
 
@@ -103,7 +103,7 @@ void init_accessors(py::module& m) {
         -------
         Geography or array
             A single or an array of either (MULTI)POINT or (MULTI)LINESTRING
-            geography object(s).
+            Geography object(s).
 
     )pbdoc");
 
@@ -122,7 +122,7 @@ void init_accessors(py::module& m) {
         Returns
         -------
         Geography or array
-            A single or an array of POLYGON geography object(s).
+            A single or an array of POLYGON Geography object(s).
 
     )pbdoc");
 
diff --git a/src/boolean-operations.cpp b/src/boolean-operations.cpp
index 014c956..57e5b3e 100644
--- a/src/boolean-operations.cpp
+++ b/src/boolean-operations.cpp
@@ -52,6 +52,7 @@ void init_boolean_operations(py::module& m) {
         Returns
         -------
         Geography or array
+            New Geography object(s) representing the union of the input geographies.
 
     )pbdoc");
 
@@ -71,6 +72,7 @@ void init_boolean_operations(py::module& m) {
         Returns
         -------
         Geography or array
+            New Geography object(s) representing the interesction of the input geographies.
 
     )pbdoc");
 
@@ -90,6 +92,7 @@ void init_boolean_operations(py::module& m) {
         Returns
         -------
         Geography or array
+            New Geography object(s) representing the difference of the input geographies.
 
     )pbdoc");
 
@@ -109,6 +112,8 @@ void init_boolean_operations(py::module& m) {
         Returns
         -------
         Geography or array
+            New Geography object(s) representing the symmetric difference of
+            the input geographies.
 
     )pbdoc");
 }
diff --git a/src/geography.cpp b/src/geography.cpp
index 4727dfa..2526606 100644
--- a/src/geography.cpp
+++ b/src/geography.cpp
@@ -434,6 +434,11 @@ void init_geography(py::module &m) {
         geography : :py:class:`Geography` or array_like
             Geography object(s)
 
+        Returns
+        -------
+        prepared : Geography or array
+            The same input Geography object(s) with an attached index.
+
         See Also
         --------
         is_prepared
@@ -458,6 +463,11 @@ void init_geography(py::module &m) {
         geography : :py:class:`Geography` or array_like
             Geography object(s)
 
+        Returns
+        -------
+        unprepared : Geography or array
+            The same input Geography object(s) with no attached index.
+
         See Also
         --------
         is_prepared
diff --git a/src/predicates.cpp b/src/predicates.cpp
index ea416bc..16beb3e 100644
--- a/src/predicates.cpp
+++ b/src/predicates.cpp
@@ -83,6 +83,11 @@ void init_predicates(py::module& m) {
         a, b : :py:class:`Geography` or array_like
             Geography object(s)
 
+        Returns
+        -------
+        bool or array
+            Results of the ``intersects`` test.
+
     )pbdoc");
 
     m.def("equals",
@@ -101,6 +106,11 @@ void init_predicates(py::module& m) {
         a, b : :py:class:`Geography` or array_like
             Geography object(s)
 
+        Returns
+        -------
+        bool or array
+            Results of the ``equals`` test.
+
     )pbdoc");
 
     m.def("contains",
@@ -116,6 +126,11 @@ void init_predicates(py::module& m) {
         a, b : :py:class:`Geography` or array_like
             Geography object(s)
 
+        Returns
+        -------
+        bool or array
+            Results of the ``contains`` test.
+
     )pbdoc");
 
     m.def("within",
@@ -135,6 +150,11 @@ void init_predicates(py::module& m) {
         a, b : :py:class:`Geography` or array_like
             Geography object(s)
 
+        Returns
+        -------
+        bool or array
+            Results of the ``within`` test.
+
     )pbdoc");
 
     m.def("disjoint",
@@ -155,6 +175,11 @@ void init_predicates(py::module& m) {
         a, b : :py:class:`Geography` or array_like
             Geography object(s)
 
+        Returns
+        -------
+        bool or array
+            Results of the ``disjoint`` test.
+
     )pbdoc");
 
     m.def("touches",
@@ -173,6 +198,11 @@ void init_predicates(py::module& m) {
         a, b : :py:class:`Geography` or array_like
             Geography object(s)
 
+        Returns
+        -------
+        bool or array
+            Results of the ``touches`` test.
+
     )pbdoc");
 
     S2BooleanOperation::Options closed_options;
@@ -198,6 +228,11 @@ void init_predicates(py::module& m) {
         a, b : :py:class:`Geography` or array_like
             Geography object(s)
 
+        Returns
+        -------
+        bool or array
+            Results of the ``covers`` test.
+
         Notes
         -----
         If A and B are both polygons and share co-linear edges,
@@ -225,8 +260,14 @@ void init_predicates(py::module& m) {
         a, b : :py:class:`Geography` or array_like
             Geography object(s)
 
+        Returns
+        -------
+        bool or array
+            Results of the ``covered_by`` test.
+
         See Also
         --------
         covers
+
     )pbdoc");
 }

From 9a5b4ffc3fedbe7492691d0e309376eabbc9f2a2 Mon Sep 17 00:00:00 2001
From: Benoit Bovy <benbovy@gmail.com>
Date: Tue, 10 Dec 2024 10:56:56 +0100
Subject: [PATCH 05/11] add docstrings for Projection static methods

Also move Projection to api-hidden.
---
 docs/api.rst        |  1 -
 docs/api_hidden.rst |  4 ++++
 src/geoarrow.cpp    |  2 +-
 src/projections.cpp | 53 ++++++++++++++++++++++++++++++++++++++++-----
 src/projections.hpp |  1 -
 5 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/docs/api.rst b/docs/api.rst
index 0395f45..3d71cfc 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -53,7 +53,6 @@ Input/Output
    to_wkb
    from_geoarrow
    to_geoarrow
-   Projection
 
 .. _api_measurement:
 
diff --git a/docs/api_hidden.rst b/docs/api_hidden.rst
index 91f6127..12058bc 100644
--- a/docs/api_hidden.rst
+++ b/docs/api_hidden.rst
@@ -8,3 +8,7 @@
    Geography
    Geography.dimensions
    Geography.nshape
+   Projection
+   Projection.lnglat
+   Projection.pseudo_mercator
+   Projection.orthographic
diff --git a/src/geoarrow.cpp b/src/geoarrow.cpp
index f91a520..84c77d6 100644
--- a/src/geoarrow.cpp
+++ b/src/geoarrow.cpp
@@ -381,7 +381,7 @@ void init_geoarrow(py::module& m) {
         Returns
         -------
         ArrowArrayHolder
-            A generic Arrow array object with geograhies encoded to GeoArrow.
+            A generic Arrow array object with geographies encoded to GeoArrow.
 
         Examples
         --------
diff --git a/src/projections.cpp b/src/projections.cpp
index 9c2078b..6cdf34c 100644
--- a/src/projections.cpp
+++ b/src/projections.cpp
@@ -7,12 +7,55 @@
 #include "pybind11.hpp"
 
 namespace py = pybind11;
-namespace s2geog = s2geography;
 using namespace spherely;
 
 void init_projections(py::module& m) {
-    py::class_<Projection>(m, "Projection")
-        .def("lnglat", &Projection::lnglat)
-        .def("pseudo_mercator", &Projection::pseudo_mercator)
-        .def("orthographic", &Projection::orthographic);
+    py::class_<Projection> projection(m, "Projection", R"pbdoc(
+        Lightweight wrapper for selecting common reference systems used to
+        project Geography points or vertices.
+
+        Cannot be instanciated directly.
+
+    )pbdoc");
+
+    py::options options;
+    options.disable_function_signatures();
+
+    projection
+        .def_static("lnglat", &Projection::lnglat, R"pbdoc(lnglat()
+
+            Selects the "plate carree" projection.
+
+            This projection maps coordinates on the sphere to (longitude, latitude) pairs.
+            The x coordinates (longitude) span [-180, 180] and the y coordinates (latitude)
+            span [-90, 90].
+
+        )pbdoc")
+        .def_static("pseudo_mercator", &Projection::pseudo_mercator, R"pbdoc(pseudo_mercator()
+
+            Selects the spherical Mercator projection.
+
+            When used together with WGS84 coordinates, known as the "Web
+            Mercator" or "WGS84/Pseudo-Mercator" projection.
+
+        )pbdoc")
+        .def_static("orthographic",
+                    &Projection::orthographic,
+                    py::arg("longitude"),
+                    py::arg("latitude"),
+                    R"pbdoc(orthographic(longitude, latitude)
+
+            Selects an orthographic projection with the given centre point.
+
+            The resulting coordinates depict a single hemisphere of the globe as
+            it appears from outer space, centred on the given point.
+
+            Parameters
+            ----------
+            longitude : float
+                Longitude coordinate of the center point, in degrees.
+            latitude : float
+                Latitude coordinate of the center point, in degrees.
+
+        )pbdoc");
 }
diff --git a/src/projections.hpp b/src/projections.hpp
index 7989053..f91f9a0 100644
--- a/src/projections.hpp
+++ b/src/projections.hpp
@@ -7,7 +7,6 @@
 
 #include "pybind11.hpp"
 
-namespace py = pybind11;
 namespace s2geog = s2geography;
 using namespace spherely;
 

From c0fe6d59f04b61ee78aa481abb0e9d3e38f5a521 Mon Sep 17 00:00:00 2001
From: Benoit Bovy <benbovy@gmail.com>
Date: Tue, 10 Dec 2024 11:14:32 +0100
Subject: [PATCH 06/11] GeographyType: add docstrings and tests

---
 src/geography.cpp       | 26 ++++++++++++++++++--------
 tests/test_geography.py | 11 +++++++++++
 2 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/src/geography.cpp b/src/geography.cpp
index 2526606..3016183 100644
--- a/src/geography.cpp
+++ b/src/geography.cpp
@@ -270,14 +270,20 @@ void init_geography(py::module &m) {
         The enumeration of Geography types
     )pbdoc");
 
-    pygeography_types.value("NONE", GeographyType::None);
-    pygeography_types.value("POINT", GeographyType::Point);
-    pygeography_types.value("LINESTRING", GeographyType::LineString);
-    pygeography_types.value("POLYGON", GeographyType::Polygon);
-    pygeography_types.value("MULTIPOINT", GeographyType::MultiPoint);
-    pygeography_types.value("MULTILINESTRING", GeographyType::MultiLineString);
-    pygeography_types.value("MULTIPOLYGON", GeographyType::MultiPolygon);
-    pygeography_types.value("GEOMETRYCOLLECTION", GeographyType::GeometryCollection);
+    pygeography_types.value("NONE", GeographyType::None, "Undefined geography type (-1).");
+    pygeography_types.value("POINT", GeographyType::Point, "Single point geography type (0).");
+    pygeography_types.value(
+        "LINESTRING", GeographyType::LineString, "Single line geography type (1).");
+    pygeography_types.value(
+        "POLYGON", GeographyType::Polygon, "Single polygon geography type (2).");
+    pygeography_types.value(
+        "MULTIPOINT", GeographyType::MultiPoint, "Multiple point geography type (3).");
+    pygeography_types.value(
+        "MULTILINESTRING", GeographyType::MultiLineString, "Multiple line geography type (4).");
+    pygeography_types.value(
+        "MULTIPOLYGON", GeographyType::MultiPolygon, "Multiple polygon geography type (5).");
+    pygeography_types.value(
+        "GEOMETRYCOLLECTION", GeographyType::GeometryCollection, "Collection geography type (6).");
 
     // Geography classes
 
@@ -347,6 +353,10 @@ void init_geography(py::module &m) {
             POINT is 0, LINESTRING is 1, etc. See the ``value`` property of the
             :py:class:`GeographyType` enumeration.
 
+        See Also
+        --------
+        GeographyType
+
     )pbdoc");
 
     m.def("get_dimensions",
diff --git a/tests/test_geography.py b/tests/test_geography.py
index 930bef5..e3fa15c 100644
--- a/tests/test_geography.py
+++ b/tests/test_geography.py
@@ -6,6 +6,17 @@
 import spherely
 
 
+def test_geography_type() -> None:
+    assert spherely.GeographyType.NONE.value == -1
+    assert spherely.GeographyType.POINT.value == 0
+    assert spherely.GeographyType.LINESTRING.value == 1
+    assert spherely.GeographyType.POLYGON.value == 2
+    assert spherely.GeographyType.MULTIPOINT.value == 3
+    assert spherely.GeographyType.MULTILINESTRING.value == 4
+    assert spherely.GeographyType.MULTIPOLYGON.value == 5
+    assert spherely.GeographyType.GEOMETRYCOLLECTION.value == 6
+
+
 def test_is_geography() -> None:
     arr = np.array([1, 2.33, spherely.create_point(30, 6)])
 

From 932c99124a9446fb216bade71625b31d953b20bc Mon Sep 17 00:00:00 2001
From: Benoit Bovy <benbovy@gmail.com>
Date: Tue, 10 Dec 2024 11:32:14 +0100
Subject: [PATCH 07/11] Use "geography" as name for single arg functions

Also move get_x and get_y functions to geography.cpp (geography
properties).
---
 src/accessors-geog.cpp               | 114 +++++++--------------------
 src/boolean-operations.cpp           |   8 +-
 src/generate_spherely_vfunc_types.py |  12 +--
 src/geoarrow.cpp                     |  14 ++--
 src/geography.cpp                    |  64 +++++++++++++--
 src/io.cpp                           |  61 +++++++-------
 src/predicates.cpp                   |  16 ++--
 src/spherely.pyi                     |  10 ++-
 tests/test_accessors.py              |  31 --------
 tests/test_geography.py              |  31 ++++++++
 10 files changed, 182 insertions(+), 179 deletions(-)

diff --git a/src/accessors-geog.cpp b/src/accessors-geog.cpp
index 8bda46e..2cc1c60 100644
--- a/src/accessors-geog.cpp
+++ b/src/accessors-geog.cpp
@@ -26,22 +26,6 @@ PyObjectGeography convex_hull(PyObjectGeography a) {
     return make_py_geography(s2geog::s2_convex_hull(a_ptr));
 }
 
-double get_x(PyObjectGeography a) {
-    auto geog = a.as_geog_ptr();
-    if (geog->geog_type() != GeographyType::Point) {
-        throw py::value_error("Only Point geometries supported");
-    }
-    return s2geog::s2_x(geog->geog());
-}
-
-double get_y(PyObjectGeography a) {
-    auto geog = a.as_geog_ptr();
-    if (geog->geog_type() != GeographyType::Point) {
-        throw py::value_error("Only Point geometries supported");
-    }
-    return s2geog::s2_y(geog->geog());
-}
-
 double distance(PyObjectGeography a,
                 PyObjectGeography b,
                 double radius = numeric_constants::EARTH_RADIUS_METERS) {
@@ -70,15 +54,15 @@ void init_accessors(py::module& m) {
 
     m.def("centroid",
           py::vectorize(&centroid),
-          py::arg("a"),
-          R"pbdoc(centroid(a)
+          py::arg("geography"),
+          R"pbdoc(centroid(geography)
 
         Computes the centroid of each geography.
 
         Parameters
         ----------
-        a : :py:class:`Geography` or array_like
-            Geography object
+        geography : :py:class:`Geography` or array_like
+            Geography object(s).
 
         Returns
         -------
@@ -89,15 +73,15 @@ void init_accessors(py::module& m) {
 
     m.def("boundary",
           py::vectorize(&boundary),
-          py::arg("a"),
-          R"pbdoc(boundary(a)
+          py::arg("geography"),
+          R"pbdoc(boundary(geography)
 
         Computes the boundary of each geography.
 
         Parameters
         ----------
-        a : :py:class:`Geography` or array_like
-            Geography object
+        geography : :py:class:`Geography` or array_like
+            Geography object(s).
 
         Returns
         -------
@@ -109,15 +93,15 @@ void init_accessors(py::module& m) {
 
     m.def("convex_hull",
           py::vectorize(&convex_hull),
-          py::arg("a"),
-          R"pbdoc(convex_hull(a)
+          py::arg("geography"),
+          R"pbdoc(convex_hull(geography)
 
         Computes the convex hull of each geography.
 
         Parameters
         ----------
-        a : :py:class:`Geography` or array_like
-            Geography object
+        geography : :py:class:`Geography` or array_like
+            Geography object(s).
 
         Returns
         -------
@@ -126,44 +110,6 @@ void init_accessors(py::module& m) {
 
     )pbdoc");
 
-    m.def("get_x",
-          py::vectorize(&get_x),
-          py::arg("a"),
-          R"pbdoc(get_x(a)
-
-        Returns the longitude value of the Point (in degrees).
-
-        Parameters
-        ----------
-        a: :py:class:`Geography` or array_like
-            Geography object(s).
-
-        Returns
-        -------
-        float or array
-            Longitude coordinate value(s).
-
-    )pbdoc");
-
-    m.def("get_y",
-          py::vectorize(&get_y),
-          py::arg("a"),
-          R"pbdoc(get_y(a)
-
-        Returns the latitude value of the Point (in degrees).
-
-        Parameters
-        ----------
-        a: :py:class:`Geography` or array_like
-            Geography object(s).
-
-        Returns
-        -------
-        float or array
-            Latitude coordinate value(s).
-
-    )pbdoc");
-
     m.def("distance",
           py::vectorize(&distance),
           py::arg("a"),
@@ -176,11 +122,11 @@ void init_accessors(py::module& m) {
         Parameters
         ----------
         a : :py:class:`Geography` or array_like
-            Geography object
+            Geography object(s).
         b : :py:class:`Geography` or array_like
-            Geography object
+            Geography object(s).
         radius : float, optional
-            Radius of Earth in meters, default 6,371,010
+            Radius of Earth in meters, default 6,371,010.
 
         Returns
         -------
@@ -191,18 +137,18 @@ void init_accessors(py::module& m) {
 
     m.def("area",
           py::vectorize(&area),
-          py::arg("a"),
+          py::arg("geography"),
           py::arg("radius") = numeric_constants::EARTH_RADIUS_METERS,
-          R"pbdoc(area(a, radius=spherely.EARTH_RADIUS_METERS)
+          R"pbdoc(area(geography, radius=spherely.EARTH_RADIUS_METERS)
 
         Calculate the area of the geography.
 
         Parameters
         ----------
-        a : :py:class:`Geography` or array_like
-            Geography object
+        geography : :py:class:`Geography` or array_like
+            Geography object(s).
         radius : float, optional
-            Radius of Earth in meters, default 6,371,010
+            Radius of Earth in meters, default 6,371,010.
 
         Returns
         -------
@@ -213,18 +159,18 @@ void init_accessors(py::module& m) {
 
     m.def("length",
           py::vectorize(&length),
-          py::arg("a"),
+          py::arg("geography"),
           py::arg("radius") = numeric_constants::EARTH_RADIUS_METERS,
-          R"pbdoc(length(a, radius=spherely.EARTH_RADIUS_METERS)
+          R"pbdoc(length(geography, radius=spherely.EARTH_RADIUS_METERS)
 
         Calculates the length of a line geography, returning zero for other types.
 
         Parameters
         ----------
-        a : :py:class:`Geography` or array_like
-            Geography object
+        geography : :py:class:`Geography` or array_like
+            Geography object(s).
         radius : float, optional
-            Radius of Earth in meters, default 6,371,010
+            Radius of Earth in meters, default 6,371,010.
 
         Returns
         -------
@@ -235,18 +181,18 @@ void init_accessors(py::module& m) {
 
     m.def("perimeter",
           py::vectorize(&perimeter),
-          py::arg("a"),
+          py::arg("geography"),
           py::arg("radius") = numeric_constants::EARTH_RADIUS_METERS,
-          R"pbdoc(perimeter(a, radius=spherely.EARTH_RADIUS_METERS)
+          R"pbdoc(perimeter(geography, radius=spherely.EARTH_RADIUS_METERS)
 
         Calculates the perimeter of a polygon geography, returning zero for other types.
 
         Parameters
         ----------
-        a : :py:class:`Geography` or array_like
-            Geography object
+        geography : :py:class:`Geography` or array_like
+            Geography object(s).
         radius : float, optional
-            Radius of Earth in meters, default 6,371,010
+            Radius of Earth in meters, default 6,371,010.
 
         Returns
         -------
diff --git a/src/boolean-operations.cpp b/src/boolean-operations.cpp
index 57e5b3e..5104d71 100644
--- a/src/boolean-operations.cpp
+++ b/src/boolean-operations.cpp
@@ -47,7 +47,7 @@ void init_boolean_operations(py::module& m) {
         Parameters
         ----------
         a, b : :py:class:`Geography` or array_like
-            Geography object
+            Geography object(s).
 
         Returns
         -------
@@ -67,7 +67,7 @@ void init_boolean_operations(py::module& m) {
         Parameters
         ----------
         a, b : :py:class:`Geography` or array_like
-            Geography object
+            Geography object(s).
 
         Returns
         -------
@@ -87,7 +87,7 @@ void init_boolean_operations(py::module& m) {
         Parameters
         ----------
         a, b : :py:class:`Geography` or array_like
-            Geography object
+            Geography object(s).
 
         Returns
         -------
@@ -107,7 +107,7 @@ void init_boolean_operations(py::module& m) {
         Parameters
         ----------
         a, b : :py:class:`Geography` or array_like
-            Geography object
+            Geography object(s).
 
         Returns
         -------
diff --git a/src/generate_spherely_vfunc_types.py b/src/generate_spherely_vfunc_types.py
index 87a8537..0f20302 100644
--- a/src/generate_spherely_vfunc_types.py
+++ b/src/generate_spherely_vfunc_types.py
@@ -40,12 +40,12 @@ def update_stub_file(path, **type_specs):
 def _vfunctype_factory(class_name, n_in, **optargs):
     """Create new VFunc types.
 
-    Based on the number of input arrays and optional arguments and their types."""
-    arg_names = (
-        ["geography"]
-        if n_in == 1 and not optargs
-        else list(string.ascii_lowercase[:n_in])
-    )
+    Based on the number of input arrays and optional arguments and their types.
+    """
+    arg_names = list(string.ascii_lowercase[:n_in])
+    if n_in == 1:
+        arg_names[0] = "geography"
+
     class_code = [
         f"class {class_name}(",
         "    Generic[_NameType, _ScalarReturnType, _ArrayReturnDType]",
diff --git a/src/geoarrow.cpp b/src/geoarrow.cpp
index 84c77d6..6922cdd 100644
--- a/src/geoarrow.cpp
+++ b/src/geoarrow.cpp
@@ -264,7 +264,7 @@ void init_geoarrow(py::module& m) {
     m.def(
         "from_geoarrow",
         &from_geoarrow,
-        py::arg("input"),
+        py::arg("geographies"),
         py::pos_only(),
         py::kw_only(),
         py::arg("oriented") = false,
@@ -272,7 +272,7 @@ void init_geoarrow(py::module& m) {
         py::arg("tessellate_tolerance") = 100.0,
         py::arg("projection") = Projection::lnglat(),
         py::arg("geometry_encoding") = py::none(),
-        R"pbdoc(from_geoarrow(input, /, *, oriented=False, planar=False, tessellate_tolerance=100.0, projection=Projection.lnglat(), geometry_encoding=None)
+        R"pbdoc(from_geoarrow(geographies, /, *, oriented=False, planar=False, tessellate_tolerance=100.0, projection=Projection.lnglat(), geometry_encoding=None)
 
         Create an array of geographies from an Arrow array object with a GeoArrow
         extension type.
@@ -287,7 +287,7 @@ void init_geoarrow(py::module& m) {
 
         Parameters
         ----------
-        input : pyarrow.Array, Arrow array
+        geographies : pyarrow.Array, Arrow array
             Any array object implementing the Arrow PyCapsule Protocol
             (i.e. has a ``__arrow_c_array__`` method). The type of the array
             should be one of the geoarrow geometry types.
@@ -331,7 +331,7 @@ void init_geoarrow(py::module& m) {
     m.def(
         "to_geoarrow",
         &to_geoarrow,
-        py::arg("input"),
+        py::arg("geographies"),
         py::pos_only(),
         py::kw_only(),
         py::arg("output_schema") = py::none(),
@@ -339,7 +339,7 @@ void init_geoarrow(py::module& m) {
         py::arg("planar") = false,
         py::arg("tessellate_tolerance") = 100.0,
         py::arg("precision") = 6,
-        R"pbdoc(to_geoarrow(input, /, *, output_schema=None, projection=Projection.lnglat(), planar=False, tessellate_tolerance=100.0, precision=6)
+        R"pbdoc(to_geoarrow(geographies, /, *, output_schema=None, projection=Projection.lnglat(), planar=False, tessellate_tolerance=100.0, precision=6)
 
         Convert an array of geographies to an Arrow array object with a GeoArrow
         extension type.
@@ -348,8 +348,8 @@ void init_geoarrow(py::module& m) {
 
         Parameters
         ----------
-        input : array_like
-            An array of geography objects.
+        geographies : array_like
+            An array of :py:class:`~spherely.Geography` objects.
         output_schema : Arrow schema, pyarrow.DataType, pyarrow.Field, default None
             The geoarrow extension type to use for the output. This can indicate
             one of the native geoarrow types (e.g. "point", "linestring", "polygon",
diff --git a/src/geography.cpp b/src/geography.cpp
index 3016183..92e08f4 100644
--- a/src/geography.cpp
+++ b/src/geography.cpp
@@ -236,6 +236,22 @@ int get_dimensions(PyObjectGeography obj) {
     return s2geog::s2_dimension(obj.as_geog_ptr()->geog());
 }
 
+double get_x(PyObjectGeography obj) {
+    auto geog = obj.as_geog_ptr();
+    if (geog->geog_type() != GeographyType::Point) {
+        throw py::value_error("Only Point geometries supported");
+    }
+    return s2geog::s2_x(geog->geog());
+}
+
+double get_y(PyObjectGeography obj) {
+    auto geog = obj.as_geog_ptr();
+    if (geog->geog_type() != GeographyType::Point) {
+        throw py::value_error("Only Point geometries supported");
+    }
+    return s2geog::s2_y(geog->geog());
+}
+
 /*
 ** Geography utils
 */
@@ -267,7 +283,7 @@ void init_geography(py::module &m) {
     // Geography types
 
     auto pygeography_types = py::enum_<GeographyType>(m, "GeographyType", py::arithmetic(), R"pbdoc(
-        The enumeration of Geography types
+        The enumeration of Geography types.
     )pbdoc");
 
     pygeography_types.value("NONE", GeographyType::None, "Undefined geography type (-1).");
@@ -369,7 +385,7 @@ void init_geography(py::module &m) {
         Parameters
         ----------
         geography : :py:class:`Geography` or array_like
-            Geography object(s)
+            Geography object(s).
 
         Returns
         -------
@@ -380,6 +396,44 @@ void init_geography(py::module &m) {
 
     )pbdoc");
 
+    m.def("get_x",
+          py::vectorize(&get_x),
+          py::arg("geography"),
+          R"pbdoc(get_x(geography)
+
+        Returns the longitude value of the Point (in degrees).
+
+        Parameters
+        ----------
+        geography: :py:class:`Geography` or array_like
+            POINT Geography object(s).
+
+        Returns
+        -------
+        float or array
+            Longitude coordinate value(s).
+
+    )pbdoc");
+
+    m.def("get_y",
+          py::vectorize(&get_y),
+          py::arg("geography"),
+          R"pbdoc(get_y(geography)
+
+        Returns the latitude value of the Point (in degrees).
+
+        Parameters
+        ----------
+        geography: :py:class:`Geography` or array_like
+            POINT Geography object(s).
+
+        Returns
+        -------
+        float or array
+            Latitude coordinate value(s).
+
+    )pbdoc");
+
     // Geography utils
 
     m.def("is_geography",
@@ -415,7 +469,7 @@ void init_geography(py::module &m) {
         Parameters
         ----------
         geography : :py:class:`Geography` or array_like
-            Geography object(s)
+            Geography object(s).
 
         See Also
         --------
@@ -442,7 +496,7 @@ void init_geography(py::module &m) {
         Parameters
         ----------
         geography : :py:class:`Geography` or array_like
-            Geography object(s)
+            Geography object(s).
 
         Returns
         -------
@@ -471,7 +525,7 @@ void init_geography(py::module &m) {
         Parameters
         ----------
         geography : :py:class:`Geography` or array_like
-            Geography object(s)
+            Geography object(s).
 
         Returns
         -------
diff --git a/src/io.cpp b/src/io.cpp
index 0732933..85e0a4d 100644
--- a/src/io.cpp
+++ b/src/io.cpp
@@ -23,8 +23,8 @@ class FromWKT {
         m_reader = std::make_shared<s2geog::WKTReader>(options);
     }
 
-    PyObjectGeography operator()(py::str a) const {
-        return make_py_geography(m_reader->read_feature(a));
+    PyObjectGeography operator()(py::str string) const {
+        return make_py_geography(m_reader->read_feature(string));
     }
 
 private:
@@ -37,8 +37,8 @@ class ToWKT {
         m_writer = std::make_shared<s2geog::WKTWriter>(precision);
     }
 
-    py::str operator()(PyObjectGeography a) const {
-        auto res = m_writer->write_feature(a.as_geog_ptr()->geog());
+    py::str operator()(PyObjectGeography obj) const {
+        auto res = m_writer->write_feature(obj.as_geog_ptr()->geog());
         return py::str(res);
     }
 
@@ -59,8 +59,8 @@ class FromWKB {
         m_reader = std::make_shared<s2geog::WKBReader>(options);
     }
 
-    PyObjectGeography operator()(py::bytes a) const {
-        return make_py_geography(m_reader->ReadFeature(a));
+    PyObjectGeography operator()(py::bytes bytes) const {
+        return make_py_geography(m_reader->ReadFeature(bytes));
     }
 
 private:
@@ -73,8 +73,8 @@ class ToWKB {
         m_writer = std::make_shared<s2geog::WKBWriter>();
     }
 
-    py::bytes operator()(PyObjectGeography a) const {
-        return m_writer->WriteFeature(a.as_geog_ptr()->geog());
+    py::bytes operator()(PyObjectGeography obj) const {
+        return m_writer->WriteFeature(obj.as_geog_ptr()->geog());
     }
 
 private:
@@ -87,21 +87,22 @@ void init_io(py::module& m) {
 
     m.def(
         "from_wkt",
-        [](py::array_t<py::str> a, bool oriented, bool planar, float tessellate_tolerance) {
-            return py::vectorize(FromWKT(oriented, planar, tessellate_tolerance))(std::move(a));
+        [](py::array_t<py::str> string, bool oriented, bool planar, float tessellate_tolerance) {
+            return py::vectorize(FromWKT(oriented, planar, tessellate_tolerance))(
+                std::move(string));
         },
-        py::arg("a"),
+        py::arg("geography"),
         py::arg("oriented") = false,
         py::arg("planar") = false,
         py::arg("tessellate_tolerance") = 100.0,
-        R"pbdoc(from_wkt(a, oriented=False, planar=False, tessellate_tolerance=100.0)
+        R"pbdoc(from_wkt(geography, oriented=False, planar=False, tessellate_tolerance=100.0)
 
         Creates geographies from the Well-Known Text (WKT) representation.
 
         Parameters
         ----------
-        a : str or array_like
-            WKT strings.
+        geography : str or array_like
+            The WKT string(s) to convert.
         oriented : bool, default False
             Set to True if polygon ring directions are known to be correct
             (i.e., exterior rings are defined counter clockwise and interior
@@ -129,19 +130,19 @@ void init_io(py::module& m) {
 
     m.def(
         "to_wkt",
-        [](py::array_t<PyObjectGeography> a, int precision) {
-            return py::vectorize(ToWKT(precision))(std::move(a));
+        [](py::array_t<PyObjectGeography> obj, int precision) {
+            return py::vectorize(ToWKT(precision))(std::move(obj));
         },
-        py::arg("a"),
+        py::arg("geography"),
         py::arg("precision") = 6,
-        R"pbdoc(to_wkt(a, precision=6)
+        R"pbdoc(to_wkt(geography, precision=6)
 
         Returns the WKT representation of each geography.
 
         Parameters
         ----------
-        a : :py:class:`Geography` or array_like
-            Geography object(s)
+        geography : :py:class:`Geography` or array_like
+            Geography object(s).
         precision : int, default 6
             The number of decimal places to include in the output.
 
@@ -154,21 +155,21 @@ void init_io(py::module& m) {
 
     m.def(
         "from_wkb",
-        [](py::array_t<py::bytes> a, bool oriented, bool planar, float tessellate_tolerance) {
-            return py::vectorize(FromWKB(oriented, planar, tessellate_tolerance))(std::move(a));
+        [](py::array_t<py::bytes> bytes, bool oriented, bool planar, float tessellate_tolerance) {
+            return py::vectorize(FromWKB(oriented, planar, tessellate_tolerance))(std::move(bytes));
         },
-        py::arg("a"),
+        py::arg("geography"),
         py::arg("oriented") = false,
         py::arg("planar") = false,
         py::arg("tessellate_tolerance") = 100.0,
-        R"pbdoc(from_wkb(a, oriented=False, planar=False, tessellate_tolerance=100.0)
+        R"pbdoc(from_wkb(geography, oriented=False, planar=False, tessellate_tolerance=100.0)
 
         Creates geographies from the Well-Known Bytes (WKB) representation.
 
         Parameters
         ----------
-        a : bytes or array_like
-            WKB objects.
+        geography : bytes or array_like
+            The WKB byte object(s) to convert.
         oriented : bool, default False
             Set to True if polygon ring directions are known to be correct
             (i.e., exterior rings are defined counter clockwise and interior
@@ -196,15 +197,15 @@ void init_io(py::module& m) {
 
     m.def("to_wkb",
           py::vectorize(ToWKB()),
-          py::arg("a"),
-          R"pbdoc(to_wkb(a)
+          py::arg("geography"),
+          R"pbdoc(to_wkb(geography)
 
         Returns the WKB representation of each geography.
 
         Parameters
         ----------
-        a : :py:class:`Geography` or array_like
-            Geography object(s)
+        geography : :py:class:`Geography` or array_like
+            Geography object(s).
 
         Returns
         -------
diff --git a/src/predicates.cpp b/src/predicates.cpp
index 16beb3e..eebe6da 100644
--- a/src/predicates.cpp
+++ b/src/predicates.cpp
@@ -81,7 +81,7 @@ void init_predicates(py::module& m) {
         Parameters
         ----------
         a, b : :py:class:`Geography` or array_like
-            Geography object(s)
+            Geography object(s).
 
         Returns
         -------
@@ -104,7 +104,7 @@ void init_predicates(py::module& m) {
         Parameters
         ----------
         a, b : :py:class:`Geography` or array_like
-            Geography object(s)
+            Geography object(s).
 
         Returns
         -------
@@ -124,7 +124,7 @@ void init_predicates(py::module& m) {
         Parameters
         ----------
         a, b : :py:class:`Geography` or array_like
-            Geography object(s)
+            Geography object(s).
 
         Returns
         -------
@@ -148,7 +148,7 @@ void init_predicates(py::module& m) {
         Parameters
         ----------
         a, b : :py:class:`Geography` or array_like
-            Geography object(s)
+            Geography object(s).
 
         Returns
         -------
@@ -173,7 +173,7 @@ void init_predicates(py::module& m) {
         Parameters
         ----------
         a, b : :py:class:`Geography` or array_like
-            Geography object(s)
+            Geography object(s).
 
         Returns
         -------
@@ -196,7 +196,7 @@ void init_predicates(py::module& m) {
         Parameters
         ----------
         a, b : :py:class:`Geography` or array_like
-            Geography object(s)
+            Geography object(s).
 
         Returns
         -------
@@ -226,7 +226,7 @@ void init_predicates(py::module& m) {
         Parameters
         ----------
         a, b : :py:class:`Geography` or array_like
-            Geography object(s)
+            Geography object(s).
 
         Returns
         -------
@@ -258,7 +258,7 @@ void init_predicates(py::module& m) {
         Parameters
         ----------
         a, b : :py:class:`Geography` or array_like
-            Geography object(s)
+            Geography object(s).
 
         Returns
         -------
diff --git a/src/spherely.pyi b/src/spherely.pyi
index 61a172e..9307990 100644
--- a/src/spherely.pyi
+++ b/src/spherely.pyi
@@ -142,11 +142,11 @@ class _VFunc_Nin1optradius_Nout1(
     def __name__(self) -> _NameType: ...
     @overload
     def __call__(
-        self, a: Geography, radius: float = 6371010.0
+        self, geography: Geography, radius: float = 6371010.0
     ) -> _ScalarReturnType: ...
     @overload
     def __call__(
-        self, a: Iterable[Geography], radius: float = 6371010.0
+        self, geography: Iterable[Geography], radius: float = 6371010.0
     ) -> npt.NDArray[_ArrayReturnDType]: ...
 
 class _VFunc_Nin1optprecision_Nout1(
@@ -155,10 +155,12 @@ class _VFunc_Nin1optprecision_Nout1(
     @property
     def __name__(self) -> _NameType: ...
     @overload
-    def __call__(self, a: Geography, precision: int = 6) -> _ScalarReturnType: ...
+    def __call__(
+        self, geography: Geography, precision: int = 6
+    ) -> _ScalarReturnType: ...
     @overload
     def __call__(
-        self, a: Iterable[Geography], precision: int = 6
+        self, geography: Iterable[Geography], precision: int = 6
     ) -> npt.NDArray[_ArrayReturnDType]: ...
 
 # /// End types
diff --git a/tests/test_accessors.py b/tests/test_accessors.py
index bdf4128..9c74451 100644
--- a/tests/test_accessors.py
+++ b/tests/test_accessors.py
@@ -87,37 +87,6 @@ def test_convex_hull(geog, expected) -> None:
     assert spherely.equals(actual, expected)
 
 
-def test_get_x_y() -> None:
-    # scalar
-    a = spherely.create_point(1.5, 2.6)
-    assert spherely.get_x(a) == pytest.approx(1.5, abs=1e-14)
-    assert spherely.get_y(a) == pytest.approx(2.6, abs=1e-14)
-
-    # array
-    arr = np.array(
-        [
-            spherely.create_point(0, 1),
-            spherely.create_point(1, 2),
-            spherely.create_point(2, 3),
-        ]
-    )
-
-    actual = spherely.get_x(arr)
-    expected = np.array([0, 1, 2], dtype="float64")
-    np.testing.assert_allclose(actual, expected)
-
-    actual = spherely.get_y(arr)
-    expected = np.array([1, 2, 3], dtype="float64")
-    np.testing.assert_allclose(actual, expected)
-
-    # only points are supported
-    with pytest.raises(ValueError):
-        spherely.get_x(spherely.create_linestring([(0, 1), (1, 2)]))
-
-    with pytest.raises(ValueError):
-        spherely.get_y(spherely.create_linestring([(0, 1), (1, 2)]))
-
-
 @pytest.mark.parametrize(
     "geog_a, geog_b, expected",
     [
diff --git a/tests/test_geography.py b/tests/test_geography.py
index e3fa15c..fd676d2 100644
--- a/tests/test_geography.py
+++ b/tests/test_geography.py
@@ -96,6 +96,37 @@ def test_get_dimensions() -> None:
     assert spherely.get_dimensions(spherely.create_point(5, 40)) == 0
 
 
+def test_get_x_y() -> None:
+    # scalar
+    a = spherely.create_point(1.5, 2.6)
+    assert spherely.get_x(a) == pytest.approx(1.5, abs=1e-14)
+    assert spherely.get_y(a) == pytest.approx(2.6, abs=1e-14)
+
+    # array
+    arr = np.array(
+        [
+            spherely.create_point(0, 1),
+            spherely.create_point(1, 2),
+            spherely.create_point(2, 3),
+        ]
+    )
+
+    actual = spherely.get_x(arr)
+    expected = np.array([0, 1, 2], dtype="float64")
+    np.testing.assert_allclose(actual, expected)
+
+    actual = spherely.get_y(arr)
+    expected = np.array([1, 2, 3], dtype="float64")
+    np.testing.assert_allclose(actual, expected)
+
+    # only points are supported
+    with pytest.raises(ValueError):
+        spherely.get_x(spherely.create_linestring([(0, 1), (1, 2)]))
+
+    with pytest.raises(ValueError):
+        spherely.get_y(spherely.create_linestring([(0, 1), (1, 2)]))
+
+
 @pytest.mark.parametrize(
     "empty_geog, expected",
     [

From 0040695be781a251e3b1ea0b34b2f5a49d962dae Mon Sep 17 00:00:00 2001
From: Benoit Bovy <benbovy@gmail.com>
Date: Tue, 10 Dec 2024 12:30:12 +0100
Subject: [PATCH 08/11] doc API: add description for each subsection

---
 docs/api.rst | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/docs/api.rst b/docs/api.rst
index 3d71cfc..1d8935a 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -10,6 +10,9 @@ API reference
 Geography properties
 --------------------
 
+Functions that provide access to properties of :py:class:`~spherely.Geography`
+objects without side-effects (except for ``prepare`` and ``destroy_prepared``).
+
 .. autosummary::
    :toctree: _api_generated/
 
@@ -28,6 +31,9 @@ Geography properties
 Geography creation
 ------------------
 
+Functions that build new :py:class:`~spherely.Geography` objects from
+coordinates or existing geographies.
+
 .. autosummary::
    :toctree: _api_generated/
 
@@ -44,6 +50,9 @@ Geography creation
 Input/Output
 ------------
 
+Functions that convert :py:class:`~spherely.Geography` objects to/from an
+external format such as `WKT <https://en.wikipedia.org/wiki/Well-known_text>`_.
+
 .. autosummary::
    :toctree: _api_generated/
 
@@ -59,6 +68,8 @@ Input/Output
 Measurement
 -----------
 
+Functions that compute measurements of one or more geographies.
+
 .. autosummary::
    :toctree: _api_generated/
 
@@ -72,6 +83,9 @@ Measurement
 Predicates
 ----------
 
+Functions that return ``True`` or ``False`` for some spatial relationship
+between two geographies.
+
 .. autosummary::
    :toctree: _api_generated/
 
@@ -89,6 +103,9 @@ Predicates
 Overlays (boolean operations)
 -----------------------------
 
+Functions that generate a new geography based on the combination of two
+geographies.
+
 .. autosummary::
    :toctree: _api_generated/
 
@@ -102,6 +119,8 @@ Overlays (boolean operations)
 Constructive operations
 -----------------------
 
+Functions that generate a new geography based on input.
+
 .. autosummary::
    :toctree: _api_generated/
 

From 06a5bd40bfb1b8f31f55feb387c692d435954494 Mon Sep 17 00:00:00 2001
From: Benoit Bovy <benbovy@gmail.com>
Date: Wed, 11 Dec 2024 13:28:31 +0100
Subject: [PATCH 09/11] add (py)arrow to intersphinx

---
 docs/conf.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/docs/conf.py b/docs/conf.py
index a504411..1af5f37 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -18,6 +18,7 @@
     "python": ("https://docs.python.org/3", None),
     "numpy": ("https://numpy.org/doc/stable", None),
     "shapely": ("https://shapely.readthedocs.io/en/latest/", None),
+    "pyarrow": ("https://arrow.apache.org/docs/", None),
 }
 
 # TODO: seem to have no effect

From ac3bcf36ecdca7ae1f89bfbc540b0bb18a8da4d6 Mon Sep 17 00:00:00 2001
From: Benoit Bovy <benbovy@gmail.com>
Date: Thu, 19 Dec 2024 21:07:11 +0100
Subject: [PATCH 10/11] review comments

---
 docs/conf.py               |  4 ----
 src/accessors-geog.cpp     |  3 ---
 src/boolean-operations.cpp |  5 +----
 src/creation.cpp           |  3 ---
 src/geoarrow.cpp           |  7 ++-----
 src/geography.cpp          | 25 +++++++++++++++++--------
 src/io.cpp                 |  3 ---
 src/predicates.cpp         | 11 -----------
 src/projections.cpp        |  5 +----
 src/spherely.cpp           |  3 +++
 10 files changed, 24 insertions(+), 45 deletions(-)

diff --git a/docs/conf.py b/docs/conf.py
index 1af5f37..10fd3db 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -21,10 +21,6 @@
     "pyarrow": ("https://arrow.apache.org/docs/", None),
 }
 
-# TODO: seem to have no effect
-# (see https://github.com/sphinx-doc/sphinx/issues/10235)
-autodoc_typehints = "none"
-
 napoleon_google_docstring = False
 napoleon_numpy_docstring = True
 napoleon_use_param = False
diff --git a/src/accessors-geog.cpp b/src/accessors-geog.cpp
index 2cc1c60..b71d93c 100644
--- a/src/accessors-geog.cpp
+++ b/src/accessors-geog.cpp
@@ -47,9 +47,6 @@ double perimeter(PyObjectGeography a, double radius = numeric_constants::EARTH_R
 }
 
 void init_accessors(py::module& m) {
-    py::options options;
-    options.disable_function_signatures();
-
     m.attr("EARTH_RADIUS_METERS") = py::float_(numeric_constants::EARTH_RADIUS_METERS);
 
     m.def("centroid",
diff --git a/src/boolean-operations.cpp b/src/boolean-operations.cpp
index 5104d71..f04ef4d 100644
--- a/src/boolean-operations.cpp
+++ b/src/boolean-operations.cpp
@@ -33,9 +33,6 @@ class BooleanOp {
 };
 
 void init_boolean_operations(py::module& m) {
-    py::options options;
-    options.disable_function_signatures();
-
     m.def("union",
           py::vectorize(BooleanOp(S2BooleanOperation::OpType::UNION)),
           py::arg("a"),
@@ -72,7 +69,7 @@ void init_boolean_operations(py::module& m) {
         Returns
         -------
         Geography or array
-            New Geography object(s) representing the interesction of the input geographies.
+            New Geography object(s) representing the intersection of the input geographies.
 
     )pbdoc");
 
diff --git a/src/creation.cpp b/src/creation.cpp
index 0be4ee4..92ffe70 100644
--- a/src/creation.cpp
+++ b/src/creation.cpp
@@ -291,9 +291,6 @@ std::unique_ptr<Geography> create_collection(const std::vector<Geography *> &fea
 //
 
 void init_creation(py::module &m) {
-    py::options options;
-    options.disable_function_signatures();
-
     // ----- scalar Geography creation functions
 
     m.def(
diff --git a/src/geoarrow.cpp b/src/geoarrow.cpp
index 6922cdd..0ad8f61 100644
--- a/src/geoarrow.cpp
+++ b/src/geoarrow.cpp
@@ -255,9 +255,6 @@ ArrowArrayHolder to_geoarrow(py::array_t<PyObjectGeography> input,
 }
 
 void init_geoarrow(py::module& m) {
-    py::options options;
-    options.disable_function_signatures();
-
     py::class_<ArrowArrayHolder>(m, "ArrowArrayHolder")
         .def("__arrow_c_array__", &ArrowArrayHolder::return_capsules);
 
@@ -272,7 +269,7 @@ void init_geoarrow(py::module& m) {
         py::arg("tessellate_tolerance") = 100.0,
         py::arg("projection") = Projection::lnglat(),
         py::arg("geometry_encoding") = py::none(),
-        R"pbdoc(from_geoarrow(geographies, /, *, oriented=False, planar=False, tessellate_tolerance=100.0, projection=Projection.lnglat(), geometry_encoding=None)
+        R"pbdoc(from_geoarrow(geographies, /, *, oriented=False, planar=False, tessellate_tolerance=100.0, projection=spherely.Projection.lnglat(), geometry_encoding=None)
 
         Create an array of geographies from an Arrow array object with a GeoArrow
         extension type.
@@ -339,7 +336,7 @@ void init_geoarrow(py::module& m) {
         py::arg("planar") = false,
         py::arg("tessellate_tolerance") = 100.0,
         py::arg("precision") = 6,
-        R"pbdoc(to_geoarrow(geographies, /, *, output_schema=None, projection=Projection.lnglat(), planar=False, tessellate_tolerance=100.0, precision=6)
+        R"pbdoc(to_geoarrow(geographies, /, *, output_schema=None, projection=spherely.Projection.lnglat(), planar=False, tessellate_tolerance=100.0, precision=6)
 
         Convert an array of geographies to an Arrow array object with a GeoArrow
         extension type.
diff --git a/src/geography.cpp b/src/geography.cpp
index 92e08f4..ec0c2f6 100644
--- a/src/geography.cpp
+++ b/src/geography.cpp
@@ -282,9 +282,8 @@ PyObjectGeography destroy_prepared(PyObjectGeography obj) {
 void init_geography(py::module &m) {
     // Geography types
 
-    auto pygeography_types = py::enum_<GeographyType>(m, "GeographyType", py::arithmetic(), R"pbdoc(
-        The enumeration of Geography types.
-    )pbdoc");
+    auto pygeography_types = py::enum_<GeographyType>(
+        m, "GeographyType", py::arithmetic(), "The enumeration of Geography types.");
 
     pygeography_types.value("NONE", GeographyType::None, "Undefined geography type (-1).");
     pygeography_types.value("POINT", GeographyType::Point, "Single point geography type (0).");
@@ -345,9 +344,6 @@ void init_geography(py::module &m) {
     pygeography.def(py::pickle([](Geography &geog) { return geog.encode(); },
                                [](py::tuple &encoded) { return Geography::decode(encoded); }));
 
-    py::options options;
-    options.disable_function_signatures();
-
     // Geography properties
 
     m.def("get_type_id",
@@ -357,6 +353,15 @@ void init_geography(py::module &m) {
 
         Returns the type ID of a geography.
 
+        - None (missing) is -1
+        - POINT is 0
+        - LINESTRING is 1
+        - POLYGON is 2
+        - MULTIPOINT is 3
+        - MULTILINESTRING is 4
+        - MULTIPOLYGON is 5
+        - GEOMETRYCOLLECTION is 6
+
         Parameters
         ----------
         geography : :py:class:`Geography` or array_like
@@ -365,8 +370,8 @@ void init_geography(py::module &m) {
         Returns
         -------
         type_id : int or array
-            The type id(s) of the input geography object(s). None (missing) is -1,
-            POINT is 0, LINESTRING is 1, etc. See the ``value`` property of the
+            The type id(s) of the input geography object(s).
+            See also the ``value`` property of the
             :py:class:`GeographyType` enumeration.
 
         See Also
@@ -493,6 +498,8 @@ void init_geography(py::module &m) {
         efficient to call this function on an array that partially contains
         prepared geographies.
 
+        This function updates the input geographies in-place!
+
         Parameters
         ----------
         geography : :py:class:`Geography` or array_like
@@ -522,6 +529,8 @@ void init_geography(py::module &m) {
         very specific circumstances, such as freeing up memory without losing
         the geographies, or benchmarking.
 
+        This function updates the input geographies in-place!
+
         Parameters
         ----------
         geography : :py:class:`Geography` or array_like
diff --git a/src/io.cpp b/src/io.cpp
index 85e0a4d..5b7004e 100644
--- a/src/io.cpp
+++ b/src/io.cpp
@@ -82,9 +82,6 @@ class ToWKB {
 };
 
 void init_io(py::module& m) {
-    py::options options;
-    options.disable_function_signatures();
-
     m.def(
         "from_wkt",
         [](py::array_t<py::str> string, bool oriented, bool planar, float tessellate_tolerance) {
diff --git a/src/predicates.cpp b/src/predicates.cpp
index eebe6da..521dfc5 100644
--- a/src/predicates.cpp
+++ b/src/predicates.cpp
@@ -65,9 +65,6 @@ class TouchesPredicate {
 };
 
 void init_predicates(py::module& m) {
-    py::options options;
-    options.disable_function_signatures();
-
     m.def("intersects",
           py::vectorize(Predicate(s2geog::s2_intersects)),
           py::arg("a"),
@@ -86,7 +83,6 @@ void init_predicates(py::module& m) {
         Returns
         -------
         bool or array
-            Results of the ``intersects`` test.
 
     )pbdoc");
 
@@ -109,7 +105,6 @@ void init_predicates(py::module& m) {
         Returns
         -------
         bool or array
-            Results of the ``equals`` test.
 
     )pbdoc");
 
@@ -129,7 +124,6 @@ void init_predicates(py::module& m) {
         Returns
         -------
         bool or array
-            Results of the ``contains`` test.
 
     )pbdoc");
 
@@ -153,7 +147,6 @@ void init_predicates(py::module& m) {
         Returns
         -------
         bool or array
-            Results of the ``within`` test.
 
     )pbdoc");
 
@@ -178,7 +171,6 @@ void init_predicates(py::module& m) {
         Returns
         -------
         bool or array
-            Results of the ``disjoint`` test.
 
     )pbdoc");
 
@@ -201,7 +193,6 @@ void init_predicates(py::module& m) {
         Returns
         -------
         bool or array
-            Results of the ``touches`` test.
 
     )pbdoc");
 
@@ -231,7 +222,6 @@ void init_predicates(py::module& m) {
         Returns
         -------
         bool or array
-            Results of the ``covers`` test.
 
         Notes
         -----
@@ -263,7 +253,6 @@ void init_predicates(py::module& m) {
         Returns
         -------
         bool or array
-            Results of the ``covered_by`` test.
 
         See Also
         --------
diff --git a/src/projections.cpp b/src/projections.cpp
index 6cdf34c..c5fefad 100644
--- a/src/projections.cpp
+++ b/src/projections.cpp
@@ -14,13 +14,10 @@ void init_projections(py::module& m) {
         Lightweight wrapper for selecting common reference systems used to
         project Geography points or vertices.
 
-        Cannot be instanciated directly.
+        Cannot be instantiated directly.
 
     )pbdoc");
 
-    py::options options;
-    options.disable_function_signatures();
-
     projection
         .def_static("lnglat", &Projection::lnglat, R"pbdoc(lnglat()
 
diff --git a/src/spherely.cpp b/src/spherely.cpp
index fe28991..1f4dce7 100644
--- a/src/spherely.cpp
+++ b/src/spherely.cpp
@@ -15,6 +15,9 @@ void init_geoarrow(py::module&);
 void init_projections(py::module&);
 
 PYBIND11_MODULE(spherely, m) {
+    py::options options;
+    options.disable_function_signatures();
+
     m.doc() = R"pbdoc(
         Spherely
         ---------

From 6c506a1f420d69ef0c33a4280277e0670c61975d Mon Sep 17 00:00:00 2001
From: Benoit Bovy <benbovy@gmail.com>
Date: Thu, 19 Dec 2024 22:01:46 +0100
Subject: [PATCH 11/11] 1-arg vectorized funcs: pos only

---
 src/accessors-geog.cpp               | 18 ++++++++++------
 src/generate_spherely_vfunc_types.py |  2 ++
 src/geography.cpp                    | 24 ++++++++++++++-------
 src/io.cpp                           | 14 ++++++++----
 src/spherely.pyi                     | 32 +++++++++++++++++-----------
 5 files changed, 60 insertions(+), 30 deletions(-)

diff --git a/src/accessors-geog.cpp b/src/accessors-geog.cpp
index b71d93c..9b894f2 100644
--- a/src/accessors-geog.cpp
+++ b/src/accessors-geog.cpp
@@ -52,7 +52,8 @@ void init_accessors(py::module& m) {
     m.def("centroid",
           py::vectorize(&centroid),
           py::arg("geography"),
-          R"pbdoc(centroid(geography)
+          py::pos_only(),
+          R"pbdoc(centroid(geography, /)
 
         Computes the centroid of each geography.
 
@@ -71,7 +72,8 @@ void init_accessors(py::module& m) {
     m.def("boundary",
           py::vectorize(&boundary),
           py::arg("geography"),
-          R"pbdoc(boundary(geography)
+          py::pos_only(),
+          R"pbdoc(boundary(geography, /)
 
         Computes the boundary of each geography.
 
@@ -91,7 +93,8 @@ void init_accessors(py::module& m) {
     m.def("convex_hull",
           py::vectorize(&convex_hull),
           py::arg("geography"),
-          R"pbdoc(convex_hull(geography)
+          py::pos_only(),
+          R"pbdoc(convex_hull(geography, /)
 
         Computes the convex hull of each geography.
 
@@ -135,8 +138,9 @@ void init_accessors(py::module& m) {
     m.def("area",
           py::vectorize(&area),
           py::arg("geography"),
+          py::pos_only(),
           py::arg("radius") = numeric_constants::EARTH_RADIUS_METERS,
-          R"pbdoc(area(geography, radius=spherely.EARTH_RADIUS_METERS)
+          R"pbdoc(area(geography, /, radius=spherely.EARTH_RADIUS_METERS)
 
         Calculate the area of the geography.
 
@@ -157,8 +161,9 @@ void init_accessors(py::module& m) {
     m.def("length",
           py::vectorize(&length),
           py::arg("geography"),
+          py::pos_only(),
           py::arg("radius") = numeric_constants::EARTH_RADIUS_METERS,
-          R"pbdoc(length(geography, radius=spherely.EARTH_RADIUS_METERS)
+          R"pbdoc(length(geography, /, radius=spherely.EARTH_RADIUS_METERS)
 
         Calculates the length of a line geography, returning zero for other types.
 
@@ -179,8 +184,9 @@ void init_accessors(py::module& m) {
     m.def("perimeter",
           py::vectorize(&perimeter),
           py::arg("geography"),
+          py::pos_only(),
           py::arg("radius") = numeric_constants::EARTH_RADIUS_METERS,
-          R"pbdoc(perimeter(geography, radius=spherely.EARTH_RADIUS_METERS)
+          R"pbdoc(perimeter(geography, /, radius=spherely.EARTH_RADIUS_METERS)
 
         Calculates the perimeter of a polygon geography, returning zero for other types.
 
diff --git a/src/generate_spherely_vfunc_types.py b/src/generate_spherely_vfunc_types.py
index 0f20302..a8063c3 100644
--- a/src/generate_spherely_vfunc_types.py
+++ b/src/generate_spherely_vfunc_types.py
@@ -65,6 +65,8 @@ def _vfunctype_factory(class_name, n_in, **optargs):
             f"{arg_name}: {arg_type}"
             for arg_name, arg_type in zip(arg_names, arg_types)
         )
+        if n_in == 1:
+            arg_str += ", /"
         return_type = (
             "_ScalarReturnType"
             if all(t == geog_types[0] for t in arg_types)
diff --git a/src/geography.cpp b/src/geography.cpp
index ec0c2f6..bbe57b2 100644
--- a/src/geography.cpp
+++ b/src/geography.cpp
@@ -349,7 +349,8 @@ void init_geography(py::module &m) {
     m.def("get_type_id",
           py::vectorize(&get_type_id),
           py::arg("geography"),
-          R"pbdoc(get_type_id(geography)
+          py::pos_only(),
+          R"pbdoc(get_type_id(geography, /)
 
         Returns the type ID of a geography.
 
@@ -383,7 +384,8 @@ void init_geography(py::module &m) {
     m.def("get_dimensions",
           py::vectorize(&get_dimensions),
           py::arg("geography"),
-          R"pbdoc(get_dimensions(geography)
+          py::pos_only(),
+          R"pbdoc(get_dimensions(geography, /)
 
         Returns the inherent dimensionality of a geography.
 
@@ -404,7 +406,8 @@ void init_geography(py::module &m) {
     m.def("get_x",
           py::vectorize(&get_x),
           py::arg("geography"),
-          R"pbdoc(get_x(geography)
+          py::pos_only(),
+          R"pbdoc(get_x(geography, /)
 
         Returns the longitude value of the Point (in degrees).
 
@@ -423,7 +426,8 @@ void init_geography(py::module &m) {
     m.def("get_y",
           py::vectorize(&get_y),
           py::arg("geography"),
-          R"pbdoc(get_y(geography)
+          py::pos_only(),
+          R"pbdoc(get_y(geography, /)
 
         Returns the latitude value of the Point (in degrees).
 
@@ -444,7 +448,8 @@ void init_geography(py::module &m) {
     m.def("is_geography",
           py::vectorize(&is_geography),
           py::arg("obj"),
-          R"pbdoc(is_geography(obj)
+          py::pos_only(),
+          R"pbdoc(is_geography(obj, /)
 
         Returns True if the object is a :py:class:`Geography`, False otherwise.
 
@@ -460,7 +465,8 @@ void init_geography(py::module &m) {
     m.def("is_prepared",
           py::vectorize(&is_prepared),
           py::arg("geography"),
-          R"pbdoc(is_prepared(geography)
+          py::pos_only(),
+          R"pbdoc(is_prepared(geography, /)
 
         Returns True if the geography object is "prepared", False otherwise.
 
@@ -486,7 +492,8 @@ void init_geography(py::module &m) {
     m.def("prepare",
           py::vectorize(&prepare),
           py::arg("geography"),
-          R"pbdoc(prepare(geography)
+          py::pos_only(),
+          R"pbdoc(prepare(geography, /)
 
         Prepare a geography, improving performance of other operations.
 
@@ -520,7 +527,8 @@ void init_geography(py::module &m) {
     m.def("destroy_prepared",
           py::vectorize(&destroy_prepared),
           py::arg("geography"),
-          R"pbdoc(destroy_prepared(geography)
+          py::pos_only(),
+          R"pbdoc(destroy_prepared(geography, /)
 
         Destroy the prepared part of a geography, freeing up memory.
 
diff --git a/src/io.cpp b/src/io.cpp
index 5b7004e..f0b54e9 100644
--- a/src/io.cpp
+++ b/src/io.cpp
@@ -89,10 +89,12 @@ void init_io(py::module& m) {
                 std::move(string));
         },
         py::arg("geography"),
+        py::pos_only(),
+        py::kw_only(),
         py::arg("oriented") = false,
         py::arg("planar") = false,
         py::arg("tessellate_tolerance") = 100.0,
-        R"pbdoc(from_wkt(geography, oriented=False, planar=False, tessellate_tolerance=100.0)
+        R"pbdoc(from_wkt(geography, /, *, oriented=False, planar=False, tessellate_tolerance=100.0)
 
         Creates geographies from the Well-Known Text (WKT) representation.
 
@@ -131,8 +133,9 @@ void init_io(py::module& m) {
             return py::vectorize(ToWKT(precision))(std::move(obj));
         },
         py::arg("geography"),
+        py::pos_only(),
         py::arg("precision") = 6,
-        R"pbdoc(to_wkt(geography, precision=6)
+        R"pbdoc(to_wkt(geography, /, precision=6)
 
         Returns the WKT representation of each geography.
 
@@ -156,10 +159,12 @@ void init_io(py::module& m) {
             return py::vectorize(FromWKB(oriented, planar, tessellate_tolerance))(std::move(bytes));
         },
         py::arg("geography"),
+        py::pos_only(),
+        py::kw_only(),
         py::arg("oriented") = false,
         py::arg("planar") = false,
         py::arg("tessellate_tolerance") = 100.0,
-        R"pbdoc(from_wkb(geography, oriented=False, planar=False, tessellate_tolerance=100.0)
+        R"pbdoc(from_wkb(geography, /, *, oriented=False, planar=False, tessellate_tolerance=100.0)
 
         Creates geographies from the Well-Known Bytes (WKB) representation.
 
@@ -195,7 +200,8 @@ void init_io(py::module& m) {
     m.def("to_wkb",
           py::vectorize(ToWKB()),
           py::arg("geography"),
-          R"pbdoc(to_wkb(geography)
+          py::pos_only(),
+          R"pbdoc(to_wkb(geography, /)
 
         Returns the WKB representation of each geography.
 
diff --git a/src/spherely.pyi b/src/spherely.pyi
index 637acec..11186c2 100644
--- a/src/spherely.pyi
+++ b/src/spherely.pyi
@@ -89,10 +89,10 @@ class _VFunc_Nin1_Nout1(Generic[_NameType, _ScalarReturnType, _ArrayReturnDType]
     @property
     def __name__(self) -> _NameType: ...
     @overload
-    def __call__(self, geography: Geography) -> _ScalarReturnType: ...
+    def __call__(self, geography: Geography, /) -> _ScalarReturnType: ...
     @overload
     def __call__(
-        self, geography: Iterable[Geography]
+        self, geography: Iterable[Geography], /
     ) -> npt.NDArray[_ArrayReturnDType]: ...
 
 class _VFunc_Nin2_Nout1(Generic[_NameType, _ScalarReturnType, _ArrayReturnDType]):
@@ -142,11 +142,11 @@ class _VFunc_Nin1optradius_Nout1(
     def __name__(self) -> _NameType: ...
     @overload
     def __call__(
-        self, geography: Geography, radius: float = 6371010.0
+        self, geography: Geography, /, radius: float = 6371010.0
     ) -> _ScalarReturnType: ...
     @overload
     def __call__(
-        self, geography: Iterable[Geography], radius: float = 6371010.0
+        self, geography: Iterable[Geography], /, radius: float = 6371010.0
     ) -> npt.NDArray[_ArrayReturnDType]: ...
 
 class _VFunc_Nin1optprecision_Nout1(
@@ -156,11 +156,11 @@ class _VFunc_Nin1optprecision_Nout1(
     def __name__(self) -> _NameType: ...
     @overload
     def __call__(
-        self, geography: Geography, precision: int = 6
+        self, geography: Geography, /, precision: int = 6
     ) -> _ScalarReturnType: ...
     @overload
     def __call__(
-        self, geography: Iterable[Geography], precision: int = 6
+        self, geography: Iterable[Geography], /, precision: int = 6
     ) -> npt.NDArray[_ArrayReturnDType]: ...
 
 # /// End types
@@ -268,28 +268,36 @@ to_wkb: _VFunc_Nin1_Nout1[Literal["to_wkb"], bytes, object]
 
 @overload
 def from_wkt(
-    a: str,
+    geography: str,
+    /,
+    *,
     oriented: bool = False,
     planar: bool = False,
     tessellate_tolerance: float = 100.0,
 ) -> Geography: ...
 @overload
 def from_wkt(
-    a: list[str] | npt.NDArray[np.str_],
+    geography: list[str] | npt.NDArray[np.str_],
+    /,
+    *,
     oriented: bool = False,
     planar: bool = False,
     tessellate_tolerance: float = 100.0,
 ) -> T_NDArray_Geography: ...
 @overload
 def from_wkb(
-    a: bytes,
+    geography: bytes,
+    /,
+    *,
     oriented: bool = False,
     planar: bool = False,
     tessellate_tolerance: float = 100.0,
 ) -> Geography: ...
 @overload
 def from_wkb(
-    a: Iterable[bytes],
+    geography: Iterable[bytes],
+    /,
+    *,
     oriented: bool = False,
     planar: bool = False,
     tessellate_tolerance: float = 100.0,
@@ -306,7 +314,7 @@ class ArrowArrayExportable(Protocol):
 class ArrowArrayHolder(ArrowArrayExportable): ...
 
 def to_geoarrow(
-    input: Geography | T_NDArray_Geography,
+    geographies: Geography | T_NDArray_Geography,
     /,
     *,
     output_schema: ArrowSchemaExportable | str | None = None,
@@ -316,7 +324,7 @@ def to_geoarrow(
     precision: int = 6,
 ) -> ArrowArrayExportable: ...
 def from_geoarrow(
-    input: ArrowArrayExportable,
+    geographies: ArrowArrayExportable,
     /,
     *,
     oriented: bool = False,