Skip to content

Commit

Permalink
Start converting user namespace machinery to use a module.
Browse files Browse the repository at this point in the history
  • Loading branch information
takluyver committed Nov 27, 2011
1 parent 5397fc8 commit 0f99efe
Showing 1 changed file with 40 additions and 76 deletions.
116 changes: 40 additions & 76 deletions IPython/core/interactiveshell.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ def profile(self):
_post_execute = Instance(dict) _post_execute = Instance(dict)


def __init__(self, config=None, ipython_dir=None, profile_dir=None, def __init__(self, config=None, ipython_dir=None, profile_dir=None,
user_ns=None, user_global_ns=None, user_module=None, user_local_ns=None,
custom_exceptions=((), None)): custom_exceptions=((), None)):


# This is where traits with a config_key argument are updated # This is where traits with a config_key argument are updated
Expand All @@ -387,7 +387,7 @@ def __init__(self, config=None, ipython_dir=None, profile_dir=None,
self.init_environment() self.init_environment()


# Create namespaces (user_ns, user_global_ns, etc.) # Create namespaces (user_ns, user_global_ns, etc.)
self.init_create_namespaces(user_ns, user_global_ns) self.init_create_namespaces(user_module, user_local_ns)
# This has to be done after init_create_namespaces because it uses # This has to be done after init_create_namespaces because it uses
# something in self.user_ns, but before init_sys_modules, which # something in self.user_ns, but before init_sys_modules, which
# is the first thing to modify sys. # is the first thing to modify sys.
Expand Down Expand Up @@ -860,7 +860,7 @@ def debugger(self,force=False):
# Things related to IPython's various namespaces # Things related to IPython's various namespaces
#------------------------------------------------------------------------- #-------------------------------------------------------------------------


def init_create_namespaces(self, user_ns=None, user_global_ns=None): def init_create_namespaces(self, user_module=None, user_local_ns=None):
# Create the namespace where the user will operate. user_ns is # Create the namespace where the user will operate. user_ns is
# normally the only one used, and it is passed to the exec calls as # normally the only one used, and it is passed to the exec calls as
# the locals argument. But we do carry a user_global_ns namespace # the locals argument. But we do carry a user_global_ns namespace
Expand Down Expand Up @@ -897,19 +897,17 @@ def init_create_namespaces(self, user_ns=None, user_global_ns=None):
# These routines return properly built dicts as needed by the rest of # These routines return properly built dicts as needed by the rest of
# the code, and can also be used by extension writers to generate # the code, and can also be used by extension writers to generate
# properly initialized namespaces. # properly initialized namespaces.
user_ns, user_global_ns = self.make_user_namespaces(user_ns, self.user_module = self.prepare_user_module(user_module)
user_global_ns)


# Assign namespaces if user_local_ns is None:
# This is the namespace where all normal user variables live user_local_ns = self.user_module.__dict__
self.user_ns = user_ns self.user_local_ns = user_local_ns
self.user_global_ns = user_global_ns


# An auxiliary namespace that checks what parts of the user_ns were # An auxiliary namespace that checks what parts of the user_ns were
# loaded at startup, so we can list later only variables defined in # loaded at startup, so we can list later only variables defined in
# actual interactive use. Since it is always a subset of user_ns, it # actual interactive use. Since it is always a subset of user_ns, it
# doesn't need to be separately tracked in the ns_table. # doesn't need to be separately tracked in the ns_table.
self.user_ns_hidden = {} self.user_ns_hidden = set()


# A namespace to keep track of internal data structures to prevent # A namespace to keep track of internal data structures to prevent
# them from cluttering user-visible stuff. Will be updated later # them from cluttering user-visible stuff. Will be updated later
Expand Down Expand Up @@ -946,8 +944,8 @@ def init_create_namespaces(self, user_ns=None, user_global_ns=None):


# A table holding all the namespaces IPython deals with, so that # A table holding all the namespaces IPython deals with, so that
# introspection facilities can search easily. # introspection facilities can search easily.
self.ns_table = {'user':user_ns, self.ns_table = {'user_global':user_module.__dict__,
'user_global':user_global_ns, 'user_local':user_local_ns,
'internal':self.internal_ns, 'internal':self.internal_ns,
'builtin':builtin_mod.__dict__ 'builtin':builtin_mod.__dict__
} }
Expand All @@ -958,66 +956,37 @@ def init_create_namespaces(self, user_ns=None, user_global_ns=None):
# user_global_ns, can NOT be listed here, as clearing them blindly # user_global_ns, can NOT be listed here, as clearing them blindly
# causes errors in object __del__ methods. Instead, the reset() method # causes errors in object __del__ methods. Instead, the reset() method
# clears them manually and carefully. # clears them manually and carefully.
self.ns_refs_table = [ self.user_ns_hidden, self.ns_refs_table = [ self.internal_ns, self._main_ns_cache ]
self.internal_ns, self._main_ns_cache ]

@property
def make_user_namespaces(self, user_ns=None, user_global_ns=None): def user_global_ns(self):
"""Return a valid local and global user interactive namespaces. return self.user_module.__dict__
This builds a dict with the minimal information needed to operate as a
valid IPython user namespace, which you can pass to the various
embedding classes in ipython. The default implementation returns the
same dict for both the locals and the globals to allow functions to
refer to variables in the namespace. Customized implementations can
return different dicts. The locals dictionary can actually be anything
following the basic mapping protocol of a dict, but the globals dict
must be a true dict, not even a subclass. It is recommended that any
custom object for the locals namespace synchronize with the globals
dict somehow.


Raises TypeError if the provided globals namespace is not a true dict. def prepare_user_module(self, user_module=None):
"""Prepares a module for use as the interactive __main__ module in
which user code is run.
Parameters Parameters
---------- ----------
user_ns : dict-like, optional user_module : module, optional
The current user namespace. The items in this namespace should The current user module in which IPython is being run. If None,
be included in the output. If None, an appropriate blank a clean module will be created.
namespace should be created.
user_global_ns : dict, optional
The current user global namespace. The items in this namespace
should be included in the output. If None, an appropriate
blank namespace should be created.
Returns Returns
------- -------
A pair of dictionary-like object to be used as the local namespace A module object.
of the interpreter and a dict to be used as the global namespace.
""" """

if user_module is None:

user_module = types.ModuleType("__main__",
doc="Automatically created module for IPython interactive environment")

# We must ensure that __builtin__ (without the final 's') is always # We must ensure that __builtin__ (without the final 's') is always
# available and pointing to the __builtin__ *module*. For more details: # available and pointing to the __builtin__ *module*. For more details:
# http://mail.python.org/pipermail/python-dev/2001-April/014068.html # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
user_module.__dict__.setdefault('__builtin__',__builtin__)
user_module.__dict__.setdefault('__builtins__',__builtin__)


if user_ns is None: return user_module
# Set __name__ to __main__ to better match the behavior of the
# normal interpreter.
user_ns = {'__name__' :'__main__',
py3compat.builtin_mod_name: builtin_mod,
'__builtins__' : builtin_mod,
}
else:
user_ns.setdefault('__name__','__main__')
user_ns.setdefault(py3compat.builtin_mod_name,builtin_mod)
user_ns.setdefault('__builtins__',builtin_mod)

if user_global_ns is None:
user_global_ns = user_ns
if type(user_global_ns) is not dict:
raise TypeError("user_global_ns must be a true dict; got %r"
% type(user_global_ns))

return user_ns, user_global_ns


def init_sys_modules(self): def init_sys_modules(self):
# We need to insert into sys.modules something that looks like a # We need to insert into sys.modules something that looks like a
Expand All @@ -1036,13 +1005,8 @@ def init_sys_modules(self):
# embedded in). # embedded in).


# This is overridden in the InteractiveShellEmbed subclass to a no-op. # This is overridden in the InteractiveShellEmbed subclass to a no-op.

main_name = self.user_module.__name__
try: sys.modules[main_name] = self.user_module
main_name = self.user_ns['__name__']
except KeyError:
raise KeyError('user_ns dictionary MUST have a "__name__" key')
else:
sys.modules[main_name] = FakeModule(self.user_ns)


def init_user_ns(self): def init_user_ns(self):
"""Initialize all user-visible namespaces to their minimum defaults. """Initialize all user-visible namespaces to their minimum defaults.
Expand Down Expand Up @@ -1073,8 +1037,8 @@ def init_user_ns(self):


# For more details: # For more details:
# http://mail.python.org/pipermail/python-dev/2001-April/014068.html # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
ns = dict(__builtin__ = builtin_mod) ns = dict()

# Put 'help' in the user namespace # Put 'help' in the user namespace
try: try:
from site import _Helper from site import _Helper
Expand Down Expand Up @@ -1109,7 +1073,7 @@ def init_user_ns(self):
# stuff, not our variables. # stuff, not our variables.


# Finally, update the real user's namespace # Finally, update the real user's namespace
self.user_ns.update(ns) self.user_local_ns.update(ns)


def reset(self, new_session=True): def reset(self, new_session=True):
"""Clear all internal namespaces, and attempt to release references to """Clear all internal namespaces, and attempt to release references to
Expand Down Expand Up @@ -1260,13 +1224,13 @@ def push(self, variables, interactive=True):
self.user_ns.update(vdict) self.user_ns.update(vdict)


# And configure interactive visibility # And configure interactive visibility
config_ns = self.user_ns_hidden user_ns_hidden = self.user_ns_hidden
if interactive: if interactive:
for name, val in vdict.iteritems(): for name in vdict:
config_ns.pop(name, None) user_ns_hidden.discard(name)
else: else:
for name,val in vdict.iteritems(): for name in vdict:
config_ns[name] = val user_ns_hidden.add(name)


def drop_by_id(self, variables): def drop_by_id(self, variables):
"""Remove a dict of variables from the user namespace, if they are the """Remove a dict of variables from the user namespace, if they are the
Expand All @@ -1284,7 +1248,7 @@ def drop_by_id(self, variables):
for name, obj in variables.iteritems(): for name, obj in variables.iteritems():
if name in self.user_ns and self.user_ns[name] is obj: if name in self.user_ns and self.user_ns[name] is obj:
del self.user_ns[name] del self.user_ns[name]
self.user_ns_hidden.pop(name, None) self.user_ns_hidden.discard(name)


#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# Things related to object introspection # Things related to object introspection
Expand Down

0 comments on commit 0f99efe

Please sign in to comment.