source: orange/setup.py @ 10828:9f259a79f12b

Revision 10828:9f259a79f12b, 29.3 KB checked in by mitar, 2 years ago (diff)

A hack for setup.py to work on Ubuntu.

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