setup.py 12 KB
Newer Older
eric pellegrini's avatar
eric pellegrini committed
1
2
3
4
5
6
7
import fnmatch
import glob
import os
import sys

import numpy

eric pellegrini's avatar
eric pellegrini committed
8
from Cython.Distutils import build_ext as cython_build_ext
eric pellegrini's avatar
eric pellegrini committed
9
10

from distutils.command.build import build
eric pellegrini's avatar
eric pellegrini committed
11
from distutils.core import setup, Extension
eric pellegrini's avatar
eric pellegrini committed
12
13
14
from distutils.sysconfig import get_config_vars
from distutils.util import convert_path

eric pellegrini's avatar
eric pellegrini committed
15
16
17
18
19
20
21
22
23
24
try:
    import sphinx
except ImportError:
    sphinx = None

try:
    import stdeb
except ImportError:
    stdeb = None

eric pellegrini's avatar
eric pellegrini committed
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
134
135
136
137
138
139
#################################
# 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")]

#################################
# 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 = {}
eric pellegrini's avatar
eric pellegrini committed
140
execfile('MDANSE/__pkginfo__.py', {}, PACKAGE_INFO)
eric pellegrini's avatar
eric pellegrini committed
141

eric pellegrini's avatar
eric pellegrini committed
142
PACKAGES = find_packages(path=".")
eric pellegrini's avatar
eric pellegrini committed
143
144
145
146
147
148
PACKAGES = PACKAGES.keys()

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

149
150
# 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
151
152
153
154
155
156

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

DATA_FILES = []
eric pellegrini's avatar
eric pellegrini committed
157
DATA_FILES.extend(find_data('Doc',exclude=[],prefix='conf_'))
eric pellegrini's avatar
eric pellegrini committed
158
159
160
161
162

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

163
164
SCRIPTS_PATH = "Scripts"
SCRIPTS = glob.glob(os.path.join(SCRIPTS_PATH,'mdanse*'))
eric pellegrini's avatar
eric pellegrini committed
165

166
167
168
169
#################################
# Documentation
#################################

eric pellegrini's avatar
eric pellegrini committed
170
171
172
if sphinx:
    import sphinx.apidoc
    import sphinx.setup_command
173

eric pellegrini's avatar
eric pellegrini committed
174
175
176
177
178
179
180
    class mdanse_build_doc(sphinx.setup_command.BuildDoc):
                              
        def run(self):
            
            build = self.get_finalized_command('build')
                    
            buildDir = os.path.abspath(build.build_lib)
181

eric pellegrini's avatar
eric pellegrini committed
182
            sys.path.insert(0,buildDir)
183

eric pellegrini's avatar
eric pellegrini committed
184
185
186
            sphinxDir = os.path.join(build.build_base,'sphinx',self.doctype)
                                 
            metadata = self.distribution.metadata
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
            
            # /!\ apidoc.main is deprecated. The API has been broken in sphinx 1.7.0, see https://github.com/sphinx-doc/sphinx/issues/4615
            if int(sphinx.__version__.split(".")[1]) <= 6:
                sphinx.apidoc.main(['',
                                '-F',
                                '--separate',
                                '-H', metadata.name,
                                '-A', metadata.author,
                                '-V', metadata.version,
                                '-R', metadata.version,
                                '-o', sphinxDir,
                                os.path.join(buildDir,'MDANSE'),
                                os.path.join(buildDir,'MDANSE','Externals')])
            else:
                sphinx.apidoc.main('', [
eric pellegrini's avatar
eric pellegrini committed
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
                                '-F',
                                '--separate',
                                '-H', metadata.name,
                                '-A', metadata.author,
                                '-V', metadata.version,
                                '-R', metadata.version,
                                '-o', sphinxDir,
                                os.path.join(buildDir,'MDANSE'),
                                os.path.join(buildDir,'MDANSE','Externals')])
            curDir = os.getcwd()
                 
            import shutil
            shutil.copy(os.path.join(curDir,'Doc','conf_%s.py' % self.doctype),os.path.join(sphinxDir,'conf.py'))
            shutil.copy(os.path.join(curDir,'Doc','mdanse_logo.png'),os.path.join(sphinxDir,'_static'))
            shutil.copy(os.path.join(curDir,'Doc','layout.html'),os.path.join(sphinxDir,'_templates'))
     
            # The directory where the rst files are located.
            self.source_dir = sphinxDir
            # The directory where the conf.py file is located.
            self.config_dir = self.source_dir
     
            # The directory where the documentation will be built
            self.build_dir = os.path.join(buildDir,'MDANSE','Doc',self.doctype)
            
            self.finalize_options()
                                                     
            sphinx.setup_command.BuildDoc.run(self)
                 
            sys.path.pop(0)
            
    class mdanse_build_help(mdanse_build_doc):
233
        
eric pellegrini's avatar
eric pellegrini committed
234
        doctype = 'help'
235

eric pellegrini's avatar
eric pellegrini committed
236
    class mdanse_build_api(mdanse_build_doc):
237
        
eric pellegrini's avatar
eric pellegrini committed
238
        doctype = 'api'
239

eric pellegrini's avatar
eric pellegrini committed
240
241
242
#################################
# Debian packaging
#################################
243

eric pellegrini's avatar
eric pellegrini committed
244
class mdanse_build(build):
245

eric pellegrini's avatar
eric pellegrini committed
246
247
248
249
250
251
252
253
    def has_sphinx(self):
        if sphinx is None:
            return False
        setup_dir = os.path.dirname(os.path.abspath(__file__))
        return os.path.isdir(os.path.join(setup_dir, 'Doc'))
    
    sub_commands = build.sub_commands + [('build_api', has_sphinx),('build_help',has_sphinx)]
                        
eric pellegrini's avatar
eric pellegrini committed
254
255
256
257
258
259
260
261
#################################
# 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')

262
EXTENSIONS = [Extension('MDANSE.Extensions.distance_histogram',
eric pellegrini's avatar
eric pellegrini committed
263
264
                        include_dirs=INCLUDE_DIR,
                        sources = [os.path.join("Extensions",'distance_histogram.pyx')]),
265
              Extension('MDANSE.Extensions.fast_calculation',
eric pellegrini's avatar
eric pellegrini committed
266
267
                        include_dirs=INCLUDE_DIR,
                        sources = [os.path.join("Extensions",'fast_calculation.pyx')]),
268
              Extension('MDANSE.Extensions.sas_fast_calc',
eric pellegrini's avatar
eric pellegrini committed
269
270
                        include_dirs=INCLUDE_DIR,
                        sources = [os.path.join("Extensions",'sas_fast_calc.pyx')]),
271
              Extension('MDANSE.Extensions.mt_fast_calc',
eric pellegrini's avatar
eric pellegrini committed
272
273
                        include_dirs=INCLUDE_DIR,
                        sources = [os.path.join("Extensions",'mt_fast_calc.pyx')]),
274
              Extension('MDANSE.Extensions.sd_fast_calc',
eric pellegrini's avatar
eric pellegrini committed
275
276
                        include_dirs=INCLUDE_DIR,
                        sources = [os.path.join("Extensions",'sd_fast_calc.pyx')]),
277
              Extension('MDANSE.Extensions.mic_fast_calc', 
eric pellegrini's avatar
eric pellegrini committed
278
279
280
                        include_dirs=INCLUDE_DIR,
                        sources = [os.path.join("Extensions",'mic_fast_calc.pyx')],
                        language="c++"),
281
              Extension('MDANSE.Extensions.qhull',
eric pellegrini's avatar
eric pellegrini committed
282
283
                        include_dirs  = QHULL_INCLUDE_DIR,
                        sources =  glob.glob(os.path.join(QHULL_DIR, 'src','*.c')) + [os.path.join("Extensions",'qhull.pyx')],
284
285
                        define_macros = [('qh_QHpointer','1')]),
              Extension('MDANSE.Extensions.xtc',
286
                        include_dirs=[numpy.get_include(),os.path.join('Extensions','xtc','include')],
287
                        sources=glob.glob(os.path.join('Extensions','xtc','src','*.c')) + [os.path.join('Extensions','xtc','xtc.pyx')])
eric pellegrini's avatar
eric pellegrini committed
288
289
              ]

eric pellegrini's avatar
eric pellegrini committed
290
291
CMDCLASS = {'build'     : mdanse_build,
            'build_ext' : cython_build_ext}
eric pellegrini's avatar
eric pellegrini committed
292

eric pellegrini's avatar
eric pellegrini committed
293
294
295
if sphinx:
    CMDCLASS['build_api'] = mdanse_build_api
    CMDCLASS['build_help'] = mdanse_build_help
eric pellegrini's avatar
eric pellegrini committed
296
297
298
299
300
             
#################################
# The setup section
#################################

301
setup (name             = "MDANSE",
eric pellegrini's avatar
eric pellegrini committed
302
       version          = PACKAGE_INFO["__version__"],
eric pellegrini's avatar
eric pellegrini committed
303
304
305
306
307
308
309
310
       description      = PACKAGE_INFO["__description__"],
       long_description = PACKAGE_INFO["__long_description__"],
       author           = PACKAGE_INFO["__author__"],
       author_email     = PACKAGE_INFO["__author_email__"],
       maintainer       = PACKAGE_INFO["__maintainer__"],
       maintainer_email = PACKAGE_INFO["__maintainer_email__"],
       url              = PACKAGE_INFO["__url__"],
       license          = PACKAGE_INFO["__license__"],
eric pellegrini's avatar
eric pellegrini committed
311
312
313
314
315
316
       packages         = PACKAGES,
       package_data     = PACKAGE_DATA,
       data_files       = DATA_FILES,
       platforms        = ['Unix','Windows'],
       ext_modules      = EXTENSIONS,
       scripts          = SCRIPTS,
317
       cmdclass         = CMDCLASS,
eric pellegrini's avatar
eric pellegrini committed
318
       install_requires = ['Jinja2'])