##// END OF EJS Templates
Use user_ns as global namespace if it is passed without user_module, and add test for pickling interactively defined objects....
Thomas Kluyver -
Show More
@@ -888,19 +888,13 b' class InteractiveShell(SingletonConfigurable, Magic):'
888 # should start with "import __builtin__" (note, no 's') which will
888 # should start with "import __builtin__" (note, no 's') which will
889 # definitely give you a module. Yeah, it's somewhat confusing:-(.
889 # definitely give you a module. Yeah, it's somewhat confusing:-(.
890
890
891 # These routines return properly built dicts as needed by the rest of
891 # These routines return a properly built module and dict as needed by
892 # the code, and can also be used by extension writers to generate
892 # the rest of the code, and can also be used by extension writers to
893 # properly initialized namespaces.
893 # generate properly initialized namespaces.
894 self.user_module = self.prepare_user_module(user_module)
894 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
895
895
896 if user_ns is None:
896 # A record of hidden variables we have added to the user namespace, so
897 user_ns = self.user_module.__dict__
897 # we can list later only variables defined in actual interactive use.
898 self.user_ns = user_ns
899
900 # An auxiliary namespace that checks what parts of the user_ns were
901 # loaded at startup, so we can list later only variables defined in
902 # actual interactive use. Since it is always a subset of user_ns, it
903 # doesn't need to be separately tracked in the ns_table.
904 self.user_ns_hidden = set()
898 self.user_ns_hidden = set()
905
899
906 # Now that FakeModule produces a real module, we've run into a nasty
900 # Now that FakeModule produces a real module, we've run into a nasty
@@ -943,20 +937,38 b' class InteractiveShell(SingletonConfigurable, Magic):'
943 def user_global_ns(self):
937 def user_global_ns(self):
944 return self.user_module.__dict__
938 return self.user_module.__dict__
945
939
946 def prepare_user_module(self, user_module=None):
940 def prepare_user_module(self, user_module=None, user_ns=None):
947 """Prepares a module for use as the interactive __main__ module in
941 """Prepare the module and namespace in which user code will be run.
948 which user code is run.
942
943 When IPython is started normally, both parameters are None: a new module
944 is created automatically, and its __dict__ used as the namespace.
945
946 If only user_module is provided, its __dict__ is used as the namespace.
947 If only user_ns is provided, a dummy module is created, and user_ns
948 becomes the global namespace. If both are provided (as they may be
949 when embedding), user_ns is the local namespace, and user_module
950 provides the global namespace.
949
951
950 Parameters
952 Parameters
951 ----------
953 ----------
952 user_module : module, optional
954 user_module : module, optional
953 The current user module in which IPython is being run. If None,
955 The current user module in which IPython is being run. If None,
954 a clean module will be created.
956 a clean module will be created.
957 user_ns : dict, optional
958 A namespace in which to run interactive commands.
955
959
956 Returns
960 Returns
957 -------
961 -------
958 A module object.
962 A tuple of user_module and user_ns, each properly initialised.
959 """
963 """
964 if user_module is None and user_ns is not None:
965 user_ns.setdefault("__name__", "__main__")
966 class DummyMod(object):
967 "A dummy module used for IPython's interactive namespace."
968 pass
969 user_module = DummyMod()
970 user_module.__dict__ = user_ns
971
960 if user_module is None:
972 if user_module is None:
961 user_module = types.ModuleType("__main__",
973 user_module = types.ModuleType("__main__",
962 doc="Automatically created module for IPython interactive environment")
974 doc="Automatically created module for IPython interactive environment")
@@ -967,7 +979,10 b' class InteractiveShell(SingletonConfigurable, Magic):'
967 user_module.__dict__.setdefault('__builtin__',__builtin__)
979 user_module.__dict__.setdefault('__builtin__',__builtin__)
968 user_module.__dict__.setdefault('__builtins__',__builtin__)
980 user_module.__dict__.setdefault('__builtins__',__builtin__)
969
981
970 return user_module
982 if user_ns is None:
983 user_ns = user_module.__dict__
984
985 return user_module, user_ns
971
986
972 def init_sys_modules(self):
987 def init_sys_modules(self):
973 # We need to insert into sys.modules something that looks like a
988 # We need to insert into sys.modules something that looks like a
@@ -1075,10 +1090,13 b' class InteractiveShell(SingletonConfigurable, Magic):'
1075 # The main execution namespaces must be cleared very carefully,
1090 # The main execution namespaces must be cleared very carefully,
1076 # skipping the deletion of the builtin-related keys, because doing so
1091 # skipping the deletion of the builtin-related keys, because doing so
1077 # would cause errors in many object's __del__ methods.
1092 # would cause errors in many object's __del__ methods.
1078 for ns in [self.user_ns, self.user_global_ns]:
1093 if self.user_ns is not self.user_global_ns:
1094 self.user_ns.clear()
1095 ns = self.user_global_ns
1079 drop_keys = set(ns.keys())
1096 drop_keys = set(ns.keys())
1080 drop_keys.discard('__builtin__')
1097 drop_keys.discard('__builtin__')
1081 drop_keys.discard('__builtins__')
1098 drop_keys.discard('__builtins__')
1099 drop_keys.discard('__name__')
1082 for k in drop_keys:
1100 for k in drop_keys:
1083 del ns[k]
1101 del ns[k]
1084
1102
@@ -25,6 +25,7 b' import shutil'
25 import tempfile
25 import tempfile
26 import unittest
26 import unittest
27 from os.path import join
27 from os.path import join
28 import sys
28 from StringIO import StringIO
29 from StringIO import StringIO
29
30
30 from IPython.testing import decorators as dec
31 from IPython.testing import decorators as dec
@@ -128,6 +129,7 b' class InteractiveShellTestCase(unittest.TestCase):'
128 f = IPython.core.formatters.PlainTextFormatter()
129 f = IPython.core.formatters.PlainTextFormatter()
129 f([Spam(),Spam()])
130 f([Spam(),Spam()])
130
131
132
131 def test_future_flags(self):
133 def test_future_flags(self):
132 """Check that future flags are used for parsing code (gh-777)"""
134 """Check that future flags are used for parsing code (gh-777)"""
133 ip = get_ipython()
135 ip = get_ipython()
@@ -152,6 +154,37 b' class InteractiveShellTestCase(unittest.TestCase):'
152 # Reset compiler flags so we don't mess up other tests.
154 # Reset compiler flags so we don't mess up other tests.
153 ip.compile.reset_compiler_flags()
155 ip.compile.reset_compiler_flags()
154
156
157 def test_can_pickle(self):
158 "Can we pickle objects defined interactively (GH-29)"
159 ip = get_ipython()
160 ip.reset()
161 ip.run_cell(("class Mylist(list):\n"
162 " def __init__(self,x=[]):\n"
163 " list.__init__(self,x)"))
164 ip.run_cell("w=Mylist([1,2,3])")
165
166 from cPickle import dumps
167
168 # We need to swap in our main module - this is only necessary
169 # inside the test framework, because IPython puts the interactive module
170 # in place (but the test framework undoes this).
171 _main = sys.modules['__main__']
172 sys.modules['__main__'] = ip.user_module
173 try:
174 res = dumps(ip.user_ns["w"])
175 finally:
176 sys.modules['__main__'] = _main
177 self.assertTrue(isinstance(res, bytes))
178
179 def test_global_ns(self):
180 "Code in functions must be able to access variables outside them."
181 ip = get_ipython()
182 ip.run_cell("a = 10")
183 ip.run_cell(("def f(x):"
184 " return x + a"))
185 ip.run_cell("b = f(12)")
186 self.assertEqual(ip.user_ns["b"], 22)
187
155 def test_bad_custom_tb(self):
188 def test_bad_custom_tb(self):
156 """Check that InteractiveShell is protected from bad custom exception handlers"""
189 """Check that InteractiveShell is protected from bad custom exception handlers"""
157 ip = get_ipython()
190 ip = get_ipython()
@@ -206,7 +206,6 b' def start_ipython():'
206 # doctest machinery would miss them.
206 # doctest machinery would miss them.
207 shell.system = py3compat.MethodType(xsys, shell)
207 shell.system = py3compat.MethodType(xsys, shell)
208
208
209
210 shell._showtraceback = py3compat.MethodType(_showtraceback, shell)
209 shell._showtraceback = py3compat.MethodType(_showtraceback, shell)
211
210
212 # IPython is ready, now clean up some global state...
211 # IPython is ready, now clean up some global state...
@@ -271,6 +271,8 b' class DocTestCase(doctests.DocTestCase):'
271 # for IPython examples *only*, we swap the globals with the ipython
271 # for IPython examples *only*, we swap the globals with the ipython
272 # namespace, after updating it with the globals (which doctest
272 # namespace, after updating it with the globals (which doctest
273 # fills with the necessary info from the module being tested).
273 # fills with the necessary info from the module being tested).
274 self.user_ns_orig = {}
275 self.user_ns_orig.update(_ip.user_ns)
274 _ip.user_ns.update(self._dt_test.globs)
276 _ip.user_ns.update(self._dt_test.globs)
275 self._dt_test.globs = _ip.user_ns
277 self._dt_test.globs = _ip.user_ns
276 # IPython must protect the _ key in the namespace (it can't exist)
278 # IPython must protect the _ key in the namespace (it can't exist)
@@ -286,6 +288,8 b' class DocTestCase(doctests.DocTestCase):'
286 # teardown doesn't destroy the ipython namespace
288 # teardown doesn't destroy the ipython namespace
287 if isinstance(self._dt_test.examples[0],IPExample):
289 if isinstance(self._dt_test.examples[0],IPExample):
288 self._dt_test.globs = self._dt_test_globs_ori
290 self._dt_test.globs = self._dt_test_globs_ori
291 _ip.user_ns.clear()
292 _ip.user_ns.update(self.user_ns_orig)
289 # Restore the behavior of the '_' key in the user namespace to
293 # Restore the behavior of the '_' key in the user namespace to
290 # normal after each doctest, so that unittests behave normally
294 # normal after each doctest, so that unittests behave normally
291 _ip.user_ns.protect_underscore = False
295 _ip.user_ns.protect_underscore = False
General Comments 0
You need to be logged in to leave comments. Login now