You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by li...@apache.org on 2023/06/15 17:04:52 UTC
[arrow-adbc] branch main updated: test(python): set up pyright (#790)
This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git
The following commit(s) were added to refs/heads/main by this push:
new 18e96c71 test(python): set up pyright (#790)
18e96c71 is described below
commit 18e96c7145377573ca78b73cb647013c47cff78f
Author: David Li <li...@gmail.com>
AuthorDate: Thu Jun 15 13:04:47 2023 -0400
test(python): set up pyright (#790)
Fixes #545.
---
.github/workflows/native-unix.yml | 5 +-
.pre-commit-config.yaml | 2 +-
CONTRIBUTING.md | 13 ++
ci/conda_env_python.txt | 1 +
ci/scripts/python_build.sh | 2 +-
ci/scripts/python_typecheck.sh | 54 +++++++
dev/release/rat_exclude_files.txt | 19 +--
pyrightconfig.json | 9 ++
python/adbc_driver_flightsql/MANIFEST.in | 1 +
.../adbc_driver_flightsql/py.typed | 0
.../adbc_driver_flightsql/tests/test_lowlevel.py | 2 +-
python/adbc_driver_manager/MANIFEST.in | 1 +
.../adbc_driver_manager/_lib.pyi | 165 +++++++++++++++++++++
.../adbc_driver_manager/dbapi.py | 22 +--
.../adbc_driver_manager/py.typed | 0
python/adbc_driver_manager/tests/test_lowlevel.py | 2 +-
python/adbc_driver_postgresql/MANIFEST.in | 1 +
python/adbc_driver_postgresql/tests/test_dbapi.py | 4 +-
.../adbc_driver_postgresql/tests/test_lowlevel.py | 2 +-
python/adbc_driver_snowflake/MANIFEST.in | 1 +
.../adbc_driver_snowflake/py.typed | 0
.../adbc_driver_snowflake/tests/test_lowlevel.py | 2 +-
python/adbc_driver_sqlite/MANIFEST.in | 1 +
.../adbc_driver_sqlite/adbc_driver_sqlite/py.typed | 0
python/adbc_driver_sqlite/tests/test_lowlevel.py | 2 +-
25 files changed, 284 insertions(+), 27 deletions(-)
diff --git a/.github/workflows/native-unix.yml b/.github/workflows/native-unix.yml
index c2d489ee..c839cbbd 100644
--- a/.github/workflows/native-unix.yml
+++ b/.github/workflows/native-unix.yml
@@ -399,7 +399,6 @@ jobs:
mamba install -c conda-forge \
python=${{ matrix.python }} \
--file ci/conda_env_cpp.txt \
- --file ci/conda_env_docs.txt \
--file ci/conda_env_python.txt
- uses: actions/setup-go@v3
with:
@@ -466,6 +465,10 @@ jobs:
shell: bash -l {0}
run: |
env BUILD_ALL=0 BUILD_DRIVER_SNOWFLAKE=1 ./ci/scripts/python_test.sh "$(pwd)" "$(pwd)/build" "$HOME/local"
+ - name: Typecheck Python
+ shell: bash -l {0}
+ run: |
+ ./ci/scripts/python_typecheck.sh "$(pwd)"
python-docs:
name: "Documentation ${{ matrix.python }} (Conda/${{ matrix.os }})"
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index ab6d5519..82df862c 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -68,7 +68,7 @@ repos:
rev: 22.3.0
hooks:
- id: black
- types_or: [python]
+ types_or: [pyi, python]
- repo: https://github.com/PyCQA/flake8
rev: 4.0.1
hooks:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d174fe9e..bcd2315e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -190,6 +190,19 @@ $ pip install -e .[test]
$ pytest -vvx
```
+Type checking is done with [pyright][pyright]. There is a script to
+run the type checker:
+
+```shell
+# Build native libraries first
+$ env ADBC_USE_ASAN=0 ADBC_USE_UBSAN=0 ./ci/scripts/cpp_build.sh $(pwd) $(pwd)/build
+# Install Python packages
+$ ./ci/scripts/python_build.sh $(pwd) $(pwd)/build
+# Run type checker
+$ ./ci/scripts/python_typecheck.sh $(pwd)
+```
+
+[pyright]: https://microsoft.github.io/pyright/
[pytest]: https://docs.pytest.org/
[setuptools]: https://setuptools.pypa.io/en/latest/index.html
diff --git a/ci/conda_env_python.txt b/ci/conda_env_python.txt
index b5348b04..63d30fc9 100644
--- a/ci/conda_env_python.txt
+++ b/ci/conda_env_python.txt
@@ -18,6 +18,7 @@
Cython
pandas
pyarrow>=8.0.0
+pyright
pytest
setuptools
diff --git a/ci/scripts/python_build.sh b/ci/scripts/python_build.sh
index e7f5521f..a6aeb384 100755
--- a/ci/scripts/python_build.sh
+++ b/ci/scripts/python_build.sh
@@ -46,7 +46,7 @@ build_subproject() {
export ADBC_SNOWFLAKE_LIBRARY="${install_dir}/lib/libadbc_driver_snowflake.${ADBC_LIBRARY_SUFFIX}"
fi
- python -m pip install -e "${source_dir}/python/${subproject}"
+ python -m pip install "${source_dir}/python/${subproject}"
}
main() {
diff --git a/ci/scripts/python_typecheck.sh b/ci/scripts/python_typecheck.sh
new file mode 100755
index 00000000..71649ca8
--- /dev/null
+++ b/ci/scripts/python_typecheck.sh
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+set -e
+
+: ${BUILD_ALL:=1}
+: ${BUILD_DRIVER_FLIGHTSQL:=${BUILD_ALL}}
+: ${BUILD_DRIVER_MANAGER:=${BUILD_ALL}}
+: ${BUILD_DRIVER_POSTGRESQL:=${BUILD_ALL}}
+: ${BUILD_DRIVER_SQLITE:=${BUILD_ALL}}
+: ${BUILD_DRIVER_SNOWFLAKE:=${BUILD_ALL}}
+
+: ${PYRIGHT_OPTIONS:=""}
+
+main() {
+ local -r source_dir="${1}"
+
+ if [[ "${BUILD_DRIVER_FLIGHTSQL}" -gt 0 ]]; then
+ pyright ${PYRIGHT_OPTIONS} "${source_dir}/python/adbc_driver_flightsql"
+ fi
+
+ if [[ "${BUILD_DRIVER_MANAGER}" -gt 0 ]]; then
+ pyright ${PYRIGHT_OPTIONS} "${source_dir}/python/adbc_driver_manager"
+ fi
+
+ if [[ "${BUILD_DRIVER_POSTGRESQL}" -gt 0 ]]; then
+ pyright ${PYRIGHT_OPTIONS} "${source_dir}/python/adbc_driver_postgresql"
+ fi
+
+ if [[ "${BUILD_DRIVER_SQLITE}" -gt 0 ]]; then
+ pyright ${PYRIGHT_OPTIONS} "${source_dir}/python/adbc_driver_sqlite"
+ fi
+
+ if [[ "${BUILD_DRIVER_SNOWFLAKE}" -gt 0 ]]; then
+ pyright ${PYRIGHT_OPTIONS} "${source_dir}/python/adbc_driver_snowflake"
+ fi
+}
+
+main "$@"
diff --git a/dev/release/rat_exclude_files.txt b/dev/release/rat_exclude_files.txt
index e72973c4..5dce6858 100644
--- a/dev/release/rat_exclude_files.txt
+++ b/dev/release/rat_exclude_files.txt
@@ -1,8 +1,17 @@
*.json
+*.Rproj
+*.Rd
+c/vendor/sqlite3/sqlite3.c
+c/vendor/sqlite3/sqlite3.h
ci/conda/.ci_support/*
ci/conda/.gitattributes
ci/linux-packages/changelog
ci/linux-packages/*.install
+csharp/Apache.Arrow.Adbc.sln
+csharp/src/Apache.Arrow.Adbc.FlightSql/Apache.Arrow.Adbc.FlightSql.csproj
+csharp/src/Apache.Arrow.Adbc/Apache.Arrow.Adbc.csproj
+csharp/test/Apache.Arrow.Adbc.FlightSql.Tests/Apache.Arrow.Adbc.FlightSql.Tests.csproj
+csharp/test/Apache.Arrow.Adbc.Tests/Apache.Arrow.Adbc.Tests.csproj
dev/release/rat_exclude_files.txt
docs/source/format/*.drawio
docs/source/format/*.svg
@@ -14,6 +23,7 @@ go/adbc/status_string.go
go/adbc/infocode_string.go
go/adbc/go.sum
java/.mvn/jvm.config
+python/*/*/py.typed
rat.txt
r/adbcdrivermanager/DESCRIPTION
r/adbcdrivermanager/NAMESPACE
@@ -29,12 +39,3 @@ r/adbcpostgresql/.Rbuildignore
r/adbcsnowflake/DESCRIPTION
r/adbcsnowflake/NAMESPACE
r/adbcsnowflake/.Rbuildignore
-c/vendor/sqlite3/sqlite3.c
-c/vendor/sqlite3/sqlite3.h
-*.Rproj
-*.Rd
-csharp/Apache.Arrow.Adbc.sln
-csharp/src/Apache.Arrow.Adbc.FlightSql/Apache.Arrow.Adbc.FlightSql.csproj
-csharp/src/Apache.Arrow.Adbc/Apache.Arrow.Adbc.csproj
-csharp/test/Apache.Arrow.Adbc.FlightSql.Tests/Apache.Arrow.Adbc.FlightSql.Tests.csproj
-csharp/test/Apache.Arrow.Adbc.Tests/Apache.Arrow.Adbc.Tests.csproj
diff --git a/pyrightconfig.json b/pyrightconfig.json
new file mode 100644
index 00000000..e78d074f
--- /dev/null
+++ b/pyrightconfig.json
@@ -0,0 +1,9 @@
+{
+ "exclude": [
+ "**/.asv/",
+ "**/_version.py",
+ "**/setup.py",
+ "**/build/",
+ "**/benchmarks/"
+ ]
+}
diff --git a/python/adbc_driver_flightsql/MANIFEST.in b/python/adbc_driver_flightsql/MANIFEST.in
index da9b1fb7..c30e0623 100644
--- a/python/adbc_driver_flightsql/MANIFEST.in
+++ b/python/adbc_driver_flightsql/MANIFEST.in
@@ -18,3 +18,4 @@
# setuptools manifest
include adbc_driver_flightsql/libadbc_driver_flightsql.so
+include adbc_driver_flightsql/py.typed
diff --git a/python/adbc_driver_flightsql/adbc_driver_flightsql/py.typed b/python/adbc_driver_flightsql/adbc_driver_flightsql/py.typed
new file mode 100644
index 00000000..e69de29b
diff --git a/python/adbc_driver_flightsql/tests/test_lowlevel.py b/python/adbc_driver_flightsql/tests/test_lowlevel.py
index 203b95b1..149888d4 100644
--- a/python/adbc_driver_flightsql/tests/test_lowlevel.py
+++ b/python/adbc_driver_flightsql/tests/test_lowlevel.py
@@ -44,4 +44,4 @@ def test_options(dremio):
def test_version():
- assert adbc_driver_flightsql.__version__
+ assert adbc_driver_flightsql.__version__ # type:ignore
diff --git a/python/adbc_driver_manager/MANIFEST.in b/python/adbc_driver_manager/MANIFEST.in
index 75f4a0dd..fe985282 100644
--- a/python/adbc_driver_manager/MANIFEST.in
+++ b/python/adbc_driver_manager/MANIFEST.in
@@ -22,3 +22,4 @@ include NOTICE.txt
include adbc_driver_manager/adbc.h
include adbc_driver_manager/adbc_driver_manager.cc
include adbc_driver_manager/adbc_driver_manager.h
+include adbc_driver_manager/py.typed
diff --git a/python/adbc_driver_manager/adbc_driver_manager/_lib.pyi b/python/adbc_driver_manager/adbc_driver_manager/_lib.pyi
new file mode 100644
index 00000000..8f107369
--- /dev/null
+++ b/python/adbc_driver_manager/adbc_driver_manager/_lib.pyi
@@ -0,0 +1,165 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# NOTE: generated with mypy's stubgen, then hand-edited to fix things
+
+from typing import Any, ClassVar, Dict, List, Literal, Optional, Tuple, Union
+
+from typing import overload
+import enum
+import typing
+
+INGEST_OPTION_MODE: str
+INGEST_OPTION_MODE_APPEND: str
+INGEST_OPTION_MODE_CREATE: str
+INGEST_OPTION_TARGET_TABLE: str
+
+class AdbcConnection(_AdbcHandle):
+ def __init__(self, database: "AdbcDatabase", **kwargs: str) -> None: ...
+ def close(self) -> None: ...
+ def commit(self) -> None: ...
+ def get_info(
+ self, info_codes: Optional[List[Union[int, "AdbcInfoCode"]]] = None
+ ) -> "ArrowArrayStreamHandle": ...
+ def get_objects(
+ self,
+ depth: "GetObjectsDepth",
+ catalog: Optional[str] = None,
+ db_schema: Optional[str] = None,
+ table_name: Optional[str] = None,
+ table_types: Optional[List[str]] = None,
+ column_name: Optional[str] = None,
+ ) -> "ArrowArrayStreamHandle": ...
+ def get_table_schema(
+ self,
+ catalog: Optional[str],
+ db_schema: Optional[str],
+ table_name: str,
+ ) -> "ArrowSchemaHandle": ...
+ def get_table_types(self) -> "ArrowArrayStreamHandle": ...
+ def read_partition(self, partition: bytes) -> "ArrowArrayStreamHandle": ...
+ def rollback(self) -> None: ...
+ def set_autocommit(self, enabled: bool) -> None: ...
+ def set_options(self, **kwargs: str) -> None: ...
+
+class AdbcDatabase(_AdbcHandle):
+ def __init__(self, **kwargs: str) -> None: ...
+ def close(self) -> None: ...
+ def set_options(self, **kwargs: str) -> None: ...
+
+class AdbcInfoCode(enum.IntEnum):
+ DRIVER_ARROW_VERSION = ...
+ DRIVER_NAME = ...
+ DRIVER_VERSION = ...
+ VENDOR_ARROW_VERSION = ...
+ VENDOR_NAME = ...
+ VENDOR_VERSION = ...
+
+class AdbcStatement(_AdbcHandle):
+ def __init__(self, *args, **kwargs) -> None: ...
+ def bind(self, *args, **kwargs) -> Any: ...
+ def bind_stream(self, *args, **kwargs) -> Any: ...
+ def close(self) -> None: ...
+ def execute_partitions(self, *args, **kwargs) -> Any: ...
+ def execute_query(self, *args, **kwargs) -> Any: ...
+ def execute_update(self, *args, **kwargs) -> Any: ...
+ def get_parameter_schema(self, *args, **kwargs) -> Any: ...
+ def prepare(self, *args, **kwargs) -> Any: ...
+ def set_options(self, *args, **kwargs) -> Any: ...
+ def set_sql_query(self, *args, **kwargs) -> Any: ...
+ def set_substrait_plan(self, *args, **kwargs) -> Any: ...
+ def __reduce__(self) -> Any: ...
+ def __setstate__(self, state) -> Any: ...
+
+class AdbcStatusCode(enum.IntEnum):
+ ALREADY_EXISTS = ...
+ CANCELLED = ...
+ INTEGRITY = ...
+ INTERNAL = ...
+ INVALID_ARGUMENT = ...
+ INVALID_DATA = ...
+ INVALID_STATE = ...
+ IO = ...
+ NOT_FOUND = ...
+ NOT_IMPLEMENTED = ...
+ OK = ...
+ TIMEOUT = ...
+ UNAUTHENTICATED = ...
+ UNAUTHORIZED = ...
+ UNKNOWN = ...
+
+class ArrowArrayHandle:
+ address: Any
+
+class ArrowArrayStreamHandle:
+ address: Any
+
+class ArrowSchemaHandle:
+ address: Any
+
+class DataError(DatabaseError): ...
+class DatabaseError(Error): ...
+
+class Error(Exception):
+ status_code: AdbcStatusCode
+ vendor_code: Optional[int]
+ sqlstate: Optional[str]
+
+ def __init__(
+ self,
+ message: str,
+ *,
+ status_code: Union[int, AdbcStatusCode],
+ vendor_code: Optional[str] = None,
+ sqlstate: Optional[str] = None
+ ) -> None: ...
+
+class GetObjectsDepth(enum.IntEnum):
+ ALL = ...
+ CATALOGS = ...
+ COLUMNS = ...
+ DB_SCHEMAS = ...
+ TABLES = ...
+
+class IntegrityError(DatabaseError): ...
+class InterfaceError(Error): ...
+class InternalError(DatabaseError): ...
+
+class NotSupportedError(DatabaseError):
+ def __init__(
+ self,
+ message: str,
+ *,
+ vendor_code: Optional[str] = None,
+ sqlstate: Optional[str] = None
+ ) -> None: ...
+
+class OperationalError(DatabaseError): ...
+class ProgrammingError(DatabaseError): ...
+class Warning(UserWarning): ...
+
+class _AdbcHandle:
+ def __init__(self, *args, **kwargs) -> None: ...
+ def __enter__(self) -> Any: ...
+ def __exit__(self, type, value, traceback) -> Any: ...
+
+def _test_error(
+ status_code: Union[int, AdbcStatusCode],
+ message: str,
+ vendor_code: Optional[int],
+ sqlstate: Optional[str],
+) -> Error: ...
diff --git a/python/adbc_driver_manager/adbc_driver_manager/dbapi.py b/python/adbc_driver_manager/adbc_driver_manager/dbapi.py
index 22fd3eb3..31e4392a 100644
--- a/python/adbc_driver_manager/adbc_driver_manager/dbapi.py
+++ b/python/adbc_driver_manager/adbc_driver_manager/dbapi.py
@@ -29,6 +29,7 @@ under pytest, or when the environment variable
"""
+import abc
import datetime
import os
import threading
@@ -45,9 +46,8 @@ except ImportError as e:
from . import _lib
if typing.TYPE_CHECKING:
- from typing import Self
-
import pandas
+ from typing_extensions import Self
# ----------------------------------------------------------
# Globals
@@ -97,12 +97,12 @@ def DateFromTicks(ticks: int) -> Date:
return Date(*time.localtime(ticks)[:3])
-def TimeFromTicks(ticks: int) -> Date:
+def TimeFromTicks(ticks: int) -> Time:
"""Construct a time value from a count of seconds."""
return Time(*time.localtime(ticks)[3:6])
-def TimestampFromTicks(ticks: int) -> Date:
+def TimestampFromTicks(ticks: int) -> Timestamp:
"""Construct a timestamp value from a count of seconds."""
return Timestamp(*time.localtime(ticks)[:6])
@@ -157,7 +157,7 @@ STRING = _TypeSet([pyarrow.string().id, pyarrow.large_string().id])
def connect(
*,
driver: str,
- entrypoint: str = None,
+ entrypoint: Optional[str] = None,
db_kwargs: Optional[Dict[str, str]] = None,
conn_kwargs: Optional[Dict[str, str]] = None,
autocommit=False,
@@ -212,7 +212,7 @@ def connect(
# Classes
-class _Closeable:
+class _Closeable(abc.ABC):
"""Base class providing context manager interface."""
def __enter__(self) -> "Self":
@@ -221,6 +221,10 @@ class _Closeable:
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
self.close()
+ @abc.abstractmethod
+ def close(self) -> None:
+ ...
+
class _SharedDatabase(_Closeable):
"""A holder for a shared AdbcDatabase."""
@@ -662,7 +666,7 @@ class Cursor(_Closeable):
self._bind(arrow_parameters)
self._rowcount = self._stmt.execute_update()
- def fetchone(self) -> tuple:
+ def fetchone(self) -> Optional[tuple]:
"""Fetch one row of the result."""
if self._results is None:
raise ProgrammingError(
@@ -949,7 +953,7 @@ class _RowIterator(_Closeable):
for field in self._reader.schema
]
- def fetchone(self):
+ def fetchone(self) -> Optional[tuple]:
if self._current_batch is None or self._next_row >= len(self._current_batch):
try:
while True:
@@ -961,7 +965,7 @@ class _RowIterator(_Closeable):
self._current_batch = None
self._finished = True
- if self._finished:
+ if self._finished or self._current_batch is None:
return None
row = tuple(arr[self._next_row].as_py() for arr in self._current_batch.columns)
diff --git a/python/adbc_driver_manager/adbc_driver_manager/py.typed b/python/adbc_driver_manager/adbc_driver_manager/py.typed
new file mode 100644
index 00000000..e69de29b
diff --git a/python/adbc_driver_manager/tests/test_lowlevel.py b/python/adbc_driver_manager/tests/test_lowlevel.py
index 819873e1..15d98e53 100644
--- a/python/adbc_driver_manager/tests/test_lowlevel.py
+++ b/python/adbc_driver_manager/tests/test_lowlevel.py
@@ -46,7 +46,7 @@ def _bind(stmt, batch):
def test_version():
- assert adbc_driver_manager.__version__
+ assert adbc_driver_manager.__version__ # type:ignore
def test_database_init():
diff --git a/python/adbc_driver_postgresql/MANIFEST.in b/python/adbc_driver_postgresql/MANIFEST.in
index bba71c47..4e654b19 100644
--- a/python/adbc_driver_postgresql/MANIFEST.in
+++ b/python/adbc_driver_postgresql/MANIFEST.in
@@ -18,3 +18,4 @@
# setuptools manifest
include adbc_driver_postgresql/libadbc_driver_postgresql.so
+include adbc_driver_postgresql/py.typed
diff --git a/python/adbc_driver_postgresql/tests/test_dbapi.py b/python/adbc_driver_postgresql/tests/test_dbapi.py
index 16301083..8d9b09b5 100644
--- a/python/adbc_driver_postgresql/tests/test_dbapi.py
+++ b/python/adbc_driver_postgresql/tests/test_dbapi.py
@@ -15,13 +15,15 @@
# specific language governing permissions and limitations
# under the License.
+from typing import Generator
+
import pytest
from adbc_driver_postgresql import dbapi
@pytest.fixture
-def postgres(postgres_uri: str) -> dbapi.Connection:
+def postgres(postgres_uri: str) -> Generator[dbapi.Connection, None, None]:
with dbapi.connect(postgres_uri) as conn:
yield conn
diff --git a/python/adbc_driver_postgresql/tests/test_lowlevel.py b/python/adbc_driver_postgresql/tests/test_lowlevel.py
index 587f7b84..d19022bc 100644
--- a/python/adbc_driver_postgresql/tests/test_lowlevel.py
+++ b/python/adbc_driver_postgresql/tests/test_lowlevel.py
@@ -38,7 +38,7 @@ def test_query_trivial(postgres):
def test_version():
- assert adbc_driver_postgresql.__version__
+ assert adbc_driver_postgresql.__version__ # type:ignore
def test_failed_connection():
diff --git a/python/adbc_driver_snowflake/MANIFEST.in b/python/adbc_driver_snowflake/MANIFEST.in
index 144d50db..7f8d0a39 100644
--- a/python/adbc_driver_snowflake/MANIFEST.in
+++ b/python/adbc_driver_snowflake/MANIFEST.in
@@ -18,3 +18,4 @@
# setuptools manifest
include adbc_driver_snowflake/libadbc_driver_snowflake.so
+include adbc_driver_snowflake/py.typed
diff --git a/python/adbc_driver_snowflake/adbc_driver_snowflake/py.typed b/python/adbc_driver_snowflake/adbc_driver_snowflake/py.typed
new file mode 100644
index 00000000..e69de29b
diff --git a/python/adbc_driver_snowflake/tests/test_lowlevel.py b/python/adbc_driver_snowflake/tests/test_lowlevel.py
index f155ddaf..6186f889 100644
--- a/python/adbc_driver_snowflake/tests/test_lowlevel.py
+++ b/python/adbc_driver_snowflake/tests/test_lowlevel.py
@@ -51,4 +51,4 @@ def test_options(snowflake):
def test_version():
- assert adbc_driver_snowflake.__version__
+ assert adbc_driver_snowflake.__version__ # type:ignore
diff --git a/python/adbc_driver_sqlite/MANIFEST.in b/python/adbc_driver_sqlite/MANIFEST.in
index f9de8e7b..95af26a2 100644
--- a/python/adbc_driver_sqlite/MANIFEST.in
+++ b/python/adbc_driver_sqlite/MANIFEST.in
@@ -18,3 +18,4 @@
# setuptools manifest
include adbc_driver_sqlite/libadbc_driver_sqlite.so
+include adbc_driver_sqlite/py.typed
diff --git a/python/adbc_driver_sqlite/adbc_driver_sqlite/py.typed b/python/adbc_driver_sqlite/adbc_driver_sqlite/py.typed
new file mode 100644
index 00000000..e69de29b
diff --git a/python/adbc_driver_sqlite/tests/test_lowlevel.py b/python/adbc_driver_sqlite/tests/test_lowlevel.py
index 6ab0acb9..58359a11 100644
--- a/python/adbc_driver_sqlite/tests/test_lowlevel.py
+++ b/python/adbc_driver_sqlite/tests/test_lowlevel.py
@@ -51,4 +51,4 @@ def test_options(sqlite):
def test_version():
- assert adbc_driver_sqlite.__version__
+ assert adbc_driver_sqlite.__version__ # type:ignore