blob: 202868d5c71e2cf6c7b44ceac3d5c5d48beb1aca [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import os
import shutil
import subprocess
import sys
import pytest
import pyarrow as pa
import pyarrow.tests.util as test_util
here = os.path.dirname(os.path.abspath(__file__))
setup_template = """if 1:
from distutils.core import setup
from Cython.Build import cythonize
import numpy as np
import pyarrow as pa
ext_modules = cythonize({pyx_file!r})
compiler_opts = {compiler_opts!r}
custom_ld_path = {test_ld_path!r}
for ext in ext_modules:
# XXX required for numpy/numpyconfig.h,
# included from arrow/python/api.h
ext.include_dirs.append(np.get_include())
ext.include_dirs.append(pa.get_include())
ext.libraries.extend(pa.get_libraries())
ext.library_dirs.extend(pa.get_library_dirs())
if custom_ld_path:
ext.library_dirs.append(custom_ld_path)
ext.extra_compile_args.extend(compiler_opts)
print("Extension module:",
ext, ext.include_dirs, ext.libraries, ext.library_dirs)
setup(
ext_modules=ext_modules,
)
"""
@pytest.mark.cython
def test_cython_api(tmpdir):
"""
Basic test for the Cython API.
"""
# Fail early if cython is not found
import cython # noqa
test_ld_path = os.environ.get('PYARROW_TEST_LD_PATH', '')
with tmpdir.as_cwd():
# Set up temporary workspace
pyx_file = 'pyarrow_cython_example.pyx'
shutil.copyfile(os.path.join(here, pyx_file),
os.path.join(str(tmpdir), pyx_file))
# Create setup.py file
if os.name == 'posix':
compiler_opts = ['-std=c++11']
else:
compiler_opts = []
setup_code = setup_template.format(pyx_file=pyx_file,
compiler_opts=compiler_opts,
test_ld_path=test_ld_path)
with open('setup.py', 'w') as f:
f.write(setup_code)
# ARROW-2263: Make environment with this pyarrow/ package first on the
# PYTHONPATH, for local dev environments
subprocess_env = test_util.get_modified_env_with_pythonpath()
# Compile extension module
subprocess.check_call([sys.executable, 'setup.py',
'build_ext', '--inplace'],
env=subprocess_env)
# Check basic functionality
orig_path = sys.path[:]
sys.path.insert(0, str(tmpdir))
try:
mod = __import__('pyarrow_cython_example')
arr = pa.array([1, 2, 3])
assert mod.get_array_length(arr) == 3
with pytest.raises(TypeError, match="not an array"):
mod.get_array_length(None)
finally:
sys.path = orig_path
# Check the extension module is loadable from a subprocess without
# pyarrow imported first.
code = """if 1:
import sys
mod = __import__({mod_name!r})
arr = mod.make_null_array(5)
assert mod.get_array_length(arr) == 5
assert arr.null_count == 5
""".format(mod_path=str(tmpdir), mod_name='pyarrow_cython_example')
if sys.platform == 'win32':
delim, var = ';', 'PATH'
else:
delim, var = ':', 'LD_LIBRARY_PATH'
subprocess_env[var] = delim.join(
pa.get_library_dirs() + [subprocess_env.get(var, '')]
)
subprocess.check_call([sys.executable, '-c', code],
stdout=subprocess.PIPE,
env=subprocess_env)