source: orange/setup.py @ 10825:6afd3857cce8

Revision 10825:6afd3857cce8, 29.1 KB checked in by mitar, 2 years ago (diff)

Updated setup.py, README and current (future) version.

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