Commits

INADA Naoki committed 479fc29 Merge

merge

Comments (0)

Files changed (13)

 ============
 Pygments
 (apt-get install python-pygments)
+Sphinx != 1.1.2 (for the documentation only)
+(apt-get install python-sphinx)
 
 Introduction
 ============
 # The MIT License
 #
 # Copyright (c) 2008 Bob Farrell
+# Copyright (c) 2013 Sebastian Ramacher
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # THE SOFTWARE.
 
+import os
 import sys
+import traceback
 
 import bpython
 from bpdb.debugger import BPdb
-
+from optparse import OptionParser
+from pdb import Restart
 
 __version__ = bpython.__version__
 
 
 def pm():
     post_mortem(getattr(sys, "last_traceback", None))
+
+def main():
+    parser = OptionParser(
+        usage='Usage: %prog [options] [file [args]]')
+    parser.add_option('--version', '-V', action='store_true',
+                      help='Print version and exit.')
+    options, args = parser.parse_args(sys.argv)
+    if options.version:
+        print 'bpdb on top of bpython version', __version__,
+        print 'on top of Python', sys.version.split()[0]
+        print ('(C) 2008-2013 Bob Farrell, Andreas Stuehrk et al. '
+               'See AUTHORS for detail.')
+        return 0
+
+    # The following code is baed on Python's pdb.py.
+    mainpyfile = args[1]
+    if not os.path.exists(mainpyfile):
+        print 'Error:', mainpyfile, 'does not exist'
+        return 1
+
+    # Hide bpdb from argument list.
+    del sys.argv[0]
+
+    # Replace bpdb's dir with script's dir in front of module search path.
+    sys.path[0] = os.path.dirname(mainpyfile)
+
+    pdb = BPdb()
+    while True:
+        try:
+            pdb._runscript(mainpyfile)
+            if pdb._user_requested_quit:
+                break
+            print "The program finished and will be restarted"
+        except Restart:
+            print "Restarting", mainpyfile, "with arguments:"
+            print "\t" + " ".join(sys.argv[1:])
+        except SystemExit:
+            # In most cases SystemExit does not warrant a post-mortem session.
+            print "The program exited via sys.exit(). Exit status: ",
+            print sys.exc_info()[1]
+        except:
+            traceback.print_exc()
+            print "Uncaught exception. Entering post mortem debugging"
+            print "Running 'cont' or 'step' will restart the program"
+            t = sys.exc_info()[2]
+            pdb.interaction(None, t)
+            print "Post mortem debugger finished. The " + mainpyfile + \
+                  " will be restarted"
+
+# The MIT License
+#
+# Copyright (c) 2013 Sebastian Ramacher
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+import sys
+
+if __name__ == '__main__':
+    from bpdb import main
+    sys.exit(main())
                 curses.flushinp()
                 raise ValueError
             # literal
-            elif 0 <= c < 127:
+            elif 0 < c < 127:
                 c = chr(c)
                 self.win.addstr(c, get_colpair(self.config, 'prompt'))
                 o += c
     curses.doupdate()
     DO_RESIZE = False
 
-    caller.resize()
+    try:
+        caller.resize()
+    except curses.error:
+        pass
     # The list win resizes itself every time it appears so no need to do it here.
 
 

bpython/config.py

             'pastebin_private': True,
             'pastebin_show_url': 'http://bpaste.net/show/$paste_id/',
             'pastebin_helper': '',
+            'save_append_py': False
         },
         'keyboard': {
             'clear_line': 'C-u',
     methods = config.get('general', 'magic_methods')
     struct.magic_methods = [meth.strip() for meth in methods.split(",")]
     struct.autocomplete_mode = config.get('general', 'autocomplete_mode')
+    struct.save_append_py = config.getboolean('general', 'save_append_py')
 
     struct.gtk_font = config.get('gtk', 'font')
 

bpython/importcompletion.py

             with catch_warnings():
                 warnings.simplefilter("ignore", ImportWarning)
                 fo, pathname, _ = imp.find_module(name, [path])
-        except (ImportError, SyntaxError):
+        except (ImportError, IOError, SyntaxError):
             continue
         except UnicodeEncodeError:
             # Happens with Python 3 when there is a filename in some
 
         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'):
+                mode = 'w'
+            elif mode in ('a', 'append'):
+                mode = 'a'
+            else:
+                self.interact.notify('Save cancelled.')
+                return
 
         s = self.formatforfile(self.getstdout())
 
         try:
-            f = open(fn, 'w')
+            f = open(fn, mode)
             f.write(s)
             f.close()
         except IOError:
             self.interact.notify("Disk write error for file '%s'." % (fn, ))
         else:
-            self.interact.notify('Saved to %s' % (fn, ))
+            self.interact.notify('Saved to %s.' % (fn, ))
 
     def pastebin(self, s=None):
         """Upload to a pastebin and display the URL in the status bar."""

doc/sphinx/source/configuration-options.rst

 ^^^^^^^^^^^^
 Whether to flush all output to stdout on exit (default: True).
 
+save_append_py
+^^^^^^^^^^^^^^
+Whether to append ``.py`` to the filename while saving the input to a file.
+
+.. versionadded:: 0.13
+
 Keyboard
 --------
 This section refers to the ``[keyboard]`` section in your ``$XDG_CONFIG_HOME/bpython/config``.

doc/sphinx/source/themes.rst

 ======
 This chapter is about bpython's themeing capabalities.
 
-bpython uses .theme files placed in your ~/.bpython directory. You can set the
-theme in the :ref:`configuration_color_scheme` option in your
-`~/bpython/config`` file (:ref:`configuration`). You can find some of our
-themes in our gallery on our website:
-http://bpython-interpreter.org/themes/
+bpython uses .theme files placed in your ``$XDG_CONFIG_HOME/bpython`` directory
+[#f1]_.  You can set the theme in the :ref:`configuration_color_scheme` option
+in your ``$XDG_CONFIG_HOME/bpython/config`` file (:ref:`configuration`). You can
+find some of our themes in our gallery on our website:
+`<http://bpython-interpreter.org/themes/>`_
 
 Available Colors
 ----------------
   # which stands for:
   #   blacK, Red, Green, Yellow, Blue, Magenta, Cyan, White, Default
   # Capital letters represent bold
-  # Copy to ~/.bpython/foo.theme and set "color_scheme = foo" in ~/bpython/config
+  # Copy to $XDG_CONFIG_HOME/bpython/foo.theme and set "color_scheme = foo" in
+  # $XDG_CONFIG_HOME/bpython/config ($XDG_CONFIG_HOME defaults to ~/.config)
 
   [syntax]
   keyword = y
   punctuation = y
   token = C
   paren = R
-  
+
   [interface]
   # XXX: gnome-terminal appears to be braindead. The cursor will disappear unless
   # you set the background colour to "d".
   prompt = c
   prompt_more = g
 
+.. :: Footnotes
+
+.. [#f1] ``$XDG_CONFIG_HOME`` defaults to ``~/.config`` if not set.
+
 # which stands for:
 #   blacK, Red, Green, Yellow, Blue, Magenta, Cyan, White, Default
 # Capital letters represent bold
-# Copy to ~/.bpython/foo.theme and set "color_scheme = foo" in
-# ~/.bpython/config
+# Copy to $XDG_CONFIG_HOME/bpython/foo.theme and set "color_scheme = foo" in
+# $XDG_CONFIG_HOME/bpython/config ($XDG_CONFIG_HOME defaults to ~/.config)
 
 [syntax]
 keyword = M
 # This is a standard python config file
 # Valid values can be True, False, integer numbers, strings
-# By default bpython will look for ~/.config/bpython/config or you
-# can specify a file with the --config option on the command line
+# By default bpython will look for $XDG_CONFIG_HOME/bpython/config
+# ($XDG_CONFIG_HOME defaults to ~/.config) or you can specify a file with the
+# --config option on the command line
 
 # General section tag
 [general]
 # Soft tab size (default: 4, see pep-8):
 tab_length = 4
 
-# Color schemes should be put in ~/.bpython/
-# e.g. to use the theme ~/.bpython/foo.theme set color_scheme = foo
-# Leave blank or set to "default" to use the default theme
+# Color schemes should be put in $XDG_CONFIG_HOME/bpython/ e.g. to use the theme
+# $XDG_CONFIG_HOME/bpython/foo.theme set color_scheme = foo. Leave blank or set
+# to "default" to use the default theme
 color_scheme = default
 
 [keyboard]
 # which stands for:
 #   blacK, Red, Green, Yellow, Blue, Magenta, Cyan, White, Default
 # Capital letters represent bold
-# Copy to ~/.bpython/foo.theme and set "color_scheme = foo" in ~/.bython/config
+# Copy to $XDG_CONFIG_HOME/bpython/foo.theme and set "color_scheme = foo" in
+# $XDG_CONFIG_HOME/bpython/config ($XDG_CONFIG_HOME defaults to ~/.config)
 
 [syntax]
 keyword = y
 
 try:
     from setuptools import setup
+    from setuptools.command.install import install as _install
     using_setuptools = True
 except ImportError:
     from distutils.core import setup
+    from distutils.command.install import install as _install
     using_setuptools = False
 
 try:
     using_translations = False
 
 try:
+    import sphinx
     from sphinx.setup_command import BuildDoc
-    using_sphinx = True
+    if sphinx.__version__ == '1.1.2':
+        # Sphinx 1.1.2 is buggy and building bpython with that version fails.
+        # See #241.
+        using_sphinx = False
+    else:
+        using_sphinx = True
 except ImportError:
     using_sphinx = False
 
+class install(_install):
+    """Force install to run build target."""
 
-cmdclass = dict(build_py=build_py, build=build)
+    def run(self):
+        self.run_command('build')
+        _install.run(self)
+
+cmdclass = dict(build_py=build_py, build=build, install=install)
 translations_dir = os.path.join(package_dir, 'translations')
 
 # localization options