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