Code

extended date syntax to make range searches even more useful
[roundup.git] / setup.py
1 #! /usr/bin/env python
2 #
3 # Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
4 # This module is free software, and you may redistribute it and/or modify
5 # under the same terms as Python, so long as this copyright message and
6 # disclaimer are retained in their original form.
7 #
8 # IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
9 # DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
10 # OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
11 # POSSIBILITY OF SUCH DAMAGE.
12 #
13 # BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
14 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15 # FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
16 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
17 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
18
19 # $Id: setup.py,v 1.49 2003-04-19 05:03:54 richard Exp $
21 from distutils.core import setup, Extension
22 from distutils.util import get_platform
23 from distutils.command.build_scripts import build_scripts
25 import sys, os, string
26 from glob import glob
28 # patch distutils if it can't cope with the "classifiers" keyword
29 if sys.version < '2.2.3':
30     from distutils.dist import DistributionMetadata
31     DistributionMetadata.classifiers = None
32     DistributionMetadata.download_url = None
35 #############################################################################
36 ### Build script files
37 #############################################################################
39 class build_scripts_create(build_scripts):
40     """ Overload the build_scripts command and create the scripts
41         from scratch, depending on the target platform.
43         You have to define the name of your package in an inherited
44         class (due to the delayed instantiation of command classes
45         in distutils, this cannot be passed to __init__).
47         The scripts are created in an uniform scheme: they start the
48         run() function in the module
50             <packagename>.scripts.<mangled_scriptname>
52         The mangling of script names replaces '-' and '/' characters
53         with '-' and '.', so that they are valid module paths. 
54     """
55     package_name = None
57     def copy_scripts(self):
58         """ Create each script listed in 'self.scripts'
59         """
60         if not self.package_name:
61             raise Exception("You have to inherit build_scripts_create and"
62                 " provide a package name")
63         
64         to_module = string.maketrans('-/', '_.')
66         self.mkpath(self.build_dir)
67         for script in self.scripts:
68             outfile = os.path.join(self.build_dir, os.path.basename(script))
70             #if not self.force and not newer(script, outfile):
71             #    self.announce("not copying %s (up-to-date)" % script)
72             #    continue
74             if self.dry_run:
75                 self.announce("would create %s" % outfile)
76                 continue
78             module = os.path.splitext(os.path.basename(script))[0]
79             module = string.translate(module, to_module)
80             script_vars = {
81                 'python': os.path.normpath(sys.executable),
82                 'package': self.package_name,
83                 'module': module,
84             }
86             self.announce("creating %s" % outfile)
87             file = open(outfile, 'w')
89             try:
90                 if sys.platform == "win32":
91                     file.write('@echo off\n'
92                         'if NOT "%%_4ver%%" == "" "%(python)s" -O -c "from %(package)s.scripts.%(module)s import run; run()" %%$\n'
93                         'if     "%%_4ver%%" == "" "%(python)s" -O -c "from %(package)s.scripts.%(module)s import run; run()" %%*\n'
94                         % script_vars)
95                 else:
96                     file.write('#! %(python)s -O\n'
97                         'from %(package)s.scripts.%(module)s import run\n'
98                         'run()\n'
99                         % script_vars)
100             finally:
101                 file.close()
102                 os.chmod(outfile, 0755)
105 class build_scripts_roundup(build_scripts_create):
106     package_name = 'roundup'
109 def scriptname(path):
110     """ Helper for building a list of script names from a list of
111         module files.
112     """
113     script = os.path.splitext(os.path.basename(path))[0]
114     script = string.replace(script, '_', '-')
115     if sys.platform == "win32":
116         script = script + ".bat"
117     return script
121 #############################################################################
122 ### Main setup stuff
123 #############################################################################
125 def main():
126     # build list of scripts from their implementation modules
127     roundup_scripts = map(scriptname, glob('roundup/scripts/[!_]*.py'))
129     # template munching
130     packagelist = [
131         'roundup',
132         'roundup.cgi',
133         'roundup.cgi.PageTemplates',
134         'roundup.cgi.TAL',
135         'roundup.cgi.ZTUtils',
136         'roundup.backends',
137         'roundup.scripts'
138     ]
139     installdatafiles = [
140         ('share/roundup/cgi-bin', ['cgi-bin/roundup.cgi']),
141     ] 
143     # install man pages on POSIX platforms
144     if os.name == 'posix':
145         installdatafiles.append(('man/man1', ['doc/roundup-admin.1',
146             'doc/roundup-mailgw.1', 'doc/roundup-server.1']))
148     # add the templates to the data files lists
149     from roundup.admin import listTemplates
150     templates = [t['path'] for t in listTemplates('templates').values()]
151     for tdir in templates:
152         # scan for data files
153         for idir in '. detectors html'.split():
154             idir = os.path.join(tdir, idir)
155             tfiles = []
156             for f in os.listdir(idir):
157                 if f.startswith('.'):
158                     continue
159                 ifile = os.path.join(idir, f)
160                 if os.path.isfile(ifile):
161                     tfiles.append(ifile)
162             installdatafiles.append(
163                 (os.path.join('share', 'roundup', idir), tfiles)
164             )
166     # perform the setup action
167     from roundup import __version__
168     setup(
169         name = "roundup", 
170         version = __version__,
171         description = "Roundup issue tracking system.",
172         author = "Richard Jones",
173         author_email = "richard@users.sourceforge.net",
174         url = 'http://sourceforge.net/projects/roundup/',
175         download_url = 'http://sourceforge.net/project/showfiles.php?group_id=31577',
176         packages = packagelist,
177         classifiers = [
178             'Development Status :: 4 - Beta',
179             'Environment :: Console',
180             'Environment :: Web Environment',
181             'Intended Audience :: End Users/Desktop',
182             'Intended Audience :: Developers',
183             'Intended Audience :: System Administrators',
184             'License :: OSI Approved :: Python Software Foundation License',
185             'Operating System :: MacOS :: MacOS X',
186             'Operating System :: Microsoft :: Windows',
187             'Operating System :: POSIX',
188             'Programming Language :: Python',
189             'Topic :: Communications :: Email',
190             'Topic :: Office/Business',
191             'Topic :: Software Development :: Bug Tracking',
192         ],
194         # Override certain command classes with our own ones
195         cmdclass = {
196             'build_scripts': build_scripts_roundup,
197         },
198         scripts = roundup_scripts,
200         data_files =  installdatafiles
201     )
203 def install_demo():
204     ''' Install a demo server for users to play with for instant gratification.
206         Sets up the web service on localhost port 8080. Disables nosy lists.
207     '''
208     import shutil, socket, errno, BaseHTTPServer
210     # create the instance
211     home = os.path.abspath('demo')
212     try:
213         shutil.rmtree(home)
214     except os.error, error:
215         if error.errno != errno.ENOENT:
216             raise
217     from roundup import init, instance, password
218     init.install(home, os.path.join('templates', 'classic'))
219     # don't have email flying around
220     os.remove(os.path.join(home, 'detectors', 'nosyreaction.py'))
221     init.write_select_db(home, 'anydbm')
223     # figure basic params for server
224     hostname = socket.gethostname()
225     # pick a fairly odd, random port
226     port = 8917
227     while 1:
228         print 'Trying to set up web server on port %d ...'%port,
229         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
230         s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
231         try:
232             s.connect((hostname, port))
233         except socket.error, e:
234             if not hasattr(e, 'args') or e.args[0] != errno.ECONNREFUSED:
235                 raise
236             print 'should be ok.'
237             break
238         else:
239             s.close()
240             print 'already in use.'
241             port += 100
242     url = 'http://%s:%s/demo/'%(hostname, port)
244     # write the config
245     f = open(os.path.join(home, 'config.py'), 'r')
246     s = f.read().replace('http://tracker.example/cgi-bin/roundup.cgi/bugs/',
247         url)
248     f.close()
249     f = open(os.path.join(home, 'config.py'), 'w')
250     f.write(s)
251     f.close()
253     # initialise the database
254     init.initialise(home, 'admin')
256     # add the "demo" user
257     tracker = instance.open(home)
258     db = tracker.open('admin')
259     db.user.create(username='demo', password=password.Password('demo'),
260         realname='Demo User', roles='User')
261     db.commit()
262     db.close()
264     # ok, so start up the server
265     from roundup.scripts.roundup_server import RoundupRequestHandler
266     RoundupRequestHandler.TRACKER_HOMES = {'demo': home}
267     httpd = BaseHTTPServer.HTTPServer((hostname, port), RoundupRequestHandler)
268     print 'Server running - connect to:\n  %s'%url
269     print 'You may log in as "demo"/"demo" or "admin"/"admin".'
270     print 'Hit Control-C to stop the server.'
271     try:
272         httpd.serve_forever()
273     except KeyboardInterrupt:
274         print 'Keyboard Interrupt: exiting'
276 if __name__ == '__main__':
277     if len(sys.argv) > 1 and sys.argv[1] == 'demo':
278         install_demo()
279     else:
280         main()
282 # vim: set filetype=python ts=4 sw=4 et si