Skip to content

Commit

Permalink
docs(python): Add example of python package with nanoarrow C extension (
Browse files Browse the repository at this point in the history
  • Loading branch information
WillAyd authored Oct 4, 2024
1 parent 85adb56 commit 4168119
Show file tree
Hide file tree
Showing 7 changed files with 287 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/examples.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,8 @@ jobs:
meson compile -C builddir
./builddir/example_meson_minimal_app
- name: Python example
run: |
python3 -m pip install examples/python-package
python3 -c "import schema_printer"
22 changes: 22 additions & 0 deletions examples/python-package/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# 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.

subprojects/*
!subprojects/packagefiles
!subprojects/*.wrap

builddir
81 changes: 81 additions & 0 deletions examples/python-package/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

# Python Package Example

This folder contains a Python project that uses the nanoarrow
project in a C extension. To make building and packaging the library
as simple as possible, this example uses Meson as a build system alongside
the meson-python frontend. The pyproject.toml file lists these as build
dependencies, so you don't need to install them yourself (unless you set
the --no-build-isolation flag from your build frontend).

This library is completely self contained. To build it, simply

```bash
git clone https://github.com/apache/arrow-nanoarrow.git
cd arrow-nanoarrow/examples/python-package
python -m pip install .
```

The nanoarrow dependency is resolved through the Meson wrap system (see
subprojects/nanoarrow.wrap). When creating your own library, be sure to
create the subprojects directory up front and then run:

```bash
mkdir -p subprojects
meson wrap install nanoarrow
```

To install the wrap definition file.

For more control over the pip installation, you may want to set options like
the build directory or the type of build. For example, to get an editable
install of the library, while also building it in debug mode and storing the
build artifacts in the builddir directory, you should run:

```bash
python -m pip install -e . -Cbuilddir=builddir -Csetup-args="-Dbuildtype=debug"
```

Note that meson will generate a compilation database in the build directory
automatically. This can be particularly helpful for IDEs and code completion
if symlinked to the root of your Python package.

```bash
ln -s builddir/compile_commands.json .
```

The code contained herein makes use of the Arrow C Data interface and
Arrow PyCapsule interface to exchange data between the Python runtime and a
C extension. After installing the project, you can run it as follows:

```python
>>> import pyarrow as pa
>>> import schema_printer

>>> schema = pa.schema([("some int", pa.int32()), ("some_string", pa.string())])
>>> schema
some int: int32
some_string: string

>>> schema_printer.print_schema(schema)
Field: some int, Type: int32
Field: some_string, Type: string
```
39 changes: 39 additions & 0 deletions examples/python-package/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 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.

project(
'nanoarrow-python-demo',
'c',
version: '0.0.1dev',
default_options: [
'warning_level=2',
'c_std=c17',
'default_library=static',
],
)

py = import('python').find_installation()
nanoarrow_dep = dependency('nanoarrow')

py.extension_module(
'schema_printer',
sources: [
'src/nanoarrow_python_demo/schema_printer.c'
],
dependencies: [nanoarrow_dep],
install: true,
)
31 changes: 31 additions & 0 deletions examples/python-package/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# 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.

[project]
name = 'nanoarrow-python-demo'
dynamic = ['version'] # gets version from build backend
description = "Sample Python package using nanoarrow"

[build-system]
requires = ['meson-python', 'meson']
build-backend= 'mesonpy'

[tool.meson-python.args]
# We are going to statically link any subprojects in our Meson configuration
# so no need to try and install them. You may need to customize this if you
# do have shared libraries that you want to install into your Python wheel
install = ['--skip-subprojects']
82 changes: 82 additions & 0 deletions examples/python-package/src/nanoarrow_python_demo/schema_printer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// 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.

#define PY_SSIZE_T_CLEAN
#include <Python.h>

#include "nanoarrow/nanoarrow.h"

static int PrintSchema(const struct ArrowSchema* schema) {
for (int64_t i = 0; i < schema->n_children; i++) {
const struct ArrowSchema* child = schema->children[i];
struct ArrowSchemaView schema_view;
struct ArrowError error;
if (ArrowSchemaViewInit(&schema_view, child, &error) != NANOARROW_OK) {
PyErr_SetString(PyExc_RuntimeError, error.message);
return -1;
}
printf("Field: %s, Type: %s\n", child->name, ArrowTypeString(schema_view.type));
}

return 0;
}

static PyObject* PrintArrowSchema(PyObject* Py_UNUSED(self), PyObject* args) {
PyObject* obj;
if (!PyArg_ParseTuple(args, "O", &obj)) {
return NULL;
}

PyObject* capsule = PyObject_CallMethod(obj, "__arrow_c_schema__", NULL);
if (capsule == NULL) {
PyErr_SetString(PyExc_TypeError,
"Could not call '__arrow_c_schema__' on provided object");
return NULL;
}

const struct ArrowSchema* schema =
(const struct ArrowSchema*)PyCapsule_GetPointer(capsule, "arrow_schema");
if (schema == NULL) {
PyErr_SetString(PyExc_RuntimeError, "Could not retrieve 'arrow_schema' pointer");
Py_DECREF(capsule);
return NULL;
}

int error = PrintSchema(schema);
Py_DECREF(capsule);
if (error) {
return NULL;
}

return Py_None;
}

static PyMethodDef schema_printer_methods[] = {
{.ml_name = "print_schema",
.ml_meth = (PyCFunction)PrintArrowSchema,
.ml_flags = METH_VARARGS,
.ml_doc = PyDoc_STR("Prints an Arrow Schema")},
{} // sentinel
};

static PyModuleDef schema_printer_def = {.m_base = PyModuleDef_HEAD_INIT,
.m_name = "schema_printer",
.m_methods = schema_printer_methods};

PyMODINIT_FUNC PyInit_schema_printer(void) {
return PyModuleDef_Init(&schema_printer_def);
}
27 changes: 27 additions & 0 deletions examples/python-package/subprojects/nanoarrow.wrap
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# 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.

[wrap-file]
directory = arrow-nanoarrow-apache-arrow-nanoarrow-0.5.0
source_url = https://github.com/apache/arrow-nanoarrow/archive/refs/tags/apache-arrow-nanoarrow-0.5.0.tar.gz
source_filename = apache-arrow-nanoarrow-0.5.0.tar.gz
source_hash = 0ceeaa1fb005dbc89c8c7d1b39f2dba07344e40aa9d885ee25fb55b4d57e331a
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/nanoarrow_0.5.0-1/apache-arrow-nanoarrow-0.5.0.tar.gz
wrapdb_version = 0.5.0-1

[provide]
nanoarrow = nanoarrow_dep

0 comments on commit 4168119

Please sign in to comment.