##// END OF EJS Templates
Miscellaneous Python 3 fixes
Thomas Kluyver -
Show More
@@ -1,821 +1,821 b''
1 """A simple configuration system.
1 """A simple configuration system.
2
2
3 Inheritance diagram:
3 Inheritance diagram:
4
4
5 .. inheritance-diagram:: IPython.config.loader
5 .. inheritance-diagram:: IPython.config.loader
6 :parts: 3
6 :parts: 3
7
7
8 Authors
8 Authors
9 -------
9 -------
10 * Brian Granger
10 * Brian Granger
11 * Fernando Perez
11 * Fernando Perez
12 * Min RK
12 * Min RK
13 """
13 """
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Copyright (C) 2008-2011 The IPython Development Team
16 # Copyright (C) 2008-2011 The IPython Development Team
17 #
17 #
18 # Distributed under the terms of the BSD License. The full license is in
18 # Distributed under the terms of the BSD License. The full license is in
19 # the file COPYING, distributed as part of this software.
19 # the file COPYING, distributed as part of this software.
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 import argparse
26 import argparse
27 import copy
27 import copy
28 import os
28 import os
29 import re
29 import re
30 import sys
30 import sys
31
31
32 from IPython.utils.path import filefind, get_ipython_dir
32 from IPython.utils.path import filefind, get_ipython_dir
33 from IPython.utils import py3compat, warn
33 from IPython.utils import py3compat, warn
34 from IPython.utils.encoding import DEFAULT_ENCODING
34 from IPython.utils.encoding import DEFAULT_ENCODING
35 from IPython.utils.py3compat import builtin_mod, unicode_type, iteritems
35 from IPython.utils.py3compat import builtin_mod, unicode_type, iteritems
36 from IPython.utils.traitlets import HasTraits, List, Any, TraitError
36 from IPython.utils.traitlets import HasTraits, List, Any, TraitError
37
37
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39 # Exceptions
39 # Exceptions
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41
41
42
42
43 class ConfigError(Exception):
43 class ConfigError(Exception):
44 pass
44 pass
45
45
46 class ConfigLoaderError(ConfigError):
46 class ConfigLoaderError(ConfigError):
47 pass
47 pass
48
48
49 class ConfigFileNotFound(ConfigError):
49 class ConfigFileNotFound(ConfigError):
50 pass
50 pass
51
51
52 class ArgumentError(ConfigLoaderError):
52 class ArgumentError(ConfigLoaderError):
53 pass
53 pass
54
54
55 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
56 # Argparse fix
56 # Argparse fix
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58
58
59 # Unfortunately argparse by default prints help messages to stderr instead of
59 # Unfortunately argparse by default prints help messages to stderr instead of
60 # stdout. This makes it annoying to capture long help screens at the command
60 # stdout. This makes it annoying to capture long help screens at the command
61 # line, since one must know how to pipe stderr, which many users don't know how
61 # line, since one must know how to pipe stderr, which many users don't know how
62 # to do. So we override the print_help method with one that defaults to
62 # to do. So we override the print_help method with one that defaults to
63 # stdout and use our class instead.
63 # stdout and use our class instead.
64
64
65 class ArgumentParser(argparse.ArgumentParser):
65 class ArgumentParser(argparse.ArgumentParser):
66 """Simple argparse subclass that prints help to stdout by default."""
66 """Simple argparse subclass that prints help to stdout by default."""
67
67
68 def print_help(self, file=None):
68 def print_help(self, file=None):
69 if file is None:
69 if file is None:
70 file = sys.stdout
70 file = sys.stdout
71 return super(ArgumentParser, self).print_help(file)
71 return super(ArgumentParser, self).print_help(file)
72
72
73 print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__
73 print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__
74
74
75 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
76 # Config class for holding config information
76 # Config class for holding config information
77 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
78
78
79 class LazyConfigValue(HasTraits):
79 class LazyConfigValue(HasTraits):
80 """Proxy object for exposing methods on configurable containers
80 """Proxy object for exposing methods on configurable containers
81
81
82 Exposes:
82 Exposes:
83
83
84 - append, extend, insert on lists
84 - append, extend, insert on lists
85 - update on dicts
85 - update on dicts
86 - update, add on sets
86 - update, add on sets
87 """
87 """
88
88
89 _value = None
89 _value = None
90
90
91 # list methods
91 # list methods
92 _extend = List()
92 _extend = List()
93 _prepend = List()
93 _prepend = List()
94
94
95 def append(self, obj):
95 def append(self, obj):
96 self._extend.append(obj)
96 self._extend.append(obj)
97
97
98 def extend(self, other):
98 def extend(self, other):
99 self._extend.extend(other)
99 self._extend.extend(other)
100
100
101 def prepend(self, other):
101 def prepend(self, other):
102 """like list.extend, but for the front"""
102 """like list.extend, but for the front"""
103 self._prepend[:0] = other
103 self._prepend[:0] = other
104
104
105 _inserts = List()
105 _inserts = List()
106 def insert(self, index, other):
106 def insert(self, index, other):
107 if not isinstance(index, int):
107 if not isinstance(index, int):
108 raise TypeError("An integer is required")
108 raise TypeError("An integer is required")
109 self._inserts.append((index, other))
109 self._inserts.append((index, other))
110
110
111 # dict methods
111 # dict methods
112 # update is used for both dict and set
112 # update is used for both dict and set
113 _update = Any()
113 _update = Any()
114 def update(self, other):
114 def update(self, other):
115 if self._update is None:
115 if self._update is None:
116 if isinstance(other, dict):
116 if isinstance(other, dict):
117 self._update = {}
117 self._update = {}
118 else:
118 else:
119 self._update = set()
119 self._update = set()
120 self._update.update(other)
120 self._update.update(other)
121
121
122 # set methods
122 # set methods
123 def add(self, obj):
123 def add(self, obj):
124 self.update({obj})
124 self.update({obj})
125
125
126 def get_value(self, initial):
126 def get_value(self, initial):
127 """construct the value from the initial one
127 """construct the value from the initial one
128
128
129 after applying any insert / extend / update changes
129 after applying any insert / extend / update changes
130 """
130 """
131 if self._value is not None:
131 if self._value is not None:
132 return self._value
132 return self._value
133 value = copy.deepcopy(initial)
133 value = copy.deepcopy(initial)
134 if isinstance(value, list):
134 if isinstance(value, list):
135 for idx, obj in self._inserts:
135 for idx, obj in self._inserts:
136 value.insert(idx, obj)
136 value.insert(idx, obj)
137 value[:0] = self._prepend
137 value[:0] = self._prepend
138 value.extend(self._extend)
138 value.extend(self._extend)
139
139
140 elif isinstance(value, dict):
140 elif isinstance(value, dict):
141 if self._update:
141 if self._update:
142 value.update(self._update)
142 value.update(self._update)
143 elif isinstance(value, set):
143 elif isinstance(value, set):
144 if self._update:
144 if self._update:
145 value.update(self._update)
145 value.update(self._update)
146 self._value = value
146 self._value = value
147 return value
147 return value
148
148
149 def to_dict(self):
149 def to_dict(self):
150 """return JSONable dict form of my data
150 """return JSONable dict form of my data
151
151
152 Currently update as dict or set, extend, prepend as lists, and inserts as list of tuples.
152 Currently update as dict or set, extend, prepend as lists, and inserts as list of tuples.
153 """
153 """
154 d = {}
154 d = {}
155 if self._update:
155 if self._update:
156 d['update'] = self._update
156 d['update'] = self._update
157 if self._extend:
157 if self._extend:
158 d['extend'] = self._extend
158 d['extend'] = self._extend
159 if self._prepend:
159 if self._prepend:
160 d['prepend'] = self._prepend
160 d['prepend'] = self._prepend
161 elif self._inserts:
161 elif self._inserts:
162 d['inserts'] = self._inserts
162 d['inserts'] = self._inserts
163 return d
163 return d
164
164
165
165
166 class Config(dict):
166 class Config(dict):
167 """An attribute based dict that can do smart merges."""
167 """An attribute based dict that can do smart merges."""
168
168
169 def __init__(self, *args, **kwds):
169 def __init__(self, *args, **kwds):
170 dict.__init__(self, *args, **kwds)
170 dict.__init__(self, *args, **kwds)
171 # This sets self.__dict__ = self, but it has to be done this way
171 # This sets self.__dict__ = self, but it has to be done this way
172 # because we are also overriding __setattr__.
172 # because we are also overriding __setattr__.
173 dict.__setattr__(self, '__dict__', self)
173 dict.__setattr__(self, '__dict__', self)
174 self._ensure_subconfig()
174 self._ensure_subconfig()
175
175
176 def _ensure_subconfig(self):
176 def _ensure_subconfig(self):
177 """ensure that sub-dicts that should be Config objects are
177 """ensure that sub-dicts that should be Config objects are
178
178
179 casts dicts that are under section keys to Config objects,
179 casts dicts that are under section keys to Config objects,
180 which is necessary for constructing Config objects from dict literals.
180 which is necessary for constructing Config objects from dict literals.
181 """
181 """
182 for key in self:
182 for key in self:
183 obj = self[key]
183 obj = self[key]
184 if self._is_section_key(key) \
184 if self._is_section_key(key) \
185 and isinstance(obj, dict) \
185 and isinstance(obj, dict) \
186 and not isinstance(obj, Config):
186 and not isinstance(obj, Config):
187 dict.__setattr__(self, key, Config(obj))
187 dict.__setattr__(self, key, Config(obj))
188
188
189 def _merge(self, other):
189 def _merge(self, other):
190 """deprecated alias, use Config.merge()"""
190 """deprecated alias, use Config.merge()"""
191 self.merge(other)
191 self.merge(other)
192
192
193 def merge(self, other):
193 def merge(self, other):
194 """merge another config object into this one"""
194 """merge another config object into this one"""
195 to_update = {}
195 to_update = {}
196 for k, v in iteritems(other):
196 for k, v in iteritems(other):
197 if k not in self:
197 if k not in self:
198 to_update[k] = v
198 to_update[k] = v
199 else: # I have this key
199 else: # I have this key
200 if isinstance(v, Config) and isinstance(self[k], Config):
200 if isinstance(v, Config) and isinstance(self[k], Config):
201 # Recursively merge common sub Configs
201 # Recursively merge common sub Configs
202 self[k].merge(v)
202 self[k].merge(v)
203 else:
203 else:
204 # Plain updates for non-Configs
204 # Plain updates for non-Configs
205 to_update[k] = v
205 to_update[k] = v
206
206
207 self.update(to_update)
207 self.update(to_update)
208
208
209 def _is_section_key(self, key):
209 def _is_section_key(self, key):
210 if key[0].upper()==key[0] and not key.startswith('_'):
210 if key[0].upper()==key[0] and not key.startswith('_'):
211 return True
211 return True
212 else:
212 else:
213 return False
213 return False
214
214
215 def __contains__(self, key):
215 def __contains__(self, key):
216 # allow nested contains of the form `"Section.key" in config`
216 # allow nested contains of the form `"Section.key" in config`
217 if '.' in key:
217 if '.' in key:
218 first, remainder = key.split('.', 1)
218 first, remainder = key.split('.', 1)
219 if first not in self:
219 if first not in self:
220 return False
220 return False
221 return remainder in self[first]
221 return remainder in self[first]
222
222
223 # we always have Sections
223 # we always have Sections
224 if self._is_section_key(key):
224 if self._is_section_key(key):
225 return True
225 return True
226 else:
226 else:
227 return super(Config, self).__contains__(key)
227 return super(Config, self).__contains__(key)
228 # .has_key is deprecated for dictionaries.
228 # .has_key is deprecated for dictionaries.
229 has_key = __contains__
229 has_key = __contains__
230
230
231 def _has_section(self, key):
231 def _has_section(self, key):
232 if self._is_section_key(key):
232 if self._is_section_key(key):
233 if super(Config, self).__contains__(key):
233 if super(Config, self).__contains__(key):
234 return True
234 return True
235 return False
235 return False
236
236
237 def copy(self):
237 def copy(self):
238 return type(self)(dict.copy(self))
238 return type(self)(dict.copy(self))
239
239
240 def __copy__(self):
240 def __copy__(self):
241 return self.copy()
241 return self.copy()
242
242
243 def __deepcopy__(self, memo):
243 def __deepcopy__(self, memo):
244 import copy
244 import copy
245 return type(self)(copy.deepcopy(self.items()))
245 return type(self)(copy.deepcopy(list(self.items())))
246
246
247 def __getitem__(self, key):
247 def __getitem__(self, key):
248 # We cannot use directly self._is_section_key, because it triggers
248 # We cannot use directly self._is_section_key, because it triggers
249 # infinite recursion on top of PyPy. Instead, we manually fish the
249 # infinite recursion on top of PyPy. Instead, we manually fish the
250 # bound method.
250 # bound method.
251 is_section_key = self.__class__._is_section_key.__get__(self)
251 is_section_key = self.__class__._is_section_key.__get__(self)
252
252
253 # Because we use this for an exec namespace, we need to delegate
253 # Because we use this for an exec namespace, we need to delegate
254 # the lookup of names in __builtin__ to itself. This means
254 # the lookup of names in __builtin__ to itself. This means
255 # that you can't have section or attribute names that are
255 # that you can't have section or attribute names that are
256 # builtins.
256 # builtins.
257 try:
257 try:
258 return getattr(builtin_mod, key)
258 return getattr(builtin_mod, key)
259 except AttributeError:
259 except AttributeError:
260 pass
260 pass
261 if is_section_key(key):
261 if is_section_key(key):
262 try:
262 try:
263 return dict.__getitem__(self, key)
263 return dict.__getitem__(self, key)
264 except KeyError:
264 except KeyError:
265 c = Config()
265 c = Config()
266 dict.__setitem__(self, key, c)
266 dict.__setitem__(self, key, c)
267 return c
267 return c
268 else:
268 else:
269 try:
269 try:
270 return dict.__getitem__(self, key)
270 return dict.__getitem__(self, key)
271 except KeyError:
271 except KeyError:
272 # undefined
272 # undefined
273 v = LazyConfigValue()
273 v = LazyConfigValue()
274 dict.__setitem__(self, key, v)
274 dict.__setitem__(self, key, v)
275 return v
275 return v
276
276
277
277
278 def __setitem__(self, key, value):
278 def __setitem__(self, key, value):
279 if self._is_section_key(key):
279 if self._is_section_key(key):
280 if not isinstance(value, Config):
280 if not isinstance(value, Config):
281 raise ValueError('values whose keys begin with an uppercase '
281 raise ValueError('values whose keys begin with an uppercase '
282 'char must be Config instances: %r, %r' % (key, value))
282 'char must be Config instances: %r, %r' % (key, value))
283 else:
283 else:
284 dict.__setitem__(self, key, value)
284 dict.__setitem__(self, key, value)
285
285
286 def __getattr__(self, key):
286 def __getattr__(self, key):
287 try:
287 try:
288 return self.__getitem__(key)
288 return self.__getitem__(key)
289 except KeyError as e:
289 except KeyError as e:
290 raise AttributeError(e)
290 raise AttributeError(e)
291
291
292 def __setattr__(self, key, value):
292 def __setattr__(self, key, value):
293 try:
293 try:
294 self.__setitem__(key, value)
294 self.__setitem__(key, value)
295 except KeyError as e:
295 except KeyError as e:
296 raise AttributeError(e)
296 raise AttributeError(e)
297
297
298 def __delattr__(self, key):
298 def __delattr__(self, key):
299 try:
299 try:
300 dict.__delitem__(self, key)
300 dict.__delitem__(self, key)
301 except KeyError as e:
301 except KeyError as e:
302 raise AttributeError(e)
302 raise AttributeError(e)
303
303
304
304
305 #-----------------------------------------------------------------------------
305 #-----------------------------------------------------------------------------
306 # Config loading classes
306 # Config loading classes
307 #-----------------------------------------------------------------------------
307 #-----------------------------------------------------------------------------
308
308
309
309
310 class ConfigLoader(object):
310 class ConfigLoader(object):
311 """A object for loading configurations from just about anywhere.
311 """A object for loading configurations from just about anywhere.
312
312
313 The resulting configuration is packaged as a :class:`Struct`.
313 The resulting configuration is packaged as a :class:`Struct`.
314
314
315 Notes
315 Notes
316 -----
316 -----
317 A :class:`ConfigLoader` does one thing: load a config from a source
317 A :class:`ConfigLoader` does one thing: load a config from a source
318 (file, command line arguments) and returns the data as a :class:`Struct`.
318 (file, command line arguments) and returns the data as a :class:`Struct`.
319 There are lots of things that :class:`ConfigLoader` does not do. It does
319 There are lots of things that :class:`ConfigLoader` does not do. It does
320 not implement complex logic for finding config files. It does not handle
320 not implement complex logic for finding config files. It does not handle
321 default values or merge multiple configs. These things need to be
321 default values or merge multiple configs. These things need to be
322 handled elsewhere.
322 handled elsewhere.
323 """
323 """
324
324
325 def __init__(self):
325 def __init__(self):
326 """A base class for config loaders.
326 """A base class for config loaders.
327
327
328 Examples
328 Examples
329 --------
329 --------
330
330
331 >>> cl = ConfigLoader()
331 >>> cl = ConfigLoader()
332 >>> config = cl.load_config()
332 >>> config = cl.load_config()
333 >>> config
333 >>> config
334 {}
334 {}
335 """
335 """
336 self.clear()
336 self.clear()
337
337
338 def clear(self):
338 def clear(self):
339 self.config = Config()
339 self.config = Config()
340
340
341 def load_config(self):
341 def load_config(self):
342 """Load a config from somewhere, return a :class:`Config` instance.
342 """Load a config from somewhere, return a :class:`Config` instance.
343
343
344 Usually, this will cause self.config to be set and then returned.
344 Usually, this will cause self.config to be set and then returned.
345 However, in most cases, :meth:`ConfigLoader.clear` should be called
345 However, in most cases, :meth:`ConfigLoader.clear` should be called
346 to erase any previous state.
346 to erase any previous state.
347 """
347 """
348 self.clear()
348 self.clear()
349 return self.config
349 return self.config
350
350
351
351
352 class FileConfigLoader(ConfigLoader):
352 class FileConfigLoader(ConfigLoader):
353 """A base class for file based configurations.
353 """A base class for file based configurations.
354
354
355 As we add more file based config loaders, the common logic should go
355 As we add more file based config loaders, the common logic should go
356 here.
356 here.
357 """
357 """
358 pass
358 pass
359
359
360
360
361 class PyFileConfigLoader(FileConfigLoader):
361 class PyFileConfigLoader(FileConfigLoader):
362 """A config loader for pure python files.
362 """A config loader for pure python files.
363
363
364 This calls execfile on a plain python file and looks for attributes
364 This calls execfile on a plain python file and looks for attributes
365 that are all caps. These attribute are added to the config Struct.
365 that are all caps. These attribute are added to the config Struct.
366 """
366 """
367
367
368 def __init__(self, filename, path=None):
368 def __init__(self, filename, path=None):
369 """Build a config loader for a filename and path.
369 """Build a config loader for a filename and path.
370
370
371 Parameters
371 Parameters
372 ----------
372 ----------
373 filename : str
373 filename : str
374 The file name of the config file.
374 The file name of the config file.
375 path : str, list, tuple
375 path : str, list, tuple
376 The path to search for the config file on, or a sequence of
376 The path to search for the config file on, or a sequence of
377 paths to try in order.
377 paths to try in order.
378 """
378 """
379 super(PyFileConfigLoader, self).__init__()
379 super(PyFileConfigLoader, self).__init__()
380 self.filename = filename
380 self.filename = filename
381 self.path = path
381 self.path = path
382 self.full_filename = ''
382 self.full_filename = ''
383 self.data = None
383 self.data = None
384
384
385 def load_config(self):
385 def load_config(self):
386 """Load the config from a file and return it as a Struct."""
386 """Load the config from a file and return it as a Struct."""
387 self.clear()
387 self.clear()
388 try:
388 try:
389 self._find_file()
389 self._find_file()
390 except IOError as e:
390 except IOError as e:
391 raise ConfigFileNotFound(str(e))
391 raise ConfigFileNotFound(str(e))
392 self._read_file_as_dict()
392 self._read_file_as_dict()
393 self._convert_to_config()
393 self._convert_to_config()
394 return self.config
394 return self.config
395
395
396 def _find_file(self):
396 def _find_file(self):
397 """Try to find the file by searching the paths."""
397 """Try to find the file by searching the paths."""
398 self.full_filename = filefind(self.filename, self.path)
398 self.full_filename = filefind(self.filename, self.path)
399
399
400 def _read_file_as_dict(self):
400 def _read_file_as_dict(self):
401 """Load the config file into self.config, with recursive loading."""
401 """Load the config file into self.config, with recursive loading."""
402 # This closure is made available in the namespace that is used
402 # This closure is made available in the namespace that is used
403 # to exec the config file. It allows users to call
403 # to exec the config file. It allows users to call
404 # load_subconfig('myconfig.py') to load config files recursively.
404 # load_subconfig('myconfig.py') to load config files recursively.
405 # It needs to be a closure because it has references to self.path
405 # It needs to be a closure because it has references to self.path
406 # and self.config. The sub-config is loaded with the same path
406 # and self.config. The sub-config is loaded with the same path
407 # as the parent, but it uses an empty config which is then merged
407 # as the parent, but it uses an empty config which is then merged
408 # with the parents.
408 # with the parents.
409
409
410 # If a profile is specified, the config file will be loaded
410 # If a profile is specified, the config file will be loaded
411 # from that profile
411 # from that profile
412
412
413 def load_subconfig(fname, profile=None):
413 def load_subconfig(fname, profile=None):
414 # import here to prevent circular imports
414 # import here to prevent circular imports
415 from IPython.core.profiledir import ProfileDir, ProfileDirError
415 from IPython.core.profiledir import ProfileDir, ProfileDirError
416 if profile is not None:
416 if profile is not None:
417 try:
417 try:
418 profile_dir = ProfileDir.find_profile_dir_by_name(
418 profile_dir = ProfileDir.find_profile_dir_by_name(
419 get_ipython_dir(),
419 get_ipython_dir(),
420 profile,
420 profile,
421 )
421 )
422 except ProfileDirError:
422 except ProfileDirError:
423 return
423 return
424 path = profile_dir.location
424 path = profile_dir.location
425 else:
425 else:
426 path = self.path
426 path = self.path
427 loader = PyFileConfigLoader(fname, path)
427 loader = PyFileConfigLoader(fname, path)
428 try:
428 try:
429 sub_config = loader.load_config()
429 sub_config = loader.load_config()
430 except ConfigFileNotFound:
430 except ConfigFileNotFound:
431 # Pass silently if the sub config is not there. This happens
431 # Pass silently if the sub config is not there. This happens
432 # when a user s using a profile, but not the default config.
432 # when a user s using a profile, but not the default config.
433 pass
433 pass
434 else:
434 else:
435 self.config.merge(sub_config)
435 self.config.merge(sub_config)
436
436
437 # Again, this needs to be a closure and should be used in config
437 # Again, this needs to be a closure and should be used in config
438 # files to get the config being loaded.
438 # files to get the config being loaded.
439 def get_config():
439 def get_config():
440 return self.config
440 return self.config
441
441
442 namespace = dict(
442 namespace = dict(
443 load_subconfig=load_subconfig,
443 load_subconfig=load_subconfig,
444 get_config=get_config,
444 get_config=get_config,
445 __file__=self.full_filename,
445 __file__=self.full_filename,
446 )
446 )
447 fs_encoding = sys.getfilesystemencoding() or 'ascii'
447 fs_encoding = sys.getfilesystemencoding() or 'ascii'
448 conf_filename = self.full_filename.encode(fs_encoding)
448 conf_filename = self.full_filename.encode(fs_encoding)
449 py3compat.execfile(conf_filename, namespace)
449 py3compat.execfile(conf_filename, namespace)
450
450
451 def _convert_to_config(self):
451 def _convert_to_config(self):
452 if self.data is None:
452 if self.data is None:
453 ConfigLoaderError('self.data does not exist')
453 ConfigLoaderError('self.data does not exist')
454
454
455
455
456 class CommandLineConfigLoader(ConfigLoader):
456 class CommandLineConfigLoader(ConfigLoader):
457 """A config loader for command line arguments.
457 """A config loader for command line arguments.
458
458
459 As we add more command line based loaders, the common logic should go
459 As we add more command line based loaders, the common logic should go
460 here.
460 here.
461 """
461 """
462
462
463 def _exec_config_str(self, lhs, rhs):
463 def _exec_config_str(self, lhs, rhs):
464 """execute self.config.<lhs> = <rhs>
464 """execute self.config.<lhs> = <rhs>
465
465
466 * expands ~ with expanduser
466 * expands ~ with expanduser
467 * tries to assign with raw eval, otherwise assigns with just the string,
467 * tries to assign with raw eval, otherwise assigns with just the string,
468 allowing `--C.a=foobar` and `--C.a="foobar"` to be equivalent. *Not*
468 allowing `--C.a=foobar` and `--C.a="foobar"` to be equivalent. *Not*
469 equivalent are `--C.a=4` and `--C.a='4'`.
469 equivalent are `--C.a=4` and `--C.a='4'`.
470 """
470 """
471 rhs = os.path.expanduser(rhs)
471 rhs = os.path.expanduser(rhs)
472 try:
472 try:
473 # Try to see if regular Python syntax will work. This
473 # Try to see if regular Python syntax will work. This
474 # won't handle strings as the quote marks are removed
474 # won't handle strings as the quote marks are removed
475 # by the system shell.
475 # by the system shell.
476 value = eval(rhs)
476 value = eval(rhs)
477 except (NameError, SyntaxError):
477 except (NameError, SyntaxError):
478 # This case happens if the rhs is a string.
478 # This case happens if the rhs is a string.
479 value = rhs
479 value = rhs
480
480
481 exec(u'self.config.%s = value' % lhs)
481 exec(u'self.config.%s = value' % lhs)
482
482
483 def _load_flag(self, cfg):
483 def _load_flag(self, cfg):
484 """update self.config from a flag, which can be a dict or Config"""
484 """update self.config from a flag, which can be a dict or Config"""
485 if isinstance(cfg, (dict, Config)):
485 if isinstance(cfg, (dict, Config)):
486 # don't clobber whole config sections, update
486 # don't clobber whole config sections, update
487 # each section from config:
487 # each section from config:
488 for sec,c in iteritems(cfg):
488 for sec,c in iteritems(cfg):
489 self.config[sec].update(c)
489 self.config[sec].update(c)
490 else:
490 else:
491 raise TypeError("Invalid flag: %r" % cfg)
491 raise TypeError("Invalid flag: %r" % cfg)
492
492
493 # raw --identifier=value pattern
493 # raw --identifier=value pattern
494 # but *also* accept '-' as wordsep, for aliases
494 # but *also* accept '-' as wordsep, for aliases
495 # accepts: --foo=a
495 # accepts: --foo=a
496 # --Class.trait=value
496 # --Class.trait=value
497 # --alias-name=value
497 # --alias-name=value
498 # rejects: -foo=value
498 # rejects: -foo=value
499 # --foo
499 # --foo
500 # --Class.trait
500 # --Class.trait
501 kv_pattern = re.compile(r'\-\-[A-Za-z][\w\-]*(\.[\w\-]+)*\=.*')
501 kv_pattern = re.compile(r'\-\-[A-Za-z][\w\-]*(\.[\w\-]+)*\=.*')
502
502
503 # just flags, no assignments, with two *or one* leading '-'
503 # just flags, no assignments, with two *or one* leading '-'
504 # accepts: --foo
504 # accepts: --foo
505 # -foo-bar-again
505 # -foo-bar-again
506 # rejects: --anything=anything
506 # rejects: --anything=anything
507 # --two.word
507 # --two.word
508
508
509 flag_pattern = re.compile(r'\-\-?\w+[\-\w]*$')
509 flag_pattern = re.compile(r'\-\-?\w+[\-\w]*$')
510
510
511 class KeyValueConfigLoader(CommandLineConfigLoader):
511 class KeyValueConfigLoader(CommandLineConfigLoader):
512 """A config loader that loads key value pairs from the command line.
512 """A config loader that loads key value pairs from the command line.
513
513
514 This allows command line options to be gives in the following form::
514 This allows command line options to be gives in the following form::
515
515
516 ipython --profile="foo" --InteractiveShell.autocall=False
516 ipython --profile="foo" --InteractiveShell.autocall=False
517 """
517 """
518
518
519 def __init__(self, argv=None, aliases=None, flags=None):
519 def __init__(self, argv=None, aliases=None, flags=None):
520 """Create a key value pair config loader.
520 """Create a key value pair config loader.
521
521
522 Parameters
522 Parameters
523 ----------
523 ----------
524 argv : list
524 argv : list
525 A list that has the form of sys.argv[1:] which has unicode
525 A list that has the form of sys.argv[1:] which has unicode
526 elements of the form u"key=value". If this is None (default),
526 elements of the form u"key=value". If this is None (default),
527 then sys.argv[1:] will be used.
527 then sys.argv[1:] will be used.
528 aliases : dict
528 aliases : dict
529 A dict of aliases for configurable traits.
529 A dict of aliases for configurable traits.
530 Keys are the short aliases, Values are the resolved trait.
530 Keys are the short aliases, Values are the resolved trait.
531 Of the form: `{'alias' : 'Configurable.trait'}`
531 Of the form: `{'alias' : 'Configurable.trait'}`
532 flags : dict
532 flags : dict
533 A dict of flags, keyed by str name. Vaues can be Config objects,
533 A dict of flags, keyed by str name. Vaues can be Config objects,
534 dicts, or "key=value" strings. If Config or dict, when the flag
534 dicts, or "key=value" strings. If Config or dict, when the flag
535 is triggered, The flag is loaded as `self.config.update(m)`.
535 is triggered, The flag is loaded as `self.config.update(m)`.
536
536
537 Returns
537 Returns
538 -------
538 -------
539 config : Config
539 config : Config
540 The resulting Config object.
540 The resulting Config object.
541
541
542 Examples
542 Examples
543 --------
543 --------
544
544
545 >>> from IPython.config.loader import KeyValueConfigLoader
545 >>> from IPython.config.loader import KeyValueConfigLoader
546 >>> cl = KeyValueConfigLoader()
546 >>> cl = KeyValueConfigLoader()
547 >>> d = cl.load_config(["--A.name='brian'","--B.number=0"])
547 >>> d = cl.load_config(["--A.name='brian'","--B.number=0"])
548 >>> sorted(d.items())
548 >>> sorted(d.items())
549 [('A', {'name': 'brian'}), ('B', {'number': 0})]
549 [('A', {'name': 'brian'}), ('B', {'number': 0})]
550 """
550 """
551 self.clear()
551 self.clear()
552 if argv is None:
552 if argv is None:
553 argv = sys.argv[1:]
553 argv = sys.argv[1:]
554 self.argv = argv
554 self.argv = argv
555 self.aliases = aliases or {}
555 self.aliases = aliases or {}
556 self.flags = flags or {}
556 self.flags = flags or {}
557
557
558
558
559 def clear(self):
559 def clear(self):
560 super(KeyValueConfigLoader, self).clear()
560 super(KeyValueConfigLoader, self).clear()
561 self.extra_args = []
561 self.extra_args = []
562
562
563
563
564 def _decode_argv(self, argv, enc=None):
564 def _decode_argv(self, argv, enc=None):
565 """decode argv if bytes, using stin.encoding, falling back on default enc"""
565 """decode argv if bytes, using stin.encoding, falling back on default enc"""
566 uargv = []
566 uargv = []
567 if enc is None:
567 if enc is None:
568 enc = DEFAULT_ENCODING
568 enc = DEFAULT_ENCODING
569 for arg in argv:
569 for arg in argv:
570 if not isinstance(arg, unicode_type):
570 if not isinstance(arg, unicode_type):
571 # only decode if not already decoded
571 # only decode if not already decoded
572 arg = arg.decode(enc)
572 arg = arg.decode(enc)
573 uargv.append(arg)
573 uargv.append(arg)
574 return uargv
574 return uargv
575
575
576
576
577 def load_config(self, argv=None, aliases=None, flags=None):
577 def load_config(self, argv=None, aliases=None, flags=None):
578 """Parse the configuration and generate the Config object.
578 """Parse the configuration and generate the Config object.
579
579
580 After loading, any arguments that are not key-value or
580 After loading, any arguments that are not key-value or
581 flags will be stored in self.extra_args - a list of
581 flags will be stored in self.extra_args - a list of
582 unparsed command-line arguments. This is used for
582 unparsed command-line arguments. This is used for
583 arguments such as input files or subcommands.
583 arguments such as input files or subcommands.
584
584
585 Parameters
585 Parameters
586 ----------
586 ----------
587 argv : list, optional
587 argv : list, optional
588 A list that has the form of sys.argv[1:] which has unicode
588 A list that has the form of sys.argv[1:] which has unicode
589 elements of the form u"key=value". If this is None (default),
589 elements of the form u"key=value". If this is None (default),
590 then self.argv will be used.
590 then self.argv will be used.
591 aliases : dict
591 aliases : dict
592 A dict of aliases for configurable traits.
592 A dict of aliases for configurable traits.
593 Keys are the short aliases, Values are the resolved trait.
593 Keys are the short aliases, Values are the resolved trait.
594 Of the form: `{'alias' : 'Configurable.trait'}`
594 Of the form: `{'alias' : 'Configurable.trait'}`
595 flags : dict
595 flags : dict
596 A dict of flags, keyed by str name. Values can be Config objects
596 A dict of flags, keyed by str name. Values can be Config objects
597 or dicts. When the flag is triggered, The config is loaded as
597 or dicts. When the flag is triggered, The config is loaded as
598 `self.config.update(cfg)`.
598 `self.config.update(cfg)`.
599 """
599 """
600 self.clear()
600 self.clear()
601 if argv is None:
601 if argv is None:
602 argv = self.argv
602 argv = self.argv
603 if aliases is None:
603 if aliases is None:
604 aliases = self.aliases
604 aliases = self.aliases
605 if flags is None:
605 if flags is None:
606 flags = self.flags
606 flags = self.flags
607
607
608 # ensure argv is a list of unicode strings:
608 # ensure argv is a list of unicode strings:
609 uargv = self._decode_argv(argv)
609 uargv = self._decode_argv(argv)
610 for idx,raw in enumerate(uargv):
610 for idx,raw in enumerate(uargv):
611 # strip leading '-'
611 # strip leading '-'
612 item = raw.lstrip('-')
612 item = raw.lstrip('-')
613
613
614 if raw == '--':
614 if raw == '--':
615 # don't parse arguments after '--'
615 # don't parse arguments after '--'
616 # this is useful for relaying arguments to scripts, e.g.
616 # this is useful for relaying arguments to scripts, e.g.
617 # ipython -i foo.py --matplotlib=qt -- args after '--' go-to-foo.py
617 # ipython -i foo.py --matplotlib=qt -- args after '--' go-to-foo.py
618 self.extra_args.extend(uargv[idx+1:])
618 self.extra_args.extend(uargv[idx+1:])
619 break
619 break
620
620
621 if kv_pattern.match(raw):
621 if kv_pattern.match(raw):
622 lhs,rhs = item.split('=',1)
622 lhs,rhs = item.split('=',1)
623 # Substitute longnames for aliases.
623 # Substitute longnames for aliases.
624 if lhs in aliases:
624 if lhs in aliases:
625 lhs = aliases[lhs]
625 lhs = aliases[lhs]
626 if '.' not in lhs:
626 if '.' not in lhs:
627 # probably a mistyped alias, but not technically illegal
627 # probably a mistyped alias, but not technically illegal
628 warn.warn("Unrecognized alias: '%s', it will probably have no effect."%lhs)
628 warn.warn("Unrecognized alias: '%s', it will probably have no effect."%lhs)
629 try:
629 try:
630 self._exec_config_str(lhs, rhs)
630 self._exec_config_str(lhs, rhs)
631 except Exception:
631 except Exception:
632 raise ArgumentError("Invalid argument: '%s'" % raw)
632 raise ArgumentError("Invalid argument: '%s'" % raw)
633
633
634 elif flag_pattern.match(raw):
634 elif flag_pattern.match(raw):
635 if item in flags:
635 if item in flags:
636 cfg,help = flags[item]
636 cfg,help = flags[item]
637 self._load_flag(cfg)
637 self._load_flag(cfg)
638 else:
638 else:
639 raise ArgumentError("Unrecognized flag: '%s'"%raw)
639 raise ArgumentError("Unrecognized flag: '%s'"%raw)
640 elif raw.startswith('-'):
640 elif raw.startswith('-'):
641 kv = '--'+item
641 kv = '--'+item
642 if kv_pattern.match(kv):
642 if kv_pattern.match(kv):
643 raise ArgumentError("Invalid argument: '%s', did you mean '%s'?"%(raw, kv))
643 raise ArgumentError("Invalid argument: '%s', did you mean '%s'?"%(raw, kv))
644 else:
644 else:
645 raise ArgumentError("Invalid argument: '%s'"%raw)
645 raise ArgumentError("Invalid argument: '%s'"%raw)
646 else:
646 else:
647 # keep all args that aren't valid in a list,
647 # keep all args that aren't valid in a list,
648 # in case our parent knows what to do with them.
648 # in case our parent knows what to do with them.
649 self.extra_args.append(item)
649 self.extra_args.append(item)
650 return self.config
650 return self.config
651
651
652 class ArgParseConfigLoader(CommandLineConfigLoader):
652 class ArgParseConfigLoader(CommandLineConfigLoader):
653 """A loader that uses the argparse module to load from the command line."""
653 """A loader that uses the argparse module to load from the command line."""
654
654
655 def __init__(self, argv=None, aliases=None, flags=None, *parser_args, **parser_kw):
655 def __init__(self, argv=None, aliases=None, flags=None, *parser_args, **parser_kw):
656 """Create a config loader for use with argparse.
656 """Create a config loader for use with argparse.
657
657
658 Parameters
658 Parameters
659 ----------
659 ----------
660
660
661 argv : optional, list
661 argv : optional, list
662 If given, used to read command-line arguments from, otherwise
662 If given, used to read command-line arguments from, otherwise
663 sys.argv[1:] is used.
663 sys.argv[1:] is used.
664
664
665 parser_args : tuple
665 parser_args : tuple
666 A tuple of positional arguments that will be passed to the
666 A tuple of positional arguments that will be passed to the
667 constructor of :class:`argparse.ArgumentParser`.
667 constructor of :class:`argparse.ArgumentParser`.
668
668
669 parser_kw : dict
669 parser_kw : dict
670 A tuple of keyword arguments that will be passed to the
670 A tuple of keyword arguments that will be passed to the
671 constructor of :class:`argparse.ArgumentParser`.
671 constructor of :class:`argparse.ArgumentParser`.
672
672
673 Returns
673 Returns
674 -------
674 -------
675 config : Config
675 config : Config
676 The resulting Config object.
676 The resulting Config object.
677 """
677 """
678 super(CommandLineConfigLoader, self).__init__()
678 super(CommandLineConfigLoader, self).__init__()
679 self.clear()
679 self.clear()
680 if argv is None:
680 if argv is None:
681 argv = sys.argv[1:]
681 argv = sys.argv[1:]
682 self.argv = argv
682 self.argv = argv
683 self.aliases = aliases or {}
683 self.aliases = aliases or {}
684 self.flags = flags or {}
684 self.flags = flags or {}
685
685
686 self.parser_args = parser_args
686 self.parser_args = parser_args
687 self.version = parser_kw.pop("version", None)
687 self.version = parser_kw.pop("version", None)
688 kwargs = dict(argument_default=argparse.SUPPRESS)
688 kwargs = dict(argument_default=argparse.SUPPRESS)
689 kwargs.update(parser_kw)
689 kwargs.update(parser_kw)
690 self.parser_kw = kwargs
690 self.parser_kw = kwargs
691
691
692 def load_config(self, argv=None, aliases=None, flags=None):
692 def load_config(self, argv=None, aliases=None, flags=None):
693 """Parse command line arguments and return as a Config object.
693 """Parse command line arguments and return as a Config object.
694
694
695 Parameters
695 Parameters
696 ----------
696 ----------
697
697
698 args : optional, list
698 args : optional, list
699 If given, a list with the structure of sys.argv[1:] to parse
699 If given, a list with the structure of sys.argv[1:] to parse
700 arguments from. If not given, the instance's self.argv attribute
700 arguments from. If not given, the instance's self.argv attribute
701 (given at construction time) is used."""
701 (given at construction time) is used."""
702 self.clear()
702 self.clear()
703 if argv is None:
703 if argv is None:
704 argv = self.argv
704 argv = self.argv
705 if aliases is None:
705 if aliases is None:
706 aliases = self.aliases
706 aliases = self.aliases
707 if flags is None:
707 if flags is None:
708 flags = self.flags
708 flags = self.flags
709 self._create_parser(aliases, flags)
709 self._create_parser(aliases, flags)
710 self._parse_args(argv)
710 self._parse_args(argv)
711 self._convert_to_config()
711 self._convert_to_config()
712 return self.config
712 return self.config
713
713
714 def get_extra_args(self):
714 def get_extra_args(self):
715 if hasattr(self, 'extra_args'):
715 if hasattr(self, 'extra_args'):
716 return self.extra_args
716 return self.extra_args
717 else:
717 else:
718 return []
718 return []
719
719
720 def _create_parser(self, aliases=None, flags=None):
720 def _create_parser(self, aliases=None, flags=None):
721 self.parser = ArgumentParser(*self.parser_args, **self.parser_kw)
721 self.parser = ArgumentParser(*self.parser_args, **self.parser_kw)
722 self._add_arguments(aliases, flags)
722 self._add_arguments(aliases, flags)
723
723
724 def _add_arguments(self, aliases=None, flags=None):
724 def _add_arguments(self, aliases=None, flags=None):
725 raise NotImplementedError("subclasses must implement _add_arguments")
725 raise NotImplementedError("subclasses must implement _add_arguments")
726
726
727 def _parse_args(self, args):
727 def _parse_args(self, args):
728 """self.parser->self.parsed_data"""
728 """self.parser->self.parsed_data"""
729 # decode sys.argv to support unicode command-line options
729 # decode sys.argv to support unicode command-line options
730 enc = DEFAULT_ENCODING
730 enc = DEFAULT_ENCODING
731 uargs = [py3compat.cast_unicode(a, enc) for a in args]
731 uargs = [py3compat.cast_unicode(a, enc) for a in args]
732 self.parsed_data, self.extra_args = self.parser.parse_known_args(uargs)
732 self.parsed_data, self.extra_args = self.parser.parse_known_args(uargs)
733
733
734 def _convert_to_config(self):
734 def _convert_to_config(self):
735 """self.parsed_data->self.config"""
735 """self.parsed_data->self.config"""
736 for k, v in iteritems(vars(self.parsed_data)):
736 for k, v in iteritems(vars(self.parsed_data)):
737 exec("self.config.%s = v"%k, locals(), globals())
737 exec("self.config.%s = v"%k, locals(), globals())
738
738
739 class KVArgParseConfigLoader(ArgParseConfigLoader):
739 class KVArgParseConfigLoader(ArgParseConfigLoader):
740 """A config loader that loads aliases and flags with argparse,
740 """A config loader that loads aliases and flags with argparse,
741 but will use KVLoader for the rest. This allows better parsing
741 but will use KVLoader for the rest. This allows better parsing
742 of common args, such as `ipython -c 'print 5'`, but still gets
742 of common args, such as `ipython -c 'print 5'`, but still gets
743 arbitrary config with `ipython --InteractiveShell.use_readline=False`"""
743 arbitrary config with `ipython --InteractiveShell.use_readline=False`"""
744
744
745 def _add_arguments(self, aliases=None, flags=None):
745 def _add_arguments(self, aliases=None, flags=None):
746 self.alias_flags = {}
746 self.alias_flags = {}
747 # print aliases, flags
747 # print aliases, flags
748 if aliases is None:
748 if aliases is None:
749 aliases = self.aliases
749 aliases = self.aliases
750 if flags is None:
750 if flags is None:
751 flags = self.flags
751 flags = self.flags
752 paa = self.parser.add_argument
752 paa = self.parser.add_argument
753 for key,value in iteritems(aliases):
753 for key,value in iteritems(aliases):
754 if key in flags:
754 if key in flags:
755 # flags
755 # flags
756 nargs = '?'
756 nargs = '?'
757 else:
757 else:
758 nargs = None
758 nargs = None
759 if len(key) is 1:
759 if len(key) is 1:
760 paa('-'+key, '--'+key, type=unicode_type, dest=value, nargs=nargs)
760 paa('-'+key, '--'+key, type=unicode_type, dest=value, nargs=nargs)
761 else:
761 else:
762 paa('--'+key, type=unicode_type, dest=value, nargs=nargs)
762 paa('--'+key, type=unicode_type, dest=value, nargs=nargs)
763 for key, (value, help) in iteritems(flags):
763 for key, (value, help) in iteritems(flags):
764 if key in self.aliases:
764 if key in self.aliases:
765 #
765 #
766 self.alias_flags[self.aliases[key]] = value
766 self.alias_flags[self.aliases[key]] = value
767 continue
767 continue
768 if len(key) is 1:
768 if len(key) is 1:
769 paa('-'+key, '--'+key, action='append_const', dest='_flags', const=value)
769 paa('-'+key, '--'+key, action='append_const', dest='_flags', const=value)
770 else:
770 else:
771 paa('--'+key, action='append_const', dest='_flags', const=value)
771 paa('--'+key, action='append_const', dest='_flags', const=value)
772
772
773 def _convert_to_config(self):
773 def _convert_to_config(self):
774 """self.parsed_data->self.config, parse unrecognized extra args via KVLoader."""
774 """self.parsed_data->self.config, parse unrecognized extra args via KVLoader."""
775 # remove subconfigs list from namespace before transforming the Namespace
775 # remove subconfigs list from namespace before transforming the Namespace
776 if '_flags' in self.parsed_data:
776 if '_flags' in self.parsed_data:
777 subcs = self.parsed_data._flags
777 subcs = self.parsed_data._flags
778 del self.parsed_data._flags
778 del self.parsed_data._flags
779 else:
779 else:
780 subcs = []
780 subcs = []
781
781
782 for k, v in iteritems(vars(self.parsed_data)):
782 for k, v in iteritems(vars(self.parsed_data)):
783 if v is None:
783 if v is None:
784 # it was a flag that shares the name of an alias
784 # it was a flag that shares the name of an alias
785 subcs.append(self.alias_flags[k])
785 subcs.append(self.alias_flags[k])
786 else:
786 else:
787 # eval the KV assignment
787 # eval the KV assignment
788 self._exec_config_str(k, v)
788 self._exec_config_str(k, v)
789
789
790 for subc in subcs:
790 for subc in subcs:
791 self._load_flag(subc)
791 self._load_flag(subc)
792
792
793 if self.extra_args:
793 if self.extra_args:
794 sub_parser = KeyValueConfigLoader()
794 sub_parser = KeyValueConfigLoader()
795 sub_parser.load_config(self.extra_args)
795 sub_parser.load_config(self.extra_args)
796 self.config.merge(sub_parser.config)
796 self.config.merge(sub_parser.config)
797 self.extra_args = sub_parser.extra_args
797 self.extra_args = sub_parser.extra_args
798
798
799
799
800 def load_pyconfig_files(config_files, path):
800 def load_pyconfig_files(config_files, path):
801 """Load multiple Python config files, merging each of them in turn.
801 """Load multiple Python config files, merging each of them in turn.
802
802
803 Parameters
803 Parameters
804 ==========
804 ==========
805 config_files : list of str
805 config_files : list of str
806 List of config files names to load and merge into the config.
806 List of config files names to load and merge into the config.
807 path : unicode
807 path : unicode
808 The full path to the location of the config files.
808 The full path to the location of the config files.
809 """
809 """
810 config = Config()
810 config = Config()
811 for cf in config_files:
811 for cf in config_files:
812 loader = PyFileConfigLoader(cf, path=path)
812 loader = PyFileConfigLoader(cf, path=path)
813 try:
813 try:
814 next_config = loader.load_config()
814 next_config = loader.load_config()
815 except ConfigFileNotFound:
815 except ConfigFileNotFound:
816 pass
816 pass
817 except:
817 except:
818 raise
818 raise
819 else:
819 else:
820 config.merge(next_config)
820 config.merge(next_config)
821 return config
821 return config
@@ -1,654 +1,654 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Display formatters.
2 """Display formatters.
3
3
4 Inheritance diagram:
4 Inheritance diagram:
5
5
6 .. inheritance-diagram:: IPython.core.formatters
6 .. inheritance-diagram:: IPython.core.formatters
7 :parts: 3
7 :parts: 3
8
8
9 Authors:
9 Authors:
10
10
11 * Robert Kern
11 * Robert Kern
12 * Brian Granger
12 * Brian Granger
13 """
13 """
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Copyright (C) 2010-2011, IPython Development Team.
15 # Copyright (C) 2010-2011, IPython Development Team.
16 #
16 #
17 # Distributed under the terms of the Modified BSD License.
17 # Distributed under the terms of the Modified BSD License.
18 #
18 #
19 # The full license is in the file COPYING.txt, distributed with this software.
19 # The full license is in the file COPYING.txt, distributed with this software.
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 # Stdlib imports
26 # Stdlib imports
27 import abc
27 import abc
28 import sys
28 import sys
29 import warnings
29 import warnings
30 # We must use StringIO, as cStringIO doesn't handle unicode properly.
30 # We must use StringIO, as cStringIO doesn't handle unicode properly.
31 from io import StringIO
31 from io import StringIO
32
32
33 # Our own imports
33 # Our own imports
34 from IPython.config.configurable import Configurable
34 from IPython.config.configurable import Configurable
35 from IPython.lib import pretty
35 from IPython.lib import pretty
36 from IPython.utils.traitlets import (
36 from IPython.utils.traitlets import (
37 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
37 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
38 )
38 )
39 from IPython.utils.py3compat import unicode_to_str, with_metaclass
39 from IPython.utils.py3compat import unicode_to_str, with_metaclass
40
40
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # The main DisplayFormatter class
43 # The main DisplayFormatter class
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45
45
46
46
47 class DisplayFormatter(Configurable):
47 class DisplayFormatter(Configurable):
48
48
49 # When set to true only the default plain text formatter will be used.
49 # When set to true only the default plain text formatter will be used.
50 plain_text_only = Bool(False, config=True)
50 plain_text_only = Bool(False, config=True)
51 def _plain_text_only_changed(self, name, old, new):
51 def _plain_text_only_changed(self, name, old, new):
52 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
52 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
53
53
54 Use DisplayFormatter.active_types = ['text/plain']
54 Use DisplayFormatter.active_types = ['text/plain']
55 for the same effect.
55 for the same effect.
56 """, DeprecationWarning)
56 """, DeprecationWarning)
57 if new:
57 if new:
58 self.active_types = ['text/plain']
58 self.active_types = ['text/plain']
59 else:
59 else:
60 self.active_types = self.format_types
60 self.active_types = self.format_types
61
61
62 active_types = List(Unicode, config=True,
62 active_types = List(Unicode, config=True,
63 help="""List of currently active mime-types to display.
63 help="""List of currently active mime-types to display.
64 You can use this to set a white-list for formats to display.
64 You can use this to set a white-list for formats to display.
65
65
66 Most users will not need to change this value.
66 Most users will not need to change this value.
67 """)
67 """)
68 def _active_types_default(self):
68 def _active_types_default(self):
69 return self.format_types
69 return self.format_types
70
70
71 def _active_types_changed(self, name, old, new):
71 def _active_types_changed(self, name, old, new):
72 for key, formatter in self.formatters.items():
72 for key, formatter in self.formatters.items():
73 if key in new:
73 if key in new:
74 formatter.enabled = True
74 formatter.enabled = True
75 else:
75 else:
76 formatter.enabled = False
76 formatter.enabled = False
77
77
78 # A dict of formatter whose keys are format types (MIME types) and whose
78 # A dict of formatter whose keys are format types (MIME types) and whose
79 # values are subclasses of BaseFormatter.
79 # values are subclasses of BaseFormatter.
80 formatters = Dict()
80 formatters = Dict()
81 def _formatters_default(self):
81 def _formatters_default(self):
82 """Activate the default formatters."""
82 """Activate the default formatters."""
83 formatter_classes = [
83 formatter_classes = [
84 PlainTextFormatter,
84 PlainTextFormatter,
85 HTMLFormatter,
85 HTMLFormatter,
86 SVGFormatter,
86 SVGFormatter,
87 PNGFormatter,
87 PNGFormatter,
88 JPEGFormatter,
88 JPEGFormatter,
89 LatexFormatter,
89 LatexFormatter,
90 JSONFormatter,
90 JSONFormatter,
91 JavascriptFormatter
91 JavascriptFormatter
92 ]
92 ]
93 d = {}
93 d = {}
94 for cls in formatter_classes:
94 for cls in formatter_classes:
95 f = cls(parent=self)
95 f = cls(parent=self)
96 d[f.format_type] = f
96 d[f.format_type] = f
97 return d
97 return d
98
98
99 def format(self, obj, include=None, exclude=None):
99 def format(self, obj, include=None, exclude=None):
100 """Return a format data dict for an object.
100 """Return a format data dict for an object.
101
101
102 By default all format types will be computed.
102 By default all format types will be computed.
103
103
104 The following MIME types are currently implemented:
104 The following MIME types are currently implemented:
105
105
106 * text/plain
106 * text/plain
107 * text/html
107 * text/html
108 * text/latex
108 * text/latex
109 * application/json
109 * application/json
110 * application/javascript
110 * application/javascript
111 * image/png
111 * image/png
112 * image/jpeg
112 * image/jpeg
113 * image/svg+xml
113 * image/svg+xml
114
114
115 Parameters
115 Parameters
116 ----------
116 ----------
117 obj : object
117 obj : object
118 The Python object whose format data will be computed.
118 The Python object whose format data will be computed.
119 include : list or tuple, optional
119 include : list or tuple, optional
120 A list of format type strings (MIME types) to include in the
120 A list of format type strings (MIME types) to include in the
121 format data dict. If this is set *only* the format types included
121 format data dict. If this is set *only* the format types included
122 in this list will be computed.
122 in this list will be computed.
123 exclude : list or tuple, optional
123 exclude : list or tuple, optional
124 A list of format type string (MIME types) to exclude in the format
124 A list of format type string (MIME types) to exclude in the format
125 data dict. If this is set all format types will be computed,
125 data dict. If this is set all format types will be computed,
126 except for those included in this argument.
126 except for those included in this argument.
127
127
128 Returns
128 Returns
129 -------
129 -------
130 (format_dict, metadata_dict) : tuple of two dicts
130 (format_dict, metadata_dict) : tuple of two dicts
131
131
132 format_dict is a dictionary of key/value pairs, one of each format that was
132 format_dict is a dictionary of key/value pairs, one of each format that was
133 generated for the object. The keys are the format types, which
133 generated for the object. The keys are the format types, which
134 will usually be MIME type strings and the values and JSON'able
134 will usually be MIME type strings and the values and JSON'able
135 data structure containing the raw data for the representation in
135 data structure containing the raw data for the representation in
136 that format.
136 that format.
137
137
138 metadata_dict is a dictionary of metadata about each mime-type output.
138 metadata_dict is a dictionary of metadata about each mime-type output.
139 Its keys will be a strict subset of the keys in format_dict.
139 Its keys will be a strict subset of the keys in format_dict.
140 """
140 """
141 format_dict = {}
141 format_dict = {}
142 md_dict = {}
142 md_dict = {}
143
143
144 for format_type, formatter in self.formatters.items():
144 for format_type, formatter in self.formatters.items():
145 if include and format_type not in include:
145 if include and format_type not in include:
146 continue
146 continue
147 if exclude and format_type in exclude:
147 if exclude and format_type in exclude:
148 continue
148 continue
149
149
150 md = None
150 md = None
151 try:
151 try:
152 data = formatter(obj)
152 data = formatter(obj)
153 except:
153 except:
154 # FIXME: log the exception
154 # FIXME: log the exception
155 raise
155 raise
156
156
157 # formatters can return raw data or (data, metadata)
157 # formatters can return raw data or (data, metadata)
158 if isinstance(data, tuple) and len(data) == 2:
158 if isinstance(data, tuple) and len(data) == 2:
159 data, md = data
159 data, md = data
160
160
161 if data is not None:
161 if data is not None:
162 format_dict[format_type] = data
162 format_dict[format_type] = data
163 if md is not None:
163 if md is not None:
164 md_dict[format_type] = md
164 md_dict[format_type] = md
165
165
166 return format_dict, md_dict
166 return format_dict, md_dict
167
167
168 @property
168 @property
169 def format_types(self):
169 def format_types(self):
170 """Return the format types (MIME types) of the active formatters."""
170 """Return the format types (MIME types) of the active formatters."""
171 return self.formatters.keys()
171 return list(self.formatters.keys())
172
172
173
173
174 #-----------------------------------------------------------------------------
174 #-----------------------------------------------------------------------------
175 # Formatters for specific format types (text, html, svg, etc.)
175 # Formatters for specific format types (text, html, svg, etc.)
176 #-----------------------------------------------------------------------------
176 #-----------------------------------------------------------------------------
177
177
178
178
179 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
179 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
180 """ Abstract base class for Formatters.
180 """ Abstract base class for Formatters.
181
181
182 A formatter is a callable class that is responsible for computing the
182 A formatter is a callable class that is responsible for computing the
183 raw format data for a particular format type (MIME type). For example,
183 raw format data for a particular format type (MIME type). For example,
184 an HTML formatter would have a format type of `text/html` and would return
184 an HTML formatter would have a format type of `text/html` and would return
185 the HTML representation of the object when called.
185 the HTML representation of the object when called.
186 """
186 """
187
187
188 # The format type of the data returned, usually a MIME type.
188 # The format type of the data returned, usually a MIME type.
189 format_type = 'text/plain'
189 format_type = 'text/plain'
190
190
191 # Is the formatter enabled...
191 # Is the formatter enabled...
192 enabled = True
192 enabled = True
193
193
194 @abc.abstractmethod
194 @abc.abstractmethod
195 def __call__(self, obj):
195 def __call__(self, obj):
196 """Return a JSON'able representation of the object.
196 """Return a JSON'able representation of the object.
197
197
198 If the object cannot be formatted by this formatter, then return None
198 If the object cannot be formatted by this formatter, then return None
199 """
199 """
200 try:
200 try:
201 return repr(obj)
201 return repr(obj)
202 except TypeError:
202 except TypeError:
203 return None
203 return None
204
204
205
205
206 class BaseFormatter(Configurable):
206 class BaseFormatter(Configurable):
207 """A base formatter class that is configurable.
207 """A base formatter class that is configurable.
208
208
209 This formatter should usually be used as the base class of all formatters.
209 This formatter should usually be used as the base class of all formatters.
210 It is a traited :class:`Configurable` class and includes an extensible
210 It is a traited :class:`Configurable` class and includes an extensible
211 API for users to determine how their objects are formatted. The following
211 API for users to determine how their objects are formatted. The following
212 logic is used to find a function to format an given object.
212 logic is used to find a function to format an given object.
213
213
214 1. The object is introspected to see if it has a method with the name
214 1. The object is introspected to see if it has a method with the name
215 :attr:`print_method`. If is does, that object is passed to that method
215 :attr:`print_method`. If is does, that object is passed to that method
216 for formatting.
216 for formatting.
217 2. If no print method is found, three internal dictionaries are consulted
217 2. If no print method is found, three internal dictionaries are consulted
218 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
218 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
219 and :attr:`deferred_printers`.
219 and :attr:`deferred_printers`.
220
220
221 Users should use these dictionaries to register functions that will be
221 Users should use these dictionaries to register functions that will be
222 used to compute the format data for their objects (if those objects don't
222 used to compute the format data for their objects (if those objects don't
223 have the special print methods). The easiest way of using these
223 have the special print methods). The easiest way of using these
224 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
224 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
225 methods.
225 methods.
226
226
227 If no function/callable is found to compute the format data, ``None`` is
227 If no function/callable is found to compute the format data, ``None`` is
228 returned and this format type is not used.
228 returned and this format type is not used.
229 """
229 """
230
230
231 format_type = Unicode('text/plain')
231 format_type = Unicode('text/plain')
232
232
233 enabled = Bool(True, config=True)
233 enabled = Bool(True, config=True)
234
234
235 print_method = ObjectName('__repr__')
235 print_method = ObjectName('__repr__')
236
236
237 # The singleton printers.
237 # The singleton printers.
238 # Maps the IDs of the builtin singleton objects to the format functions.
238 # Maps the IDs of the builtin singleton objects to the format functions.
239 singleton_printers = Dict(config=True)
239 singleton_printers = Dict(config=True)
240 def _singleton_printers_default(self):
240 def _singleton_printers_default(self):
241 return {}
241 return {}
242
242
243 # The type-specific printers.
243 # The type-specific printers.
244 # Map type objects to the format functions.
244 # Map type objects to the format functions.
245 type_printers = Dict(config=True)
245 type_printers = Dict(config=True)
246 def _type_printers_default(self):
246 def _type_printers_default(self):
247 return {}
247 return {}
248
248
249 # The deferred-import type-specific printers.
249 # The deferred-import type-specific printers.
250 # Map (modulename, classname) pairs to the format functions.
250 # Map (modulename, classname) pairs to the format functions.
251 deferred_printers = Dict(config=True)
251 deferred_printers = Dict(config=True)
252 def _deferred_printers_default(self):
252 def _deferred_printers_default(self):
253 return {}
253 return {}
254
254
255 def __call__(self, obj):
255 def __call__(self, obj):
256 """Compute the format for an object."""
256 """Compute the format for an object."""
257 if self.enabled:
257 if self.enabled:
258 obj_id = id(obj)
258 obj_id = id(obj)
259 try:
259 try:
260 obj_class = getattr(obj, '__class__', None) or type(obj)
260 obj_class = getattr(obj, '__class__', None) or type(obj)
261 # First try to find registered singleton printers for the type.
261 # First try to find registered singleton printers for the type.
262 try:
262 try:
263 printer = self.singleton_printers[obj_id]
263 printer = self.singleton_printers[obj_id]
264 except (TypeError, KeyError):
264 except (TypeError, KeyError):
265 pass
265 pass
266 else:
266 else:
267 return printer(obj)
267 return printer(obj)
268 # Next look for type_printers.
268 # Next look for type_printers.
269 for cls in pretty._get_mro(obj_class):
269 for cls in pretty._get_mro(obj_class):
270 if cls in self.type_printers:
270 if cls in self.type_printers:
271 return self.type_printers[cls](obj)
271 return self.type_printers[cls](obj)
272 else:
272 else:
273 printer = self._in_deferred_types(cls)
273 printer = self._in_deferred_types(cls)
274 if printer is not None:
274 if printer is not None:
275 return printer(obj)
275 return printer(obj)
276 # Finally look for special method names.
276 # Finally look for special method names.
277 if hasattr(obj_class, self.print_method):
277 if hasattr(obj_class, self.print_method):
278 printer = getattr(obj_class, self.print_method)
278 printer = getattr(obj_class, self.print_method)
279 return printer(obj)
279 return printer(obj)
280 return None
280 return None
281 except Exception:
281 except Exception:
282 pass
282 pass
283 else:
283 else:
284 return None
284 return None
285
285
286 def for_type(self, typ, func):
286 def for_type(self, typ, func):
287 """Add a format function for a given type.
287 """Add a format function for a given type.
288
288
289 Parameters
289 Parameters
290 -----------
290 -----------
291 typ : class
291 typ : class
292 The class of the object that will be formatted using `func`.
292 The class of the object that will be formatted using `func`.
293 func : callable
293 func : callable
294 The callable that will be called to compute the format data. The
294 The callable that will be called to compute the format data. The
295 call signature of this function is simple, it must take the
295 call signature of this function is simple, it must take the
296 object to be formatted and return the raw data for the given
296 object to be formatted and return the raw data for the given
297 format. Subclasses may use a different call signature for the
297 format. Subclasses may use a different call signature for the
298 `func` argument.
298 `func` argument.
299 """
299 """
300 oldfunc = self.type_printers.get(typ, None)
300 oldfunc = self.type_printers.get(typ, None)
301 if func is not None:
301 if func is not None:
302 # To support easy restoration of old printers, we need to ignore
302 # To support easy restoration of old printers, we need to ignore
303 # Nones.
303 # Nones.
304 self.type_printers[typ] = func
304 self.type_printers[typ] = func
305 return oldfunc
305 return oldfunc
306
306
307 def for_type_by_name(self, type_module, type_name, func):
307 def for_type_by_name(self, type_module, type_name, func):
308 """Add a format function for a type specified by the full dotted
308 """Add a format function for a type specified by the full dotted
309 module and name of the type, rather than the type of the object.
309 module and name of the type, rather than the type of the object.
310
310
311 Parameters
311 Parameters
312 ----------
312 ----------
313 type_module : str
313 type_module : str
314 The full dotted name of the module the type is defined in, like
314 The full dotted name of the module the type is defined in, like
315 ``numpy``.
315 ``numpy``.
316 type_name : str
316 type_name : str
317 The name of the type (the class name), like ``dtype``
317 The name of the type (the class name), like ``dtype``
318 func : callable
318 func : callable
319 The callable that will be called to compute the format data. The
319 The callable that will be called to compute the format data. The
320 call signature of this function is simple, it must take the
320 call signature of this function is simple, it must take the
321 object to be formatted and return the raw data for the given
321 object to be formatted and return the raw data for the given
322 format. Subclasses may use a different call signature for the
322 format. Subclasses may use a different call signature for the
323 `func` argument.
323 `func` argument.
324 """
324 """
325 key = (type_module, type_name)
325 key = (type_module, type_name)
326 oldfunc = self.deferred_printers.get(key, None)
326 oldfunc = self.deferred_printers.get(key, None)
327 if func is not None:
327 if func is not None:
328 # To support easy restoration of old printers, we need to ignore
328 # To support easy restoration of old printers, we need to ignore
329 # Nones.
329 # Nones.
330 self.deferred_printers[key] = func
330 self.deferred_printers[key] = func
331 return oldfunc
331 return oldfunc
332
332
333 def _in_deferred_types(self, cls):
333 def _in_deferred_types(self, cls):
334 """
334 """
335 Check if the given class is specified in the deferred type registry.
335 Check if the given class is specified in the deferred type registry.
336
336
337 Returns the printer from the registry if it exists, and None if the
337 Returns the printer from the registry if it exists, and None if the
338 class is not in the registry. Successful matches will be moved to the
338 class is not in the registry. Successful matches will be moved to the
339 regular type registry for future use.
339 regular type registry for future use.
340 """
340 """
341 mod = getattr(cls, '__module__', None)
341 mod = getattr(cls, '__module__', None)
342 name = getattr(cls, '__name__', None)
342 name = getattr(cls, '__name__', None)
343 key = (mod, name)
343 key = (mod, name)
344 printer = None
344 printer = None
345 if key in self.deferred_printers:
345 if key in self.deferred_printers:
346 # Move the printer over to the regular registry.
346 # Move the printer over to the regular registry.
347 printer = self.deferred_printers.pop(key)
347 printer = self.deferred_printers.pop(key)
348 self.type_printers[cls] = printer
348 self.type_printers[cls] = printer
349 return printer
349 return printer
350
350
351
351
352 class PlainTextFormatter(BaseFormatter):
352 class PlainTextFormatter(BaseFormatter):
353 """The default pretty-printer.
353 """The default pretty-printer.
354
354
355 This uses :mod:`IPython.lib.pretty` to compute the format data of
355 This uses :mod:`IPython.lib.pretty` to compute the format data of
356 the object. If the object cannot be pretty printed, :func:`repr` is used.
356 the object. If the object cannot be pretty printed, :func:`repr` is used.
357 See the documentation of :mod:`IPython.lib.pretty` for details on
357 See the documentation of :mod:`IPython.lib.pretty` for details on
358 how to write pretty printers. Here is a simple example::
358 how to write pretty printers. Here is a simple example::
359
359
360 def dtype_pprinter(obj, p, cycle):
360 def dtype_pprinter(obj, p, cycle):
361 if cycle:
361 if cycle:
362 return p.text('dtype(...)')
362 return p.text('dtype(...)')
363 if hasattr(obj, 'fields'):
363 if hasattr(obj, 'fields'):
364 if obj.fields is None:
364 if obj.fields is None:
365 p.text(repr(obj))
365 p.text(repr(obj))
366 else:
366 else:
367 p.begin_group(7, 'dtype([')
367 p.begin_group(7, 'dtype([')
368 for i, field in enumerate(obj.descr):
368 for i, field in enumerate(obj.descr):
369 if i > 0:
369 if i > 0:
370 p.text(',')
370 p.text(',')
371 p.breakable()
371 p.breakable()
372 p.pretty(field)
372 p.pretty(field)
373 p.end_group(7, '])')
373 p.end_group(7, '])')
374 """
374 """
375
375
376 # The format type of data returned.
376 # The format type of data returned.
377 format_type = Unicode('text/plain')
377 format_type = Unicode('text/plain')
378
378
379 # This subclass ignores this attribute as it always need to return
379 # This subclass ignores this attribute as it always need to return
380 # something.
380 # something.
381 enabled = Bool(True, config=False)
381 enabled = Bool(True, config=False)
382
382
383 # Look for a _repr_pretty_ methods to use for pretty printing.
383 # Look for a _repr_pretty_ methods to use for pretty printing.
384 print_method = ObjectName('_repr_pretty_')
384 print_method = ObjectName('_repr_pretty_')
385
385
386 # Whether to pretty-print or not.
386 # Whether to pretty-print or not.
387 pprint = Bool(True, config=True)
387 pprint = Bool(True, config=True)
388
388
389 # Whether to be verbose or not.
389 # Whether to be verbose or not.
390 verbose = Bool(False, config=True)
390 verbose = Bool(False, config=True)
391
391
392 # The maximum width.
392 # The maximum width.
393 max_width = Integer(79, config=True)
393 max_width = Integer(79, config=True)
394
394
395 # The newline character.
395 # The newline character.
396 newline = Unicode('\n', config=True)
396 newline = Unicode('\n', config=True)
397
397
398 # format-string for pprinting floats
398 # format-string for pprinting floats
399 float_format = Unicode('%r')
399 float_format = Unicode('%r')
400 # setter for float precision, either int or direct format-string
400 # setter for float precision, either int or direct format-string
401 float_precision = CUnicode('', config=True)
401 float_precision = CUnicode('', config=True)
402
402
403 def _float_precision_changed(self, name, old, new):
403 def _float_precision_changed(self, name, old, new):
404 """float_precision changed, set float_format accordingly.
404 """float_precision changed, set float_format accordingly.
405
405
406 float_precision can be set by int or str.
406 float_precision can be set by int or str.
407 This will set float_format, after interpreting input.
407 This will set float_format, after interpreting input.
408 If numpy has been imported, numpy print precision will also be set.
408 If numpy has been imported, numpy print precision will also be set.
409
409
410 integer `n` sets format to '%.nf', otherwise, format set directly.
410 integer `n` sets format to '%.nf', otherwise, format set directly.
411
411
412 An empty string returns to defaults (repr for float, 8 for numpy).
412 An empty string returns to defaults (repr for float, 8 for numpy).
413
413
414 This parameter can be set via the '%precision' magic.
414 This parameter can be set via the '%precision' magic.
415 """
415 """
416
416
417 if '%' in new:
417 if '%' in new:
418 # got explicit format string
418 # got explicit format string
419 fmt = new
419 fmt = new
420 try:
420 try:
421 fmt%3.14159
421 fmt%3.14159
422 except Exception:
422 except Exception:
423 raise ValueError("Precision must be int or format string, not %r"%new)
423 raise ValueError("Precision must be int or format string, not %r"%new)
424 elif new:
424 elif new:
425 # otherwise, should be an int
425 # otherwise, should be an int
426 try:
426 try:
427 i = int(new)
427 i = int(new)
428 assert i >= 0
428 assert i >= 0
429 except ValueError:
429 except ValueError:
430 raise ValueError("Precision must be int or format string, not %r"%new)
430 raise ValueError("Precision must be int or format string, not %r"%new)
431 except AssertionError:
431 except AssertionError:
432 raise ValueError("int precision must be non-negative, not %r"%i)
432 raise ValueError("int precision must be non-negative, not %r"%i)
433
433
434 fmt = '%%.%if'%i
434 fmt = '%%.%if'%i
435 if 'numpy' in sys.modules:
435 if 'numpy' in sys.modules:
436 # set numpy precision if it has been imported
436 # set numpy precision if it has been imported
437 import numpy
437 import numpy
438 numpy.set_printoptions(precision=i)
438 numpy.set_printoptions(precision=i)
439 else:
439 else:
440 # default back to repr
440 # default back to repr
441 fmt = '%r'
441 fmt = '%r'
442 if 'numpy' in sys.modules:
442 if 'numpy' in sys.modules:
443 import numpy
443 import numpy
444 # numpy default is 8
444 # numpy default is 8
445 numpy.set_printoptions(precision=8)
445 numpy.set_printoptions(precision=8)
446 self.float_format = fmt
446 self.float_format = fmt
447
447
448 # Use the default pretty printers from IPython.lib.pretty.
448 # Use the default pretty printers from IPython.lib.pretty.
449 def _singleton_printers_default(self):
449 def _singleton_printers_default(self):
450 return pretty._singleton_pprinters.copy()
450 return pretty._singleton_pprinters.copy()
451
451
452 def _type_printers_default(self):
452 def _type_printers_default(self):
453 d = pretty._type_pprinters.copy()
453 d = pretty._type_pprinters.copy()
454 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
454 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
455 return d
455 return d
456
456
457 def _deferred_printers_default(self):
457 def _deferred_printers_default(self):
458 return pretty._deferred_type_pprinters.copy()
458 return pretty._deferred_type_pprinters.copy()
459
459
460 #### FormatterABC interface ####
460 #### FormatterABC interface ####
461
461
462 def __call__(self, obj):
462 def __call__(self, obj):
463 """Compute the pretty representation of the object."""
463 """Compute the pretty representation of the object."""
464 if not self.pprint:
464 if not self.pprint:
465 try:
465 try:
466 return repr(obj)
466 return repr(obj)
467 except TypeError:
467 except TypeError:
468 return ''
468 return ''
469 else:
469 else:
470 # This uses use StringIO, as cStringIO doesn't handle unicode.
470 # This uses use StringIO, as cStringIO doesn't handle unicode.
471 stream = StringIO()
471 stream = StringIO()
472 # self.newline.encode() is a quick fix for issue gh-597. We need to
472 # self.newline.encode() is a quick fix for issue gh-597. We need to
473 # ensure that stream does not get a mix of unicode and bytestrings,
473 # ensure that stream does not get a mix of unicode and bytestrings,
474 # or it will cause trouble.
474 # or it will cause trouble.
475 printer = pretty.RepresentationPrinter(stream, self.verbose,
475 printer = pretty.RepresentationPrinter(stream, self.verbose,
476 self.max_width, unicode_to_str(self.newline),
476 self.max_width, unicode_to_str(self.newline),
477 singleton_pprinters=self.singleton_printers,
477 singleton_pprinters=self.singleton_printers,
478 type_pprinters=self.type_printers,
478 type_pprinters=self.type_printers,
479 deferred_pprinters=self.deferred_printers)
479 deferred_pprinters=self.deferred_printers)
480 printer.pretty(obj)
480 printer.pretty(obj)
481 printer.flush()
481 printer.flush()
482 return stream.getvalue()
482 return stream.getvalue()
483
483
484
484
485 class HTMLFormatter(BaseFormatter):
485 class HTMLFormatter(BaseFormatter):
486 """An HTML formatter.
486 """An HTML formatter.
487
487
488 To define the callables that compute the HTML representation of your
488 To define the callables that compute the HTML representation of your
489 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
489 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
490 or :meth:`for_type_by_name` methods to register functions that handle
490 or :meth:`for_type_by_name` methods to register functions that handle
491 this.
491 this.
492
492
493 The return value of this formatter should be a valid HTML snippet that
493 The return value of this formatter should be a valid HTML snippet that
494 could be injected into an existing DOM. It should *not* include the
494 could be injected into an existing DOM. It should *not* include the
495 ```<html>`` or ```<body>`` tags.
495 ```<html>`` or ```<body>`` tags.
496 """
496 """
497 format_type = Unicode('text/html')
497 format_type = Unicode('text/html')
498
498
499 print_method = ObjectName('_repr_html_')
499 print_method = ObjectName('_repr_html_')
500
500
501
501
502 class SVGFormatter(BaseFormatter):
502 class SVGFormatter(BaseFormatter):
503 """An SVG formatter.
503 """An SVG formatter.
504
504
505 To define the callables that compute the SVG representation of your
505 To define the callables that compute the SVG representation of your
506 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
506 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
507 or :meth:`for_type_by_name` methods to register functions that handle
507 or :meth:`for_type_by_name` methods to register functions that handle
508 this.
508 this.
509
509
510 The return value of this formatter should be valid SVG enclosed in
510 The return value of this formatter should be valid SVG enclosed in
511 ```<svg>``` tags, that could be injected into an existing DOM. It should
511 ```<svg>``` tags, that could be injected into an existing DOM. It should
512 *not* include the ```<html>`` or ```<body>`` tags.
512 *not* include the ```<html>`` or ```<body>`` tags.
513 """
513 """
514 format_type = Unicode('image/svg+xml')
514 format_type = Unicode('image/svg+xml')
515
515
516 print_method = ObjectName('_repr_svg_')
516 print_method = ObjectName('_repr_svg_')
517
517
518
518
519 class PNGFormatter(BaseFormatter):
519 class PNGFormatter(BaseFormatter):
520 """A PNG formatter.
520 """A PNG formatter.
521
521
522 To define the callables that compute the PNG representation of your
522 To define the callables that compute the PNG representation of your
523 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
523 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
524 or :meth:`for_type_by_name` methods to register functions that handle
524 or :meth:`for_type_by_name` methods to register functions that handle
525 this.
525 this.
526
526
527 The return value of this formatter should be raw PNG data, *not*
527 The return value of this formatter should be raw PNG data, *not*
528 base64 encoded.
528 base64 encoded.
529 """
529 """
530 format_type = Unicode('image/png')
530 format_type = Unicode('image/png')
531
531
532 print_method = ObjectName('_repr_png_')
532 print_method = ObjectName('_repr_png_')
533
533
534
534
535 class JPEGFormatter(BaseFormatter):
535 class JPEGFormatter(BaseFormatter):
536 """A JPEG formatter.
536 """A JPEG formatter.
537
537
538 To define the callables that compute the JPEG representation of your
538 To define the callables that compute the JPEG representation of your
539 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
539 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
540 or :meth:`for_type_by_name` methods to register functions that handle
540 or :meth:`for_type_by_name` methods to register functions that handle
541 this.
541 this.
542
542
543 The return value of this formatter should be raw JPEG data, *not*
543 The return value of this formatter should be raw JPEG data, *not*
544 base64 encoded.
544 base64 encoded.
545 """
545 """
546 format_type = Unicode('image/jpeg')
546 format_type = Unicode('image/jpeg')
547
547
548 print_method = ObjectName('_repr_jpeg_')
548 print_method = ObjectName('_repr_jpeg_')
549
549
550
550
551 class LatexFormatter(BaseFormatter):
551 class LatexFormatter(BaseFormatter):
552 """A LaTeX formatter.
552 """A LaTeX formatter.
553
553
554 To define the callables that compute the LaTeX representation of your
554 To define the callables that compute the LaTeX representation of your
555 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
555 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
556 or :meth:`for_type_by_name` methods to register functions that handle
556 or :meth:`for_type_by_name` methods to register functions that handle
557 this.
557 this.
558
558
559 The return value of this formatter should be a valid LaTeX equation,
559 The return value of this formatter should be a valid LaTeX equation,
560 enclosed in either ```$```, ```$$``` or another LaTeX equation
560 enclosed in either ```$```, ```$$``` or another LaTeX equation
561 environment.
561 environment.
562 """
562 """
563 format_type = Unicode('text/latex')
563 format_type = Unicode('text/latex')
564
564
565 print_method = ObjectName('_repr_latex_')
565 print_method = ObjectName('_repr_latex_')
566
566
567
567
568 class JSONFormatter(BaseFormatter):
568 class JSONFormatter(BaseFormatter):
569 """A JSON string formatter.
569 """A JSON string formatter.
570
570
571 To define the callables that compute the JSON string representation of
571 To define the callables that compute the JSON string representation of
572 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
572 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
573 or :meth:`for_type_by_name` methods to register functions that handle
573 or :meth:`for_type_by_name` methods to register functions that handle
574 this.
574 this.
575
575
576 The return value of this formatter should be a valid JSON string.
576 The return value of this formatter should be a valid JSON string.
577 """
577 """
578 format_type = Unicode('application/json')
578 format_type = Unicode('application/json')
579
579
580 print_method = ObjectName('_repr_json_')
580 print_method = ObjectName('_repr_json_')
581
581
582
582
583 class JavascriptFormatter(BaseFormatter):
583 class JavascriptFormatter(BaseFormatter):
584 """A Javascript formatter.
584 """A Javascript formatter.
585
585
586 To define the callables that compute the Javascript representation of
586 To define the callables that compute the Javascript representation of
587 your objects, define a :meth:`_repr_javascript_` method or use the
587 your objects, define a :meth:`_repr_javascript_` method or use the
588 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
588 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
589 that handle this.
589 that handle this.
590
590
591 The return value of this formatter should be valid Javascript code and
591 The return value of this formatter should be valid Javascript code and
592 should *not* be enclosed in ```<script>``` tags.
592 should *not* be enclosed in ```<script>``` tags.
593 """
593 """
594 format_type = Unicode('application/javascript')
594 format_type = Unicode('application/javascript')
595
595
596 print_method = ObjectName('_repr_javascript_')
596 print_method = ObjectName('_repr_javascript_')
597
597
598 FormatterABC.register(BaseFormatter)
598 FormatterABC.register(BaseFormatter)
599 FormatterABC.register(PlainTextFormatter)
599 FormatterABC.register(PlainTextFormatter)
600 FormatterABC.register(HTMLFormatter)
600 FormatterABC.register(HTMLFormatter)
601 FormatterABC.register(SVGFormatter)
601 FormatterABC.register(SVGFormatter)
602 FormatterABC.register(PNGFormatter)
602 FormatterABC.register(PNGFormatter)
603 FormatterABC.register(JPEGFormatter)
603 FormatterABC.register(JPEGFormatter)
604 FormatterABC.register(LatexFormatter)
604 FormatterABC.register(LatexFormatter)
605 FormatterABC.register(JSONFormatter)
605 FormatterABC.register(JSONFormatter)
606 FormatterABC.register(JavascriptFormatter)
606 FormatterABC.register(JavascriptFormatter)
607
607
608
608
609 def format_display_data(obj, include=None, exclude=None):
609 def format_display_data(obj, include=None, exclude=None):
610 """Return a format data dict for an object.
610 """Return a format data dict for an object.
611
611
612 By default all format types will be computed.
612 By default all format types will be computed.
613
613
614 The following MIME types are currently implemented:
614 The following MIME types are currently implemented:
615
615
616 * text/plain
616 * text/plain
617 * text/html
617 * text/html
618 * text/latex
618 * text/latex
619 * application/json
619 * application/json
620 * application/javascript
620 * application/javascript
621 * image/png
621 * image/png
622 * image/jpeg
622 * image/jpeg
623 * image/svg+xml
623 * image/svg+xml
624
624
625 Parameters
625 Parameters
626 ----------
626 ----------
627 obj : object
627 obj : object
628 The Python object whose format data will be computed.
628 The Python object whose format data will be computed.
629
629
630 Returns
630 Returns
631 -------
631 -------
632 format_dict : dict
632 format_dict : dict
633 A dictionary of key/value pairs, one or each format that was
633 A dictionary of key/value pairs, one or each format that was
634 generated for the object. The keys are the format types, which
634 generated for the object. The keys are the format types, which
635 will usually be MIME type strings and the values and JSON'able
635 will usually be MIME type strings and the values and JSON'able
636 data structure containing the raw data for the representation in
636 data structure containing the raw data for the representation in
637 that format.
637 that format.
638 include : list or tuple, optional
638 include : list or tuple, optional
639 A list of format type strings (MIME types) to include in the
639 A list of format type strings (MIME types) to include in the
640 format data dict. If this is set *only* the format types included
640 format data dict. If this is set *only* the format types included
641 in this list will be computed.
641 in this list will be computed.
642 exclude : list or tuple, optional
642 exclude : list or tuple, optional
643 A list of format type string (MIME types) to exclue in the format
643 A list of format type string (MIME types) to exclue in the format
644 data dict. If this is set all format types will be computed,
644 data dict. If this is set all format types will be computed,
645 except for those included in this argument.
645 except for those included in this argument.
646 """
646 """
647 from IPython.core.interactiveshell import InteractiveShell
647 from IPython.core.interactiveshell import InteractiveShell
648
648
649 InteractiveShell.instance().display_formatter.format(
649 InteractiveShell.instance().display_formatter.format(
650 obj,
650 obj,
651 include,
651 include,
652 exclude
652 exclude
653 )
653 )
654
654
General Comments 0
You need to be logged in to leave comments. Login now