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")
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