skeleton/setup.py
changeset 5024 9e718abe3fde
parent 4212 ab6573088b4a
child 5184 955ee1b24756
equal deleted inserted replaced
5023:70d5d54e8b81 5024:9e718abe3fde
     1 #!/usr/bin/env python
     1 #!/usr/bin/env python
     2 """
     2 """Generic Setup script, takes package info from __pkginfo__.py file
     3 
     3 
     4 :organization: Logilab
     4 :organization: Logilab
     5 :copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
     5 :copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
     6 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     6 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     7 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
     7 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
     8 """
     8 """
     9 # pylint: disable-msg=W0404,W0622,W0704,W0613,W0152
     9 # pylint: disable-msg=W0142,W0403,W0404,W0613,W0622,W0622,W0704,R0904,C0103,E0611
    10 # Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE).
       
    11 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
       
    12 #
    10 #
    13 # This program is free software; you can redistribute it and/or modify it under
    11 # This program is free software; you can redistribute it and/or modify it under
    14 # the terms of the GNU General Public License as published by the Free Software
    12 # the terms of the GNU General Public License as published by the Free Software
    15 # Foundation; either version 2 of the License, or (at your option) any later
    13 # Foundation; either version 2 of the License, or (at your option) any later
    16 # version.
    14 # version.
    20 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    18 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    21 #
    19 #
    22 # You should have received a copy of the GNU General Public License along with
    20 # You should have received a copy of the GNU General Public License along with
    23 # this program; if not, write to the Free Software Foundation, Inc.,
    21 # this program; if not, write to the Free Software Foundation, Inc.,
    24 # 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    22 # 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    25 """ Generic Setup script, takes package info from __pkginfo__.py file """
       
    26 
    23 
    27 from distutils.core import setup
    24 import os
       
    25 import sys
       
    26 import shutil
       
    27 from os.path import isdir, exists, join, walk
       
    28 
       
    29 try:
       
    30    if os.environ.get('NO_SETUPTOOLS'):
       
    31       raise ImportError() # do as there is no setuptools
       
    32    from setuptools import setup
       
    33    from setuptools.command import install_lib
       
    34    USE_SETUPTOOLS = True
       
    35 except ImportError:
       
    36    from distutils.core import setup
       
    37    from distutils.command import install_lib
       
    38    USE_SETUPTOOLS = False
    28 
    39 
    29 # import required features
    40 # import required features
    30 from __pkginfo__ import distname, version, license, short_desc, long_desc, \
    41 from __pkginfo__ import modname, version, license, description, web, \
    31      web, author, author_email
    42      author, author_email
       
    43 
       
    44 if exists('README'):
       
    45    long_description = file('README').read()
       
    46 
    32 # import optional features
    47 # import optional features
    33 try:
    48 import __pkginfo__
    34     from __pkginfo__ import data_files
    49 if USE_SETUPTOOLS:
    35 except ImportError:
    50    requires = {}
    36     data_files = None
    51    for entry in ("__depends__", "__recommends__"):
    37 try:
    52       requires.update(getattr(__pkginfo__, entry, {}))
    38     from __pkginfo__ import include_dirs
    53    install_requires = [("%s %s" % (d, v and v or "")).strip()
    39 except ImportError:
    54                        for d, v in requires.iteritems()]
    40     include_dirs = []
    55 else:
       
    56    install_requires = []
       
    57 
       
    58 distname = getattr(__pkginfo__, 'distname', modname)
       
    59 scripts = getattr(__pkginfo__, 'scripts', ())
       
    60 include_dirs = getattr(__pkginfo__, 'include_dirs', ())
       
    61 data_files = getattr(__pkginfo__, 'data_files', None)
       
    62 subpackage_of = getattr(__pkginfo__, 'subpackage_of', None)
       
    63 ext_modules = getattr(__pkginfo__, 'ext_modules', None)
       
    64 
       
    65 
       
    66 BASE_BLACKLIST = ('CVS', 'debian', 'dist', 'build', '__buildlog')
       
    67 IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc')
       
    68 
       
    69 
       
    70 def ensure_scripts(linux_scripts):
       
    71     """
       
    72     Creates the proper script names required for each platform
       
    73     (taken from 4Suite)
       
    74     """
       
    75     from distutils import util
       
    76     if util.get_platform()[:3] == 'win':
       
    77         scripts_ = [script + '.bat' for script in linux_scripts]
       
    78     else:
       
    79         scripts_ = linux_scripts
       
    80     return scripts_
       
    81 
       
    82 
       
    83 def get_packages(directory, prefix):
       
    84     """return a list of subpackages for the given directory
       
    85     """
       
    86     result = []
       
    87     for package in os.listdir(directory):
       
    88         absfile = join(directory, package)
       
    89         if isdir(absfile):
       
    90             if exists(join(absfile, '__init__.py')) or \
       
    91                    package in ('test', 'tests'):
       
    92                 if prefix:
       
    93                     result.append('%s.%s' % (prefix, package))
       
    94                 else:
       
    95                     result.append(package)
       
    96                 result += get_packages(absfile, result[-1])
       
    97     return result
       
    98 
       
    99 def export(from_dir, to_dir,
       
   100            blacklist=BASE_BLACKLIST,
       
   101            ignore_ext=IGNORED_EXTENSIONS,
       
   102            verbose=True):
       
   103     """make a mirror of from_dir in to_dir, omitting directories and files
       
   104     listed in the black list
       
   105     """
       
   106     def make_mirror(arg, directory, fnames):
       
   107         """walk handler"""
       
   108         for norecurs in blacklist:
       
   109             try:
       
   110                 fnames.remove(norecurs)
       
   111             except ValueError:
       
   112                 pass
       
   113         for filename in fnames:
       
   114             # don't include binary files
       
   115             if filename[-4:] in ignore_ext:
       
   116                 continue
       
   117             if filename[-1] == '~':
       
   118                 continue
       
   119             src = '%s/%s' % (directory, filename)
       
   120             dest = to_dir + src[len(from_dir):]
       
   121             if verbose:
       
   122                print >> sys.stderr, src, '->', dest
       
   123             if os.path.isdir(src):
       
   124                 if not exists(dest):
       
   125                     os.mkdir(dest)
       
   126             else:
       
   127                 if exists(dest):
       
   128                     os.remove(dest)
       
   129                 shutil.copy2(src, dest)
       
   130     try:
       
   131         os.mkdir(to_dir)
       
   132     except OSError, ex:
       
   133         # file exists ?
       
   134         import errno
       
   135         if ex.errno != errno.EEXIST:
       
   136             raise
       
   137     walk(from_dir, make_mirror, None)
       
   138 
       
   139 
       
   140 EMPTY_FILE = '"""generated file, don\'t modify or your data will be lost"""\n'
       
   141 
       
   142 class MyInstallLib(install_lib.install_lib):
       
   143     """extend install_lib command to handle  package __init__.py and
       
   144     include_dirs variable if necessary
       
   145     """
       
   146     def run(self):
       
   147         """overridden from install_lib class"""
       
   148         install_lib.install_lib.run(self)
       
   149         # create Products.__init__.py if needed
       
   150         if subpackage_of:
       
   151             product_init = join(self.install_dir, subpackage_of, '__init__.py')
       
   152             if not exists(product_init):
       
   153                 self.announce('creating %s' % product_init)
       
   154                 stream = open(product_init, 'w')
       
   155                 stream.write(EMPTY_FILE)
       
   156                 stream.close()
       
   157         # manually install included directories if any
       
   158         if include_dirs:
       
   159             if subpackage_of:
       
   160                 base = join(subpackage_of, modname)
       
   161             else:
       
   162                 base = modname
       
   163             for directory in include_dirs:
       
   164                 dest = join(self.install_dir, base, directory)
       
   165                 export(directory, dest, verbose=False)
    41 
   166 
    42 def install(**kwargs):
   167 def install(**kwargs):
    43     """setup entry point"""
   168     """setup entry point"""
    44     #kwargs['distname'] = modname
   169     if not USE_SETUPTOOLS and '--install-layout=deb' in sys.argv and \
    45     return setup(name=distname,
   170            sys.versioninfo < (2, 5, 4):
    46                  version=version,
   171        sys.argv.remove('--install-layout=deb')
    47                  license=license,
   172        print "W: remove '--install-layout=deb' option"
    48                  description=short_desc,
   173     if subpackage_of:
    49                  long_description=long_desc,
   174         package = subpackage_of + '.' + modname
    50                  author=author,
   175         kwargs['package_dir'] = {package : '.'}
    51                  author_email=author_email,
   176         packages = [package] + get_packages(os.getcwd(), package)
    52                  url=web,
   177         if USE_SETUPTOOLS:
    53                  data_files=data_files,
   178             kwargs['namespace_packages'] = [subpackage_of]
    54                  **kwargs)
   179     else:
       
   180         kwargs['package_dir'] = {modname : '.'}
       
   181         packages = [modname] + get_packages(os.getcwd(), modname)
       
   182     kwargs['packages'] = packages
       
   183     return setup(name=distname, version=version, license=license, url=web,
       
   184                  description=description, long_description=long_description,
       
   185                  author=author, author_email=author_email,
       
   186                  scripts=ensure_scripts(scripts), data_files=data_files,
       
   187                  ext_modules=ext_modules,
       
   188                  install_requires=install_requires,
       
   189                  #dependency_links=["http://alain:alain@intranet.logilab.fr/~alain/"],
       
   190                  cmdclass={'install_lib': MyInstallLib},
       
   191                  **kwargs
       
   192                  )
    55 
   193 
    56 if __name__ == '__main__' :
   194 if __name__ == '__main__' :
    57     install()
   195     install()