Skip to content

Commit 318e93d

Browse files
committed
Merge in main branch to stay up to date
2 parents a9826fd + ec72900 commit 318e93d

File tree

10 files changed

+832
-42
lines changed

10 files changed

+832
-42
lines changed

AUTHORS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ Other contributors are (in alphabetical order):
88
* Federico Ceratto <federico dot ceratto at gmail dot com>
99
* Pavel Panchekha <pavpanchekha at gmail dot com>
1010
* Simon de Vlieger <simon at ikanobori dot jp>
11-
11+
* Marien Zwart <marien dot zwart at gmail dot com>
1212

1313
Many thanks for all contributions!

ROADMAP

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,7 @@ bpython.gtk_
2222

2323
common
2424
- test suite
25+
26+
v1.0
27+
----
28+
- Ditch curses for an urwid/twisted loop

bpython/args.py

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,20 @@
77
import sys
88
import code
99
from optparse import OptionParser, OptionGroup
10-
from itertools import takewhile
1110

1211
from bpython import __version__
1312
from bpython.config import loadini, Struct, migrate_rc
1413

14+
15+
class OptionParserFailed(ValueError):
16+
"""Raised by the RaisingOptionParser for a bogus commandline."""
17+
18+
19+
class RaisingOptionParser(OptionParser):
20+
def error(self, msg):
21+
raise OptionParserFailed()
22+
23+
1524
def parse(args, extras=None):
1625
"""Receive an argument list - if None, use sys.argv - parse all args and
1726
take appropriate action. Also receive optional extra options: this should
@@ -39,10 +48,16 @@ def parse(args, extras=None):
3948
if args is None:
4049
args = sys.argv[1:]
4150

42-
parser = OptionParser(usage='Usage: %prog [options] [file [args]]\n'
43-
'NOTE: If bpython sees an argument it does '
44-
'not know, execution falls back to the '
45-
'regular Python interpreter.')
51+
parser = RaisingOptionParser(
52+
usage='Usage: %prog [options] [file [args]]\n'
53+
'NOTE: If bpython sees an argument it does '
54+
'not know, execution falls back to the '
55+
'regular Python interpreter.')
56+
# This is not sufficient if bpython gains its own -m support
57+
# (instead of falling back to Python itself for that).
58+
# That's probably fixable though, for example by having that
59+
# option swallow all remaining arguments in a callback.
60+
parser.disable_interspersed_args()
4661
parser.add_option('--config', '-c', default='~/.bpython/config',
4762
help='use CONFIG instead of default config file')
4863
parser.add_option('--interactive', '-i', action='store_true',
@@ -59,17 +74,11 @@ def parse(args, extras=None):
5974
extras_group.add_option(option)
6075
parser.add_option_group(extras_group)
6176

62-
all_args = set(parser._short_opt.keys() + parser._long_opt.keys())
63-
if args and not all_args.intersection(arg.split('=')[0] for arg in args):
77+
try:
78+
options, args = parser.parse_args(args)
79+
except OptionParserFailed:
6480
# Just let Python handle this
6581
os.execv(sys.executable, [sys.executable] + args)
66-
else:
67-
# Split args in bpython args and args for the executed file
68-
real_args = list(takewhile(lambda arg: arg.split('=')[0] in all_args,
69-
args))
70-
exec_args = args[len(real_args):]
71-
72-
options, args = parser.parse_args(real_args)
7382

7483
if options.version:
7584
print 'bpython version', __version__,
@@ -91,7 +100,7 @@ def parse(args, extras=None):
91100

92101
loadini(config, options.config)
93102

94-
return config, options, exec_args
103+
return config, options, args
95104

96105
def exec_code(interpreter, args):
97106
"""

bpython/cli.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ def make_colors(config):
240240
class CLIRepl(Repl):
241241

242242
def __init__(self, scr, interp, statusbar, config, idle=None):
243-
Repl.__init__(self, interp, config, idle)
243+
Repl.__init__(self, interp, config)
244244
interp.writetb = self.writetb
245245
self.scr = scr
246246
self.list_win = newwin(get_colpair(config, 'background'), 1, 1, 1, 1)
@@ -253,6 +253,7 @@ def __init__(self, scr, interp, statusbar, config, idle=None):
253253
self.last_key_press = time.time()
254254
self.s = ''
255255
self.statusbar = statusbar
256+
self.formatter = BPythonFormatter(config.color_scheme)
256257

257258
def addstr(self, s):
258259
"""Add a string to the current input line and figure out
@@ -462,13 +463,6 @@ def echo(self, s, redraw=True):
462463
# Replace NUL bytes, as addstr raises an exception otherwise
463464
s = s.replace('\x00', '')
464465

465-
screen_height, screen_width = self.scr.getmaxyx()
466-
if self.iy >= (screen_height - 1):
467-
lines = (self.ix + len(s)) // screen_width
468-
if lines > 0:
469-
self.scr.scroll(lines)
470-
self.iy -= lines
471-
self.scr.move(self.iy, self.ix)
472466
self.scr.addstr(s, a)
473467

474468
if redraw and not self.evaluating:
@@ -865,8 +859,7 @@ def print_line(self, s, clr=False, newline=False):
865859
self.highlighted_paren = None
866860

867861
if self.config.syntax and (not self.paste_mode or newline):
868-
o = format(self.tokenize(s, newline),
869-
BPythonFormatter(self.config.color_scheme))
862+
o = format(self.tokenize(s, newline), self.formatter)
870863
else:
871864
o = s
872865

@@ -1622,6 +1615,7 @@ def main(args=None, locals_=None, banner=None):
16221615

16231616

16241617
if __name__ == '__main__':
1618+
from bpython.cli import main
16251619
main()
16261620

16271621
# vim: sw=4 ts=4 sts=4 ai et

bpython/formatter.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,14 @@ class BPythonFormatter(Formatter):
8383
See the Pygments source for more info; it's pretty
8484
straightforward."""
8585

86-
f_strings = {}
87-
8886
def __init__(self, color_scheme, **options):
89-
if not self.f_strings:
90-
for k, v in theme_map.iteritems():
91-
self.f_strings[k] = '\x01%s' % (color_scheme[v],)
92-
if k is Parenthesis:
93-
# FIXME: Find a way to make this the inverse of the current
94-
# background colour
95-
self.f_strings[k] += 'I'
87+
self.f_strings = {}
88+
for k, v in theme_map.iteritems():
89+
self.f_strings[k] = '\x01%s' % (color_scheme[v],)
90+
if k is Parenthesis:
91+
# FIXME: Find a way to make this the inverse of the current
92+
# background colour
93+
self.f_strings[k] += 'I'
9694
Formatter.__init__(self, **options)
9795

9896
def format(self, tokensource, outfile):

bpython/gtk_.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,4 +695,5 @@ def main(args=None):
695695

696696

697697
if __name__ == '__main__':
698+
from bpython.gtk_ import main
698699
main()

bpython/importcompletion.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ def find_modules(path):
7575
# Possibly a package
7676
if '.' in name:
7777
continue
78+
elif os.path.isdir(os.path.join(path, name)):
79+
# Unfortunately, CPython just crashes if there is a directory
80+
# which ends with a python extension, so work around.
81+
continue
7882
name = os.path.splitext(name)[0]
7983
try:
8084
fo, pathname, _ = imp.find_module(name, [path])
@@ -99,6 +103,8 @@ def find_all_modules(path=None):
99103
path = sys.path
100104

101105
for p in path:
106+
if not path:
107+
path = os.curdir
102108
for module in find_modules(p):
103109
modules.add(module)
104110
yield

bpython/inspection.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#
2323

2424
from __future__ import with_statement
25+
import collections
2526
import inspect
2627
import pydoc
2728
import re
@@ -31,6 +32,17 @@
3132
from pygments.lexers import PythonLexer
3233
from pygments.token import Token
3334

35+
try:
36+
collections.Callable
37+
has_collections_callable = True
38+
try:
39+
import types
40+
types.InstanceType
41+
has_instance_type = True
42+
except AttributeError:
43+
has_instance_type = False
44+
except AttributeError:
45+
has_collections_callable = False
3446

3547
py3 = sys.version_info[0] == 3
3648

@@ -223,3 +235,13 @@ def is_eval_safe_name(string):
223235
return all(part.isidentifier() for part in string.split('.'))
224236
else:
225237
return all(_name.match(part) for part in string.split('.'))
238+
239+
240+
def is_callable(obj):
241+
if has_instance_type and isinstance(obj, types.InstanceType):
242+
# Work around a Python bug, see issue 7624
243+
return callable(obj)
244+
elif has_collections_callable:
245+
return isinstance(obj, collections.Callable)
246+
else:
247+
return callable(obj)

bpython/repl.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -270,15 +270,13 @@ class Repl(object):
270270
XXX Subclasses should implement echo, current_line, cw
271271
"""
272272

273-
def __init__(self, interp, config, idle=None):
274-
"""Initialise the repl with, unfortunately, a curses screen passed to
275-
it. This needs to be split up so the curses crap isn't in here.
273+
def __init__(self, interp, config):
274+
"""Initialise the repl.
276275
277276
interp is a Python code.InteractiveInterpreter instance
278277
279-
The optional 'idle' parameter is a function that the repl call while
280-
it's blocking (waiting for keypresses). This, again, should be in a
281-
different class"""
278+
config is a populated bpython.config.Struct.
279+
"""
282280

283281
self.config = config
284282
self.cut_buffer = ''
@@ -365,7 +363,7 @@ def attr_lookup(self, obj, expr, attr):
365363
def _callable_postfix(self, value, word):
366364
"""rlcompleter's _callable_postfix done right."""
367365
with inspection.AttrCleaner(value):
368-
if hasattr(value, '__call__'):
366+
if inspection.is_callable(value):
369367
word += '('
370368
return word
371369

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy