source: orange/setup.py @ 11692:356c325c0efb

Revision 11692:356c325c0efb, 30.9 KB checked in by Ales Erjavec <ales.erjavec@…>, 8 months ago (diff)

Removed 'Earth' code from Orange (moved to 'orangecontrib.earth' package).

  • Property exe set to *
Line 
1#!/usr/bin/env python2
2
3try:
4    import distribute_setup
5    # require distutils >= 0.6.26 or setuptools >= 0.7
6    distribute_setup.use_setuptools(version='0.6.26')
7except ImportError:
8    # For documentation we load setup.py to get version
9    # so it does not matter if importing fails
10    pass
11
12import glob, os, sys, types
13from distutils import log
14from distutils.command.build import build
15from distutils.command.build_ext import build_ext
16from distutils.command.install_lib import install_lib
17from distutils.dep_util import newer_group
18from distutils.errors import DistutilsSetupError
19from distutils.file_util import copy_file
20from distutils.msvccompiler import MSVCCompiler
21from distutils.unixccompiler import UnixCCompiler
22from distutils.util import convert_path
23from distutils.sysconfig import get_python_inc, get_config_var
24import subprocess
25from subprocess import check_call
26from collections import namedtuple
27from ConfigParser import SafeConfigParser
28
29from setuptools import setup, find_packages
30from setuptools.command.install import install
31
32# Has to be last import as it seems something is changing it somewhere
33from distutils.extension import Extension
34
35NAME = 'Orange'
36
37VERSION = '2.7.2'
38ISRELEASED = False
39
40DESCRIPTION = 'Orange, a component-based data mining framework.'
41LONG_DESCRIPTION = open(os.path.join(os.path.dirname(__file__), 'README.txt')).read()
42AUTHOR = 'Bioinformatics Laboratory, FRI UL'
43AUTHOR_EMAIL = 'contact@orange.biolab.si'
44URL = 'http://orange.biolab.si/'
45DOWNLOAD_URL = 'https://bitbucket.org/biolab/orange/downloads'
46LICENSE = 'GPLv3'
47
48KEYWORDS = (
49    'data mining',
50    'machine learning',
51    'artificial intelligence',
52)
53
54CLASSIFIERS = (
55    'Development Status :: 4 - Beta',
56    'Environment :: X11 Applications :: Qt',
57    'Environment :: Console',
58    'Environment :: Plugins',
59    'Programming Language :: Python',
60    'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
61    'Operating System :: POSIX',
62    'Operating System :: Microsoft :: Windows',
63    'Topic :: Scientific/Engineering :: Artificial Intelligence',
64    'Topic :: Scientific/Engineering :: Visualization',
65    'Topic :: Software Development :: Libraries :: Python Modules',
66    'Intended Audience :: Education',
67    'Intended Audience :: Science/Research',
68    'Intended Audience :: Developers',
69)
70
71try:
72    import numpy
73    numpy_include_dir = numpy.get_include()
74except ImportError:
75    # When setup.py is first run to install orange, numpy can still be missing
76    pass
77    numpy_include_dir = None
78
79python_include_dir = get_python_inc(plat_specific=1)
80
81include_dirs = [python_include_dir, numpy_include_dir, 'source/include']
82
83if sys.platform == 'darwin':
84    extra_compile_args = '-fPIC -fno-common -w -DDARWIN'.split()
85    extra_link_args = '-headerpad_max_install_names -undefined dynamic_lookup'.split()
86elif sys.platform == 'win32':
87    extra_compile_args = ['-EHsc']
88    extra_link_args = []
89elif sys.platform.startswith('linux'):
90    extra_compile_args = '-fPIC -w -DLINUX'.split()
91    extra_link_args = ['-Wl,-R$ORIGIN']
92else:
93    extra_compile_args = []
94    extra_link_args = []
95
96lib_cfg = namedtuple(
97    "lib_cfg", ["libraries", "library_dirs", "include_dirs"])
98
99site_cfg = namedtuple(
100    "site_cfg", ["libsvm", "liblinear", "blas", "qhull"])
101
102
103def libs_parse(text):
104    return [lib.strip() for lib in text.strip().split()]
105
106
107def dirs_parse(text):
108    return text.strip().split(os.path.pathsep)
109
110
111def parse_lib_opt(parser, section):
112    libs, library_dirs, include_dirs = [], [], []
113
114    if parser.has_option(section, "libraries"):
115        libs = libs_parse(parser.get(section, "libraries"))
116    elif parser.has_option(section, "library"):
117        libs = libs_parse(parser.get(section, "library"))
118
119    if parser.has_option(section, "library_dirs"):
120        library_dirs = \
121            dirs_parse(parser.get(section, "library_dirs"))
122
123    if parser.has_option(section, "include_dirs"):
124        include_dirs = dirs_parse(parser.get(section, "include_dirs"))
125
126    if libs or library_dirs or include_dirs:
127        return lib_cfg(libs, library_dirs, include_dirs)
128    else:
129        return None
130
131
132def site_config():
133    """Return the parsed site configuration.
134    """
135    parser = SafeConfigParser()
136    parser.read(["setup-site.cfg",
137                 os.path.expanduser("~/.orange-site.cfg")])
138
139    libsvm = parse_lib_opt(parser, "libsvm")
140    liblinear = parse_lib_opt(parser, "liblinear")
141    blas = parse_lib_opt(parser, "blas")
142    qhull = parse_lib_opt(parser, "qhull")
143
144    return site_cfg(libsvm, liblinear, blas, qhull)
145
146
147# Get the command for building orangeqt extension from
148# source/orangeqt/setup.py file.
149# Fails without PyQt4.
150import imp
151try:
152    orangeqt_setup = imp.load_source('orangeqt_setup', os.path.join(os.path.dirname(__file__), 'source/orangeqt/setup.py'))
153    build_pyqt_ext = orangeqt_setup.build_pyqt_ext
154except ImportError:
155    orangeqt_setup = None
156    build_pyqt_ext = None
157
158class LibStatic(Extension):
159    pass
160
161class PyXtractExtension(Extension):
162    def __init__(self, *args, **kwargs):
163        for name, default in [("extra_pyxtract_cmds", []), ("lib_type", "dynamic")]:
164            setattr(self, name, kwargs.get(name, default))
165            if name in kwargs:
166                del kwargs[name]
167
168        Extension.__init__(self, *args, **kwargs)
169
170class PyXtractSharedExtension(PyXtractExtension):
171    pass
172
173class pyxtract_build_ext(build_ext):
174    def run_pyxtract(self, ext, dir):
175        original_dir = os.path.realpath(os.path.curdir)
176        log.info("running pyxtract for %s" % ext.name)
177        try:
178            os.chdir(dir)
179            ## we use the commands which are used for building under windows
180            pyxtract_cmds = [cmd.split() for cmd in getattr(ext, "extra_pyxtract_cmds", [])]
181            if os.path.exists("_pyxtract.bat"):
182                pyxtract_cmds.extend([cmd.split()[1:] for cmd in open("_pyxtract.bat").read().strip().splitlines()])
183            for cmd in pyxtract_cmds:
184                log.info(" ".join([sys.executable] + cmd))
185                check_call([sys.executable] + cmd)
186            if pyxtract_cmds:
187                ext.include_dirs.append(os.path.join(dir, "ppp"))
188                ext.include_dirs.append(os.path.join(dir, "px"))
189
190        finally:
191            os.chdir(original_dir)
192
193    def finalize_options(self):
194        build_ext.finalize_options(self)
195        # add the build_lib dir and build_temp (for
196        # liborange_include and liborange linking)
197        if not self.inplace:
198            # for linking with liborange.so (it is in Orange package)
199            self.library_dirs.append(os.path.join(self.build_lib, "Orange"))
200            # for linking with liborange_include.a
201            self.library_dirs.append(self.build_temp)
202        else:
203            # for linking with liborange.so
204            self.library_dirs.append("./Orange") 
205            # for linking with liborange_include.a
206            self.library_dirs.append(self.build_temp)
207
208    def build_extension(self, ext):
209        if isinstance(ext, LibStatic):
210            # Build static library
211            self.build_static(ext)
212        elif isinstance(ext, PyXtractExtension):
213            # Build pyextract extension
214            self.build_pyxtract(ext)
215        elif orangeqt_setup and isinstance(ext, orangeqt_setup.PyQt4Extension):
216            # Skip the build (will be handled by build_pyqt_ext command)
217            return
218        else:
219            build_ext.build_extension(self, ext)
220
221        if isinstance(ext, PyXtractSharedExtension):
222            # Fix extension modules so they can be linked
223            # by other modules
224            if self.dry_run:
225                # No need to do anything here.
226                return
227
228            if isinstance(self.compiler, MSVCCompiler):
229                # Copy ${TEMP}/orange/orange.lib to ${BUILD}/orange.lib
230                ext_fullpath = self.get_ext_fullpath(ext.name)
231                # Get the last component of the name
232                ext_name = ext.name.rsplit(".", 1)[-1]
233                libs = glob.glob(os.path.join(self.build_temp,
234                                              "*", "*", ext_name + ".lib"))
235                if not libs:
236                    log.info("Could not locate library %r in directory %r" \
237                             % (ext_name, self.build_temp))
238                else:
239                    lib = libs[0]
240                    lib_path = os.path.splitext(ext_fullpath)[0] + ".lib"
241                    copy_file(lib, lib_path, dry_run=self.dry_run)
242            else:
243                # Make lib{name}.so link to {name}.so
244                ext_path = self.get_ext_fullpath(ext.name)
245                ext_path, ext_filename = os.path.split(ext_path)
246                realpath = os.path.realpath(os.curdir)
247                try:
248                    os.chdir(ext_path)
249                    # Get the shared library name
250                    _, name = ext.name.rsplit(".", 1)
251                    lib_filename = self.compiler.library_filename(name, lib_type="shared")
252                    # Create the link
253                    copy_file(ext_filename, lib_filename, link="sym",
254                              dry_run=self.dry_run)
255                except OSError, ex:
256                    log.info("failed to create shared library for %s: %s" % (ext.name, str(ex)))
257                finally:
258                    os.chdir(realpath)
259
260    def build_pyxtract(self, ext):
261        ## mostly copied from build_extension
262        sources = ext.sources
263        if sources is None or type(sources) not in (types.ListType, types.TupleType):
264            raise DistutilsSetupError, \
265                  ("in 'ext_modules' option (extension '%s'), " +
266                   "'sources' must be present and must be " +
267                   "a list of source filenames") % ext.name
268        sources = list(sources)
269
270        ext_path = self.get_ext_fullpath(ext.name)
271
272        depends = sources + ext.depends
273        if not (self.force or newer_group(depends, ext_path, 'newer')):
274            log.debug("skipping '%s' extension (up-to-date)", ext.name)
275            return
276        else:
277            log.info("building '%s' extension", ext.name)
278
279        # First, scan the sources for SWIG definition files (.i), run
280        # SWIG on 'em to create .c files, and modify the sources list
281        # accordingly.
282        sources = self.swig_sources(sources, ext)
283
284        # Run pyxtract in dir this adds ppp and px dirs to include_dirs
285        dir = os.path.commonprefix([os.path.split(s)[0] for s in ext.sources])
286        self.run_pyxtract(ext, dir)
287
288        # Next, compile the source code to object files.
289
290        # XXX not honouring 'define_macros' or 'undef_macros' -- the
291        # CCompiler API needs to change to accommodate this, and I
292        # want to do one thing at a time!
293
294        # Two possible sources for extra compiler arguments:
295        #   - 'extra_compile_args' in Extension object
296        #   - CFLAGS environment variable (not particularly
297        #     elegant, but people seem to expect it and I
298        #     guess it's useful)
299        # The environment variable should take precedence, and
300        # any sensible compiler will give precedence to later
301        # command line args.  Hence we combine them in order:
302        extra_args = ext.extra_compile_args or []
303
304        macros = ext.define_macros[:]
305        for undef in ext.undef_macros:
306            macros.append((undef,))
307
308        objects = self.compiler.compile(sources,
309                                         output_dir=self.build_temp,
310                                         macros=macros,
311                                         include_dirs=ext.include_dirs,
312                                         debug=self.debug,
313                                         extra_postargs=extra_args,
314                                         depends=ext.depends)
315
316        # XXX -- this is a Vile HACK!
317        #
318        # The setup.py script for Python on Unix needs to be able to
319        # get this list so it can perform all the clean up needed to
320        # avoid keeping object files around when cleaning out a failed
321        # build of an extension module.  Since Distutils does not
322        # track dependencies, we have to get rid of intermediates to
323        # ensure all the intermediates will be properly re-built.
324        #
325        self._built_objects = objects[:]
326
327        # Now link the object files together into a "shared object" --
328        # of course, first we have to figure out all the other things
329        # that go into the mix.
330        if ext.extra_objects:
331            objects.extend(ext.extra_objects)
332        extra_args = ext.extra_link_args or []
333
334        # Detect target language, if not provided
335        language = ext.language or self.compiler.detect_language(sources)
336
337        self.compiler.link_shared_object(
338            objects, ext_path,
339            libraries=self.get_libraries(ext),
340            library_dirs=ext.library_dirs,
341            runtime_library_dirs=ext.runtime_library_dirs,
342            extra_postargs=extra_args,
343            export_symbols=self.get_export_symbols(ext),
344            debug=self.debug,
345            build_temp=self.build_temp,
346            target_lang=language)
347
348
349    def build_static(self, ext):
350        ## mostly copied from build_extension, changed
351        sources = ext.sources
352        if sources is None or type(sources) not in (types.ListType, types.TupleType):
353            raise DistutilsSetupError, \
354                  ("in 'ext_modules' option (extension '%s'), " +
355                   "'sources' must be present and must be " +
356                   "a list of source filenames") % ext.name
357        sources = list(sources)
358
359        # Static libs get build in the build_temp directory
360        output_dir = self.build_temp
361        if not os.path.exists(output_dir): #VSC fails if the dir does not exist
362            os.makedirs(output_dir)
363
364        lib_filename = self.compiler.library_filename(ext.name, lib_type='static', output_dir=output_dir)
365
366        depends = sources + ext.depends
367        if not (self.force or newer_group(depends, lib_filename, 'newer')):
368            log.debug("skipping '%s' extension (up-to-date)", ext.name)
369            return
370        else:
371            log.info("building '%s' extension", ext.name)
372
373        # First, scan the sources for SWIG definition files (.i), run
374        # SWIG on 'em to create .c files, and modify the sources list
375        # accordingly.
376        sources = self.swig_sources(sources, ext)
377
378        # Next, compile the source code to object files.
379
380        # XXX not honouring 'define_macros' or 'undef_macros' -- the
381        # CCompiler API needs to change to accommodate this, and I
382        # want to do one thing at a time!
383
384        # Two possible sources for extra compiler arguments:
385        #   - 'extra_compile_args' in Extension object
386        #   - CFLAGS environment variable (not particularly
387        #     elegant, but people seem to expect it and I
388        #     guess it's useful)
389        # The environment variable should take precedence, and
390        # any sensible compiler will give precedence to later
391        # command line args.  Hence we combine them in order:
392        extra_args = ext.extra_compile_args or []
393
394        macros = ext.define_macros[:]
395        for undef in ext.undef_macros:
396            macros.append((undef,))
397
398        objects = self.compiler.compile(sources,
399                                         output_dir=self.build_temp,
400                                         macros=macros,
401                                         include_dirs=ext.include_dirs,
402                                         debug=self.debug,
403                                         extra_postargs=extra_args,
404                                         depends=ext.depends)
405
406        # XXX -- this is a Vile HACK!
407        #
408        # The setup.py script for Python on Unix needs to be able to
409        # get this list so it can perform all the clean up needed to
410        # avoid keeping object files around when cleaning out a failed
411        # build of an extension module.  Since Distutils does not
412        # track dependencies, we have to get rid of intermediates to
413        # ensure all the intermediates will be properly re-built.
414        #
415        self._built_objects = objects[:]
416
417        # Now link the object files together into a "shared object" --
418        # of course, first we have to figure out all the other things
419        # that go into the mix.
420        if ext.extra_objects:
421            objects.extend(ext.extra_objects)
422        extra_args = ext.extra_link_args or []
423
424        # Detect target language, if not provided
425        language = ext.language or self.compiler.detect_language(sources)
426       
427        #first remove old library (ar only appends the contents if archive already exists)
428        try:
429            os.remove(lib_filename)
430        except OSError, ex:
431            log.debug("failed to remove obsolete static library %s: %s" %(ext.name, str(ex)))
432
433        # The static library is created in the temp dir, it is used during the compile step only
434        # it should not be included in the final install
435        self.compiler.create_static_lib(
436            objects, ext.name, output_dir,
437            debug=self.debug,
438            target_lang=language)
439
440    def get_libraries(self, ext):
441        """ Change the 'orange' library name to 'orange_d' if
442        building in debug mode. Using ``get_ext_filename`` to discover if
443        _d postfix is required.
444       
445        """
446        libraries = build_ext.get_libraries(self, ext)
447        if "orange" in libraries and self.debug:
448            filename = self.get_ext_filename("orange")
449            basename = os.path.basename(filename)
450            name, ext = os.path.splitext(basename)
451            if name.endswith("_d"):
452                index = libraries.index("orange")
453                libraries[index] = "orange_d"
454
455        return libraries
456
457    if not hasattr(build_ext, "get_ext_fullpath"):
458        #On mac OS X python 2.6.1 distutils does not have this method
459        def get_ext_fullpath(self, ext_name):
460            """Returns the path of the filename for a given extension.
461           
462            The file is located in `build_lib` or directly in the package
463            (inplace option).
464            """
465            import string
466            # makes sure the extension name is only using dots
467            all_dots = string.maketrans('/' + os.sep, '..')
468            ext_name = ext_name.translate(all_dots)
469            fullname = self.get_ext_fullname(ext_name)
470            modpath = fullname.split('.')
471            filename = self.get_ext_filename(ext_name)
472            filename = os.path.split(filename)[-1]
473            if not self.inplace:
474                # no further work needed
475                # returning :
476                #   build_dir/package/path/filename
477                filename = os.path.join(*modpath[:-1] + [filename])
478                return os.path.join(self.build_lib, filename)
479            # the inplace option requires to find the package directory
480            # using the build_py command for that
481            package = '.'.join(modpath[0:-1])
482            build_py = self.get_finalized_command('build_py')
483            package_dir = os.path.abspath(build_py.get_package_dir(package))
484            # returning
485            #   package_dir/filename
486            return os.path.join(package_dir, filename)
487
488# Add build_pyqt_ext to build subcommands
489class orange_build(build):
490    def has_pyqt_extensions(self):
491        # For now this is disabled unless specifically requested
492        # using build_pyqt_ext command
493        return False
494#        return any([isinstance(ext, orangeqt_setup.PyQt4Extension) \
495#                   for ext in self.distribution.ext_modules]
496#                   )
497
498    sub_commands = build.sub_commands
499    if orangeqt_setup:
500        sub_commands += [("build_pyqt_ext", has_pyqt_extensions)]
501
502
503class orange_install_lib(install_lib):
504    """ An command to install orange (preserves liborange.so -> orange.so symlink)
505    """
506    def run(self):
507        install_lib.run(self)
508
509    def copy_tree(self, infile, outfile, preserve_mode=1, preserve_times=1,
510                  preserve_symlinks=1, level=1):
511        """ Run copy_tree with preserve_symlinks=1 as default
512        """
513        install_lib.copy_tree(self, infile, outfile, preserve_mode,
514                              preserve_times, preserve_symlinks, level)
515
516    def install(self):
517        """ Copy build_dir to install_dir
518        """
519        # A Hack to unlink liborange.so -> orange.so if it already exists,
520        # because copy_tree fails to overwrite it
521        #
522        liborange = os.path.join(self.install_dir, "Orange", "liborange.so")
523        if os.path.exists(liborange) and os.path.islink(liborange):
524            log.info("unlinking %s -> %s", liborange,
525                     os.path.join(self.install_dir, "orange.so"))
526
527            if not self.dry_run:
528                os.unlink(liborange)
529
530        return install_lib.install(self)
531
532
533class orange_install(install):
534    """ A command to install orange while also creating
535    a .pth path to access the old orng* modules and orange,
536    orangeom etc.
537
538    """
539    def run(self):
540        install.run(self)
541        # Create a .pth file with a path inside the Orange/orng directory
542        # so the old modules are importable
543        self.path_file, self.extra_dirs = ("Orange-orng-modules", "Orange/orng")
544        self.extra_dirs = convert_path(self.extra_dirs)
545        log.info("creating portal path for orange compatibility.")
546        self.create_path_file()
547        self.path_file, self.extra_dirs = None, None
548
549
550def get_source_files(path, ext="cpp", exclude=[]):
551    files = glob.glob(os.path.join(path, "*." + ext))
552    files = [file for file in files if os.path.basename(file) not in exclude]
553    return files
554
555# common library statically linked into orange, orangeom, ...
556include_ext = LibStatic(
557    "orange_include",
558    get_source_files("source/include/"),
559    include_dirs=include_dirs,
560    extra_compile_args=extra_compile_args
561)
562
563
564if sys.platform == "win32": # ?? mingw/cygwin
565    libraries = ["orange_include"]
566else:
567    libraries = ["stdc++", "orange_include"]
568
569
570# Custom site configuration
571
572site = site_config()
573
574orange_sources = get_source_files("source/orange/")
575
576orange_include_dirs = list(include_dirs)
577orange_library_dirs = []
578orange_libraries = list(libraries)
579
580if site.blas:
581    # Link external blas library
582    orange_libraries += site.blas.libraries
583    orange_library_dirs += site.blas.library_dirs
584else:
585    orange_sources += get_source_files("source/orange/blas/", "c")
586
587if site.liblinear:
588    # Link external LIBLINEAR library
589    orange_libraries += site.liblinear.libraries
590    orange_include_dirs += site.liblinear.include_dirs
591    orange_library_dirs += site.liblinear.library_dirs
592else:
593    orange_sources += get_source_files("source/orange/liblinear/", "cpp")
594    orange_include_dirs += ["source/orange/liblinear"]
595
596if site.libsvm:
597    # Link external LibSVM library
598    orange_libraries += site.libsvm.libraries
599    orange_include_dirs += site.libsvm.include_dirs
600    orange_library_dirs += site.libsvm.library_dirs
601else:
602    orange_sources += get_source_files("source/orange/libsvm/", "cpp")
603
604
605orange_ext = PyXtractSharedExtension(
606    "Orange.orange",
607    orange_sources,
608    include_dirs=orange_include_dirs,
609    extra_compile_args=extra_compile_args + ["-DORANGE_EXPORTS"],
610    extra_link_args=extra_link_args,
611    libraries=orange_libraries,
612    library_dirs=orange_library_dirs,
613    extra_pyxtract_cmds=["../pyxtract/defvectors.py"],
614)
615
616
617if sys.platform == "darwin":
618    build_shared_cmd = get_config_var("BLDSHARED")
619    # Dont link liborange.so with orangeom and orangene - MacOS X treats
620    # loadable modules and shared libraries different
621    if "-bundle" in build_shared_cmd.split():
622        shared_libs = libraries
623    else:
624        shared_libs = libraries + ["orange"]
625else:
626    shared_libs = libraries + ["orange"]
627
628orangeom_sources = get_source_files(
629    "source/orangeom/", exclude=["lib_vectors.cpp"])
630
631orangeom_libraries = list(shared_libs)
632orangeom_include_dirs = list(include_dirs)
633orangeom_library_dirs = []
634
635
636if site.qhull:
637    # Link external qhull library
638    orangeom_libraries += site.qhull.libraries
639    orangeom_include_dirs += site.qhull.include_dirs
640    orangeom_library_dirs += site.qhull.library_dirs
641else:
642    orangeom_sources += get_source_files("source/orangeom/qhull/", "c")
643    orangeom_include_dirs += ["source/orangeom"]
644
645orangeom_ext = PyXtractExtension(
646    "Orange.orangeom",
647    orangeom_sources,
648    include_dirs=orangeom_include_dirs + ["source/orange/"],
649    extra_compile_args=extra_compile_args + ["-DORANGEOM_EXPORTS"],
650    extra_link_args=extra_link_args,
651    libraries=orangeom_libraries,
652    library_dirs=orangeom_library_dirs
653 )
654
655orangene_ext = PyXtractExtension(
656    "Orange.orangene",
657    get_source_files("source/orangene/", exclude=["lib_vectors.cpp"]),
658    include_dirs=include_dirs + ["source/orange/"],
659    extra_compile_args=extra_compile_args + ["-DORANGENE_EXPORTS"],
660    extra_link_args=extra_link_args,
661    libraries=shared_libs,
662)
663
664corn_ext = Extension(
665    "Orange.corn", get_source_files("source/corn/"),
666    include_dirs=include_dirs + ["source/orange/"],
667    extra_compile_args=extra_compile_args + ["-DCORN_EXPORTS"],
668    extra_link_args=extra_link_args,
669    libraries=libraries
670)
671
672statc_ext = Extension(
673    "Orange.statc", get_source_files("source/statc/"),
674    include_dirs=include_dirs + ["source/orange/"],
675    extra_compile_args=extra_compile_args + ["-DSTATC_EXPORTS"],
676    extra_link_args=extra_link_args,
677    libraries=libraries
678)
679
680
681ext_modules = [include_ext, orange_ext, orangeom_ext,
682               orangene_ext, corn_ext, statc_ext]
683
684cmdclass = {"build": orange_build,
685            "build_ext": pyxtract_build_ext,
686            "install_lib": orange_install_lib,
687            "install": orange_install}
688                   
689if orangeqt_setup:
690    orangeqt_ext = orangeqt_setup.orangeqt_ext
691    # Fix relative paths, name etc.
692    orangeqt_ext.name = "Orange.orangeqt"
693    orangeqt_ext.sources = ["source/orangeqt/orangeqt.sip"] + \
694                           get_source_files("source/orangeqt", "cpp",
695                                exclude=["canvas3d.cpp", "plot3d.cpp", 
696                                         "glextensions.cpp"]
697                                            )
698
699    orangeqt_ext.include_dirs += ["source/orangeqt"]
700
701    ext_modules += [orangeqt_ext]
702
703    cmdclass["build_pyqt_ext"] = build_pyqt_ext
704
705def all_with_extension(path, extensions):
706    return [os.path.join(path, "*.%s"%extension) for extension in extensions]
707
708# TODO: Simply replace with include_package_data = True and configure missed files in MANIFEST.in?
709
710#Marko 20120128: Removed "doc/style.css", "doc/widgets/*/*.*" from the package
711
712def get_package_data():
713    package_data = {
714        "Orange":
715            ["orangerc.cfg" ] +\
716             all_with_extension(path="datasets", extensions=("tab", "csv", "basket")) +\
717             all_with_extension(path="testing/regression/tests_20", extensions=("net", "tab", "basket", "csv")),
718        "Orange.OrangeCanvas": ["icons/*.png", "icons/*.svg",
719                                "orngCanvas.pyw", "WidgetTabs.txt"],
720        "Orange.OrangeCanvas.styles": ["*.qss", "orange/*.svg"],
721        "Orange.OrangeCanvas.application.tutorials": ["*.ows"],
722        "Orange.OrangeWidgets": ["icons/*.png", "icons/backgrounds/*.png",
723                                 "report/index.html"],
724        "Orange.OrangeWidgets.Associate": ["icons/*.png", "icons/*.svg"],
725        "Orange.OrangeWidgets.Classify": ["icons/*.png", "icons/*.svg"],
726        "Orange.OrangeWidgets.Data": ["icons/*.png", "icons/*.svg"],
727        "Orange.OrangeWidgets.Evaluate": ["icons/*.png", "icons/*.svg"],
728        "Orange.OrangeWidgets.Prototypes": ["icons/*.png", "icons/*.svg"],
729        "Orange.OrangeWidgets.Regression": ["icons/*.png", "icons/*.svg"],
730        "Orange.OrangeWidgets.Unsupervised": ["icons/*.png", "icons/*.svg"],
731        "Orange.OrangeWidgets.Visualize": ["icons/*.png", "icons/*.svg"],
732        "Orange.OrangeWidgets.Visualize Qt": ["icons/*.png", "icons/*.svg"],
733        "Orange.OrangeWidgets.plot": ["*.gs", "*.vs"],
734        "Orange.OrangeWidgets.plot.primitives": ["*.obj"],
735    }
736
737    return package_data
738
739def hg_revision():
740    # Copied from numpy setup.py and modified to work with hg
741    def _minimal_ext_cmd(cmd):
742        # construct minimal environment
743        env = {}
744        for k in ['SYSTEMROOT', 'PATH']:
745            v = os.environ.get(k)
746            if v is not None:
747                env[k] = v
748        # LANGUAGE is used on win32
749        env['LANGUAGE'] = 'C'
750        env['LANG'] = 'C'
751        env['LC_ALL'] = 'C'
752        out = subprocess.Popen(cmd, stdout = subprocess.PIPE, env=env).communicate()[0]
753        return out
754
755    try:
756        out = _minimal_ext_cmd(['hg', 'ide', '-i'])
757        HG_REVISION = str(out.strip().decode('ascii'))
758    except OSError:
759        HG_REVISION = "Unknown"
760
761    return HG_REVISION
762
763def write_version_py(filename='Orange/version.py'):
764    # Copied from numpy setup.py
765    cnt = """
766# THIS FILE IS GENERATED FROM ORANGE SETUP.PY
767short_version = '%(version)s'
768version = '%(version)s'
769full_version = '%(full_version)s'
770hg_revision = '%(hg_revision)s'
771release = %(isrelease)s
772
773if not release:
774    version = full_version
775"""
776    FULLVERSION = VERSION
777    if os.path.exists('.hg'):
778        HG_REVISION = hg_revision()
779    elif os.path.exists('Orange/version.py'):
780        # must be a source distribution, use existing version file
781        version = imp.load_source("Orange.version", "Orange/version.py")
782        HG_REVISION = version.hg_revision
783    else:
784        HG_REVISION = "Unknown"
785
786    if not ISRELEASED:
787        FULLVERSION += '.dev-' + HG_REVISION[:7]
788
789    a = open(filename, 'w')
790    try:
791        a.write(cnt % {'version': VERSION,
792                       'full_version' : FULLVERSION,
793                       'hg_revision' : HG_REVISION,
794                       'isrelease': str(ISRELEASED)})
795    finally:
796        a.close()
797
798PACKAGES = find_packages()
799
800PACKAGE_DATA = get_package_data()
801
802SETUP_REQUIRES = (
803    'setuptools',
804)
805
806# If you change the requirements, check whether all ADD-ons still work!
807
808INSTALL_REQUIRES = (
809    'setuptools',
810    'numpy',
811)
812
813EXTRAS_REQUIRE = {
814    'GUI': (
815        'PyQt4',
816        'PyQwt',
817    ),
818    'reST': (
819        'numpydoc',
820    ),
821}
822
823DEPENDENCY_LINKS = (
824)
825
826ENTRY_POINTS = {
827    'gui_scripts': (
828            'orange-canvas = Orange.OrangeCanvas.main:main',
829    ),
830    'orange.canvas.help': (
831            'intersphinx = Orange.OrangeWidgets:intersphinx',
832    )
833}
834
835
836def setup_package():
837    write_version_py()
838    setup(
839        name = NAME,
840        version = VERSION,
841        description = DESCRIPTION,
842        long_description = LONG_DESCRIPTION,
843        author = AUTHOR,
844        author_email = AUTHOR_EMAIL,
845        url = URL,
846        download_url = DOWNLOAD_URL,
847        license = LICENSE,
848        keywords = KEYWORDS,
849        classifiers = CLASSIFIERS,
850        packages = PACKAGES,
851        package_data = PACKAGE_DATA,
852        setup_requires = SETUP_REQUIRES,
853        extras_require = EXTRAS_REQUIRE,
854        install_requires = INSTALL_REQUIRES,
855        dependency_links = DEPENDENCY_LINKS,
856        entry_points = ENTRY_POINTS,
857        include_package_data = True,
858        zip_safe = False,
859        test_suite = 'Orange.testing.unit.tests.test_suite',
860        cmdclass = cmdclass,
861        ext_modules = ext_modules,
862    )
863
864if __name__ == '__main__':
865    setup_package()
Note: See TracBrowser for help on using the repository browser.