source: orange/setup.py @ 10845:c2d42494144b

Revision 10845:c2d42494144b, 29.2 KB checked in by Ales Erjavec <ales.erjavec@…>, 2 years ago (diff)

Renamed README.rst back to README.txt, added distribute_setup.py to MANIFEST.in

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