setup.py 9.71 KB
Newer Older
eric pellegrini's avatar
eric pellegrini committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
import fnmatch
import glob
import os
import sys

import numpy

from Cython.Distutils import build_ext

from distutils.core import setup, Extension
from distutils.command.build import build
from distutils.command.build_py import build_py
from distutils.command.build_scripts import build_scripts 
from distutils.sysconfig import get_config_vars
from distutils.util import convert_path

#################################
# Modules variables
#################################
EXCLUDE = ['*.py', '*.pyc', '*$py.class', '*~', '.*', '*.bak', '*.so', '*.pyd']

EXCLUDE_DIRECTORIES = ('.*', 'CVS', '_darcs', './build','*svn','./dist', 'EGG-INFO', '*.egg-info')

EXTENSIONS_PATH = "Extensions"

INCLUDE_DIR = [numpy.get_include()]

QHULL_DIR = os.path.join("Extensions","qhull_lib")

QHULL_INCLUDE_DIR = INCLUDE_DIR + [EXTENSIONS_PATH] + [os.path.join(QHULL_DIR,"ext")] + [os.path.join(QHULL_DIR,"src")]

SCRIPTS_PATH = "Scripts"

#################################
# Helper function
#################################

def is_package(path):
    return (os.path.isdir(path) and os.path.isfile(os.path.join(path, '__init__.py')))

def find_packages(path, base="", exclude=None):

    packages = {}

    for item in os.listdir(path):
        d = os.path.join(path, item)
        if exclude is not None and (os.path.abspath(d) == os.path.abspath(exclude)):
            continue
        if is_package(d):
            if base:
                module_name = "%(base)s.%(item)s" % vars()
            else:
                module_name = item
            packages[module_name] = d
            packages.update(find_packages(d, module_name, exclude))
            
    return packages

def find_package_data(where='.', package='', exclude=EXCLUDE, exclude_directories=EXCLUDE_DIRECTORIES, only_in_packages=True, show_ignored=False):
    
    out = {}
    stack = [(convert_path(where), '', package, only_in_packages)]
    while stack:
        where, prefix, package, only_in_packages = stack.pop(0)
        for name in os.listdir(where):
            fn = os.path.join(where, name)
            if os.path.isdir(fn):
                bad_name = False
                for pattern in exclude_directories:
                    if (fnmatch.fnmatchcase(name, pattern)
                        or fn.lower() == pattern.lower()):
                        bad_name = True
                        if show_ignored:
                            print >> sys.stderr, ("Directory %s ignored by pattern %s" % (fn, pattern))
                        break
                if bad_name:
                    continue
                if (os.path.isfile(os.path.join(fn, '__init__.py')) and not prefix):
                    if not package:
                        new_package = name
                    else:
                        new_package = package + '.' + name
                    stack.append((fn, '', new_package, False))
                else:
                    stack.append((fn, prefix + name + '/', package, only_in_packages))
            elif package or not only_in_packages:
                # is a file
                bad_name = False
                for pattern in exclude:
                    if (fnmatch.fnmatchcase(name, pattern)
                        or fn.lower() == pattern.lower()):
                        bad_name = True
                        if show_ignored:
                            print >> sys.stderr, ("File %s ignored by pattern %s" % (fn, pattern))
                        break
                if bad_name:
                    continue
                out.setdefault(package, []).append(prefix+name)
    
    return out


def find_data(where=".", exclude=EXCLUDE, exclude_directories=EXCLUDE_DIRECTORIES, prefix=""):

    out = {}
    stack = [convert_path(where)]
    while stack:
        where = stack.pop(0)
        for name in os.listdir(where):
            fn = os.path.join(where, name)
            d = os.path.join(prefix,os.path.dirname(fn))
            if os.path.isdir(fn):
                stack.append(fn)
            else:
                bad_name = False
                for pattern in exclude:
                    if (fnmatch.fnmatchcase(name, pattern) or fn.lower() == pattern.lower()):
                        bad_name = True
                        break
                if bad_name:
                    continue
                out.setdefault(d, []).append(fn)
            
    out = [(k,v) for k, v in out.items()]
    
    return out


#################################
# Packages section
#################################

PACKAGE_INFO = {}
134
execfile('MDANSE/__pkginfo__.py', PACKAGE_INFO)
eric pellegrini's avatar
eric pellegrini committed
135

136
PACKAGES = find_packages(path=".", exclude=os.path.join("MDANSE","App","GUI"))
eric pellegrini's avatar
eric pellegrini committed
137 138 139 140 141 142
PACKAGES = PACKAGES.keys()

#################################
# Package data section
#################################

143 144
# Retrieve all the data related to the MDANSE package.
PACKAGE_DATA = find_package_data(where='MDANSE', package='MDANSE', show_ignored=False)
eric pellegrini's avatar
eric pellegrini committed
145 146 147 148 149 150 151 152 153 154 155 156

#################################
# User data section
#################################

DATA_FILES = []

#################################
# Scripts section
#################################

SCRIPTS = []
157
SCRIPTS.append(os.path.join(SCRIPTS_PATH,'mdanse'))
eric pellegrini's avatar
eric pellegrini committed
158 159 160 161 162 163 164 165 166

#################################
# Extensions section
#################################

if 'linux' in sys.platform:
    (opt,) = get_config_vars('OPT')
    os.environ['OPT'] = " ".join(flag for flag in opt.split() if flag != '-Wstrict-prototypes')

167
EXTENSIONS = [Extension('MDANSE.Extensions.distance_histogram',
eric pellegrini's avatar
eric pellegrini committed
168 169
                        include_dirs=INCLUDE_DIR,
                        sources = [os.path.join("Extensions",'distance_histogram.pyx')]),
170
              Extension('MDANSE.Extensions.fast_calculation',
eric pellegrini's avatar
eric pellegrini committed
171 172
                        include_dirs=INCLUDE_DIR,
                        sources = [os.path.join("Extensions",'fast_calculation.pyx')]),
173
              Extension('MDANSE.Extensions.sas_fast_calc',
eric pellegrini's avatar
eric pellegrini committed
174 175
                        include_dirs=INCLUDE_DIR,
                        sources = [os.path.join("Extensions",'sas_fast_calc.pyx')]),
176
              Extension('MDANSE.Extensions.mt_fast_calc',
eric pellegrini's avatar
eric pellegrini committed
177 178
                        include_dirs=INCLUDE_DIR,
                        sources = [os.path.join("Extensions",'mt_fast_calc.pyx')]),
179
              Extension('MDANSE.Extensions.sd_fast_calc',
eric pellegrini's avatar
eric pellegrini committed
180 181
                        include_dirs=INCLUDE_DIR,
                        sources = [os.path.join("Extensions",'sd_fast_calc.pyx')]),
182
              Extension('MDANSE.Extensions.mic_fast_calc', 
eric pellegrini's avatar
eric pellegrini committed
183 184 185
                        include_dirs=INCLUDE_DIR,
                        sources = [os.path.join("Extensions",'mic_fast_calc.pyx')],
                        language="c++"),
186
              Extension('MDANSE.Extensions.qhull',
eric pellegrini's avatar
eric pellegrini committed
187 188 189 190 191 192 193 194 195 196 197 198
                        include_dirs  = QHULL_INCLUDE_DIR,
                        sources =  glob.glob(os.path.join(QHULL_DIR, 'src','*.c')) + [os.path.join("Extensions",'qhull.pyx')],
                        define_macros = [('qh_QHpointer','1')])
              ]

class ModifiedBuildScripts(build_scripts):
    
    def finalize_options (self):

        build_scripts.finalize_options(self)

        if self.distribution.command_obj['build'].gui:
199
            self.scripts.append(os.path.join(SCRIPTS_PATH,'mdanse_gui'))
eric pellegrini's avatar
eric pellegrini committed
200 201 202 203 204 205 206 207 208
                    

class ModifiedBuildPy(build_py):

    def finalize_options(self):

        build_py.finalize_options(self)

        if self.distribution.command_obj['build'].gui:
209 210
            self.packages.append('MDANSE.App.GUI')
            self.packages.extend(find_packages(path=os.path.join("MDANSE","App","GUI"), base="MDANSE.App.GUI").keys())
eric pellegrini's avatar
eric pellegrini committed
211 212 213 214 215 216
             
        self.data_files = self.get_data_files()


class ModifiedBuild(build):
    
217 218
    user_options = build.user_options + [('gui',None,'Build MDANSE with GUI [default]'),
                                         ('no-gui', None, "Build MDANSE without GUI")]
eric pellegrini's avatar
eric pellegrini committed
219 220 221 222 223 224 225 226 227 228 229 230 231 232
    
    boolean_options = build.boolean_options + ['gui']

    negative_opt = {'no-gui' : 'gui'}

    def initialize_options(self):
        build.initialize_options(self)
        self.gui = 1
 
         
#################################
# The setup section
#################################

233
setup (name             = "MDANSE",
eric pellegrini's avatar
eric pellegrini committed
234 235 236
       version          = PACKAGE_INFO["__version__"],
       description      = "Analysis of Molecular Dynamics trajectories",
       long_description =
237
"""MDANSE is an interactive program for the analysis of Molecular
eric pellegrini's avatar
eric pellegrini committed
238 239 240 241 242 243 244
Dynamics simulations. It is especially designed for the computation
and decomposition of neutron scattering spectra. The structure and
dynamics of the simulated systems can be characterized in terms of
various space and time correlation functions. To analyze the dynamics
of complex systems, rigid-body motions of arbitrarily chosen molecular
subunits can be studied.
""",
245 246
       author           = "B. Aoun & G. Goret & E. Pellegrini",
       author_email     = "aoun.ill.fr, goretg@ill.fr, pellegrini@ill.fr",
eric pellegrini's avatar
eric pellegrini committed
247 248
       maintainer       = "B. Aoun, G. Goret, E. Pellegrini",
       maintainer_email = "aoun.ill.fr, goretg.ill.fr, pellegrini@ill.fr",
249
       url              = "https://github.com/eurydyce/MDANSE/tree/master/MDANSE",
eric pellegrini's avatar
eric pellegrini committed
250 251 252 253 254 255 256 257 258 259 260 261
       license          = "CeCILL",
       packages         = PACKAGES,
       package_data     = PACKAGE_DATA,
       data_files       = DATA_FILES,
       platforms        = ['Unix','Windows'],
       ext_modules      = EXTENSIONS,
       scripts          = SCRIPTS,
        cmdclass         = {'build_ext'     : build_ext,
                            'build'         : ModifiedBuild,
                            'build_py'      : ModifiedBuildPy,
                            'build_scripts' : ModifiedBuildScripts}
       )