Exemplo n.º 1
0
    def paste(self, s):
        """Call out to helper program for pastebin upload."""

        try:
            helper = subprocess.Popen('',
                                      executable=self.executable,
                                      stdin=subprocess.PIPE,
                                      stdout=subprocess.PIPE)
            helper.stdin.write(s.encode(getpreferredencoding()))
            output = helper.communicate()[0].decode(getpreferredencoding())
            paste_url = output.split()[0]
        except OSError as e:
            if e.errno == errno.ENOENT:
                raise PasteFailed(_('Helper program not found.'))
            else:
                raise PasteFailed(_('Helper program could not be run.'))

        if helper.returncode != 0:
            raise PasteFailed(_('Helper program returned non-zero exit '
                                'status %d.' % (helper.returncode, )))

        if not paste_url:
            raise PasteFailed(_('No output from helper program.'))
        else:
            parsed_url = urlparse(paste_url)
            if (not parsed_url.scheme or
                any(unicodedata.category(c) == 'Cc'
                    for c in paste_url)):
                raise PasteFailed(_('Failed to recognize the helper '
                                    'program\'s output as an URL.'))

        return paste_url,
Exemplo n.º 2
0
    def do_pastebin_xmlrpc(self, s):
        """Upload to pastebin via XML-RPC."""
        try:
            pasteservice = ServerProxy(self.config.pastebin_url)
        except IOError as e:
            self.interact.notify(
                _("Pastebin error for URL '%s': %s") %
                (self.config.pastebin_url, str(e)))
            return

        self.interact.notify(_('Posting data to pastebin...'))
        try:
            paste_id = pasteservice.pastes.newPaste(
                'pycon', s, '', '', '', self.config.pastebin_private)
        except (SocketError, XMLRPCError) as e:
            self.interact.notify(_('Upload failed: %s') % (str(e), ))
            return

        self.prev_pastebin_content = s

        paste_url_template = Template(self.config.pastebin_show_url)
        paste_id = urlquote(paste_id)
        paste_url = paste_url_template.safe_substitute(paste_id=paste_id)
        self.prev_pastebin_url = paste_url
        self.interact.notify(_('Pastebin URL: %s') % (paste_url, ), 10)
        return paste_url
Exemplo n.º 3
0
    def do_pastebin(self, s):
        """Actually perform the upload."""
        if s == self.prev_pastebin_content:
            self.interact.notify(_('Duplicate pastebin. Previous URL: %s. '
                                   'Removal URL: %s') %
                                  (self.prev_pastebin_url,
                                   self.prev_removal_url), 10)
            return self.prev_pastebin_url

        self.interact.notify(_('Posting data to pastebin...'))
        try:
            paste_url, removal_url = self.paster.paste(s)
        except PasteFailed as e:
            self.interact.notify(_('Upload failed: %s') % e)
            return

        self.prev_pastebin_content = s
        self.prev_pastebin_url = paste_url
        self.prev_removal_url = removal_url

        if removal_url is not None:
            self.interact.notify(_('Pastebin URL: %s - Removal URL: %s') %
                                 (paste_url, removal_url), 10)
        else:
            self.interact.notify(_('Pastebin URL: %s') % (paste_url, ), 10)

        return paste_url
Exemplo n.º 4
0
    def do_pastebin_json(self, s):
        """Upload to pastebin via json interface."""

        url = urljoin(self.config.pastebin_url, '/json/new')
        payload = {
            'code': s,
            'lexer': 'pycon',
            'expiry': self.config.pastebin_expiry
        }

        self.interact.notify(_('Posting data to pastebin...'))
        try:
            response = requests.post(url, data=payload, verify=True)
            response.raise_for_status()
        except requests.exceptions.RequestException as exc:
          self.interact.notify(_('Upload failed: %s') % (str(exc), ))
          return

        self.prev_pastebin_content = s
        data = response.json()

        paste_url_template = Template(self.config.pastebin_show_url)
        paste_id = urlquote(data['paste_id'])
        paste_url = paste_url_template.safe_substitute(paste_id=paste_id)

        removal_url_template = Template(self.config.pastebin_removal_url)
        removal_id = urlquote(data['removal_id'])
        removal_url = removal_url_template.safe_substitute(removal_id=removal_id)

        self.prev_pastebin_url = paste_url
        self.interact.notify(_('Pastebin URL: %s - Removal URL: %s') %
                             (paste_url, removal_url))

        return paste_url
Exemplo n.º 5
0
    def file_prompt(self, s):
        chooser = gtk.FileChooserDialog(title=_("File to save to"),
                                        action=gtk.FILE_CHOOSER_ACTION_SAVE,
                                        buttons=(gtk.STOCK_CANCEL,
                                                 gtk.RESPONSE_CANCEL,
                                                 gtk.STOCK_OPEN,
                                                 gtk.RESPONSE_OK))
        chooser.set_default_response(gtk.RESPONSE_OK)
        chooser.set_current_name('test.py')
        chooser.set_current_folder(os.path.expanduser('~'))

        pyfilter = gtk.FileFilter()
        pyfilter.set_name(_("Python files"))
        pyfilter.add_pattern("*.py")
        chooser.add_filter(pyfilter)

        allfilter = gtk.FileFilter()
        allfilter.set_name(_("All files"))
        allfilter.add_pattern("*")
        chooser.add_filter(allfilter)

        response = chooser.run()
        if response == gtk.RESPONSE_OK:
            fn = chooser.get_filename()
        else:
            fn = False

        chooser.destroy()

        return fn
Exemplo n.º 6
0
 def prompt_undo(self):
     """Returns how many lines to undo, 0 means don't undo"""
     if (self.config.single_undo_time < 0 or
             self.interp.timer.estimate() < self.config.single_undo_time):
         return 1
     est = self.interp.timer.estimate()
     n = self.interact.file_prompt(
         _("Undo how many lines? (Undo will take up to ~%.1f seconds) [1]")
         % (est,))
     try:
         if n == '':
             n = '1'
         n = int(n)
     except ValueError:
         self.interact.notify(_('Undo canceled'), .1)
         return 0
     else:
         if n == 0:
             self.interact.notify(_('Undo canceled'), .1)
             return 0
         else:
             message = ngettext('Undoing %d line... (est. %.1f seconds)',
                                'Undoing %d lines... (est. %.1f seconds)',
                                n)
             self.interact.notify(message % (n, est), .1)
         return n
Exemplo n.º 7
0
    def do_pastebin_xmlrpc(self, s):
        """Upload to pastebin via XML-RPC."""
        try:
            pasteservice = ServerProxy(self.config.pastebin_url)
        except IOError as e:
            self.interact.notify(_("Pastebin error for URL '%s': %s") %
                                 (self.config.pastebin_url, str(e)))
            return

        self.interact.notify(_('Posting data to pastebin...'))
        try:
            paste_id = pasteservice.pastes.newPaste('pycon', s, '', '', '',
                                                    self.config.pastebin_private)
        except (SocketError, XMLRPCError) as e:
            self.interact.notify(_('Upload failed: %s') % (str(e), ))
            return

        self.prev_pastebin_content = s

        paste_url_template = Template(self.config.pastebin_show_url)
        paste_id = urlquote(paste_id)
        paste_url = paste_url_template.safe_substitute(paste_id=paste_id)
        self.prev_pastebin_url = paste_url
        self.interact.notify(_('Pastebin URL: %s') % (paste_url, ), 10)
        return paste_url
Exemplo n.º 8
0
    def file_prompt(self, s):
        chooser = gtk.FileChooserDialog(
            title=_("File to save to"),
            action=gtk.FILE_CHOOSER_ACTION_SAVE,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN,
                     gtk.RESPONSE_OK))
        chooser.set_default_response(gtk.RESPONSE_OK)
        chooser.set_current_name('test.py')
        chooser.set_current_folder(os.path.expanduser('~'))

        pyfilter = gtk.FileFilter()
        pyfilter.set_name(_("Python files"))
        pyfilter.add_pattern("*.py")
        chooser.add_filter(pyfilter)

        allfilter = gtk.FileFilter()
        allfilter.set_name(_("All files"))
        allfilter.add_pattern("*")
        chooser.add_filter(allfilter)

        response = chooser.run()
        if response == gtk.RESPONSE_OK:
            fn = chooser.get_filename()
        else:
            fn = False

        chooser.destroy()

        return fn
Exemplo n.º 9
0
    def edit_config(self):
        if not (os.path.isfile(self.config.config_path)):
            if self.interact.confirm(_("Config file does not exist - create "
                                       "new from default? (y/N)")):
                try:
                    default_config = pkgutil.get_data('bpython',
                                                      'sample-config')
                    if py3:  # py3 files need unicode
                        default_config = default_config.decode('ascii')
                    bpython_dir, script_name = os.path.split(__file__)
                    containing_dir = os.path.dirname(
                        os.path.abspath(self.config.config_path))
                    if not os.path.exists(containing_dir):
                        os.makedirs(containing_dir)
                    with open(self.config.config_path, 'w') as f:
                        f.write(default_config)
                except (IOError, OSError) as e:
                    self.interact.notify(_("Error writing file '%s': %s") %
                                         (self.config.config.path, e))
                    return False
            else:
                return False

        try:
            if self.open_in_external_editor(self.config.config_path):
                self.interact.notify(_('bpython config file edited. Restart '
                                       'bpython for changes to take effect.'))
        except OSError as e:
            self.interact.notify(_('Error editing config file: %s') % e)
Exemplo n.º 10
0
    def paste(self, s):
        """Call out to helper program for pastebin upload."""

        try:
            helper = subprocess.Popen('',
                                      executable=self.executable,
                                      stdin=subprocess.PIPE,
                                      stdout=subprocess.PIPE)
            helper.stdin.write(s.encode(getpreferredencoding()))
            output = helper.communicate()[0].decode(getpreferredencoding())
            paste_url = output.split()[0]
        except OSError as e:
            if e.errno == errno.ENOENT:
                raise PasteFailed(_('Helper program not found.'))
            else:
                raise PasteFailed(_('Helper program could not be run.'))

        if helper.returncode != 0:
            raise PasteFailed(
                _('Helper program returned non-zero exit '
                  'status %d.' % (helper.returncode, )))

        if not paste_url:
            raise PasteFailed(_('No output from helper program.'))
        else:
            parsed_url = urlparse(paste_url)
            if (not parsed_url.scheme
                    or any(unicodedata.category(c) == 'Cc'
                           for c in paste_url)):
                raise PasteFailed(
                    _('Failed to recognize the helper '
                      'program\'s output as an URL.'))

        return paste_url,
Exemplo n.º 11
0
 def prompt_undo(self):
     """Returns how many lines to undo, 0 means don't undo"""
     if (self.config.single_undo_time < 0 or
             self.interp.timer.estimate() < self.config.single_undo_time):
         return 1
     est = self.interp.timer.estimate()
     n = self.interact.file_prompt(
         _("Undo how many lines? (Undo will take up to ~%.1f seconds) [1]")
         % (est,))
     try:
         if n == '':
             n = '1'
         n = int(n)
     except ValueError:
         self.interact.notify(_('Undo canceled'), .1)
         return 0
     else:
         if n == 0:
             self.interact.notify(_('Undo canceled'), .1)
             return 0
         else:
             message = ngettext('Undoing %d line... (est. %.1f seconds)',
                                'Undoing %d lines... (est. %.1f seconds)',
                                n)
             self.interact.notify(message % (n, est), .1)
         return n
Exemplo n.º 12
0
def main(args=None, locals_=None, banner=None):
    config, options, exec_args = bpargs.parse(args, (
        'scroll options', None, [
            Option('--log', '-L', action='store_true',
                help=_("log debug messages to bpython-curtsies.log")),
            Option('--type', '-t', action='store_true',
                help=_("enter lines of file as though interactively typed")),
            ]))
    if options.log:
        import logging
        logging.basicConfig(filename='scroll.log', level=logging.DEBUG)

    interp = None
    paste = None
    if exec_args:
        assert options, "don't pass in exec_args without options"
        exit_value = 0
        if options.type:
            paste = curtsies.events.PasteEvent()
            sourcecode = open(exec_args[0]).read()
            paste.events.extend(sourcecode)
        else:
            try:
                interp = code.InteractiveInterpreter(locals=locals_)
                bpargs.exec_code(interp, exec_args)
            except SystemExit, e:
                exit_value = e.args
            if not options.interactive:
                raise SystemExit(exit_value)
Exemplo n.º 13
0
    def do_pastebin(self, s):
        """Actually perform the upload."""
        if s == self.prev_pastebin_content:
            self.interact.notify(_('Duplicate pastebin. Previous URL: %s. '
                                   'Removal URL: %s') %
                                  (self.prev_pastebin_url,
                                   self.prev_removal_url), 10)
            return self.prev_pastebin_url


        self.interact.notify(_('Posting data to pastebin...'))
        try:
            paste_url, removal_url = self.paster.paste(s)
        except PasteFailed as e:
            self.interact.notify(_('Upload failed: %s') % e)
            return

        self.prev_pastebin_content = s
        self.prev_pastebin_url = paste_url
        self.prev_removal_url = removal_url

        if removal_url is not None:
            self.interact.notify(_('Pastebin URL: %s - Removal URL: %s') %
                                 (paste_url, removal_url), 10)
        else:
            self.interact.notify(_('Pastebin URL: %s') % (paste_url, ), 10)

        return paste_url
Exemplo n.º 14
0
    def do_pastebin_json(self, s):
        """Upload to pastebin via json interface."""

        url = urljoin(self.config.pastebin_url, '/json/new')
        payload = {
            'code': s,
            'lexer': 'pycon',
            'expiry': self.config.pastebin_expiry
        }

        self.interact.notify(_('Posting data to pastebin...'))
        try:
            response = requests.post(url, data=payload, verify=True)
            response.raise_for_status()
        except requests.exceptions.RequestException as exc:
            self.interact.notify(_('Upload failed: %s') % (str(exc), ))
            return

        self.prev_pastebin_content = s
        data = response.json()

        paste_url_template = Template(self.config.pastebin_show_url)
        paste_id = urlquote(data['paste_id'])
        paste_url = paste_url_template.safe_substitute(paste_id=paste_id)

        removal_url_template = Template(self.config.pastebin_removal_url)
        removal_id = urlquote(data['removal_id'])
        removal_url = removal_url_template.safe_substitute(
            removal_id=removal_id)

        self.prev_pastebin_url = paste_url
        self.interact.notify(
            _('Pastebin URL: %s - Removal URL: %s') % (paste_url, removal_url))

        return paste_url
Exemplo n.º 15
0
    def edit_config(self):
        if not (os.path.isfile(self.config.config_path)):
            if self.interact.confirm(_("Config file does not exist - create "
                                       "new from default? (y/N)")):
                try:
                    default_config = pkgutil.get_data('bpython',
                                                      'sample-config')
                    if py3:  # py3 files need unicode
                        default_config = default_config.decode('ascii')
                    bpython_dir, script_name = os.path.split(__file__)
                    containing_dir = os.path.dirname(
                        os.path.abspath(self.config.config_path))
                    if not os.path.exists(containing_dir):
                        os.makedirs(containing_dir)
                    with open(self.config.config_path, 'w') as f:
                        f.write(default_config)
                except (IOError, OSError) as e:
                    self.interact.notify(_("Error writing file '%s': %s") %
                                         (self.config.config.path, e))
                    return False
            else:
                return False

        if self.open_in_external_editor(self.config.config_path):
            self.interact.notify(_('bpython config file edited. Restart '
                                   'bpython for changes to take effect.'))
        else:
            self.interact.notify(_('Error editing config file.'))
Exemplo n.º 16
0
    def confirm(self, q):
        """Ask for yes or no and return boolean"""
        try:
            reply = self.statusbar.prompt(q)
        except ValueError:
            return False

        return reply.lower() in (_('y'), _('yes'))
Exemplo n.º 17
0
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 = 0
        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:
                raise SystemExit(exit_value)
    else:
        # expected for interactive sessions (vanilla python does it)
        sys.path.insert(0, '')

    print(bpargs.version_banner())
    mainloop(config,
             locals_,
             banner,
             interp,
             paste,
             interactive=(not exec_args))
Exemplo n.º 18
0
    def pastebin(self, s=None):
        """Upload to a pastebin and display the URL in the status bar."""

        if s is None:
            s = self.getstdout()

        if (self.config.pastebin_confirm
                and not self.interact.confirm(_("Pastebin buffer? (y/N) "))):
            self.interact.notify(_("Pastebin aborted"))
            return
        return self.do_pastebin(s)
Exemplo n.º 19
0
    def pastebin(self, s=None):
        """Upload to a pastebin and display the URL in the status bar."""

        if s is None:
            s = self.getstdout()

        if (self.config.pastebin_confirm and
            not self.interact.confirm(_("Pastebin buffer? (y/N) "))):
            self.interact.notify(_("Pastebin aborted"))
            return
        return self.do_pastebin(s)
Exemplo n.º 20
0
    def copy2clipboard(self):
        """Copy current content to clipboard."""

        if self.clipboard is None:
            self.interact.notify(_('No clipboard available.'))
            return

        content = self.formatforfile(self.getstdout())
        try:
            self.clipboard.copy(content)
        except CopyFailed:
            self.interact.notify(_('Could not copy to clipboard.'))
        else:
            self.interact.notify(_('Copied content to clipboard.'))
Exemplo n.º 21
0
    def copy2clipboard(self):
        """Copy current content to clipboard."""

        if self.clipboard is None:
            self.interact.notify(_('No clipboard available.'))
            return

        content = self.formatforfile(self.getstdout())
        try:
            self.clipboard.copy(content)
        except CopyFailed:
            self.interact.notify(_('Could not copy to clipboard.'))
        else:
            self.interact.notify(_('Copied content to clipboard.'))
Exemplo n.º 22
0
    def append_reload_and_write(self, s, filename, encoding):
        if not self.hist_size:
            return self.append(s)

        try:
            with codecs.open(filename, 'a+', encoding, 'ignore') as hfile:
                with FileLock(hfile):
                    # read entries
                    hfile.seek(0, os.SEEK_SET)
                    entries = self.load_from(hfile)
                    self.append_to(entries, s)

                    # write new entries
                    hfile.seek(0, os.SEEK_SET)
                    hfile.truncate()
                    self.save_to(hfile, entries, self.hist_size)

                    self.entries = entries
        except EnvironmentError as err:
            raise RuntimeError(
                _('Error occurred while writing to file %s (%s)') %
                (filename, err.strerror))
        else:
            if len(self.entries) == 0:
                # Make sure that entries contains at least one element. If the
                # file and s are empty, this can occur.
                self.entries = ['']
Exemplo n.º 23
0
 def do_expose_event(self, event):
     """Draw a flat box around the popup window on expose event."""
     width, height = self.get_size()
     self.style.paint_flat_box(self.window, gtk.STATE_NORMAL,
                               gtk.SHADOW_OUT, None, self,
                               _('tooltip'), 0, 0, width, height)
     gtk.Window.do_expose_event(self, event)
Exemplo n.º 24
0
    def append_reload_and_write(self, s, filename, encoding):
        if not self.hist_size:
            return self.append(s)

        try:
            fd = os.open(filename, os.O_APPEND | os.O_RDWR | os.O_CREAT,
                         stat.S_IRUSR | stat.S_IWUSR)
            with io.open(fd, 'a+', encoding=encoding,
                         errors='ignore') as hfile:
                with FileLock(hfile):
                    # read entries
                    hfile.seek(0, os.SEEK_SET)
                    entries = self.load_from(hfile)
                    self.append_to(entries, s)

                    # write new entries
                    hfile.seek(0, os.SEEK_SET)
                    hfile.truncate()
                    self.save_to(hfile, entries, self.hist_size)

                    self.entries = entries
        except EnvironmentError as err:
            raise RuntimeError(
                _('Error occurred while writing to file %s (%s)')
                % (filename, err.strerror))
        else:
            if len(self.entries) == 0:
                # Make sure that entries contains at least one element. If the
                # file and s are empty, this can occur.
                self.entries = ['']
Exemplo n.º 25
0
    def edit_config(self):
        if not (os.path.isfile(self.config.config_path)):
            if self.interact.confirm(
                    _("Config file does not exist - create new from default? (y/N)"
                      )):
                try:
                    bpython_dir, script_name = os.path.split(__file__)
                    with open(os.path.join(bpython_dir, "sample-config")) as f:
                        default_config = f.read()

                    containing_dir = os.path.dirname(
                        os.path.abspath(self.config.config_path))
                    if not os.path.exists(containing_dir):
                        os.makedirs(containing_dir)
                    with open(self.config.config_path, 'w') as f:
                        f.write(default_config)
                except (IOError, OSError) as e:
                    self.interact.notify('error creating file: %r' % e)
                    return False
            else:
                return False

        if self.open_in_external_editor(self.config.config_path):
            self.interact.notify(
                'bpython config file edited. Restart bpython for changes to take effect.'
            )
        else:
            self.interact.notify('error editing config file')
Exemplo n.º 26
0
 def do_pastebin_xmlrpc(self, s):
     """Upload to pastebin via XML-RPC."""
     try:
         pasteservice = ServerProxy(self.config.pastebin_url)
     except IOError, e:
         self.interact.notify(_("Pastebin error for URL '%s': %s") %
                              (self.config.pastebin_url, str(e)))
         return
Exemplo n.º 27
0
 def __init__(self, exc_type, exc_value, tb, text=None):
     if text is None:
         text = _('An error occurred.')
     gtk.MessageDialog.__init__(self, buttons=gtk.BUTTONS_CLOSE,
                                type=gtk.MESSAGE_ERROR,
                                message_format=text)
     self.set_resizable(True)
     import cgitb
     text = cgitb.text((exc_type, exc_value, tb), 5)
     expander = gtk.Expander(_('Exception details'))
     self.vbox.pack_start(expander)
     textview = gtk.TextView()
     textview.get_buffer().set_text(text)
     scrolled_window = gtk.ScrolledWindow()
     scrolled_window.add(textview)
     expander.add(scrolled_window)
     self.show_all()
Exemplo n.º 28
0
 def do_pastebin_xmlrpc(self, s):
     """Upload to pastebin via XML-RPC."""
     try:
         pasteservice = ServerProxy(self.config.pastebin_url)
     except IOError, e:
         self.interact.notify(_("Pastebin error for URL '%s': %s") %
                              (self.config.pastebin_url, str(e)))
         return
Exemplo n.º 29
0
 def __init__(self, exc_type, exc_value, tb, text=None):
     if text is None:
         text = _('An error occurred.')
     gtk.MessageDialog.__init__(self, buttons=gtk.BUTTONS_CLOSE,
                                type=gtk.MESSAGE_ERROR,
                                message_format=text)
     self.set_resizable(True)
     import cgitb
     text = cgitb.text((exc_type, exc_value, tb), 5)
     expander = gtk.Expander(_('Exception details'))
     self.vbox.pack_start(expander)
     textview = gtk.TextView()
     textview.get_buffer().set_text(text)
     scrolled_window = gtk.ScrolledWindow()
     scrolled_window.add(textview)
     expander.add(scrolled_window)
     self.show_all()
Exemplo n.º 30
0
    def do_show_source(dispatcher):
        from bpython.translations import _
        from plugins.introspection import show_source

        obj = dispatcher.owner.current_object
        if obj is not None:
            show_source(obj)
        else:
            dispatcher.owner.interact.notify(_('Cannot show source.'))
        return ''
Exemplo n.º 31
0
    def do_pastebin(self, s):
        """Actually perform the upload."""
        if s == self.prev_pastebin_content:
            self.interact.notify(_('Duplicate pastebin. Previous URL: %s') %
                                  (self.prev_pastebin_url, ))
            return self.prev_pastebin_url

        if self.config.pastebin_helper:
            return self.do_pastebin_helper(s)
        else:
            return self.do_pastebin_json(s)
Exemplo n.º 32
0
    def do_pastebin_helper(self, s):
        """Call out to helper program for pastebin upload."""
        self.interact.notify(_('Posting data to pastebin...'))

        try:
            helper = subprocess.Popen('',
                                      executable=self.config.pastebin_helper,
                                      stdin=subprocess.PIPE,
                                      stdout=subprocess.PIPE)
            helper.stdin.write(s.encode(getpreferredencoding()))
            output = helper.communicate()[0].decode(getpreferredencoding())
            paste_url = output.split()[0]
        except OSError, e:
            if e.errno == errno.ENOENT:
                self.interact.notify(_('Upload failed: '
                                       'Helper program not found.'))
            else:
                self.interact.notify(_('Upload failed: '
                                       'Helper program could not be run.'))
            return
Exemplo n.º 33
0
    def do_pastebin_helper(self, s):
        """Call out to helper program for pastebin upload."""
        self.interact.notify(_('Posting data to pastebin...'))

        try:
            helper = subprocess.Popen('',
                                      executable=self.config.pastebin_helper,
                                      stdin=subprocess.PIPE,
                                      stdout=subprocess.PIPE)
            helper.stdin.write(s.encode(getpreferredencoding()))
            output = helper.communicate()[0].decode(getpreferredencoding())
            paste_url = output.split()[0]
        except OSError, e:
            if e.errno == errno.ENOENT:
                self.interact.notify(_('Upload failed: '
                                       'Helper program not found.'))
            else:
                self.interact.notify(_('Upload failed: '
                                       'Helper program could not be run.'))
            return
Exemplo n.º 34
0
    def do_pastebin(self, s):
        """Actually perform the upload."""
        if s == self.prev_pastebin_content:
            self.interact.notify(_('Duplicate pastebin. Previous URL: %s') %
                                  (self.prev_pastebin_url, ))
            return self.prev_pastebin_url

        if self.config.pastebin_helper:
            return self.do_pastebin_helper(s)
        else:
            return self.do_pastebin_xmlrpc(s)
Exemplo n.º 35
0
def main(args=None, locals_=None, banner=None):
    config, options, exec_args = bpargs.parse(args, (
        'scroll options', None, [
            Option('--log', '-L', action='store_true',
                help=_("log debug messages to bpython.log")),
            Option('--type', '-t', action='store_true',
                help=_("enter lines of file as though interactively typed")),
            ]))
    if options.log:
        handler = logging.FileHandler(filename='bpython.log')
        logging.getLogger('curtsies').setLevel(logging.DEBUG)
        logging.getLogger('curtsies').addHandler(handler)
        logging.getLogger('curtsies').propagate = False
        logging.getLogger('bpython').setLevel(logging.DEBUG)
        logging.getLogger('bpython').addHandler(handler)
        logging.getLogger('bpython').propagate = False
    else:
        logging.getLogger('bpython').setLevel(logging.WARNING)

    interp = hy.cmdline.HyREPL()
    paste = None
    if exec_args:
        assert options, "don't pass in exec_args without options"
        exit_value = 0
        if options.type:
            paste = curtsies.events.PasteEvent()
            sourcecode = open(exec_args[0]).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:
                raise SystemExit(exit_value)
    else:
        sys.path.insert(0, '') # expected for interactive sessions (vanilla python does it)

    mainloop(config, locals_, banner, interp, paste, interactive=(not exec_args))
Exemplo n.º 36
0
def main(args=None, locals_=None, banner=None):
    config, options, exec_args = bpargs.parse(args, ('scroll options', None, [
        Option('--log',
               '-L',
               action='store_true',
               help=_("log debug messages to bpython.log")),
        Option('--type',
               '-t',
               action='store_true',
               help=_("enter lines of file as though interactively typed")),
    ]))
    if options.log:
        handler = logging.FileHandler(filename='bpython.log')
        logging.getLogger('curtsies').setLevel(logging.DEBUG)
        logging.getLogger('curtsies').addHandler(handler)
        logging.getLogger('curtsies').propagate = False
        logging.getLogger('bpython').setLevel(logging.DEBUG)
        logging.getLogger('bpython').addHandler(handler)
        logging.getLogger('bpython').propagate = False
    else:
        logging.getLogger('bpython').setLevel(logging.WARNING)

    interp = None
    paste = None
    if exec_args:
        if not options:
            raise ValueError("don't pass in exec_args without options")
        exit_value = 0
        if options.type:
            paste = curtsies.events.PasteEvent()
            sourcecode = open(exec_args[0]).read()
            paste.events.extend(sourcecode)
        else:
            try:
                interp = code.InteractiveInterpreter(locals=locals_)
                bpargs.exec_code(interp, exec_args)
            except SystemExit, e:
                exit_value = e.args
            if not options.interactive:
                raise SystemExit(exit_value)
Exemplo n.º 37
0
def main(args=None, locals_=None, banner=None):
    config, options, exec_args = bpargs.parse(args, (
        'curtsies options', None, [
            Option('--log', '-L', action='store_true',
                   help=_("log debug messages to bpython.log")),
            Option('--type', '-t', action='store_true',
                   help=_("enter lines of file as though interactively typed")),
            ]))
    if options.log:
        handler = logging.FileHandler(filename='bpython.log')
        logging.getLogger('curtsies').setLevel(logging.WARNING)
        logging.getLogger('curtsies').addHandler(handler)
        logging.getLogger('curtsies').propagate = False
        logging.getLogger('bpython').setLevel(logging.WARNING)
        logging.getLogger('bpython').addHandler(handler)
        logging.getLogger('bpython').propagate = False
    else:
        logging.getLogger('bpython').setLevel(logging.ERROR)
        logging.getLogger('curtsies').setLevel(logging.ERROR)

    interp = None
    paste = None
    if exec_args:
        if not options:
            raise ValueError("don't pass in exec_args without options")
        exit_value = 0
        if options.type:
            paste = curtsies.events.PasteEvent()
            sourcecode = open(exec_args[0]).read()
            paste.events.extend(sourcecode)
        else:
            try:
                interp = code.InteractiveInterpreter(locals=locals_)
                bpargs.exec_code(interp, exec_args)
            except SystemExit, e:
                exit_value = e.args
            if not options.interactive:
                raise SystemExit(exit_value)
Exemplo n.º 38
0
    def write2file(self):
        """Prompt for a filename and write the current contents of the stdout
        buffer to disk."""

        try:
            fn = self.interact.file_prompt(_('Save to file (Esc to cancel): '))
            if not fn:
                self.interact.notify(_('Save cancelled.'))
                return
        except ValueError:
            self.interact.notify(_('Save cancelled.'))
            return

        if fn.startswith('~'):
            fn = os.path.expanduser(fn)
        if not fn.endswith('.py') and self.config.save_append_py:
            fn = fn + '.py'

        mode = 'w'
        if os.path.exists(fn):
            mode = self.interact.file_prompt(
                _('%s already exists. Do you '
                  'want to (c)ancel, '
                  ' (o)verwrite or '
                  '(a)ppend? ') % (fn, ))
            if mode in ('o', 'overwrite', _('overwrite')):
                mode = 'w'
            elif mode in ('a', 'append', _('append')):
                mode = 'a'
            else:
                self.interact.notify(_('Save cancelled.'))
                return

        s = self.formatforfile(self.getstdout())

        try:
            with open(fn, mode) as f:
                f.write(s)
        except IOError as e:
            self.interact.notify(
                _("Error writing file '%s': %s") % (fn, str(e)))
        else:
            self.interact.notify(_('Saved to %s.') % (fn, ))
Exemplo n.º 39
0
 def get_source_of_current_name(self):
     """Return the source code of the object which is bound to the
     current name in the current input line. Throw `SourceNotFound` if the
     source cannot be found. Returns bytestring in py2, unicode in py3."""
     obj = self.current_func
     try:
         if obj is None:
             line = self.current_line
             if not line.strip():
                 raise SourceNotFound(_("Nothing to get source of"))
             if inspection.is_eval_safe_name(line):
                 obj = self.get_object(line)
         return inspect.getsource(obj)
     except (AttributeError, NameError) as e:
         msg = _("Cannot get source: %s") % (str(e), )
     except IOError as e:
         msg = str(e)
     except TypeError as e:
         if "built-in" in str(e):
             msg = _("Cannot access source of %r") % (obj, )
         else:
             msg = _("No source code found for %s") % (self.current_line, )
     raise SourceNotFound(msg)
    def write2file(self):
        """Prompt for a filename and write the current contents of the stdout
        buffer to disk."""

        try:
            fn = self.interact.file_prompt(_('Save to file (Esc to cancel): '))
            if not fn:
                self.interact.notify(_('Save cancelled.'))
                return
        except ValueError:
            self.interact.notify(_('Save cancelled.'))
            return

        if fn.startswith('~'):
            fn = os.path.expanduser(fn)
        if not fn.endswith('.py') and self.config.save_append_py:
            fn = fn + '.py'

        mode = 'w'
        if os.path.exists(fn):
            mode = self.interact.file_prompt(_('%s already exists. Do you '
                                               'want to (c)ancel, '
                                               ' (o)verwrite or '
                                               '(a)ppend? ') % (fn, ))
            if mode in ('o', 'overwrite', _('overwrite')):
                mode = 'w'
            elif mode in ('a', 'append', _('append')):
                mode = 'a'
            else:
                self.interact.notify(_('Save cancelled.'))
                return

        s = self.formatforfile(self.getstdout())

        try:
            with open(fn, mode) as f:
                f.write(s)
        except IOError as e:
            self.interact.notify(_("Error writing file '%s': %s") % (fn,
                                                                     str(e)))
        else:
            self.interact.notify(_('Saved to %s.') % (fn, ))
Exemplo n.º 41
0
    def __init__(self, event_loop, palette, interpreter, config):
        repl.Repl.__init__(self, interpreter, config)

        self._redraw_handle = None
        self._redraw_pending = False
        self._redraw_time = 0

        self.listbox = BPythonListBox(urwid.SimpleListWalker([]))

        self.tooltip = urwid.ListBox(urwid.SimpleListWalker([]))
        self.tooltip.grid = None
        self.overlay = Tooltip(self.listbox, self.tooltip)
        self.stdout_hist = ''

        self.frame = urwid.Frame(self.overlay)

        if urwid.get_encoding_mode() == 'narrow':
            input_filter = decoding_input_filter
        else:
            input_filter = None

        # This constructs a raw_display.Screen, which nabs sys.stdin/out.
        self.main_loop = urwid.MainLoop(self.frame,
                                        palette,
                                        event_loop=event_loop,
                                        unhandled_input=self.handle_input,
                                        input_filter=input_filter,
                                        handle_mouse=False)

        # String is straight from bpython.cli
        self.statusbar = Statusbar(
            config,
            _(" <%s> Rewind  <%s> Save  <%s> Pastebin "
              " <%s> Pager  <%s> Show Source ") %
            (config.undo_key, config.save_key, config.pastebin_key,
             config.last_output_key, config.show_source_key), self.main_loop)
        self.frame.set_footer(self.statusbar.widget)
        self.interact = URWIDInteraction(self.config, self.statusbar,
                                         self.frame)

        self.edits = []
        self.edit = None
        self.current_output = None
        self._completion_update_suppressed = False

        # Bulletproof: this is a value extract_exit_value accepts.
        self.exit_value = ()

        load_urwid_command_map(config)
Exemplo n.º 42
0
    def get_source_of_current_name(self):
        """Return the unicode source code of the object which is bound to the
        current name in the current input line. Throw `SourceNotFound` if the
        source cannot be found."""

        obj = self.current_func
        try:
            if obj is None:
                line = self.current_line
                if not line.strip():
                    raise SourceNotFound(_("Nothing to get source of"))
                if inspection.is_eval_safe_name(line):
                    obj = self.get_object(line)
            return inspection.get_source_unicode(obj)
        except (AttributeError, NameError) as e:
            msg = _(u"Cannot get source: %s") % (e, )
        except IOError as e:
            msg = u"%s" % (e, )
        except TypeError as e:
            if "built-in" in u"%s" % (e, ):
                msg = _("Cannot access source of %r") % (obj, )
            else:
                msg = _("No source code found for %s") % (self.current_line, )
        raise SourceNotFound(msg)
Exemplo n.º 43
0
    def __init__(self, event_loop, palette, interpreter, config):
        repl.Repl.__init__(self, interpreter, config)

        self._redraw_handle = None
        self._redraw_pending = False
        self._redraw_time = 0

        self.listbox = BPythonListBox(urwid.SimpleListWalker([]))

        self.tooltip = urwid.ListBox(urwid.SimpleListWalker([]))
        self.tooltip.grid = None
        self.overlay = Tooltip(self.listbox, self.tooltip)
        self.stdout_hist = ""

        self.frame = urwid.Frame(self.overlay)

        if urwid.get_encoding_mode() == "narrow":
            input_filter = decoding_input_filter
        else:
            input_filter = None

        # This constructs a raw_display.Screen, which nabs sys.stdin/out.
        self.main_loop = urwid.MainLoop(
            self.frame,
            palette,
            event_loop=event_loop,
            unhandled_input=self.handle_input,
            input_filter=input_filter,
            handle_mouse=False,
        )

        # String is straight from bpython.cli
        self.statusbar = Statusbar(
            config,
            _(" <%s> Rewind  <%s> Save  <%s> Pastebin " " <%s> Pager  <%s> Show Source ")
            % (config.undo_key, config.save_key, config.pastebin_key, config.last_output_key, config.show_source_key),
            self.main_loop,
        )
        self.frame.set_footer(self.statusbar.widget)
        self.interact = URWIDInteraction(self.config, self.statusbar, self.frame)

        self.edits = []
        self.edit = None
        self.current_output = None
        self._completion_update_suppressed = False

        load_urwid_command_map(config)
Exemplo n.º 44
0
    def do_pastebin_helper(self, s):
        """Call out to helper program for pastebin upload."""
        self.interact.notify(_('Posting data to pastebin...'))

        try:
            helper = subprocess.Popen('',
                                      executable=self.config.pastebin_helper,
                                      stdin=subprocess.PIPE,
                                      stdout=subprocess.PIPE)
            helper.stdin.write(s.encode(getpreferredencoding()))
            output = helper.communicate()[0].decode(getpreferredencoding())
            paste_url = output.split()[0]
        except OSError as e:
            if e.errno == errno.ENOENT:
                self.interact.notify(
                    _('Upload failed: '
                      'Helper program not found.'))
            else:
                self.interact.notify(
                    _('Upload failed: '
                      'Helper program could not be run.'))
            return

        if helper.returncode != 0:
            self.interact.notify(
                _('Upload failed: '
                  'Helper program returned non-zero exit '
                  'status %s.' % (helper.returncode, )))
            return

        if not paste_url:
            self.interact.notify(
                _('Upload failed: '
                  'No output from helper program.'))
            return
        else:
            parsed_url = urlparse(paste_url)
            if (not parsed_url.scheme
                    or any(unicodedata.category(c) == 'Cc'
                           for c in paste_url)):
                self.interact.notify(
                    _("Upload failed: "
                      "Failed to recognize the helper "
                      "program's output as an URL."))
                return

        self.prev_pastebin_content = s
        self.interact.notify(_('Pastebin URL: %s') % (paste_url, ), 10)
        return paste_url
Exemplo n.º 45
0
    def __init__(self):
        logging.debug("starting init")
        interp = code.InteractiveInterpreter()

        config = Struct()
        loadini(config, default_config_path())
        config.autocomplete_mode = SIMPLE # only one implemented currently

        #TODO determine if this is supposed to use this, or if it should be
        # frontend specific.
        if config.cli_suggestion_width <= 0 or config.cli_suggestion_width > 1:
            config.cli_suggestion_width = 1

        self.status_bar = StatusBar(_('welcome to bpython'))
        self.rl_char_sequences = get_updated_char_sequences(key_dispatch, config)
        logging.debug("starting parent init")
        super(Repl, self).__init__(interp, config)
        self.formatter = BPythonFormatter(config.color_scheme)
        self.interact = self.status_bar # overwriting what bpython.Repl put there
                                        # interact is called to interact with the status bar,
                                        # so we're just using the same object
        self._current_line = '' # line currently being edited, without '>>> '
        self.current_formatted_line = fmtstr('') # needs to be updated before each draw
                                                 # by calling set_formatted_line
        self.display_lines = [] # lines separated whenever logical line
                                # length goes over what the terminal width
                                # was at the time of original output
        self.history = [] # this is every line that's been executed;
                                # it gets smaller on rewind
        self.display_buffer = [] # formatted version of lines in the buffer
                                 # kept around so we can unhighlight parens
                                 # using self.reprint_line as called by
                                 # bpython.Repl
        self.scroll_offset = 0
        self.cursor_offset_in_line = 0 # from the left, 0 means first char
        self.done = True

        self.paste_mode = False

        self.width = None
        self.height = None
        self.start_background_tasks()
    def do_pastebin_helper(self, s):
        """Call out to helper program for pastebin upload."""
        self.interact.notify(_('Posting data to pastebin...'))

        try:
            helper = subprocess.Popen('',
                                      executable=self.config.pastebin_helper,
                                      stdin=subprocess.PIPE,
                                      stdout=subprocess.PIPE)
            helper.stdin.write(s.encode(getpreferredencoding()))
            output = helper.communicate()[0].decode(getpreferredencoding())
            paste_url = output.split()[0]
        except OSError as e:
            if e.errno == errno.ENOENT:
                self.interact.notify(_('Upload failed: '
                                       'Helper program not found.'))
            else:
                self.interact.notify(_('Upload failed: '
                                       'Helper program could not be run.'))
            return

        if helper.returncode != 0:
            self.interact.notify(_('Upload failed: '
                                   'Helper program returned non-zero exit '
                                   'status %d.' % (helper.returncode, )))
            return

        if not paste_url:
            self.interact.notify(_('Upload failed: '
                                   'No output from helper program.'))
            return
        else:
            parsed_url = urlparse(paste_url)
            if (not parsed_url.scheme
                    or any(unicodedata.category(c) == 'Cc'
                           for c in paste_url)):
                self.interact.notify(_("Upload failed: "
                                       "Failed to recognize the helper "
                                       "program's output as an URL."))
                return

        self.prev_pastebin_content = s
        self.interact.notify(_('Pastebin URL: %s') % (paste_url, ), 10)
        return paste_url
Exemplo n.º 47
0
    def edit_config(self):
        if not (os.path.isfile(self.config.config_path)):
            if self.interact.confirm(_("Config file does not exist - create new from default? (y/N)")):
                try:
                    bpython_dir, script_name = os.path.split(__file__)
                    with open(os.path.join(bpython_dir, "sample-config")) as f:
                        default_config = f.read()

                    containing_dir = os.path.dirname(os.path.abspath(self.config.config_path))
                    if not os.path.exists(containing_dir):
                        os.makedirs(containing_dir)
                    with open(self.config.config_path, 'w') as f:
                        f.write(default_config)
                except (IOError, OSError) as e:
                    self.interact.notify('error creating file: %r' % e)
                    return False
            else:
                return False

        if self.open_in_external_editor(self.config.config_path):
            self.interact.notify('bpython config file edited. Restart bpython for changes to take effect.')
        else:
            self.interact.notify('error editing config file')
Exemplo n.º 48
0
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)
Exemplo n.º 49
0
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)
Exemplo n.º 50
0
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)
Exemplo n.º 51
0
 def callback_wrapper(result):
     callback(result.lower() in (_('y'), _('yes')))
Exemplo n.º 52
0
    def __init__(self, locals_=None, config=None, request_refresh=lambda: None, banner=None, interp=None):
        """
        locals_ is a mapping of locals to pass into the interpreter
        config is a bpython config.Struct with config attributes
        request_refresh is a function that will be called when the Repl
            wants to refresh the display, but wants control returned to it afterwards
        banner is a string to display briefly in the status bar
        interp is an interpreter to use
        """

        logging.debug("starting init")

        if config is None:
            config = Struct()
            loadini(config, default_config_path())

        self.weak_rewind = bool(locals_ or interp) # If creating a new interpreter on undo
                                                   # would be unsafe because initial
                                                   # state was passed in
        if interp is None:
            interp = code.InteractiveInterpreter(locals=locals_)
        if banner is None:
            banner = _('welcome to bpython')
        config.autocomplete_mode = SIMPLE # only one implemented currently
        if config.cli_suggestion_width <= 0 or config.cli_suggestion_width > 1:
            config.cli_suggestion_width = 1

        self.reevaluating = False
        self.fake_refresh_requested = False
        def smarter_request_refresh():
            if self.reevaluating or self.paste_mode:
                self.fake_refresh_requested = True
            else:
                request_refresh()
        self.request_refresh = smarter_request_refresh

        self.status_bar = StatusBar(banner if config.curtsies_fill_terminal else '', _(
            " <%s> Rewind  <%s> Save  <%s> Pastebin <%s> Editor"
            ) % (config.undo_key, config.save_key, config.pastebin_key, config.external_editor_key),
            refresh_request=self.request_refresh
            )
        self.rl_char_sequences = get_updated_char_sequences(key_dispatch, config)
        logging.debug("starting parent init")
        super(Repl, self).__init__(interp, config)
        self.formatter = BPythonFormatter(config.color_scheme)
        self.interact = self.status_bar # overwriting what bpython.Repl put there
                                        # interact is called to interact with the status bar,
                                        # so we're just using the same object
        self._current_line = '' # line currently being edited, without '>>> '
        self.current_stdouterr_line = '' # current line of output - stdout and stdin go here
        self.display_lines = [] # lines separated whenever logical line
                                # length goes over what the terminal width
                                # was at the time of original output
        self.history = [] # this is every line that's been executed;
                          # it gets smaller on rewind
        self.display_buffer = [] # formatted version of lines in the buffer
                                 # kept around so we can unhighlight parens
                                 # using self.reprint_line as called by
                                 # bpython.Repl
        self.scroll_offset = 0 # how many times display has been scrolled down
                               # because there wasn't room to display everything
        self.cursor_offset_in_line = 0 # from the left, 0 means first char

        self.coderunner = CodeRunner(self.interp, self.request_refresh)
        self.stdout = FakeOutput(self.coderunner, self.send_to_stdout)
        self.stderr = FakeOutput(self.coderunner, self.send_to_stderr)
        self.stdin = FakeStdin(self.coderunner, self)

        self.request_paint_to_clear_screen = False # next paint should clear screen
        self.last_events = [None] * 50
        self.presentation_mode = False
        self.paste_mode = False

        self.width = None  # will both be set by a window resize event
        self.height = None
Exemplo n.º 53
0
def parse(args, extras=None, ignore_stdin=False):
    """Receive an argument list - if None, use sys.argv - parse all args and
    take appropriate action. Also receive optional extra options: this should
    be a tuple of (title, description, options)
        title:          The title for the option group
        description:    A full description of the option group
        options:        A list of optparse.Option objects to be added to the
                        group

    e.g.:

    parse(
        ['-i', '-m', 'foo.py'],
        ('Front end-specific options',
        'A full description of what these options are for',
        [optparse.Option('-f', action='store_true', dest='f', help='Explode'),
        optparse.Option('-l', action='store_true', dest='l', help='Love')]))


    Return a tuple of (config, options, exec_args) wherein "config" is the
    config object either parsed from a default/specified config file or default
    config options, "options" is the parsed options from
    OptionParser.parse_args, and "exec_args" are the args (if any) to be parsed
    to the executed file (if any).
    """
    if args is None:
        args = sys.argv[1:]

    parser = RaisingOptionParser(
        usage=_('Usage: %prog [options] [file [args]]\n'
                'NOTE: If bpython sees an argument it does '
                'not know, execution falls back to the '
                'regular Python interpreter.'))
    # This is not sufficient if bpython gains its own -m support
    # (instead of falling back to Python itself for that).
    # That's probably fixable though, for example by having that
    # option swallow all remaining arguments in a callback.
    parser.disable_interspersed_args()
    parser.add_option('--config',
                      default=default_config_path(),
                      help=_('Use CONFIG instead of default config file.'))
    parser.add_option('--interactive',
                      '-i',
                      action='store_true',
                      help=_('Drop to bpython shell after running file '
                             'instead of exiting.'))
    parser.add_option('--quiet',
                      '-q',
                      action='store_true',
                      help=_("Don't flush the output to stdout."))
    parser.add_option('--version',
                      '-V',
                      action='store_true',
                      help=_('Print version and exit.'))

    if extras is not None:
        extras_group = OptionGroup(parser, extras[0], extras[1])
        for option in extras[2]:
            extras_group.add_option(option)
        parser.add_option_group(extras_group)

    try:
        options, args = parser.parse_args(args)
    except OptionParserFailed:
        # Just let Python handle this
        os.execv(sys.executable, [sys.executable] + args)

    if options.version:
        print('bpython version', __version__, end=" ")
        print('on top of Python', sys.version.split()[0])
        print('(C) 2008-2015 Bob Farrell, Andreas Stuehrk et al. '
              'See AUTHORS for detail.')
        raise SystemExit

    if not ignore_stdin and not (sys.stdin.isatty() and sys.stdout.isatty()):
        interpreter = code.InteractiveInterpreter()
        interpreter.runsource(sys.stdin.read())
        raise SystemExit

    config = Struct()
    loadini(config, options.config)

    return config, options, args
Exemplo n.º 54
0
                                      stdout=subprocess.PIPE)
            helper.stdin.write(s.encode(getpreferredencoding()))
            output = helper.communicate()[0].decode(getpreferredencoding())
            paste_url = output.split()[0]
        except OSError, e:
            if e.errno == errno.ENOENT:
                self.interact.notify(_('Upload failed: '
                                       'Helper program not found.'))
            else:
                self.interact.notify(_('Upload failed: '
                                       'Helper program could not be run.'))
            return

        if helper.returncode != 0:
            self.interact.notify(_('Upload failed: '
                                   'Helper program returned non-zero exit '
                                   'status %s.' % (helper.returncode, )))
            return

        if not paste_url:
            self.interact.notify(_('Upload failed: '
                                   'No output from helper program.'))
            return
        else:
            parsed_url = urlparse(paste_url)
            if (not parsed_url.scheme
                or any(unicodedata.category(c) == 'Cc' for c in paste_url)):
                self.interact.notify(_("Upload failed: "
                                       "Failed to recognize the helper "
                                       "program's output as an URL."))
                return
Exemplo n.º 55
0
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 0
Exemplo n.º 56
0
 def do_key_press_event(self, event):
     state = event.state & (gtk.gdk.CONTROL_MASK | gtk.gdk.MOD1_MASK
                            | gtk.gdk.MOD4_MASK | gtk.gdk.SHIFT_MASK)
     if not state:
         if event.keyval == gtk.keysyms.F2:
             source = self.get_source_of_current_name()
             if source is not None:
                 show_source_in_new_window(source,
                                           self.config.color_gtk_scheme,
                                           self.config.syntax)
             else:
                 self.interact.notify(_('Cannot show source.'))
         elif event.keyval == gtk.keysyms.Return:
             if self.list_win_visible:
                 self.list_win_visible = False
                 self.list_win.hide()
             self.rl_history.reset()
             line = self.current_line()
             more = self.push_line()
             self.prompt(more)
             if self.reset_indent:
                 self.reset_indent = False
             else:
                 indentation = self.next_indentation()
                 if indentation:
                     with self.editing:
                         self.text_buffer.insert(self.get_cursor_iter(),
                                                 '\t' * indentation)
                     self.move_cursor(indentation)
             return True
         elif event.keyval == gtk.keysyms.Tab and self.list_win_visible:
             self.list_win.forward()
             return True
         elif event.keyval == gtk.keysyms.Up:
             if self.list_win_visible:
                 self.list_win.back()
             else:
                 if not self.rl_history.is_at_end:
                     self.rl_history.enter(self.current_line())
                     self.change_line(self.rl_history.back())
                     self.text_buffer.place_cursor(self.get_line_end_iter())
             return True
         elif event.keyval == gtk.keysyms.Down:
             if self.list_win_visible:
                 self.list_win.forward()
             else:
                 if not self.rl_history.is_at_start:
                     self.rl_history.enter(self.current_line())
                     self.change_line(self.rl_history.forward())
                     self.text_buffer.place_cursor(self.get_line_end_iter())
             return True
     elif state & gtk.gdk.SHIFT_MASK:
         if (event.keyval == gtk.keysyms.ISO_Left_Tab
                 and self.list_win_visible):
             self.list_win.back()
             return True
     elif state & gtk.gdk.CONTROL_MASK:
         if event.string == chr(4) and not self.current_line():
             self.emit('exit-event')
             return True
     return gtk.TextView.do_key_press_event(self, event)
Exemplo n.º 57
0
def parse(args, extras=None, ignore_stdin=False):
    """Receive an argument list - if None, use sys.argv - parse all args and
    take appropriate action. Also receive optional extra options: this should
    be a tuple of (title, description, options)
        title:          The title for the option group
        description:    A full description of the option group
        options:        A list of optparse.Option objects to be added to the
                        group

    e.g.:

    parse(['-i', '-m', 'foo.py'],
          ('Front end-specific options',
          'A full description of what these options are for',
          [optparse.Option('-f', action='store_true', dest='f', help='Explode'),
           optparse.Option('-l', action='store_true', dest='l', help='Love')]))


    Return a tuple of (config, options, exec_args) wherein "config" is the
    config object either parsed from a default/specified config file or default
    config options, "options" is the parsed options from
    OptionParser.parse_args, and "exec_args" are the args (if any) to be parsed
    to the executed file (if any).
    """
    if args is None:
        args = sys.argv[1:]

    parser = RaisingOptionParser(
        usage=_('Usage: %prog [options] [file [args]]\n'
                'NOTE: If bpython sees an argument it does '
                'not know, execution falls back to the '
                'regular Python interpreter.'))
    # This is not sufficient if bpython gains its own -m support
    # (instead of falling back to Python itself for that).
    # That's probably fixable though, for example by having that
    # option swallow all remaining arguments in a callback.
    parser.disable_interspersed_args()
    parser.add_option('--config', default=default_config_path(),
                      help=_('Use CONFIG instead of default config file.'))
    parser.add_option('--interactive', '-i', action='store_true',
                      help=_('Drop to bpython shell after running file '
                             'instead of exiting.'))
    parser.add_option('--quiet', '-q', action='store_true',
                      help=_("Don't flush the output to stdout."))
    parser.add_option('--version', '-V', action='store_true',
                      help=_('Print version and exit.'))

    if extras is not None:
        extras_group = OptionGroup(parser, extras[0], extras[1])
        for option in extras[2]:
            extras_group.add_option(option)
        parser.add_option_group(extras_group)

    try:
        options, args = parser.parse_args(args)
    except OptionParserFailed:
        # Just let Python handle this
        os.execv(sys.executable, [sys.executable] + args)

    if options.version:
        print('bpython version', __version__, end=' ')
        print('on top of Python', sys.version.split()[0])
        print('(C) 2008-2012 Bob Farrell, Andreas Stuehrk et al. '
              'See AUTHORS for detail.')
        raise SystemExit

    if not ignore_stdin and not (sys.stdin.isatty() and sys.stdout.isatty()):
        interpreter = code.InteractiveInterpreter()
        interpreter.runsource(sys.stdin.read())
        raise SystemExit

    config = Struct()
    loadini(config, options.config)

    return config, options, args
Exemplo n.º 58
0
 def __init__(self):
     gtk.Statusbar.__init__(self)
     self.context_id = self.get_context_id(_('Statusbar'))
Exemplo n.º 59
0
 def __init__(self, DialogType, text=None):
     self.DialogType = DialogType
     self.text = text or _('An error occurred.')