diff --git a/python/CHANGES.txt b/python/CHANGES.txt deleted file mode 100644 index e5767d5702..0000000000 --- a/python/CHANGES.txt +++ /dev/null @@ -1,3 +0,0 @@ -Changes -================================================================================ - diff --git a/python/MANIFEST.in b/python/MANIFEST.in deleted file mode 100644 index ff6f5924ff..0000000000 --- a/python/MANIFEST.in +++ /dev/null @@ -1,6 +0,0 @@ -exclude *.txt -exclude MANIFEST.in -include CHANGES.txt README.rst VERSION.txt -recursive-include test *.py -recursive-include pdal *.pyx -recursive-include pdal *.hpp diff --git a/python/PKG-INFO b/python/PKG-INFO deleted file mode 100644 index 7d2bfc03f0..0000000000 --- a/python/PKG-INFO +++ /dev/null @@ -1,75 +0,0 @@ -Metadata-Version: 1.1 -Name: PDAL -Version: 1.6.0 -Summary: Point cloud data processing -Home-page: http://pdal.io -Author: Howard Butler -Author-email: howard@hobu.co -License: BSD -Description: ================================================================================ - PDAL - ================================================================================ - - The PDAL Python extension allows you to process data with PDAL into `Numpy`_ - arrays. Additionally, you can use it to fetch `schema`_ and `metadata`_ from - PDAL operations. - - Usage - -------------------------------------------------------------------------------- - - Given the following pipeline, which simply reads an `ASPRS LAS`_ file and - sorts it by the ``X`` dimension: - - .. _`ASPRS LAS`: https://www.asprs.org/committee-general/laser-las-file-format-exchange-activities.html - - .. code-block:: python - - - json = """ - { - "pipeline": [ - "1.2-with-color.las", - { - "type": "filters.sort", - "dimension": "X" - } - ] - }""" - - import pdal - pipeline = pdal.Pipeline(json) - pipeline.validate() # check if our JSON and options were good - pipeline.loglevel = 9 #really noisy - count = pipeline.execute() - arrays = pipeline.arrays - metadata = pipeline.metadata - log = pipeline.log - - - .. _`Numpy`: http://www.numpy.org/ - .. _`schema`: http://www.pdal.io/dimensions.html - .. _`metadata`: http://www.pdal.io/development/metadata.html - - Requirements - ================================================================================ - - * PDAL 1.4+ - * Python >=2.7 (including Python 3.x) - - - - Changes - ================================================================================ - - -Keywords: point cloud spatial -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Science/Research -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Topic :: Scientific/Engineering :: GIS -Requires: Python (>=2.7) diff --git a/python/README.rst b/python/README.rst deleted file mode 100644 index f538ed9425..0000000000 --- a/python/README.rst +++ /dev/null @@ -1,50 +0,0 @@ -================================================================================ -PDAL -================================================================================ - -The PDAL Python extension allows you to process data with PDAL into `Numpy`_ -arrays. Additionally, you can use it to fetch `schema`_ and `metadata`_ from -PDAL operations. - -Usage --------------------------------------------------------------------------------- - -Given the following pipeline, which simply reads an `ASPRS LAS`_ file and -sorts it by the ``X`` dimension: - -.. _`ASPRS LAS`: https://www.asprs.org/committee-general/laser-las-file-format-exchange-activities.html - -.. code-block:: python - - - json = """ - { - "pipeline": [ - "1.2-with-color.las", - { - "type": "filters.sort", - "dimension": "X" - } - ] - }""" - - import pdal - pipeline = pdal.Pipeline(json) - pipeline.validate() # check if our JSON and options were good - pipeline.loglevel = 9 #really noisy - count = pipeline.execute() - arrays = pipeline.arrays - metadata = pipeline.metadata - log = pipeline.log - - -.. _`Numpy`: http://www.numpy.org/ -.. _`schema`: http://www.pdal.io/dimensions.html -.. _`metadata`: http://www.pdal.io/development/metadata.html - -Requirements -================================================================================ - -* PDAL 1.4+ -* Python >=2.7 (including Python 3.x) - diff --git a/python/VERSION.txt b/python/VERSION.txt deleted file mode 100644 index ce6a70b9d8..0000000000 --- a/python/VERSION.txt +++ /dev/null @@ -1 +0,0 @@ -1.6.0 \ No newline at end of file diff --git a/python/pdal/PyArray.hpp b/python/pdal/PyArray.hpp deleted file mode 100644 index 1e3e2bdb15..0000000000 --- a/python/pdal/PyArray.hpp +++ /dev/null @@ -1,212 +0,0 @@ -/****************************************************************************** -* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com) -* -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following -* conditions are met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided -* with the distribution. -* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the -* names of its contributors may be used to endorse or promote -* products derived from this software without specific prior -* written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -* OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include - -#include - -#pragma warning(disable: 4127) // conditional expression is constant - - -#include -#undef toupper -#undef tolower -#undef isspace - -#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -#include - -// forward declare PyObject so we don't need the python headers everywhere -// see: http://mail.python.org/pipermail/python-dev/2003-August/037601.html -#ifndef PyObject_HEAD -struct _object; -typedef _object PyObject; -#endif - -namespace pdal -{ -namespace python -{ - - -class PDAL_DLL Array -{ -public: - - Array() : m_py_array(0) - {} - - ~Array() - { - cleanup(); - } - - - inline void update(PointViewPtr view) - { - typedef std::unique_ptr> DataPtr; - cleanup(); - int nd = 1; - Dimension::IdList dims = view->dims(); - npy_intp mydims = view->size(); - npy_intp* ndims = &mydims; - std::vector strides(dims.size()); - - - DataPtr pdata( new std::vector(view->pointSize()* view->size(), 0)); - - PyArray_Descr *dtype(0); - PyObject * dtype_dict = (PyObject*)buildNumpyDescription(view); - if (!dtype_dict) - throw pdal_error("Unable to build numpy dtype description dictionary"); - int did_convert = PyArray_DescrConverter(dtype_dict, &dtype); - if (did_convert == NPY_FAIL) - throw pdal_error("Unable to build numpy dtype"); - Py_XDECREF(dtype_dict); - -#ifdef NPY_ARRAY_CARRAY - int flags = NPY_ARRAY_CARRAY; -#else - int flags = NPY_CARRAY; -#endif - uint8_t* sp = pdata.get()->data(); - PyObject * pyArray = PyArray_NewFromDescr(&PyArray_Type, - dtype, - nd, - ndims, - 0, - sp, - flags, - NULL); - - // copy the data - uint8_t* p(sp); - DimTypeList types = view->dimTypes(); - for (PointId idx = 0; idx < view->size(); idx++) - { - p = sp + (view->pointSize() * idx); - view->getPackedPoint(types, idx, (char*)p); - } - - m_py_array = pyArray; - m_data_array = std::move(pdata); - } - - - inline PyObject* getPythonArray() const { return m_py_array; } - - -private: - - inline void cleanup() - { - PyObject* p = (PyObject*)(m_py_array); - Py_XDECREF(p); - m_data_array.reset(); - } - - inline PyObject* buildNumpyDescription(PointViewPtr view) const - { - - // Build up a numpy dtype dictionary - // - // {'formats': ['f8', 'f8', 'f8', 'u2', 'u1', 'u1', 'u1', 'u1', 'u1', 'f4', 'u1', 'u2', 'f8', 'u2', 'u2', 'u2'], - // 'names': ['X', 'Y', 'Z', 'Intensity', 'ReturnNumber', 'NumberOfReturns', - // 'ScanDirectionFlag', 'EdgeOfFlightLine', 'Classification', - // 'ScanAngleRank', 'UserData', 'PointSourceId', 'GpsTime', 'Red', 'Green', - // 'Blue']} - // - - std::stringstream oss; - Dimension::IdList dims = view->dims(); - - PyObject* dict = PyDict_New(); - PyObject* sizes = PyList_New(dims.size()); - PyObject* formats = PyList_New(dims.size()); - PyObject* titles = PyList_New(dims.size()); - - for (Dimension::IdList::size_type i=0; i < dims.size(); ++i) - { - Dimension::Id id = (dims[i]); - Dimension::Type t = view->dimType(id); - npy_intp stride = view->dimSize(id); - - std::string name = view->dimName(id); - - std::string kind("i"); - Dimension::BaseType b = Dimension::base(t); - if (b == Dimension::BaseType::Unsigned) - kind = "u"; - else if (b == Dimension::BaseType::Floating) - kind = "f"; - else - { - std::stringstream o; - oss << "unable to map kind '" << kind <<"' to PDAL dimension type"; - throw pdal::pdal_error(o.str()); - } - - oss << kind << stride; - PyObject* pySize = PyLong_FromLong(stride); - PyObject* pyTitle = PyUnicode_FromString(name.c_str()); - PyObject* pyFormat = PyUnicode_FromString(oss.str().c_str()); - - PyList_SetItem(sizes, i, pySize); - PyList_SetItem(titles, i, pyTitle); - PyList_SetItem(formats, i, pyFormat); - - oss.str(""); - } - - PyDict_SetItemString(dict, "names", titles); - PyDict_SetItemString(dict, "formats", formats); - - // PyObject* obj = PyUnicode_AsASCIIString(PyObject_Str(dict)); - // const char* s = PyBytes_AsString(obj); - // std::string output(s); - // std::cout << "array: " << output << std::endl; - return dict; - } - - PyObject* m_py_array; - std::unique_ptr > m_data_array; - - Array& operator=(Array const& rhs); -}; - -} // namespace python -} // namespace pdal - diff --git a/python/pdal/PyPipeline.cpp b/python/pdal/PyPipeline.cpp deleted file mode 100644 index 2a4f08f2fc..0000000000 --- a/python/pdal/PyPipeline.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/****************************************************************************** -* Copyright (c) 2016, Howard Butler (howard@hobu.co) -* -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following -* conditions are met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided -* with the distribution. -* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the -* names of its contributors may be used to endorse or promote -* products derived from this software without specific prior -* written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -* OF SUCH DAMAGE. -****************************************************************************/ - -#include "PyPipeline.hpp" -#ifdef PDAL_HAVE_LIBXML2 -#include -#endif - -#ifndef _WIN32 -#include -#endif - -#include -#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -#include - -#include "PyArray.hpp" - -namespace libpdalpython -{ - -using namespace pdal::python; - -Pipeline::Pipeline(std::string const& json) - : m_executor(json) -{ - // Make the symbols in pdal_base global so that they're accessible - // to PDAL plugins. Python dlopen's this extension with RTLD_LOCAL, - // which means that without this, symbols in libpdal_base aren't available - // for resolution of symbols on future runtime linking. This is an issue - // on Apline and other Linux variants that doesn't use UNIQUE symbols - // for C++ template statics. only -#ifndef _WIN32 - ::dlopen("libpdal_base.so", RTLD_NOLOAD | RTLD_GLOBAL); -#endif - - import_array(); -} - -Pipeline::~Pipeline() -{ -} - -void Pipeline::setLogLevel(int level) -{ - m_executor.setLogLevel(level); -} - -int Pipeline::getLogLevel() const -{ - return static_cast(m_executor.getLogLevel()); -} - -int64_t Pipeline::execute() -{ - - int64_t count = m_executor.execute(); - return count; -} - -bool Pipeline::validate() -{ - return m_executor.validate(); -} - -std::vector Pipeline::getArrays() const -{ - std::vector output; - - if (!m_executor.executed()) - throw python_error("call execute() before fetching arrays"); - - const pdal::PointViewSet& pvset = m_executor.getManagerConst().views(); - - for (auto i: pvset) - { - //ABELL - Leak? - Array *array = new pdal::python::Array; - array->update(i); - output.push_back(array); - } - return output; -} -} //namespace libpdalpython - diff --git a/python/pdal/PyPipeline.hpp b/python/pdal/PyPipeline.hpp deleted file mode 100644 index 5d12ac2580..0000000000 --- a/python/pdal/PyPipeline.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/****************************************************************************** -* Copyright (c) 2016, Howard Butler (howard@hobu.co) -* -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following -* conditions are met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided -* with the distribution. -* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the -* names of its contributors may be used to endorse or promote -* products derived from this software without specific prior -* written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -* OF SUCH DAMAGE. -****************************************************************************/ - -#pragma once - -#include -#include -#include -#include - -#include -#include -#undef toupper -#undef tolower -#undef isspace - -namespace pdal -{ -namespace python -{ - class Array; -} -} - -namespace libpdalpython -{ - -class python_error : public std::runtime_error -{ -public: - inline python_error(std::string const& msg) : std::runtime_error(msg) - {} -}; - -class Pipeline { -public: - Pipeline(std::string const& xml); - ~Pipeline(); - - int64_t execute(); - bool validate(); - inline std::string getPipeline() const - { - return m_executor.getPipeline(); - } - inline std::string getMetadata() const - { - return m_executor.getMetadata(); - } - inline std::string getSchema() const - { - return m_executor.getSchema(); - } - inline std::string getLog() const - { - return m_executor.getLog(); - } - std::vector getArrays() const; - - void setLogLevel(int level); - int getLogLevel() const; - -private: - pdal::PipelineExecutor m_executor; -}; - -} diff --git a/python/pdal/__init__.py b/python/pdal/__init__.py deleted file mode 100644 index 4e4e32f513..0000000000 --- a/python/pdal/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -__version__='1.6.0' - -from .pipeline import Pipeline diff --git a/python/pdal/libpdalpython.pyx b/python/pdal/libpdalpython.pyx deleted file mode 100644 index ae90ff2cd0..0000000000 --- a/python/pdal/libpdalpython.pyx +++ /dev/null @@ -1,93 +0,0 @@ -# distutils: language = c++ - -from libcpp.vector cimport vector -from libcpp.string cimport string -from libc.stdint cimport uint32_t, int64_t -from libcpp cimport bool -from cpython.version cimport PY_MAJOR_VERSION -cimport numpy as np -np.import_array() - -from cpython cimport PyObject, Py_INCREF -from cython.operator cimport dereference as deref, preincrement as inc - - -cdef extern from "PyArray.hpp" namespace "pdal::python": - cdef cppclass Array: - void* getPythonArray() except+ - -cdef extern from "PyPipeline.hpp" namespace "libpdalpython": - cdef cppclass Pipeline: - Pipeline(const char* ) except + - int64_t execute() except + - bool validate() except + - string getPipeline() except + - string getMetadata() except + - string getSchema() except + - string getLog() except + - vector[Array*] getArrays() except + - int getLogLevel() - void setLogLevel(int) - -cdef class PyPipeline: - cdef Pipeline *thisptr # hold a c++ instance which we're wrapping - def __cinit__(self, unicode json): - cdef char* x - if PY_MAJOR_VERSION >= 3: - py_byte_string = json.encode('UTF-8') - x= py_byte_string - self.thisptr = new Pipeline(x) - else: - self.thisptr = new Pipeline(json) - def __dealloc__(self): - del self.thisptr - - property pipeline: - def __get__(self): - return self.thisptr.getPipeline().decode('UTF-8') - - property metadata: - def __get__(self): - return self.thisptr.getMetadata().decode('UTF-8') - - property loglevel: - def __get__(self): - return self.thisptr.getLogLevel() - def __set__(self, v): - self.thisptr.setLogLevel(v) - - property log: - def __get__(self): - - return self.thisptr.getLog().decode('UTF-8') - - property schema: - def __get__(self): - import json - - j = self.thisptr.getSchema().decode('UTF-8') - return json.loads(j) - - property arrays: - def __get__(self): - v = self.thisptr.getArrays() - output = [] - cdef vector[Array*].iterator it = v.begin() - cdef Array* a - while it != v.end(): - ptr = deref(it) - a = ptr#.get() - o = a.getPythonArray() - output.append(o) - inc(it) - return output - - def execute(self): - if not self.thisptr: - raise Exception("C++ Pipeline object not constructed!") - return self.thisptr.execute() - - def validate(self): - if not self.thisptr: - raise Exception("C++ Pipeline object not constructed!") - return self.thisptr.validate() diff --git a/python/pdal/pipeline.py b/python/pdal/pipeline.py deleted file mode 100644 index 7cd7aef080..0000000000 --- a/python/pdal/pipeline.py +++ /dev/null @@ -1,46 +0,0 @@ - -from pdal import libpdalpython - -class Pipeline(object): - """A PDAL pipeline object, defined by JSON. See http://www.pdal.io/pipeline.html for more - information on how to define one""" - - def __init__(self, json): - if isinstance(json, str): - data = json - else: - data = json.decode('UTF-8') - self.p = libpdalpython.PyPipeline(data) - - def get_metadata(self): - return self.p.metadata - metadata = property(get_metadata) - - def get_schema(self): - return self.p.schema - schema = property(get_schema) - - def get_pipeline(self): - return self.p.pipeline - pipeline = property(get_pipeline) - - def get_loglevel(self): - return self.p.loglevel - - def set_loglevel(self, v): - self.p.loglevel = v - loglevel = property(get_loglevel, set_loglevel) - - def get_log(self): - return self.p.log - log = property(get_log) - - def execute(self): - return self.p.execute() - - def validate(self): - return self.p.validate() - - def get_arrays(self): - return self.p.arrays - arrays = property(get_arrays) diff --git a/python/setup.cfg b/python/setup.cfg deleted file mode 100644 index 861a9f5542..0000000000 --- a/python/setup.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 - diff --git a/python/setup.py b/python/setup.py deleted file mode 100644 index 7826ad75ef..0000000000 --- a/python/setup.py +++ /dev/null @@ -1,196 +0,0 @@ -#!/usr/bin/env python - -# Stolen from Shapely's setup.py -# Two environment variables influence this script. -# -# PDAL_LIBRARY_PATH: a path to a PDAL C++ shared library. -# -# PDAL_CONFIG: the path to a pdal-config program that points to PDAL version, -# headers, and libraries. -# -# NB: within this setup scripts, software versions are evaluated according -# to https://www.python.org/dev/peps/pep-0440/. - -import logging -import os -import platform -import sys -import numpy -from Cython.Build import cythonize - -USE_CYTHON = True -try: - from Cython.Build import cythonize -except ImportError: - USE_CYTHON = False - -ext = '.pyx' if USE_CYTHON else '.cpp' - -from setuptools import setup -from packaging.version import Version - - -logging.basicConfig() -log = logging.getLogger(__file__) - -# python -W all setup.py ... -if 'all' in sys.warnoptions: - log.level = logging.DEBUG - - -# Second try: use PDAL_CONFIG environment variable -if 'PDAL_CONFIG' in os.environ: - pdal_config = os.environ['PDAL_CONFIG'] - log.debug('pdal_config: %s', pdal_config) -else: - pdal_config = 'pdal-config' - # in case of windows... - if os.name in ['nt']: - pdal_config += '.bat' - - -def get_pdal_config(option): - '''Get configuration option from the `pdal-config` development utility - - This code was adapted from Shapely's geos-config stuff - ''' - import subprocess - pdal_config = globals().get('pdal_config') - if not pdal_config or not isinstance(pdal_config, str): - raise OSError('Path to pdal-config is not set') - try: - stdout, stderr = subprocess.Popen( - [pdal_config, option], - stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() - except OSError as ex: - # e.g., [Errno 2] No such file or directory - raise OSError( - 'Could not find pdal-config %r: %s' % (pdal_config, ex)) - if stderr and not stdout: - raise ValueError(stderr.strip()) - if sys.version_info[0] >= 3: - result = stdout.decode('ascii').strip() - else: - result = stdout.strip() - log.debug('%s %s: %r', pdal_config, option, result) - return result - -# Get the version from the pdal module -module_version = None -with open('pdal/__init__.py', 'r') as fp: - for line in fp: - if line.startswith("__version__"): - module_version = Version(line.split("=")[1].strip().strip("\"'")) - break - -if not module_version: - raise ValueError("Could not determine PDAL's version") - -# Handle UTF-8 encoding of certain text files. -open_kwds = {} -if sys.version_info >= (3,): - open_kwds['encoding'] = 'utf-8' - -with open('VERSION.txt', 'w', **open_kwds) as fp: - fp.write(str(module_version)) - -with open('README.rst', 'r', **open_kwds) as fp: - readme = fp.read() - -with open('CHANGES.txt', 'r', **open_kwds) as fp: - changes = fp.read() - -long_description = readme + '\n\n' + changes - -include_dirs = [] -library_dirs = [] -libraries = [] -extra_link_args = [] - -from setuptools.extension import Extension as DistutilsExtension - -if pdal_config and "clean" not in sys.argv: - # Collect other options from PDAL - try: - - # Running against different major versions is going to fail. - # Minor versions might too, depending on numpy. - for item in get_pdal_config('--python-version').split(): - if item: - # 2.7.4 or 3.5.2 - built_version = item.split('.') - built_major = int(built_version[0]) - running_major = int(sys.version_info[0]) - if built_major != running_major: - message = "Version mismatch. PDAL Python support was compiled against version %d.x but setup is running version is %d.x. " - raise Exception(message % (built_major, running_major)) - - # older versions of pdal-config do not include --python-version switch - except ValueError: - pass - - separator = ':' - if os.name in ['nt']: - separator = ';' - - for item in get_pdal_config('--includes').split(): - if item.startswith("-I"): - include_dirs.extend(item[2:].split(separator)) - - for item in get_pdal_config('--libs').split(): - if item.startswith("-L"): - library_dirs.extend(item[2:].split(separator)) - elif item.startswith("-l"): - libraries.append(item[2:]) - -include_dirs.append(numpy.get_include()) -extra_compile_args = ['-std=c++11','-Wno-unknown-pragmas'] - -DEBUG=False -if DEBUG: - extra_compile_args += ['-g','-O0'] - -sources=['pdal/libpdalpython'+ext, "pdal/PyPipeline.cpp" ] -extensions = [DistutilsExtension("*", - sources, - include_dirs=include_dirs, - library_dirs=library_dirs, - extra_compile_args=extra_compile_args, - libraries=libraries, - extra_link_args=extra_link_args,)] -if USE_CYTHON and "clean" not in sys.argv: - from Cython.Build import cythonize - extensions= cythonize(extensions, language="c++") - -setup_args = dict( - name = 'PDAL', - version = str(module_version), - requires = ['Python (>=2.7)', ], - description = 'Point cloud data processing', - license = 'BSD', - keywords = 'point cloud spatial', - author = 'Howard Butler', - author_email = 'howard@hobu.co', - maintainer = 'Howard Butler', - maintainer_email = 'howard@hobu.co', - url = 'http://pdal.io', - long_description = long_description, - test_suite = 'test', - packages = [ - 'pdal', - ], - classifiers = [ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Intended Audience :: Science/Research', - 'License :: OSI Approved :: BSD License', - 'Operating System :: OS Independent', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Topic :: Scientific/Engineering :: GIS', - ], - cmdclass = {}, - install_requires = ['numpy', 'packaging'], -) -setup(ext_modules=extensions, **setup_args) - diff --git a/python/test/__init__.py b/python/test/__init__.py deleted file mode 100644 index 8a3c854594..0000000000 --- a/python/test/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -import sys -DATADIRECTORY = sys.argv.pop() -from test.test_pipeline import test_suite diff --git a/python/test/test_pipeline.py b/python/test/test_pipeline.py deleted file mode 100644 index d497e31af1..0000000000 --- a/python/test/test_pipeline.py +++ /dev/null @@ -1,127 +0,0 @@ -import unittest -import pdal -import os - -DATADIRECTORY = os.environ.get('PDAL_TEST_DIR') -if not DATADIRECTORY: - DATADIRECTORY = "../test" - -bad_json = u""" -{ - "pipeline": [ - "nofile.las", - { - "type": "filters.sort", - "dimension": "X" - } - ] -} -""" - -class TestPipeline(unittest.TestCase): - - DATADIRECTORY = os.environ.get('PDAL_TEST_DIR') - if not DATADIRECTORY: - DATADIRECTORY = "../test" - def fetch_json(self, filename): - import os - fn = DATADIRECTORY + os.path.sep + filename - output = '' - with open(fn, 'rb') as f: - output = f.read().decode('UTF-8') - return output - - @unittest.skipUnless(os.path.exists(os.path.join(DATADIRECTORY, 'data/pipeline/sort.json')), - "missing test data") - def test_construction(self): - """Can we construct a PDAL pipeline""" - json = self.fetch_json('/data/pipeline/sort.json') - r = pdal.Pipeline(json) - - @unittest.skipUnless(os.path.exists(os.path.join(DATADIRECTORY, 'data/pipeline/sort.json')), - "missing test data") - def test_execution(self): - """Can we execute a PDAL pipeline""" - x = self.fetch_json('/data/pipeline/sort.json') - r = pdal.Pipeline(x) - r.execute() - self.assertGreater(len(r.pipeline), 200) - - def test_validate(self): - """Do we complain with bad pipelines""" - r = pdal.Pipeline(bad_json) - with self.assertRaises(RuntimeError): - r.validate() - - @unittest.skipUnless(os.path.exists(os.path.join(DATADIRECTORY, 'data/pipeline/sort.json')), - "missing test data") - def test_array(self): - """Can we fetch PDAL data as a numpy array""" - json = self.fetch_json('/data/pipeline/sort.json') - r = pdal.Pipeline(json) - r.execute() - arrays = r.arrays - self.assertEqual(len(arrays), 1) - - a = arrays[0] - self.assertAlmostEqual(a[0][0], 635619.85, 7) - self.assertAlmostEqual(a[1064][2], 456.92, 7) - - @unittest.skipUnless(os.path.exists(os.path.join(DATADIRECTORY, 'data/pipeline/sort.json')), - "missing test data") - def test_metadata(self): - """Can we fetch PDAL metadata""" - json = self.fetch_json('/data/pipeline/sort.json') - r = pdal.Pipeline(json) - r.execute() - metadata = r.metadata - import json - j = json.loads(metadata) - self.assertEqual(j["metadata"]["readers.las"]["count"], 1065) - - - @unittest.skipUnless(os.path.exists(os.path.join(DATADIRECTORY, 'data/pipeline/sort.json')), - "missing test data") - def test_no_execute(self): - """Does fetching arrays without executing throw an exception""" - json = self.fetch_json('/data/pipeline/sort.json') - r = pdal.Pipeline(json) - with self.assertRaises(RuntimeError): - r.arrays - - @unittest.skipUnless(os.path.exists(os.path.join(DATADIRECTORY, 'data/pipeline/reproject.json')), - "missing test data") - def test_logging(self): - """Can we fetch log output""" - json = self.fetch_json('/data/pipeline/reproject.json') - r = pdal.Pipeline(json) - r.loglevel = 8 - count = r.execute() - self.assertEqual(count, 789) - self.assertEqual(r.log.split()[0], '(pypipeline') - - @unittest.skipUnless(os.path.exists(os.path.join(DATADIRECTORY, 'data/pipeline/sort.json')), - "missing test data") - def test_schema(self): - """Fetching a schema works""" - json = self.fetch_json('/data/pipeline/sort.json') - r = pdal.Pipeline(json) - r.execute() - self.assertEqual(r.schema['schema']['dimensions'][0]['name'], 'X') - - @unittest.skipUnless(os.path.exists(os.path.join(DATADIRECTORY, 'data/filters/chip.json')), - "missing test data") - def test_merged_arrays(self): - """Can we fetch multiple point views from merged PDAL data """ - json = self.fetch_json('/data/filters/chip.json') - r = pdal.Pipeline(json) - r.execute() - arrays = r.arrays - self.assertEqual(len(arrays), 43) - -def test_suite(): - return unittest.TestSuite( - [TestXML]) - -if __name__ == '__main__': - unittest.main() diff --git a/scripts/ci/script.sh b/scripts/ci/script.sh index 5cac3f4474..3290be5be7 100755 --- a/scripts/ci/script.sh +++ b/scripts/ci/script.sh @@ -89,8 +89,9 @@ ctest -V make install # Python extension testing -cd /pdal/python pip install packaging +git clone https://github.com/PDAL/python.git pdal-python +cd pdal-python python setup.py build echo "current path: " `pwd` export PDAL_TEST_DIR=/pdal/_build/test