From e3dfb4f28c1ee10e4603cc976946fd29e055fa16 Mon Sep 17 00:00:00 2001 From: Amjith Ramanujam Date: Thu, 12 Mar 2015 22:59:33 -0700 Subject: [PATCH 01/19] Add Ctrl-e to complete current suggestion. --- bpython/curtsiesfrontend/repl.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bpython/curtsiesfrontend/repl.py b/bpython/curtsiesfrontend/repl.py index cb913b76f..6f2055bf5 100644 --- a/bpython/curtsiesfrontend/repl.py +++ b/bpython/curtsiesfrontend/repl.py @@ -594,12 +594,11 @@ def process_key_event(self, e): if self.stdin.has_focus: return self.stdin.process_event(e) - if (e in ("", '') and + if (e in ("", '', '') and self.config.curtsies_right_arrow_completion and self.cursor_offset == len(self.current_line)): self.current_line += self.current_suggestion self.cursor_offset = len(self.current_line) - elif e in ("",) + key_dispatch[self.config.up_one_line_key]: self.up_one_line() elif e in ("",) + key_dispatch[self.config.down_one_line_key]: From 577b9c731d0ac559635fc2445a2ab3120b19d242 Mon Sep 17 00:00:00 2001 From: Thomas Ballinger Date: Fri, 13 Mar 2015 13:01:52 -0400 Subject: [PATCH 02/19] use configurable keys for right arrow completion --- bpython/curtsiesfrontend/repl.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/bpython/curtsiesfrontend/repl.py b/bpython/curtsiesfrontend/repl.py index 6f2055bf5..f4da90230 100644 --- a/bpython/curtsiesfrontend/repl.py +++ b/bpython/curtsiesfrontend/repl.py @@ -594,9 +594,12 @@ def process_key_event(self, e): if self.stdin.has_focus: return self.stdin.process_event(e) - if (e in ("", '', '') and - self.config.curtsies_right_arrow_completion and - self.cursor_offset == len(self.current_line)): + if (e in (key_dispatch[self.config.right_key] + + key_dispatch[self.config.end_of_line_key] + + ("",)) + and self.config.curtsies_right_arrow_completion + and self.cursor_offset == len(self.current_line)): + self.current_line += self.current_suggestion self.cursor_offset = len(self.current_line) elif e in ("",) + key_dispatch[self.config.up_one_line_key]: From e83fb4a04960a8b165f5cf3915f8f9492edefa0d Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Sun, 15 Mar 2015 18:39:54 +0100 Subject: [PATCH 03/19] Change default to None and set it to LOCK_EX in __init__ (fixes #509) Signed-off-by: Sebastian Ramacher --- bpython/filelock.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bpython/filelock.py b/bpython/filelock.py index 94cb16d3e..a2d14cbe9 100644 --- a/bpython/filelock.py +++ b/bpython/filelock.py @@ -36,7 +36,10 @@ class FileLock(object): On platforms without fcntl, all operations in this class are no-ops. """ - def __init__(self, fd, mode=fcntl.LOCK_EX): + def __init__(self, fd, mode=None): + if has_fcntl and mode is None: + mode = fcntl.LOCK_EX + self.fd = fd self.mode = mode From 4d266217264e7872d43c5538c34bfb02d93f2880 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Sun, 15 Mar 2015 23:53:13 +0100 Subject: [PATCH 04/19] Move attr_{matches,lookup} to AttrCompleter Signed-off-by: Sebastian Ramacher --- bpython/autocomplete.py | 100 ++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 51 deletions(-) diff --git a/bpython/autocomplete.py b/bpython/autocomplete.py index 6e3ddb900..9c3a481d2 100644 --- a/bpython/autocomplete.py +++ b/bpython/autocomplete.py @@ -199,6 +199,9 @@ def format(self, filename): return filename +attr_matches_re = LazyReCompile(r"(\w+(\.\w+)*)\.(\w*)") + + class AttrCompletion(BaseCompletionType): def matches(self, cursor_offset, line, **kwargs): @@ -222,7 +225,7 @@ def matches(self, cursor_offset, line, **kwargs): break methodtext = text[-i:] matches = set(''.join([text[:-i], m]) - for m in attr_matches(methodtext, locals_)) + for m in self.attr_matches(methodtext, locals_)) # TODO add open paren for methods via _callable_prefix (or decide not # to) unless the first character is a _ filter out all attributes @@ -238,6 +241,51 @@ def locate(self, current_offset, line): def format(self, word): return after_last_dot(word) + def attr_matches(self, text, namespace): + """Taken from rlcompleter.py and bent to my will. + """ + + # Gna, Py 2.6's rlcompleter searches for __call__ inside the + # instance instead of the type, so we monkeypatch to prevent + # side-effects (__getattr__/__getattribute__) + m = attr_matches_re.match(text) + if not m: + return [] + + expr, attr = m.group(1, 3) + if expr.isdigit(): + # Special case: float literal, using attrs here will result in + # a SyntaxError + return [] + try: + obj = safe_eval(expr, namespace) + except EvaluationError: + return [] + with inspection.AttrCleaner(obj): + matches = self.attr_lookup(obj, expr, attr) + return matches + + def attr_lookup(self, obj, expr, attr): + """Second half of original attr_matches method factored out so it can + be wrapped in a safe try/finally block in case anything bad happens to + restore the original __getattribute__ method.""" + words = dir(obj) + if hasattr(obj, '__class__'): + words.append('__class__') + words = words + rlcompleter.get_class_members(obj.__class__) + if not isinstance(obj.__class__, abc.ABCMeta): + try: + words.remove('__abstractmethods__') + except ValueError: + pass + + matches = [] + n = len(attr) + for word in words: + if method_match(word, n, attr) and word != "__builtins__": + matches.append("%s.%s" % (expr, word)) + return matches + class DictKeyCompletion(BaseCompletionType): @@ -498,56 +546,6 @@ def safe_eval(expr, namespace): raise EvaluationError -attr_matches_re = LazyReCompile(r"(\w+(\.\w+)*)\.(\w*)") - - -def attr_matches(text, namespace): - """Taken from rlcompleter.py and bent to my will. - """ - - # Gna, Py 2.6's rlcompleter searches for __call__ inside the - # instance instead of the type, so we monkeypatch to prevent - # side-effects (__getattr__/__getattribute__) - m = attr_matches_re.match(text) - if not m: - return [] - - expr, attr = m.group(1, 3) - if expr.isdigit(): - # Special case: float literal, using attrs here will result in - # a SyntaxError - return [] - try: - obj = safe_eval(expr, namespace) - except EvaluationError: - return [] - with inspection.AttrCleaner(obj): - matches = attr_lookup(obj, expr, attr) - return matches - - -def attr_lookup(obj, expr, attr): - """Second half of original attr_matches method factored out so it can - be wrapped in a safe try/finally block in case anything bad happens to - restore the original __getattribute__ method.""" - words = dir(obj) - if hasattr(obj, '__class__'): - words.append('__class__') - words = words + rlcompleter.get_class_members(obj.__class__) - if not isinstance(obj.__class__, abc.ABCMeta): - try: - words.remove('__abstractmethods__') - except ValueError: - pass - - matches = [] - n = len(attr) - for word in words: - if method_match(word, n, attr) and word != "__builtins__": - matches.append("%s.%s" % (expr, word)) - return matches - - def _callable_postfix(value, word): """rlcompleter's _callable_postfix done right.""" with inspection.AttrCleaner(value): From 5cf6f520256ebada88de43ec7bc56e78b21e1c54 Mon Sep 17 00:00:00 2001 From: llllllllll Date: Sun, 15 Mar 2015 19:42:27 -0400 Subject: [PATCH 05/19] Makes old style classes and instances show __dict__ in the autocomplete. --- bpython/autocomplete.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bpython/autocomplete.py b/bpython/autocomplete.py index 6e3ddb900..b2011674a 100644 --- a/bpython/autocomplete.py +++ b/bpython/autocomplete.py @@ -33,6 +33,7 @@ import re import rlcompleter import sys +from types import InstanceType, ClassType from six.moves import range, builtins from six import string_types, iteritems @@ -539,6 +540,9 @@ def attr_lookup(obj, expr, attr): words.remove('__abstractmethods__') except ValueError: pass + if isinstance(obj, (InstanceType, ClassType)): + # Account for the __dict__ in an old-style class. + words.append('__dict__') matches = [] n = len(attr) From cb908722ac73c1aac0873039921e149276faba32 Mon Sep 17 00:00:00 2001 From: llllllllll Date: Sun, 15 Mar 2015 19:43:09 -0400 Subject: [PATCH 06/19] Adds tests to validate that __dict__ is in the autocomplete of an old style class or instance. --- bpython/test/test_autocomplete.py | 33 +++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/bpython/test/test_autocomplete.py b/bpython/test/test_autocomplete.py index cad960e33..3b87ce720 100644 --- a/bpython/test/test_autocomplete.py +++ b/bpython/test/test_autocomplete.py @@ -215,13 +215,42 @@ def method(self, x): pass +class OldStyleFoo: + a = 10 + + def __init__(self): + self.b = 20 + + def method(self, x): + pass + + +skip_old_style = unittest.skipIf(py3, + 'In Python 3 there are no old style classes') + + class TestAttrCompletion(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.com = autocomplete.AttrCompletion() def test_att_matches_found_on_instance(self): - com = autocomplete.AttrCompletion() - self.assertSetEqual(com.matches(2, 'a.', locals_={'a': Foo()}), + self.assertSetEqual(self.com.matches(2, 'a.', locals_={'a': Foo()}), set(['a.method', 'a.a', 'a.b'])) + @skip_old_style + def test_att_matches_found_on_old_style_instance(self): + self.assertSetEqual(self.com.matches(2, 'a.', + locals_={'a': OldStyleFoo()}), + {'a.method', 'a.a', 'a.b'}) + self.assertIn(u'a.__dict__', + self.com.matches(3, 'a._', locals_={'a': OldStyleFoo()})) + + @skip_old_style + def test_att_matches_found_on_old_style_class_object(self): + self.assertIn(u'A.__dict__', + self.com.matches(3, 'A._', locals_={'A': OldStyleFoo})) + class TestMagicMethodCompletion(unittest.TestCase): From a82b4b5dba14a3a497560c583410f058a93a779f Mon Sep 17 00:00:00 2001 From: llllllllll Date: Sun, 15 Mar 2015 19:58:42 -0400 Subject: [PATCH 07/19] Makes the old-style class autocomplete work in 2.6 and 3.x --- bpython/autocomplete.py | 6 ++++-- bpython/test/test_autocomplete.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/bpython/autocomplete.py b/bpython/autocomplete.py index b2011674a..3b64d0b2f 100644 --- a/bpython/autocomplete.py +++ b/bpython/autocomplete.py @@ -33,7 +33,6 @@ import re import rlcompleter import sys -from types import InstanceType, ClassType from six.moves import range, builtins from six import string_types, iteritems @@ -43,6 +42,9 @@ from bpython._py3compat import py3, try_decode from bpython.lazyre import LazyReCompile +if not py3: + from types import InstanceType, ClassType + # Autocomplete modes SIMPLE = 'simple' @@ -540,7 +542,7 @@ def attr_lookup(obj, expr, attr): words.remove('__abstractmethods__') except ValueError: pass - if isinstance(obj, (InstanceType, ClassType)): + if not py3 and isinstance(obj, (InstanceType, ClassType)): # Account for the __dict__ in an old-style class. words.append('__dict__') diff --git a/bpython/test/test_autocomplete.py b/bpython/test/test_autocomplete.py index 3b87ce720..a6f2f153a 100644 --- a/bpython/test/test_autocomplete.py +++ b/bpython/test/test_autocomplete.py @@ -242,7 +242,7 @@ def test_att_matches_found_on_instance(self): def test_att_matches_found_on_old_style_instance(self): self.assertSetEqual(self.com.matches(2, 'a.', locals_={'a': OldStyleFoo()}), - {'a.method', 'a.a', 'a.b'}) + set(['a.method', 'a.a', 'a.b'])) self.assertIn(u'a.__dict__', self.com.matches(3, 'a._', locals_={'a': OldStyleFoo()})) From 2cfa83b1fb132b2f03e545fd896ff32474f4a5a0 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Mon, 16 Mar 2015 03:58:19 +0100 Subject: [PATCH 08/19] Re-introduce autocompletion modes Signed-off-by: Sebastian Ramacher --- bpython/autocomplete.py | 73 +++++++++++++++++++++++++++-------------- bpython/repl.py | 6 +++- 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/bpython/autocomplete.py b/bpython/autocomplete.py index 9c3a481d2..b1d0969ed 100644 --- a/bpython/autocomplete.py +++ b/bpython/autocomplete.py @@ -68,11 +68,32 @@ def after_last_dot(name): return name.rstrip('.').rsplit('.')[-1] +def method_match_simple(word, size, text): + return word[:size] == text + + +def method_match_substring(word, size, text): + return text in word + + +def method_match_fuzzy(word, size, text): + s = r'.*%s.*' % '.*'.join(list(text)) + return re.search(s, word) + + +MODES_MAP = { + SIMPLE: method_match_simple, + SUBSTRING: method_match_substring, + FUZZY: method_match_fuzzy +} + + class BaseCompletionType(object): """Describes different completion types""" - def __init__(self, shown_before_tab=True): + def __init__(self, shown_before_tab=True, mode=SIMPLE): self._shown_before_tab = shown_before_tab + self.method_match = MODES_MAP[mode] def matches(self, cursor_offset, line, **kwargs): """Returns a list of possible matches given a line and cursor, or None @@ -112,17 +133,20 @@ def shown_before_tab(self): once that has happened.""" return self._shown_before_tab + def method_match(self, word, size, text): + return word[:size] == text + class CumulativeCompleter(BaseCompletionType): """Returns combined matches from several completers""" - def __init__(self, completers): + def __init__(self, completers, mode=SIMPLE): if not completers: raise ValueError( "CumulativeCompleter requires at least one completer") self._completers = completers - super(CumulativeCompleter, self).__init__(True) + super(CumulativeCompleter, self).__init__(True, mode) def locate(self, current_offset, line): return self._completers[0].locate(current_offset, line) @@ -158,8 +182,8 @@ def format(self, word): class FilenameCompletion(BaseCompletionType): - def __init__(self): - super(FilenameCompletion, self).__init__(False) + def __init__(self, mode=SIMPLE): + super(FilenameCompletion, self).__init__(False, mode) if sys.version_info[:2] >= (3, 4): def safe_glob(self, pathname): @@ -282,7 +306,7 @@ def attr_lookup(self, obj, expr, attr): matches = [] n = len(attr) for word in words: - if method_match(word, n, attr) and word != "__builtins__": + if self.method_match(word, n, attr) and word != "__builtins__": matches.append("%s.%s" % (expr, word)) return matches @@ -354,11 +378,11 @@ def matches(self, cursor_offset, line, **kwargs): matches = set() n = len(text) for word in KEYWORDS: - if method_match(word, n, text): + if self.method_match(word, n, text): matches.add(word) for nspace in (builtins.__dict__, locals_): for word, val in iteritems(nspace): - if method_match(word, n, text) and word != "__builtins__": + if self.method_match(word, n, text) and word != "__builtins__": word = try_decode(word, 'ascii') # if identifier isn't ascii, don't complete (syntax error) if word is None: @@ -508,28 +532,31 @@ def get_completer(completers, cursor_offset, line, **kwargs): """ for completer in completers: - matches = completer.matches( - cursor_offset, line, **kwargs) + matches = completer.matches(cursor_offset, line, **kwargs) if matches is not None: return sorted(matches), (completer if matches else None) return [], None -BPYTHON_COMPLETER = ( - DictKeyCompletion(), - StringLiteralAttrCompletion(), - ImportCompletion(), - FilenameCompletion(), - MagicMethodCompletion(), - MultilineJediCompletion(), - GlobalCompletion(), - CumulativeCompleter((AttrCompletion(), ParameterNameCompletion())) -) +def get_default_completer(mode=SIMPLE): + return ( + DictKeyCompletion(mode=mode), + StringLiteralAttrCompletion(mode=mode), + ImportCompletion(mode=mode), + FilenameCompletion(mode=mode), + MagicMethodCompletion(mode=mode), + MultilineJediCompletion(mode=mode), + GlobalCompletion(mode=mode), + CumulativeCompleter((AttrCompletion(mode=mode), + ParameterNameCompletion(mode=mode)), + mode=mode) + ) def get_completer_bpython(cursor_offset, line, **kwargs): """""" - return get_completer(BPYTHON_COMPLETER, cursor_offset, line, **kwargs) + return get_completer(get_default_completer(), + cursor_offset, line, **kwargs) class EvaluationError(Exception): @@ -552,7 +579,3 @@ def _callable_postfix(value, word): if inspection.is_callable(value): word += '(' return word - - -def method_match(word, size, text): - return word[:size] == text diff --git a/bpython/repl.py b/bpython/repl.py index cb1a61fec..3a55c4e2c 100644 --- a/bpython/repl.py +++ b/bpython/repl.py @@ -384,6 +384,9 @@ def __init__(self, interp, config): except EnvironmentError: pass + self.completers = autocomplete.get_default_completer( + config.autocomplete_mode) + @property def ps1(self): try: @@ -595,7 +598,8 @@ def complete(self, tab=False): self.set_docstring() - matches, completer = autocomplete.get_completer_bpython( + matches, completer = autocomplete.get_completer( + self.completers, cursor_offset=self.cursor_offset, line=self.current_line, locals_=self.interp.locals, From c830c7502c34b5e9f568df10c501ecd02f3d6fb4 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Mon, 16 Mar 2015 03:58:53 +0100 Subject: [PATCH 09/19] Update tests Signed-off-by: Sebastian Ramacher --- bpython/test/test_curtsies_repl.py | 6 +++--- bpython/test/test_repl.py | 20 ++++++++------------ 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/bpython/test/test_curtsies_repl.py b/bpython/test/test_curtsies_repl.py index 36b3546ef..fe2363914 100644 --- a/bpython/test/test_curtsies_repl.py +++ b/bpython/test/test_curtsies_repl.py @@ -179,7 +179,7 @@ def setUp(self): def test_list_win_visible_match_selected_on_tab_multiple_options(self): self.repl._current_line = " './'" self.repl._cursor_offset = 2 - with mock.patch('bpython.autocomplete.get_completer_bpython') as m: + with mock.patch('bpython.autocomplete.get_completer') as m: m.return_value = (['./abc', './abcd', './bcd'], autocomplete.FilenameCompletion()) self.repl.update_completion() @@ -191,7 +191,7 @@ def test_list_win_visible_match_selected_on_tab_multiple_options(self): def test_list_win_not_visible_and_cseq_if_cseq(self): self.repl._current_line = " './a'" self.repl._cursor_offset = 5 - with mock.patch('bpython.autocomplete.get_completer_bpython') as m: + with mock.patch('bpython.autocomplete.get_completer') as m: m.return_value = (['./abcd', './abce'], autocomplete.FilenameCompletion()) self.repl.update_completion() @@ -204,7 +204,7 @@ def test_list_win_not_visible_and_cseq_if_cseq(self): def test_list_win_not_visible_and_match_selected_if_one_option(self): self.repl._current_line = " './a'" self.repl._cursor_offset = 5 - with mock.patch('bpython.autocomplete.get_completer_bpython') as m: + with mock.patch('bpython.autocomplete.get_completer') as m: m.return_value = (['./abcd'], autocomplete.FilenameCompletion()) self.repl.update_completion() self.assertEqual(self.repl.list_win_visible, False) diff --git a/bpython/test/test_repl.py b/bpython/test/test_repl.py index f4f8e6e7d..b2a55f1cc 100644 --- a/bpython/test/test_repl.py +++ b/bpython/test/test_repl.py @@ -316,24 +316,22 @@ def test_simple_global_complete(self): ['def', 'del', 'delattr(', 'dict(', 'dir(', 'divmod(']) - @unittest.skip("disabled while non-simple completion is disabled") def test_substring_global_complete(self): self.repl = FakeRepl({'autocomplete_mode': autocomplete.SUBSTRING}) self.set_input_line("time") self.assertTrue(self.repl.complete()) - self.assertTrue(hasattr(self.repl.completer, 'matches')) - self.assertEqual(self.repl.completer.matches, + self.assertTrue(hasattr(self.repl.matches_iter, 'matches')) + self.assertEqual(self.repl.matches_iter.matches, ['RuntimeError(', 'RuntimeWarning(']) - @unittest.skip("disabled while non-simple completion is disabled") def test_fuzzy_global_complete(self): self.repl = FakeRepl({'autocomplete_mode': autocomplete.FUZZY}) self.set_input_line("doc") self.assertTrue(self.repl.complete()) - self.assertTrue(hasattr(self.repl.completer, 'matches')) - self.assertEqual(self.repl.completer.matches, + self.assertTrue(hasattr(self.repl.matches_iter, 'matches')) + self.assertEqual(self.repl.matches_iter.matches, ['UnboundLocalError(', '__doc__']) # 2. Attribute tests @@ -349,7 +347,6 @@ def test_simple_attribute_complete(self): self.assertTrue(hasattr(self.repl.matches_iter, 'matches')) self.assertEqual(self.repl.matches_iter.matches, ['Foo.bar']) - @unittest.skip("disabled while non-simple completion is disabled") def test_substring_attribute_complete(self): self.repl = FakeRepl({'autocomplete_mode': autocomplete.SUBSTRING}) self.set_input_line("Foo.az") @@ -359,10 +356,9 @@ def test_substring_attribute_complete(self): self.repl.push(line) self.assertTrue(self.repl.complete()) - self.assertTrue(hasattr(self.repl.completer, 'matches')) - self.assertEqual(self.repl.completer.matches, ['Foo.baz']) + self.assertTrue(hasattr(self.repl.matches_iter, 'matches')) + self.assertEqual(self.repl.matches_iter.matches, ['Foo.baz']) - @unittest.skip("disabled while non-simple completion is disabled") def test_fuzzy_attribute_complete(self): self.repl = FakeRepl({'autocomplete_mode': autocomplete.FUZZY}) self.set_input_line("Foo.br") @@ -372,8 +368,8 @@ def test_fuzzy_attribute_complete(self): self.repl.push(line) self.assertTrue(self.repl.complete()) - self.assertTrue(hasattr(self.repl.completer, 'matches')) - self.assertEqual(self.repl.completer.matches, ['Foo.bar']) + self.assertTrue(hasattr(self.repl.matches_iter, 'matches')) + self.assertEqual(self.repl.matches_iter.matches, ['Foo.bar']) # 3. Edge Cases def test_updating_namespace_complete(self): From 27b9493e634bf67d9586dbcad7ab9c636bb373bf Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Mon, 16 Mar 2015 04:28:15 +0100 Subject: [PATCH 10/19] Fix fuzzy completion test Signed-off-by: Sebastian Ramacher --- bpython/test/test_repl.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bpython/test/test_repl.py b/bpython/test/test_repl.py index b2a55f1cc..7e0e7aaa8 100644 --- a/bpython/test/test_repl.py +++ b/bpython/test/test_repl.py @@ -332,7 +332,8 @@ def test_fuzzy_global_complete(self): self.assertTrue(self.repl.complete()) self.assertTrue(hasattr(self.repl.matches_iter, 'matches')) self.assertEqual(self.repl.matches_iter.matches, - ['UnboundLocalError(', '__doc__']) + ['UnboundLocalError(', '__doc__'] if not py3 else + ['ChildProcessError(', 'UnboundLocalError(', '__doc__']) # 2. Attribute tests def test_simple_attribute_complete(self): From ac630cc4dd630b7cb0e98eba8113b89271714cce Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Tue, 24 Mar 2015 00:19:14 +0100 Subject: [PATCH 11/19] Move pasting logic out of Repl Signed-off-by: Sebastian Ramacher --- bpython/paste.py | 112 +++++++++++++++++++++++++++++++++++++++++++++++ bpython/repl.py | 94 +++++++-------------------------------- 2 files changed, 127 insertions(+), 79 deletions(-) create mode 100644 bpython/paste.py diff --git a/bpython/paste.py b/bpython/paste.py new file mode 100644 index 000000000..237807287 --- /dev/null +++ b/bpython/paste.py @@ -0,0 +1,112 @@ +# encoding: utf-8 + +# The MIT License +# +# Copyright (c) 2014-2015 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. + +from locale import getpreferredencoding +from six.moves.urllib_parse import quote as urlquote, urljoin, urlparse +from string import Template +import errno +import requests +import subprocess +import unicodedata + +from bpython.translations import _ + + +class PasteFailed(Exception): + pass + + +class PastePinnwand(object): + def __init__(self, url, expiry, show_url, removal_url): + self.url = url + self.expiry = expiry + self.show_url = show_url + self.removal_url = removal_url + + def paste(self, s): + """Upload to pastebin via json interface.""" + + url = urljoin(self.url, '/json/new') + payload = { + 'code': s, + 'lexer': 'pycon', + 'expiry': self.expiry + } + + try: + response = requests.post(url, data=payload, verify=True) + response.raise_for_status() + except requests.exceptions.RequestException as exc: + raise PasteFailed(exc.message) + + data = response.json() + + paste_url_template = Template(self.show_url) + paste_id = urlquote(data['paste_id']) + paste_url = paste_url_template.safe_substitute(paste_id=paste_id) + + removal_url_template = Template(self.removal_url) + removal_id = urlquote(data['removal_id']) + removal_url = removal_url_template.safe_substitute( + removal_id=removal_id) + + return (paste_url, removal_url) + + +class PasteHelper(object): + def __init__(self, executable): + self.executable = executable + + 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, diff --git a/bpython/repl.py b/bpython/repl.py index 3a55c4e2c..f46186238 100644 --- a/bpython/repl.py +++ b/bpython/repl.py @@ -24,13 +24,11 @@ # THE SOFTWARE. import code -import errno import inspect import io import os import pkgutil import pydoc -import requests import shlex import subprocess import sys @@ -38,12 +36,9 @@ import textwrap import time import traceback -import unicodedata from itertools import takewhile from locale import getpreferredencoding -from string import Template from six import itervalues -from six.moves.urllib_parse import quote as urlquote, urljoin, urlparse from pygments.token import Token @@ -53,6 +48,7 @@ from bpython.clipboard import get_clipboard, CopyFailed from bpython.formatter import Parenthesis from bpython.history import History +from bpython.paste import PasteHelper, PastePinnwand, PasteFailed from bpython.translations import _, ngettext @@ -386,6 +382,13 @@ def __init__(self, interp, config): self.completers = autocomplete.get_default_completer( config.autocomplete_mode) + if self.config.pastebin_helper: + self.paster = PasteHelper(self.config.pastebin_helper) + else: + self.paster = PastePinnwand(self.config.pastebin_url, + self.config.pastebin_expiry, + self.config.pastebin_show_url, + self.config.pastebin_removal_url) @property def ps1(self): @@ -761,91 +764,24 @@ def do_pastebin(self, s): self.prev_removal_url), 10) return self.prev_pastebin_url - if self.config.pastebin_helper: - return self.do_pastebin_helper(s) - else: - return self.do_pastebin_json(s) - - 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') % (exc, )) + 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 - 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.prev_removal_url = removal_url - self.interact.notify(_('Pastebin URL: %s - Removal URL: %s') % - (paste_url, removal_url), 10) - - return paste_url - 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 + if removal_url is not None: + self.interact.notify(_('Pastebin URL: %s - Removal URL: %s') % + (paste_url, removal_url), 10) 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.interact.notify(_('Pastebin URL: %s') % (paste_url, ), 10) - self.prev_pastebin_content = s - self.interact.notify(_('Pastebin URL: %s') % (paste_url, ), 10) return paste_url def push(self, s, insert_into_history=True): From 5cdfa51abef618086014417de24df116acfb9eef Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Tue, 24 Mar 2015 00:31:12 +0100 Subject: [PATCH 12/19] Update translations Signed-off-by: Sebastian Ramacher --- bpython/translations/bpython.pot | 122 +++++++------- .../translations/de/LC_MESSAGES/bpython.po | 142 ++++++++-------- .../translations/es_ES/LC_MESSAGES/bpython.po | 120 ++++++------- .../translations/fr_FR/LC_MESSAGES/bpython.po | 157 +++++++++--------- .../translations/it_IT/LC_MESSAGES/bpython.po | 120 ++++++------- .../translations/nl_NL/LC_MESSAGES/bpython.po | 120 ++++++------- 6 files changed, 389 insertions(+), 392 deletions(-) diff --git a/bpython/translations/bpython.pot b/bpython/translations/bpython.pot index 00b44b691..074e4a475 100644 --- a/bpython/translations/bpython.pot +++ b/bpython/translations/bpython.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: bpython 0.13-641\n" +"Project-Id-Version: bpython 0.15.dev98\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2015-02-16 21:56+0100\n" +"POT-Creation-Date: 2015-03-24 00:25+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -68,159 +68,159 @@ msgstr "" msgid "Show Source" msgstr "" -#: bpython/curtsies.py:36 +#: bpython/curtsies.py:37 msgid "log debug messages to bpython.log" msgstr "" -#: bpython/curtsies.py:38 +#: bpython/curtsies.py:39 msgid "start by pasting lines of a file into session" msgstr "" -#: bpython/history.py:223 +#: bpython/history.py:228 #, python-format msgid "Error occurred while writing to file %s (%s)" msgstr "" -#: bpython/repl.py:537 +#: bpython/paste.py:94 +msgid "Helper program not found." +msgstr "" + +#: bpython/paste.py:96 +msgid "Helper program could not be run." +msgstr "" + +#: bpython/paste.py:100 +#, python-format +msgid "Helper program returned non-zero exit status %d." +msgstr "" + +#: bpython/paste.py:103 +msgid "No output from helper program." +msgstr "" + +#: bpython/paste.py:109 +msgid "Failed to recognize the helper program's output as an URL." +msgstr "" + +#: bpython/repl.py:549 msgid "Nothing to get source of" msgstr "" -#: bpython/repl.py:542 +#: bpython/repl.py:554 #, python-format msgid "Cannot get source: %s" msgstr "" -#: bpython/repl.py:547 +#: bpython/repl.py:559 #, python-format msgid "Cannot access source of %r" msgstr "" -#: bpython/repl.py:549 +#: bpython/repl.py:561 #, python-format msgid "No source code found for %s" msgstr "" -#: bpython/repl.py:681 +#: bpython/repl.py:694 msgid "Save to file (Esc to cancel): " msgstr "" -#: bpython/repl.py:683 bpython/repl.py:686 bpython/repl.py:705 +#: bpython/repl.py:696 bpython/repl.py:699 bpython/repl.py:718 msgid "Save cancelled." msgstr "" -#: bpython/repl.py:696 +#: bpython/repl.py:709 #, python-format msgid "%s already exists. Do you want to (c)ancel, (o)verwrite or (a)ppend? " msgstr "" -#: bpython/repl.py:700 +#: bpython/repl.py:713 msgid "overwrite" msgstr "" -#: bpython/repl.py:702 +#: bpython/repl.py:715 msgid "append" msgstr "" -#: bpython/repl.py:714 bpython/repl.py:1075 +#: bpython/repl.py:727 bpython/repl.py:1022 #, python-format msgid "Error writing file '%s': %s" msgstr "" -#: bpython/repl.py:717 +#: bpython/repl.py:729 #, python-format msgid "Saved to %s." msgstr "" -#: bpython/repl.py:723 +#: bpython/repl.py:735 msgid "No clipboard available." msgstr "" -#: bpython/repl.py:730 +#: bpython/repl.py:742 msgid "Could not copy to clipboard." msgstr "" -#: bpython/repl.py:732 +#: bpython/repl.py:744 msgid "Copied content to clipboard." msgstr "" -#: bpython/repl.py:741 +#: bpython/repl.py:753 msgid "Pastebin buffer? (y/N) " msgstr "" -#: bpython/repl.py:742 +#: bpython/repl.py:754 msgid "Pastebin aborted." msgstr "" -#: bpython/repl.py:749 +#: bpython/repl.py:761 #, python-format msgid "Duplicate pastebin. Previous URL: %s. Removal URL: %s" msgstr "" -#: bpython/repl.py:770 bpython/repl.py:799 +#: bpython/repl.py:768 msgid "Posting data to pastebin..." msgstr "" -#: bpython/repl.py:775 +#: bpython/repl.py:772 #, python-format msgid "Upload failed: %s" msgstr "" -#: bpython/repl.py:792 +#: bpython/repl.py:780 #, python-format msgid "Pastebin URL: %s - Removal URL: %s" msgstr "" -#: bpython/repl.py:811 -msgid "Upload failed: Helper program not found." -msgstr "" - -#: bpython/repl.py:814 -msgid "Upload failed: Helper program could not be run." -msgstr "" - -#: bpython/repl.py:821 -#, python-format -msgid "Upload failed: Helper program returned non-zero exit status %d." -msgstr "" - -#: bpython/repl.py:825 -msgid "Upload failed: No output from helper program." -msgstr "" - -#: bpython/repl.py:833 -msgid "Upload failed: Failed to recognize the helper program's output as an URL." -msgstr "" - -#: bpython/repl.py:839 +#: bpython/repl.py:783 #, python-format msgid "Pastebin URL: %s" msgstr "" -#: bpython/repl.py:872 +#: bpython/repl.py:817 #, python-format msgid "Undo how many lines? (Undo will take up to ~%.1f seconds) [1]" msgstr "" -#: bpython/repl.py:879 bpython/repl.py:883 +#: bpython/repl.py:824 bpython/repl.py:828 msgid "Undo canceled" msgstr "" -#: bpython/repl.py:886 +#: bpython/repl.py:831 #, python-format msgid "Undoing %d line... (est. %.1f seconds)" msgid_plural "Undoing %d lines... (est. %.1f seconds)" msgstr[0] "" msgstr[1] "" -#: bpython/repl.py:1062 +#: bpython/repl.py:1007 msgid "Config file does not exist - create new from default? (y/N)" msgstr "" -#: bpython/repl.py:1082 +#: bpython/repl.py:1029 msgid "bpython config file edited. Restart bpython for changes to take effect." msgstr "" -#: bpython/repl.py:1085 +#: bpython/repl.py:1032 msgid "Error editing config file." msgstr "" @@ -251,39 +251,39 @@ msgstr "" msgid "Port to run an eval server on (forces Twisted)." msgstr "" -#: bpython/curtsiesfrontend/repl.py:286 +#: bpython/curtsiesfrontend/repl.py:344 msgid "Welcome to bpython!" msgstr "" -#: bpython/curtsiesfrontend/repl.py:287 +#: bpython/curtsiesfrontend/repl.py:345 #, python-format msgid "Press <%s> for help." msgstr "" -#: bpython/curtsiesfrontend/repl.py:526 +#: bpython/curtsiesfrontend/repl.py:565 #, python-format msgid "Executing PYTHONSTARTUP failed: %s" msgstr "" -#: bpython/curtsiesfrontend/repl.py:543 +#: bpython/curtsiesfrontend/repl.py:582 #, python-format msgid "Reloaded at %s because %s modified." msgstr "" -#: bpython/curtsiesfrontend/repl.py:814 +#: bpython/curtsiesfrontend/repl.py:855 #, python-format msgid "Reloaded at %s by user." msgstr "" -#: bpython/curtsiesfrontend/repl.py:820 +#: bpython/curtsiesfrontend/repl.py:861 msgid "Auto-reloading deactivated." msgstr "" -#: bpython/curtsiesfrontend/repl.py:825 +#: bpython/curtsiesfrontend/repl.py:866 msgid "Auto-reloading active, watching for file changes..." msgstr "" -#: bpython/curtsiesfrontend/repl.py:830 +#: bpython/curtsiesfrontend/repl.py:871 msgid "Auto-reloading not available because watchdog not installed." msgstr "" diff --git a/bpython/translations/de/LC_MESSAGES/bpython.po b/bpython/translations/de/LC_MESSAGES/bpython.po index 5afe91d62..094fab1e5 100644 --- a/bpython/translations/de/LC_MESSAGES/bpython.po +++ b/bpython/translations/de/LC_MESSAGES/bpython.po @@ -7,21 +7,23 @@ msgid "" msgstr "" "Project-Id-Version: bpython mercurial\n" "Report-Msgid-Bugs-To: http://github.com/bpython/bpython/issues\n" -"POT-Creation-Date: 2015-02-16 21:56+0100\n" -"PO-Revision-Date: 2015-02-05 14:54+0100\n" +"POT-Creation-Date: 2015-03-24 00:25+0100\n" +"PO-Revision-Date: 2015-03-24 00:27+0100\n" "Last-Translator: Sebastian Ramacher \n" "Language-Team: de \n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" +"Language: de\n" +"X-Generator: Poedit 1.6.10\n" #: bpython/args.py:59 msgid "" "Usage: %prog [options] [file [args]]\n" -"NOTE: If bpython sees an argument it does not know, execution falls back " -"to the regular Python interpreter." +"NOTE: If bpython sees an argument it does not know, execution falls back to " +"the regular Python interpreter." msgstr "" #: bpython/args.py:69 @@ -68,167 +70,164 @@ msgstr "" msgid "Show Source" msgstr "Quellcode anzeigen" -#: bpython/curtsies.py:36 +#: bpython/curtsies.py:37 msgid "log debug messages to bpython.log" msgstr "" -#: bpython/curtsies.py:38 +#: bpython/curtsies.py:39 msgid "start by pasting lines of a file into session" msgstr "" -#: bpython/history.py:223 +#: bpython/history.py:228 #, python-format msgid "Error occurred while writing to file %s (%s)" msgstr "Fehler beim Schreiben in Datei %s aufgetreten (%s)" -#: bpython/repl.py:537 +#: bpython/paste.py:94 +msgid "Helper program not found." +msgstr "Hilfsprogramm konnte nicht gefunden werden." + +#: bpython/paste.py:96 +msgid "Helper program could not be run." +msgstr "Hilfsprogramm konnte nicht ausgeführt werden." + +#: bpython/paste.py:100 +#, python-format +msgid "Helper program returned non-zero exit status %d." +msgstr "Hilfsprogramm beendete mit Status %d." + +#: bpython/paste.py:103 +msgid "No output from helper program." +msgstr "Keine Ausgabe von Hilfsprogramm vorhanden." + +#: bpython/paste.py:109 +msgid "Failed to recognize the helper program's output as an URL." +msgstr "Konnte Ausgabe von Hilfsprogramm nicht verarbeiten." + +#: bpython/repl.py:549 msgid "Nothing to get source of" msgstr "" -#: bpython/repl.py:542 +#: bpython/repl.py:554 #, python-format msgid "Cannot get source: %s" msgstr "Kann Quellcode nicht finden: %s" -#: bpython/repl.py:547 +#: bpython/repl.py:559 #, python-format msgid "Cannot access source of %r" msgstr "Kann auf Quellcode nicht zugreifen: %r" -#: bpython/repl.py:549 +#: bpython/repl.py:561 #, python-format msgid "No source code found for %s" msgstr "Quellcode für %s nicht gefunden" -#: bpython/repl.py:681 +#: bpython/repl.py:694 msgid "Save to file (Esc to cancel): " msgstr "In Datei speichern (Esc um abzubrechen): " -#: bpython/repl.py:683 bpython/repl.py:686 bpython/repl.py:705 +#: bpython/repl.py:696 bpython/repl.py:699 bpython/repl.py:718 msgid "Save cancelled." msgstr "Speichern abgebrochen." -#: bpython/repl.py:696 +#: bpython/repl.py:709 #, python-format msgid "%s already exists. Do you want to (c)ancel, (o)verwrite or (a)ppend? " -msgstr "%s existiert bereit. (C) abbrechen, (o) überschrieben oder (a) anhängen?" +msgstr "" +"%s existiert bereit. (C) abbrechen, (o) überschrieben oder (a) anhängen?" -#: bpython/repl.py:700 +#: bpython/repl.py:713 msgid "overwrite" msgstr "überschreiben" -#: bpython/repl.py:702 +#: bpython/repl.py:715 msgid "append" msgstr "anhängen" -#: bpython/repl.py:714 bpython/repl.py:1075 +#: bpython/repl.py:727 bpython/repl.py:1022 #, python-format msgid "Error writing file '%s': %s" msgstr "Fehler beim Schreiben in Datei '%s': %s" -#: bpython/repl.py:717 +#: bpython/repl.py:729 #, python-format msgid "Saved to %s." msgstr "Nach %s gespeichert." -#: bpython/repl.py:723 +#: bpython/repl.py:735 msgid "No clipboard available." msgstr "Zwischenablage ist nicht verfügbar." -#: bpython/repl.py:730 +#: bpython/repl.py:742 msgid "Could not copy to clipboard." msgstr "Konnte nicht in Zwischenablage kopieren." -#: bpython/repl.py:732 +#: bpython/repl.py:744 msgid "Copied content to clipboard." msgstr "Inhalt wurde in Zwischenablage kopiert." -#: bpython/repl.py:741 +#: bpython/repl.py:753 msgid "Pastebin buffer? (y/N) " msgstr "" -#: bpython/repl.py:742 +#: bpython/repl.py:754 msgid "Pastebin aborted." msgstr "" -#: bpython/repl.py:749 +#: bpython/repl.py:761 #, python-format msgid "Duplicate pastebin. Previous URL: %s. Removal URL: %s" msgstr "" -#: bpython/repl.py:770 bpython/repl.py:799 +#: bpython/repl.py:768 msgid "Posting data to pastebin..." msgstr "Lade Daten hoch..." -#: bpython/repl.py:775 +#: bpython/repl.py:772 #, python-format msgid "Upload failed: %s" msgstr "Hochladen ist fehlgeschlagen: %s" -#: bpython/repl.py:792 +#: bpython/repl.py:780 #, python-format msgid "Pastebin URL: %s - Removal URL: %s" msgstr "" -#: bpython/repl.py:811 -msgid "Upload failed: Helper program not found." -msgstr "Hochladen ist fehlgeschlagen: Hilfsprogramm konnte nicht gefunden werden." - -#: bpython/repl.py:814 -msgid "Upload failed: Helper program could not be run." -msgstr "" -"Hochladen ist fehlgeschlagen: Hilfsprogramm konnte nicht ausgeführt " -"werden." - -#: bpython/repl.py:821 -#, python-format -msgid "Upload failed: Helper program returned non-zero exit status %d." -msgstr "Hochladen ist fehlgeschlagen: Hilfsprogramm beendete mit Status %d." - -#: bpython/repl.py:825 -msgid "Upload failed: No output from helper program." -msgstr "Hochladen ist fehlgeschlagen: Keine Ausgabe von Hilfsprogramm vorhanden." - -#: bpython/repl.py:833 -msgid "Upload failed: Failed to recognize the helper program's output as an URL." -msgstr "" -"Hochladen ist fehlgeschlagen: Konte Ausgabe von Hilfsprogramm nicht " -"verarbeiten." - -#: bpython/repl.py:839 +#: bpython/repl.py:783 #, python-format msgid "Pastebin URL: %s" msgstr "" -#: bpython/repl.py:872 +#: bpython/repl.py:817 #, python-format msgid "Undo how many lines? (Undo will take up to ~%.1f seconds) [1]" msgstr "" -#: bpython/repl.py:879 bpython/repl.py:883 +#: bpython/repl.py:824 bpython/repl.py:828 msgid "Undo canceled" msgstr "Rückgängigmachen abgebrochen" -#: bpython/repl.py:886 +#: bpython/repl.py:831 #, python-format msgid "Undoing %d line... (est. %.1f seconds)" msgid_plural "Undoing %d lines... (est. %.1f seconds)" msgstr[0] "" msgstr[1] "" -#: bpython/repl.py:1062 +#: bpython/repl.py:1007 msgid "Config file does not exist - create new from default? (y/N)" msgstr "" -"Konfigurationsdatei existiert nicht. Soll eine neue Datei erstellt " -"werden? (j/N)" +"Konfigurationsdatei existiert nicht. Soll eine neue Datei erstellt werden? " +"(j/N)" -#: bpython/repl.py:1082 +#: bpython/repl.py:1029 msgid "bpython config file edited. Restart bpython for changes to take effect." msgstr "" "bpython Konfigurationsdatei bearbeitet. Starte bpython neu damit die " "Änderungen übernommen werden." -#: bpython/repl.py:1085 +#: bpython/repl.py:1032 msgid "Error editing config file." msgstr "Fehler beim Bearbeiten der Konfigurationsdatei." @@ -259,39 +258,38 @@ msgstr "" msgid "Port to run an eval server on (forces Twisted)." msgstr "" -#: bpython/curtsiesfrontend/repl.py:286 +#: bpython/curtsiesfrontend/repl.py:344 msgid "Welcome to bpython!" msgstr "Willkommen by bpython!" -#: bpython/curtsiesfrontend/repl.py:287 +#: bpython/curtsiesfrontend/repl.py:345 #, python-format msgid "Press <%s> for help." msgstr "Drücke <%s> für Hilfe." -#: bpython/curtsiesfrontend/repl.py:526 +#: bpython/curtsiesfrontend/repl.py:565 #, python-format msgid "Executing PYTHONSTARTUP failed: %s" msgstr "Fehler beim Ausführen von PYTHONSTARTUP: %s" -#: bpython/curtsiesfrontend/repl.py:543 +#: bpython/curtsiesfrontend/repl.py:582 #, python-format msgid "Reloaded at %s because %s modified." msgstr "" -#: bpython/curtsiesfrontend/repl.py:814 +#: bpython/curtsiesfrontend/repl.py:855 #, python-format msgid "Reloaded at %s by user." msgstr "" -#: bpython/curtsiesfrontend/repl.py:820 +#: bpython/curtsiesfrontend/repl.py:861 msgid "Auto-reloading deactivated." msgstr "" -#: bpython/curtsiesfrontend/repl.py:825 +#: bpython/curtsiesfrontend/repl.py:866 msgid "Auto-reloading active, watching for file changes..." msgstr "" -#: bpython/curtsiesfrontend/repl.py:830 +#: bpython/curtsiesfrontend/repl.py:871 msgid "Auto-reloading not available because watchdog not installed." msgstr "" - diff --git a/bpython/translations/es_ES/LC_MESSAGES/bpython.po b/bpython/translations/es_ES/LC_MESSAGES/bpython.po index 34604d59f..d88ebcc9d 100644 --- a/bpython/translations/es_ES/LC_MESSAGES/bpython.po +++ b/bpython/translations/es_ES/LC_MESSAGES/bpython.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: bpython 0.9.7\n" "Report-Msgid-Bugs-To: http://github.com/bpython/bpython/issues\n" -"POT-Creation-Date: 2015-02-16 21:56+0100\n" +"POT-Creation-Date: 2015-03-24 00:25+0100\n" "PO-Revision-Date: 2015-02-02 00:34+0100\n" "Last-Translator: Sebastian Ramacher \n" "Language-Team: bpython developers\n" @@ -68,159 +68,159 @@ msgstr "" msgid "Show Source" msgstr "" -#: bpython/curtsies.py:36 +#: bpython/curtsies.py:37 msgid "log debug messages to bpython.log" msgstr "" -#: bpython/curtsies.py:38 +#: bpython/curtsies.py:39 msgid "start by pasting lines of a file into session" msgstr "" -#: bpython/history.py:223 +#: bpython/history.py:228 #, python-format msgid "Error occurred while writing to file %s (%s)" msgstr "" -#: bpython/repl.py:537 +#: bpython/paste.py:94 +msgid "Helper program not found." +msgstr "" + +#: bpython/paste.py:96 +msgid "Helper program could not be run." +msgstr "" + +#: bpython/paste.py:100 +#, python-format +msgid "Helper program returned non-zero exit status %d." +msgstr "" + +#: bpython/paste.py:103 +msgid "No output from helper program." +msgstr "" + +#: bpython/paste.py:109 +msgid "Failed to recognize the helper program's output as an URL." +msgstr "" + +#: bpython/repl.py:549 msgid "Nothing to get source of" msgstr "" -#: bpython/repl.py:542 +#: bpython/repl.py:554 #, python-format msgid "Cannot get source: %s" msgstr "" -#: bpython/repl.py:547 +#: bpython/repl.py:559 #, python-format msgid "Cannot access source of %r" msgstr "" -#: bpython/repl.py:549 +#: bpython/repl.py:561 #, python-format msgid "No source code found for %s" msgstr "" -#: bpython/repl.py:681 +#: bpython/repl.py:694 msgid "Save to file (Esc to cancel): " msgstr "" -#: bpython/repl.py:683 bpython/repl.py:686 bpython/repl.py:705 +#: bpython/repl.py:696 bpython/repl.py:699 bpython/repl.py:718 msgid "Save cancelled." msgstr "" -#: bpython/repl.py:696 +#: bpython/repl.py:709 #, python-format msgid "%s already exists. Do you want to (c)ancel, (o)verwrite or (a)ppend? " msgstr "" -#: bpython/repl.py:700 +#: bpython/repl.py:713 msgid "overwrite" msgstr "" -#: bpython/repl.py:702 +#: bpython/repl.py:715 msgid "append" msgstr "" -#: bpython/repl.py:714 bpython/repl.py:1075 +#: bpython/repl.py:727 bpython/repl.py:1022 #, python-format msgid "Error writing file '%s': %s" msgstr "" -#: bpython/repl.py:717 +#: bpython/repl.py:729 #, python-format msgid "Saved to %s." msgstr "" -#: bpython/repl.py:723 +#: bpython/repl.py:735 msgid "No clipboard available." msgstr "" -#: bpython/repl.py:730 +#: bpython/repl.py:742 msgid "Could not copy to clipboard." msgstr "" -#: bpython/repl.py:732 +#: bpython/repl.py:744 msgid "Copied content to clipboard." msgstr "" -#: bpython/repl.py:741 +#: bpython/repl.py:753 msgid "Pastebin buffer? (y/N) " msgstr "" -#: bpython/repl.py:742 +#: bpython/repl.py:754 msgid "Pastebin aborted." msgstr "" -#: bpython/repl.py:749 +#: bpython/repl.py:761 #, python-format msgid "Duplicate pastebin. Previous URL: %s. Removal URL: %s" msgstr "" -#: bpython/repl.py:770 bpython/repl.py:799 +#: bpython/repl.py:768 msgid "Posting data to pastebin..." msgstr "" -#: bpython/repl.py:775 +#: bpython/repl.py:772 #, python-format msgid "Upload failed: %s" msgstr "" -#: bpython/repl.py:792 +#: bpython/repl.py:780 #, python-format msgid "Pastebin URL: %s - Removal URL: %s" msgstr "" -#: bpython/repl.py:811 -msgid "Upload failed: Helper program not found." -msgstr "" - -#: bpython/repl.py:814 -msgid "Upload failed: Helper program could not be run." -msgstr "" - -#: bpython/repl.py:821 -#, python-format -msgid "Upload failed: Helper program returned non-zero exit status %d." -msgstr "" - -#: bpython/repl.py:825 -msgid "Upload failed: No output from helper program." -msgstr "" - -#: bpython/repl.py:833 -msgid "Upload failed: Failed to recognize the helper program's output as an URL." -msgstr "" - -#: bpython/repl.py:839 +#: bpython/repl.py:783 #, python-format msgid "Pastebin URL: %s" msgstr "" -#: bpython/repl.py:872 +#: bpython/repl.py:817 #, python-format msgid "Undo how many lines? (Undo will take up to ~%.1f seconds) [1]" msgstr "" -#: bpython/repl.py:879 bpython/repl.py:883 +#: bpython/repl.py:824 bpython/repl.py:828 msgid "Undo canceled" msgstr "" -#: bpython/repl.py:886 +#: bpython/repl.py:831 #, python-format msgid "Undoing %d line... (est. %.1f seconds)" msgid_plural "Undoing %d lines... (est. %.1f seconds)" msgstr[0] "" msgstr[1] "" -#: bpython/repl.py:1062 +#: bpython/repl.py:1007 msgid "Config file does not exist - create new from default? (y/N)" msgstr "" -#: bpython/repl.py:1082 +#: bpython/repl.py:1029 msgid "bpython config file edited. Restart bpython for changes to take effect." msgstr "" -#: bpython/repl.py:1085 +#: bpython/repl.py:1032 msgid "Error editing config file." msgstr "" @@ -253,39 +253,39 @@ msgstr "" msgid "Port to run an eval server on (forces Twisted)." msgstr "" -#: bpython/curtsiesfrontend/repl.py:286 +#: bpython/curtsiesfrontend/repl.py:344 msgid "Welcome to bpython!" msgstr "" -#: bpython/curtsiesfrontend/repl.py:287 +#: bpython/curtsiesfrontend/repl.py:345 #, python-format msgid "Press <%s> for help." msgstr "" -#: bpython/curtsiesfrontend/repl.py:526 +#: bpython/curtsiesfrontend/repl.py:565 #, python-format msgid "Executing PYTHONSTARTUP failed: %s" msgstr "" -#: bpython/curtsiesfrontend/repl.py:543 +#: bpython/curtsiesfrontend/repl.py:582 #, python-format msgid "Reloaded at %s because %s modified." msgstr "" -#: bpython/curtsiesfrontend/repl.py:814 +#: bpython/curtsiesfrontend/repl.py:855 #, python-format msgid "Reloaded at %s by user." msgstr "" -#: bpython/curtsiesfrontend/repl.py:820 +#: bpython/curtsiesfrontend/repl.py:861 msgid "Auto-reloading deactivated." msgstr "" -#: bpython/curtsiesfrontend/repl.py:825 +#: bpython/curtsiesfrontend/repl.py:866 msgid "Auto-reloading active, watching for file changes..." msgstr "" -#: bpython/curtsiesfrontend/repl.py:830 +#: bpython/curtsiesfrontend/repl.py:871 msgid "Auto-reloading not available because watchdog not installed." msgstr "" diff --git a/bpython/translations/fr_FR/LC_MESSAGES/bpython.po b/bpython/translations/fr_FR/LC_MESSAGES/bpython.po index 1bb4aaff5..cc326c2de 100644 --- a/bpython/translations/fr_FR/LC_MESSAGES/bpython.po +++ b/bpython/translations/fr_FR/LC_MESSAGES/bpython.po @@ -6,25 +6,27 @@ msgid "" msgstr "" "Project-Id-Version: bpython 0.13-442\n" "Report-Msgid-Bugs-To: http://github.com/bpython/bpython/issues\n" -"POT-Creation-Date: 2015-02-16 21:56+0100\n" -"PO-Revision-Date: 2015-02-05 14:54+0100\n" +"POT-Creation-Date: 2015-03-24 00:25+0100\n" +"PO-Revision-Date: 2015-03-24 00:29+0100\n" "Last-Translator: Sebastian Ramacher \n" "Language-Team: bpython developers\n" -"Plural-Forms: nplurals=2; plural=(n > 1)\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 1.3\n" +"Language: fr_FR\n" +"X-Generator: Poedit 1.6.10\n" #: bpython/args.py:59 msgid "" "Usage: %prog [options] [file [args]]\n" -"NOTE: If bpython sees an argument it does not know, execution falls back " -"to the regular Python interpreter." +"NOTE: If bpython sees an argument it does not know, execution falls back to " +"the regular Python interpreter." msgstr "" "Utilisation: %prog [options] [fichier [arguments]]\n" -"NOTE: Si bpython ne reconnaît pas un des arguments fournis, " -"l'interpréteur Python classique sera lancé" +"NOTE: Si bpython ne reconnaît pas un des arguments fournis, l'interpréteur " +"Python classique sera lancé" #: bpython/args.py:69 msgid "Use CONFIG instead of default config file." @@ -33,8 +35,7 @@ msgstr "Utiliser CONFIG à la place du fichier de configuration par défaut." #: bpython/args.py:71 msgid "Drop to bpython shell after running file instead of exiting." msgstr "" -"Aller dans le shell bpython après l'exécution du fichier au lieu de " -"quitter." +"Aller dans le shell bpython après l'exécution du fichier au lieu de quitter." #: bpython/args.py:74 msgid "Don't flush the output to stdout." @@ -72,163 +73,161 @@ msgstr "" msgid "Show Source" msgstr "Montrer le code source" -#: bpython/curtsies.py:36 +#: bpython/curtsies.py:37 msgid "log debug messages to bpython.log" msgstr "logger les messages de debug dans bpython.log" -#: bpython/curtsies.py:38 +#: bpython/curtsies.py:39 msgid "start by pasting lines of a file into session" msgstr "" -#: bpython/history.py:223 +#: bpython/history.py:228 #, python-format msgid "Error occurred while writing to file %s (%s)" msgstr "Une erreur s'est produite pendant l'écriture du fichier %s (%s)" -#: bpython/repl.py:537 +#: bpython/paste.py:94 +msgid "Helper program not found." +msgstr "programme externe non trouvé." + +#: bpython/paste.py:96 +msgid "Helper program could not be run." +msgstr "impossible de lancer le programme externe." + +#: bpython/paste.py:100 +#, python-format +msgid "Helper program returned non-zero exit status %d." +msgstr "" +"le programme externe a renvoyé un statut de sortie différent de zéro %d." + +#: bpython/paste.py:103 +msgid "No output from helper program." +msgstr "pas de sortie du programme externe." + +#: bpython/paste.py:109 +msgid "Failed to recognize the helper program's output as an URL." +msgstr "la sortie du programme externe ne correspond pas à une URL." + +#: bpython/repl.py:549 msgid "Nothing to get source of" msgstr "" -#: bpython/repl.py:542 +#: bpython/repl.py:554 #, python-format msgid "Cannot get source: %s" msgstr "Impossible de récupérer le source: %s" -#: bpython/repl.py:547 +#: bpython/repl.py:559 #, python-format msgid "Cannot access source of %r" msgstr "Impossible d'accéder au source de %r" -#: bpython/repl.py:549 +#: bpython/repl.py:561 #, python-format msgid "No source code found for %s" msgstr "Pas de code source trouvé pour %s" -#: bpython/repl.py:681 +#: bpython/repl.py:694 msgid "Save to file (Esc to cancel): " msgstr "" -#: bpython/repl.py:683 bpython/repl.py:686 bpython/repl.py:705 +#: bpython/repl.py:696 bpython/repl.py:699 bpython/repl.py:718 msgid "Save cancelled." msgstr "" -#: bpython/repl.py:696 +#: bpython/repl.py:709 #, python-format msgid "%s already exists. Do you want to (c)ancel, (o)verwrite or (a)ppend? " msgstr "" -#: bpython/repl.py:700 +#: bpython/repl.py:713 msgid "overwrite" msgstr "" -#: bpython/repl.py:702 +#: bpython/repl.py:715 msgid "append" msgstr "" -#: bpython/repl.py:714 bpython/repl.py:1075 +#: bpython/repl.py:727 bpython/repl.py:1022 #, python-format msgid "Error writing file '%s': %s" msgstr "Une erreur s'est produite pendant l'écriture du fichier '%s': %s" -#: bpython/repl.py:717 +#: bpython/repl.py:729 #, python-format msgid "Saved to %s." msgstr "" -#: bpython/repl.py:723 +#: bpython/repl.py:735 msgid "No clipboard available." msgstr "Pas de presse-papier disponible." -#: bpython/repl.py:730 +#: bpython/repl.py:742 msgid "Could not copy to clipboard." msgstr "Impossible de copier vers le presse-papier." -#: bpython/repl.py:732 +#: bpython/repl.py:744 msgid "Copied content to clipboard." msgstr "Contenu copié vers le presse-papier." -#: bpython/repl.py:741 +#: bpython/repl.py:753 msgid "Pastebin buffer? (y/N) " msgstr "Tampon Pastebin ? (o/N) " -#: bpython/repl.py:742 +#: bpython/repl.py:754 msgid "Pastebin aborted." msgstr "Pastebin abandonné." -#: bpython/repl.py:749 +#: bpython/repl.py:761 #, python-format msgid "Duplicate pastebin. Previous URL: %s. Removal URL: %s" msgstr "Pastebin dupliqué. URL précédente: %s. URL de suppression: %s" -#: bpython/repl.py:770 bpython/repl.py:799 +#: bpython/repl.py:768 msgid "Posting data to pastebin..." msgstr "Envoi des donnés à pastebin..." -#: bpython/repl.py:775 +#: bpython/repl.py:772 #, python-format msgid "Upload failed: %s" msgstr "Echec du téléchargement: %s" -#: bpython/repl.py:792 +#: bpython/repl.py:780 #, python-format msgid "Pastebin URL: %s - Removal URL: %s" msgstr "URL Pastebin: %s - URL de suppression: %s" -#: bpython/repl.py:811 -msgid "Upload failed: Helper program not found." -msgstr "Echec de l'upload: programme externe non trouvé." - -#: bpython/repl.py:814 -msgid "Upload failed: Helper program could not be run." -msgstr "Echec de l'upload: impossible de lancer le programme externe." - -#: bpython/repl.py:821 -#, python-format -msgid "Upload failed: Helper program returned non-zero exit status %d." -msgstr "" -"Echec de l'upload: le programme externe a renvoyé un statut de sortie " -"différent de zéro %d." - -#: bpython/repl.py:825 -msgid "Upload failed: No output from helper program." -msgstr "Echec de l'upload: pas de sortie du programme externe." - -#: bpython/repl.py:833 -msgid "Upload failed: Failed to recognize the helper program's output as an URL." -msgstr "" -"Echec de l'upload: la sortie du programme externe ne correspond pas à une" -" URL." - -#: bpython/repl.py:839 +#: bpython/repl.py:783 #, python-format msgid "Pastebin URL: %s" msgstr "URL Pastebin: %s" -#: bpython/repl.py:872 +#: bpython/repl.py:817 #, python-format msgid "Undo how many lines? (Undo will take up to ~%.1f seconds) [1]" msgstr "" -#: bpython/repl.py:879 bpython/repl.py:883 +#: bpython/repl.py:824 bpython/repl.py:828 msgid "Undo canceled" msgstr "" -#: bpython/repl.py:886 +#: bpython/repl.py:831 #, python-format msgid "Undoing %d line... (est. %.1f seconds)" msgid_plural "Undoing %d lines... (est. %.1f seconds)" msgstr[0] "" msgstr[1] "" -#: bpython/repl.py:1062 +#: bpython/repl.py:1007 msgid "Config file does not exist - create new from default? (y/N)" -msgstr "Le fichier de configuration n'existe pas - en créér un par défaut? (o/N)" +msgstr "" +"Le fichier de configuration n'existe pas - en créér un par défaut? (o/N)" -#: bpython/repl.py:1082 +#: bpython/repl.py:1029 msgid "bpython config file edited. Restart bpython for changes to take effect." msgstr "" -#: bpython/repl.py:1085 +#: bpython/repl.py:1032 msgid "Error editing config file." msgstr "" @@ -236,8 +235,8 @@ msgstr "" #, python-format msgid " <%s> Rewind <%s> Save <%s> Pastebin <%s> Pager <%s> Show Source " msgstr "" -" <%s> Rebobiner <%s> Sauvegarder <%s> Pastebin <%s> Pager <%s> " -"Montrer Source " +" <%s> Rebobiner <%s> Sauvegarder <%s> Pastebin <%s> Pager <%s> Montrer " +"Source " #: bpython/urwid.py:1128 msgid "Run twisted reactor." @@ -245,7 +244,8 @@ msgstr "Lancer le reactor twisted." #: bpython/urwid.py:1130 msgid "Select specific reactor (see --help-reactors). Implies --twisted." -msgstr "Choisir un reactor spécifique (voir --help-reactors). Nécessite --twisted." +msgstr "" +"Choisir un reactor spécifique (voir --help-reactors). Nécessite --twisted." #: bpython/urwid.py:1133 msgid "List available reactors for -r." @@ -256,46 +256,45 @@ msgid "" "twistd plugin to run (use twistd for a list). Use \"--\" to pass further " "options to the plugin." msgstr "" -"plugin twistd à lancer (utiliser twistd pour une list). Utiliser \"--\" " -"pour donner plus d'options au plugin." +"plugin twistd à lancer (utiliser twistd pour une list). Utiliser \"--\" pour " +"donner plus d'options au plugin." #: bpython/urwid.py:1138 msgid "Port to run an eval server on (forces Twisted)." msgstr "Port pour lancer un server eval (force Twisted)." -#: bpython/curtsiesfrontend/repl.py:286 +#: bpython/curtsiesfrontend/repl.py:344 msgid "Welcome to bpython!" msgstr "Bienvenue dans bpython!" -#: bpython/curtsiesfrontend/repl.py:287 +#: bpython/curtsiesfrontend/repl.py:345 #, python-format msgid "Press <%s> for help." msgstr "Appuyer sur <%s> pour de l'aide." -#: bpython/curtsiesfrontend/repl.py:526 +#: bpython/curtsiesfrontend/repl.py:565 #, python-format msgid "Executing PYTHONSTARTUP failed: %s" msgstr "L'exécution de PYTHONSTARTUP a échoué: %s" -#: bpython/curtsiesfrontend/repl.py:543 +#: bpython/curtsiesfrontend/repl.py:582 #, python-format msgid "Reloaded at %s because %s modified." msgstr "" -#: bpython/curtsiesfrontend/repl.py:814 +#: bpython/curtsiesfrontend/repl.py:855 #, python-format msgid "Reloaded at %s by user." msgstr "" -#: bpython/curtsiesfrontend/repl.py:820 +#: bpython/curtsiesfrontend/repl.py:861 msgid "Auto-reloading deactivated." msgstr "" -#: bpython/curtsiesfrontend/repl.py:825 +#: bpython/curtsiesfrontend/repl.py:866 msgid "Auto-reloading active, watching for file changes..." msgstr "" -#: bpython/curtsiesfrontend/repl.py:830 +#: bpython/curtsiesfrontend/repl.py:871 msgid "Auto-reloading not available because watchdog not installed." msgstr "" - diff --git a/bpython/translations/it_IT/LC_MESSAGES/bpython.po b/bpython/translations/it_IT/LC_MESSAGES/bpython.po index 08446d970..66cd0d5a5 100644 --- a/bpython/translations/it_IT/LC_MESSAGES/bpython.po +++ b/bpython/translations/it_IT/LC_MESSAGES/bpython.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: bpython 0.9.7\n" "Report-Msgid-Bugs-To: http://github.com/bpython/bpython/issues\n" -"POT-Creation-Date: 2015-02-16 21:56+0100\n" +"POT-Creation-Date: 2015-03-24 00:25+0100\n" "PO-Revision-Date: 2015-02-02 00:34+0100\n" "Last-Translator: Sebastian Ramacher \n" "Language-Team: Michele Orrù\n" @@ -68,159 +68,159 @@ msgstr "" msgid "Show Source" msgstr "" -#: bpython/curtsies.py:36 +#: bpython/curtsies.py:37 msgid "log debug messages to bpython.log" msgstr "" -#: bpython/curtsies.py:38 +#: bpython/curtsies.py:39 msgid "start by pasting lines of a file into session" msgstr "" -#: bpython/history.py:223 +#: bpython/history.py:228 #, python-format msgid "Error occurred while writing to file %s (%s)" msgstr "" -#: bpython/repl.py:537 +#: bpython/paste.py:94 +msgid "Helper program not found." +msgstr "" + +#: bpython/paste.py:96 +msgid "Helper program could not be run." +msgstr "" + +#: bpython/paste.py:100 +#, python-format +msgid "Helper program returned non-zero exit status %d." +msgstr "" + +#: bpython/paste.py:103 +msgid "No output from helper program." +msgstr "" + +#: bpython/paste.py:109 +msgid "Failed to recognize the helper program's output as an URL." +msgstr "" + +#: bpython/repl.py:549 msgid "Nothing to get source of" msgstr "" -#: bpython/repl.py:542 +#: bpython/repl.py:554 #, python-format msgid "Cannot get source: %s" msgstr "" -#: bpython/repl.py:547 +#: bpython/repl.py:559 #, python-format msgid "Cannot access source of %r" msgstr "" -#: bpython/repl.py:549 +#: bpython/repl.py:561 #, python-format msgid "No source code found for %s" msgstr "" -#: bpython/repl.py:681 +#: bpython/repl.py:694 msgid "Save to file (Esc to cancel): " msgstr "" -#: bpython/repl.py:683 bpython/repl.py:686 bpython/repl.py:705 +#: bpython/repl.py:696 bpython/repl.py:699 bpython/repl.py:718 msgid "Save cancelled." msgstr "" -#: bpython/repl.py:696 +#: bpython/repl.py:709 #, python-format msgid "%s already exists. Do you want to (c)ancel, (o)verwrite or (a)ppend? " msgstr "" -#: bpython/repl.py:700 +#: bpython/repl.py:713 msgid "overwrite" msgstr "" -#: bpython/repl.py:702 +#: bpython/repl.py:715 msgid "append" msgstr "" -#: bpython/repl.py:714 bpython/repl.py:1075 +#: bpython/repl.py:727 bpython/repl.py:1022 #, python-format msgid "Error writing file '%s': %s" msgstr "" -#: bpython/repl.py:717 +#: bpython/repl.py:729 #, python-format msgid "Saved to %s." msgstr "" -#: bpython/repl.py:723 +#: bpython/repl.py:735 msgid "No clipboard available." msgstr "" -#: bpython/repl.py:730 +#: bpython/repl.py:742 msgid "Could not copy to clipboard." msgstr "" -#: bpython/repl.py:732 +#: bpython/repl.py:744 msgid "Copied content to clipboard." msgstr "" -#: bpython/repl.py:741 +#: bpython/repl.py:753 msgid "Pastebin buffer? (y/N) " msgstr "" -#: bpython/repl.py:742 +#: bpython/repl.py:754 msgid "Pastebin aborted." msgstr "" -#: bpython/repl.py:749 +#: bpython/repl.py:761 #, python-format msgid "Duplicate pastebin. Previous URL: %s. Removal URL: %s" msgstr "" -#: bpython/repl.py:770 bpython/repl.py:799 +#: bpython/repl.py:768 msgid "Posting data to pastebin..." msgstr "" -#: bpython/repl.py:775 +#: bpython/repl.py:772 #, python-format msgid "Upload failed: %s" msgstr "" -#: bpython/repl.py:792 +#: bpython/repl.py:780 #, python-format msgid "Pastebin URL: %s - Removal URL: %s" msgstr "" -#: bpython/repl.py:811 -msgid "Upload failed: Helper program not found." -msgstr "" - -#: bpython/repl.py:814 -msgid "Upload failed: Helper program could not be run." -msgstr "" - -#: bpython/repl.py:821 -#, python-format -msgid "Upload failed: Helper program returned non-zero exit status %d." -msgstr "" - -#: bpython/repl.py:825 -msgid "Upload failed: No output from helper program." -msgstr "" - -#: bpython/repl.py:833 -msgid "Upload failed: Failed to recognize the helper program's output as an URL." -msgstr "" - -#: bpython/repl.py:839 +#: bpython/repl.py:783 #, python-format msgid "Pastebin URL: %s" msgstr "" -#: bpython/repl.py:872 +#: bpython/repl.py:817 #, python-format msgid "Undo how many lines? (Undo will take up to ~%.1f seconds) [1]" msgstr "" -#: bpython/repl.py:879 bpython/repl.py:883 +#: bpython/repl.py:824 bpython/repl.py:828 msgid "Undo canceled" msgstr "" -#: bpython/repl.py:886 +#: bpython/repl.py:831 #, python-format msgid "Undoing %d line... (est. %.1f seconds)" msgid_plural "Undoing %d lines... (est. %.1f seconds)" msgstr[0] "" msgstr[1] "" -#: bpython/repl.py:1062 +#: bpython/repl.py:1007 msgid "Config file does not exist - create new from default? (y/N)" msgstr "" -#: bpython/repl.py:1082 +#: bpython/repl.py:1029 msgid "bpython config file edited. Restart bpython for changes to take effect." msgstr "" -#: bpython/repl.py:1085 +#: bpython/repl.py:1032 msgid "Error editing config file." msgstr "" @@ -251,39 +251,39 @@ msgstr "" msgid "Port to run an eval server on (forces Twisted)." msgstr "" -#: bpython/curtsiesfrontend/repl.py:286 +#: bpython/curtsiesfrontend/repl.py:344 msgid "Welcome to bpython!" msgstr "" -#: bpython/curtsiesfrontend/repl.py:287 +#: bpython/curtsiesfrontend/repl.py:345 #, python-format msgid "Press <%s> for help." msgstr "" -#: bpython/curtsiesfrontend/repl.py:526 +#: bpython/curtsiesfrontend/repl.py:565 #, python-format msgid "Executing PYTHONSTARTUP failed: %s" msgstr "" -#: bpython/curtsiesfrontend/repl.py:543 +#: bpython/curtsiesfrontend/repl.py:582 #, python-format msgid "Reloaded at %s because %s modified." msgstr "" -#: bpython/curtsiesfrontend/repl.py:814 +#: bpython/curtsiesfrontend/repl.py:855 #, python-format msgid "Reloaded at %s by user." msgstr "" -#: bpython/curtsiesfrontend/repl.py:820 +#: bpython/curtsiesfrontend/repl.py:861 msgid "Auto-reloading deactivated." msgstr "" -#: bpython/curtsiesfrontend/repl.py:825 +#: bpython/curtsiesfrontend/repl.py:866 msgid "Auto-reloading active, watching for file changes..." msgstr "" -#: bpython/curtsiesfrontend/repl.py:830 +#: bpython/curtsiesfrontend/repl.py:871 msgid "Auto-reloading not available because watchdog not installed." msgstr "" diff --git a/bpython/translations/nl_NL/LC_MESSAGES/bpython.po b/bpython/translations/nl_NL/LC_MESSAGES/bpython.po index 2da674b5e..c82908ee7 100644 --- a/bpython/translations/nl_NL/LC_MESSAGES/bpython.po +++ b/bpython/translations/nl_NL/LC_MESSAGES/bpython.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: bpython 0.9.7.1\n" "Report-Msgid-Bugs-To: http://github.com/bpython/bpython/issues\n" -"POT-Creation-Date: 2015-02-16 21:56+0100\n" +"POT-Creation-Date: 2015-03-24 00:25+0100\n" "PO-Revision-Date: 2015-02-02 00:34+0100\n" "Last-Translator: Sebastian Ramacher \n" "Language-Team: bpython developers\n" @@ -68,159 +68,159 @@ msgstr "" msgid "Show Source" msgstr "" -#: bpython/curtsies.py:36 +#: bpython/curtsies.py:37 msgid "log debug messages to bpython.log" msgstr "" -#: bpython/curtsies.py:38 +#: bpython/curtsies.py:39 msgid "start by pasting lines of a file into session" msgstr "" -#: bpython/history.py:223 +#: bpython/history.py:228 #, python-format msgid "Error occurred while writing to file %s (%s)" msgstr "" -#: bpython/repl.py:537 +#: bpython/paste.py:94 +msgid "Helper program not found." +msgstr "" + +#: bpython/paste.py:96 +msgid "Helper program could not be run." +msgstr "" + +#: bpython/paste.py:100 +#, python-format +msgid "Helper program returned non-zero exit status %d." +msgstr "" + +#: bpython/paste.py:103 +msgid "No output from helper program." +msgstr "" + +#: bpython/paste.py:109 +msgid "Failed to recognize the helper program's output as an URL." +msgstr "" + +#: bpython/repl.py:549 msgid "Nothing to get source of" msgstr "" -#: bpython/repl.py:542 +#: bpython/repl.py:554 #, python-format msgid "Cannot get source: %s" msgstr "" -#: bpython/repl.py:547 +#: bpython/repl.py:559 #, python-format msgid "Cannot access source of %r" msgstr "" -#: bpython/repl.py:549 +#: bpython/repl.py:561 #, python-format msgid "No source code found for %s" msgstr "" -#: bpython/repl.py:681 +#: bpython/repl.py:694 msgid "Save to file (Esc to cancel): " msgstr "" -#: bpython/repl.py:683 bpython/repl.py:686 bpython/repl.py:705 +#: bpython/repl.py:696 bpython/repl.py:699 bpython/repl.py:718 msgid "Save cancelled." msgstr "" -#: bpython/repl.py:696 +#: bpython/repl.py:709 #, python-format msgid "%s already exists. Do you want to (c)ancel, (o)verwrite or (a)ppend? " msgstr "" -#: bpython/repl.py:700 +#: bpython/repl.py:713 msgid "overwrite" msgstr "" -#: bpython/repl.py:702 +#: bpython/repl.py:715 msgid "append" msgstr "" -#: bpython/repl.py:714 bpython/repl.py:1075 +#: bpython/repl.py:727 bpython/repl.py:1022 #, python-format msgid "Error writing file '%s': %s" msgstr "" -#: bpython/repl.py:717 +#: bpython/repl.py:729 #, python-format msgid "Saved to %s." msgstr "" -#: bpython/repl.py:723 +#: bpython/repl.py:735 msgid "No clipboard available." msgstr "" -#: bpython/repl.py:730 +#: bpython/repl.py:742 msgid "Could not copy to clipboard." msgstr "" -#: bpython/repl.py:732 +#: bpython/repl.py:744 msgid "Copied content to clipboard." msgstr "" -#: bpython/repl.py:741 +#: bpython/repl.py:753 msgid "Pastebin buffer? (y/N) " msgstr "" -#: bpython/repl.py:742 +#: bpython/repl.py:754 msgid "Pastebin aborted." msgstr "" -#: bpython/repl.py:749 +#: bpython/repl.py:761 #, python-format msgid "Duplicate pastebin. Previous URL: %s. Removal URL: %s" msgstr "" -#: bpython/repl.py:770 bpython/repl.py:799 +#: bpython/repl.py:768 msgid "Posting data to pastebin..." msgstr "" -#: bpython/repl.py:775 +#: bpython/repl.py:772 #, python-format msgid "Upload failed: %s" msgstr "" -#: bpython/repl.py:792 +#: bpython/repl.py:780 #, python-format msgid "Pastebin URL: %s - Removal URL: %s" msgstr "" -#: bpython/repl.py:811 -msgid "Upload failed: Helper program not found." -msgstr "" - -#: bpython/repl.py:814 -msgid "Upload failed: Helper program could not be run." -msgstr "" - -#: bpython/repl.py:821 -#, python-format -msgid "Upload failed: Helper program returned non-zero exit status %d." -msgstr "" - -#: bpython/repl.py:825 -msgid "Upload failed: No output from helper program." -msgstr "" - -#: bpython/repl.py:833 -msgid "Upload failed: Failed to recognize the helper program's output as an URL." -msgstr "" - -#: bpython/repl.py:839 +#: bpython/repl.py:783 #, python-format msgid "Pastebin URL: %s" msgstr "" -#: bpython/repl.py:872 +#: bpython/repl.py:817 #, python-format msgid "Undo how many lines? (Undo will take up to ~%.1f seconds) [1]" msgstr "" -#: bpython/repl.py:879 bpython/repl.py:883 +#: bpython/repl.py:824 bpython/repl.py:828 msgid "Undo canceled" msgstr "" -#: bpython/repl.py:886 +#: bpython/repl.py:831 #, python-format msgid "Undoing %d line... (est. %.1f seconds)" msgid_plural "Undoing %d lines... (est. %.1f seconds)" msgstr[0] "" msgstr[1] "" -#: bpython/repl.py:1062 +#: bpython/repl.py:1007 msgid "Config file does not exist - create new from default? (y/N)" msgstr "" -#: bpython/repl.py:1082 +#: bpython/repl.py:1029 msgid "bpython config file edited. Restart bpython for changes to take effect." msgstr "" -#: bpython/repl.py:1085 +#: bpython/repl.py:1032 msgid "Error editing config file." msgstr "" @@ -251,39 +251,39 @@ msgstr "" msgid "Port to run an eval server on (forces Twisted)." msgstr "" -#: bpython/curtsiesfrontend/repl.py:286 +#: bpython/curtsiesfrontend/repl.py:344 msgid "Welcome to bpython!" msgstr "" -#: bpython/curtsiesfrontend/repl.py:287 +#: bpython/curtsiesfrontend/repl.py:345 #, python-format msgid "Press <%s> for help." msgstr "" -#: bpython/curtsiesfrontend/repl.py:526 +#: bpython/curtsiesfrontend/repl.py:565 #, python-format msgid "Executing PYTHONSTARTUP failed: %s" msgstr "" -#: bpython/curtsiesfrontend/repl.py:543 +#: bpython/curtsiesfrontend/repl.py:582 #, python-format msgid "Reloaded at %s because %s modified." msgstr "" -#: bpython/curtsiesfrontend/repl.py:814 +#: bpython/curtsiesfrontend/repl.py:855 #, python-format msgid "Reloaded at %s by user." msgstr "" -#: bpython/curtsiesfrontend/repl.py:820 +#: bpython/curtsiesfrontend/repl.py:861 msgid "Auto-reloading deactivated." msgstr "" -#: bpython/curtsiesfrontend/repl.py:825 +#: bpython/curtsiesfrontend/repl.py:866 msgid "Auto-reloading active, watching for file changes..." msgstr "" -#: bpython/curtsiesfrontend/repl.py:830 +#: bpython/curtsiesfrontend/repl.py:871 msgid "Auto-reloading not available because watchdog not installed." msgstr "" From 21b9a5416410b8b7d680e2557741b8802a990e11 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Tue, 24 Mar 2015 22:15:55 +0100 Subject: [PATCH 13/19] Use bpython.config's getpreferredencoding Signed-off-by: Sebastian Ramacher --- bpython/repl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bpython/repl.py b/bpython/repl.py index f46186238..349cdc00b 100644 --- a/bpython/repl.py +++ b/bpython/repl.py @@ -37,7 +37,6 @@ import time import traceback from itertools import takewhile -from locale import getpreferredencoding from six import itervalues from pygments.token import Token @@ -46,6 +45,7 @@ from bpython import inspection from bpython._py3compat import PythonLexer, py3, prepare_for_exec from bpython.clipboard import get_clipboard, CopyFailed +from bpython.config import getpreferredencoding from bpython.formatter import Parenthesis from bpython.history import History from bpython.paste import PasteHelper, PastePinnwand, PasteFailed From 38f1ed6bc30283ce036bc069ca9b3d8d8de28278 Mon Sep 17 00:00:00 2001 From: Michael Mulley Date: Wed, 25 Mar 2015 16:13:52 -0400 Subject: [PATCH 14/19] Remember the source of interactively defined functions - Patches the linecache module to achieve this - inspect.getsource() works for functions defined on the console - tracebacks show code for frames inside interactively defined functions fixes bpython/bpython#229 --- bpython/history.py | 72 ++++++++++++++++++++++++++++++++ bpython/repl.py | 6 ++- bpython/test/test_interpreter.py | 26 +++++++++--- 3 files changed, 97 insertions(+), 7 deletions(-) diff --git a/bpython/history.py b/bpython/history.py index e08ec2684..a6f632f08 100644 --- a/bpython/history.py +++ b/bpython/history.py @@ -25,6 +25,7 @@ from __future__ import unicode_literals import io +import linecache import os import stat from itertools import islice @@ -232,3 +233,74 @@ def append_reload_and_write(self, s, filename, encoding): # Make sure that entries contains at least one element. If the # file and s are empty, this can occur. self.entries = [''] + +class BPythonLinecache(dict): + """Replaces the cache dict in the standard-library linecache module, + to also remember (in an unerasable way) bpython console input.""" + + def __init__(self, *args, **kwargs): + dict.__init__(self, *args, **kwargs) + self.bpython_history = [] + + def is_bpython_filename(self, fname): + try: + return fname.startswith('' diff --git a/bpython/repl.py b/bpython/repl.py index 349cdc00b..d71aba2c3 100644 --- a/bpython/repl.py +++ b/bpython/repl.py @@ -47,7 +47,7 @@ from bpython.clipboard import get_clipboard, CopyFailed from bpython.config import getpreferredencoding from bpython.formatter import Parenthesis -from bpython.history import History +from bpython.history import History, filename_for_console_input from bpython.paste import PasteHelper, PastePinnwand, PasteFailed from bpython.translations import _, ngettext @@ -94,7 +94,7 @@ def __init__(self, locals=None, encoding=None): def reset_running_time(self): self.running_time = 0 - def runsource(self, source, filename='', symbol='single', + def runsource(self, source, filename=None, symbol='single', encode=True): """Execute Python code. @@ -104,6 +104,8 @@ def runsource(self, source, filename='', symbol='single', if not py3 and encode: source = u'# coding: %s\n%s' % (self.encoding, source) source = source.encode(self.encoding) + if filename is None: + filename = filename_for_console_input(source) with self.timer: return code.InteractiveInterpreter.runsource(self, source, filename, symbol) diff --git a/bpython/test/test_interpreter.py b/bpython/test/test_interpreter.py index a203accbc..49c01d69a 100644 --- a/bpython/test/test_interpreter.py +++ b/bpython/test/test_interpreter.py @@ -17,6 +17,14 @@ pypy = 'PyPy' in sys.version +def _last_console_filename(): + """Returns the last 'filename' used for console input + (as will be displayed in a traceback).""" + import linecache + try: + return '' % (len(linecache.cache.bpython_history) - 1) + except AttributeError: + return '' class TestInterpreter(unittest.TestCase): def test_syntaxerror(self): @@ -30,11 +38,11 @@ def append_to_a(message): i.runsource('1.1.1.1') if pypy: - expected = ' File ' + green('""') + ', line ' + \ + expected = ' File ' + green('"%s"' % _last_console_filename()) + ', line ' + \ bold(magenta('1')) + '\n 1.1.1.1\n ^\n' + \ bold(red('SyntaxError')) + ': ' + cyan('invalid syntax') + '\n' else: - expected = ' File ' + green('""') + ', line ' + \ + expected = ' File ' + green('"%s"' % _last_console_filename()) + ', line ' + \ bold(magenta('1')) + '\n 1.1.1.1\n ^\n' + \ bold(red('SyntaxError')) + ': ' + cyan('invalid syntax') + '\n' @@ -56,7 +64,7 @@ def f(): def g(): return f() - i.runsource('g()') + i.runsource('g()', encode=False) if pypy: global_not_found = "global name 'g' is not defined" @@ -64,8 +72,8 @@ def g(): global_not_found = "name 'g' is not defined" expected = 'Traceback (most recent call last):\n File ' + \ - green('""') + ', line ' + bold(magenta('1')) + ', in ' + \ - cyan('') + '\n' + bold(red('NameError')) + ': ' + \ + green('"%s"' % _last_console_filename()) + ', line ' + bold(magenta('1')) + ', in ' + \ + cyan('') + '\n g()\n' + bold(red('NameError')) + ': ' + \ cyan(global_not_found) + '\n' self.assertMultiLineEqual(str(plain('').join(a)), str(expected)) @@ -106,3 +114,11 @@ def test_runsource_unicode(self): i.runsource("a = u'\xfe'", encode=True) self.assertIsInstance(i.locals['a'], type(u'')) self.assertEqual(i.locals['a'], u"\xfe") + + def test_getsource_works_on_interactively_defined_functions(self): + source = 'def foo(x):\n return x + 1\n' + i = interpreter.Interp() + i.runsource(source) + import inspect + inspected_source = inspect.getsource(i.locals['foo']) + self.assertEquals(inspected_source, source) From 7ca380d12e3e5b56653d5a321991b29dd87f63e7 Mon Sep 17 00:00:00 2001 From: Michael Mulley Date: Wed, 25 Mar 2015 17:40:46 -0400 Subject: [PATCH 15/19] Move linecache code to new file, use super() --- bpython/history.py | 72 ------------------------------------ bpython/patch_linecache.py | 75 ++++++++++++++++++++++++++++++++++++++ bpython/repl.py | 3 +- 3 files changed, 77 insertions(+), 73 deletions(-) create mode 100644 bpython/patch_linecache.py diff --git a/bpython/history.py b/bpython/history.py index a6f632f08..e08ec2684 100644 --- a/bpython/history.py +++ b/bpython/history.py @@ -25,7 +25,6 @@ from __future__ import unicode_literals import io -import linecache import os import stat from itertools import islice @@ -233,74 +232,3 @@ def append_reload_and_write(self, s, filename, encoding): # Make sure that entries contains at least one element. If the # file and s are empty, this can occur. self.entries = [''] - -class BPythonLinecache(dict): - """Replaces the cache dict in the standard-library linecache module, - to also remember (in an unerasable way) bpython console input.""" - - def __init__(self, *args, **kwargs): - dict.__init__(self, *args, **kwargs) - self.bpython_history = [] - - def is_bpython_filename(self, fname): - try: - return fname.startswith('' diff --git a/bpython/patch_linecache.py b/bpython/patch_linecache.py new file mode 100644 index 000000000..9bd935b50 --- /dev/null +++ b/bpython/patch_linecache.py @@ -0,0 +1,75 @@ +import linecache + +class BPythonLinecache(dict): + """Replaces the cache dict in the standard-library linecache module, + to also remember (in an unerasable way) bpython console input.""" + + def __init__(self, *args, **kwargs): + super(BPythonLinecache, self).__init__(*args, **kwargs) + self.bpython_history = [] + + def is_bpython_filename(self, fname): + try: + return fname.startswith('' diff --git a/bpython/repl.py b/bpython/repl.py index d71aba2c3..877bafc53 100644 --- a/bpython/repl.py +++ b/bpython/repl.py @@ -47,8 +47,9 @@ from bpython.clipboard import get_clipboard, CopyFailed from bpython.config import getpreferredencoding from bpython.formatter import Parenthesis -from bpython.history import History, filename_for_console_input +from bpython.history import History from bpython.paste import PasteHelper, PastePinnwand, PasteFailed +from bpython.patch_linecache import filename_for_console_input from bpython.translations import _, ngettext From 92e9b0b3b8b8a528af94a085df5e7a23df1697e2 Mon Sep 17 00:00:00 2001 From: Michael Mulley Date: Wed, 25 Mar 2015 17:46:36 -0400 Subject: [PATCH 16/19] No need to catch this AttributeError in test code --- bpython/test/test_interpreter.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/bpython/test/test_interpreter.py b/bpython/test/test_interpreter.py index 49c01d69a..43118096f 100644 --- a/bpython/test/test_interpreter.py +++ b/bpython/test/test_interpreter.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals +import linecache import sys try: @@ -20,11 +21,7 @@ def _last_console_filename(): """Returns the last 'filename' used for console input (as will be displayed in a traceback).""" - import linecache - try: - return '' % (len(linecache.cache.bpython_history) - 1) - except AttributeError: - return '' + return '' % (len(linecache.cache.bpython_history) - 1) class TestInterpreter(unittest.TestCase): def test_syntaxerror(self): From 80765a8017973c643566ab64f76371fa5bc4e126 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Mon, 20 Apr 2015 22:08:50 +0200 Subject: [PATCH 17/19] Fix bpdb name --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e34a95981..14151fabb 100755 --- a/setup.py +++ b/setup.py @@ -247,7 +247,7 @@ def initialize_options(self): 'bpython = bpython.curtsies:main', 'bpython-curses = bpython.cli:main', 'bpython-urwid = bpython.urwid:main [urwid]', - 'bpbd = bpdb:main' + 'bpdb = bpdb:main' ] } From bb1389adfaefa125f5637320229295a62c3d74f7 Mon Sep 17 00:00:00 2001 From: Sebastian Ramacher Date: Mon, 20 Apr 2015 23:37:59 +0200 Subject: [PATCH 18/19] Add Keywords --- data/bpython.desktop | 1 + 1 file changed, 1 insertion(+) diff --git a/data/bpython.desktop b/data/bpython.desktop index bdb121590..d28912bcc 100644 --- a/data/bpython.desktop +++ b/data/bpython.desktop @@ -7,3 +7,4 @@ Terminal=true Type=Application Categories=Development;Utility;ConsoleOnly; StartupNotify=true +Keywords=Python;REPL;interpreter; From a33048d500bdad5dd7232ac6f4d117fc9df8dd32 Mon Sep 17 00:00:00 2001 From: thekthuser Date: Sun, 26 Apr 2015 16:56:07 -0400 Subject: [PATCH 19/19] fixed bug #506 --- bpython/args.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bpython/args.py b/bpython/args.py index 6fd2b519c..91c8fc7fe 100644 --- a/bpython/args.py +++ b/bpython/args.py @@ -3,9 +3,10 @@ """ from __future__ import print_function +import code +import imp import os import sys -import code from optparse import OptionParser, OptionGroup from bpython import __version__ @@ -114,6 +115,9 @@ def exec_code(interpreter, args): source = sourcefile.read() old_argv, sys.argv = sys.argv, args sys.path.insert(0, os.path.abspath(os.path.dirname(args[0]))) + mod = imp.new_module('__console__') + sys.modules['__console__'] = mod + interpreter.locals = mod.__dict__ interpreter.locals['__file__'] = args[0] interpreter.runsource(source, args[0], 'exec') sys.argv = old_argv