Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow access to user_ns in prompt_manager #1151

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion IPython/core/prompts.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import sys import sys
import time import time


from string import Formatter

from IPython.config.configurable import Configurable from IPython.config.configurable import Configurable
from IPython.core import release from IPython.core import release
from IPython.utils import coloransi from IPython.utils import coloransi
Expand Down Expand Up @@ -241,6 +243,26 @@ def _lenlastline(s):
return 0 return 0
return len(s.splitlines()[-1]) return len(s.splitlines()[-1])



class UserNSFormatter(Formatter):
"""A Formatter that falls back on a shell's user_ns and __builtins__ for name resolution"""
def __init__(self, shell):
self.shell = shell

def get_value(self, key, args, kwargs):
# try regular formatting first:
try:
return Formatter.get_value(self, key, args, kwargs)
except Exception:
pass
# next, look in user_ns and builtins:
for container in (self.shell.user_ns, __builtins__):
if key in container:
return container[key]
# nothing found, put error message in its place
return "<ERROR: '%s' not found>" % key


class PromptManager(Configurable): class PromptManager(Configurable):
"""This is the primary interface for producing IPython's prompts.""" """This is the primary interface for producing IPython's prompts."""
shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
Expand Down Expand Up @@ -293,6 +315,7 @@ def __init__(self, shell, config=None):
self.color_scheme_table = coloransi.ColorSchemeTable([PColNoColors, self.color_scheme_table = coloransi.ColorSchemeTable([PColNoColors,
PColLinux, PColLightBG], self.color_scheme) PColLinux, PColLightBG], self.color_scheme)


self._formatter = UserNSFormatter(shell)
# Prepare templates & numbers of invisible characters # Prepare templates & numbers of invisible characters
self.update_prompt('in', self.in_template) self.update_prompt('in', self.in_template)
self.update_prompt('in2', self.in2_template) self.update_prompt('in2', self.in2_template)
Expand Down Expand Up @@ -357,7 +380,7 @@ def _render(self, name, color=True, **kwargs):
prompt = colors.prompt + self.templates[name] + colors.normal prompt = colors.prompt + self.templates[name] + colors.normal


# Fill in required fields # Fill in required fields
return prompt.format(**fmtargs) return self._formatter.format(prompt, **fmtargs)


def _render_rewrite(self, color=True): def _render_rewrite(self, color=True):
"""Render the ---> rewrite prompt.""" """Render the ---> rewrite prompt."""
Expand Down
19 changes: 19 additions & 0 deletions IPython/core/tests/test_prompts.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -38,6 +38,25 @@ def do_translate(template):


tt.check_pairs(do_translate, pairs) tt.check_pairs(do_translate, pairs)


def test_user_ns(self):
self.pm.color_scheme = 'NoColor'
ip.ex("foo='bar'")
self.pm.in_template = "In [{foo}]"
prompt = self.pm.render('in')
self.assertEquals(prompt, u'In [bar]')

def test_builtins(self):
self.pm.color_scheme = 'NoColor'
self.pm.in_template = "In [{int}]"
prompt = self.pm.render('in')
self.assertEquals(prompt, u"In [<type 'int'>]")

def test_undefined(self):
self.pm.color_scheme = 'NoColor'
self.pm.in_template = "In [{foo_dne}]"
prompt = self.pm.render('in')
self.assertEquals(prompt, u"In [<ERROR: 'foo_dne' not found>]")

def test_render(self): def test_render(self):
self.pm.in_template = r'\#>' self.pm.in_template = r'\#>'
self.assertEqual(self.pm.render('in',color=False), '%d>' % ip.execution_count) self.assertEqual(self.pm.render('in',color=False), '%d>' % ip.execution_count)