source: orange/setup.py @ 10433:510c2b571117

Revision 10433:510c2b571117, 28.3 KB checked in by anzeh <anze.staric@…>, 2 years ago (diff)

Fixed a bug when setup.py crashed if .hg was missing.
(fix inspired by numpy)

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