123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- import glob
- import os
- import os.path as osp
- import re
- import shutil
- import sys
- from distutils.command.clean import clean as _clean
- from distutils import sysconfig
- from os.path import join as pjoin
- from setuptools import setup, Extension, Distribution
- from setuptools.command.build_ext import build_ext as _build_ext
- # Check if we're running 64-bit Python
- is_64_bit = sys.maxsize > 2**32
- class clean(_clean):
- def run(self):
- _clean.run(self)
- for x in []:
- try:
- os.remove(x)
- except OSError:
- pass
- class build_ext(_build_ext):
- def run(self):
- self._run_cmake()
- # adapted from cmake_build_ext in dynd-python
- # github.com/libdynd/dynd-python
- description = "Build the C-extensions for arrow"
- user_options = ([('extra-cmake-args=', None, 'extra arguments for CMake'),
- ('build-type=', None, 'build type (Debug or Release)')] +
- _build_ext.user_options)
- def initialize_options(self):
- _build_ext.initialize_options(self)
- self.extra_cmake_args = os.environ.get('XLNTPYARROW_CMAKE_OPTIONS', '')
- self.build_type = os.environ.get('XLNTPYARROW_BUILD_TYPE', 'Debug')
- self.cmake_cxxflags = os.environ.get('XLNTPYARROW_CXXFLAGS', '')
- if sys.platform == 'win32':
- # Cannot do debug builds in Windows unless Python itself is a debug
- # build
- if not hasattr(sys, 'gettotalrefcount'):
- self.build_type = 'Release'
- def _run_cmake(self):
- # The directory containing this setup.py
- source = osp.dirname(osp.abspath(__file__))
- # The staging directory for the module being built
- build_temp = pjoin(os.getcwd(), self.build_temp)
- build_lib = os.path.join(os.getcwd(), self.build_lib)
- # Change to the build directory
- saved_cwd = os.getcwd()
- if not os.path.isdir(self.build_temp):
- self.mkpath(self.build_temp)
- os.chdir(self.build_temp)
- # Detect if we built elsewhere
- if os.path.isfile('CMakeCache.txt'):
- cachefile = open('CMakeCache.txt', 'r')
- cachedir = re.search('CMAKE_CACHEFILE_DIR:INTERNAL=(.*)',
- cachefile.read()).group(1)
- cachefile.close()
- if (cachedir != build_temp):
- return
- static_lib_option = ''
- cmake_options = [
- '-DPYTHON_EXECUTABLE=%s' % sys.executable,
- static_lib_option,
- ]
- if len(self.cmake_cxxflags) > 0:
- cmake_options.append('-DPYARROW_CXXFLAGS="{0}"'
- .format(self.cmake_cxxflags))
- cmake_options.append('-DCMAKE_BUILD_TYPE={0}'
- .format(self.build_type))
- if 'CMAKE_GENERATOR' in os.environ:
- cmake_options.append('-G{}'
- .format(os.environ['CMAKE_GENERATOR']))
- if sys.platform != 'win32':
- cmake_options.append('-DCMAKE_INSTALL_PREFIX={0}'
- .format(os.environ['PREFIX']))
- cmake_command = (['cmake', self.extra_cmake_args] +
- cmake_options + [source])
- print("-- Runnning cmake for xlntpyarrow")
- self.spawn(cmake_command)
- print("-- Finished cmake for xlntpyarrow")
- args = ['make']
- if os.environ.get('XLNTPYARROW_BUILD_VERBOSE', '0') == '1':
- args.append('VERBOSE=1')
- if 'XLNTPYARROW_PARALLEL' in os.environ:
- args.append('-j{0}'.format(os.environ['XLNTPYARROW_PARALLEL']))
- args.append('install')
- print("-- Running cmake --build for xlntpyarrow")
- self.spawn(args)
- print("-- Finished cmake --build for xlntpyarrow")
- else:
- import shlex
- if not is_64_bit:
- raise RuntimeError('Not supported on 32-bit Windows')
- cmake_options.append('-DCMAKE_INSTALL_PREFIX={0}'
- .format(os.environ['LIBRARY_PREFIX']))
- extra_cmake_args = shlex.split(self.extra_cmake_args)
- cmake_command = (['cmake'] + extra_cmake_args +
- cmake_options + [source])
- print("-- Runnning cmake for xlntpyarrow")
- self.spawn(cmake_command)
- print("-- Finished cmake for xlntpyarrow")
- # Do the build
- print("-- Running cmake --build for xlntpyarrow")
- self.spawn(['cmake', '--build', '.', '--config', self.build_type, '--target', 'INSTALL'])
- print("-- Finished cmake --build for xlntpyarrow")
- if self.inplace:
- # a bit hacky
- build_lib = saved_cwd
- # Move the libraries to the place expected by the Python
- # build
- shared_library_prefix = 'lib'
- if sys.platform == 'darwin':
- shared_library_suffix = '.dylib'
- elif sys.platform == 'win32':
- shared_library_suffix = '.dll'
- shared_library_prefix = ''
- else:
- shared_library_suffix = '.so'
- try:
- os.makedirs(pjoin(build_lib, 'xlntpyarrow'))
- except OSError:
- pass
- self._found_names = []
- built_path = self.get_ext_built('lib')
- if not os.path.exists(built_path):
- raise RuntimeError('xlntpyarrow C-extension failed to build:',
- os.path.abspath(built_path))
- ext_path = pjoin(build_lib, self._get_cmake_ext_path('lib'))
- if os.path.exists(ext_path):
- os.remove(ext_path)
- self.mkpath(os.path.dirname(ext_path))
- print('Moving built C-extension', built_path,
- 'to build path', ext_path)
- shutil.move(self.get_ext_built('lib'), ext_path)
- self._found_names.append('lib')
- os.chdir(saved_cwd)
- def _failure_permitted(self, name):
- return False
- def _get_inplace_dir(self):
- pass
- def _get_cmake_ext_path(self, name):
- # Get the package directory from build_py
- build_py = self.get_finalized_command('build_py')
- package_dir = build_py.get_package_dir('xlntpyarrow')
- # This is the name of the arrow C-extension
- suffix = sysconfig.get_config_var('EXT_SUFFIX')
- if suffix is None:
- suffix = sysconfig.get_config_var('SO')
- filename = name + suffix
- return pjoin(package_dir, filename)
- def get_ext_built(self, name):
- if sys.platform == 'win32':
- head, tail = os.path.split(name)
- suffix = sysconfig.get_config_var('SO')
- return pjoin(head, self.build_type, tail + suffix)
- else:
- suffix = sysconfig.get_config_var('SO')
- print('suffix is', suffix)
- return name + suffix
- def get_names(self):
- return self._found_names
- def get_outputs(self):
- # Just the C extensions
- # regular_exts = _build_ext.get_outputs(self)
- return [self._get_cmake_ext_path(name)
- for name in self.get_names()]
- long_description = """
- xlntpyarrow allows Apache Arrow tables to be written to and read from an XLSX
- file efficiently using the C++ library xlnt.
- """.strip()
- classifiers = [
- 'Development Status :: 5 - Production/Stable',
- 'Environment :: Plugins',
- 'Intended Audience :: Science/Research',
- 'License :: OSI Approved :: MIT License',
- 'Natural Language :: English',
- 'Operating System :: Microsoft :: Windows',
- 'Operating System :: MacOS :: MacOS X',
- 'Operating System :: POSIX :: Linux',
- 'Programming Language :: C',
- 'Programming Language :: C++',
- 'Programming Language :: Python :: 2.7',
- 'Programming Language :: Python :: 3.6',
- 'Programming Language :: Python :: Implementation :: CPython',
- 'Topic :: Database',
- 'Topic :: Office/Business :: Financial :: Spreadsheet',
- 'Topic :: Scientific/Engineering :: Information Analysis',
- 'Topic :: Software Development :: Libraries :: Python Modules'
- ]
- class BinaryDistribution(Distribution):
- def has_ext_modules(foo):
- return True
- setup(
- name = 'xlntpyarrow',
- version = '1.1.0',
- description = 'Python library for converting Apache Arrow tables<->XLSX files',
- long_description = long_description,
- author = 'Thomas Fussell',
- author_email = 'thomas.fussell@gmail.com',
- maintainer = 'Thomas Fussell',
- maintainer_email = 'thomas.fussell@gmail.com',
- url = 'https://github.com/tfussell/xlnt',
- download_url = 'https://github.com/tfussell/xlnt/releases',
- packages = ['xlntpyarrow'],
- ext_modules = [Extension('xlntpyarrow.lib', [])],
- cmdclass = {
- 'clean': clean,
- 'build_ext': build_ext
- },
- classifiers = classifiers,
- distclass = BinaryDistribution,
- zip_safe = False
- )
|