Package web2py :: Package gluon :: Module widget
[hide private]
[frames] | no frames]

Source Code for Module web2py.gluon.widget

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  """ 
  5  This file is part of the web2py Web Framework 
  6  Copyrighted by Massimo Di Pierro <mdipierro@cs.depaul.edu> 
  7  License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html) 
  8   
  9  The widget is called from web2py. 
 10  """ 
 11   
 12  import sys 
 13  import cStringIO 
 14  import time 
 15  import thread 
 16  import re 
 17  import os 
 18  import socket 
 19  import signal 
 20  import math 
 21  import logging 
 22   
 23  import newcron 
 24  import main 
 25   
 26  from fileutils import w2p_pack, read_file, write_file 
 27  from shell import run, test 
 28  from settings import global_settings 
 29   
 30  try: 
 31      import Tkinter, tkMessageBox 
 32      import contrib.taskbar_widget 
 33      from winservice import web2py_windows_service_handler 
 34  except: 
 35      pass 
 36   
 37   
 38  try: 
 39      BaseException 
 40  except NameError: 
 41      BaseException = Exception 
 42   
 43  ProgramName = 'web2py Web Framework' 
 44  ProgramAuthor = 'Created by Massimo Di Pierro, Copyright 2007-2011' 
 45  ProgramVersion = read_file('VERSION').strip() 
 46   
 47  ProgramInfo = '''%s 
 48                   %s 
 49                   %s''' % (ProgramName, ProgramAuthor, ProgramVersion) 
 50   
 51  if not sys.version[:3] in ['2.4', '2.5', '2.6', '2.7']: 
 52      msg = 'Warning: web2py requires Python 2.4, 2.5 (recommended), 2.6 or 2.7 but you are running:\n%s' 
 53      msg = msg % sys.version 
 54      sys.stderr.write(msg) 
 55   
 56  logger = logging.getLogger("web2py") 
 57   
58 -class IO(object):
59 """ """ 60
61 - def __init__(self):
62 """ """ 63 64 self.buffer = cStringIO.StringIO()
65
66 - def write(self, data):
67 """ """ 68 69 sys.__stdout__.write(data) 70 if hasattr(self, 'callback'): 71 self.callback(data) 72 else: 73 self.buffer.write(data)
74 75
76 -def try_start_browser(url):
77 """ Try to start the default browser """ 78 79 try: 80 import webbrowser 81 webbrowser.open(url) 82 except: 83 print 'warning: unable to detect your browser'
84 85
86 -def start_browser(ip, port):
87 """ Starts the default browser """ 88 print 'please visit:' 89 print '\thttp://%s:%s' % (ip, port) 90 print 'starting browser...' 91 try_start_browser('http://%s:%s' % (ip, port))
92 93
94 -def presentation(root):
95 """ Draw the splash screen """ 96 97 root.withdraw() 98 99 dx = root.winfo_screenwidth() 100 dy = root.winfo_screenheight() 101 102 dialog = Tkinter.Toplevel(root, bg='white') 103 dialog.geometry('%ix%i+%i+%i' % (500, 300, dx / 2 - 200, dy / 2 - 150)) 104 105 dialog.overrideredirect(1) 106 dialog.focus_force() 107 108 canvas = Tkinter.Canvas(dialog, 109 background='white', 110 width=500, 111 height=300) 112 canvas.pack() 113 root.update() 114 115 img = Tkinter.PhotoImage(file='splashlogo.gif') 116 pnl = Tkinter.Label(canvas, image=img, background='white', bd=0) 117 pnl.pack(side='top', fill='both', expand='yes') 118 # Prevent garbage collection of img 119 pnl.image=img 120 121 def add_label(text='Change Me', font_size=12, foreground='#195866', height=1): 122 return Tkinter.Label( 123 master=canvas, 124 width=250, 125 height=height, 126 text=text, 127 font=('Helvetica', font_size), 128 anchor=Tkinter.CENTER, 129 foreground=foreground, 130 background='white' 131 )
132 133 add_label('Welcome to...').pack(side='top') 134 add_label(ProgramName, 18, '#FF5C1F', 2).pack() 135 add_label(ProgramAuthor).pack() 136 add_label(ProgramVersion).pack() 137 138 root.update() 139 time.sleep(5) 140 dialog.destroy() 141 return 142 143
144 -class web2pyDialog(object):
145 """ Main window dialog """ 146
147 - def __init__(self, root, options):
148 """ web2pyDialog constructor """ 149 150 root.title('web2py server') 151 self.root = Tkinter.Toplevel(root) 152 self.options = options 153 self.menu = Tkinter.Menu(self.root) 154 servermenu = Tkinter.Menu(self.menu, tearoff=0) 155 httplog = os.path.join(self.options.folder, 'httpserver.log') 156 157 # Building the Menu 158 item = lambda: try_start_browser(httplog) 159 servermenu.add_command(label='View httpserver.log', 160 command=item) 161 162 servermenu.add_command(label='Quit (pid:%i)' % os.getpid(), 163 command=self.quit) 164 165 self.menu.add_cascade(label='Server', menu=servermenu) 166 167 self.pagesmenu = Tkinter.Menu(self.menu, tearoff=0) 168 self.menu.add_cascade(label='Pages', menu=self.pagesmenu) 169 170 helpmenu = Tkinter.Menu(self.menu, tearoff=0) 171 172 # Home Page 173 item = lambda: try_start_browser('http://www.web2py.com') 174 helpmenu.add_command(label='Home Page', 175 command=item) 176 177 # About 178 item = lambda: tkMessageBox.showinfo('About web2py', ProgramInfo) 179 helpmenu.add_command(label='About', 180 command=item) 181 182 self.menu.add_cascade(label='Info', menu=helpmenu) 183 184 self.root.config(menu=self.menu) 185 186 if options.taskbar: 187 self.root.protocol('WM_DELETE_WINDOW', 188 lambda: self.quit(True)) 189 else: 190 self.root.protocol('WM_DELETE_WINDOW', self.quit) 191 192 sticky = Tkinter.NW 193 194 # IP 195 Tkinter.Label(self.root, 196 text='Server IP:', 197 justify=Tkinter.LEFT).grid(row=0, 198 column=0, 199 sticky=sticky) 200 self.ip = Tkinter.Entry(self.root) 201 self.ip.insert(Tkinter.END, self.options.ip) 202 self.ip.grid(row=0, column=1, sticky=sticky) 203 204 # Port 205 Tkinter.Label(self.root, 206 text='Server Port:', 207 justify=Tkinter.LEFT).grid(row=1, 208 column=0, 209 sticky=sticky) 210 211 self.port_number = Tkinter.Entry(self.root) 212 self.port_number.insert(Tkinter.END, self.options.port) 213 self.port_number.grid(row=1, column=1, sticky=sticky) 214 215 # Password 216 Tkinter.Label(self.root, 217 text='Choose Password:', 218 justify=Tkinter.LEFT).grid(row=2, 219 column=0, 220 sticky=sticky) 221 222 self.password = Tkinter.Entry(self.root, show='*') 223 self.password.bind('<Return>', lambda e: self.start()) 224 self.password.focus_force() 225 self.password.grid(row=2, column=1, sticky=sticky) 226 227 # Prepare the canvas 228 self.canvas = Tkinter.Canvas(self.root, 229 width=300, 230 height=100, 231 bg='black') 232 self.canvas.grid(row=3, column=0, columnspan=2) 233 self.canvas.after(1000, self.update_canvas) 234 235 # Prepare the frame 236 frame = Tkinter.Frame(self.root) 237 frame.grid(row=4, column=0, columnspan=2) 238 239 # Start button 240 self.button_start = Tkinter.Button(frame, 241 text='start server', 242 command=self.start) 243 244 self.button_start.grid(row=0, column=0) 245 246 # Stop button 247 self.button_stop = Tkinter.Button(frame, 248 text='stop server', 249 command=self.stop) 250 251 self.button_stop.grid(row=0, column=1) 252 self.button_stop.configure(state='disabled') 253 254 if options.taskbar: 255 self.tb = contrib.taskbar_widget.TaskBarIcon() 256 self.checkTaskBar() 257 258 if options.password != '<ask>': 259 self.password.insert(0, options.password) 260 self.start() 261 self.root.withdraw() 262 else: 263 self.tb = None
264
265 - def checkTaskBar(self):
266 """ Check taskbar status """ 267 268 if self.tb.status: 269 if self.tb.status[0] == self.tb.EnumStatus.QUIT: 270 self.quit() 271 elif self.tb.status[0] == self.tb.EnumStatus.TOGGLE: 272 if self.root.state() == 'withdrawn': 273 self.root.deiconify() 274 else: 275 self.root.withdraw() 276 elif self.tb.status[0] == self.tb.EnumStatus.STOP: 277 self.stop() 278 elif self.tb.status[0] == self.tb.EnumStatus.START: 279 self.start() 280 elif self.tb.status[0] == self.tb.EnumStatus.RESTART: 281 self.stop() 282 self.start() 283 del self.tb.status[0] 284 285 self.root.after(1000, self.checkTaskBar)
286
287 - def update(self, text):
288 """ Update app text """ 289 290 try: 291 self.text.configure(state='normal') 292 self.text.insert('end', text) 293 self.text.configure(state='disabled') 294 except: 295 pass # ## this should only happen in case app is destroyed
296
297 - def connect_pages(self):
298 """ Connect pages """ 299 300 for arq in os.listdir('applications/'): 301 if os.path.exists('applications/%s/__init__.py' % arq): 302 url = self.url + '/' + arq 303 start_browser = lambda u = url: try_start_browser(u) 304 self.pagesmenu.add_command(label=url, 305 command=start_browser)
306
307 - def quit(self, justHide=False):
308 """ Finish the program execution """ 309 310 if justHide: 311 self.root.withdraw() 312 else: 313 try: 314 self.server.stop() 315 except: 316 pass 317 318 try: 319 self.tb.Destroy() 320 except: 321 pass 322 323 self.root.destroy() 324 sys.exit()
325
326 - def error(self, message):
327 """ Show error message """ 328 329 tkMessageBox.showerror('web2py start server', message)
330
331 - def start(self):
332 """ Start web2py server """ 333 334 password = self.password.get() 335 336 if not password: 337 self.error('no password, no web admin interface') 338 339 ip = self.ip.get() 340 341 regexp = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}' 342 if ip and not re.compile(regexp).match(ip): 343 return self.error('invalid host ip address') 344 345 try: 346 port = int(self.port_number.get()) 347 except: 348 return self.error('invalid port number') 349 350 self.url = 'http://%s:%s' % (ip, port) 351 self.connect_pages() 352 self.button_start.configure(state='disabled') 353 354 try: 355 options = self.options 356 req_queue_size = options.request_queue_size 357 self.server = main.HttpServer( 358 ip, 359 port, 360 password, 361 pid_filename=options.pid_filename, 362 log_filename=options.log_filename, 363 profiler_filename=options.profiler_filename, 364 ssl_certificate=options.ssl_certificate, 365 ssl_private_key=options.ssl_private_key, 366 min_threads=options.minthreads, 367 max_threads=options.maxthreads, 368 server_name=options.server_name, 369 request_queue_size=req_queue_size, 370 timeout=options.timeout, 371 shutdown_timeout=options.shutdown_timeout, 372 path=options.folder, 373 interfaces=options.interfaces) 374 375 thread.start_new_thread(self.server.start, ()) 376 except Exception, e: 377 self.button_start.configure(state='normal') 378 return self.error(str(e)) 379 380 self.button_stop.configure(state='normal') 381 382 if not options.taskbar: 383 thread.start_new_thread(start_browser, (ip, port)) 384 385 self.password.configure(state='readonly') 386 self.ip.configure(state='readonly') 387 self.port_number.configure(state='readonly') 388 389 if self.tb: 390 self.tb.SetServerRunning()
391
392 - def stop(self):
393 """ Stop web2py server """ 394 395 self.button_start.configure(state='normal') 396 self.button_stop.configure(state='disabled') 397 self.password.configure(state='normal') 398 self.ip.configure(state='normal') 399 self.port_number.configure(state='normal') 400 self.server.stop() 401 402 if self.tb: 403 self.tb.SetServerStopped()
404
405 - def update_canvas(self):
406 """ Update canvas """ 407 408 try: 409 t1 = os.path.getsize('httpserver.log') 410 except: 411 self.canvas.after(1000, self.update_canvas) 412 return 413 414 try: 415 fp = open('httpserver.log', 'r') 416 fp.seek(self.t0) 417 data = fp.read(t1 - self.t0) 418 fp.close() 419 value = self.p0[1:] + [10 + 90.0 / math.sqrt(1 + data.count('\n'))] 420 self.p0 = value 421 422 for i in xrange(len(self.p0) - 1): 423 c = self.canvas.coords(self.q0[i]) 424 self.canvas.coords(self.q0[i], 425 (c[0], 426 self.p0[i], 427 c[2], 428 self.p0[i + 1])) 429 self.t0 = t1 430 except BaseException: 431 self.t0 = time.time() 432 self.t0 = t1 433 self.p0 = [100] * 300 434 self.q0 = [self.canvas.create_line(i, 100, i + 1, 100, 435 fill='green') for i in xrange(len(self.p0) - 1)] 436 437 self.canvas.after(1000, self.update_canvas)
438 439
440 -def console():
441 """ Defines the behavior of the console web2py execution """ 442 import optparse 443 import textwrap 444 445 usage = "python web2py.py" 446 447 description = """\ 448 web2py Web Framework startup script. 449 ATTENTION: unless a password is specified (-a 'passwd') web2py will 450 attempt to run a GUI. In this case command line options are ignored.""" 451 452 description = textwrap.dedent(description) 453 454 parser = optparse.OptionParser(usage, None, optparse.Option, ProgramVersion) 455 456 parser.description = description 457 458 parser.add_option('-i', 459 '--ip', 460 default='127.0.0.1', 461 dest='ip', 462 help='ip address of the server (127.0.0.1)') 463 464 parser.add_option('-p', 465 '--port', 466 default='8000', 467 dest='port', 468 type='int', 469 help='port of server (8000)') 470 471 msg = 'password to be used for administration' 472 msg += ' (use -a "<recycle>" to reuse the last password))' 473 parser.add_option('-a', 474 '--password', 475 default='<ask>', 476 dest='password', 477 help=msg) 478 479 parser.add_option('-c', 480 '--ssl_certificate', 481 default='', 482 dest='ssl_certificate', 483 help='file that contains ssl certificate') 484 485 parser.add_option('-k', 486 '--ssl_private_key', 487 default='', 488 dest='ssl_private_key', 489 help='file that contains ssl private key') 490 491 parser.add_option('-d', 492 '--pid_filename', 493 default='httpserver.pid', 494 dest='pid_filename', 495 help='file to store the pid of the server') 496 497 parser.add_option('-l', 498 '--log_filename', 499 default='httpserver.log', 500 dest='log_filename', 501 help='file to log connections') 502 503 parser.add_option('-n', 504 '--numthreads', 505 default=None, 506 type='int', 507 dest='numthreads', 508 help='number of threads (deprecated)') 509 510 parser.add_option('--minthreads', 511 default=None, 512 type='int', 513 dest='minthreads', 514 help='minimum number of server threads') 515 516 parser.add_option('--maxthreads', 517 default=None, 518 type='int', 519 dest='maxthreads', 520 help='maximum number of server threads') 521 522 parser.add_option('-s', 523 '--server_name', 524 default=socket.gethostname(), 525 dest='server_name', 526 help='server name for the web server') 527 528 msg = 'max number of queued requests when server unavailable' 529 parser.add_option('-q', 530 '--request_queue_size', 531 default='5', 532 type='int', 533 dest='request_queue_size', 534 help=msg) 535 536 parser.add_option('-o', 537 '--timeout', 538 default='10', 539 type='int', 540 dest='timeout', 541 help='timeout for individual request (10 seconds)') 542 543 parser.add_option('-z', 544 '--shutdown_timeout', 545 default='5', 546 type='int', 547 dest='shutdown_timeout', 548 help='timeout on shutdown of server (5 seconds)') 549 parser.add_option('-f', 550 '--folder', 551 default=os.getcwd(), 552 dest='folder', 553 help='folder from which to run web2py') 554 555 parser.add_option('-v', 556 '--verbose', 557 action='store_true', 558 dest='verbose', 559 default=False, 560 help='increase --test verbosity') 561 562 parser.add_option('-Q', 563 '--quiet', 564 action='store_true', 565 dest='quiet', 566 default=False, 567 help='disable all output') 568 569 msg = 'set debug output level (0-100, 0 means all, 100 means none;' 570 msg += ' default is 30)' 571 parser.add_option('-D', 572 '--debug', 573 dest='debuglevel', 574 default=30, 575 type='int', 576 help=msg) 577 578 msg = 'run web2py in interactive shell or IPython (if installed) with' 579 msg += ' specified appname (if app does not exist it will be created).' 580 parser.add_option('-S', 581 '--shell', 582 dest='shell', 583 metavar='APPNAME', 584 help=msg) 585 586 msg = 'run web2py in interactive shell or bpython (if installed) with' 587 msg += ' specified appname (if app does not exist it will be created).' 588 msg += '\n Use combined with --shell' 589 parser.add_option('-B', 590 '--bpython', 591 action='store_true', 592 default=False, 593 dest='bpython', 594 help=msg) 595 596 msg = 'only use plain python shell; should be used with --shell option' 597 parser.add_option('-P', 598 '--plain', 599 action='store_true', 600 default=False, 601 dest='plain', 602 help=msg) 603 604 msg = 'auto import model files; default is False; should be used' 605 msg += ' with --shell option' 606 parser.add_option('-M', 607 '--import_models', 608 action='store_true', 609 default=False, 610 dest='import_models', 611 help=msg) 612 613 msg = 'run PYTHON_FILE in web2py environment;' 614 msg += ' should be used with --shell option' 615 parser.add_option('-R', 616 '--run', 617 dest='run', 618 metavar='PYTHON_FILE', 619 default='', 620 help=msg) 621 622 msg = 'run doctests in web2py environment; ' +\ 623 'TEST_PATH like a/c/f (c,f optional)' 624 parser.add_option('-T', 625 '--test', 626 dest='test', 627 metavar='TEST_PATH', 628 default=None, 629 help=msg) 630 631 parser.add_option('-W', 632 '--winservice', 633 dest='winservice', 634 default='', 635 help='-W install|start|stop as Windows service') 636 637 msg = 'trigger a cron run manually; usually invoked from a system crontab' 638 parser.add_option('-C', 639 '--cron', 640 action='store_true', 641 dest='extcron', 642 default=False, 643 help=msg) 644 645 msg = 'triggers the use of softcron' 646 parser.add_option('--softcron', 647 action='store_true', 648 dest='softcron', 649 default=False, 650 help=msg) 651 652 parser.add_option('-N', 653 '--no-cron', 654 action='store_true', 655 dest='nocron', 656 default=False, 657 help='do not start cron automatically') 658 659 parser.add_option('-J', 660 '--cronjob', 661 action='store_true', 662 dest='cronjob', 663 default=False, 664 help='identify cron-initiated command') 665 666 parser.add_option('-L', 667 '--config', 668 dest='config', 669 default='', 670 help='config file') 671 672 parser.add_option('-F', 673 '--profiler', 674 dest='profiler_filename', 675 default=None, 676 help='profiler filename') 677 678 parser.add_option('-t', 679 '--taskbar', 680 action='store_true', 681 dest='taskbar', 682 default=False, 683 help='use web2py gui and run in taskbar (system tray)') 684 685 parser.add_option('', 686 '--nogui', 687 action='store_true', 688 default=False, 689 dest='nogui', 690 help='text-only, no GUI') 691 692 parser.add_option('-A', 693 '--args', 694 action='store', 695 dest='args', 696 default=None, 697 help='should be followed by a list of arguments to be passed to script, to be used with -S, -A must be the last option') 698 699 parser.add_option('--no-banner', 700 action='store_true', 701 default=False, 702 dest='nobanner', 703 help='Do not print header banner') 704 705 msg = 'listen on multiple addresses: "ip:port:cert:key;ip2:port2:cert2:key2;..." (:cert:key optional; no spaces)' 706 parser.add_option('--interfaces', 707 action='store', 708 dest='interfaces', 709 default=None, 710 help=msg) 711 712 if '-A' in sys.argv: k = sys.argv.index('-A') 713 elif '--args' in sys.argv: k = sys.argv.index('--args') 714 else: k=len(sys.argv) 715 sys.argv, other_args = sys.argv[:k], sys.argv[k+1:] 716 (options, args) = parser.parse_args() 717 options.args = [options.run] + other_args 718 global_settings.cmd_options = options 719 global_settings.cmd_args = args 720 721 if options.quiet: 722 capture = cStringIO.StringIO() 723 sys.stdout = capture 724 logger.setLevel(logging.CRITICAL + 1) 725 else: 726 logger.setLevel(options.debuglevel) 727 728 if options.config[-3:] == '.py': 729 options.config = options.config[:-3] 730 731 if options.cronjob: 732 global_settings.cronjob = True # tell the world 733 options.nocron = True # don't start cron jobs 734 options.plain = True # cronjobs use a plain shell 735 736 options.folder = os.path.abspath(options.folder) 737 738 # accept --interfaces in the form "ip:port:cert:key;ip2:port2;ip3:port3:cert3:key3" 739 # (no spaces; optional cert:key indicate SSL) 740 # 741 if isinstance(options.interfaces, str): 742 options.interfaces = [interface.split(':') for interface in options.interfaces.split(';')] 743 for interface in options.interfaces: 744 interface[1] = int(interface[1]) # numeric port 745 options.interfaces = [tuple(interface) for interface in options.interfaces] 746 747 if options.numthreads is not None and options.minthreads is None: 748 options.minthreads = options.numthreads # legacy 749 750 if not options.cronjob: 751 # If we have the applications package or if we should upgrade 752 if not os.path.exists('applications/__init__.py'): 753 write_file('applications/__init__.py', '') 754 755 if not os.path.exists('welcome.w2p') or os.path.exists('NEWINSTALL'): 756 try: 757 w2p_pack('welcome.w2p','applications/welcome') 758 os.unlink('NEWINSTALL') 759 except: 760 msg = "New installation: unable to create welcome.w2p file" 761 sys.stderr.write(msg) 762 763 return (options, args)
764 765
766 -def start(cron=True):
767 """ Start server """ 768 769 # ## get command line arguments 770 771 (options, args) = console() 772 773 if not options.nobanner: 774 print ProgramName 775 print ProgramAuthor 776 print ProgramVersion 777 778 from dal import drivers 779 if not options.nobanner: 780 print 'Database drivers available: %s' % ', '.join(drivers) 781 782 783 # ## if -L load options from options.config file 784 if options.config: 785 try: 786 options2 = __import__(options.config, {}, {}, '') 787 except Exception: 788 try: 789 # Jython doesn't like the extra stuff 790 options2 = __import__(options.config) 791 except Exception: 792 print 'Cannot import config file [%s]' % options.config 793 sys.exit(1) 794 for key in dir(options2): 795 if hasattr(options,key): 796 setattr(options,key,getattr(options2,key)) 797 798 # ## if -T run doctests (no cron) 799 if hasattr(options,'test') and options.test: 800 test(options.test, verbose=options.verbose) 801 return 802 803 # ## if -S start interactive shell (also no cron) 804 if options.shell: 805 if options.args!=None: 806 sys.argv[:] = options.args 807 run(options.shell, plain=options.plain, bpython=options.bpython, 808 import_models=options.import_models, startfile=options.run) 809 return 810 811 # ## if -C start cron run (extcron) and exit 812 # ## if -N or not cron disable cron in this *process* 813 # ## if --softcron use softcron 814 # ## use hardcron in all other cases 815 if options.extcron: 816 print 'Starting extcron...' 817 global_settings.web2py_crontype = 'external' 818 extcron = newcron.extcron(options.folder) 819 extcron.start() 820 extcron.join() 821 return 822 elif cron and not options.nocron and options.softcron: 823 print 'Using softcron (but this is not very efficient)' 824 global_settings.web2py_crontype = 'soft' 825 elif cron and not options.nocron: 826 print 'Starting hardcron...' 827 global_settings.web2py_crontype = 'hard' 828 newcron.hardcron(options.folder).start() 829 830 # ## if -W install/start/stop web2py as service 831 if options.winservice: 832 if os.name == 'nt': 833 web2py_windows_service_handler(['', options.winservice], 834 options.config) 835 else: 836 print 'Error: Windows services not supported on this platform' 837 sys.exit(1) 838 return 839 840 # ## if no password provided and havetk start Tk interface 841 # ## or start interface if we want to put in taskbar (system tray) 842 843 try: 844 options.taskbar 845 except: 846 options.taskbar = False 847 848 if options.taskbar and os.name != 'nt': 849 print 'Error: taskbar not supported on this platform' 850 sys.exit(1) 851 852 root = None 853 854 if not options.nogui: 855 try: 856 import Tkinter 857 havetk = True 858 except ImportError: 859 logger.warn('GUI not available because Tk library is not installed') 860 havetk = False 861 862 if options.password == '<ask>' and havetk or options.taskbar and havetk: 863 try: 864 root = Tkinter.Tk() 865 except: 866 pass 867 868 if root: 869 root.focus_force() 870 if not options.quiet: 871 presentation(root) 872 master = web2pyDialog(root, options) 873 signal.signal(signal.SIGTERM, lambda a, b: master.quit()) 874 875 try: 876 root.mainloop() 877 except: 878 master.quit() 879 880 sys.exit() 881 882 # ## if no tk and no password, ask for a password 883 884 if not root and options.password == '<ask>': 885 options.password = raw_input('choose a password:') 886 887 if not options.password and not options.nobanner: 888 print 'no password, no admin interface' 889 890 # ## start server 891 892 (ip, port) = (options.ip, int(options.port)) 893 894 if not options.nobanner: 895 print 'please visit:' 896 print '\thttp://%s:%s' % (ip, port) 897 print 'use "kill -SIGTERM %i" to shutdown the web2py server' % os.getpid() 898 899 server = main.HttpServer(ip=ip, 900 port=port, 901 password=options.password, 902 pid_filename=options.pid_filename, 903 log_filename=options.log_filename, 904 profiler_filename=options.profiler_filename, 905 ssl_certificate=options.ssl_certificate, 906 ssl_private_key=options.ssl_private_key, 907 min_threads=options.minthreads, 908 max_threads=options.maxthreads, 909 server_name=options.server_name, 910 request_queue_size=options.request_queue_size, 911 timeout=options.timeout, 912 shutdown_timeout=options.shutdown_timeout, 913 path=options.folder, 914 interfaces=options.interfaces) 915 916 try: 917 server.start() 918 except KeyboardInterrupt: 919 server.stop() 920 logging.shutdown()
921