setup.py
author Reimar Bauer <rb.proj AT googlemail DOT com>
Mon, 19 Jan 2009 01:20:04 +0100
changeset 4247 c76d50dac855
parent 3439 b9879146620d
permissions -rw-r--r--
text_html_text_moin_wiki: bug fix for GuiEditorBreaksIndentedTable
     1 #!/usr/bin/env python
     2 # -*- coding: iso-8859-1 -*-
     3 """
     4     MoinMoin installer
     5 
     6     @copyright: 2001-2005 by Jürgen Hermann <jh@web.de>,
     7                 2006-2007 by MoinMoin:ThomasWaldmann
     8     @license: GNU GPL, see COPYING for details.
     9 """
    10 
    11 import os, sys, glob
    12 
    13 import distutils
    14 from distutils.core import setup
    15 from distutils.command.build_scripts import build_scripts
    16 
    17 from MoinMoin.version import release, revision
    18 
    19 # we need this for distutils from python 2.3 compatibility, python 2.4 has the
    20 # 'package_data' keyword to the 'setup' function to install data in packages
    21 # see http://wiki.python.org/moin/DistutilsInstallDataScattered
    22 from distutils.command.install_data import install_data
    23 class smart_install_data(install_data):
    24     def run(self):
    25         i18n_data_files = [(target, files) for (target, files) in self.data_files if target.startswith('MoinMoin/i18n')]
    26         share_data_files = [(target, files) for (target, files) in self.data_files if target.startswith('share/moin')]
    27         # first install the share/moin stuff:
    28         self.data_files = share_data_files
    29         install_data.run(self)
    30         # now we need to install the *.po files to the package dir:
    31         # need to change self.install_dir to the library dir
    32         install_cmd = self.get_finalized_command('install')
    33         self.install_dir = getattr(install_cmd, 'install_lib')
    34         self.data_files = i18n_data_files
    35         return install_data.run(self)
    36 
    37 #############################################################################
    38 ### Helpers
    39 #############################################################################
    40 
    41 def isbad(name):
    42     """ Whether name should not be installed """
    43     return (name.startswith('.') or
    44             name.startswith('#') or
    45             name.endswith('.pickle') or
    46             name == 'CVS')
    47 
    48 def isgood(name):
    49     """ Whether name should be installed """
    50     return not isbad(name)
    51 
    52 def makeDataFiles(prefix, dir):
    53     """ Create distutils data_files structure from dir
    54 
    55     distutil will copy all file rooted under dir into prefix, excluding
    56     dir itself, just like 'ditto src dst' works, and unlike 'cp -r src
    57     dst, which copy src into dst'.
    58 
    59     Typical usage:
    60         # install the contents of 'wiki' under sys.prefix+'share/moin'
    61         data_files = makeDataFiles('share/moin', 'wiki')
    62 
    63     For this directory structure:
    64         root
    65             file1
    66             file2
    67             dir
    68                 file
    69                 subdir
    70                     file
    71 
    72     makeDataFiles('prefix', 'root')  will create this distutil data_files structure:
    73         [('prefix', ['file1', 'file2']),
    74          ('prefix/dir', ['file']),
    75          ('prefix/dir/subdir', ['file'])]
    76 
    77     """
    78     # Strip 'dir/' from of path before joining with prefix
    79     dir = dir.rstrip('/')
    80     strip = len(dir) + 1
    81     found = []
    82     os.path.walk(dir, visit, (prefix, strip, found))
    83     return found
    84 
    85 def visit((prefix, strip, found), dirname, names):
    86     """ Visit directory, create distutil tuple
    87 
    88     Add distutil tuple for each directory using this format:
    89         (destination, [dirname/file1, dirname/file2, ...])
    90 
    91     distutil will copy later file1, file2, ... info destination.
    92     """
    93     files = []
    94     # Iterate over a copy of names, modify names
    95     for name in names[:]:
    96         path = os.path.join(dirname, name)
    97         # Ignore directories -  we will visit later
    98         if os.path.isdir(path):
    99             # Remove directories we don't want to visit later
   100             if isbad(name):
   101                 names.remove(name)
   102             continue
   103         elif isgood(name):
   104             files.append(path)
   105     destination = os.path.join(prefix, dirname[strip:])
   106     found.append((destination, files))
   107 
   108 
   109 #############################################################################
   110 ### Build script files
   111 #############################################################################
   112 
   113 class build_scripts_create(build_scripts):
   114     """ Overload the build_scripts command and create the scripts
   115         from scratch, depending on the target platform.
   116 
   117         You have to define the name of your package in an inherited
   118         class (due to the delayed instantiation of command classes
   119         in distutils, this cannot be passed to __init__).
   120 
   121         The scripts are created in an uniform scheme: they start the
   122         run() function in the module
   123 
   124             <packagename>.script.<mangled_scriptname>
   125 
   126         The mangling of script names replaces '-' and '/' characters
   127         with '-' and '.', so that they are valid module paths.
   128     """
   129     package_name = None
   130 
   131     def copy_scripts(self):
   132         """ Create each script listed in 'self.scripts'
   133         """
   134         if not self.package_name:
   135             raise Exception("You have to inherit build_scripts_create and"
   136                 " provide a package name")
   137 
   138         self.mkpath(self.build_dir)
   139         for script in self.scripts:
   140             outfile = os.path.join(self.build_dir, os.path.basename(script))
   141 
   142             #if not self.force and not newer(script, outfile):
   143             #    self.announce("not copying %s (up-to-date)" % script)
   144             #    continue
   145 
   146             if self.dry_run:
   147                 self.announce("would create %s" % outfile)
   148                 continue
   149 
   150             module = os.path.splitext(os.path.basename(script))[0]
   151             module = module.replace('-', '_').replace('/', '.')
   152             script_vars = {
   153                 'python': os.path.normpath(sys.executable),
   154                 'package': self.package_name,
   155                 'module': module,
   156                 'package_location': '/usr/lib/python/site-packages', # FIXME: we need to know the correct path
   157             }
   158 
   159             self.announce("creating %s" % outfile)
   160             file = open(outfile, 'w')
   161 
   162             try:
   163                 if sys.platform == "win32":
   164                     file.write('@echo off\n'
   165                         'if NOT "%%_4ver%%" == "" %(python)s -c "from %(package)s.script.%(module)s import run; run()" %%$\n'
   166                         'if     "%%_4ver%%" == "" %(python)s -c "from %(package)s.script.%(module)s import run; run()" %%*\n'
   167                         % script_vars)
   168                 else:
   169                     file.write("#! %(python)s\n"
   170                         "#Fix and uncomment those 2 lines if your moin command doesn't find the MoinMoin package:\n"
   171                         "#import sys\n"
   172                         "#sys.path.insert(0, '%(package_location)s')\n"
   173                         "from %(package)s.script.%(module)s import run\n"
   174                         "run()\n"
   175                         % script_vars)
   176             finally:
   177                 file.close()
   178                 os.chmod(outfile, 0755)
   179 
   180 
   181 class build_scripts_moin(build_scripts_create):
   182     package_name = 'MoinMoin'
   183 
   184 
   185 def scriptname(path):
   186     """ Helper for building a list of script names from a list of
   187         module files.
   188     """
   189     script = os.path.splitext(os.path.basename(path))[0]
   190     script = script.replace('_', '-')
   191     if sys.platform == "win32":
   192         script = script + ".bat"
   193     return script
   194 
   195 # build list of scripts from their implementation modules
   196 moin_scripts = [scriptname(fn) for fn in glob.glob('MoinMoin/script/[!_]*.py')]
   197 
   198 
   199 #############################################################################
   200 ### Call setup()
   201 #############################################################################
   202 
   203 setup_args = {
   204     'name': "moin",
   205     'version': release,
   206     'description': "MoinMoin %s is an easy to use, full-featured and extensible wiki software package" % (release, ),
   207     'author': "Juergen Hermann et al.",
   208     'author_email': "moin-user@lists.sourceforge.net",
   209     # maintainer(_email) not active because distutils/register can't handle author and maintainer at once
   210     'download_url': 'http://static.moinmo.in/files/moin-%s.tar.gz' % (release, ),
   211     'url': "http://moinmo.in/",
   212     'license': "GNU GPL",
   213     'long_description': """
   214     MoinMoin is an easy to use, full-featured and extensible wiki software
   215     package written in Python. It can fulfill a wide range of roles, such as
   216     a personal notes organizer deployed on a laptop or home web server,
   217     a company knowledge base deployed on an intranet, or an Internet server
   218     open to individuals sharing the same interests, goals or projects.""",
   219     'classifiers': """Development Status :: 5 - Production/Stable
   220 Environment :: No Input/Output (Daemon)
   221 Environment :: Web Environment
   222 Environment :: Win32 (MS Windows)
   223 Intended Audience :: Customer Service
   224 Intended Audience :: Developers
   225 Intended Audience :: Education
   226 Intended Audience :: End Users/Desktop
   227 Intended Audience :: Financial and Insurance Industry
   228 Intended Audience :: Healthcare Industry
   229 Intended Audience :: Information Technology
   230 Intended Audience :: Legal Industry
   231 Intended Audience :: Manufacturing
   232 Intended Audience :: Other Audience
   233 Intended Audience :: Religion
   234 Intended Audience :: Science/Research
   235 Intended Audience :: System Administrators
   236 Intended Audience :: Telecommunications Industry
   237 License :: OSI Approved :: GNU General Public License (GPL)
   238 Natural Language :: Chinese (Simplified)
   239 Natural Language :: Chinese (Traditional)
   240 Natural Language :: Danish
   241 Natural Language :: Dutch
   242 Natural Language :: English
   243 Natural Language :: French
   244 Natural Language :: German
   245 Natural Language :: Hebrew
   246 Natural Language :: Hungarian
   247 Natural Language :: Italian
   248 Natural Language :: Javanese
   249 Natural Language :: Korean
   250 Natural Language :: Norwegian
   251 Natural Language :: Russian
   252 Natural Language :: Serbian
   253 Natural Language :: Spanish
   254 Natural Language :: Vietnamese
   255 Operating System :: MacOS :: MacOS X
   256 Operating System :: Microsoft :: Windows
   257 Operating System :: Microsoft :: Windows :: Windows 95/98/2000
   258 Operating System :: Microsoft :: Windows :: Windows NT/2000
   259 Operating System :: OS Independent
   260 Operating System :: POSIX
   261 Operating System :: POSIX :: BSD :: FreeBSD
   262 Operating System :: POSIX :: Linux
   263 Operating System :: Unix
   264 Programming Language :: Python
   265 Topic :: Communications :: Conferencing
   266 Topic :: Internet :: WWW/HTTP :: Dynamic Content
   267 Topic :: Office/Business :: Groupware
   268 Topic :: Text Processing :: Markup""".splitlines(),
   269 
   270     'packages': [
   271         'jabberbot',
   272         'MoinMoin',
   273         'MoinMoin.action',
   274         'MoinMoin.auth',
   275         'MoinMoin.config',
   276         'MoinMoin.converter',
   277         'MoinMoin.events',
   278         'MoinMoin.filter',
   279         'MoinMoin.formatter',
   280         'MoinMoin.i18n',
   281         'MoinMoin.i18n.tools',
   282         'MoinMoin.logfile',
   283         'MoinMoin.macro',
   284         'MoinMoin.mail',
   285         'MoinMoin.parser',
   286         'MoinMoin.request',
   287         'MoinMoin.script',
   288         'MoinMoin.script.account',
   289         'MoinMoin.script.cli',
   290         'MoinMoin.script.export',
   291         'MoinMoin.script.import',
   292         'MoinMoin.script.index',
   293         'MoinMoin.script.maint',
   294         'MoinMoin.script.migration',
   295         'MoinMoin.script.old',
   296         'MoinMoin.script.old.migration',
   297         'MoinMoin.script.old.xmlrpc-tools',
   298         'MoinMoin.script.server',
   299         'MoinMoin.script.xmlrpc',
   300         'MoinMoin.search',
   301         'MoinMoin.security',
   302         'MoinMoin.server',
   303         'MoinMoin.stats',
   304         'MoinMoin.support',
   305         'MoinMoin.support.xapwrap',
   306         'MoinMoin.support.parsedatetime',
   307         'MoinMoin.theme',
   308         'MoinMoin.userform',
   309         'MoinMoin.userprefs',
   310         'MoinMoin.util',
   311         'MoinMoin.widget',
   312         'MoinMoin.wikixml',
   313         'MoinMoin.xmlrpc',
   314 
   315         # all other _tests are missing here, either we have all or nothing:
   316         #'MoinMoin._tests',
   317     ],
   318 
   319     # We can use package_* instead of the smart_install_data hack when we
   320     # require Python 2.4.
   321     #'package_dir': { 'MoinMoin.i18n': 'MoinMoin/i18n', },
   322     #'package_data': { 'MoinMoin.i18n': ['README', 'Makefile', 'MoinMoin.pot', 'POTFILES.in',
   323     #                                    '*.po',
   324     #                                    'tools/*',], },
   325 
   326     # Override certain command classes with our own ones
   327     'cmdclass': {
   328         'build_scripts': build_scripts_moin,
   329         'install_data': smart_install_data, # hack needed for 2.3
   330     },
   331 
   332     'scripts': moin_scripts,
   333 
   334     # This copies the contents of wiki dir under sys.prefix/share/moin
   335     # Do not put files that should not be installed in the wiki dir, or
   336     # clean the dir before you make the distribution tarball.
   337     'data_files': makeDataFiles('share/moin', 'wiki') + makeDataFiles('MoinMoin/i18n', 'MoinMoin/i18n')
   338 }
   339 
   340 if hasattr(distutils.dist.DistributionMetadata, 'get_keywords'):
   341     setup_args['keywords'] = "wiki web"
   342 
   343 if hasattr(distutils.dist.DistributionMetadata, 'get_platforms'):
   344     setup_args['platforms'] = "any"
   345 
   346 
   347 try:
   348     setup(**setup_args)
   349 except distutils.errors.DistutilsPlatformError, ex:
   350     print
   351     print str(ex)
   352 
   353     print """
   354 POSSIBLE CAUSE
   355 
   356 "distutils" often needs developer support installed to work
   357 correctly, which is usually located in a separate package
   358 called "python%d.%d-dev(el)".
   359 
   360 Please contact the system administrator to have it installed.
   361 """ % sys.version_info[:2]
   362     sys.exit(1)
   363