diff --git a/.github/environment.yml b/.github/environment.yml index 26096eb..23c4777 100644 --- a/.github/environment.yml +++ b/.github/environment.yml @@ -8,3 +8,7 @@ dependencies: - compilers - python - pip + - scikit-build-core + - pybind11 + - cmake + - ninja diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dad35b4..d354e28 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ defaults: jobs: build: - name: Build ${{ matrix.os }} py${{ matrix.python-version }} + name: ${{ matrix.os }} py${{ matrix.python-version }} numpy${{ matrix.numpy-version }} runs-on: ${{ matrix.os }} strategy: @@ -25,6 +25,10 @@ jobs: matrix: os: ['ubuntu-latest', 'macos-latest', 'windows-latest'] python-version: ['3.9', '3.10', '3.11', '3.12'] + numpy-version: ['1.26', '2.0', '2.1'] + exclude: + - python-version: 3.9 + numpy-version: 2.1 steps: - name: Check out @@ -40,6 +44,10 @@ jobs: auto-update-conda: true environment-file: .github/environment.yml + - name: Install Numpy ${{ matrix.numpy-version }} + shell: bash -l {0} + run: | + mamba install numpy=${{ matrix.numpy-version }} - name: Install shell: bash -l {0} diff --git a/CMakeLists.txt b/CMakeLists.txt index 055c2bf..39e3448 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,4 @@ -cmake_minimum_required(VERSION 3.11.0) -project(pdal-python-plugins) +cmake_minimum_required(VERSION 3.13.0) project(pdal-python-plugins VERSION ${SKBUILD_PROJECT_VERSION} DESCRIPTION "PDAL Python Plugins" HOMEPAGE_URL "https://github.com/PDAL/python-plugins") diff --git a/pyproject.toml b/pyproject.toml index ad9157f..63215ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ dependencies = [ "numpy >= 1.22" ] -version="1.6.1" +version="1.6.2" [project.optional-dependencies] test = [ ] diff --git a/src/pdal/io/NumpyReader.cpp b/src/pdal/io/NumpyReader.cpp index 199faaa..299703c 100644 --- a/src/pdal/io/NumpyReader.cpp +++ b/src/pdal/io/NumpyReader.cpp @@ -43,7 +43,7 @@ #include #include -#include "../plang/Environment.hpp" + #if NPY_ABI_VERSION < 0x02000000 #define PyDataType_FIELDS(descr) ((descr)->fields) @@ -138,10 +138,13 @@ void NumpyReader::setArray(PyObject* array) Py_XINCREF(m_array); } + PyArrayObject* load_npy_file(std::string const& filename) { PyObject *py_filename = PyUnicode_FromString(filename.c_str()); + if (!py_filename) + throw pdal::pdal_error(plang::getTraceback()); PyObject *numpy_module = PyImport_ImportModule("numpy"); if (!numpy_module) throw pdal::pdal_error(plang::getTraceback()); @@ -165,7 +168,11 @@ PyArrayObject* load_npy_file(std::string const& filename) if (!array) throw pdal::pdal_error(plang::getTraceback()); - return reinterpret_cast(array); + + PyArrayObject* nparray = reinterpret_cast(array); + if (!PyArray_Check(array)) + throw pdal_error("Numpy file did not return an array!"); + return nparray; } PyArrayObject* load_npy_script(std::string const& source, @@ -196,6 +203,9 @@ PyArrayObject* load_npy_script(std::string const& source, Py_XDECREF(scriptArgs); + if (!PyArray_Check(array)) + throw pdal_error("Numpy script did not return an array!"); + return reinterpret_cast(array); } @@ -350,32 +360,24 @@ Dimension::Id NumpyReader::registerDim(PointLayoutPtr layout, return id; } -namespace -{ - -Dimension::Type getType(PyArray_Descr *dtype, const std::string& name) +void NumpyReader::createFields(PointLayoutPtr layout) { - if (!dtype) - throw pdal_error("Can't fetch data type for numpy field."); - Dimension::Type pdalType = - plang::Environment::getPDALDataType(dtype->type_num); - if (pdalType == Dimension::Type::None) + auto getPDALType = [](int type_num, const std::string& name) { - std::ostringstream oss; - oss << "Unable to map dimension '" << name << "' because its " - "type '" << dtype->type_num <<"' is not mappable to PDAL"; - throw pdal_error(oss.str()); - } - return pdalType; -} - -} // unnamed namespace - + Dimension::Type pdalType = + plang::Environment::getPDALDataType(type_num); + if (pdalType == Dimension::Type::None) + { + std::ostringstream oss; + oss << "Unable to map dimension '" << name << "' because its " + "type '" << type_num <<"' is not mappable to PDAL"; + throw pdal_error(oss.str()); + } + return pdalType; + }; -void NumpyReader::createFields(PointLayoutPtr layout) -{ Dimension::Id id; Dimension::Type type; int offset; @@ -388,7 +390,7 @@ void NumpyReader::createFields(PointLayoutPtr layout) // Array isn't structured - just a bunch of data. if (m_numFields <= 0) { - type = getType(m_dtype, m_defaultDimension); + type = getPDALType(m_dtype->type_num, m_defaultDimension); id = registerDim(layout, m_defaultDimension, type); m_fields.push_back({id, type, 0}); } @@ -415,7 +417,7 @@ void NumpyReader::createFields(PointLayoutPtr layout) // Get type. PyArray_Descr* dt = (PyArray_Descr *)PySequence_Fast_GET_ITEM(tup, 0); - type = getType(dt, name); + type = getPDALType(dt->type_num, name); char byteorder = dt->byteorder; int elsize = (int) PyDataType_ELSIZE(dt); diff --git a/src/pdal/io/NumpyReader.hpp b/src/pdal/io/NumpyReader.hpp index ebffbb6..e9f19a6 100644 --- a/src/pdal/io/NumpyReader.hpp +++ b/src/pdal/io/NumpyReader.hpp @@ -37,13 +37,11 @@ #include #include +#include "../plang/Environment.hpp" #include "../plang/Invocation.hpp" -#include -#define NPY_NO_DEPRECATED_API NPY_1_22_API_VERSION -#define PY_ARRAY_UNIQUE_SYMBOL PDAL_ARRAY_API -#define NO_IMPORT_ARRAY -#include +#define NO_IMPORT_ARRAY // Already have it from Environment.hpp +#include #include diff --git a/src/pdal/plang/Environment.cpp b/src/pdal/plang/Environment.cpp index 210aa64..3aad88d 100644 --- a/src/pdal/plang/Environment.cpp +++ b/src/pdal/plang/Environment.cpp @@ -39,12 +39,8 @@ #include "Environment.hpp" #include "Redirector.hpp" -#define NPY_TARGET_VERSION NPY_1_22_API_VERSION -#define NPY_NO_DEPRECATED_API NPY_1_22_API_VERSION -#define PY_ARRAY_UNIQUE_SYMBOL PDAL_ARRAY_API - -#include +#include #include #include @@ -145,9 +141,12 @@ Environment::Environment() // the return. auto initNumpy = []() { -// #undef NUMPY_IMPORT_ARRAY_RETVAL -// #define NUMPY_IMPORT_ARRAY_RETVAL VOID + +#if NPY_ABI_VERSION < 0x02000000 _import_array(); +#else + PyArray_ImportNumPyAPI(); +#endif return ; }; @@ -165,7 +164,6 @@ Environment::Environment() throw pdal_error("unable to add redirector module!"); } - initNumpy(); PyImport_ImportModule("redirector"); diff --git a/src/pdal/plang/Environment.hpp b/src/pdal/plang/Environment.hpp index fed4fd6..75f33c7 100644 --- a/src/pdal/plang/Environment.hpp +++ b/src/pdal/plang/Environment.hpp @@ -49,6 +49,11 @@ #include "Script.hpp" #include "gil.hpp" +#define PY_ARRAY_UNIQUE_SYMBOL PDAL_NPARRAY_API +#define NPY_TARGET_VERSION NPY_1_22_API_VERSION +#define NPY_API_SYMBOL_ATTRIBUTE +#define NPY_NO_DEPRECATED_API NPY_1_22_API_VERSION + namespace pdal { namespace plang diff --git a/src/pdal/plang/Invocation.cpp b/src/pdal/plang/Invocation.cpp index ee9342f..808fe5f 100644 --- a/src/pdal/plang/Invocation.cpp +++ b/src/pdal/plang/Invocation.cpp @@ -36,10 +36,8 @@ #include -#define NPY_NO_DEPRECATED_API NPY_1_22_API_VERSION #define NO_IMPORT_ARRAY -#define PY_ARRAY_UNIQUE_SYMBOL PDAL_ARRAY_API -#include +#include namespace { diff --git a/src/pdal/test/data/1.2-with-color.npy b/src/pdal/test/data/1.2-with-color.npy index ee9b0fd..5930c18 100644 Binary files a/src/pdal/test/data/1.2-with-color.npy and b/src/pdal/test/data/1.2-with-color.npy differ