print 'Using HTTP/1.1 protocol version' httpd.serve_forever() elif options.protocol in ('scgi', 'ajp', 'fcgi'): def serve(): server_cls = __import__('flup.server.%s' % options.protocol, None, None, ['']).WSGIServer flup_app = wsgi_app if options.unquote: from trac.web.fcgi_frontend import FlupMiddleware flup_app = FlupMiddleware(flup_app) ret = server_cls(flup_app, bindAddress=server_address).run() sys.exit(42 if ret else 0) # if SIGHUP exit with status 42 try: if options.daemonize: daemon.daemonize(pidfile=options.pidfile, progname='tracd', umask=options.umask) if options.group is not None: os.setgid(options.group) if options.user is not None: os.setuid(options.user) if options.autoreload: def modification_callback(file): print >> sys.stderr, 'Detected modification of %s, ' \ 'restarting.' % file autoreload.main(serve, modification_callback) else: serve() except OSError, e: print >> sys.stderr, '%s: %s' % (e.__class__.__name__, e)
def main(): from optparse import OptionParser, OptionValueError parser = OptionParser(usage='usage: %prog [options] [projenv] ...', version='%%prog %s' % VERSION) auths = {} def _auth_callback(option, opt_str, value, parser, cls): info = value.split(',', 3) if len(info) != 3: raise OptionValueError("Incorrect number of parameters for %s" % option) env_name, filename, realm = info if env_name in auths: print >> sys.stderr, 'Ignoring duplicate authentication option ' \ 'for project: %s' % env_name else: auths[env_name] = cls(os.path.abspath(filename), realm) def _validate_callback(option, opt_str, value, parser, valid_values): if value not in valid_values: raise OptionValueError('%s must be one of: %s, not %s' % (opt_str, '|'.join(valid_values), value)) setattr(parser.values, option.dest, value) def _octal(option, opt_str, value, parser): try: setattr(parser.values, option.dest, int(value, 8)) except ValueError: raise OptionValueError('Invalid octal umask value: %r' % value) parser.add_option('-a', '--auth', action='callback', type='string', metavar='DIGESTAUTH', callback=_auth_callback, callback_args=(DigestAuthentication,), help='[projectdir],[htdigest_file],[realm]') parser.add_option('--basic-auth', action='callback', type='string', metavar='BASICAUTH', callback=_auth_callback, callback_args=(BasicAuthentication,), help='[projectdir],[htpasswd_file],[realm]') parser.add_option('-p', '--port', action='store', type='int', dest='port', help='the port number to bind to') parser.add_option('-b', '--hostname', action='store', dest='hostname', help='the host name or IP address to bind to') parser.add_option('--protocol', action='callback', type="string", dest='protocol', callback=_validate_callback, callback_args=(('http', 'scgi', 'ajp', 'fcgi'),), help='http|scgi|ajp|fcgi') parser.add_option('-q', '--unquote', action='store_true', dest='unquote', help='unquote PATH_INFO (may be needed when using ajp)') parser.add_option('--http10', action='store_false', dest='http11', help='use HTTP/1.0 protocol version instead of HTTP/1.1') parser.add_option('--http11', action='store_true', dest='http11', help='use HTTP/1.1 protocol version (default)') parser.add_option('-e', '--env-parent-dir', action='store', dest='env_parent_dir', metavar='PARENTDIR', help='parent directory of the project environments') parser.add_option('--base-path', action='store', type='string', # XXX call this url_base_path? dest='base_path', help='the initial portion of the request URL\'s "path"') parser.add_option('-r', '--auto-reload', action='store_true', dest='autoreload', help='restart automatically when sources are modified') parser.add_option('-s', '--single-env', action='store_true', dest='single_env', help='only serve a single ' 'project without the project list', default=False) if os.name == 'posix': parser.add_option('-d', '--daemonize', action='store_true', dest='daemonize', help='run in the background as a daemon') parser.add_option('--pidfile', action='store', dest='pidfile', help='When daemonizing, file to which to write pid') parser.add_option('--umask', action='callback', type='string', dest='umask', metavar='MASK', callback=_octal, help='When daemonizing, file mode creation mask ' 'to use, in octal notation (default 022)') parser.set_defaults(port=None, hostname='', base_path='', daemonize=False, protocol='http', http11=True, umask=022) options, args = parser.parse_args() if not args and not options.env_parent_dir: parser.error('either the --env-parent-dir option or at least one ' 'environment must be specified') if options.single_env: if options.env_parent_dir: parser.error('the --single-env option cannot be used with ' '--env-parent-dir') elif len(args) > 1: parser.error('the --single-env option cannot be used with ' 'more than one enviroment') if options.daemonize and options.autoreload: parser.error('the --auto-reload option cannot be used with ' '--daemonize') if options.port is None: options.port = { 'http': 80, 'scgi': 4000, 'ajp': 8009, 'fcgi': 8000, }[options.protocol] server_address = (options.hostname, options.port) # relative paths don't work when daemonized args = [os.path.abspath(a) for a in args] if options.env_parent_dir: options.env_parent_dir = os.path.abspath(options.env_parent_dir) if parser.has_option('pidfile') and options.pidfile: options.pidfile = os.path.abspath(options.pidfile) wsgi_app = TracEnvironMiddleware(dispatch_request, options.env_parent_dir, args, options.single_env) if auths: if options.single_env: project_name = os.path.basename(args[0]) wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name) else: wsgi_app = AuthenticationMiddleware(wsgi_app, auths) base_path = options.base_path.strip('/') if base_path: wsgi_app = BasePathMiddleware(wsgi_app, base_path) if options.protocol == 'http': def serve(): httpd = TracHTTPServer(server_address, wsgi_app, options.env_parent_dir, args, use_http_11=options.http11) print 'Server starting in PID %i.' % os.getpid() addr, port = server_address if not addr or addr == '0.0.0.0': print 'Serving on 0.0.0.0:%s view at http://127.0.0.1:%s/%s' \ % (port, port, base_path) else: print 'Serving on http://%s:%s/%s' % (addr, port, base_path) if options.http11: print 'Using HTTP/1.1 protocol version' httpd.serve_forever() elif options.protocol in ('scgi', 'ajp', 'fcgi'): def serve(): server_cls = __import__('flup.server.%s' % options.protocol, None, None, ['']).WSGIServer flup_app = wsgi_app if options.unquote: from trac.web.fcgi_frontend import FlupMiddleware flup_app = FlupMiddleware(flup_app) ret = server_cls(flup_app, bindAddress=server_address).run() sys.exit(ret and 42 or 0) # if SIGHUP exit with status 42 try: if options.daemonize: daemon.daemonize(pidfile=options.pidfile, progname='tracd', umask=options.umask) if options.autoreload: def modification_callback(file): print >> sys.stderr, 'Detected modification of %s, ' \ 'restarting.' % file autoreload.main(serve, modification_callback) else: serve() except OSError: sys.exit(1) except KeyboardInterrupt: pass
def main(): from optparse import OptionParser, OptionValueError parser = OptionParser(usage='usage: %prog [options] [projenv] ...', version='%%prog %s' % VERSION) auths = {} def _auth_callback(option, opt_str, value, parser, cls): info = value.split(',', 3) if len(info) != 3: raise OptionValueError("Incorrect number of parameters for %s" % option) env_name, filename, realm = info if env_name in auths: print('Ignoring duplicate authentication option for project: %s' % env_name, file=sys.stderr) else: auths[env_name] = cls(os.path.abspath(filename), realm) def _validate_callback(option, opt_str, value, parser, valid_values): if value not in valid_values: raise OptionValueError('%s must be one of: %s, not %s' % (opt_str, '|'.join(valid_values), value)) setattr(parser.values, option.dest, value) def _octal(option, opt_str, value, parser): try: setattr(parser.values, option.dest, int(value, 8)) except ValueError: raise OptionValueError('Invalid octal umask value: %r' % value) parser.add_option('-a', '--auth', action='callback', type='string', metavar='DIGESTAUTH', callback=_auth_callback, callback_args=(DigestAuthentication, ), help='[projectdir],[htdigest_file],[realm]') parser.add_option('--basic-auth', action='callback', type='string', metavar='BASICAUTH', callback=_auth_callback, callback_args=(BasicAuthentication, ), help='[projectdir],[htpasswd_file],[realm]') parser.add_option('-p', '--port', action='store', type='int', dest='port', help='the port number to bind to') parser.add_option('-b', '--hostname', action='store', dest='hostname', help='the host name or IP address to bind to') parser.add_option('--protocol', action='callback', type="string", dest='protocol', callback=_validate_callback, callback_args=(('http', 'scgi', 'ajp', 'fcgi'), ), help='http|scgi|ajp|fcgi') parser.add_option('-q', '--unquote', action='store_true', dest='unquote', help='unquote PATH_INFO (may be needed when using ajp)') parser.add_option('--http10', action='store_false', dest='http11', help='use HTTP/1.0 protocol version instead of HTTP/1.1') parser.add_option('--http11', action='store_true', dest='http11', help='use HTTP/1.1 protocol version (default)') parser.add_option('-e', '--env-parent-dir', action='store', dest='env_parent_dir', metavar='PARENTDIR', help='parent directory of the project environments') parser.add_option( '--base-path', action='store', type='string', # XXX call this url_base_path? dest='base_path', help='the initial portion of the request URL\'s "path"') parser.add_option('-r', '--auto-reload', action='store_true', dest='autoreload', help='restart automatically when sources are modified') parser.add_option('-s', '--single-env', action='store_true', dest='single_env', help='only serve a single ' 'project without the project list', default=False) if os.name == 'posix': parser.add_option('-d', '--daemonize', action='store_true', dest='daemonize', help='run in the background as a daemon') parser.add_option('--pidfile', action='store', dest='pidfile', help='when daemonizing, file to which to write pid') parser.add_option('--umask', action='callback', type='string', dest='umask', metavar='MASK', callback=_octal, help='when daemonizing, file mode creation mask ' 'to use, in octal notation (default 022)') try: import grp, pwd def _group(option, opt_str, value, parser): try: value = int(value) except ValueError: try: value = grp.getgrnam(value)[2] except KeyError: raise OptionValueError('group not found: %r' % value) setattr(parser.values, option.dest, value) def _user(option, opt_str, value, parser): try: value = int(value) except ValueError: try: value = pwd.getpwnam(value)[2] except KeyError: raise OptionValueError('user not found: %r' % value) setattr(parser.values, option.dest, value) parser.add_option('--group', action='callback', type='string', dest='group', metavar='GROUP', callback=_group, help='the group to run as') parser.add_option('--user', action='callback', type='string', dest='user', metavar='USER', callback=_user, help='the user to run as') except ImportError: pass parser.set_defaults(port=None, hostname='', base_path='', daemonize=False, protocol='http', http11=True, umask=022, user=None, group=None) options, args = parser.parse_args() if not args and not options.env_parent_dir: parser.error('either the --env-parent-dir option or at least one ' 'environment must be specified') if options.single_env: if options.env_parent_dir: parser.error('the --single-env option cannot be used with ' '--env-parent-dir') elif len(args) > 1: parser.error('the --single-env option cannot be used with ' 'more than one enviroment') if options.daemonize and options.autoreload: parser.error('the --auto-reload option cannot be used with ' '--daemonize') if options.port is None: options.port = { 'http': 80, 'scgi': 4000, 'ajp': 8009, 'fcgi': 8000, }[options.protocol] server_address = (options.hostname, options.port) # relative paths don't work when daemonized args = [os.path.abspath(a) for a in args] if options.env_parent_dir: options.env_parent_dir = os.path.abspath(options.env_parent_dir) if parser.has_option('pidfile') and options.pidfile: options.pidfile = os.path.abspath(options.pidfile) wsgi_app = TracEnvironMiddleware(dispatch_request, options.env_parent_dir, args, options.single_env) if auths: if options.single_env: project_name = os.path.basename(args[0]) wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name) else: wsgi_app = AuthenticationMiddleware(wsgi_app, auths) base_path = options.base_path.strip('/') if base_path: wsgi_app = BasePathMiddleware(wsgi_app, base_path) if options.protocol == 'http': def serve(): addr, port = server_address if not addr or addr == '0.0.0.0': loc = '0.0.0.0:%s view at http://127.0.0.1:%s/%s' \ % (port, port, base_path) else: loc = 'http://%s:%s/%s' % (addr, port, base_path) try: httpd = TracHTTPServer(server_address, wsgi_app, options.env_parent_dir, args, use_http_11=options.http11) except socket.error as e: print("Error starting Trac server on %s" % loc) print("[Errno %s] %s" % e.args) sys.exit(1) print("Server starting in PID %s." % os.getpid()) print("Serving on %s" % loc) if options.http11: print("Using HTTP/1.1 protocol version") httpd.serve_forever() elif options.protocol in ('scgi', 'ajp', 'fcgi'): def serve(): server_cls = __import__('flup.server.%s' % options.protocol, None, None, ['']).WSGIServer flup_app = wsgi_app if options.unquote: from trac.web.fcgi_frontend import FlupMiddleware flup_app = FlupMiddleware(flup_app) ret = server_cls(flup_app, bindAddress=server_address).run() sys.exit(42 if ret else 0) # if SIGHUP exit with status 42 try: if options.daemonize: daemon.daemonize(pidfile=options.pidfile, progname='tracd', umask=options.umask) if options.group is not None: os.setgid(options.group) if options.user is not None: os.setuid(options.user) if options.autoreload: def modification_callback(file): print("Detected modification of %s, restarting." % file, file=sys.stderr) autoreload.main(serve, modification_callback) else: serve() except OSError as e: print("%s: %s" % (e.__class__.__name__, e), file=sys.stderr) sys.exit(1) except KeyboardInterrupt: pass
def main(): args = parse_args() wsgi_app = TracEnvironMiddleware(dispatch_request, args.env_parent_dir, args.envs, args.single_env) if args.auths: if args.single_env: project_name = os.path.basename(args.envs[0]) wsgi_app = AuthenticationMiddleware(wsgi_app, args.auths, project_name) else: wsgi_app = AuthenticationMiddleware(wsgi_app, args.auths) base_path = args.base_path.strip('/') if base_path: wsgi_app = BasePathMiddleware(wsgi_app, base_path) server_address = (args.hostname, args.port) if args.protocol in ('http', 'https'): def serve(): addr, port = server_address if not addr or addr == '0.0.0.0': loc = '0.0.0.0:%s view at %s://127.0.0.1:%s/%s' \ % (port, args.protocol, port, base_path) else: loc = '%s://%s:%s/%s' % (args.protocol, addr, port, base_path) try: httpd = TracHTTPServer(server_address, wsgi_app, args.env_parent_dir, args.envs, use_http_11=args.http11) except socket.error as e: print("Error starting Trac server on %s" % loc) print("[Errno %s] %s" % e.args) sys.exit(1) print("Server starting in PID %s." % os.getpid()) print("Serving on %s" % loc) if args.http11: print("Using HTTP/1.1 protocol version") if args.protocol == 'https': httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile=args.certfile, keyfile=args.keyfile) httpd.serve_forever() elif args.protocol in ('scgi', 'ajp', 'fcgi'): def serve(): module = 'flup.server.%s' % args.protocol try: server_cls = importlib.import_module(module).WSGIServer except ImportError: printerr("Install the flup package to use the '%s' " "protocol" % args.protocol) sys.exit(1) flup_app = wsgi_app if args.unquote: from trac.web.fcgi_frontend import FlupMiddleware flup_app = FlupMiddleware(flup_app) ret = server_cls(flup_app, bindAddress=server_address).run() sys.exit(42 if ret else 0) # if SIGHUP exit with status 42 try: if args.daemonize: daemon.daemonize(pidfile=args.pidfile, progname='tracd', umask=args.umask) if args.group is not None: os.setgid(args.group) if args.user is not None: os.setuid(args.user) if args.auto_reload: def modification_callback(file): printerr("Detected modification of %s, restarting." % file) autoreload.main(serve, modification_callback) else: serve() except OSError as e: printerr("%s: %s" % (e.__class__.__name__, e)) sys.exit(1) except KeyboardInterrupt: pass
def main(): from optparse import OptionParser, OptionValueError parser = OptionParser(usage="usage: %prog [options] [projenv] ...", version="%%prog %s" % VERSION) auths = {} def _auth_callback(option, opt_str, value, parser, cls): info = value.split(",", 3) if len(info) != 3: raise OptionValueError(u"Nombre de parametres incorrects pour %s" % option) env_name, filename, realm = info if env_name in auths: print >>sys.stderr, "Ignoring duplicate authentication option for " "project: %s" % env_name else: auths[env_name] = cls(filename, realm) def _validate_callback(option, opt_str, value, parser, valid_values): if value not in valid_values: raise OptionValueError("%s must be one of: %s, not %s" % (opt_str, "|".join(valid_values), value)) setattr(parser.values, option.dest, value) parser.add_option( "-a", "--auth", action="callback", type="string", metavar="DIGESTAUTH", callback=_auth_callback, callback_args=(DigestAuthentication,), help="[projectdir],[htdigest_file],[realm]", ) parser.add_option( "--basic-auth", action="callback", type="string", metavar="BASICAUTH", callback=_auth_callback, callback_args=(BasicAuthentication,), help="[projectdir],[htpasswd_file],[realm]", ) parser.add_option("-p", "--port", action="store", type="int", dest="port", help="the port number to bind to") parser.add_option( "-b", "--hostname", action="store", dest="hostname", help="the host name or IP address to bind to" ) parser.add_option( "--protocol", action="callback", type="string", dest="protocol", callback=_validate_callback, callback_args=(("http", "scgi", "ajp"),), help="http|scgi|ajp", ) parser.add_option( "-e", "--env-parent-dir", action="store", dest="env_parent_dir", metavar="PARENTDIR", help="parent directory of the project environments", ) parser.add_option( "--base-path", action="store", type="string", dest="base_path", help="base path" # XXX call this url_base_path? ) parser.add_option( "-r", "--auto-reload", action="store_true", dest="autoreload", help="restart automatically when sources are modified", ) parser.add_option( "-s", "--single-env", action="store_true", dest="single_env", help="only serve a single " "project without the project list", default=False, ) if os.name == "posix": parser.add_option( "-d", "--daemonize", action="store_true", dest="daemonize", help="run in the background as a daemon" ) parser.add_option( "--pidfile", action="store", dest="pidfile", help="When daemonizing, file to which to write pid" ) parser.set_defaults(port=None, hostname="", base_path="", daemonize=False, protocol="http") options, args = parser.parse_args() if not args and not options.env_parent_dir: parser.error("either the --env-parent-dir option or at least one " "environment must be specified") if options.single_env and len(args) > 1: parser.error("the --single-env option cannot be used with more " "than one enviroment") if options.port is None: options.port = {"http": 80, "scgi": 4000, "ajp": 8009}[options.protocol] server_address = (options.hostname, options.port) wsgi_app = TracEnvironMiddleware(dispatch_request, options.env_parent_dir, args, options.single_env) if auths: if options.single_env: project_name = os.path.basename(os.path.normpath(args[0])) wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name) else: wsgi_app = AuthenticationMiddleware(wsgi_app, auths) base_path = options.base_path.strip("/") if base_path: wsgi_app = BasePathMiddleware(wsgi_app, base_path) if options.protocol == "http": def serve(): httpd = TracHTTPServer(server_address, wsgi_app, options.env_parent_dir, args) httpd.serve_forever() elif options.protocol in ("scgi", "ajp"): def serve(): server_cls = __import__("flup.server.%s" % options.protocol, None, None, [""]).WSGIServer ret = server_cls(wsgi_app, bindAddress=server_address).run() sys.exit(ret and 42 or 0) # if SIGHUP exit with status 42 try: if os.name == "posix": if options.pidfile: options.pidfile = os.path.abspath(options.pidfile) if os.path.exists(options.pidfile): pidfile = open(options.pidfile) try: pid = int(pidfile.read()) finally: pidfile.close() try: # signal the process to see if it is still running os.kill(pid, 0) except OSError, e: if e.errno != errno.ESRCH: raise else: sys.exit("tracd is already running with pid %s" % pid) realserve = serve def serve(): try: pidfile = open(options.pidfile, "w") try: pidfile.write(str(os.getpid())) finally: pidfile.close() realserve() finally: if os.path.exists(options.pidfile): os.remove(options.pidfile) if options.daemonize: daemon.daemonize() if options.autoreload: def modification_callback(file): print >>sys.stderr, "Detected modification of %s, restarting." % file autoreload.main(serve, modification_callback) else: serve()
def main(): from optparse import OptionParser, OptionValueError parser = OptionParser(usage='usage: %prog [options] [projenv] ...', version='%%prog %s' % VERSION) auths = {} def _auth_callback(option, opt_str, value, parser, cls): info = value.split(',', 3) if len(info) != 3: raise OptionValueError(u"Nombre de parametres incorrects pour %s" % option) env_name, filename, realm = info if env_name in auths: print >>sys.stderr, 'Ignoring duplicate authentication option for ' \ 'project: %s' % env_name else: auths[env_name] = cls(filename, realm) def _validate_callback(option, opt_str, value, parser, valid_values): if value not in valid_values: raise OptionValueError('%s must be one of: %s, not %s' % (opt_str, '|'.join(valid_values), value)) setattr(parser.values, option.dest, value) parser.add_option('-a', '--auth', action='callback', type='string', metavar='DIGESTAUTH', callback=_auth_callback, callback_args=(DigestAuthentication, ), help='[projectdir],[htdigest_file],[realm]') parser.add_option('--basic-auth', action='callback', type='string', metavar='BASICAUTH', callback=_auth_callback, callback_args=(BasicAuthentication, ), help='[projectdir],[htpasswd_file],[realm]') parser.add_option('-p', '--port', action='store', type='int', dest='port', help='the port number to bind to') parser.add_option('-b', '--hostname', action='store', dest='hostname', help='the host name or IP address to bind to') parser.add_option('--protocol', action='callback', type="string", dest='protocol', callback=_validate_callback, callback_args=(('http', 'scgi', 'ajp'), ), help='http|scgi|ajp') parser.add_option('-e', '--env-parent-dir', action='store', dest='env_parent_dir', metavar='PARENTDIR', help='parent directory of the project environments') parser.add_option( '--base-path', action='store', type='string', # XXX call this url_base_path? dest='base_path', help='base path') parser.add_option('-r', '--auto-reload', action='store_true', dest='autoreload', help='restart automatically when sources are modified') parser.add_option('-s', '--single-env', action='store_true', dest='single_env', help='only serve a single ' 'project without the project list', default=False) if os.name == 'posix': parser.add_option('-d', '--daemonize', action='store_true', dest='daemonize', help='run in the background as a daemon') parser.add_option('--pidfile', action='store', dest='pidfile', help='When daemonizing, file to which to write pid') parser.set_defaults(port=None, hostname='', base_path='', daemonize=False, protocol='http') options, args = parser.parse_args() if not args and not options.env_parent_dir: parser.error('either the --env-parent-dir option or at least one ' 'environment must be specified') if options.single_env and len(args) > 1: parser.error('the --single-env option cannot be used with more ' 'than one enviroment') if options.port is None: options.port = { 'http': 80, 'scgi': 4000, 'ajp': 8009, }[options.protocol] server_address = (options.hostname, options.port) wsgi_app = TracEnvironMiddleware(dispatch_request, options.env_parent_dir, args, options.single_env) if auths: if options.single_env: project_name = os.path.basename(os.path.normpath(args[0])) wsgi_app = AuthenticationMiddleware(wsgi_app, auths, project_name) else: wsgi_app = AuthenticationMiddleware(wsgi_app, auths) base_path = options.base_path.strip('/') if base_path: wsgi_app = BasePathMiddleware(wsgi_app, base_path) if options.protocol == 'http': def serve(): httpd = TracHTTPServer(server_address, wsgi_app, options.env_parent_dir, args) httpd.serve_forever() elif options.protocol in ('scgi', 'ajp'): def serve(): server_cls = __import__('flup.server.%s' % options.protocol, None, None, ['']).WSGIServer ret = server_cls(wsgi_app, bindAddress=server_address).run() sys.exit(ret and 42 or 0) # if SIGHUP exit with status 42 try: if os.name == 'posix': if options.pidfile: options.pidfile = os.path.abspath(options.pidfile) if os.path.exists(options.pidfile): pidfile = open(options.pidfile) try: pid = int(pidfile.read()) finally: pidfile.close() try: # signal the process to see if it is still running os.kill(pid, 0) except OSError, e: if e.errno != errno.ESRCH: raise else: sys.exit("tracd is already running with pid %s" % pid) realserve = serve def serve(): try: pidfile = open(options.pidfile, 'w') try: pidfile.write(str(os.getpid())) finally: pidfile.close() realserve() finally: if os.path.exists(options.pidfile): os.remove(options.pidfile) if options.daemonize: daemon.daemonize() if options.autoreload: def modification_callback(file): print>>sys.stderr, 'Detected modification of %s, restarting.' \ % file autoreload.main(serve, modification_callback) else: serve()