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

github-bot pushed a commit to branch asf-staging
in repository https://gitbox.apache.org/repos/asf/datafusion-python.git


The following commit(s) were added to refs/heads/asf-staging by this push:
     new 9894b5e0 Publish built docs triggered by 
e6f6e66c1d180246ad933f8bcc0d40faa8426dfa
9894b5e0 is described below

commit 9894b5e0b6eb3d219decb1bfad5577041e198296
Author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Feb 21 21:08:50 2025 +0000

    Publish built docs triggered by e6f6e66c1d180246ad933f8bcc0d40faa8426dfa
---
 _sources/contributor-guide/ffi.rst.txt             | 212 +++++++
 _sources/index.rst.txt                             |   1 +
 autoapi/datafusion/catalog/index.html              |   5 +
 autoapi/datafusion/context/index.html              |   5 +
 autoapi/datafusion/dataframe/index.html            |   5 +
 autoapi/datafusion/expr/index.html                 |   5 +
 autoapi/datafusion/functions/index.html            |   5 +
 autoapi/datafusion/index.html                      |   5 +
 autoapi/datafusion/input/base/index.html           |   5 +
 autoapi/datafusion/input/index.html                |   5 +
 autoapi/datafusion/input/location/index.html       |   5 +
 autoapi/datafusion/object_store/index.html         |   5 +
 autoapi/datafusion/plan/index.html                 |   5 +
 autoapi/datafusion/record_batch/index.html         |   5 +
 autoapi/datafusion/substrait/index.html            |   5 +
 autoapi/datafusion/udf/index.html                  |   5 +
 autoapi/index.html                                 |  11 +-
 contributor-guide/ffi.html                         | 639 +++++++++++++++++++++
 contributor-guide/introduction.html                |  11 +-
 genindex.html                                      |   5 +
 index.html                                         |   5 +
 objects.inv                                        | Bin 5945 -> 5964 bytes
 py-modindex.html                                   |   5 +
 search.html                                        |   5 +
 searchindex.js                                     |   2 +-
 user-guide/basics.html                             |   5 +
 user-guide/common-operations/aggregations.html     |  67 ++-
 user-guide/common-operations/basic-info.html       |  51 +-
 user-guide/common-operations/expressions.html      |   5 +
 user-guide/common-operations/functions.html        |  25 +-
 user-guide/common-operations/index.html            |   5 +
 user-guide/common-operations/joins.html            |   5 +
 .../common-operations/select-and-filter.html       |   5 +
 user-guide/common-operations/udf-and-udfa.html     |   5 +
 user-guide/common-operations/windows.html          |  33 +-
 user-guide/configuration.html                      |   5 +
 user-guide/data-sources.html                       |   5 +
 user-guide/introduction.html                       |   5 +
 user-guide/io/arrow.html                           |   5 +
 user-guide/io/avro.html                            |   5 +
 user-guide/io/csv.html                             |   5 +
 user-guide/io/index.html                           |   5 +
 user-guide/io/json.html                            |   5 +
 user-guide/io/parquet.html                         |   5 +
 user-guide/io/table_provider.html                  |   5 +
 user-guide/sql.html                                |   5 +
 46 files changed, 1142 insertions(+), 85 deletions(-)

diff --git a/_sources/contributor-guide/ffi.rst.txt 
b/_sources/contributor-guide/ffi.rst.txt
new file mode 100644
index 00000000..c1f9806b
--- /dev/null
+++ b/_sources/contributor-guide/ffi.rst.txt
@@ -0,0 +1,212 @@
+.. 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.
+
+Python Extensions
+=================
+
+The DataFusion in Python project is designed to allow users to extend its 
functionality in a few core
+areas. Ideally many users would like to package their extensions as a Python 
package and easily
+integrate that package with this project. This page serves to describe some of 
the challenges we face
+when doing these integrations and the approach our project uses.
+
+The Primary Issue
+-----------------
+
+Suppose you wish to use DataFusion and you have a custom data source that can 
produce tables that
+can then be queried against, similar to how you can register a :ref:`CSV 
<io_csv>` or
+:ref:`Parquet <io_parquet>` file. In DataFusion terminology, you likely want 
to implement a 
+:ref:`Custom Table Provider <io_custom_table_provider>`. In an effort to make 
your data source
+as performant as possible and to utilize the features of DataFusion, you may 
decide to write
+your source in Rust and then expose it through `PyO3 <https://pyo3.rs>`_ as a 
Python library.
+
+At first glance, it may appear the best way to do this is to add the 
``datafusion-python``
+crate as a dependency, provide a ``PyTable``, and then to register it with the 
+``SessionContext``. Unfortunately, this will not work.
+
+When you produce your code as a Python library and it needs to interact with 
the DataFusion
+library, at the lowest level they communicate through an Application Binary 
Interface (ABI).
+The acronym sounds similar to API (Application Programming Interface), but it 
is distinctly
+different.
+
+The ABI sets the standard for how these libraries can share data and functions 
between each
+other. One of the key differences between Rust and other programming languages 
is that Rust
+does not have a stable ABI. What this means in practice is that if you compile 
a Rust library
+with one version of the ``rustc`` compiler and I compile another library to 
interface with it
+but I use a different version of the compiler, there is no guarantee the 
interface will be
+the same.
+
+In practice, this means that a Python library built with ``datafusion-python`` 
as a Rust
+dependency will generally **not** be compatible with the DataFusion Python 
package, even
+if they reference the same version of ``datafusion-python``. If you attempt to 
do this, it may
+work on your local computer if you have built both packages with the same 
optimizations.
+This can sometimes lead to a false expectation that the code will work, but it 
frequently
+breaks the moment you try to use your package against the released packages.
+
+You can find more information about the Rust ABI in their
+`online documentation <https://doc.rust-lang.org/reference/abi.html>`_.
+
+The FFI Approach
+----------------
+
+Rust supports interacting with other programming languages through it's 
Foreign Function
+Interface (FFI). The advantage of using the FFI is that it enables you to 
write data structures
+and functions that have a stable ABI. The allows you to use Rust code with C, 
Python, and
+other languages. In fact, the `PyO3 <https://pyo3.rs>`_ library uses the FFI 
to share data
+and functions between Python and Rust.
+
+The approach we are taking in the DataFusion in Python project is to 
incrementally expose
+more portions of the DataFusion project via FFI interfaces. This allows users 
to write Rust
+code that does **not** require the ``datafusion-python`` crate as a 
dependency, expose their
+code in Python via PyO3, and have it interact with the DataFusion Python 
package.
+
+Early adopters of this approach include `delta-rs 
<https://delta-io.github.io/delta-rs/>`_
+who has adapted their Table Provider for use in ```datafusion-python``` with 
only a few lines
+of code. Also, the DataFusion Python project uses the existing definitions from
+`Apache Arrow CStream Interface 
<https://arrow.apache.org/docs/format/CStreamInterface.html>`_
+to support importing **and** exporting tables. Any Python package that 
supports reading
+the Arrow C Stream interface can work with DataFusion Python out of the box! 
You can read
+more about working with Arrow sources in the :ref:`Data Sources 
<user_guide_data_sources>`
+page.
+
+To learn more about the Foreign Function Interface in Rust, the
+`Rustonomicon <https://doc.rust-lang.org/nomicon/ffi.html>`_ is a good 
resource.
+
+Inspiration from Arrow
+----------------------
+
+DataFusion is built upon `Apache Arrow <https://arrow.apache.org/>`_. The 
canonical Python
+Arrow implementation, `pyarrow 
<https://arrow.apache.org/docs/python/index.html>`_ provides
+an excellent way to share Arrow data between Python projects without 
performing any copy
+operations on the data. They do this by using a well defined set of 
interfaces. You can
+find the details about their stream interface
+`here <https://arrow.apache.org/docs/format/CStreamInterface.html>`_. The
+`Rust Arrow Implementation <https://github.com/apache/arrow-rs>`_ also 
supports these
+``C`` style definitions via the Foreign Function Interface.
+
+In addition to using these interfaces to transfer Arrow data between 
libraries, ``pyarrow``
+goes one step further to make sharing the interfaces easier in Python. They do 
this
+by exposing PyCapsules that contain the expected functionality.
+
+You can learn more about PyCapsules from the official
+`Python online documentation <https://docs.python.org/3/c-api/capsule.html>`_. 
PyCapsules
+have excellent support in PyO3 already. The
+`PyO3 online documentation 
<https://pyo3.rs/main/doc/pyo3/types/struct.pycapsule>`_ is a good source
+for more details on using PyCapsules in Rust.
+
+Two lessons we leverage from the Arrow project in DataFusion Python are:
+
+- We reuse the existing Arrow FFI functionality wherever possible.
+- We expose PyCapsules that contain a FFI stable struct.
+
+Implementation Details
+----------------------
+
+The bulk of the code necessary to perform our FFI operations is in the 
upstream 
+`DataFusion <https://datafusion.apache.org/>`_ core repository. You can review 
the code and
+documentation in the `datafusion-ffi`_ crate.
+
+Our FFI implementation is narrowly focused at sharing data and functions with 
Rust backed
+libraries. This allows us to use the `abi_stable crate 
<https://crates.io/crates/abi_stable>`_.
+This is an excellent crate that allows for easy conversion between Rust native 
types
+and FFI-safe alternatives. For example, if you needed to pass a 
``Vec<String>`` via FFI,
+you can simply convert it to a ``RVec<RString>`` in an intuitive manner. It 
also supports
+features like ``RResult`` and ``ROption`` that do not have an obvious 
translation to a
+C equivalent.
+
+The `datafusion-ffi`_ crate has been designed to make it easy to convert from 
DataFusion
+traits into their FFI counterparts. For example, if you have defined a custom
+`TableProvider 
<https://docs.rs/datafusion/45.0.0/datafusion/catalog/trait.TableProvider.html>`_
+and you want to create a sharable FFI counterpart, you could write:
+
+.. code-block:: rust
+
+    let my_provider = MyTableProvider::default();
+    let ffi_provider = FFI_TableProvider::new(Arc::new(my_provider), false, 
None);
+
+If you were interfacing with a library that provided the above 
``FFI_TableProvider`` and
+you needed to turn it back into an ``TableProvider``, you can turn it into a
+``ForeignTableProvider`` with implements the ``TableProvider`` trait.
+
+.. code-block:: rust
+
+    let foreign_provider: ForeignTableProvider = ffi_provider.into();
+
+If you review the code in `datafusion-ffi`_ you will find that each of the 
traits we share
+across the boundary has two portions, one with a ``FFI_`` prefix and one with 
a ``Foreign``
+prefix. This is used to distinguish which side of the FFI boundary that struct 
is
+designed to be used on. The structures with the ``FFI_`` prefix are to be used 
on the
+**provider** of the structure. In the example we're showing, this means the 
code that has
+written the underlying ``TableProvider`` implementation to access your custom 
data source.
+The structures with the ``Foreign`` prefix are to be used by the receiver. In 
this case,
+it is the ``datafusion-python`` library.
+
+In order to share these FFI structures, we need to wrap them in some kind of 
Python object
+that can be used to interface from one package to another. As described in the 
above
+section on our inspiration from Arrow, we use ``PyCapsule``. We can create a 
``PyCapsule``
+for our provider thusly:
+
+.. code-block:: rust
+
+    let name = CString::new("datafusion_table_provider")?;
+    let my_capsule = PyCapsule::new_bound(py, provider, Some(name))?;
+
+On the receiving side, turn this pycapsule object into the 
``FFI_TableProvider``, which
+can then be turned into a ``ForeignTableProvider`` the associated code is:
+
+.. code-block:: rust
+
+    let capsule = capsule.downcast::<PyCapsule>()?;
+    let provider = unsafe { capsule.reference::<FFI_TableProvider>() };
+
+By convention the ``datafusion-python`` library expects a Python object that 
has a
+``TableProvider`` PyCapsule to have this capsule accessible by calling a 
function named
+``__datafusion_table_provider__``. You can see a complete working example of 
how to
+share a ``TableProvider`` from one python library to DataFusion Python in the
+`repository examples folder 
<https://github.com/apache/datafusion-python/tree/main/examples/ffi-table-provider>`_.
+
+This section has been written using ``TableProvider`` as an example. It is the 
first
+extension that has been written using this approach and the most thoroughly 
implemented.
+As we continue to expose more of the DataFusion features, we intend to follow 
this same
+design pattern.
+
+Alternative Approach
+--------------------
+
+Suppose you needed to expose some other features of DataFusion and you could 
not wait
+for the upstream repository to implement the FFI approach we describe. In this 
case
+you decide to create your dependency on the ``datafusion-python`` crate 
instead.
+
+As we discussed, this is not guaranteed to work across different compiler 
versions and
+optimization levels. If you wish to go down this route, there are two 
approaches we
+have identified you can use.
+
+#. Re-export all of ``datafusion-python`` yourself with your extensions built 
in.
+#. Carefully synchonize your software releases with the ``datafusion-python`` 
CI build
+   system so that your libraries use the exact same compiler, features, and
+   optimization level.
+
+We currently do not recommend either of these approaches as they are difficult 
to
+maintain over a long period. Additionally, they require a tight version 
coupling
+between libraries.
+
+Status of Work
+--------------
+
+At the time of this writing, the FFI features are under active development. To 
see
+the latest status, we recommend reviewing the code in the `datafusion-ffi`_ 
crate.
+
+.. _datafusion-ffi: https://crates.io/crates/datafusion-ffi
diff --git a/_sources/index.rst.txt b/_sources/index.rst.txt
index 34eb23b2..558b2d57 100644
--- a/_sources/index.rst.txt
+++ b/_sources/index.rst.txt
@@ -85,6 +85,7 @@ Example
    :caption: CONTRIBUTOR GUIDE
 
    contributor-guide/introduction
+   contributor-guide/ffi
 
 .. _toc.api:
 .. toctree::
diff --git a/autoapi/datafusion/catalog/index.html 
b/autoapi/datafusion/catalog/index.html
index 3f250b3d..36c952b1 100644
--- a/autoapi/datafusion/catalog/index.html
+++ b/autoapi/datafusion/catalog/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/context/index.html 
b/autoapi/datafusion/context/index.html
index e2026edb..e2490f47 100644
--- a/autoapi/datafusion/context/index.html
+++ b/autoapi/datafusion/context/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/dataframe/index.html 
b/autoapi/datafusion/dataframe/index.html
index da5003d9..8faad512 100644
--- a/autoapi/datafusion/dataframe/index.html
+++ b/autoapi/datafusion/dataframe/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/expr/index.html 
b/autoapi/datafusion/expr/index.html
index 78ecdc6c..93510fcb 100644
--- a/autoapi/datafusion/expr/index.html
+++ b/autoapi/datafusion/expr/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/functions/index.html 
b/autoapi/datafusion/functions/index.html
index 6ddd0a95..9d0bf9c0 100644
--- a/autoapi/datafusion/functions/index.html
+++ b/autoapi/datafusion/functions/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/index.html b/autoapi/datafusion/index.html
index f4c3d351..fd9864c3 100644
--- a/autoapi/datafusion/index.html
+++ b/autoapi/datafusion/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/input/base/index.html 
b/autoapi/datafusion/input/base/index.html
index cf44b1ae..4d2835a8 100644
--- a/autoapi/datafusion/input/base/index.html
+++ b/autoapi/datafusion/input/base/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/input/index.html 
b/autoapi/datafusion/input/index.html
index 896164da..fada80ae 100644
--- a/autoapi/datafusion/input/index.html
+++ b/autoapi/datafusion/input/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/input/location/index.html 
b/autoapi/datafusion/input/location/index.html
index 9d466821..2e087e41 100644
--- a/autoapi/datafusion/input/location/index.html
+++ b/autoapi/datafusion/input/location/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/object_store/index.html 
b/autoapi/datafusion/object_store/index.html
index 71ad4a83..e780cdf8 100644
--- a/autoapi/datafusion/object_store/index.html
+++ b/autoapi/datafusion/object_store/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/plan/index.html 
b/autoapi/datafusion/plan/index.html
index ddf72b35..c5f958c6 100644
--- a/autoapi/datafusion/plan/index.html
+++ b/autoapi/datafusion/plan/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/record_batch/index.html 
b/autoapi/datafusion/record_batch/index.html
index f322281d..7e5bdde2 100644
--- a/autoapi/datafusion/record_batch/index.html
+++ b/autoapi/datafusion/record_batch/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/substrait/index.html 
b/autoapi/datafusion/substrait/index.html
index 9b71cde5..d91a000a 100644
--- a/autoapi/datafusion/substrait/index.html
+++ b/autoapi/datafusion/substrait/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/datafusion/udf/index.html 
b/autoapi/datafusion/udf/index.html
index 5452e591..b129e3a1 100644
--- a/autoapi/datafusion/udf/index.html
+++ b/autoapi/datafusion/udf/index.html
@@ -232,6 +232,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/autoapi/index.html b/autoapi/index.html
index da449fcf..c9749203 100644
--- a/autoapi/index.html
+++ b/autoapi/index.html
@@ -35,7 +35,7 @@
     <link rel="index" title="Index" href="../genindex.html" />
     <link rel="search" title="Search" href="../search.html" />
     <link rel="next" title="datafusion" href="datafusion/index.html" />
-    <link rel="prev" title="Introduction" 
href="../contributor-guide/introduction.html" />
+    <link rel="prev" title="Python Extensions" 
href="../contributor-guide/ffi.html" />
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <meta name="docsearch:language" content="en">
     
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
@@ -415,11 +420,11 @@
               
               <!-- Previous / next buttons -->
 <div class='prev-next-area'>
-    <a class='left-prev' id="prev-link" 
href="../contributor-guide/introduction.html" title="previous page">
+    <a class='left-prev' id="prev-link" href="../contributor-guide/ffi.html" 
title="previous page">
         <i class="fas fa-angle-left"></i>
         <div class="prev-next-info">
             <p class="prev-next-subtitle">previous</p>
-            <p class="prev-next-title">Introduction</p>
+            <p class="prev-next-title">Python Extensions</p>
         </div>
     </a>
     <a class='right-next' id="next-link" href="datafusion/index.html" 
title="next page">
diff --git a/contributor-guide/ffi.html b/contributor-guide/ffi.html
new file mode 100644
index 00000000..2d3a3011
--- /dev/null
+++ b/contributor-guide/ffi.html
@@ -0,0 +1,639 @@
+<!DOCTYPE html>
+
+<html lang="en" data-content_root="../">
+  <head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" 
/><meta name="viewport" content="width=device-width, initial-scale=1" />
+
+    <title>Python Extensions &#8212; Apache Arrow DataFusion  
documentation</title>
+    
+    <link href="../_static/styles/theme.css?digest=1999514e3f237ded88cf" 
rel="stylesheet">
+<link 
href="../_static/styles/pydata-sphinx-theme.css?digest=1999514e3f237ded88cf" 
rel="stylesheet">
+  
+    
+    <link rel="stylesheet"
+      href="../_static/vendor/fontawesome/5.13.0/css/all.min.css">
+    <link rel="preload" as="font" type="font/woff2" crossorigin
+      href="../_static/vendor/fontawesome/5.13.0/webfonts/fa-solid-900.woff2">
+    <link rel="preload" as="font" type="font/woff2" crossorigin
+      href="../_static/vendor/fontawesome/5.13.0/webfonts/fa-brands-400.woff2">
+  
+    
+      
+  
+    
+    <link rel="stylesheet" type="text/css" 
href="../_static/pygments.css?v=8f2a1f02" />
+    <link rel="stylesheet" type="text/css" 
href="../_static/styles/pydata-sphinx-theme.css?v=1140d252" />
+    <link rel="stylesheet" type="text/css" 
href="../_static/graphviz.css?v=4ae1632d" />
+    <link rel="stylesheet" type="text/css" 
href="../_static/theme_overrides.css?v=dca7052a" />
+    
+    <link rel="preload" as="script" 
href="../_static/scripts/pydata-sphinx-theme.js?digest=1999514e3f237ded88cf">
+  
+    <script src="../_static/documentation_options.js?v=8a448e45"></script>
+    <script src="../_static/doctools.js?v=9bcbadda"></script>
+    <script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
+    <link rel="index" title="Index" href="../genindex.html" />
+    <link rel="search" title="Search" href="../search.html" />
+    <link rel="next" title="API Reference" href="../autoapi/index.html" />
+    <link rel="prev" title="Introduction" href="introduction.html" />
+    <meta name="viewport" content="width=device-width, initial-scale=1" />
+    <meta name="docsearch:language" content="en">
+    
+
+    <!-- Google Analytics -->
+    
+  </head>
+  <body data-spy="scroll" data-target="#bd-toc-nav" data-offset="80">
+    
+    <div class="container-fluid" id="banner"></div>
+
+    
+
+
+    <div class="container-xl">
+      <div class="row">
+          
+            
+            <!-- Only show if we have sidebars configured, else just a small 
margin  -->
+            <div class="col-12 col-md-3 bd-sidebar">
+              <div class="sidebar-start-items">
+<a class="navbar-brand" href="../index.html">
+  <img src="../_static/images/2x_bgwhite_original.png" class="logo" alt="logo">
+</a>
+
+<form class="bd-search d-flex align-items-center" action="../search.html" 
method="get">
+  <i class="icon fas fa-search"></i>
+  <input type="search" class="form-control" name="q" id="search-input" 
placeholder="Search the docs ..." aria-label="Search the docs ..." 
autocomplete="off" >
+</form>
+
+<nav class="bd-links" id="bd-docs-nav" aria-label="Main navigation">
+  <div class="bd-toc-item active">
+    
+    <p aria-level="2" class="caption" role="heading">
+ <span class="caption-text">
+  LINKS
+ </span>
+</p>
+<ul class="nav bd-sidenav">
+ <li class="toctree-l1">
+  <a class="reference external" 
href="https://github.com/apache/datafusion-python";>
+   Github and Issue Tracker
+  </a>
+ </li>
+ <li class="toctree-l1">
+  <a class="reference external" 
href="https://docs.rs/datafusion/latest/datafusion/";>
+   Rust's API Docs
+  </a>
+ </li>
+ <li class="toctree-l1">
+  <a class="reference external" 
href="https://github.com/apache/datafusion/blob/main/CODE_OF_CONDUCT.md";>
+   Code of conduct
+  </a>
+ </li>
+ <li class="toctree-l1">
+  <a class="reference external" 
href="https://github.com/apache/datafusion-python/tree/main/examples";>
+   Examples
+  </a>
+ </li>
+</ul>
+<p aria-level="2" class="caption" role="heading">
+ <span class="caption-text">
+  USER GUIDE
+ </span>
+</p>
+<ul class="nav bd-sidenav">
+ <li class="toctree-l1">
+  <a class="reference internal" href="../user-guide/introduction.html">
+   Introduction
+  </a>
+ </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../user-guide/basics.html">
+   Concepts
+  </a>
+ </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../user-guide/data-sources.html">
+   Data Sources
+  </a>
+ </li>
+ <li class="toctree-l1 has-children">
+  <a class="reference internal" 
href="../user-guide/common-operations/index.html">
+   Common Operations
+  </a>
+  <input class="toctree-checkbox" id="toctree-checkbox-1" 
name="toctree-checkbox-1" type="checkbox"/>
+  <label for="toctree-checkbox-1">
+   <i class="fas fa-chevron-down">
+   </i>
+  </label>
+  <ul>
+   <li class="toctree-l2">
+    <a class="reference internal" 
href="../user-guide/common-operations/basic-info.html">
+     Basic Operations
+    </a>
+   </li>
+   <li class="toctree-l2">
+    <a class="reference internal" 
href="../user-guide/common-operations/select-and-filter.html">
+     Column Selections
+    </a>
+   </li>
+   <li class="toctree-l2">
+    <a class="reference internal" 
href="../user-guide/common-operations/expressions.html">
+     Expressions
+    </a>
+   </li>
+   <li class="toctree-l2">
+    <a class="reference internal" 
href="../user-guide/common-operations/joins.html">
+     Joins
+    </a>
+   </li>
+   <li class="toctree-l2">
+    <a class="reference internal" 
href="../user-guide/common-operations/functions.html">
+     Functions
+    </a>
+   </li>
+   <li class="toctree-l2">
+    <a class="reference internal" 
href="../user-guide/common-operations/aggregations.html">
+     Aggregation
+    </a>
+   </li>
+   <li class="toctree-l2">
+    <a class="reference internal" 
href="../user-guide/common-operations/windows.html">
+     Window Functions
+    </a>
+   </li>
+   <li class="toctree-l2">
+    <a class="reference internal" 
href="../user-guide/common-operations/udf-and-udfa.html">
+     User-Defined Functions
+    </a>
+   </li>
+  </ul>
+ </li>
+ <li class="toctree-l1 has-children">
+  <a class="reference internal" href="../user-guide/io/index.html">
+   IO
+  </a>
+  <input class="toctree-checkbox" id="toctree-checkbox-2" 
name="toctree-checkbox-2" type="checkbox"/>
+  <label for="toctree-checkbox-2">
+   <i class="fas fa-chevron-down">
+   </i>
+  </label>
+  <ul>
+   <li class="toctree-l2">
+    <a class="reference internal" href="../user-guide/io/arrow.html">
+     Arrow
+    </a>
+   </li>
+   <li class="toctree-l2">
+    <a class="reference internal" href="../user-guide/io/avro.html">
+     Avro
+    </a>
+   </li>
+   <li class="toctree-l2">
+    <a class="reference internal" href="../user-guide/io/csv.html">
+     CSV
+    </a>
+   </li>
+   <li class="toctree-l2">
+    <a class="reference internal" href="../user-guide/io/json.html">
+     JSON
+    </a>
+   </li>
+   <li class="toctree-l2">
+    <a class="reference internal" href="../user-guide/io/parquet.html">
+     Parquet
+    </a>
+   </li>
+   <li class="toctree-l2">
+    <a class="reference internal" href="../user-guide/io/table_provider.html">
+     Custom Table Provider
+    </a>
+   </li>
+  </ul>
+ </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../user-guide/configuration.html">
+   Configuration
+  </a>
+ </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../user-guide/sql.html">
+   SQL
+  </a>
+ </li>
+</ul>
+<p aria-level="2" class="caption" role="heading">
+ <span class="caption-text">
+  CONTRIBUTOR GUIDE
+ </span>
+</p>
+<ul class="current nav bd-sidenav">
+ <li class="toctree-l1">
+  <a class="reference internal" href="introduction.html">
+   Introduction
+  </a>
+ </li>
+ <li class="toctree-l1 current active">
+  <a class="current reference internal" href="#">
+   Python Extensions
+  </a>
+ </li>
+</ul>
+<p aria-level="2" class="caption" role="heading">
+ <span class="caption-text">
+  API
+ </span>
+</p>
+<ul class="nav bd-sidenav">
+ <li class="toctree-l1 has-children">
+  <a class="reference internal" href="../autoapi/index.html">
+   API Reference
+  </a>
+  <input class="toctree-checkbox" id="toctree-checkbox-3" 
name="toctree-checkbox-3" type="checkbox"/>
+  <label for="toctree-checkbox-3">
+   <i class="fas fa-chevron-down">
+   </i>
+  </label>
+  <ul>
+   <li class="toctree-l2 has-children">
+    <a class="reference internal" href="../autoapi/datafusion/index.html">
+     datafusion
+    </a>
+    <input class="toctree-checkbox" id="toctree-checkbox-4" 
name="toctree-checkbox-4" type="checkbox"/>
+    <label for="toctree-checkbox-4">
+     <i class="fas fa-chevron-down">
+     </i>
+    </label>
+    <ul>
+     <li class="toctree-l3">
+      <a class="reference internal" 
href="../autoapi/datafusion/catalog/index.html">
+       datafusion.catalog
+      </a>
+     </li>
+     <li class="toctree-l3">
+      <a class="reference internal" 
href="../autoapi/datafusion/context/index.html">
+       datafusion.context
+      </a>
+     </li>
+     <li class="toctree-l3">
+      <a class="reference internal" 
href="../autoapi/datafusion/dataframe/index.html">
+       datafusion.dataframe
+      </a>
+     </li>
+     <li class="toctree-l3">
+      <a class="reference internal" 
href="../autoapi/datafusion/expr/index.html">
+       datafusion.expr
+      </a>
+     </li>
+     <li class="toctree-l3">
+      <a class="reference internal" 
href="../autoapi/datafusion/functions/index.html">
+       datafusion.functions
+      </a>
+     </li>
+     <li class="toctree-l3 has-children">
+      <a class="reference internal" 
href="../autoapi/datafusion/input/index.html">
+       datafusion.input
+      </a>
+      <input class="toctree-checkbox" id="toctree-checkbox-5" 
name="toctree-checkbox-5" type="checkbox"/>
+      <label for="toctree-checkbox-5">
+       <i class="fas fa-chevron-down">
+       </i>
+      </label>
+      <ul>
+       <li class="toctree-l4">
+        <a class="reference internal" 
href="../autoapi/datafusion/input/base/index.html">
+         datafusion.input.base
+        </a>
+       </li>
+       <li class="toctree-l4">
+        <a class="reference internal" 
href="../autoapi/datafusion/input/location/index.html">
+         datafusion.input.location
+        </a>
+       </li>
+      </ul>
+     </li>
+     <li class="toctree-l3">
+      <a class="reference internal" 
href="../autoapi/datafusion/object_store/index.html">
+       datafusion.object_store
+      </a>
+     </li>
+     <li class="toctree-l3">
+      <a class="reference internal" 
href="../autoapi/datafusion/plan/index.html">
+       datafusion.plan
+      </a>
+     </li>
+     <li class="toctree-l3">
+      <a class="reference internal" 
href="../autoapi/datafusion/record_batch/index.html">
+       datafusion.record_batch
+      </a>
+     </li>
+     <li class="toctree-l3">
+      <a class="reference internal" 
href="../autoapi/datafusion/substrait/index.html">
+       datafusion.substrait
+      </a>
+     </li>
+     <li class="toctree-l3">
+      <a class="reference internal" 
href="../autoapi/datafusion/udf/index.html">
+       datafusion.udf
+      </a>
+     </li>
+    </ul>
+   </li>
+  </ul>
+ </li>
+</ul>
+
+    
+  </div>
+</nav>
+              </div>
+              <div class="sidebar-end-items">
+              </div>
+            </div>
+            
+          
+
+          
+          <div class="d-none d-xl-block col-xl-2 bd-toc">
+            
+              
+              <div class="toc-item">
+                
+<div class="tocsection onthispage pt-5 pb-3">
+    <i class="fas fa-list"></i> On this page
+</div>
+
+<nav id="bd-toc-nav">
+    <ul class="visible nav section-nav flex-column">
+ <li class="toc-h2 nav-item toc-entry">
+  <a class="reference internal nav-link" href="#the-primary-issue">
+   The Primary Issue
+  </a>
+ </li>
+ <li class="toc-h2 nav-item toc-entry">
+  <a class="reference internal nav-link" href="#the-ffi-approach">
+   The FFI Approach
+  </a>
+ </li>
+ <li class="toc-h2 nav-item toc-entry">
+  <a class="reference internal nav-link" href="#inspiration-from-arrow">
+   Inspiration from Arrow
+  </a>
+ </li>
+ <li class="toc-h2 nav-item toc-entry">
+  <a class="reference internal nav-link" href="#implementation-details">
+   Implementation Details
+  </a>
+ </li>
+ <li class="toc-h2 nav-item toc-entry">
+  <a class="reference internal nav-link" href="#alternative-approach">
+   Alternative Approach
+  </a>
+ </li>
+ <li class="toc-h2 nav-item toc-entry">
+  <a class="reference internal nav-link" href="#status-of-work">
+   Status of Work
+  </a>
+ </li>
+</ul>
+
+</nav>
+              </div>
+              
+              <div class="toc-item">
+                
+              </div>
+              
+            
+          </div>
+          
+
+          
+          
+            
+          
+          <main class="col-12 col-md-9 col-xl-7 py-md-5 pl-md-5 pr-md-4 
bd-content" role="main">
+              
+              <div>
+                
+  <section id="python-extensions">
+<h1>Python Extensions<a class="headerlink" href="#python-extensions" 
title="Link to this heading">¶</a></h1>
+<p>The DataFusion in Python project is designed to allow users to extend its 
functionality in a few core
+areas. Ideally many users would like to package their extensions as a Python 
package and easily
+integrate that package with this project. This page serves to describe some of 
the challenges we face
+when doing these integrations and the approach our project uses.</p>
+<section id="the-primary-issue">
+<h2>The Primary Issue<a class="headerlink" href="#the-primary-issue" 
title="Link to this heading">¶</a></h2>
+<p>Suppose you wish to use DataFusion and you have a custom data source that 
can produce tables that
+can then be queried against, similar to how you can register a <a 
class="reference internal" href="../user-guide/io/csv.html#io-csv"><span 
class="std std-ref">CSV</span></a> or
+<a class="reference internal" 
href="../user-guide/io/parquet.html#io-parquet"><span class="std 
std-ref">Parquet</span></a> file. In DataFusion terminology, you likely want to 
implement a
+<a class="reference internal" 
href="../user-guide/io/table_provider.html#io-custom-table-provider"><span 
class="std std-ref">Custom Table Provider</span></a>. In an effort to make your 
data source
+as performant as possible and to utilize the features of DataFusion, you may 
decide to write
+your source in Rust and then expose it through <a class="reference external" 
href="https://pyo3.rs";>PyO3</a> as a Python library.</p>
+<p>At first glance, it may appear the best way to do this is to add the <code 
class="docutils literal notranslate"><span 
class="pre">datafusion-python</span></code>
+crate as a dependency, provide a <code class="docutils literal 
notranslate"><span class="pre">PyTable</span></code>, and then to register it 
with the
+<code class="docutils literal notranslate"><span 
class="pre">SessionContext</span></code>. Unfortunately, this will not work.</p>
+<p>When you produce your code as a Python library and it needs to interact 
with the DataFusion
+library, at the lowest level they communicate through an Application Binary 
Interface (ABI).
+The acronym sounds similar to API (Application Programming Interface), but it 
is distinctly
+different.</p>
+<p>The ABI sets the standard for how these libraries can share data and 
functions between each
+other. One of the key differences between Rust and other programming languages 
is that Rust
+does not have a stable ABI. What this means in practice is that if you compile 
a Rust library
+with one version of the <code class="docutils literal notranslate"><span 
class="pre">rustc</span></code> compiler and I compile another library to 
interface with it
+but I use a different version of the compiler, there is no guarantee the 
interface will be
+the same.</p>
+<p>In practice, this means that a Python library built with <code 
class="docutils literal notranslate"><span 
class="pre">datafusion-python</span></code> as a Rust
+dependency will generally <strong>not</strong> be compatible with the 
DataFusion Python package, even
+if they reference the same version of <code class="docutils literal 
notranslate"><span class="pre">datafusion-python</span></code>. If you attempt 
to do this, it may
+work on your local computer if you have built both packages with the same 
optimizations.
+This can sometimes lead to a false expectation that the code will work, but it 
frequently
+breaks the moment you try to use your package against the released 
packages.</p>
+<p>You can find more information about the Rust ABI in their
+<a class="reference external" 
href="https://doc.rust-lang.org/reference/abi.html";>online 
documentation</a>.</p>
+</section>
+<section id="the-ffi-approach">
+<h2>The FFI Approach<a class="headerlink" href="#the-ffi-approach" title="Link 
to this heading">¶</a></h2>
+<p>Rust supports interacting with other programming languages through it’s 
Foreign Function
+Interface (FFI). The advantage of using the FFI is that it enables you to 
write data structures
+and functions that have a stable ABI. The allows you to use Rust code with C, 
Python, and
+other languages. In fact, the <a class="reference external" 
href="https://pyo3.rs";>PyO3</a> library uses the FFI to share data
+and functions between Python and Rust.</p>
+<p>The approach we are taking in the DataFusion in Python project is to 
incrementally expose
+more portions of the DataFusion project via FFI interfaces. This allows users 
to write Rust
+code that does <strong>not</strong> require the <code class="docutils literal 
notranslate"><span class="pre">datafusion-python</span></code> crate as a 
dependency, expose their
+code in Python via PyO3, and have it interact with the DataFusion Python 
package.</p>
+<p>Early adopters of this approach include <a class="reference external" 
href="https://delta-io.github.io/delta-rs/";>delta-rs</a>
+who has adapted their Table Provider for use in <code class="docutils literal 
notranslate"><span class="pre">`datafusion-python`</span></code> with only a 
few lines
+of code. Also, the DataFusion Python project uses the existing definitions from
+<a class="reference external" 
href="https://arrow.apache.org/docs/format/CStreamInterface.html";>Apache Arrow 
CStream Interface</a>
+to support importing <strong>and</strong> exporting tables. Any Python package 
that supports reading
+the Arrow C Stream interface can work with DataFusion Python out of the box! 
You can read
+more about working with Arrow sources in the <a class="reference internal" 
href="../user-guide/data-sources.html#user-guide-data-sources"><span class="std 
std-ref">Data Sources</span></a>
+page.</p>
+<p>To learn more about the Foreign Function Interface in Rust, the
+<a class="reference external" 
href="https://doc.rust-lang.org/nomicon/ffi.html";>Rustonomicon</a> is a good 
resource.</p>
+</section>
+<section id="inspiration-from-arrow">
+<h2>Inspiration from Arrow<a class="headerlink" href="#inspiration-from-arrow" 
title="Link to this heading">¶</a></h2>
+<p>DataFusion is built upon <a class="reference external" 
href="https://arrow.apache.org/";>Apache Arrow</a>. The canonical Python
+Arrow implementation, <a class="reference external" 
href="https://arrow.apache.org/docs/python/index.html";>pyarrow</a> provides
+an excellent way to share Arrow data between Python projects without 
performing any copy
+operations on the data. They do this by using a well defined set of 
interfaces. You can
+find the details about their stream interface
+<a class="reference external" 
href="https://arrow.apache.org/docs/format/CStreamInterface.html";>here</a>. The
+<a class="reference external" href="https://github.com/apache/arrow-rs";>Rust 
Arrow Implementation</a> also supports these
+<code class="docutils literal notranslate"><span class="pre">C</span></code> 
style definitions via the Foreign Function Interface.</p>
+<p>In addition to using these interfaces to transfer Arrow data between 
libraries, <code class="docutils literal notranslate"><span 
class="pre">pyarrow</span></code>
+goes one step further to make sharing the interfaces easier in Python. They do 
this
+by exposing PyCapsules that contain the expected functionality.</p>
+<p>You can learn more about PyCapsules from the official
+<a class="reference external" 
href="https://docs.python.org/3/c-api/capsule.html";>Python online 
documentation</a>. PyCapsules
+have excellent support in PyO3 already. The
+<a class="reference external" 
href="https://pyo3.rs/main/doc/pyo3/types/struct.pycapsule";>PyO3 online 
documentation</a> is a good source
+for more details on using PyCapsules in Rust.</p>
+<p>Two lessons we leverage from the Arrow project in DataFusion Python are:</p>
+<ul class="simple">
+<li><p>We reuse the existing Arrow FFI functionality wherever 
possible.</p></li>
+<li><p>We expose PyCapsules that contain a FFI stable struct.</p></li>
+</ul>
+</section>
+<section id="implementation-details">
+<h2>Implementation Details<a class="headerlink" href="#implementation-details" 
title="Link to this heading">¶</a></h2>
+<p>The bulk of the code necessary to perform our FFI operations is in the 
upstream
+<a class="reference external" 
href="https://datafusion.apache.org/";>DataFusion</a> core repository. You can 
review the code and
+documentation in the <a class="reference external" 
href="https://crates.io/crates/datafusion-ffi";>datafusion-ffi</a> crate.</p>
+<p>Our FFI implementation is narrowly focused at sharing data and functions 
with Rust backed
+libraries. This allows us to use the <a class="reference external" 
href="https://crates.io/crates/abi_stable";>abi_stable crate</a>.
+This is an excellent crate that allows for easy conversion between Rust native 
types
+and FFI-safe alternatives. For example, if you needed to pass a <code 
class="docutils literal notranslate"><span 
class="pre">Vec&lt;String&gt;</span></code> via FFI,
+you can simply convert it to a <code class="docutils literal 
notranslate"><span class="pre">RVec&lt;RString&gt;</span></code> in an 
intuitive manner. It also supports
+features like <code class="docutils literal notranslate"><span 
class="pre">RResult</span></code> and <code class="docutils literal 
notranslate"><span class="pre">ROption</span></code> that do not have an 
obvious translation to a
+C equivalent.</p>
+<p>The <a class="reference external" 
href="https://crates.io/crates/datafusion-ffi";>datafusion-ffi</a> crate has 
been designed to make it easy to convert from DataFusion
+traits into their FFI counterparts. For example, if you have defined a custom
+<a class="reference external" 
href="https://docs.rs/datafusion/45.0.0/datafusion/catalog/trait.TableProvider.html";>TableProvider</a>
+and you want to create a sharable FFI counterpart, you could write:</p>
+<div class="highlight-rust notranslate"><div 
class="highlight"><pre><span></span><span class="kd">let</span><span class="w"> 
</span><span class="n">my_provider</span><span class="w"> </span><span 
class="o">=</span><span class="w"> </span><span 
class="n">MyTableProvider</span><span class="p">::</span><span 
class="n">default</span><span class="p">();</span>
+<span class="kd">let</span><span class="w"> </span><span 
class="n">ffi_provider</span><span class="w"> </span><span 
class="o">=</span><span class="w"> </span><span 
class="n">FFI_TableProvider</span><span class="p">::</span><span 
class="n">new</span><span class="p">(</span><span class="n">Arc</span><span 
class="p">::</span><span class="n">new</span><span class="p">(</span><span 
class="n">my_provider</span><span class="p">),</span><span class="w"> 
</span><span class="kc">false</span><span  [...]
+</pre></div>
+</div>
+<p>If you were interfacing with a library that provided the above <code 
class="docutils literal notranslate"><span 
class="pre">FFI_TableProvider</span></code> and
+you needed to turn it back into an <code class="docutils literal 
notranslate"><span class="pre">TableProvider</span></code>, you can turn it 
into a
+<code class="docutils literal notranslate"><span 
class="pre">ForeignTableProvider</span></code> with implements the <code 
class="docutils literal notranslate"><span 
class="pre">TableProvider</span></code> trait.</p>
+<div class="highlight-rust notranslate"><div 
class="highlight"><pre><span></span><span class="kd">let</span><span class="w"> 
</span><span class="n">foreign_provider</span><span class="p">:</span><span 
class="w"> </span><span class="nc">ForeignTableProvider</span><span class="w"> 
</span><span class="o">=</span><span class="w"> </span><span 
class="n">ffi_provider</span><span class="p">.</span><span 
class="n">into</span><span class="p">();</span>
+</pre></div>
+</div>
+<p>If you review the code in <a class="reference external" 
href="https://crates.io/crates/datafusion-ffi";>datafusion-ffi</a> you will find 
that each of the traits we share
+across the boundary has two portions, one with a <code class="docutils literal 
notranslate"><span class="pre">FFI_</span></code> prefix and one with a <code 
class="docutils literal notranslate"><span class="pre">Foreign</span></code>
+prefix. This is used to distinguish which side of the FFI boundary that struct 
is
+designed to be used on. The structures with the <code class="docutils literal 
notranslate"><span class="pre">FFI_</span></code> prefix are to be used on the
+<strong>provider</strong> of the structure. In the example we’re showing, this 
means the code that has
+written the underlying <code class="docutils literal notranslate"><span 
class="pre">TableProvider</span></code> implementation to access your custom 
data source.
+The structures with the <code class="docutils literal notranslate"><span 
class="pre">Foreign</span></code> prefix are to be used by the receiver. In 
this case,
+it is the <code class="docutils literal notranslate"><span 
class="pre">datafusion-python</span></code> library.</p>
+<p>In order to share these FFI structures, we need to wrap them in some kind 
of Python object
+that can be used to interface from one package to another. As described in the 
above
+section on our inspiration from Arrow, we use <code class="docutils literal 
notranslate"><span class="pre">PyCapsule</span></code>. We can create a <code 
class="docutils literal notranslate"><span class="pre">PyCapsule</span></code>
+for our provider thusly:</p>
+<div class="highlight-rust notranslate"><div 
class="highlight"><pre><span></span><span class="kd">let</span><span class="w"> 
</span><span class="n">name</span><span class="w"> </span><span 
class="o">=</span><span class="w"> </span><span class="n">CString</span><span 
class="p">::</span><span class="n">new</span><span class="p">(</span><span 
class="s">&quot;datafusion_table_provider&quot;</span><span 
class="p">)</span><span class="o">?</span><span class="p">;</span>
+<span class="kd">let</span><span class="w"> </span><span 
class="n">my_capsule</span><span class="w"> </span><span 
class="o">=</span><span class="w"> </span><span class="n">PyCapsule</span><span 
class="p">::</span><span class="n">new_bound</span><span 
class="p">(</span><span class="n">py</span><span class="p">,</span><span 
class="w"> </span><span class="n">provider</span><span class="p">,</span><span 
class="w"> </span><span class="nb">Some</span><span class="p">(</span><span 
class="n">nam [...]
+</pre></div>
+</div>
+<p>On the receiving side, turn this pycapsule object into the <code 
class="docutils literal notranslate"><span 
class="pre">FFI_TableProvider</span></code>, which
+can then be turned into a <code class="docutils literal notranslate"><span 
class="pre">ForeignTableProvider</span></code> the associated code is:</p>
+<div class="highlight-rust notranslate"><div 
class="highlight"><pre><span></span><span class="kd">let</span><span class="w"> 
</span><span class="n">capsule</span><span class="w"> </span><span 
class="o">=</span><span class="w"> </span><span class="n">capsule</span><span 
class="p">.</span><span class="n">downcast</span><span class="p">::</span><span 
class="o">&lt;</span><span class="n">PyCapsule</span><span 
class="o">&gt;</span><span class="p">()</span><span class="o">?</span><span 
class=" [...]
+<span class="kd">let</span><span class="w"> </span><span 
class="n">provider</span><span class="w"> </span><span class="o">=</span><span 
class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span 
class="p">{</span><span class="w"> </span><span class="n">capsule</span><span 
class="p">.</span><span class="n">reference</span><span 
class="p">::</span><span class="o">&lt;</span><span 
class="n">FFI_TableProvider</span><span class="o">&gt;</span><span 
class="p">()</span><span c [...]
+</pre></div>
+</div>
+<p>By convention the <code class="docutils literal notranslate"><span 
class="pre">datafusion-python</span></code> library expects a Python object 
that has a
+<code class="docutils literal notranslate"><span 
class="pre">TableProvider</span></code> PyCapsule to have this capsule 
accessible by calling a function named
+<code class="docutils literal notranslate"><span 
class="pre">__datafusion_table_provider__</span></code>. You can see a complete 
working example of how to
+share a <code class="docutils literal notranslate"><span 
class="pre">TableProvider</span></code> from one python library to DataFusion 
Python in the
+<a class="reference external" 
href="https://github.com/apache/datafusion-python/tree/main/examples/ffi-table-provider";>repository
 examples folder</a>.</p>
+<p>This section has been written using <code class="docutils literal 
notranslate"><span class="pre">TableProvider</span></code> as an example. It is 
the first
+extension that has been written using this approach and the most thoroughly 
implemented.
+As we continue to expose more of the DataFusion features, we intend to follow 
this same
+design pattern.</p>
+</section>
+<section id="alternative-approach">
+<h2>Alternative Approach<a class="headerlink" href="#alternative-approach" 
title="Link to this heading">¶</a></h2>
+<p>Suppose you needed to expose some other features of DataFusion and you 
could not wait
+for the upstream repository to implement the FFI approach we describe. In this 
case
+you decide to create your dependency on the <code class="docutils literal 
notranslate"><span class="pre">datafusion-python</span></code> crate 
instead.</p>
+<p>As we discussed, this is not guaranteed to work across different compiler 
versions and
+optimization levels. If you wish to go down this route, there are two 
approaches we
+have identified you can use.</p>
+<ol class="arabic simple">
+<li><p>Re-export all of <code class="docutils literal notranslate"><span 
class="pre">datafusion-python</span></code> yourself with your extensions built 
in.</p></li>
+<li><p>Carefully synchonize your software releases with the <code 
class="docutils literal notranslate"><span 
class="pre">datafusion-python</span></code> CI build
+system so that your libraries use the exact same compiler, features, and
+optimization level.</p></li>
+</ol>
+<p>We currently do not recommend either of these approaches as they are 
difficult to
+maintain over a long period. Additionally, they require a tight version 
coupling
+between libraries.</p>
+</section>
+<section id="status-of-work">
+<h2>Status of Work<a class="headerlink" href="#status-of-work" title="Link to 
this heading">¶</a></h2>
+<p>At the time of this writing, the FFI features are under active development. 
To see
+the latest status, we recommend reviewing the code in the <a class="reference 
external" href="https://crates.io/crates/datafusion-ffi";>datafusion-ffi</a> 
crate.</p>
+</section>
+</section>
+
+
+              </div>
+              
+              
+              <!-- Previous / next buttons -->
+<div class='prev-next-area'>
+    <a class='left-prev' id="prev-link" href="introduction.html" 
title="previous page">
+        <i class="fas fa-angle-left"></i>
+        <div class="prev-next-info">
+            <p class="prev-next-subtitle">previous</p>
+            <p class="prev-next-title">Introduction</p>
+        </div>
+    </a>
+    <a class='right-next' id="next-link" href="../autoapi/index.html" 
title="next page">
+    <div class="prev-next-info">
+        <p class="prev-next-subtitle">next</p>
+        <p class="prev-next-title">API Reference</p>
+    </div>
+    <i class="fas fa-angle-right"></i>
+    </a>
+</div>
+              
+          </main>
+          
+
+      </div>
+    </div>
+  
+    <script 
src="../_static/scripts/pydata-sphinx-theme.js?digest=1999514e3f237ded88cf"></script>
+  
+<!-- Based on pydata_sphinx_theme/footer.html -->
+<footer class="footer mt-5 mt-md-0">
+  <div class="container">
+    
+    <div class="footer-item">
+      <p class="copyright">
+    &copy; Copyright 2019-2024, Apache Software Foundation.<br>
+</p>
+    </div>
+    
+    <div class="footer-item">
+      <p class="sphinx-version">
+Created using <a href="http://sphinx-doc.org/";>Sphinx</a> 8.1.3.<br>
+</p>
+    </div>
+    
+    <div class="footer-item">
+      <p>Apache Arrow DataFusion, Arrow DataFusion, Apache, the Apache feather 
logo, and the Apache Arrow DataFusion project logo</p>
+      <p>are either registered trademarks or trademarks of The Apache Software 
Foundation in the United States and other countries.</p>
+    </div>
+  </div>
+</footer>
+
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/contributor-guide/introduction.html 
b/contributor-guide/introduction.html
index 1ff78cef..883463d9 100644
--- a/contributor-guide/introduction.html
+++ b/contributor-guide/introduction.html
@@ -34,7 +34,7 @@
     <script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
     <link rel="index" title="Index" href="../genindex.html" />
     <link rel="search" title="Search" href="../search.html" />
-    <link rel="next" title="API Reference" href="../autoapi/index.html" />
+    <link rel="next" title="Python Extensions" href="ffi.html" />
     <link rel="prev" title="SQL" href="../user-guide/sql.html" />
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <meta name="docsearch:language" content="en">
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
@@ -528,10 +533,10 @@ to your settings. You can find the appropriate rust flags 
by looking in the
             <p class="prev-next-title">SQL</p>
         </div>
     </a>
-    <a class='right-next' id="next-link" href="../autoapi/index.html" 
title="next page">
+    <a class='right-next' id="next-link" href="ffi.html" title="next page">
     <div class="prev-next-info">
         <p class="prev-next-subtitle">next</p>
-        <p class="prev-next-title">API Reference</p>
+        <p class="prev-next-title">Python Extensions</p>
     </div>
     <i class="fas fa-angle-right"></i>
     </a>
diff --git a/genindex.html b/genindex.html
index c65d715c..3f626d6e 100644
--- a/genindex.html
+++ b/genindex.html
@@ -230,6 +230,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/index.html b/index.html
index 57890523..9a935a6c 100644
--- a/index.html
+++ b/index.html
@@ -232,6 +232,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/objects.inv b/objects.inv
index a9e2b001..7d58068e 100644
Binary files a/objects.inv and b/objects.inv differ
diff --git a/py-modindex.html b/py-modindex.html
index 23fde1c9..48b97dc1 100644
--- a/py-modindex.html
+++ b/py-modindex.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/search.html b/search.html
index acc066c4..b7bc90c9 100644
--- a/search.html
+++ b/search.html
@@ -237,6 +237,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/searchindex.js b/searchindex.js
index 55bc5567..a04d6be5 100644
--- a/searchindex.js
+++ b/searchindex.js
@@ -1 +1 @@
-Search.setIndex({"alltitles": {"API Reference": [[14, null]], "Aggregate 
Functions": [[18, "aggregate-functions"], [25, "aggregate-functions"], [26, 
"aggregate-functions"]], "Aggregation": [[18, null]], "Arrays": [[20, 
"arrays"]], "Arrow": [[30, null]], "Attributes": [[3, "attributes"], [5, 
"attributes"], [9, "attributes"], [13, "attributes"]], "Available Functions": 
[[26, "available-functions"]], "Avro": [[31, null]], "Basic Operations": [[19, 
null]], "Boolean": [[20, "boolean"]], "CSV" [...]
\ No newline at end of file
+Search.setIndex({"alltitles": {"API Reference": [[14, null]], "Aggregate 
Functions": [[19, "aggregate-functions"], [26, "aggregate-functions"], [27, 
"aggregate-functions"]], "Aggregation": [[19, null]], "Alternative Approach": 
[[15, "alternative-approach"]], "Arrays": [[21, "arrays"]], "Arrow": [[31, 
null]], "Attributes": [[3, "attributes"], [5, "attributes"], [9, "attributes"], 
[13, "attributes"]], "Available Functions": [[27, "available-functions"]], 
"Avro": [[32, null]], "Basic Operat [...]
\ No newline at end of file
diff --git a/user-guide/basics.html b/user-guide/basics.html
index b7d61220..7e4b40e8 100644
--- a/user-guide/basics.html
+++ b/user-guide/basics.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/common-operations/aggregations.html 
b/user-guide/common-operations/aggregations.html
index 7f0221d5..5cde9abc 100644
--- a/user-guide/common-operations/aggregations.html
+++ b/user-guide/common-operations/aggregations.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
@@ -488,20 +493,20 @@ For grouping the <code class="code docutils literal 
notranslate"><span class="pr
    <span class="o">....</span><span class="p">:</span> 
 <span class="n">Out</span><span class="p">[</span><span 
class="mi">10</span><span class="p">]:</span> 
 <span class="n">DataFrame</span><span class="p">()</span>
-<span 
class="o">+----------+--------+-----------+--------------------+-----------+</span>
-<span class="o">|</span> <span class="n">Type</span> <span class="mi">1</span> 
  <span class="o">|</span> <span class="n">Type</span> <span 
class="mi">2</span> <span class="o">|</span> <span class="n">Max</span> <span 
class="n">Speed</span> <span class="o">|</span> <span class="n">Avg</span> 
<span class="n">Speed</span>          <span class="o">|</span> <span 
class="n">Min</span> <span class="n">Speed</span> <span class="o">|</span>
-<span 
class="o">+----------+--------+-----------+--------------------+-----------+</span>
-<span class="o">|</span> <span class="n">Fire</span>     <span 
class="o">|</span>        <span class="o">|</span> <span class="mi">105</span>  
     <span class="o">|</span> <span class="mf">81.8</span>               <span 
class="o">|</span> <span class="mi">60</span>        <span class="o">|</span>
-<span class="o">|</span> <span class="n">Water</span>    <span 
class="o">|</span>        <span class="o">|</span> <span class="mi">90</span>   
     <span class="o">|</span> <span class="mf">68.05263157894737</span>  <span 
class="o">|</span> <span class="mi">40</span>        <span class="o">|</span>
-<span class="o">|</span> <span class="n">Ground</span>   <span 
class="o">|</span>        <span class="o">|</span> <span class="mi">120</span>  
     <span class="o">|</span> <span class="mf">66.66666666666667</span>  <span 
class="o">|</span> <span class="mi">35</span>        <span class="o">|</span>
-<span class="o">|</span> <span class="n">Normal</span>   <span 
class="o">|</span> <span class="n">Fairy</span>  <span class="o">|</span> <span 
class="mi">45</span>        <span class="o">|</span> <span 
class="mf">32.5</span>               <span class="o">|</span> <span 
class="mi">20</span>        <span class="o">|</span>
-<span class="o">|</span> <span class="n">Fighting</span> <span 
class="o">|</span>        <span class="o">|</span> <span class="mi">95</span>   
     <span class="o">|</span> <span class="mf">66.14285714285714</span>  <span 
class="o">|</span> <span class="mi">35</span>        <span class="o">|</span>
-<span class="o">|</span> <span class="n">Psychic</span>  <span 
class="o">|</span>        <span class="o">|</span> <span class="mi">150</span>  
     <span class="o">|</span> <span class="mf">100.57142857142857</span> <span 
class="o">|</span> <span class="mi">42</span>        <span class="o">|</span>
-<span class="o">|</span> <span class="n">Grass</span>    <span 
class="o">|</span>        <span class="o">|</span> <span class="mi">60</span>   
     <span class="o">|</span> <span class="mf">60.0</span>               <span 
class="o">|</span> <span class="mi">60</span>        <span class="o">|</span>
-<span class="o">|</span> <span class="n">Dragon</span>   <span 
class="o">|</span>        <span class="o">|</span> <span class="mi">70</span>   
     <span class="o">|</span> <span class="mf">60.0</span>               <span 
class="o">|</span> <span class="mi">50</span>        <span class="o">|</span>
-<span class="o">|</span> <span class="n">Grass</span>    <span 
class="o">|</span> <span class="n">Poison</span> <span class="o">|</span> <span 
class="mi">80</span>        <span class="o">|</span> <span 
class="mf">55.0</span>               <span class="o">|</span> <span 
class="mi">30</span>        <span class="o">|</span>
-<span class="o">|</span> <span class="n">Bug</span>      <span 
class="o">|</span> <span class="n">Flying</span> <span class="o">|</span> <span 
class="mi">105</span>       <span class="o">|</span> <span 
class="mf">93.33333333333333</span>  <span class="o">|</span> <span 
class="mi">70</span>        <span class="o">|</span>
-<span 
class="o">+----------+--------+-----------+--------------------+-----------+</span>
+<span 
class="o">+----------+--------+-----------+-------------------+-----------+</span>
+<span class="o">|</span> <span class="n">Type</span> <span class="mi">1</span> 
  <span class="o">|</span> <span class="n">Type</span> <span 
class="mi">2</span> <span class="o">|</span> <span class="n">Max</span> <span 
class="n">Speed</span> <span class="o">|</span> <span class="n">Avg</span> 
<span class="n">Speed</span>         <span class="o">|</span> <span 
class="n">Min</span> <span class="n">Speed</span> <span class="o">|</span>
+<span 
class="o">+----------+--------+-----------+-------------------+-----------+</span>
+<span class="o">|</span> <span class="n">Grass</span>    <span 
class="o">|</span> <span class="n">Poison</span> <span class="o">|</span> <span 
class="mi">80</span>        <span class="o">|</span> <span 
class="mf">55.0</span>              <span class="o">|</span> <span 
class="mi">30</span>        <span class="o">|</span>
+<span class="o">|</span> <span class="n">Bug</span>      <span 
class="o">|</span> <span class="n">Flying</span> <span class="o">|</span> <span 
class="mi">105</span>       <span class="o">|</span> <span 
class="mf">93.33333333333333</span> <span class="o">|</span> <span 
class="mi">70</span>        <span class="o">|</span>
+<span class="o">|</span> <span class="n">Poison</span>   <span 
class="o">|</span> <span class="n">Ground</span> <span class="o">|</span> <span 
class="mi">85</span>        <span class="o">|</span> <span 
class="mf">80.5</span>              <span class="o">|</span> <span 
class="mi">76</span>        <span class="o">|</span>
+<span class="o">|</span> <span class="n">Poison</span>   <span 
class="o">|</span> <span class="n">Flying</span> <span class="o">|</span> <span 
class="mi">90</span>        <span class="o">|</span> <span 
class="mf">72.5</span>              <span class="o">|</span> <span 
class="mi">55</span>        <span class="o">|</span>
+<span class="o">|</span> <span class="n">Bug</span>      <span 
class="o">|</span> <span class="n">Grass</span>  <span class="o">|</span> <span 
class="mi">30</span>        <span class="o">|</span> <span 
class="mf">27.5</span>              <span class="o">|</span> <span 
class="mi">25</span>        <span class="o">|</span>
+<span class="o">|</span> <span class="n">Water</span>    <span 
class="o">|</span> <span class="n">Poison</span> <span class="o">|</span> <span 
class="mi">100</span>       <span class="o">|</span> <span 
class="mf">85.0</span>              <span class="o">|</span> <span 
class="mi">70</span>        <span class="o">|</span>
+<span class="o">|</span> <span class="n">Electric</span> <span 
class="o">|</span> <span class="n">Steel</span>  <span class="o">|</span> <span 
class="mi">70</span>        <span class="o">|</span> <span 
class="mf">57.5</span>              <span class="o">|</span> <span 
class="mi">45</span>        <span class="o">|</span>
+<span class="o">|</span> <span class="n">Ghost</span>    <span 
class="o">|</span> <span class="n">Poison</span> <span class="o">|</span> <span 
class="mi">130</span>       <span class="o">|</span> <span 
class="mf">103.75</span>            <span class="o">|</span> <span 
class="mi">80</span>        <span class="o">|</span>
+<span class="o">|</span> <span class="n">Psychic</span>  <span 
class="o">|</span> <span class="n">Fairy</span>  <span class="o">|</span> <span 
class="mi">90</span>        <span class="o">|</span> <span 
class="mf">90.0</span>              <span class="o">|</span> <span 
class="mi">90</span>        <span class="o">|</span>
+<span class="o">|</span> <span class="n">Electric</span> <span 
class="o">|</span> <span class="n">Flying</span> <span class="o">|</span> <span 
class="mi">100</span>       <span class="o">|</span> <span 
class="mf">100.0</span>             <span class="o">|</span> <span 
class="mi">100</span>       <span class="o">|</span>
+<span 
class="o">+----------+--------+-----------+-------------------+-----------+</span>
 </pre></div>
 </div>
 <section id="setting-parameters">
@@ -559,15 +564,15 @@ Pokemon set. Since there will be many entries of <code 
class="docutils literal n
 <span 
class="o">+----------+--------------------------------------------------+</span>
 <span class="o">|</span> <span class="n">Type</span> <span class="mi">1</span> 
  <span class="o">|</span> <span class="n">Type</span> <span 
class="mi">2</span> <span class="n">List</span>                                 
     <span class="o">|</span>
 <span 
class="o">+----------+--------------------------------------------------+</span>
-<span class="o">|</span> <span class="n">Normal</span>   <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="n">Fairy</span><span class="p">,</span> <span 
class="p">]</span>                                <span class="o">|</span>
+<span class="o">|</span> <span class="n">Normal</span>   <span 
class="o">|</span> <span class="p">[,</span> <span class="n">Fairy</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">]</span>        
                        <span class="o">|</span>
 <span class="o">|</span> <span class="n">Ice</span>      <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="n">Psychic</span><span class="p">]</span>       
                         <span class="o">|</span>
-<span class="o">|</span> <span class="n">Bug</span>      <span 
class="o">|</span> <span class="p">[</span><span class="n">Grass</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">,</span> <span 
class="p">,</span> <span class="n">Poison</span><span class="p">]</span>        
                <span class="o">|</span>
-<span class="o">|</span> <span class="n">Poison</span>   <span 
class="o">|</span> <span class="p">[,</span> <span class="n">Flying</span><span 
class="p">,</span> <span class="n">Ground</span><span class="p">]</span>        
                       <span class="o">|</span>
+<span class="o">|</span> <span class="n">Bug</span>      <span 
class="o">|</span> <span class="p">[,</span> <span class="n">Poison</span><span 
class="p">,</span> <span class="n">Grass</span><span class="p">,</span> <span 
class="n">Flying</span><span class="p">]</span>                        <span 
class="o">|</span>
+<span class="o">|</span> <span class="n">Poison</span>   <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="p">,</span> <span class="n">Ground</span><span 
class="p">]</span>                               <span class="o">|</span>
 <span class="o">|</span> <span class="n">Electric</span> <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="p">,</span> <span class="n">Steel</span><span 
class="p">]</span>                                <span class="o">|</span>
 <span class="o">|</span> <span class="n">Fairy</span>    <span 
class="o">|</span> <span class="p">[]</span>                                    
           <span class="o">|</span>
-<span class="o">|</span> <span class="n">Grass</span>    <span 
class="o">|</span> <span class="p">[</span><span class="n">Poison</span><span 
class="p">,</span> <span class="n">Psychic</span><span class="p">,</span> <span 
class="p">]</span>                              <span class="o">|</span>
-<span class="o">|</span> <span class="n">Fire</span>     <span 
class="o">|</span> <span class="p">[,</span> <span class="n">Flying</span><span 
class="p">,</span> <span class="n">Dragon</span><span class="p">]</span>        
                       <span class="o">|</span>
-<span class="o">|</span> <span class="n">Water</span>    <span 
class="o">|</span> <span class="p">[</span><span class="n">Dark</span><span 
class="p">,</span> <span class="p">,</span> <span class="n">Ice</span><span 
class="p">,</span> <span class="n">Poison</span><span class="p">,</span> <span 
class="n">Fighting</span><span class="p">,</span> <span 
class="n">Psychic</span><span class="p">,</span> <span 
class="n">Flying</span><span class="p">]</span> <span class="o">|</span>
+<span class="o">|</span> <span class="n">Grass</span>    <span 
class="o">|</span> <span class="p">[</span><span class="n">Psychic</span><span 
class="p">,</span> <span class="p">,</span> <span class="n">Poison</span><span 
class="p">]</span>                              <span class="o">|</span>
+<span class="o">|</span> <span class="n">Fire</span>     <span 
class="o">|</span> <span class="p">[,</span> <span class="n">Dragon</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">]</span>        
                       <span class="o">|</span>
+<span class="o">|</span> <span class="n">Water</span>    <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="n">Psychic</span><span class="p">,</span> <span 
class="n">Poison</span><span class="p">,</span> <span class="p">,</span> <span 
class="n">Ice</span><span class="p">,</span> <span class="n">Dark</span><span 
class="p">,</span> <span class="n">Fighting</span><span class="p">]</span> 
<span class="o">|</span>
 <span class="o">|</span> <span class="n">Ground</span>   <span 
class="o">|</span> <span class="p">[,</span> <span class="n">Rock</span><span 
class="p">]</span>                                         <span 
class="o">|</span>
 <span 
class="o">+----------+--------------------------------------------------+</span>
 </pre></div>
@@ -582,15 +587,15 @@ entries entirely removed. The second is we can use the 
<code class="docutils lit
 <span 
class="o">+----------+------------------------------------------------+</span>
 <span class="o">|</span> <span class="n">Type</span> <span class="mi">1</span> 
  <span class="o">|</span> <span class="n">Type</span> <span 
class="mi">2</span> <span class="n">List</span>                                 
   <span class="o">|</span>
 <span 
class="o">+----------+------------------------------------------------+</span>
-<span class="o">|</span> <span class="n">Bug</span>      <span 
class="o">|</span> <span class="p">[</span><span class="n">Poison</span><span 
class="p">,</span> <span class="n">Grass</span><span class="p">,</span> <span 
class="n">Flying</span><span class="p">]</span>                        <span 
class="o">|</span>
+<span class="o">|</span> <span class="n">Normal</span>   <span 
class="o">|</span> <span class="p">[</span><span class="n">Fairy</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">]</span>        
                        <span class="o">|</span>
+<span class="o">|</span> <span class="n">Ice</span>      <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="n">Psychic</span><span class="p">]</span>       
                       <span class="o">|</span>
+<span class="o">|</span> <span class="n">Bug</span>      <span 
class="o">|</span> <span class="p">[</span><span class="n">Poison</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">,</span> <span 
class="n">Grass</span><span class="p">]</span>                        <span 
class="o">|</span>
 <span class="o">|</span> <span class="n">Poison</span>   <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="n">Ground</span><span class="p">]</span>        
                       <span class="o">|</span>
 <span class="o">|</span> <span class="n">Electric</span> <span 
class="o">|</span> <span class="p">[</span><span class="n">Steel</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">]</span>        
                        <span class="o">|</span>
-<span class="o">|</span> <span class="n">Normal</span>   <span 
class="o">|</span> <span class="p">[</span><span class="n">Fairy</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">]</span>        
                        <span class="o">|</span>
-<span class="o">|</span> <span class="n">Ice</span>      <span 
class="o">|</span> <span class="p">[</span><span class="n">Psychic</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">]</span>        
                      <span class="o">|</span>
 <span class="o">|</span> <span class="n">Grass</span>    <span 
class="o">|</span> <span class="p">[</span><span class="n">Psychic</span><span 
class="p">,</span> <span class="n">Poison</span><span class="p">]</span>        
                      <span class="o">|</span>
-<span class="o">|</span> <span class="n">Fire</span>     <span 
class="o">|</span> <span class="p">[</span><span class="n">Dragon</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">]</span>        
                       <span class="o">|</span>
-<span class="o">|</span> <span class="n">Water</span>    <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="n">Ice</span><span class="p">,</span> <span 
class="n">Psychic</span><span class="p">,</span> <span 
class="n">Fighting</span><span class="p">,</span> <span 
class="n">Dark</span><span class="p">,</span> <span 
class="n">Poison</span><span class="p">]</span> <span class="o">|</span>
-<span class="o">|</span> <span class="n">Rock</span>     <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="n">Ground</span><span class="p">,</span> <span 
class="n">Water</span><span class="p">]</span>                        <span 
class="o">|</span>
+<span class="o">|</span> <span class="n">Fire</span>     <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="n">Dragon</span><span class="p">]</span>        
                       <span class="o">|</span>
+<span class="o">|</span> <span class="n">Water</span>    <span 
class="o">|</span> <span class="p">[</span><span class="n">Fighting</span><span 
class="p">,</span> <span class="n">Poison</span><span class="p">,</span> <span 
class="n">Ice</span><span class="p">,</span> <span class="n">Dark</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">,</span> <span 
class="n">Psychic</span><span class="p">]</span> <span class="o">|</span>
+<span class="o">|</span> <span class="n">Rock</span>     <span 
class="o">|</span> <span class="p">[</span><span class="n">Water</span><span 
class="p">,</span> <span class="n">Ground</span><span class="p">,</span> <span 
class="n">Flying</span><span class="p">]</span>                        <span 
class="o">|</span>
 <span class="o">|</span> <span class="n">Ghost</span>    <span 
class="o">|</span> <span class="p">[</span><span class="n">Poison</span><span 
class="p">]</span>                                       <span 
class="o">|</span>
 <span 
class="o">+----------+------------------------------------------------+</span>
 
@@ -600,15 +605,15 @@ entries entirely removed. The second is we can use the 
<code class="docutils lit
 <span 
class="o">+----------+------------------------------------------------+</span>
 <span class="o">|</span> <span class="n">Type</span> <span class="mi">1</span> 
  <span class="o">|</span> <span class="n">Type</span> <span 
class="mi">2</span> <span class="n">List</span>                                 
   <span class="o">|</span>
 <span 
class="o">+----------+------------------------------------------------+</span>
-<span class="o">|</span> <span class="n">Normal</span>   <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="n">Fairy</span><span class="p">]</span>         
                       <span class="o">|</span>
-<span class="o">|</span> <span class="n">Ice</span>      <span 
class="o">|</span> <span class="p">[</span><span class="n">Psychic</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">]</span>        
                      <span class="o">|</span>
-<span class="o">|</span> <span class="n">Bug</span>      <span 
class="o">|</span> <span class="p">[</span><span class="n">Grass</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">,</span> <span 
class="n">Poison</span><span class="p">]</span>                        <span 
class="o">|</span>
-<span class="o">|</span> <span class="n">Poison</span>   <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="n">Ground</span><span class="p">]</span>        
                       <span class="o">|</span>
+<span class="o">|</span> <span class="n">Normal</span>   <span 
class="o">|</span> <span class="p">[</span><span class="n">Fairy</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">]</span>        
                        <span class="o">|</span>
+<span class="o">|</span> <span class="n">Ice</span>      <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="n">Psychic</span><span class="p">]</span>       
                       <span class="o">|</span>
+<span class="o">|</span> <span class="n">Bug</span>      <span 
class="o">|</span> <span class="p">[</span><span class="n">Flying</span><span 
class="p">,</span> <span class="n">Poison</span><span class="p">,</span> <span 
class="n">Grass</span><span class="p">]</span>                        <span 
class="o">|</span>
+<span class="o">|</span> <span class="n">Poison</span>   <span 
class="o">|</span> <span class="p">[</span><span class="n">Ground</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">]</span>        
                       <span class="o">|</span>
 <span class="o">|</span> <span class="n">Electric</span> <span 
class="o">|</span> <span class="p">[</span><span class="n">Steel</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">]</span>        
                        <span class="o">|</span>
 <span class="o">|</span> <span class="n">Fairy</span>    <span 
class="o">|</span>                                                <span 
class="o">|</span>
 <span class="o">|</span> <span class="n">Grass</span>    <span 
class="o">|</span> <span class="p">[</span><span class="n">Poison</span><span 
class="p">,</span> <span class="n">Psychic</span><span class="p">]</span>       
                       <span class="o">|</span>
 <span class="o">|</span> <span class="n">Fire</span>     <span 
class="o">|</span> <span class="p">[</span><span class="n">Dragon</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">]</span>        
                       <span class="o">|</span>
-<span class="o">|</span> <span class="n">Water</span>    <span 
class="o">|</span> <span class="p">[</span><span class="n">Ice</span><span 
class="p">,</span> <span class="n">Poison</span><span class="p">,</span> <span 
class="n">Fighting</span><span class="p">,</span> <span 
class="n">Dark</span><span class="p">,</span> <span 
class="n">Flying</span><span class="p">,</span> <span 
class="n">Psychic</span><span class="p">]</span> <span class="o">|</span>
+<span class="o">|</span> <span class="n">Water</span>    <span 
class="o">|</span> <span class="p">[</span><span class="n">Fighting</span><span 
class="p">,</span> <span class="n">Flying</span><span class="p">,</span> <span 
class="n">Psychic</span><span class="p">,</span> <span 
class="n">Ice</span><span class="p">,</span> <span class="n">Dark</span><span 
class="p">,</span> <span class="n">Poison</span><span class="p">]</span> <span 
class="o">|</span>
 <span class="o">|</span> <span class="n">Ground</span>   <span 
class="o">|</span> <span class="p">[</span><span class="n">Rock</span><span 
class="p">]</span>                                         <span 
class="o">|</span>
 <span 
class="o">+----------+------------------------------------------------+</span>
 </pre></div>
diff --git a/user-guide/common-operations/basic-info.html 
b/user-guide/common-operations/basic-info.html
index cba290a0..0d17396f 100644
--- a/user-guide/common-operations/basic-info.html
+++ b/user-guide/common-operations/basic-info.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
@@ -399,11 +404,11 @@
 <span class="o">+-----+---------+--------+--------+</span>
 <span class="o">|</span> <span class="n">nrs</span> <span class="o">|</span> 
<span class="n">names</span>   <span class="o">|</span> <span 
class="n">random</span> <span class="o">|</span> <span class="n">groups</span> 
<span class="o">|</span>
 <span class="o">+-----+---------+--------+--------+</span>
-<span class="o">|</span> <span class="mi">1</span>   <span class="o">|</span> 
<span class="n">python</span>  <span class="o">|</span> <span 
class="mi">617</span>    <span class="o">|</span> <span class="n">A</span>      
<span class="o">|</span>
-<span class="o">|</span> <span class="mi">2</span>   <span class="o">|</span> 
<span class="n">ruby</span>    <span class="o">|</span> <span 
class="mi">82</span>     <span class="o">|</span> <span class="n">A</span>      
<span class="o">|</span>
-<span class="o">|</span> <span class="mi">3</span>   <span class="o">|</span> 
<span class="n">java</span>    <span class="o">|</span> <span 
class="mi">137</span>    <span class="o">|</span> <span class="n">B</span>      
<span class="o">|</span>
-<span class="o">|</span> <span class="mi">4</span>   <span class="o">|</span> 
<span class="n">haskell</span> <span class="o">|</span> <span 
class="mi">183</span>    <span class="o">|</span> <span class="n">C</span>      
<span class="o">|</span>
-<span class="o">|</span> <span class="mi">5</span>   <span class="o">|</span> 
<span class="n">go</span>      <span class="o">|</span> <span 
class="mi">244</span>    <span class="o">|</span> <span class="n">B</span>      
<span class="o">|</span>
+<span class="o">|</span> <span class="mi">1</span>   <span class="o">|</span> 
<span class="n">python</span>  <span class="o">|</span> <span 
class="mi">747</span>    <span class="o">|</span> <span class="n">A</span>      
<span class="o">|</span>
+<span class="o">|</span> <span class="mi">2</span>   <span class="o">|</span> 
<span class="n">ruby</span>    <span class="o">|</span> <span 
class="mi">57</span>     <span class="o">|</span> <span class="n">A</span>      
<span class="o">|</span>
+<span class="o">|</span> <span class="mi">3</span>   <span class="o">|</span> 
<span class="n">java</span>    <span class="o">|</span> <span 
class="mi">376</span>    <span class="o">|</span> <span class="n">B</span>      
<span class="o">|</span>
+<span class="o">|</span> <span class="mi">4</span>   <span class="o">|</span> 
<span class="n">haskell</span> <span class="o">|</span> <span 
class="mi">591</span>    <span class="o">|</span> <span class="n">C</span>      
<span class="o">|</span>
+<span class="o">|</span> <span class="mi">5</span>   <span class="o">|</span> 
<span class="n">go</span>      <span class="o">|</span> <span 
class="mi">123</span>    <span class="o">|</span> <span class="n">B</span>      
<span class="o">|</span>
 <span class="o">+-----+---------+--------+--------+</span>
 </pre></div>
 </div>
@@ -414,8 +419,8 @@
 <span class="o">+-----+--------+--------+--------+</span>
 <span class="o">|</span> <span class="n">nrs</span> <span class="o">|</span> 
<span class="n">names</span>  <span class="o">|</span> <span 
class="n">random</span> <span class="o">|</span> <span class="n">groups</span> 
<span class="o">|</span>
 <span class="o">+-----+--------+--------+--------+</span>
-<span class="o">|</span> <span class="mi">1</span>   <span class="o">|</span> 
<span class="n">python</span> <span class="o">|</span> <span 
class="mi">617</span>    <span class="o">|</span> <span class="n">A</span>      
<span class="o">|</span>
-<span class="o">|</span> <span class="mi">2</span>   <span class="o">|</span> 
<span class="n">ruby</span>   <span class="o">|</span> <span 
class="mi">82</span>     <span class="o">|</span> <span class="n">A</span>      
<span class="o">|</span>
+<span class="o">|</span> <span class="mi">1</span>   <span class="o">|</span> 
<span class="n">python</span> <span class="o">|</span> <span 
class="mi">747</span>    <span class="o">|</span> <span class="n">A</span>      
<span class="o">|</span>
+<span class="o">|</span> <span class="mi">2</span>   <span class="o">|</span> 
<span class="n">ruby</span>   <span class="o">|</span> <span 
class="mi">57</span>     <span class="o">|</span> <span class="n">A</span>      
<span class="o">|</span>
 <span class="o">+-----+--------+--------+--------+</span>
 </pre></div>
 </div>
@@ -433,28 +438,28 @@ passing them to an Arrow table, and then converting them 
to a pandas DataFrame.<
 <div class="highlight-ipython notranslate"><div 
class="highlight"><pre><span></span><span class="n">In</span> <span 
class="p">[</span><span class="mi">8</span><span class="p">]:</span> <span 
class="n">df</span><span class="o">.</span><span 
class="n">to_pandas</span><span class="p">()</span>
 <span class="n">Out</span><span class="p">[</span><span 
class="mi">8</span><span class="p">]:</span> 
    <span class="n">nrs</span>    <span class="n">names</span>  <span 
class="n">random</span> <span class="n">groups</span>
-<span class="mi">0</span>    <span class="mi">1</span>   <span 
class="n">python</span>     <span class="mi">617</span>      <span 
class="n">A</span>
-<span class="mi">1</span>    <span class="mi">2</span>     <span 
class="n">ruby</span>      <span class="mi">82</span>      <span 
class="n">A</span>
-<span class="mi">2</span>    <span class="mi">3</span>     <span 
class="n">java</span>     <span class="mi">137</span>      <span 
class="n">B</span>
-<span class="mi">3</span>    <span class="mi">4</span>  <span 
class="n">haskell</span>     <span class="mi">183</span>      <span 
class="n">C</span>
-<span class="mi">4</span>    <span class="mi">5</span>       <span 
class="n">go</span>     <span class="mi">244</span>      <span 
class="n">B</span>
+<span class="mi">0</span>    <span class="mi">1</span>   <span 
class="n">python</span>     <span class="mi">747</span>      <span 
class="n">A</span>
+<span class="mi">1</span>    <span class="mi">2</span>     <span 
class="n">ruby</span>      <span class="mi">57</span>      <span 
class="n">A</span>
+<span class="mi">2</span>    <span class="mi">3</span>     <span 
class="n">java</span>     <span class="mi">376</span>      <span 
class="n">B</span>
+<span class="mi">3</span>    <span class="mi">4</span>  <span 
class="n">haskell</span>     <span class="mi">591</span>      <span 
class="n">C</span>
+<span class="mi">4</span>    <span class="mi">5</span>       <span 
class="n">go</span>     <span class="mi">123</span>      <span 
class="n">B</span>
 </pre></div>
 </div>
 <p><a class="reference internal" 
href="../../autoapi/datafusion/dataframe/index.html#datafusion.dataframe.DataFrame.describe"
 title="datafusion.dataframe.DataFrame.describe"><code class="xref py py-func 
docutils literal notranslate"><span class="pre">describe()</span></code></a> 
shows a quick statistic summary of your data:</p>
 <div class="highlight-ipython notranslate"><div 
class="highlight"><pre><span></span><span class="n">In</span> <span 
class="p">[</span><span class="mi">9</span><span class="p">]:</span> <span 
class="n">df</span><span class="o">.</span><span class="n">describe</span><span 
class="p">()</span>
 <span class="n">Out</span><span class="p">[</span><span 
class="mi">9</span><span class="p">]:</span> 
 <span class="n">DataFrame</span><span class="p">()</span>
-<span 
class="o">+------------+--------------------+-------+--------------------+--------+</span>
-<span class="o">|</span> <span class="n">describe</span>   <span 
class="o">|</span> <span class="n">nrs</span>                <span 
class="o">|</span> <span class="n">names</span> <span class="o">|</span> <span 
class="n">random</span>             <span class="o">|</span> <span 
class="n">groups</span> <span class="o">|</span>
-<span 
class="o">+------------+--------------------+-------+--------------------+--------+</span>
-<span class="o">|</span> <span class="n">count</span>      <span 
class="o">|</span> <span class="mf">5.0</span>                <span 
class="o">|</span> <span class="mi">5</span>     <span class="o">|</span> <span 
class="mf">5.0</span>                <span class="o">|</span> <span 
class="mi">5</span>      <span class="o">|</span>
-<span class="o">|</span> <span class="n">null_count</span> <span 
class="o">|</span> <span class="mf">0.0</span>                <span 
class="o">|</span> <span class="mi">0</span>     <span class="o">|</span> <span 
class="mf">0.0</span>                <span class="o">|</span> <span 
class="mi">0</span>      <span class="o">|</span>
-<span class="o">|</span> <span class="n">mean</span>       <span 
class="o">|</span> <span class="mf">3.0</span>                <span 
class="o">|</span> <span class="n">null</span>  <span class="o">|</span> <span 
class="mf">252.6</span>              <span class="o">|</span> <span 
class="n">null</span>   <span class="o">|</span>
-<span class="o">|</span> <span class="n">std</span>        <span 
class="o">|</span> <span class="mf">1.5811388300841898</span> <span 
class="o">|</span> <span class="n">null</span>  <span class="o">|</span> <span 
class="mf">212.23406889564174</span> <span class="o">|</span> <span 
class="n">null</span>   <span class="o">|</span>
-<span class="o">|</span> <span class="nb">min</span>        <span 
class="o">|</span> <span class="mf">1.0</span>                <span 
class="o">|</span> <span class="n">go</span>    <span class="o">|</span> <span 
class="mf">82.0</span>               <span class="o">|</span> <span 
class="n">A</span>      <span class="o">|</span>
-<span class="o">|</span> <span class="nb">max</span>        <span 
class="o">|</span> <span class="mf">5.0</span>                <span 
class="o">|</span> <span class="n">ruby</span>  <span class="o">|</span> <span 
class="mf">617.0</span>              <span class="o">|</span> <span 
class="n">C</span>      <span class="o">|</span>
-<span class="o">|</span> <span class="n">median</span>     <span 
class="o">|</span> <span class="mf">3.0</span>                <span 
class="o">|</span> <span class="n">null</span>  <span class="o">|</span> <span 
class="mf">183.0</span>              <span class="o">|</span> <span 
class="n">null</span>   <span class="o">|</span>
-<span 
class="o">+------------+--------------------+-------+--------------------+--------+</span>
+<span 
class="o">+------------+--------------------+-------+-------------------+--------+</span>
+<span class="o">|</span> <span class="n">describe</span>   <span 
class="o">|</span> <span class="n">nrs</span>                <span 
class="o">|</span> <span class="n">names</span> <span class="o">|</span> <span 
class="n">random</span>            <span class="o">|</span> <span 
class="n">groups</span> <span class="o">|</span>
+<span 
class="o">+------------+--------------------+-------+-------------------+--------+</span>
+<span class="o">|</span> <span class="n">count</span>      <span 
class="o">|</span> <span class="mf">5.0</span>                <span 
class="o">|</span> <span class="mi">5</span>     <span class="o">|</span> <span 
class="mf">5.0</span>               <span class="o">|</span> <span 
class="mi">5</span>      <span class="o">|</span>
+<span class="o">|</span> <span class="n">null_count</span> <span 
class="o">|</span> <span class="mf">0.0</span>                <span 
class="o">|</span> <span class="mi">0</span>     <span class="o">|</span> <span 
class="mf">0.0</span>               <span class="o">|</span> <span 
class="mi">0</span>      <span class="o">|</span>
+<span class="o">|</span> <span class="n">mean</span>       <span 
class="o">|</span> <span class="mf">3.0</span>                <span 
class="o">|</span> <span class="n">null</span>  <span class="o">|</span> <span 
class="mf">378.8</span>             <span class="o">|</span> <span 
class="n">null</span>   <span class="o">|</span>
+<span class="o">|</span> <span class="n">std</span>        <span 
class="o">|</span> <span class="mf">1.5811388300841898</span> <span 
class="o">|</span> <span class="n">null</span>  <span class="o">|</span> <span 
class="mf">295.6335569586105</span> <span class="o">|</span> <span 
class="n">null</span>   <span class="o">|</span>
+<span class="o">|</span> <span class="nb">min</span>        <span 
class="o">|</span> <span class="mf">1.0</span>                <span 
class="o">|</span> <span class="n">go</span>    <span class="o">|</span> <span 
class="mf">57.0</span>              <span class="o">|</span> <span 
class="n">A</span>      <span class="o">|</span>
+<span class="o">|</span> <span class="nb">max</span>        <span 
class="o">|</span> <span class="mf">5.0</span>                <span 
class="o">|</span> <span class="n">ruby</span>  <span class="o">|</span> <span 
class="mf">747.0</span>             <span class="o">|</span> <span 
class="n">C</span>      <span class="o">|</span>
+<span class="o">|</span> <span class="n">median</span>     <span 
class="o">|</span> <span class="mf">3.0</span>                <span 
class="o">|</span> <span class="n">null</span>  <span class="o">|</span> <span 
class="mf">376.0</span>             <span class="o">|</span> <span 
class="n">null</span>   <span class="o">|</span>
+<span 
class="o">+------------+--------------------+-------+-------------------+--------+</span>
 </pre></div>
 </div>
 </section>
diff --git a/user-guide/common-operations/expressions.html 
b/user-guide/common-operations/expressions.html
index 6542c9e6..3c6b44f2 100644
--- a/user-guide/common-operations/expressions.html
+++ b/user-guide/common-operations/expressions.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/common-operations/functions.html 
b/user-guide/common-operations/functions.html
index d20ed611..fa774f0c 100644
--- a/user-guide/common-operations/functions.html
+++ b/user-guide/common-operations/functions.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
@@ -490,16 +495,16 @@ In here we will cover some of the more popular use cases. 
If you want to view al
 <span class="o">+--------------------------------+</span>
 <span class="o">|</span> <span class="n">now</span><span class="p">()</span>   
                       <span class="o">|</span>
 <span class="o">+--------------------------------+</span>
-<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">20</span><span class="n">T01</span><span class="p">:</span><span 
class="mi">55</span><span class="p">:</span><span 
class="mf">24.583282540</span><span class="n">Z</span> <span class="o">|</span>
-<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">20</span><span class="n">T01</span><span class="p">:</span><span 
class="mi">55</span><span class="p">:</span><span 
class="mf">24.583282540</span><span class="n">Z</span> <span class="o">|</span>
-<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">20</span><span class="n">T01</span><span class="p">:</span><span 
class="mi">55</span><span class="p">:</span><span 
class="mf">24.583282540</span><span class="n">Z</span> <span class="o">|</span>
-<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">20</span><span class="n">T01</span><span class="p">:</span><span 
class="mi">55</span><span class="p">:</span><span 
class="mf">24.583282540</span><span class="n">Z</span> <span class="o">|</span>
-<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">20</span><span class="n">T01</span><span class="p">:</span><span 
class="mi">55</span><span class="p">:</span><span 
class="mf">24.583282540</span><span class="n">Z</span> <span class="o">|</span>
-<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">20</span><span class="n">T01</span><span class="p">:</span><span 
class="mi">55</span><span class="p">:</span><span 
class="mf">24.583282540</span><span class="n">Z</span> <span class="o">|</span>
-<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">20</span><span class="n">T01</span><span class="p">:</span><span 
class="mi">55</span><span class="p">:</span><span 
class="mf">24.583282540</span><span class="n">Z</span> <span class="o">|</span>
-<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">20</span><span class="n">T01</span><span class="p">:</span><span 
class="mi">55</span><span class="p">:</span><span 
class="mf">24.583282540</span><span class="n">Z</span> <span class="o">|</span>
-<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">20</span><span class="n">T01</span><span class="p">:</span><span 
class="mi">55</span><span class="p">:</span><span 
class="mf">24.583282540</span><span class="n">Z</span> <span class="o">|</span>
-<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">20</span><span class="n">T01</span><span class="p">:</span><span 
class="mi">55</span><span class="p">:</span><span 
class="mf">24.583282540</span><span class="n">Z</span> <span class="o">|</span>
+<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">21</span><span class="n">T21</span><span class="p">:</span><span 
class="mi">08</span><span class="p">:</span><span 
class="mf">42.620547788</span><span class="n">Z</span> <span class="o">|</span>
+<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">21</span><span class="n">T21</span><span class="p">:</span><span 
class="mi">08</span><span class="p">:</span><span 
class="mf">42.620547788</span><span class="n">Z</span> <span class="o">|</span>
+<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">21</span><span class="n">T21</span><span class="p">:</span><span 
class="mi">08</span><span class="p">:</span><span 
class="mf">42.620547788</span><span class="n">Z</span> <span class="o">|</span>
+<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">21</span><span class="n">T21</span><span class="p">:</span><span 
class="mi">08</span><span class="p">:</span><span 
class="mf">42.620547788</span><span class="n">Z</span> <span class="o">|</span>
+<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">21</span><span class="n">T21</span><span class="p">:</span><span 
class="mi">08</span><span class="p">:</span><span 
class="mf">42.620547788</span><span class="n">Z</span> <span class="o">|</span>
+<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">21</span><span class="n">T21</span><span class="p">:</span><span 
class="mi">08</span><span class="p">:</span><span 
class="mf">42.620547788</span><span class="n">Z</span> <span class="o">|</span>
+<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">21</span><span class="n">T21</span><span class="p">:</span><span 
class="mi">08</span><span class="p">:</span><span 
class="mf">42.620547788</span><span class="n">Z</span> <span class="o">|</span>
+<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">21</span><span class="n">T21</span><span class="p">:</span><span 
class="mi">08</span><span class="p">:</span><span 
class="mf">42.620547788</span><span class="n">Z</span> <span class="o">|</span>
+<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">21</span><span class="n">T21</span><span class="p">:</span><span 
class="mi">08</span><span class="p">:</span><span 
class="mf">42.620547788</span><span class="n">Z</span> <span class="o">|</span>
+<span class="o">|</span> <span class="mi">2025</span><span 
class="o">-</span><span class="mi">02</span><span class="o">-</span><span 
class="mi">21</span><span class="n">T21</span><span class="p">:</span><span 
class="mi">08</span><span class="p">:</span><span 
class="mf">42.620547788</span><span class="n">Z</span> <span class="o">|</span>
 <span class="o">+--------------------------------+</span>
 </pre></div>
 </div>
diff --git a/user-guide/common-operations/index.html 
b/user-guide/common-operations/index.html
index e66669a2..32caf1f0 100644
--- a/user-guide/common-operations/index.html
+++ b/user-guide/common-operations/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/common-operations/joins.html 
b/user-guide/common-operations/joins.html
index 026f289c..ba14264e 100644
--- a/user-guide/common-operations/joins.html
+++ b/user-guide/common-operations/joins.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/common-operations/select-and-filter.html 
b/user-guide/common-operations/select-and-filter.html
index 63ebfb15..86ee7d18 100644
--- a/user-guide/common-operations/select-and-filter.html
+++ b/user-guide/common-operations/select-and-filter.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/common-operations/udf-and-udfa.html 
b/user-guide/common-operations/udf-and-udfa.html
index 38b15b12..d4e37cc3 100644
--- a/user-guide/common-operations/udf-and-udfa.html
+++ b/user-guide/common-operations/udf-and-udfa.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/common-operations/windows.html 
b/user-guide/common-operations/windows.html
index a2b08de4..cf976287 100644
--- a/user-guide/common-operations/windows.html
+++ b/user-guide/common-operations/windows.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
@@ -658,20 +663,20 @@ power in its <code class="docutils literal 
notranslate"><span class="pre">&quot;
    <span class="o">....</span><span class="p">:</span> 
 <span class="n">Out</span><span class="p">[</span><span 
class="mi">13</span><span class="p">]:</span> 
 <span class="n">DataFrame</span><span class="p">()</span>
-<span 
class="o">+-----------------------+--------+--------+-------------------+</span>
-<span class="o">|</span> <span class="n">Name</span>                  <span 
class="o">|</span> <span class="n">Attack</span> <span class="o">|</span> <span 
class="n">Type</span> <span class="mi">1</span> <span class="o">|</span> <span 
class="n">Average</span> <span class="n">Attack</span>    <span 
class="o">|</span>
-<span 
class="o">+-----------------------+--------+--------+-------------------+</span>
-<span class="o">|</span> <span class="n">Metapod</span>               <span 
class="o">|</span> <span class="mi">20</span>     <span class="o">|</span> 
<span class="n">Bug</span>    <span class="o">|</span> <span 
class="mf">76.42857142857143</span> <span class="o">|</span>
-<span class="o">|</span> <span class="n">Butterfree</span>            <span 
class="o">|</span> <span class="mi">45</span>     <span class="o">|</span> 
<span class="n">Bug</span>    <span class="o">|</span> <span 
class="mf">76.42857142857143</span> <span class="o">|</span>
-<span class="o">|</span> <span class="n">Weedle</span>                <span 
class="o">|</span> <span class="mi">35</span>     <span class="o">|</span> 
<span class="n">Bug</span>    <span class="o">|</span> <span 
class="mf">76.42857142857143</span> <span class="o">|</span>
-<span class="o">|</span> <span class="n">Kakuna</span>                <span 
class="o">|</span> <span class="mi">25</span>     <span class="o">|</span> 
<span class="n">Bug</span>    <span class="o">|</span> <span 
class="mf">76.42857142857143</span> <span class="o">|</span>
-<span class="o">|</span> <span class="n">Beedrill</span>              <span 
class="o">|</span> <span class="mi">90</span>     <span class="o">|</span> 
<span class="n">Bug</span>    <span class="o">|</span> <span 
class="mf">76.42857142857143</span> <span class="o">|</span>
-<span class="o">|</span> <span class="n">BeedrillMega</span> <span 
class="n">Beedrill</span> <span class="o">|</span> <span class="mi">150</span>  
  <span class="o">|</span> <span class="n">Bug</span>    <span 
class="o">|</span> <span class="mf">76.42857142857143</span> <span 
class="o">|</span>
-<span class="o">|</span> <span class="n">Paras</span>                 <span 
class="o">|</span> <span class="mi">70</span>     <span class="o">|</span> 
<span class="n">Bug</span>    <span class="o">|</span> <span 
class="mf">76.42857142857143</span> <span class="o">|</span>
-<span class="o">|</span> <span class="n">Parasect</span>              <span 
class="o">|</span> <span class="mi">95</span>     <span class="o">|</span> 
<span class="n">Bug</span>    <span class="o">|</span> <span 
class="mf">76.42857142857143</span> <span class="o">|</span>
-<span class="o">|</span> <span class="n">Venonat</span>               <span 
class="o">|</span> <span class="mi">55</span>     <span class="o">|</span> 
<span class="n">Bug</span>    <span class="o">|</span> <span 
class="mf">76.42857142857143</span> <span class="o">|</span>
-<span class="o">|</span> <span class="n">Venomoth</span>              <span 
class="o">|</span> <span class="mi">65</span>     <span class="o">|</span> 
<span class="n">Bug</span>    <span class="o">|</span> <span 
class="mf">76.42857142857143</span> <span class="o">|</span>
-<span 
class="o">+-----------------------+--------+--------+-------------------+</span>
+<span 
class="o">+---------------------+--------+--------+----------------+</span>
+<span class="o">|</span> <span class="n">Name</span>                <span 
class="o">|</span> <span class="n">Attack</span> <span class="o">|</span> <span 
class="n">Type</span> <span class="mi">1</span> <span class="o">|</span> <span 
class="n">Average</span> <span class="n">Attack</span> <span class="o">|</span>
+<span 
class="o">+---------------------+--------+--------+----------------+</span>
+<span class="o">|</span> <span class="n">Jynx</span>                <span 
class="o">|</span> <span class="mi">50</span>     <span class="o">|</span> 
<span class="n">Ice</span>    <span class="o">|</span> <span 
class="mf">67.5</span>           <span class="o">|</span>
+<span class="o">|</span> <span class="n">Articuno</span>            <span 
class="o">|</span> <span class="mi">85</span>     <span class="o">|</span> 
<span class="n">Ice</span>    <span class="o">|</span> <span 
class="mf">67.5</span>           <span class="o">|</span>
+<span class="o">|</span> <span class="n">Pidgey</span>              <span 
class="o">|</span> <span class="mi">45</span>     <span class="o">|</span> 
<span class="n">Normal</span> <span class="o">|</span> <span 
class="mf">70.625</span>         <span class="o">|</span>
+<span class="o">|</span> <span class="n">Pidgeotto</span>           <span 
class="o">|</span> <span class="mi">60</span>     <span class="o">|</span> 
<span class="n">Normal</span> <span class="o">|</span> <span 
class="mf">70.625</span>         <span class="o">|</span>
+<span class="o">|</span> <span class="n">Pidgeot</span>             <span 
class="o">|</span> <span class="mi">80</span>     <span class="o">|</span> 
<span class="n">Normal</span> <span class="o">|</span> <span 
class="mf">70.625</span>         <span class="o">|</span>
+<span class="o">|</span> <span class="n">PidgeotMega</span> <span 
class="n">Pidgeot</span> <span class="o">|</span> <span class="mi">80</span>    
 <span class="o">|</span> <span class="n">Normal</span> <span 
class="o">|</span> <span class="mf">70.625</span>         <span 
class="o">|</span>
+<span class="o">|</span> <span class="n">Rattata</span>             <span 
class="o">|</span> <span class="mi">56</span>     <span class="o">|</span> 
<span class="n">Normal</span> <span class="o">|</span> <span 
class="mf">70.625</span>         <span class="o">|</span>
+<span class="o">|</span> <span class="n">Raticate</span>            <span 
class="o">|</span> <span class="mi">81</span>     <span class="o">|</span> 
<span class="n">Normal</span> <span class="o">|</span> <span 
class="mf">70.625</span>         <span class="o">|</span>
+<span class="o">|</span> <span class="n">Spearow</span>             <span 
class="o">|</span> <span class="mi">60</span>     <span class="o">|</span> 
<span class="n">Normal</span> <span class="o">|</span> <span 
class="mf">70.625</span>         <span class="o">|</span>
+<span class="o">|</span> <span class="n">Fearow</span>              <span 
class="o">|</span> <span class="mi">90</span>     <span class="o">|</span> 
<span class="n">Normal</span> <span class="o">|</span> <span 
class="mf">70.625</span>         <span class="o">|</span>
+<span 
class="o">+---------------------+--------+--------+----------------+</span>
 </pre></div>
 </div>
 </section>
diff --git a/user-guide/configuration.html b/user-guide/configuration.html
index 257958d4..8ea8c390 100644
--- a/user-guide/configuration.html
+++ b/user-guide/configuration.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/data-sources.html b/user-guide/data-sources.html
index 6fb95668..0c7da12f 100644
--- a/user-guide/data-sources.html
+++ b/user-guide/data-sources.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/introduction.html b/user-guide/introduction.html
index 17f1c218..2da3a880 100644
--- a/user-guide/introduction.html
+++ b/user-guide/introduction.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/io/arrow.html b/user-guide/io/arrow.html
index 4fd6b96a..3016c379 100644
--- a/user-guide/io/arrow.html
+++ b/user-guide/io/arrow.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/io/avro.html b/user-guide/io/avro.html
index 1f33f294..a11b3bef 100644
--- a/user-guide/io/avro.html
+++ b/user-guide/io/avro.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/io/csv.html b/user-guide/io/csv.html
index d99d2f0a..982565f2 100644
--- a/user-guide/io/csv.html
+++ b/user-guide/io/csv.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/io/index.html b/user-guide/io/index.html
index 30b06703..3e4f35d7 100644
--- a/user-guide/io/index.html
+++ b/user-guide/io/index.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/io/json.html b/user-guide/io/json.html
index 63441b69..b4ba740e 100644
--- a/user-guide/io/json.html
+++ b/user-guide/io/json.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/io/parquet.html b/user-guide/io/parquet.html
index 00f0aa18..8880ca6a 100644
--- a/user-guide/io/parquet.html
+++ b/user-guide/io/parquet.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/io/table_provider.html 
b/user-guide/io/table_provider.html
index 9558846a..2c45a7ff 100644
--- a/user-guide/io/table_provider.html
+++ b/user-guide/io/table_provider.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">
diff --git a/user-guide/sql.html b/user-guide/sql.html
index e1fe06d1..5604381b 100644
--- a/user-guide/sql.html
+++ b/user-guide/sql.html
@@ -233,6 +233,11 @@
    Introduction
   </a>
  </li>
+ <li class="toctree-l1">
+  <a class="reference internal" href="../contributor-guide/ffi.html">
+   Python Extensions
+  </a>
+ </li>
 </ul>
 <p aria-level="2" class="caption" role="heading">
  <span class="caption-text">


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to