#!/usr/bin/env python # -*- coding: utf-8 -*- # ######### COPYRIGHT ######### # Credits # ####### # # Copyright(c) 2015-2018 # ---------------------- # # * `LabEx Archimède <http://labex-archimede.univ-amu.fr/>`_ # * `Laboratoire d'Informatique Fondamentale <http://www.lif.univ-mrs.fr/>`_ # (now `Laboratoire d'Informatique et Systèmes <http://www.lis-lab.fr/>`_) # * `Institut de Mathématiques de Marseille <http://www.i2m.univ-amu.fr/>`_ # * `Université d'Aix-Marseille <http://www.univ-amu.fr/>`_ # # This software is a port from LTFAT 2.1.0 : # Copyright (C) 2005-2018 Peter L. Soendergaard <peter@sonderport.dk>. # # Contributors # ------------ # # * Denis Arrivault <contact.dev_AT_lis-lab.fr> # * Florent Jaillet <contact.dev_AT_lis-lab.fr> # # Description # ----------- # # ltfatpy is a partial Python port of the # `Large Time/Frequency Analysis Toolbox <http://ltfat.sourceforge.net/>`_, # a MATLAB®/Octave toolbox for working with time-frequency analysis and # synthesis. # # Version # ------- # # * ltfatpy version = 1.0.12 # * LTFAT version = 2.1.0 # # Licence # ------- # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # ######### COPYRIGHT ######### from __future__ import print_function, division import sys import os import shutil import distutils.spawn as ds import distutils.dir_util as dd # Always prefer setuptools over distutils from setuptools import setup, find_packages, Extension from distutils.command.clean import clean from distutils.command.sdist import sdist # Test if Cython is installed USE_CYTHON = True try: from Cython.Distutils import build_ext except ImportError: USE_CYTHON = False from distutils.command.build_ext import build_ext USE_COPYRIGHT = True try: from copyright import writeStamp, eraseStamp except ImportError: USE_COPYRIGHT = False ################### # Get ltfat version #################### def get_version(): v_text = open('VERSION').read().strip() v_text_formted = '{"' + v_text.replace('\n', '","').replace(':', '":"') v_text_formted += '"}' v_dict = eval(v_text_formted) return v_dict["ltfatpy"] ######################## # Set ltfat __version__ ######################## def set_version(ltfat_dir, VERSION): filename = os.path.join(ltfat_dir, '__init__.py') buf = "" for line in open(filename, "rb"): if not line.decode("utf8").startswith("__version__ ="): buf += line.decode("utf8") f = open(filename, "wb") f.write(buf.encode("utf8")) f.write(('__version__ = "%s"\n' % VERSION).encode("utf8")) ################# # CMake function ################# def run_cmake(root_dir): """ Runs CMake to determine configuration for this build """ if ds.find_executable('cmake') is None: print("CMake is required to build ltfatpy") print("Please install cmake version >= 2.6 and re-run setup") sys.exit(-1) print("Configuring ltfatpy build with CMake.... ") print("Root dir : " + root_dir) new_dir = os.path.join(root_dir, 'build') dd.mkpath(new_dir) os.chdir(new_dir) try: ds.spawn(['cmake', '..']) except ds.DistutilsExecError: print("Error while running cmake") print("run 'setup.py build --help' for build options") print("You may also try editing the settings in CMakeLists.txt file " + "and re-running setup") sys.exit(-1) ################# # make function ################# def run_make(root_dir): """ Runs make to build ltfatpy libraries """ print("Building ltfatpy libraries.... ") build_dir = os.path.join(root_dir, 'build') os.chdir(build_dir) try: ds.spawn(['make']) except ds.DistutilsExecError: print("Error while running make") print("run 'setup.py build --help' for build options") print("You may also try editing the settings in CMakeLists.txt file " + "and re-running setup") sys.exit(-1) ####################### # make install function ####################### def run_make_install(root_dir): """ Runs make install to install ltfatpy libraries """ print("Installing ltfatpy libraries.... ") build_dir = os.path.join(root_dir, 'build') os.chdir(build_dir) try: ds.spawn(['make', 'install']) # +cmake_args.split()) except ds.DistutilsExecError: print("Error while running make install") print("run 'setup.py build --help' for build options") print("You may also try editing the settings in CMakeLists.txt file " + "and re-running setup") sys.exit(-1) ################# # uninstall libs ################# def run_uninstall(root_dir): """ Un-installs ltfatpy libraries """ print("Uninstall ltfatpy libraries.... ") build_dir = os.path.join(root_dir, 'build') os.chdir(build_dir) try: ds.spawn(['make', 'uninstall']) except ds.DistutilsExecError: print("Error while running make uninstall") print("run 'setup.py build --help' for build options") print("You may also try editing the settings in CMakeLists.txt file " + "and re-running setup") sys.exit(-1) ######################### # Custom 'build_ext' command ######################### class m_build_ext(build_ext): """ Custom build_ext command """ def run(self): root_dir = os.path.dirname(os.path.abspath(__file__)) cur_dir = os.getcwd() run_cmake(root_dir) run_make(root_dir) run_make_install(root_dir) os.chdir(cur_dir) build_ext.run(self) ########################## # File path read command ########################## def read(*paths): """Build a file path from *paths* and return the contents.""" from io import open with open(os.path.join(*paths), 'r', encoding='utf-8') as f: return f.read() ##################################### # Directory pyx files scan command ##################################### def findpyxfiles(directory, files=[]): """scan a directory for pyx extension files.""" for filename in os.listdir(directory): path = os.path.join(directory, filename) if os.path.isfile(path) and path.endswith(".pyx"): files.append(path.replace(os.path.sep, ".")[:-4]) elif os.path.isdir(path): findpyxfiles(path, files) return files ################# # Extension maker ################# def makeExtension(extName, fileExt, lib_dir): """Generate an Extension object from its dotted name.""" extPath = extName.replace(".", os.path.sep) + fileExt print("Found " + extName + " extension...") return Extension( extName, [extPath], # include_dirs=[numpy.get_include()], language="c", # library_dirs=[], libraries=["fftw3", "m", "blas", "lapack"], extra_objects=[os.path.join(lib_dir, "libltfat.a"), os.path.join(lib_dir, "libltfatf.a")], ) ###################### # Custom clean command ###################### class m_clean(clean): """ Remove build directories, and compiled file in the source tree""" def run(self): clean.run(self) if os.path.exists('build'): shutil.rmtree('build') if os.path.exists('doc' + os.path.sep + '_build'): shutil.rmtree('doc' + os.path.sep + '_build') for dirpath, dirnames, filenames in os.walk('.'): for filename in filenames: if (filename.endswith('.so') or filename.endswith('.pyd') or filename.endswith('.dll') or filename.endswith('.pyc')): os.unlink(os.path.join(dirpath, filename)) for dirname in dirnames: if dirname == '__pycache__': shutil.rmtree(os.path.join(dirpath, dirname)) ############################## # Custom sdist command ############################## class m_sdist(sdist): """ Build source package WARNING : The stamping must be done on an default utf8 machine ! """ def run(self): if USE_COPYRIGHT: writeStamp() sdist.run(self) # eraseStamp() else: sdist.run(self) #################### # Setup method #################### def setup_package(): """ Setup function""" # set version VERSION = get_version() lib_dir = os.path.join('ltfat_C_kernel', 'lib') ltfat_dir = 'ltfatpy' set_version(ltfat_dir, get_version()) # get the list of extensions extNames = findpyxfiles(ltfat_dir) # and build up the set of Extension objects if USE_CYTHON: fileExt = ".pyx" else: fileExt = ".c" extensions = [makeExtension(name, fileExt, lib_dir) for name in extNames] setup(name="ltfatpy", version=VERSION, description='The Large Time-Frequency Toolbox (LTFAT) in Python', long_description=(read('README.rst') + '\n\n' + read('HISTORY.rst') + '\n\n' + read('AUTHORS.rst')), packages=find_packages(), package_data={'ltfatpy.signals': ['*.wav'], 'ltfatpy.comp': ['*.pxd'], 'ltfatpy.tests.datasets': ['*.mat']}, url="https://gitlab.lis-lab.fr/dev/ltfatpy", license='GNU GPL V3', author='Denis Arrivault and Florent Jaillet', author_email='contact.dev@lis-lab.fr ', ext_modules=extensions, test_suite='nose.collector', tests_require=['nose', 'coverage'], cmdclass={'build_ext': m_build_ext, 'clean': m_clean, 'sdist': m_sdist}, classifiers=['Development Status :: 5 - Production/Stable', 'Intended Audience :: Science/Research', 'Intended Audience :: End Users/Desktop', 'Intended Audience :: Developers', 'Natural Language :: English', 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 'Operating System :: MacOS :: MacOS X', 'Operating System :: POSIX :: Linux', 'Programming Language :: C', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.4', 'Topic :: Scientific/Engineering :: Mathematics', 'Topic :: Scientific/Engineering' ], install_requires=['scipy>=0.18', 'numpy>=1.8', 'matplotlib>=1.4', 'six>=1.10'], ) if __name__ == "__main__": setup_package()