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 msg += ' APPNAME like a/c/f (c,f optional)' 581 parser.add_option('-S', 582 '--shell', 583 dest='shell', 584 metavar='APPNAME', 585 help=msg) 586 587 msg = 'run web2py in interactive shell or bpython (if installed) with' 588 msg += ' specified appname (if app does not exist it will be created).' 589 msg += '\n Use combined with --shell' 590 parser.add_option('-B', 591 '--bpython', 592 action='store_true', 593 default=False, 594 dest='bpython', 595 help=msg) 596 597 msg = 'only use plain python shell; should be used with --shell option' 598 parser.add_option('-P', 599 '--plain', 600 action='store_true', 601 default=False, 602 dest='plain', 603 help=msg) 604 605 msg = 'auto import model files; default is False; should be used' 606 msg += ' with --shell option' 607 parser.add_option('-M', 608 '--import_models', 609 action='store_true', 610 default=False, 611 dest='import_models', 612 help=msg) 613 614 msg = 'run PYTHON_FILE in web2py environment;' 615 msg += ' should be used with --shell option' 616 parser.add_option('-R', 617 '--run', 618 dest='run', 619 metavar='PYTHON_FILE', 620 default='', 621 help=msg) 622 623 msg = 'run doctests in web2py environment; ' +\ 624 'TEST_PATH like a/c/f (c,f optional)' 625 parser.add_option('-T', 626 '--test', 627 dest='test', 628 metavar='TEST_PATH', 629 default=None, 630 help=msg) 631 632 parser.add_option('-W', 633 '--winservice', 634 dest='winservice', 635 default='', 636 help='-W install|start|stop as Windows service') 637 638 msg = 'trigger a cron run manually; usually invoked from a system crontab' 639 parser.add_option('-C', 640 '--cron', 641 action='store_true', 642 dest='extcron', 643 default=False, 644 help=msg) 645 646 msg = 'triggers the use of softcron' 647 parser.add_option('--softcron', 648 action='store_true', 649 dest='softcron', 650 default=False, 651 help=msg) 652 653 parser.add_option('-N', 654 '--no-cron', 655 action='store_true', 656 dest='nocron', 657 default=False, 658 help='do not start cron automatically') 659 660 parser.add_option('-J', 661 '--cronjob', 662 action='store_true', 663 dest='cronjob', 664 default=False, 665 help='identify cron-initiated command') 666 667 parser.add_option('-L', 668 '--config', 669 dest='config', 670 default='', 671 help='config file') 672 673 parser.add_option('-F', 674 '--profiler', 675 dest='profiler_filename', 676 default=None, 677 help='profiler filename') 678 679 parser.add_option('-t', 680 '--taskbar', 681 action='store_true', 682 dest='taskbar', 683 default=False, 684 help='use web2py gui and run in taskbar (system tray)') 685 686 parser.add_option('', 687 '--nogui', 688 action='store_true', 689 default=False, 690 dest='nogui', 691 help='text-only, no GUI') 692 693 parser.add_option('-A', 694 '--args', 695 action='store', 696 dest='args', 697 default=None, 698 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') 699 700 parser.add_option('--no-banner', 701 action='store_true', 702 default=False, 703 dest='nobanner', 704 help='Do not print header banner') 705 706 msg = 'listen on multiple addresses: "ip:port:cert:key;ip2:port2:cert2:key2;..." (:cert:key optional; no spaces)' 707 parser.add_option('--interfaces', 708 action='store', 709 dest='interfaces', 710 default=None, 711 help=msg) 712 713 if '-A' in sys.argv: k = sys.argv.index('-A') 714 elif '--args' in sys.argv: k = sys.argv.index('--args') 715 else: k=len(sys.argv) 716 sys.argv, other_args = sys.argv[:k], sys.argv[k+1:] 717 (options, args) = parser.parse_args() 718 options.args = [options.run] + other_args 719 global_settings.cmd_options = options 720 global_settings.cmd_args = args 721 722 if options.quiet: 723 capture = cStringIO.StringIO() 724 sys.stdout = capture 725 logger.setLevel(logging.CRITICAL + 1) 726 else: 727 logger.setLevel(options.debuglevel) 728 729 if options.config[-3:] == '.py': 730 options.config = options.config[:-3] 731 732 if options.cronjob: 733 global_settings.cronjob = True # tell the world 734 options.nocron = True # don't start cron jobs 735 options.plain = True # cronjobs use a plain shell 736 737 options.folder = os.path.abspath(options.folder) 738 739 # accept --interfaces in the form "ip:port:cert:key;ip2:port2;ip3:port3:cert3:key3" 740 # (no spaces; optional cert:key indicate SSL) 741 # 742 if isinstance(options.interfaces, str): 743 options.interfaces = [interface.split(':') for interface in options.interfaces.split(';')] 744 for interface in options.interfaces: 745 interface[1] = int(interface[1]) # numeric port 746 options.interfaces = [tuple(interface) for interface in options.interfaces] 747 748 if options.numthreads is not None and options.minthreads is None: 749 options.minthreads = options.numthreads # legacy 750 751 if not options.cronjob: 752 # If we have the applications package or if we should upgrade 753 if not os.path.exists('applications/__init__.py'): 754 write_file('applications/__init__.py', '') 755 756 if not os.path.exists('welcome.w2p') or os.path.exists('NEWINSTALL'): 757 try: 758 w2p_pack('welcome.w2p','applications/welcome') 759 os.unlink('NEWINSTALL') 760 except: 761 msg = "New installation: unable to create welcome.w2p file" 762 sys.stderr.write(msg) 763 764 return (options, args)
765 766
767 -def start(cron=True):
768 """ Start server """ 769 770 # ## get command line arguments 771 772 (options, args) = console() 773 774 if not options.nobanner: 775 print ProgramName 776 print ProgramAuthor 777 print ProgramVersion 778 779 from dal import drivers 780 if not options.nobanner: 781 print 'Database drivers available: %s' % ', '.join(drivers) 782 783 784 # ## if -L load options from options.config file 785 if options.config: 786 try: 787 options2 = __import__(options.config, {}, {}, '') 788 except Exception: 789 try: 790 # Jython doesn't like the extra stuff 791 options2 = __import__(options.config) 792 except Exception: 793 print 'Cannot import config file [%s]' % options.config 794 sys.exit(1) 795 for key in dir(options2): 796 if hasattr(options,key): 797 setattr(options,key,getattr(options2,key)) 798 799 # ## if -T run doctests (no cron) 800 if hasattr(options,'test') and options.test: 801 test(options.test, verbose=options.verbose) 802 return 803 804 # ## if -S start interactive shell (also no cron) 805 if options.shell: 806 if options.args!=None: 807 sys.argv[:] = options.args 808 run(options.shell, plain=options.plain, bpython=options.bpython, 809 import_models=options.import_models, startfile=options.run) 810 return 811 812 # ## if -C start cron run (extcron) and exit 813 # ## if -N or not cron disable cron in this *process* 814 # ## if --softcron use softcron 815 # ## use hardcron in all other cases 816 if options.extcron: 817 print 'Starting extcron...' 818 global_settings.web2py_crontype = 'external' 819 extcron = newcron.extcron(options.folder) 820 extcron.start() 821 extcron.join() 822 return 823 elif cron and not options.nocron and options.softcron: 824 print 'Using softcron (but this is not very efficient)' 825 global_settings.web2py_crontype = 'soft' 826 elif cron and not options.nocron: 827 print 'Starting hardcron...' 828 global_settings.web2py_crontype = 'hard' 829 newcron.hardcron(options.folder).start() 830 831 # ## if -W install/start/stop web2py as service 832 if options.winservice: 833 if os.name == 'nt': 834 web2py_windows_service_handler(['', options.winservice], 835 options.config) 836 else: 837 print 'Error: Windows services not supported on this platform' 838 sys.exit(1) 839 return 840 841 # ## if no password provided and havetk start Tk interface 842 # ## or start interface if we want to put in taskbar (system tray) 843 844 try: 845 options.taskbar 846 except: 847 options.taskbar = False 848 849 if options.taskbar and os.name != 'nt': 850 print 'Error: taskbar not supported on this platform' 851 sys.exit(1) 852 853 root = None 854 855 if not options.nogui: 856 try: 857 import Tkinter 858 havetk = True 859 except ImportError: 860 logger.warn('GUI not available because Tk library is not installed') 861 havetk = False 862 863 if options.password == '<ask>' and havetk or options.taskbar and havetk: 864 try: 865 root = Tkinter.Tk() 866 except: 867 pass 868 869 if root: 870 root.focus_force() 871 if not options.quiet: 872 presentation(root) 873 master = web2pyDialog(root, options) 874 signal.signal(signal.SIGTERM, lambda a, b: master.quit()) 875 876 try: 877 root.mainloop() 878 except: 879 master.quit() 880 881 sys.exit() 882 883 # ## if no tk and no password, ask for a password 884 885 if not root and options.password == '<ask>': 886 options.password = raw_input('choose a password:') 887 888 if not options.password and not options.nobanner: 889 print 'no password, no admin interface' 890 891 # ## start server 892 893 (ip, port) = (options.ip, int(options.port)) 894 895 if not options.nobanner: 896 print 'please visit:' 897 print '\thttp://%s:%s' % (ip, port) 898 print 'use "kill -SIGTERM %i" to shutdown the web2py server' % os.getpid() 899 900 server = main.HttpServer(ip=ip, 901 port=port, 902 password=options.password, 903 pid_filename=options.pid_filename, 904 log_filename=options.log_filename, 905 profiler_filename=options.profiler_filename, 906 ssl_certificate=options.ssl_certificate, 907 ssl_private_key=options.ssl_private_key, 908 min_threads=options.minthreads, 909 max_threads=options.maxthreads, 910 server_name=options.server_name, 911 request_queue_size=options.request_queue_size, 912 timeout=options.timeout, 913 shutdown_timeout=options.shutdown_timeout, 914 path=options.folder, 915 interfaces=options.interfaces) 916 917 try: 918 server.start() 919 except KeyboardInterrupt: 920 server.stop() 921 logging.shutdown()
922