source: orange/setup.py @ 10793:35713869d753

Revision 10793:35713869d753, 29.7 KB checked in by Ales Erjavec <ales.erjavec@…>, 2 years ago (diff)

Don't fail if orangeqt's setup.py can't be imported (due to a missing PyQt4).

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