def main(args=None, locals_=None, banner=None, welcome_message=None): """ banner is displayed directly after the version information. welcome_message is passed on to Repl and displayed in the statusbar. """ translations.init() config, options, exec_args = bpargs.parse(args, ( 'curtsies options', None, [ Option('--log', '-L', action='count', help=_("log debug messages to bpython.log")), Option('--paste', '-p', action='store_true', help=_("start by pasting lines of a file into session")), ])) if options.log is None: options.log = 0 logging_levels = [logging.ERROR, logging.INFO, logging.DEBUG] level = logging_levels[min(len(logging_levels) - 1, options.log)] logging.getLogger('curtsies').setLevel(level) logging.getLogger('bpython').setLevel(level) if options.log: handler = logging.FileHandler(filename='bpython.log') logging.getLogger('curtsies').addHandler(handler) logging.getLogger('curtsies').propagate = False logging.getLogger('bpython').addHandler(handler) logging.getLogger('bpython').propagate = False interp = None paste = None if exec_args: if not options: raise ValueError("don't pass in exec_args without options") exit_value = () if options.paste: paste = curtsies.events.PasteEvent() encoding = inspection.get_encoding_file(exec_args[0]) with io.open(exec_args[0], encoding=encoding) as f: sourcecode = f.read() paste.events.extend(sourcecode) else: try: interp = Interp(locals=locals_) bpargs.exec_code(interp, exec_args) except SystemExit as e: exit_value = e.args if not options.interactive: return extract_exit_value(exit_value) else: # expected for interactive sessions (vanilla python does it) sys.path.insert(0, '') if not options.quiet: print(bpargs.version_banner()) if banner is not None: print(banner) global repl repl = FullCurtsiesRepl(config, locals_, welcome_message, interp, paste) try: with repl.input_generator: with repl.window as win: with repl: repl.height, repl.width = win.t.height, win.t.width exit_value = repl.mainloop() except (SystemExitFromCodeGreenlet, SystemExit) as e: exit_value = e.args return extract_exit_value(exit_value)
def main(args=None, locals_=None, banner=None): translations.init() # TODO: maybe support displays other than raw_display? config, options, exec_args = bpargs.parse(args, ( 'Urwid options', None, [ Option('--twisted', '-T', action='store_true', help=_('Run twisted reactor.')), Option('--reactor', '-r', help=_('Select specific reactor (see --help-reactors). ' 'Implies --twisted.')), Option('--help-reactors', action='store_true', help=_('List available reactors for -r.')), Option('--plugin', '-p', help=_('twistd plugin to run (use twistd for a list). ' 'Use "--" to pass further options to the plugin.')), Option('--server', '-s', type='int', help=_('Port to run an eval server on (forces Twisted).')), ])) if options.help_reactors: try: from twisted.application import reactors # Stolen from twisted.application.app (twistd). for r in reactors.getReactorTypes(): print(' %-4s\t%s' % (r.shortName, r.description)) except ImportError: sys.stderr.write('No reactors are available. Please install ' 'twisted for reactor support.\n') return palette = [ (name, COLORMAP[color.lower()], 'default', 'bold' if color.isupper() else 'default') for name, color in iteritems(config.color_scheme)] palette.extend([ ('bold ' + name, color + ',bold', background, monochrome) for name, color, background, monochrome in palette]) if options.server or options.plugin: options.twisted = True if options.reactor: try: from twisted.application import reactors except ImportError: sys.stderr.write('No reactors are available. Please install ' 'twisted for reactor support.\n') return try: # XXX why does this not just return the reactor it installed? reactor = reactors.installReactor(options.reactor) if reactor is None: from twisted.internet import reactor except reactors.NoSuchReactor: sys.stderr.write('Reactor %s does not exist\n' % ( options.reactor,)) return event_loop = TwistedEventLoop(reactor) elif options.twisted: try: from twisted.internet import reactor except ImportError: sys.stderr.write('No reactors are available. Please install ' 'twisted for reactor support.\n') return event_loop = TwistedEventLoop(reactor) else: # None, not urwid.SelectEventLoop(), to work with # screens that do not support external event loops. event_loop = None # TODO: there is also a glib event loop. Do we want that one? # __main__ construction from bpython.cli if locals_ is None: main_mod = sys.modules['__main__'] = ModuleType('__main__') locals_ = main_mod.__dict__ if options.plugin: try: from twisted import plugin from twisted.application import service except ImportError: sys.stderr.write('No twisted plugins are available. Please install ' 'twisted for twisted plugin support.\n') return for plug in plugin.getPlugins(service.IServiceMaker): if plug.tapname == options.plugin: break else: sys.stderr.write('Plugin %s does not exist\n' % (options.plugin,)) return plugopts = plug.options() plugopts.parseOptions(exec_args) serv = plug.makeService(plugopts) locals_['service'] = serv reactor.callWhenRunning(serv.startService) exec_args = [] interpreter = repl.Interpreter(locals_, locale.getpreferredencoding()) # This nabs sys.stdin/out via urwid.MainLoop myrepl = URWIDRepl(event_loop, palette, interpreter, config) if options.server: factory = EvalFactory(myrepl) reactor.listenTCP(options.server, factory, interface='127.0.0.1') if options.reactor: # Twisted sets a sigInt handler that stops the reactor unless # it sees a different custom signal handler. def sigint(*args): reactor.callFromThread(myrepl.keyboard_interrupt) signal.signal(signal.SIGINT, sigint) # Save stdin, stdout and stderr for later restoration orig_stdin = sys.stdin orig_stdout = sys.stdout orig_stderr = sys.stderr # urwid's screen start() and stop() calls currently hit sys.stdin # directly (via RealTerminal.tty_signal_keys), so start the screen # before swapping sys.std*, and swap them back before restoring # the screen. This also avoids crashes if our redirected sys.std* # are called before we get around to starting the mainloop # (urwid raises an exception if we try to draw to the screen # before starting it). def run_with_screen_before_mainloop(): try: # Currently we just set this to None because I do not # expect code hitting stdin to work. For example: exit() # (not sys.exit, site.py's exit) tries to close sys.stdin, # which breaks urwid's shutdown. bpython.cli sets this to # a fake object that reads input through curses and # returns it. When using twisted I do not think we can do # that because sys.stdin.read and friends block, and we # cannot re-enter the reactor. If using urwid's own # mainloop we *might* be able to do something similar and # re-enter its mainloop. sys.stdin = None #FakeStdin(myrepl) sys.stdout = myrepl sys.stderr = myrepl myrepl.main_loop.set_alarm_in(0, start) while True: try: myrepl.main_loop.run() except KeyboardInterrupt: # HACK: if we run under a twisted mainloop this should # never happen: we have a SIGINT handler set. # If we use the urwid select-based loop we just restart # that loop if interrupted, instead of trying to cook # up an equivalent to reactor.callFromThread (which # is what our Twisted sigint handler does) myrepl.main_loop.set_alarm_in( 0, lambda *args: myrepl.keyboard_interrupt()) continue break finally: sys.stdin = orig_stdin sys.stderr = orig_stderr sys.stdout = orig_stdout # This needs more thought. What needs to happen inside the mainloop? def start(main_loop, user_data): if exec_args: bpargs.exec_code(interpreter, exec_args) if not options.interactive: raise urwid.ExitMainLoop() if not exec_args: sys.path.insert(0, '') # this is CLIRepl.startup inlined. filename = os.environ.get('PYTHONSTARTUP') if filename and os.path.isfile(filename): with open(filename, 'r') as f: if py3: interpreter.runsource(f.read(), filename, 'exec') else: interpreter.runsource(f.read(), filename, 'exec', encode=False) if banner is not None: myrepl.write(banner) myrepl.write('\n') myrepl.start() # This bypasses main_loop.set_alarm_in because we must *not* # hit the draw_screen call (it's unnecessary and slow). def run_find_coroutine(): if find_coroutine(): main_loop.event_loop.alarm(0, run_find_coroutine) run_find_coroutine() myrepl.main_loop.screen.run_wrapper(run_with_screen_before_mainloop) if config.flush_output and not options.quiet: sys.stdout.write(myrepl.getstdout()) if hasattr(sys.stdout, "flush"): sys.stdout.flush() return repl.extract_exit_value(myrepl.exit_value)
def main(args=None): translations.init() gtk_options = (_('gtk-specific options'), _("Options specific to bpython's Gtk+ front end"), [ optparse.Option('--socket-id', dest='socket_id', type='int', help=_('Embed bpython')) ]) config, options, exec_args = bpython.args.parse(args, gtk_options, True) interpreter = repl.Interpreter(None, getpreferredencoding()) repl_widget = ReplWidget(interpreter, config) repl_widget.connect('exit-event', gtk.main_quit) gobject.idle_add(init_import_completion) if not exec_args: sys.path.insert(0, '') gobject.idle_add(repl_widget.startup) else: if options.interactive: gobject.idle_add(bpython.args.exec_code, interpreter, exec_args) else: bpython.args.exec_code(interpreter, exec_args) return 0 sys.stderr = repl_widget sys.stdout = repl_widget if not options.socket_id: parent = gtk.Window() parent.connect('delete-event', lambda widget, event: gtk.main_quit()) # branding # fix icon to be distributed and loaded from the correct path icon = gtk.gdk.pixbuf_new_from_file( os.path.join(os.path.dirname(__file__), 'logo.png')) parent.set_title('bpython') parent.set_icon(icon) parent.resize(600, 300) else: parent = gtk.Plug(options.socket_id) parent.connect('destroy', gtk.main_quit) container = gtk.VBox() parent.add(container) mb = gtk.MenuBar() filemenu = gtk.Menu() filem = gtk.MenuItem("File") filem.set_submenu(filemenu) save = gtk.ImageMenuItem(gtk.STOCK_SAVE) save.connect("activate", repl_widget.do_write2file) filemenu.append(save) pastebin = gtk.MenuItem("Pastebin") pastebin.connect("activate", repl_widget.do_paste) filemenu.append(pastebin) pastebin_partial = gtk.MenuItem(_("Pastebin selection")) pastebin_partial.connect("activate", repl_widget.do_partial_paste) filemenu.append(pastebin_partial) exit = gtk.ImageMenuItem(gtk.STOCK_QUIT) exit.connect("activate", gtk.main_quit) filemenu.append(exit) mb.append(filem) vbox = gtk.VBox(False, 2) vbox.pack_start(mb, False, False, 0) container.pack_start(vbox, expand=False) # read from config sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) sw.add(repl_widget) container.add(sw) sb = repl_widget.interact.statusbar container.pack_end(sb, expand=False) parent.set_focus(repl_widget) parent.show_all() parent.connect('delete-event', lambda widget, event: gtk.main_quit()) try: gtk.main() except KeyboardInterrupt: pass return repl.extract_exit_value(repl_widget.exit_value)
def main(args=None, locals_=None, banner=None, welcome_message=None): """ banner is displayed directly after the version information. welcome_message is passed on to Repl and displayed in the statusbar. """ translations.init() config, options, exec_args = bpargs.parse( args, ('curtsies options', None, [ Option('--log', '-L', action='count', help=_("log debug messages to bpython.log")), Option('--paste', '-p', action='store_true', help=_("start by pasting lines of a file into session")), ])) if options.log is None: options.log = 0 logging_levels = [logging.ERROR, logging.INFO, logging.DEBUG] level = logging_levels[min(len(logging_levels) - 1, options.log)] logging.getLogger('curtsies').setLevel(level) logging.getLogger('bpython').setLevel(level) if options.log: handler = logging.FileHandler(filename='bpython.log') logging.getLogger('curtsies').addHandler(handler) logging.getLogger('curtsies').propagate = False logging.getLogger('bpython').addHandler(handler) logging.getLogger('bpython').propagate = False interp = None paste = None if exec_args: if not options: raise ValueError("don't pass in exec_args without options") exit_value = () if options.paste: paste = curtsies.events.PasteEvent() encoding = inspection.get_encoding_file(exec_args[0]) with io.open(exec_args[0], encoding=encoding) as f: sourcecode = f.read() paste.events.extend(sourcecode) else: try: interp = Interp(locals=locals_) bpargs.exec_code(interp, exec_args) except SystemExit as e: exit_value = e.args if not options.interactive: return extract_exit_value(exit_value) else: # expected for interactive sessions (vanilla python does it) sys.path.insert(0, '') if not options.quiet: print(bpargs.version_banner()) if banner is not None: print(banner) global repl repl = FullCurtsiesRepl(config, locals_, welcome_message, interp, paste) try: with repl.input_generator: with repl.window as win: with repl: repl.height, repl.width = win.t.height, win.t.width exit_value = repl.mainloop() except (SystemExitFromCodeGreenlet, SystemExit) as e: exit_value = e.args return extract_exit_value(exit_value)
def main(args=None, locals_=None, banner=None): translations.init() # TODO: maybe support displays other than raw_display? config, options, exec_args = bpargs.parse(args, ('Urwid options', None, [ Option('--twisted', '-T', action='store_true', help=_('Run twisted reactor.')), Option('--reactor', '-r', help=_('Select specific reactor (see --help-reactors). ' 'Implies --twisted.')), Option('--help-reactors', action='store_true', help=_('List available reactors for -r.')), Option('--plugin', '-p', help=_('twistd plugin to run (use twistd for a list). ' 'Use "--" to pass further options to the plugin.')), Option('--server', '-s', type='int', help=_('Port to run an eval server on (forces Twisted).')), ])) if options.help_reactors: try: from twisted.application import reactors # Stolen from twisted.application.app (twistd). for r in reactors.getReactorTypes(): print(' %-4s\t%s' % (r.shortName, r.description)) except ImportError: sys.stderr.write('No reactors are available. Please install ' 'twisted for reactor support.\n') return palette = [(name, COLORMAP[color.lower()], 'default', 'bold' if color.isupper() else 'default') for name, color in config.color_scheme.items()] palette.extend([('bold ' + name, color + ',bold', background, monochrome) for name, color, background, monochrome in palette]) if options.server or options.plugin: options.twisted = True if options.reactor: try: from twisted.application import reactors except ImportError: sys.stderr.write('No reactors are available. Please install ' 'twisted for reactor support.\n') return try: # XXX why does this not just return the reactor it installed? reactor = reactors.installReactor(options.reactor) if reactor is None: from twisted.internet import reactor except reactors.NoSuchReactor: sys.stderr.write('Reactor %s does not exist\n' % (options.reactor, )) return event_loop = TwistedEventLoop(reactor) elif options.twisted: try: from twisted.internet import reactor except ImportError: sys.stderr.write('No reactors are available. Please install ' 'twisted for reactor support.\n') return event_loop = TwistedEventLoop(reactor) else: # None, not urwid.SelectEventLoop(), to work with # screens that do not support external event loops. event_loop = None # TODO: there is also a glib event loop. Do we want that one? # __main__ construction from bpython.cli if locals_ is None: main_mod = sys.modules['__main__'] = ModuleType('__main__') locals_ = main_mod.__dict__ if options.plugin: try: from twisted import plugin from twisted.application import service except ImportError: sys.stderr.write( 'No twisted plugins are available. Please install ' 'twisted for twisted plugin support.\n') return for plug in plugin.getPlugins(service.IServiceMaker): if plug.tapname == options.plugin: break else: sys.stderr.write('Plugin %s does not exist\n' % (options.plugin, )) return plugopts = plug.options() plugopts.parseOptions(exec_args) serv = plug.makeService(plugopts) locals_['service'] = serv reactor.callWhenRunning(serv.startService) exec_args = [] interpreter = repl.Interpreter(locals_, locale.getpreferredencoding()) # This nabs sys.stdin/out via urwid.MainLoop myrepl = URWIDRepl(event_loop, palette, interpreter, config) if options.server: factory = EvalFactory(myrepl) reactor.listenTCP(options.server, factory, interface='127.0.0.1') if options.reactor: # Twisted sets a sigInt handler that stops the reactor unless # it sees a different custom signal handler. def sigint(*args): reactor.callFromThread(myrepl.keyboard_interrupt) signal.signal(signal.SIGINT, sigint) # Save stdin, stdout and stderr for later restoration orig_stdin = sys.stdin orig_stdout = sys.stdout orig_stderr = sys.stderr # urwid's screen start() and stop() calls currently hit sys.stdin # directly (via RealTerminal.tty_signal_keys), so start the screen # before swapping sys.std*, and swap them back before restoring # the screen. This also avoids crashes if our redirected sys.std* # are called before we get around to starting the mainloop # (urwid raises an exception if we try to draw to the screen # before starting it). def run_with_screen_before_mainloop(): try: # Currently we just set this to None because I do not # expect code hitting stdin to work. For example: exit() # (not sys.exit, site.py's exit) tries to close sys.stdin, # which breaks urwid's shutdown. bpython.cli sets this to # a fake object that reads input through curses and # returns it. When using twisted I do not think we can do # that because sys.stdin.read and friends block, and we # cannot re-enter the reactor. If using urwid's own # mainloop we *might* be able to do something similar and # re-enter its mainloop. sys.stdin = None #FakeStdin(myrepl) sys.stdout = myrepl sys.stderr = myrepl myrepl.main_loop.set_alarm_in(0, start) while True: try: myrepl.main_loop.run() except KeyboardInterrupt: # HACK: if we run under a twisted mainloop this should # never happen: we have a SIGINT handler set. # If we use the urwid select-based loop we just restart # that loop if interrupted, instead of trying to cook # up an equivalent to reactor.callFromThread (which # is what our Twisted sigint handler does) myrepl.main_loop.set_alarm_in( 0, lambda *args: myrepl.keyboard_interrupt()) continue break finally: sys.stdin = orig_stdin sys.stderr = orig_stderr sys.stdout = orig_stdout # This needs more thought. What needs to happen inside the mainloop? def start(main_loop, user_data): if exec_args: bpargs.exec_code(interpreter, exec_args) if not options.interactive: raise urwid.ExitMainLoop() if not exec_args: sys.path.insert(0, '') # this is CLIRepl.startup inlined. filename = os.environ.get('PYTHONSTARTUP') if filename and os.path.isfile(filename): with open(filename, 'r') as f: if py3: interpreter.runsource(f.read(), filename, 'exec') else: interpreter.runsource(f.read(), filename, 'exec', encode=False) if banner is not None: repl.write(banner) repl.write('\n') myrepl.start() # This bypasses main_loop.set_alarm_in because we must *not* # hit the draw_screen call (it's unnecessary and slow). def run_find_coroutine(): if find_coroutine(): main_loop.event_loop.alarm(0, run_find_coroutine) run_find_coroutine() myrepl.main_loop.screen.run_wrapper(run_with_screen_before_mainloop) if config.flush_output and not options.quiet: sys.stdout.write(myrepl.getstdout()) if hasattr(sys.stdout, "flush"): sys.stdout.flush() return repl.extract_exit_value(myrepl.exit_value)
#Input edit = CommandEdit('> ') #Master container fill = urwid.Frame(myrepl.frame, menu) myrepl.main_loop = PandaMainLoop( fill, palette, unhandled_input=myrepl.handle_input, event_loop=PandaEventLoop() ) if config.flush_output and not options.quiet: sys.stdout.write(myrepl.getstdout()) if hasattr(sys.stdout, "flush"): sys.stdout.flush() repl.extract_exit_value(myrepl.exit_value) def run_with_screen_before_mainloop(): sys.stdin = None # FakeStdin(myrepl) sys.stdout = myrepl sys.stderr = myrepl myrepl.main_loop.set_alarm_in(0, start) '''try: # Currently we just set this to None because I do not # expect code hitting stdin to work. For example: exit() # (not sys.exit, site.py's exit) tries to close sys.stdin, # which breaks urwid's shutdown. bpython.cli sets this to # a fake object that reads input through curses and # returns it. When using twisted I do not think we can do
def main(args=None, locals_=None, banner=None): translations.init() config, options, exec_args = bpargs.parse( args, ('curtsies options', None, [ Option('--log', '-L', action='count', help=_("log debug messages to bpython.log")), Option('--paste', '-p', action='store_true', help=_("start by pasting lines of a file into session")), ])) if options.log is None: options.log = 0 logging_levels = [logging.ERROR, logging.INFO, logging.DEBUG] level = logging_levels[min(len(logging_levels) - 1, options.log)] logging.getLogger('curtsies').setLevel(level) logging.getLogger('bpython').setLevel(level) if options.log: handler = logging.FileHandler(filename='bpython.log') logging.getLogger('curtsies').addHandler(handler) logging.getLogger('curtsies').propagate = False logging.getLogger('bpython').addHandler(handler) logging.getLogger('bpython').propagate = False interp = None paste = None if exec_args: if not options: raise ValueError("don't pass in exec_args without options") exit_value = () if options.paste: paste = curtsies.events.PasteEvent() encoding = inspection.get_encoding_file(exec_args[0]) with io.open(exec_args[0], encoding=encoding) as f: sourcecode = f.read() paste.events.extend(sourcecode) else: try: interp = code.InteractiveInterpreter(locals=locals_) bpargs.exec_code(interp, exec_args) except SystemExit as e: exit_value = e.args if not options.interactive: return extract_exit_value(exit_value) else: # expected for interactive sessions (vanilla python does it) sys.path.insert(0, '') print(bpargs.version_banner()) try: exit_value = mainloop(config, locals_, banner, interp, paste, interactive=(not exec_args)) except (SystemExitFromCodeGreenlet, SystemExit) as e: exit_value = e.args return extract_exit_value(exit_value)
def main(args=None): translations.init() gtk_options = (_('gtk-specific options'), _("Options specific to bpython's Gtk+ front end"), [optparse.Option('--socket-id', dest='socket_id', type='int', help=_('Embed bpython'))]) config, options, exec_args = bpython.args.parse(args, gtk_options, True) interpreter = repl.Interpreter(None, getpreferredencoding()) repl_widget = ReplWidget(interpreter, config) repl_widget.connect('exit-event', gtk.main_quit) gobject.idle_add(init_import_completion) if not exec_args: sys.path.insert(0, '') gobject.idle_add(repl_widget.startup) else: if options.interactive: gobject.idle_add(bpython.args.exec_code, interpreter, exec_args) else: bpython.args.exec_code(interpreter, exec_args) return 0 sys.stderr = repl_widget sys.stdout = repl_widget if not options.socket_id: parent = gtk.Window() parent.connect('delete-event', lambda widget, event: gtk.main_quit()) # branding # fix icon to be distributed and loaded from the correct path icon = gtk.gdk.pixbuf_new_from_file(os.path.join(os.path.dirname(__file__), 'logo.png')) parent.set_title('bpython') parent.set_icon(icon) parent.resize(600, 300) else: parent = gtk.Plug(options.socket_id) parent.connect('destroy', gtk.main_quit) container = gtk.VBox() parent.add(container) mb = gtk.MenuBar() filemenu = gtk.Menu() filem = gtk.MenuItem("File") filem.set_submenu(filemenu) save = gtk.ImageMenuItem(gtk.STOCK_SAVE) save.connect("activate", repl_widget.do_write2file) filemenu.append(save) pastebin = gtk.MenuItem("Pastebin") pastebin.connect("activate", repl_widget.do_paste) filemenu.append(pastebin) pastebin_partial = gtk.MenuItem(_("Pastebin selection")) pastebin_partial.connect("activate", repl_widget.do_partial_paste) filemenu.append(pastebin_partial) exit = gtk.ImageMenuItem(gtk.STOCK_QUIT) exit.connect("activate", gtk.main_quit) filemenu.append(exit) mb.append(filem) vbox = gtk.VBox(False, 2) vbox.pack_start(mb, False, False, 0) container.pack_start(vbox, expand=False) # read from config sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) sw.add(repl_widget) container.add(sw) sb = repl_widget.interact.statusbar container.pack_end(sb, expand=False) parent.set_focus(repl_widget) parent.show_all() parent.connect('delete-event', lambda widget, event: gtk.main_quit()) try: gtk.main() except KeyboardInterrupt: pass return repl.extract_exit_value(repl_widget.exit_value)