Skip to content

Commit 8ca1ae3

Browse files
authored
Add pyogrio stubs (#16004)
1 parent bdbb6ec commit 8ca1ae3

11 files changed

Lines changed: 441 additions & 0 deletions

File tree

lib/ts_utils/py315.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"hnswlib",
99
"networkx",
1010
"pycocotools",
11+
"pyogrio",
1112
"resampy",
1213
"shapely",
1314
"tensorflow",

pyrightconfig.stricter.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
"stubs/pyasn1",
8282
"stubs/Pygments",
8383
"stubs/PyMySQL",
84+
"stubs/pyogrio",
8485
"stubs/python-jose",
8586
"stubs/pywin32",
8687
"stubs/PyYAML",
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pyogrio\.tests(\..*)?
2+
pyogrio\._typing # stubs only module

stubs/pyogrio/METADATA.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
version = "0.13.*"
2+
# Requires a version of numpy with a `py.typed` file
3+
dependencies = ["numpy>=1.20", "types-geopandas"]
4+
upstream-repository = "https://github.com/geopandas/pyogrio"

stubs/pyogrio/pyogrio/__init__.pyi

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from .core import (
2+
__gdal_geos_version__ as __gdal_geos_version__,
3+
__gdal_version__ as __gdal_version__,
4+
__gdal_version_string__ as __gdal_version_string__,
5+
detect_write_driver as detect_write_driver,
6+
get_gdal_config_option as get_gdal_config_option,
7+
get_gdal_data_path as get_gdal_data_path,
8+
list_drivers as list_drivers,
9+
list_drivers_details as list_drivers_details,
10+
list_layers as list_layers,
11+
read_bounds as read_bounds,
12+
read_info as read_info,
13+
set_gdal_config_options as set_gdal_config_options,
14+
vsi_curl_clear_cache as vsi_curl_clear_cache,
15+
vsi_listtree as vsi_listtree,
16+
vsi_rmtree as vsi_rmtree,
17+
vsi_unlink as vsi_unlink,
18+
)
19+
from .geopandas import read_dataframe as read_dataframe, write_dataframe as write_dataframe
20+
from .raw import open_arrow as open_arrow, read_arrow as read_arrow, write_arrow as write_arrow
21+
22+
__all__ = [
23+
"__gdal_geos_version__",
24+
"__gdal_version__",
25+
"__gdal_version_string__",
26+
"__version__",
27+
"detect_write_driver",
28+
"get_gdal_config_option",
29+
"get_gdal_data_path",
30+
"list_drivers",
31+
"list_drivers_details",
32+
"list_layers",
33+
"open_arrow",
34+
"read_arrow",
35+
"read_bounds",
36+
"read_dataframe",
37+
"read_info",
38+
"set_gdal_config_options",
39+
"vsi_curl_clear_cache",
40+
"vsi_listtree",
41+
"vsi_rmtree",
42+
"vsi_unlink",
43+
"write_arrow",
44+
"write_dataframe",
45+
]
46+
47+
__version__: str

stubs/pyogrio/pyogrio/_typing.pyi

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import io
2+
from _typeshed import SupportsRead
3+
from collections.abc import Collection
4+
from pathlib import Path
5+
from typing import Any, Protocol, TypeAlias, TypeVar, type_check_only
6+
from typing_extensions import CapsuleType
7+
8+
import numpy as np
9+
10+
_T = TypeVar("_T")
11+
_G = TypeVar("_G", bound=np.generic)
12+
_G_co = TypeVar("_G_co", bound=np.generic, covariant=True)
13+
14+
@type_check_only
15+
class SupportsArrowCStream(Protocol):
16+
def __arrow_c_stream__(self, requested_schema: object | None = None) -> CapsuleType: ...
17+
18+
@type_check_only
19+
class SupportsArray(Protocol[_G_co]):
20+
def __array__(self) -> np.ndarray[Any, np.dtype[_G_co]]: ...
21+
22+
Array1D: TypeAlias = np.ndarray[tuple[int], np.dtype[_G]]
23+
Array2D: TypeAlias = np.ndarray[tuple[int, int], np.dtype[_G]]
24+
ReadPathOrBuffer: TypeAlias = str | Path | bytes | SupportsRead[bytes]
25+
WritePathOrBuffer: TypeAlias = str | Path | io.BytesIO
26+
27+
DualArrayLike: TypeAlias = SupportsArray[_G] | Collection[_T] | _T
28+
ArrayLikeInt: TypeAlias = DualArrayLike[np.bool | np.integer, int]

stubs/pyogrio/pyogrio/core.pyi

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
from pathlib import Path
2+
from typing import Any, Literal, TypedDict, type_check_only
3+
4+
import numpy as np
5+
import shapely as shp
6+
7+
from ._typing import Array1D, Array2D, ReadPathOrBuffer
8+
9+
__gdal_version__: tuple[int, int, int]
10+
__gdal_version_string__: str
11+
__gdal_geos_version__: tuple[int, int, int] | None
12+
13+
@type_check_only
14+
class _Capabilities(TypedDict):
15+
random_read: bool
16+
fast_set_next_by_index: bool
17+
fast_spatial_filter: bool
18+
fast_feature_count: bool
19+
fast_total_bounds: bool
20+
21+
@type_check_only
22+
class _LayerInfo(TypedDict):
23+
layer_name: str
24+
# crs is `None` for non-spatial layers
25+
crs: str | None
26+
fields: Array1D[np.object_] # field names (strings)
27+
dtypes: Array1D[np.object_] # field dtypes (strings)
28+
ogr_types: list[str]
29+
ogr_subtypes: list[str]
30+
encoding: str
31+
fid_column: str
32+
geometry_name: str
33+
# geometry_type is `None` for non-spatial layers
34+
geometry_type: str | None
35+
features: int
36+
# total_bounds is `None` for non-spatial layers or if expensive to compute
37+
total_bounds: tuple[float, float, float, float] | None
38+
driver: str
39+
capabilities: _Capabilities
40+
dataset_metadata: dict[str, str] | None
41+
layer_metadata: dict[str, str] | None
42+
43+
@type_check_only
44+
class _DriverDetails(TypedDict):
45+
long_name: str
46+
read: bool
47+
append: bool
48+
write: bool
49+
supports_vsi: bool
50+
help_topic_url: str | None
51+
extensions: list[str] | None
52+
53+
def list_drivers(read: bool = False, write: bool = False, append: bool = False) -> dict[str, Literal["r", "rw"]]: ...
54+
def list_drivers_details() -> dict[str, _DriverDetails]: ...
55+
def detect_write_driver(path: str | Path) -> str: ... # `path` is coerced to string internally
56+
def list_layers(path_or_buffer: ReadPathOrBuffer, /) -> Array2D[np.object_]: ...
57+
def read_bounds(
58+
path_or_buffer: ReadPathOrBuffer,
59+
/,
60+
layer: int | str | None = None,
61+
skip_features: int = 0,
62+
max_features: int | None = None,
63+
where: str | None = None,
64+
bbox: tuple[float, float, float, float] | None = None,
65+
mask: shp.Geometry | None = None,
66+
) -> tuple[Array1D[np.int64], Array2D[np.float64]]: ...
67+
def read_info(
68+
path_or_buffer: ReadPathOrBuffer,
69+
/,
70+
layer: int | str | None = None,
71+
encoding: str | None = None,
72+
force_feature_count: bool = False,
73+
force_total_bounds: bool = False,
74+
**kwargs: Any, # Dataset open options passed to OGR
75+
) -> _LayerInfo: ...
76+
def set_gdal_config_options(options: dict[str, Any]) -> None: ...
77+
def get_gdal_config_option(name: str) -> Any: ... # Could return str, int, bool, or None
78+
def get_gdal_data_path() -> str: ...
79+
def vsi_listtree(path: str | Path, pattern: str | None = None) -> list[str]: ...
80+
def vsi_rmtree(path: str | Path) -> None: ...
81+
def vsi_unlink(path: str | Path) -> None: ...
82+
def vsi_curl_clear_cache(prefix: str | Path = "") -> None: ...

stubs/pyogrio/pyogrio/errors.pyi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class DataSourceError(RuntimeError): ...
2+
class DataLayerError(RuntimeError): ...
3+
class CRSError(DataLayerError): ...
4+
class FeatureError(DataLayerError): ...
5+
class GeometryError(DataLayerError): ...
6+
class FieldError(DataLayerError): ...
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import os
2+
from collections.abc import Collection, Mapping
3+
from typing import Any, Literal, overload
4+
5+
import geopandas as gpd
6+
import pandas as pd
7+
import shapely as shp
8+
9+
from ._typing import ArrayLikeInt, ReadPathOrBuffer, WritePathOrBuffer
10+
11+
@overload
12+
def read_dataframe(
13+
path_or_buffer: ReadPathOrBuffer | os.PathLike[str],
14+
/,
15+
layer: int | str | None = None,
16+
encoding: str | None = None,
17+
columns: Collection[str] | None = None,
18+
read_geometry: Literal[True] = True,
19+
force_2d: bool = False,
20+
skip_features: int = 0,
21+
max_features: int | None = None,
22+
where: str | None = None,
23+
bbox: tuple[float, float, float, float] | None = None,
24+
mask: shp.Geometry | None = None,
25+
fids: ArrayLikeInt | None = None,
26+
sql: str | None = None,
27+
sql_dialect: str | None = None,
28+
fid_as_index: bool = False,
29+
use_arrow: bool | None = None,
30+
on_invalid: Literal["raise", "warn", "ignore", "fix"] = "raise",
31+
arrow_to_pandas_kwargs: Mapping[str, Any] | None = None,
32+
datetime_as_string: bool = False,
33+
mixed_offsets_as_utc: bool = True,
34+
**kwargs: Any, # Dataset open options passed to OGR
35+
) -> gpd.GeoDataFrame: ...
36+
@overload
37+
def read_dataframe(
38+
path_or_buffer: ReadPathOrBuffer | os.PathLike[str],
39+
/,
40+
layer: int | str | None = None,
41+
encoding: str | None = None,
42+
columns: Collection[str] | None = None,
43+
*,
44+
read_geometry: Literal[False],
45+
force_2d: bool = False,
46+
skip_features: int = 0,
47+
max_features: int | None = None,
48+
where: str | None = None,
49+
bbox: tuple[float, float, float, float] | None = None,
50+
mask: shp.Geometry | None = None,
51+
fids: ArrayLikeInt | None = None,
52+
sql: str | None = None,
53+
sql_dialect: str | None = None,
54+
fid_as_index: bool = False,
55+
use_arrow: bool | None = None,
56+
on_invalid: Literal["raise", "warn", "ignore", "fix"] = "raise",
57+
arrow_to_pandas_kwargs: Mapping[str, Any] | None = None,
58+
datetime_as_string: bool = False,
59+
mixed_offsets_as_utc: bool = True,
60+
**kwargs: Any, # Dataset open options passed to OGR
61+
) -> pd.DataFrame: ...
62+
63+
def write_dataframe(
64+
df: pd.DataFrame,
65+
path: WritePathOrBuffer,
66+
layer: str | None = None,
67+
driver: str | None = None,
68+
encoding: str | None = None,
69+
geometry_type: str | None = None,
70+
promote_to_multi: bool | None = None,
71+
nan_as_null: bool = True,
72+
append: bool = False,
73+
use_arrow: bool | None = None,
74+
dataset_metadata: dict[str, Any] | None = None,
75+
layer_metadata: dict[str, Any] | None = None,
76+
metadata: dict[str, Any] | None = None,
77+
dataset_options: dict[str, Any] | None = None,
78+
layer_options: dict[str, Any] | None = None,
79+
**kwargs: Any, # Additional driver-specific dataset or layer creation options passed to OGR
80+
) -> None: ...

0 commit comments

Comments
 (0)