You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by pa...@apache.org on 2024/09/19 03:34:32 UTC

(arrow-nanoarrow) branch main updated: chore(python): Fix type stubs for updated module structure (#606)

This is an automated email from the ASF dual-hosted git repository.

paleolimbot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-nanoarrow.git


The following commit(s) were added to refs/heads/main by this push:
     new 499d865c chore(python): Fix type stubs for updated module structure (#606)
499d865c is described below

commit 499d865c862606c69d8dca1a15fc0cf542696599
Author: Dewey Dunnington <de...@dunnington.ca>
AuthorDate: Wed Sep 18 22:34:27 2024 -0500

    chore(python): Fix type stubs for updated module structure (#606)
    
    This PR updates the type stubs for the Cython modules to reflect the
    updated structure. I don't think this mechanism for generating stubs is
    the best long-term strategy (requires remembering to do so!)...we could
    also do something like omit the generated stubs from the source tree and
    generate them only before packaging; however, this would make them not
    useful for local development (which is one of the primary short-term
    benefits of including them).
---
 .github/workflows/python.yaml          |  15 +--
 python/generate_type_stubs.sh          |  26 ++--
 python/src/nanoarrow/_array.pyi        | 187 +++++++++++++++++++++++++++
 python/src/nanoarrow/_array_stream.pyi | 128 ++++++++++++++++++
 python/src/nanoarrow/_array_stream.pyx |   1 +
 python/src/nanoarrow/_buffer.pyi       | 230 +++++++++++++++++++++++++++++++++
 python/src/nanoarrow/_device.pyi       |  81 ++++++++++++
 python/src/nanoarrow/_ipc_lib.pyi      |  71 ++++++++++
 python/src/nanoarrow/_schema.pyi       | 179 +++++++++++++++++++++++++
 python/src/nanoarrow/_types.pyi        | 133 +++++++++++++++++++
 python/src/nanoarrow/_utils.pyi        |  38 ++++++
 11 files changed, 1067 insertions(+), 22 deletions(-)

diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml
index 5639d256..2dd7490e 100644
--- a/.github/workflows/python.yaml
+++ b/.github/workflows/python.yaml
@@ -64,15 +64,12 @@ jobs:
       - name: Check type stubs
         if: success() && matrix.python-version == '3.12'
         run: |
-          pip install mypy "black==22.3.0"
-          python/generate_type_stubs.sh
-
-          if git diff --name-only | grep -e "\\.pxi$"; then
-            echo "Type stubs were changed. Update them with python/generate_type_stubs.sh."
-          fi
-
-          stubtest nanoarrow._lib
-          stubtest nanoarrow._ipc_lib
+          pip install mypy
+          cd src/nanoarrow
+          for mod in $(find . -name "*.pyx" | sed -e "s|./||" -e "s|.pyx||"); do
+            cat $mod
+            stubtest "nanoarrow.$mod"
+          done
 
       - name: Run doctests
         if: success() && matrix.python-version == '3.12'
diff --git a/python/generate_type_stubs.sh b/python/generate_type_stubs.sh
index 2a8aec60..e250f54a 100755
--- a/python/generate_type_stubs.sh
+++ b/python/generate_type_stubs.sh
@@ -23,11 +23,7 @@ SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 
 pushd "${SOURCE_DIR}"
 
-# Generate stubs using mypy
-stubgen --module nanoarrow._lib --include-docstrings -o build/tmp
-stubgen --module nanoarrow._ipc_lib --include-docstrings -o build/tmp
-
-# Add license to the start of the files
+# We'll add the license to the start of the files
 LICENSE='
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
@@ -47,13 +43,17 @@ LICENSE='
 # under the License.
 '
 
-echo "$LICENSE" > src/nanoarrow/_lib.pyi
-cat build/tmp/nanoarrow/_lib.pyi >> src/nanoarrow/_lib.pyi
-
-echo "$LICENSE" > src/nanoarrow/_ipc_lib.pyi
-cat build/tmp/nanoarrow/_ipc_lib.pyi >> src/nanoarrow/_ipc_lib.pyi
-
-# Reformat stubs
-black src/nanoarrow/*.pyi
+# Remove old stubs
+find src/nanoarrow -name "*.pyi" -delete
+
+# Generate new ones
+pushd src/nanoarrow
+for mod in $(find . -name "*.pyx" | sed -e "s|./||" -e "s|.pyx||"); do
+  stubgen --module "nanoarrow.${mod}" --include-docstrings -o ../../build/tmp
+  echo "$LICENSE" > "${mod}.pyi"
+  cat "../../build/tmp/nanoarrow/${mod}.pyi" >> "${mod}.pyi"
+  black "${mod}.pyi"
+done
+popd
 
 popd
diff --git a/python/src/nanoarrow/_array.pyi b/python/src/nanoarrow/_array.pyi
new file mode 100644
index 00000000..aa3d8a71
--- /dev/null
+++ b/python/src/nanoarrow/_array.pyi
@@ -0,0 +1,187 @@
+# 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.
+
+import _cython_3_0_11
+import nanoarrow._device
+from _typeshed import Incomplete
+from nanoarrow._device import DeviceType as DeviceType
+from typing import ClassVar
+
+DEVICE_CPU: nanoarrow._device.Device
+__reduce_cython__: _cython_3_0_11.cython_function_or_method
+__setstate_cython__: _cython_3_0_11.cython_function_or_method
+__test__: dict
+
+class CArray:
+    __pyx_vtable__: ClassVar[PyCapsule] = ...
+    buffers: Incomplete
+    children: Incomplete
+    device_id: Incomplete
+    device_type: Incomplete
+    device_type_id: Incomplete
+    dictionary: Incomplete
+    length: Incomplete
+    n_buffers: Incomplete
+    n_children: Incomplete
+    null_count: Incomplete
+    offset: Incomplete
+    schema: Incomplete
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    @staticmethod
+    def allocate(*args, **kwargs):
+        """Allocate a released ArrowArray"""
+    def child(self, *args, **kwargs): ...
+    def is_valid(self, *args, **kwargs):
+        """Check for a non-null and non-released underlying ArrowArray"""
+    def view(self, *args, **kwargs):
+        """Allocate a :class:`CArrayView` to access the buffers of this array"""
+    def __arrow_c_array__(self, *args, **kwargs):
+        """
+        Get a pair of PyCapsules containing a C ArrowArray representation of the object.
+
+        Parameters
+        ----------
+        requested_schema : PyCapsule | None
+            A PyCapsule containing a C ArrowSchema representation of a requested
+            schema. Not supported.
+
+        Returns
+        -------
+        Tuple[PyCapsule, PyCapsule]
+            A pair of PyCapsules containing a C ArrowSchema and ArrowArray,
+            respectively.
+        """
+    def __getitem__(self, index):
+        """Return self[key]."""
+    def __len__(self) -> int:
+        """Return len(self)."""
+    def __reduce__(self): ...
+
+class CArrayBuilder:
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    @staticmethod
+    def allocate(*args, **kwargs):
+        """Create a CArrayBuilder
+
+        Allocates memory for an ArrowArray and populates it with nanoarrow's
+        ArrowArray private_data/release callback implementation. This should
+        usually be followed by :meth:`init_from_type` or :meth:`init_from_schema`.
+        """
+    def append_bytes(self, *args, **kwargs): ...
+    def append_strings(self, *args, **kwargs): ...
+    def finish(self, *args, **kwargs):
+        """Finish building this array
+
+        Performs any steps required to return a valid ArrowArray and optionally
+        validates the output to ensure that the result is valid (given the information
+        the array has available to it).
+
+        Parameters
+        ----------
+        validation_level : None, "full", "default", "minimal", or "none", optional
+            Explicitly define a validation level or use None to perform default
+            validation if possible. Validation may not be possible if children
+            were set that were not created by nanoarrow.
+        """
+    def finish_device(self, *args, **kwargs):
+        """Finish building this array and export to an ArrowDeviceArray
+
+        Calls :meth:`finish`, propagating device information into an ArrowDeviceArray.
+        """
+    def init_from_schema(self, *args, **kwargs): ...
+    def init_from_type(self, *args, **kwargs): ...
+    def is_empty(self, *args, **kwargs):
+        """Check if any items have been appended to this builder"""
+    def resolve_null_count(self, *args, **kwargs):
+        """Ensure the output null count is synchronized with existing buffers
+
+        Note that this will not attempt to access non-CPU buffers such that
+        :attr:`null_count` might still be -1 after calling this method.
+        """
+    def set_buffer(self, *args, **kwargs):
+        """Set an ArrowArray buffer
+
+        Sets a buffer of this ArrowArray such the pointer at array->buffers[i] is
+        equal to buffer->data and such that the buffer's lifcycle is managed by
+        the array. If move is True, the input Python object that previously wrapped
+        the ArrowBuffer will be invalidated, which is usually the desired behaviour
+        if you built or imported a buffer specifically to build this array. If move
+        is False (the default), this function will a make a shallow copy via another
+        layer of Python object wrapping.
+        """
+    def set_child(self, *args, **kwargs):
+        """Set an ArrowArray child
+
+        Set a child of this array by performing a show copy or optionally
+        transferring ownership to this object. The initialized child array
+        must have been initialized before this call by initializing this
+        builder with a schema containing the correct number of children.
+        """
+    def set_length(self, *args, **kwargs): ...
+    def set_null_count(self, *args, **kwargs): ...
+    def set_offset(self, *args, **kwargs): ...
+    def start_appending(self, *args, **kwargs):
+        """Use append mode for building this ArrowArray
+
+        Calling this method is required to produce a valid array prior to calling
+        :meth:`append_strings` or `append_bytes`.
+        """
+    def __reduce__(self): ...
+
+class CArrayView:
+    buffers: Incomplete
+    children: Incomplete
+    dictionary: Incomplete
+    layout: Incomplete
+    length: Incomplete
+    n_buffers: Incomplete
+    n_children: Incomplete
+    null_count: Incomplete
+    offset: Incomplete
+    storage_type: Incomplete
+    storage_type_id: Incomplete
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def buffer(self, *args, **kwargs): ...
+    def buffer_type(self, *args, **kwargs): ...
+    def child(self, *args, **kwargs): ...
+    @staticmethod
+    def from_array(*args, **kwargs): ...
+    @staticmethod
+    def from_schema(*args, **kwargs): ...
+    def __len__(self) -> int:
+        """Return len(self)."""
+    def __reduce__(self): ...
+
+class CDeviceArray:
+    array: Incomplete
+    device_id: Incomplete
+    device_type: Incomplete
+    device_type_id: Incomplete
+    schema: Incomplete
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def view(self, *args, **kwargs): ...
+    def __arrow_c_array__(self, *args, **kwargs): ...
+    def __arrow_c_device_array__(self, *args, **kwargs): ...
+    def __reduce__(self): ...
diff --git a/python/src/nanoarrow/_array_stream.pyi b/python/src/nanoarrow/_array_stream.pyi
new file mode 100644
index 00000000..b0fca6ef
--- /dev/null
+++ b/python/src/nanoarrow/_array_stream.pyi
@@ -0,0 +1,128 @@
+# 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.
+
+import _cython_3_0_11
+import types
+from _typeshed import Incomplete
+from typing import ClassVar
+
+__reduce_cython__: _cython_3_0_11.cython_function_or_method
+__setstate_cython__: _cython_3_0_11.cython_function_or_method
+__test__: dict
+
+class CArrayStream:
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    @staticmethod
+    def allocate(*args, **kwargs):
+        """Allocate a released ArrowArrayStream"""
+    @staticmethod
+    def from_c_arrays(*args, **kwargs):
+        """Create an ArrowArrayStream from an existing set of arrays
+
+        Given a previously resolved list of arrays, create an ArrowArrayStream
+        representation of the sequence of chunks.
+
+        Parameters
+        ----------
+        arrays : List[CArray]
+            A list of arrays to use as batches.
+        schema : CSchema
+            The schema that will be returned. Must be type equal with the schema
+            of each array (this is checked if validate is ``True``)
+        move : bool, optional
+            If True, transfer ownership from each array instead of creating a
+            shallow copy. This is only safe if the caller knows the origin of the
+            arrays and knows that they will not be accessed after this stream has been
+            created.
+        validate : bool, optional
+            If True, enforce type equality between the provided schema and the schema
+            of each array.
+        """
+    def get_next(self, *args, **kwargs):
+        """Get the next Array from this stream
+
+        Raises StopIteration when there are no more arrays in this stream.
+        """
+    def get_schema(self, *args, **kwargs):
+        """Get the schema associated with this stream
+
+        Calling this method will always issue a call to the underlying stream's
+        get_schema callback.
+        """
+    def is_valid(self, *args, **kwargs):
+        """Check for a non-null and non-released underlying ArrowArrayStream"""
+    def release(self, *args, **kwargs):
+        """Explicitly call the release callback of this stream"""
+    def __arrow_c_stream__(self, *args, **kwargs):
+        """
+        Export the stream as an Arrow C stream PyCapsule.
+
+        Parameters
+        ----------
+        requested_schema : PyCapsule | None
+            A PyCapsule containing a C ArrowSchema representation of a requested
+            schema. Not supported.
+
+        Returns
+        -------
+        PyCapsule
+        """
+    def __enter__(self): ...
+    def __exit__(
+        self,
+        type: type[BaseException] | None,
+        value: BaseException | None,
+        traceback: types.TracebackType | None,
+    ): ...
+    def __iter__(self):
+        """Implement iter(self)."""
+    def __next__(self): ...
+    def __reduce__(self): ...
+
+class CMaterializedArrayStream:
+    __pyx_vtable__: ClassVar[PyCapsule] = ...
+    arrays: Incomplete
+    n_arrays: Incomplete
+    schema: Incomplete
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def array(self, *args, **kwargs): ...
+    def child(self, *args, **kwargs): ...
+    @staticmethod
+    def from_c_array(*args, **kwargs):
+        """ "Create a materialized array stream from a single array"""
+    @staticmethod
+    def from_c_array_stream(*args, **kwargs):
+        """ "Create a materialized array stream from an unmaterialized ArrowArrayStream"""
+    @staticmethod
+    def from_c_arrays(*args, **kwargs):
+        """ "Create a materialized array stream from an existing iterable of arrays
+
+        This is slightly more efficient than creating a stream and then consuming it
+        because the implementation can avoid a shallow copy of each array.
+        """
+    def __arrow_c_stream__(self, *args, **kwargs): ...
+    def __getitem__(self, index):
+        """Return self[key]."""
+    def __iter__(self):
+        """Implement iter(self)."""
+    def __len__(self) -> int:
+        """Return len(self)."""
+    def __reduce__(self): ...
diff --git a/python/src/nanoarrow/_array_stream.pyx b/python/src/nanoarrow/_array_stream.pyx
index b7692711..b33d8c83 100644
--- a/python/src/nanoarrow/_array_stream.pyx
+++ b/python/src/nanoarrow/_array_stream.pyx
@@ -184,6 +184,7 @@ cdef class CArrayStream:
         return array_stream_capsule
 
     def _addr(self) -> int:
+        """test to see if this causes a ci fail"""
         return <uintptr_t>self._ptr
 
     def is_valid(self) -> bool:
diff --git a/python/src/nanoarrow/_buffer.pyi b/python/src/nanoarrow/_buffer.pyi
new file mode 100644
index 00000000..aed13289
--- /dev/null
+++ b/python/src/nanoarrow/_buffer.pyi
@@ -0,0 +1,230 @@
+# 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.
+
+import _cython_3_0_11
+import nanoarrow._device
+from _typeshed import Incomplete
+from typing import ClassVar
+
+DEVICE_CPU: nanoarrow._device.Device
+__reduce_cython__: _cython_3_0_11.cython_function_or_method
+__setstate_cython__: _cython_3_0_11.cython_function_or_method
+__test__: dict
+
+class CBuffer:
+    __pyx_vtable__: ClassVar[PyCapsule] = ...
+    data_type: Incomplete
+    data_type_id: Incomplete
+    device: Incomplete
+    element_size_bits: Incomplete
+    format: Incomplete
+    itemsize: Incomplete
+    n_elements: Incomplete
+    size_bytes: Incomplete
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def element(self, *args, **kwargs): ...
+    def elements(self, *args, **kwargs): ...
+    @staticmethod
+    def empty(*args, **kwargs):
+        """Create an empty CBuffer"""
+    @staticmethod
+    def from_dlpack(*args, **kwargs):
+        """Create a CBuffer using the DLPack protocol
+
+        Wraps a tensor from an external library as a CBuffer that can be used
+        to create an array.
+
+        Parameters
+        ----------
+        obj : object with a ``__dlpack__`` attribute
+            The object on which to invoke the DLPack protocol
+        stream : int, optional
+            The stream on which the tensor represented by obj should be made
+            safe for use. This value is passed to the object's ``__dlpack__``
+            method; however, the CBuffer does not keep any record of this (i.e.,
+            the caller is responsible for creating a sync event after creating one
+            or more buffers in this way).
+        """
+    @staticmethod
+    def from_pybuffer(*args, **kwargs):
+        """Create a CBuffer using the Python buffer protocol
+
+        Wraps a buffer using the Python buffer protocol as a CBuffer that can be
+        used to create an array.
+
+        Parameters
+        ----------
+        obj : buffer-like
+            The object on which to invoke the Python buffer protocol
+        """
+    def view(self, *args, **kwargs):
+        """Export this buffer as a CBufferView
+
+        Returns a :class:`CBufferView` of this buffer. After calling this
+        method, the original CBuffer will be invalidated and cannot be used.
+        In general, the view of the buffer should be used to consume a buffer
+        (whereas the CBuffer is primarily used to wrap an existing object in
+        a way that it can be used to build a :class:`CArray`).
+        """
+    def __buffer__(self, *args, **kwargs):
+        """Return a buffer object that exposes the underlying memory of the object."""
+    def __getitem__(self, index):
+        """Return self[key]."""
+    def __iter__(self):
+        """Implement iter(self)."""
+    def __len__(self) -> int:
+        """Return len(self)."""
+    def __reduce__(self): ...
+    def __release_buffer__(self, *args, **kwargs):
+        """Release the buffer object that exposes the underlying memory of the object."""
+
+class CBufferBuilder:
+    __pyx_vtable__: ClassVar[PyCapsule] = ...
+    capacity_bytes: Incomplete
+    format: Incomplete
+    itemsize: Incomplete
+    size_bytes: Incomplete
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def advance(self, *args, **kwargs):
+        """Manually increase :attr:`size_bytes` by ``additional_bytes``
+
+        This can be used after writing to the buffer using the buffer protocol
+        to ensure that :attr:`size_bytes` accurately reflects the number of
+        bytes written to the buffer.
+        """
+    def finish(self, *args, **kwargs):
+        """Finish building this buffer
+
+        Performs any steps required to finish building this buffer and
+        returns the result. Any behaviour resulting from calling methods
+        on this object after it has been finished is not currently
+        defined (but should not crash).
+        """
+    def reserve_bytes(self, *args, **kwargs):
+        """Ensure that the underlying buffer has space for ``additional_bytes``
+        more bytes to be written"""
+    def set_data_type(self, *args, **kwargs):
+        """Set the data type used to interpret elements in :meth:`write_elements`."""
+    def set_format(self, *args, **kwargs):
+        """Set the Python buffer format used to interpret elements in
+        :meth:`write_elements`.
+        """
+    def write(self, *args, **kwargs):
+        """Write bytes to this buffer
+
+        Writes the bytes of ``content`` without considering the element type of
+        ``content`` or the element type of this buffer.
+
+        This method returns the number of bytes that were written.
+        """
+    def write_elements(self, *args, **kwargs):
+        """ "Write an iterable of elements to this buffer
+
+        Writes the elements of iterable ``obj`` according to the binary
+        representation specified by :attr:`format`. This is currently
+        powered by ``struct.pack_into()`` except when building bitmaps
+        where an internal implementation is used.
+
+        This method returns the number of elements that were written.
+        """
+    def write_fill(self, *args, **kwargs):
+        """Write fill bytes to this buffer
+
+        Appends the byte ``value`` to this buffer ``size_bytes`` times.
+        """
+    def __buffer__(self, *args, **kwargs):
+        """Return a buffer object that exposes the underlying memory of the object."""
+    def __len__(self) -> int:
+        """Return len(self)."""
+    def __reduce__(self): ...
+    def __release_buffer__(self, *args, **kwargs):
+        """Release the buffer object that exposes the underlying memory of the object."""
+
+class CBufferView:
+    __pyx_vtable__: ClassVar[PyCapsule] = ...
+    data_type: Incomplete
+    data_type_id: Incomplete
+    device: Incomplete
+    element_size_bits: Incomplete
+    format: Incomplete
+    itemsize: Incomplete
+    n_elements: Incomplete
+    size_bytes: Incomplete
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def copy(self, *args, **kwargs): ...
+    def copy_into(self, *args, **kwargs): ...
+    def element(self, *args, **kwargs): ...
+    def elements(self, *args, **kwargs): ...
+    def unpack_bits(self, *args, **kwargs): ...
+    def unpack_bits_into(self, *args, **kwargs): ...
+    def __buffer__(self, *args, **kwargs):
+        """Return a buffer object that exposes the underlying memory of the object."""
+    def __dlpack__(self, *args, **kwargs):
+        """
+        Export CBufferView as a DLPack capsule.
+
+        Parameters
+        ----------
+        stream : int, optional
+            A Python integer representing a pointer to a stream.
+            Stream is provided by the consumer to the producer to instruct the producer
+            to ensure that operations can safely be performed on the array.
+
+        Returns
+        -------
+        capsule : PyCapsule
+            A DLPack capsule for the array, pointing to a DLManagedTensor.
+        """
+    def __dlpack_device__(self, *args, **kwargs):
+        """
+        Return the DLPack device tuple this CBufferView resides on.
+
+        Returns
+        -------
+        tuple : Tuple[int, int]
+            Tuple with index specifying the type of the device (where
+            CPU = 1, see python/src/nanoarrow/dpack_abi.h) and index of the
+            device which is 0 by default for CPU.
+        """
+    def __getitem__(self, index):
+        """Return self[key]."""
+    def __iter__(self):
+        """Implement iter(self)."""
+    def __len__(self) -> int:
+        """Return len(self)."""
+    def __reduce__(self): ...
+    def __release_buffer__(self, *args, **kwargs):
+        """Release the buffer object that exposes the underlying memory of the object."""
+
+class NoneAwareWrapperIterator:
+    __pyx_vtable__: ClassVar[PyCapsule] = ...
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def finish(self, *args, **kwargs):
+        """Obtain the total count, null count, and validity bitmap after
+        consuming this iterable."""
+    def reserve(self, *args, **kwargs): ...
+    def __iter__(self):
+        """Implement iter(self)."""
+    def __reduce__(self): ...
diff --git a/python/src/nanoarrow/_device.pyi b/python/src/nanoarrow/_device.pyi
new file mode 100644
index 00000000..4d2c2079
--- /dev/null
+++ b/python/src/nanoarrow/_device.pyi
@@ -0,0 +1,81 @@
+# 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.
+
+import _cython_3_0_11
+import enum
+from _typeshed import Incomplete
+from typing import Callable, ClassVar
+
+DEVICE_CPU: Device
+__reduce_cython__: _cython_3_0_11.cython_function_or_method
+__setstate_cython__: _cython_3_0_11.cython_function_or_method
+__test__: dict
+
+class CSharedSyncEvent:
+    __pyx_vtable__: ClassVar[PyCapsule] = ...
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def __reduce__(self): ...
+
+class Device:
+    device_id: Incomplete
+    device_type: Incomplete
+    device_type_id: Incomplete
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    @staticmethod
+    def resolve(*args, **kwargs): ...
+    def __eq__(self, other: object) -> bool:
+        """Return self==value."""
+    def __ge__(self, other: object) -> bool:
+        """Return self>=value."""
+    def __gt__(self, other: object) -> bool:
+        """Return self>value."""
+    def __le__(self, other: object) -> bool:
+        """Return self<=value."""
+    def __lt__(self, other: object) -> bool:
+        """Return self<value."""
+    def __ne__(self, other: object) -> bool:
+        """Return self!=value."""
+    def __reduce__(self): ...
+
+class DeviceType(enum.Enum):
+    __new__: ClassVar[Callable] = ...
+    CPU: ClassVar[DeviceType] = ...
+    CUDA: ClassVar[DeviceType] = ...
+    CUDA_HOST: ClassVar[DeviceType] = ...
+    CUDA_MANAGED: ClassVar[DeviceType] = ...
+    EXT_DEV: ClassVar[DeviceType] = ...
+    HEXAGON: ClassVar[DeviceType] = ...
+    METAL: ClassVar[DeviceType] = ...
+    ONEAPI: ClassVar[DeviceType] = ...
+    OPENCL: ClassVar[DeviceType] = ...
+    ROCM: ClassVar[DeviceType] = ...
+    ROCM_HOST: ClassVar[DeviceType] = ...
+    VPI: ClassVar[DeviceType] = ...
+    VULKAN: ClassVar[DeviceType] = ...
+    WEBGPU: ClassVar[DeviceType] = ...
+    _generate_next_value_: ClassVar[Callable] = ...
+    _member_map_: ClassVar[dict] = ...
+    _member_names_: ClassVar[list] = ...
+    _member_type_: ClassVar[type[object]] = ...
+    _unhashable_values_: ClassVar[list] = ...
+    _use_args_: ClassVar[bool] = ...
+    _value2member_map_: ClassVar[dict] = ...
+    _value_repr_: ClassVar[None] = ...
diff --git a/python/src/nanoarrow/_ipc_lib.pyi b/python/src/nanoarrow/_ipc_lib.pyi
new file mode 100644
index 00000000..620dcba4
--- /dev/null
+++ b/python/src/nanoarrow/_ipc_lib.pyi
@@ -0,0 +1,71 @@
+# 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.
+
+import _cython_3_0_11
+from _typeshed import Incomplete
+
+__reduce_cython__: _cython_3_0_11.cython_function_or_method
+__setstate_cython__: _cython_3_0_11.cython_function_or_method
+__test__: dict
+init_array_stream: _cython_3_0_11.cython_function_or_method
+
+class CIpcInputStream:
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    @staticmethod
+    def from_readable(*args, **kwargs): ...
+    def is_valid(self, *args, **kwargs): ...
+    def release(self, *args, **kwargs): ...
+    def __reduce__(self): ...
+
+class CIpcOutputStream:
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    @staticmethod
+    def from_writable(*args, **kwargs): ...
+    def is_valid(self, *args, **kwargs): ...
+    def release(self, *args, **kwargs): ...
+    def __reduce__(self): ...
+
+class CIpcWriter:
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def is_valid(self, *args, **kwargs): ...
+    def release(self, *args, **kwargs): ...
+    def write_array_stream(self, *args, **kwargs): ...
+    def write_array_view(self, *args, **kwargs): ...
+    def write_end_of_stream(self, *args, **kwargs): ...
+    def write_schema(self, *args, **kwargs): ...
+    def __reduce__(self): ...
+
+class PyStreamPrivate:
+    close_obj: Incomplete
+    obj: Incomplete
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def set_buffer(self, *args, **kwargs): ...
+    def __buffer__(self, *args, **kwargs):
+        """Return a buffer object that exposes the underlying memory of the object."""
+    def __len__(self) -> int:
+        """Return len(self)."""
+    def __reduce__(self): ...
+    def __release_buffer__(self, *args, **kwargs):
+        """Release the buffer object that exposes the underlying memory of the object."""
diff --git a/python/src/nanoarrow/_schema.pyi b/python/src/nanoarrow/_schema.pyi
new file mode 100644
index 00000000..218fb783
--- /dev/null
+++ b/python/src/nanoarrow/_schema.pyi
@@ -0,0 +1,179 @@
+# 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.
+
+import _cython_3_0_11
+from _typeshed import Incomplete
+from typing import ClassVar
+
+__pyx_capi__: dict
+__reduce_cython__: _cython_3_0_11.cython_function_or_method
+__setstate_cython__: _cython_3_0_11.cython_function_or_method
+__test__: dict
+assert_type_equal: _cython_3_0_11.cython_function_or_method
+
+class CArrowTimeUnit:
+    MICRO: ClassVar[int] = ...
+    MILLI: ClassVar[int] = ...
+    NANO: ClassVar[int] = ...
+    SECOND: ClassVar[int] = ...
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def __reduce__(self): ...
+    def __reduce_cython__(self, *args, **kwargs): ...
+    def __setstate_cython__(self, *args, **kwargs): ...
+
+class CLayout:
+    buffer_data_type_id: Incomplete
+    child_size_elements: Incomplete
+    element_size_bits: Incomplete
+    n_buffers: Incomplete
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def __reduce__(self): ...
+
+class CSchema:
+    children: Incomplete
+    dictionary: Incomplete
+    flags: Incomplete
+    format: Incomplete
+    metadata: Incomplete
+    n_children: Incomplete
+    name: Incomplete
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    @staticmethod
+    def allocate(*args, **kwargs):
+        """Allocate a released CSchema"""
+    def child(self, *args, **kwargs): ...
+    def is_valid(self, *args, **kwargs):
+        """Check for a non-null and non-released underlying ArrowSchema"""
+    def modify(self, *args, **kwargs): ...
+    def type_equals(self, *args, **kwargs):
+        """Test two schemas for data type equality
+
+        Checks two CSchema objects for type equality (i.e., that an array with
+        schema ``actual`` contains elements with the same logical meaning as and
+        array with schema ``expected``). Notably, this excludes metadata from
+        all nodes in the schema.
+
+        Parameters
+        ----------
+        other : CSchema
+            The schema against which to test
+        check_nullability : bool
+            If True, actual and expected will be considered equal if their
+            data type information and marked nullability are identical.
+        """
+    def __arrow_c_schema__(self, *args, **kwargs):
+        """
+        Export to a ArrowSchema PyCapsule
+        """
+    def __deepcopy__(self): ...
+    def __reduce__(self): ...
+
+class CSchemaBuilder:
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    @staticmethod
+    def allocate(*args, **kwargs):
+        """Create a CSchemaBuilder
+
+        Allocates memory for an ArrowSchema and populates it with nanoarrow's
+        ArrowSchema private_data/release callback implementation. This should
+        usually be followed by :meth:`set_type` or :meth:`set_format`.
+        """
+    def allocate_children(self, *args, **kwargs): ...
+    def append_metadata(self, *args, **kwargs):
+        """Append key/value metadata"""
+    def child(self, *args, **kwargs): ...
+    def finish(self, *args, **kwargs): ...
+    def set_child(self, *args, **kwargs): ...
+    def set_dictionary(self, *args, **kwargs): ...
+    def set_dictionary_ordered(self, *args, **kwargs): ...
+    def set_flags(self, *args, **kwargs): ...
+    def set_format(self, *args, **kwargs): ...
+    def set_name(self, *args, **kwargs): ...
+    def set_nullable(self, *args, **kwargs): ...
+    def set_type(self, *args, **kwargs): ...
+    def set_type_date_time(self, *args, **kwargs): ...
+    def set_type_decimal(self, *args, **kwargs): ...
+    def set_type_fixed_size(self, *args, **kwargs): ...
+    def validate(self, *args, **kwargs): ...
+    def __reduce__(self): ...
+
+class CSchemaView:
+    buffer_format: Incomplete
+    decimal_bitwidth: Incomplete
+    decimal_precision: Incomplete
+    decimal_scale: Incomplete
+    dictionary_ordered: Incomplete
+    extension_metadata: Incomplete
+    extension_name: Incomplete
+    fixed_size: Incomplete
+    layout: Incomplete
+    map_keys_sorted: Incomplete
+    nullable: Incomplete
+    storage_buffer_format: Incomplete
+    storage_type: Incomplete
+    storage_type_id: Incomplete
+    time_unit: Incomplete
+    time_unit_id: Incomplete
+    timezone: Incomplete
+    type: Incomplete
+    type_id: Incomplete
+    union_type_ids: Incomplete
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def __reduce__(self): ...
+
+class SchemaMetadata:
+    __pyx_vtable__: ClassVar[PyCapsule] = ...
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    @staticmethod
+    def empty(*args, **kwargs):
+        """Create an empty SchemaMetadata with no keys or values"""
+    def items(self, *args, **kwargs):
+        """Iterate over key/value pairs
+
+        The result may contain duplicate keys if they exist in the metadata."""
+    def keys(self, *args, **kwargs):
+        """List meadata keys
+
+        The result may contain duplicate keys if they exist in the metadata.
+        """
+    def values(self, *args, **kwargs):
+        """List metadata values"""
+    def __contains__(self, other) -> bool:
+        """Return bool(key in self)."""
+    def __getitem__(self, index):
+        """Get the value associated with a unique key
+
+        Retrieves the unique value associated with k. Raises KeyError if
+        k does not point to exactly one value in the metadata.
+        """
+    def __iter__(self):
+        """Implement iter(self)."""
+    def __len__(self) -> int:
+        """Return len(self)."""
+    def __reduce__(self): ...
diff --git a/python/src/nanoarrow/_types.pyi b/python/src/nanoarrow/_types.pyi
new file mode 100644
index 00000000..23c8cf8c
--- /dev/null
+++ b/python/src/nanoarrow/_types.pyi
@@ -0,0 +1,133 @@
+# 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.
+
+import _cython_3_0_11
+import enum
+from typing import Callable, ClassVar
+
+BINARY: CArrowType
+BOOL: CArrowType
+DATE32: CArrowType
+DATE64: CArrowType
+DECIMAL128: CArrowType
+DECIMAL256: CArrowType
+DENSE_UNION: CArrowType
+DICTIONARY: CArrowType
+DOUBLE: CArrowType
+DURATION: CArrowType
+EXTENSION: CArrowType
+FIXED_SIZE_BINARY: CArrowType
+FIXED_SIZE_LIST: CArrowType
+FLOAT: CArrowType
+HALF_FLOAT: CArrowType
+INT16: CArrowType
+INT32: CArrowType
+INT64: CArrowType
+INT8: CArrowType
+INTERVAL_DAY_TIME: CArrowType
+INTERVAL_MONTHS: CArrowType
+INTERVAL_MONTH_DAY_NANO: CArrowType
+LARGE_BINARY: CArrowType
+LARGE_LIST: CArrowType
+LARGE_STRING: CArrowType
+LIST: CArrowType
+MAP: CArrowType
+NA: CArrowType
+SPARSE_UNION: CArrowType
+STRING: CArrowType
+STRUCT: CArrowType
+TIME32: CArrowType
+TIME64: CArrowType
+TIMESTAMP: CArrowType
+UINT16: CArrowType
+UINT32: CArrowType
+UINT64: CArrowType
+UINT8: CArrowType
+UNINITIALIZED: CArrowType
+__pyx_capi__: dict
+__test__: dict
+has_time_unit: _cython_3_0_11.cython_function_or_method
+is_decimal: _cython_3_0_11.cython_function_or_method
+is_fixed_size: _cython_3_0_11.cython_function_or_method
+is_floating_point: _cython_3_0_11.cython_function_or_method
+is_signed_integer: _cython_3_0_11.cython_function_or_method
+is_union: _cython_3_0_11.cython_function_or_method
+is_unsigned_integer: _cython_3_0_11.cython_function_or_method
+sys_byteorder: str
+
+class CArrowType(enum.IntFlag):
+    __new__: ClassVar[Callable] = ...
+    BINARY: ClassVar[CArrowType] = ...
+    BOOL: ClassVar[CArrowType] = ...
+    DATE32: ClassVar[CArrowType] = ...
+    DATE64: ClassVar[CArrowType] = ...
+    DECIMAL128: ClassVar[CArrowType] = ...
+    DECIMAL256: ClassVar[CArrowType] = ...
+    DENSE_UNION: ClassVar[CArrowType] = ...
+    DICTIONARY: ClassVar[CArrowType] = ...
+    DOUBLE: ClassVar[CArrowType] = ...
+    DURATION: ClassVar[CArrowType] = ...
+    EXTENSION: ClassVar[CArrowType] = ...
+    FIXED_SIZE_BINARY: ClassVar[CArrowType] = ...
+    FIXED_SIZE_LIST: ClassVar[CArrowType] = ...
+    FLOAT: ClassVar[CArrowType] = ...
+    HALF_FLOAT: ClassVar[CArrowType] = ...
+    INT16: ClassVar[CArrowType] = ...
+    INT32: ClassVar[CArrowType] = ...
+    INT64: ClassVar[CArrowType] = ...
+    INT8: ClassVar[CArrowType] = ...
+    INTERVAL_DAY_TIME: ClassVar[CArrowType] = ...
+    INTERVAL_MONTHS: ClassVar[CArrowType] = ...
+    INTERVAL_MONTH_DAY_NANO: ClassVar[CArrowType] = ...
+    LARGE_BINARY: ClassVar[CArrowType] = ...
+    LARGE_LIST: ClassVar[CArrowType] = ...
+    LARGE_STRING: ClassVar[CArrowType] = ...
+    LIST: ClassVar[CArrowType] = ...
+    MAP: ClassVar[CArrowType] = ...
+    NA: ClassVar[CArrowType] = ...
+    SPARSE_UNION: ClassVar[CArrowType] = ...
+    STRING: ClassVar[CArrowType] = ...
+    STRUCT: ClassVar[CArrowType] = ...
+    TIME32: ClassVar[CArrowType] = ...
+    TIME64: ClassVar[CArrowType] = ...
+    TIMESTAMP: ClassVar[CArrowType] = ...
+    UINT16: ClassVar[CArrowType] = ...
+    UINT32: ClassVar[CArrowType] = ...
+    UINT64: ClassVar[CArrowType] = ...
+    UINT8: ClassVar[CArrowType] = ...
+    UNINITIALIZED: ClassVar[CArrowType] = ...
+    _all_bits_: ClassVar[int] = ...
+    _boundary_: ClassVar[enum.FlagBoundary] = ...
+    _flag_mask_: ClassVar[int] = ...
+    _generate_next_value_: ClassVar[Callable] = ...
+    _inverted_: ClassVar[None] = ...
+    _member_map_: ClassVar[dict] = ...
+    _member_names_: ClassVar[list] = ...
+    _member_type_: ClassVar[type[int]] = ...
+    _singles_mask_: ClassVar[int] = ...
+    _unhashable_values_: ClassVar[list] = ...
+    _use_args_: ClassVar[bool] = ...
+    _value2member_map_: ClassVar[dict] = ...
+    __and__: ClassVar[Callable] = ...
+    __invert__: ClassVar[Callable] = ...
+    __or__: ClassVar[Callable] = ...
+    __rand__: ClassVar[Callable] = ...
+    __ror__: ClassVar[Callable] = ...
+    __rxor__: ClassVar[Callable] = ...
+    __xor__: ClassVar[Callable] = ...
+    def __format__(self, *args, **kwargs) -> str:
+        """Convert to a string according to format_spec."""
diff --git a/python/src/nanoarrow/_utils.pyi b/python/src/nanoarrow/_utils.pyi
new file mode 100644
index 00000000..90a68cd5
--- /dev/null
+++ b/python/src/nanoarrow/_utils.pyi
@@ -0,0 +1,38 @@
+# 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.
+
+import _cython_3_0_11
+from typing import ClassVar
+
+__pyx_capi__: dict
+__reduce_cython__: _cython_3_0_11.cython_function_or_method
+__setstate_cython__: _cython_3_0_11.cython_function_or_method
+__test__: dict
+c_version: _cython_3_0_11.cython_function_or_method
+get_pyobject_buffer_count: _cython_3_0_11.cython_function_or_method
+obj_is_buffer: _cython_3_0_11.cython_function_or_method
+obj_is_capsule: _cython_3_0_11.cython_function_or_method
+
+class Error:
+    __pyx_vtable__: ClassVar[PyCapsule] = ...
+    @classmethod
+    def __init__(cls, *args, **kwargs) -> None:
+        """Create and return a new object.  See help(type) for accurate signature."""
+    def __reduce__(self): ...
+
+class NanoarrowException(RuntimeError):
+    def __init__(self, *args, **kwargs) -> None: ...