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 | 41 | line_cell_magic, on_off, needs_local_scope) |
|
42 | 42 | from IPython.testing.skipdoctest import skip_doctest |
|
43 | 43 | from IPython.utils import py3compat |
|
44 | from IPython.utils.contexts import preserve_keys | |
|
44 | 45 | from IPython.utils.io import capture_output |
|
45 | 46 | from IPython.utils.ipstruct import Struct |
|
46 | 47 | from IPython.utils.module_paths import find_mod |
@@ -466,6 +467,8 b' python-profiler package from non-free.""")' | |||
|
466 | 467 | return |
|
467 | 468 | |
|
468 | 469 | if filename.lower().endswith('.ipy'): |
|
470 | with preserve_keys(self.shell.user_ns, '__file__'): | |
|
471 | self.shell.user_ns['__file__'] = filename | |
|
469 | 472 | self.shell.safe_execfile_ipy(filename) |
|
470 | 473 | return |
|
471 | 474 | |
@@ -624,6 +627,7 b' python-profiler package from non-free.""")' | |||
|
624 | 627 | # worry about a possible KeyError. |
|
625 | 628 | prog_ns.pop('__name__', None) |
|
626 | 629 | |
|
630 | with preserve_keys(self.shell.user_ns, '__file__'): | |
|
627 | 631 | self.shell.user_ns.update(prog_ns) |
|
628 | 632 | finally: |
|
629 | 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 | 31 | from IPython.config.loader import Config |
|
32 | 32 | from IPython.core import pylabtools |
|
33 | 33 | from IPython.utils import py3compat |
|
34 | from IPython.utils.contexts import preserve_keys | |
|
34 | 35 | from IPython.utils.path import filefind |
|
35 | 36 | from IPython.utils.traitlets import ( |
|
36 | 37 | Unicode, Instance, List, Bool, CaselessStrEnum |
@@ -277,20 +278,18 b' class InteractiveShellApp(Configurable):' | |||
|
277 | 278 | sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ] |
|
278 | 279 | try: |
|
279 | 280 | if os.path.isfile(full_filename): |
|
280 | if full_filename.endswith('.ipy'): | |
|
281 | 281 |
|
|
282 | 282 |
|
|
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 | 288 | self.shell.safe_execfile_ipy(full_filename) |
|
284 | 289 | else: |
|
285 | 290 | # default to python, even without extension |
|
286 | self.log.info("Running file in user namespace: %s" % | |
|
287 |
|
|
|
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__'] | |
|
291 | self.shell.safe_execfile(full_filename, | |
|
292 | self.shell.user_ns) | |
|
294 | 293 | finally: |
|
295 | 294 | sys.argv = save_argv |
|
296 | 295 |
General Comments 0
You need to be logged in to leave comments.
Login now