Show More
@@ -0,0 +1,71 b'' | |||||
|
1 | # encoding: utf-8 | |||
|
2 | """ | |||
|
3 | Context managers for temporarily updating dictionaries. | |||
|
4 | ||||
|
5 | Authors: | |||
|
6 | ||||
|
7 | * Bradley Froehle | |||
|
8 | """ | |||
|
9 | ||||
|
10 | #----------------------------------------------------------------------------- | |||
|
11 | # Copyright (C) 2012 The IPython Development Team | |||
|
12 | # | |||
|
13 | # Distributed under the terms of the BSD License. The full license is in | |||
|
14 | # the file COPYING, distributed as part of this software. | |||
|
15 | #----------------------------------------------------------------------------- | |||
|
16 | ||||
|
17 | #----------------------------------------------------------------------------- | |||
|
18 | # Code | |||
|
19 | #----------------------------------------------------------------------------- | |||
|
20 | ||||
|
21 | class preserve_keys(object): | |||
|
22 | """Preserve a set of keys in a dictionary. | |||
|
23 | ||||
|
24 | Upon entering the context manager the current values of the keys | |||
|
25 | will be saved. Upon exiting, the dictionary will be updated to | |||
|
26 | restore the original value of the preserved keys. Preserved keys | |||
|
27 | which did not exist when entering the context manager will be | |||
|
28 | deleted. | |||
|
29 | ||||
|
30 | Example | |||
|
31 | ------- | |||
|
32 | ||||
|
33 | >>> d = {'a': 1, 'b': 2, 'c': 3} | |||
|
34 | >>> with preserve_keys(d, 'b', 'c', 'd'): | |||
|
35 | ... del d['a'] | |||
|
36 | ... del d['b'] # will be reset to 2 | |||
|
37 | ... d['c'] = None # will be reset to 3 | |||
|
38 | ... d['d'] = 4 # will be deleted | |||
|
39 | ... d['e'] = 5 | |||
|
40 | ... print(sorted(d.items())) | |||
|
41 | ... | |||
|
42 | [('c', None), ('d', 4), ('e', 5)] | |||
|
43 | >>> print(sorted(d.items())) | |||
|
44 | [('b', 2), ('c', 3), ('e', 5)] | |||
|
45 | """ | |||
|
46 | ||||
|
47 | def __init__(self, dictionary, *keys): | |||
|
48 | self.dictionary = dictionary | |||
|
49 | self.keys = keys | |||
|
50 | ||||
|
51 | def __enter__(self): | |||
|
52 | # Actions to perform upon exiting. | |||
|
53 | to_delete = [] | |||
|
54 | to_update = {} | |||
|
55 | ||||
|
56 | d = self.dictionary | |||
|
57 | for k in self.keys: | |||
|
58 | if k in d: | |||
|
59 | to_update[k] = d[k] | |||
|
60 | else: | |||
|
61 | to_delete.append(k) | |||
|
62 | ||||
|
63 | self.to_delete = to_delete | |||
|
64 | self.to_update = to_update | |||
|
65 | ||||
|
66 | def __exit__(self, *exc_info): | |||
|
67 | d = self.dictionary | |||
|
68 | ||||
|
69 | for k in self.to_delete: | |||
|
70 | d.pop(k, None) | |||
|
71 | d.update(self.to_update) |
@@ -41,6 +41,7 b' from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,' | |||||
41 | line_cell_magic, on_off, needs_local_scope) |
|
41 | line_cell_magic, on_off, needs_local_scope) | |
42 | from IPython.testing.skipdoctest import skip_doctest |
|
42 | from IPython.testing.skipdoctest import skip_doctest | |
43 | from IPython.utils import py3compat |
|
43 | from IPython.utils import py3compat | |
|
44 | from IPython.utils.contexts import preserve_keys | |||
44 | from IPython.utils.io import capture_output |
|
45 | from IPython.utils.io import capture_output | |
45 | from IPython.utils.ipstruct import Struct |
|
46 | from IPython.utils.ipstruct import Struct | |
46 | from IPython.utils.module_paths import find_mod |
|
47 | from IPython.utils.module_paths import find_mod | |
@@ -466,6 +467,8 b' python-profiler package from non-free.""")' | |||||
466 | return |
|
467 | return | |
467 |
|
468 | |||
468 | if filename.lower().endswith('.ipy'): |
|
469 | if filename.lower().endswith('.ipy'): | |
|
470 | with preserve_keys(self.shell.user_ns, '__file__'): | |||
|
471 | self.shell.user_ns['__file__'] = filename | |||
469 | self.shell.safe_execfile_ipy(filename) |
|
472 | self.shell.safe_execfile_ipy(filename) | |
470 | return |
|
473 | return | |
471 |
|
474 | |||
@@ -624,6 +627,7 b' python-profiler package from non-free.""")' | |||||
624 | # worry about a possible KeyError. |
|
627 | # worry about a possible KeyError. | |
625 | prog_ns.pop('__name__', None) |
|
628 | prog_ns.pop('__name__', None) | |
626 |
|
629 | |||
|
630 | with preserve_keys(self.shell.user_ns, '__file__'): | |||
627 | self.shell.user_ns.update(prog_ns) |
|
631 | self.shell.user_ns.update(prog_ns) | |
628 | finally: |
|
632 | finally: | |
629 | # It's a bit of a mystery why, but __builtins__ can change from |
|
633 | # It's a bit of a mystery why, but __builtins__ can change from |
@@ -31,6 +31,7 b' from IPython.config.configurable import Configurable' | |||||
31 | from IPython.config.loader import Config |
|
31 | from IPython.config.loader import Config | |
32 | from IPython.core import pylabtools |
|
32 | from IPython.core import pylabtools | |
33 | from IPython.utils import py3compat |
|
33 | from IPython.utils import py3compat | |
|
34 | from IPython.utils.contexts import preserve_keys | |||
34 | from IPython.utils.path import filefind |
|
35 | from IPython.utils.path import filefind | |
35 | from IPython.utils.traitlets import ( |
|
36 | from IPython.utils.traitlets import ( | |
36 | Unicode, Instance, List, Bool, CaselessStrEnum |
|
37 | Unicode, Instance, List, Bool, CaselessStrEnum | |
@@ -277,20 +278,18 b' class InteractiveShellApp(Configurable):' | |||||
277 | sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ] |
|
278 | sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ] | |
278 | try: |
|
279 | try: | |
279 | if os.path.isfile(full_filename): |
|
280 | if os.path.isfile(full_filename): | |
280 | if full_filename.endswith('.ipy'): |
|
|||
281 |
|
|
281 | self.log.info("Running file in user namespace: %s" % | |
282 |
|
|
282 | full_filename) | |
|
283 | # Ensure that __file__ is always defined to match Python | |||
|
284 | # behavior. | |||
|
285 | with preserve_keys(self.shell.user_ns, '__file__'): | |||
|
286 | self.shell.user_ns['__file__'] = fname | |||
|
287 | if full_filename.endswith('.ipy'): | |||
283 | self.shell.safe_execfile_ipy(full_filename) |
|
288 | self.shell.safe_execfile_ipy(full_filename) | |
284 | else: |
|
289 | else: | |
285 | # default to python, even without extension |
|
290 | # default to python, even without extension | |
286 | self.log.info("Running file in user namespace: %s" % |
|
291 | self.shell.safe_execfile(full_filename, | |
287 |
|
|
292 | self.shell.user_ns) | |
288 | # Ensure that __file__ is always defined to match Python behavior |
|
|||
289 | self.shell.user_ns['__file__'] = fname |
|
|||
290 | try: |
|
|||
291 | self.shell.safe_execfile(full_filename, self.shell.user_ns) |
|
|||
292 | finally: |
|
|||
293 | del self.shell.user_ns['__file__'] |
|
|||
294 | finally: |
|
293 | finally: | |
295 | sys.argv = save_argv |
|
294 | sys.argv = save_argv | |
296 |
|
295 |
General Comments 0
You need to be logged in to leave comments.
Login now