##// END OF EJS Templates
fix error in doc (arg->kwarg) and pep-8
Matthias BUSSONNIER -
Show More
@@ -1,356 +1,356 b''
1 1 # encoding: utf-8
2 2 """
3 3 A base class for objects that are configurable.
4 4
5 5 Inheritance diagram:
6 6
7 7 .. inheritance-diagram:: IPython.config.configurable
8 8 :parts: 3
9 9
10 10 Authors:
11 11
12 12 * Brian Granger
13 13 * Fernando Perez
14 14 * Min RK
15 15 """
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Copyright (C) 2008-2011 The IPython Development Team
19 19 #
20 20 # Distributed under the terms of the BSD License. The full license is in
21 21 # the file COPYING, distributed as part of this software.
22 22 #-----------------------------------------------------------------------------
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Imports
26 26 #-----------------------------------------------------------------------------
27 27
28 28 import datetime
29 29 from copy import deepcopy
30 30
31 31 from loader import Config
32 32 from IPython.utils.traitlets import HasTraits, Instance
33 33 from IPython.utils.text import indent, wrap_paragraphs
34 34
35 35
36 36 #-----------------------------------------------------------------------------
37 37 # Helper classes for Configurables
38 38 #-----------------------------------------------------------------------------
39 39
40 40
41 41 class ConfigurableError(Exception):
42 42 pass
43 43
44 44
45 45 class MultipleInstanceError(ConfigurableError):
46 46 pass
47 47
48 48 #-----------------------------------------------------------------------------
49 49 # Configurable implementation
50 50 #-----------------------------------------------------------------------------
51 51
52 52 class Configurable(HasTraits):
53 53
54 config = Instance(Config,(),{})
54 config = Instance(Config, (), {})
55 55 created = None
56 56
57 57 def __init__(self, **kwargs):
58 58 """Create a configurable given a config config.
59 59
60 60 Parameters
61 61 ----------
62 62 config : Config
63 63 If this is empty, default values are used. If config is a
64 64 :class:`Config` instance, it will be used to configure the
65 65 instance.
66 66
67 67 Notes
68 68 -----
69 69 Subclasses of Configurable must call the :meth:`__init__` method of
70 70 :class:`Configurable` *before* doing anything else and using
71 71 :func:`super`::
72 72
73 73 class MyConfigurable(Configurable):
74 74 def __init__(self, config=None):
75 super(MyConfigurable, self).__init__(config)
75 super(MyConfigurable, self).__init__(config=config)
76 76 # Then any other code you need to finish initialization.
77 77
78 78 This ensures that instances will be configured properly.
79 79 """
80 80 config = kwargs.pop('config', None)
81 81 if config is not None:
82 82 # We used to deepcopy, but for now we are trying to just save
83 83 # by reference. This *could* have side effects as all components
84 84 # will share config. In fact, I did find such a side effect in
85 85 # _config_changed below. If a config attribute value was a mutable type
86 86 # all instances of a component were getting the same copy, effectively
87 87 # making that a class attribute.
88 88 # self.config = deepcopy(config)
89 89 self.config = config
90 90 # This should go second so individual keyword arguments override
91 91 # the values in config.
92 92 super(Configurable, self).__init__(**kwargs)
93 93 self.created = datetime.datetime.now()
94 94
95 95 #-------------------------------------------------------------------------
96 96 # Static trait notifiations
97 97 #-------------------------------------------------------------------------
98 98
99 99 def _config_changed(self, name, old, new):
100 100 """Update all the class traits having ``config=True`` as metadata.
101 101
102 102 For any class trait with a ``config`` metadata attribute that is
103 103 ``True``, we update the trait with the value of the corresponding
104 104 config entry.
105 105 """
106 106 # Get all traits with a config metadata entry that is True
107 107 traits = self.traits(config=True)
108 108
109 109 # We auto-load config section for this class as well as any parent
110 110 # classes that are Configurable subclasses. This starts with Configurable
111 111 # and works down the mro loading the config for each section.
112 112 section_names = [cls.__name__ for cls in \
113 113 reversed(self.__class__.__mro__) if
114 114 issubclass(cls, Configurable) and issubclass(self.__class__, cls)]
115 115
116 116 for sname in section_names:
117 117 # Don't do a blind getattr as that would cause the config to
118 118 # dynamically create the section with name self.__class__.__name__.
119 119 if new._has_section(sname):
120 120 my_config = new[sname]
121 121 for k, v in traits.iteritems():
122 122 # Don't allow traitlets with config=True to start with
123 123 # uppercase. Otherwise, they are confused with Config
124 124 # subsections. But, developers shouldn't have uppercase
125 125 # attributes anyways! (PEP 6)
126 126 if k[0].upper()==k[0] and not k.startswith('_'):
127 127 raise ConfigurableError('Configurable traitlets with '
128 128 'config=True must start with a lowercase so they are '
129 129 'not confused with Config subsections: %s.%s' % \
130 130 (self.__class__.__name__, k))
131 131 try:
132 132 # Here we grab the value from the config
133 133 # If k has the naming convention of a config
134 134 # section, it will be auto created.
135 135 config_value = my_config[k]
136 136 except KeyError:
137 137 pass
138 138 else:
139 139 # print "Setting %s.%s from %s.%s=%r" % \
140 140 # (self.__class__.__name__,k,sname,k,config_value)
141 141 # We have to do a deepcopy here if we don't deepcopy the entire
142 142 # config object. If we don't, a mutable config_value will be
143 143 # shared by all instances, effectively making it a class attribute.
144 144 setattr(self, k, deepcopy(config_value))
145 145
146 146 def update_config(self, config):
147 147 """Fire the traits events when the config is updated."""
148 148 # Save a copy of the current config.
149 149 newconfig = deepcopy(self.config)
150 150 # Merge the new config into the current one.
151 151 newconfig._merge(config)
152 152 # Save the combined config as self.config, which triggers the traits
153 153 # events.
154 154 self.config = newconfig
155 155
156 156 @classmethod
157 157 def class_get_help(cls, inst=None):
158 158 """Get the help string for this class in ReST format.
159 159
160 160 If `inst` is given, it's current trait values will be used in place of
161 161 class defaults.
162 162 """
163 163 assert inst is None or isinstance(inst, cls)
164 164 cls_traits = cls.class_traits(config=True)
165 165 final_help = []
166 166 final_help.append(u'%s options' % cls.__name__)
167 167 final_help.append(len(final_help[0])*u'-')
168 for k,v in sorted(cls.class_traits(config=True).iteritems()):
168 for k, v in sorted(cls.class_traits(config=True).iteritems()):
169 169 help = cls.class_get_trait_help(v, inst)
170 170 final_help.append(help)
171 171 return '\n'.join(final_help)
172 172
173 173 @classmethod
174 174 def class_get_trait_help(cls, trait, inst=None):
175 175 """Get the help string for a single trait.
176 176
177 177 If `inst` is given, it's current trait values will be used in place of
178 178 the class default.
179 179 """
180 180 assert inst is None or isinstance(inst, cls)
181 181 lines = []
182 182 header = "--%s.%s=<%s>" % (cls.__name__, trait.name, trait.__class__.__name__)
183 183 lines.append(header)
184 184 if inst is not None:
185 185 lines.append(indent('Current: %r' % getattr(inst, trait.name), 4))
186 186 else:
187 187 try:
188 188 dvr = repr(trait.get_default_value())
189 189 except Exception:
190 190 dvr = None # ignore defaults we can't construct
191 191 if dvr is not None:
192 192 if len(dvr) > 64:
193 193 dvr = dvr[:61]+'...'
194 194 lines.append(indent('Default: %s' % dvr, 4))
195 195 if 'Enum' in trait.__class__.__name__:
196 196 # include Enum choices
197 197 lines.append(indent('Choices: %r' % (trait.values,)))
198 198
199 199 help = trait.get_metadata('help')
200 200 if help is not None:
201 201 help = '\n'.join(wrap_paragraphs(help, 76))
202 202 lines.append(indent(help, 4))
203 203 return '\n'.join(lines)
204 204
205 205 @classmethod
206 206 def class_print_help(cls, inst=None):
207 207 """Get the help string for a single trait and print it."""
208 208 print cls.class_get_help(inst)
209 209
210 210 @classmethod
211 211 def class_config_section(cls):
212 212 """Get the config class config section"""
213 213 def c(s):
214 214 """return a commented, wrapped block."""
215 215 s = '\n\n'.join(wrap_paragraphs(s, 78))
216 216
217 217 return '# ' + s.replace('\n', '\n# ')
218 218
219 219 # section header
220 220 breaker = '#' + '-'*78
221 s = "# %s configuration"%cls.__name__
221 s = "# %s configuration" % cls.__name__
222 222 lines = [breaker, s, breaker, '']
223 223 # get the description trait
224 224 desc = cls.class_traits().get('description')
225 225 if desc:
226 226 desc = desc.default_value
227 227 else:
228 228 # no description trait, use __doc__
229 229 desc = getattr(cls, '__doc__', '')
230 230 if desc:
231 231 lines.append(c(desc))
232 232 lines.append('')
233 233
234 234 parents = []
235 235 for parent in cls.mro():
236 236 # only include parents that are not base classes
237 237 # and are not the class itself
238 238 # and have some configurable traits to inherit
239 239 if parent is not cls and issubclass(parent, Configurable) and \
240 240 parent.class_traits(config=True):
241 241 parents.append(parent)
242 242
243 243 if parents:
244 244 pstr = ', '.join([ p.__name__ for p in parents ])
245 245 lines.append(c('%s will inherit config from: %s'%(cls.__name__, pstr)))
246 246 lines.append('')
247 247
248 for name,trait in cls.class_traits(config=True).iteritems():
248 for name, trait in cls.class_traits(config=True).iteritems():
249 249 help = trait.get_metadata('help') or ''
250 250 lines.append(c(help))
251 251 lines.append('# c.%s.%s = %r'%(cls.__name__, name, trait.get_default_value()))
252 252 lines.append('')
253 253 return '\n'.join(lines)
254 254
255 255
256 256
257 257 class SingletonConfigurable(Configurable):
258 258 """A configurable that only allows one instance.
259 259
260 260 This class is for classes that should only have one instance of itself
261 261 or *any* subclass. To create and retrieve such a class use the
262 262 :meth:`SingletonConfigurable.instance` method.
263 263 """
264 264
265 265 _instance = None
266 266
267 267 @classmethod
268 268 def _walk_mro(cls):
269 269 """Walk the cls.mro() for parent classes that are also singletons
270 270
271 271 For use in instance()
272 272 """
273 273
274 274 for subclass in cls.mro():
275 275 if issubclass(cls, subclass) and \
276 276 issubclass(subclass, SingletonConfigurable) and \
277 277 subclass != SingletonConfigurable:
278 278 yield subclass
279 279
280 280 @classmethod
281 281 def clear_instance(cls):
282 282 """unset _instance for this class and singleton parents.
283 283 """
284 284 if not cls.initialized():
285 285 return
286 286 for subclass in cls._walk_mro():
287 287 if isinstance(subclass._instance, cls):
288 288 # only clear instances that are instances
289 289 # of the calling class
290 290 subclass._instance = None
291 291
292 292 @classmethod
293 293 def instance(cls, *args, **kwargs):
294 294 """Returns a global instance of this class.
295 295
296 296 This method create a new instance if none have previously been created
297 297 and returns a previously created instance is one already exists.
298 298
299 299 The arguments and keyword arguments passed to this method are passed
300 300 on to the :meth:`__init__` method of the class upon instantiation.
301 301
302 302 Examples
303 303 --------
304 304
305 305 Create a singleton class using instance, and retrieve it::
306 306
307 307 >>> from IPython.config.configurable import SingletonConfigurable
308 308 >>> class Foo(SingletonConfigurable): pass
309 309 >>> foo = Foo.instance()
310 310 >>> foo == Foo.instance()
311 311 True
312 312
313 313 Create a subclass that is retrived using the base class instance::
314 314
315 315 >>> class Bar(SingletonConfigurable): pass
316 316 >>> class Bam(Bar): pass
317 317 >>> bam = Bam.instance()
318 318 >>> bam == Bar.instance()
319 319 True
320 320 """
321 321 # Create and save the instance
322 322 if cls._instance is None:
323 323 inst = cls(*args, **kwargs)
324 324 # Now make sure that the instance will also be returned by
325 325 # parent classes' _instance attribute.
326 326 for subclass in cls._walk_mro():
327 327 subclass._instance = inst
328 328
329 329 if isinstance(cls._instance, cls):
330 330 return cls._instance
331 331 else:
332 332 raise MultipleInstanceError(
333 333 'Multiple incompatible subclass instances of '
334 334 '%s are being created.' % cls.__name__
335 335 )
336 336
337 337 @classmethod
338 338 def initialized(cls):
339 339 """Has an instance been created?"""
340 340 return hasattr(cls, "_instance") and cls._instance is not None
341 341
342 342
343 343 class LoggingConfigurable(Configurable):
344 344 """A parent class for Configurables that log.
345 345
346 346 Subclasses have a log trait, and the default behavior
347 347 is to get the logger from the currently running Application
348 348 via Application.instance().log.
349 349 """
350 350
351 351 log = Instance('logging.Logger')
352 352 def _log_default(self):
353 353 from IPython.config.application import Application
354 354 return Application.instance().log
355 355
356 356
@@ -1,336 +1,334 b''
1 1 # encoding: utf-8
2 2 """
3 3 An application for IPython.
4 4
5 5 All top-level applications should use the classes in this module for
6 6 handling configuration and creating componenets.
7 7
8 8 The job of an :class:`Application` is to create the master configuration
9 9 object and then create the configurable objects, passing the config to them.
10 10
11 11 Authors:
12 12
13 13 * Brian Granger
14 14 * Fernando Perez
15 15 * Min RK
16 16
17 17 """
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Copyright (C) 2008-2011 The IPython Development Team
21 21 #
22 22 # Distributed under the terms of the BSD License. The full license is in
23 23 # the file COPYING, distributed as part of this software.
24 24 #-----------------------------------------------------------------------------
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Imports
28 28 #-----------------------------------------------------------------------------
29 29
30 30 import atexit
31 31 import glob
32 32 import logging
33 33 import os
34 34 import shutil
35 35 import sys
36 36
37 37 from IPython.config.application import Application, catch_config_error
38 from IPython.config.configurable import Configurable
39 from IPython.config.loader import Config, ConfigFileNotFound
38 from IPython.config.loader import ConfigFileNotFound
40 39 from IPython.core import release, crashhandler
41 40 from IPython.core.profiledir import ProfileDir, ProfileDirError
42 41 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir
43 42 from IPython.utils.traitlets import List, Unicode, Type, Bool, Dict
44 from IPython.utils import py3compat
45 43
46 44 #-----------------------------------------------------------------------------
47 45 # Classes and functions
48 46 #-----------------------------------------------------------------------------
49 47
50 48
51 49 #-----------------------------------------------------------------------------
52 50 # Base Application Class
53 51 #-----------------------------------------------------------------------------
54 52
55 53 # aliases and flags
56 54
57 55 base_aliases = {
58 56 'profile' : 'BaseIPythonApplication.profile',
59 57 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
60 58 'log-level' : 'Application.log_level',
61 59 }
62 60
63 61 base_flags = dict(
64 62 debug = ({'Application' : {'log_level' : logging.DEBUG}},
65 63 "set log level to logging.DEBUG (maximize logging output)"),
66 64 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
67 65 "set log level to logging.CRITICAL (minimize logging output)"),
68 66 init = ({'BaseIPythonApplication' : {
69 67 'copy_config_files' : True,
70 68 'auto_create' : True}
71 69 }, """Initialize profile with default config files. This is equivalent
72 70 to running `ipython profile create <profile>` prior to startup.
73 71 """)
74 72 )
75 73
76 74
77 75 class BaseIPythonApplication(Application):
78 76
79 77 name = Unicode(u'ipython')
80 78 description = Unicode(u'IPython: an enhanced interactive Python shell.')
81 79 version = Unicode(release.version)
82 80
83 81 aliases = Dict(base_aliases)
84 82 flags = Dict(base_flags)
85 83 classes = List([ProfileDir])
86 84
87 85 # Track whether the config_file has changed,
88 86 # because some logic happens only if we aren't using the default.
89 87 config_file_specified = Bool(False)
90 88
91 89 config_file_name = Unicode(u'ipython_config.py')
92 90 def _config_file_name_default(self):
93 91 return self.name.replace('-','_') + u'_config.py'
94 92 def _config_file_name_changed(self, name, old, new):
95 93 if new != old:
96 94 self.config_file_specified = True
97 95
98 96 # The directory that contains IPython's builtin profiles.
99 97 builtin_profile_dir = Unicode(
100 98 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
101 99 )
102 100
103 101 config_file_paths = List(Unicode)
104 102 def _config_file_paths_default(self):
105 103 return [os.getcwdu()]
106 104
107 105 profile = Unicode(u'default', config=True,
108 106 help="""The IPython profile to use."""
109 107 )
110 108
111 109 def _profile_changed(self, name, old, new):
112 110 self.builtin_profile_dir = os.path.join(
113 111 get_ipython_package_dir(), u'config', u'profile', new
114 112 )
115 113
116 114 ipython_dir = Unicode(get_ipython_dir(), config=True,
117 115 help="""
118 116 The name of the IPython directory. This directory is used for logging
119 117 configuration (through profiles), history storage, etc. The default
120 118 is usually $HOME/.ipython. This options can also be specified through
121 119 the environment variable IPYTHONDIR.
122 120 """
123 121 )
124 122
125 123 overwrite = Bool(False, config=True,
126 124 help="""Whether to overwrite existing config files when copying""")
127 125 auto_create = Bool(False, config=True,
128 126 help="""Whether to create profile dir if it doesn't exist""")
129 127
130 128 config_files = List(Unicode)
131 129 def _config_files_default(self):
132 130 return [u'ipython_config.py']
133 131
134 132 copy_config_files = Bool(False, config=True,
135 133 help="""Whether to install the default config files into the profile dir.
136 134 If a new profile is being created, and IPython contains config files for that
137 135 profile, then they will be staged into the new directory. Otherwise,
138 136 default config files will be automatically generated.
139 137 """)
140 138
141 139 verbose_crash = Bool(False, config=True,
142 140 help="""Create a massive crash report when IPython encounters what may be an
143 141 internal error. The default is to append a short message to the
144 142 usual traceback""")
145 143
146 144 # The class to use as the crash handler.
147 145 crash_handler_class = Type(crashhandler.CrashHandler)
148 146
149 147 def __init__(self, **kwargs):
150 148 super(BaseIPythonApplication, self).__init__(**kwargs)
151 149 # ensure even default IPYTHONDIR exists
152 150 if not os.path.exists(self.ipython_dir):
153 151 self._ipython_dir_changed('ipython_dir', self.ipython_dir, self.ipython_dir)
154 152
155 153 #-------------------------------------------------------------------------
156 154 # Various stages of Application creation
157 155 #-------------------------------------------------------------------------
158 156
159 157 def init_crash_handler(self):
160 158 """Create a crash handler, typically setting sys.excepthook to it."""
161 159 self.crash_handler = self.crash_handler_class(self)
162 160 sys.excepthook = self.excepthook
163 161 def unset_crashhandler():
164 162 sys.excepthook = sys.__excepthook__
165 163 atexit.register(unset_crashhandler)
166 164
167 165 def excepthook(self, etype, evalue, tb):
168 166 """this is sys.excepthook after init_crashhandler
169 167
170 168 set self.verbose_crash=True to use our full crashhandler, instead of
171 169 a regular traceback with a short message (crash_handler_lite)
172 170 """
173 171
174 172 if self.verbose_crash:
175 173 return self.crash_handler(etype, evalue, tb)
176 174 else:
177 175 return crashhandler.crash_handler_lite(etype, evalue, tb)
178 176
179 177 def _ipython_dir_changed(self, name, old, new):
180 178 if old in sys.path:
181 179 sys.path.remove(old)
182 180 sys.path.append(os.path.abspath(new))
183 181 if not os.path.isdir(new):
184 182 os.makedirs(new, mode=0o777)
185 183 readme = os.path.join(new, 'README')
186 184 if not os.path.exists(readme):
187 185 path = os.path.join(get_ipython_package_dir(), u'config', u'profile')
188 186 shutil.copy(os.path.join(path, 'README'), readme)
189 187 self.log.debug("IPYTHONDIR set to: %s" % new)
190 188
191 189 def load_config_file(self, suppress_errors=True):
192 190 """Load the config file.
193 191
194 192 By default, errors in loading config are handled, and a warning
195 193 printed on screen. For testing, the suppress_errors option is set
196 194 to False, so errors will make tests fail.
197 195 """
198 196 self.log.debug("Searching path %s for config files", self.config_file_paths)
199 197 base_config = 'ipython_config.py'
200 198 self.log.debug("Attempting to load config file: %s" %
201 199 base_config)
202 200 try:
203 201 Application.load_config_file(
204 202 self,
205 203 base_config,
206 204 path=self.config_file_paths
207 205 )
208 206 except ConfigFileNotFound:
209 207 # ignore errors loading parent
210 208 self.log.debug("Config file %s not found", base_config)
211 209 pass
212 210 if self.config_file_name == base_config:
213 211 # don't load secondary config
214 212 return
215 213 self.log.debug("Attempting to load config file: %s" %
216 214 self.config_file_name)
217 215 try:
218 216 Application.load_config_file(
219 217 self,
220 218 self.config_file_name,
221 219 path=self.config_file_paths
222 220 )
223 221 except ConfigFileNotFound:
224 222 # Only warn if the default config file was NOT being used.
225 223 if self.config_file_specified:
226 224 msg = self.log.warn
227 225 else:
228 226 msg = self.log.debug
229 227 msg("Config file not found, skipping: %s", self.config_file_name)
230 228 except:
231 229 # For testing purposes.
232 230 if not suppress_errors:
233 231 raise
234 232 self.log.warn("Error loading config file: %s" %
235 233 self.config_file_name, exc_info=True)
236 234
237 235 def init_profile_dir(self):
238 236 """initialize the profile dir"""
239 237 try:
240 238 # location explicitly specified:
241 239 location = self.config.ProfileDir.location
242 240 except AttributeError:
243 241 # location not specified, find by profile name
244 242 try:
245 243 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
246 244 except ProfileDirError:
247 245 # not found, maybe create it (always create default profile)
248 if self.auto_create or self.profile=='default':
246 if self.auto_create or self.profile == 'default':
249 247 try:
250 248 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
251 249 except ProfileDirError:
252 250 self.log.fatal("Could not create profile: %r"%self.profile)
253 251 self.exit(1)
254 252 else:
255 253 self.log.info("Created profile dir: %r"%p.location)
256 254 else:
257 255 self.log.fatal("Profile %r not found."%self.profile)
258 256 self.exit(1)
259 257 else:
260 258 self.log.info("Using existing profile dir: %r"%p.location)
261 259 else:
262 260 # location is fully specified
263 261 try:
264 262 p = ProfileDir.find_profile_dir(location, self.config)
265 263 except ProfileDirError:
266 264 # not found, maybe create it
267 265 if self.auto_create:
268 266 try:
269 267 p = ProfileDir.create_profile_dir(location, self.config)
270 268 except ProfileDirError:
271 269 self.log.fatal("Could not create profile directory: %r"%location)
272 270 self.exit(1)
273 271 else:
274 272 self.log.info("Creating new profile dir: %r"%location)
275 273 else:
276 274 self.log.fatal("Profile directory %r not found."%location)
277 275 self.exit(1)
278 276 else:
279 277 self.log.info("Using existing profile dir: %r"%location)
280 278
281 279 self.profile_dir = p
282 280 self.config_file_paths.append(p.location)
283 281
284 282 def init_config_files(self):
285 283 """[optionally] copy default config files into profile dir."""
286 284 # copy config files
287 285 path = self.builtin_profile_dir
288 286 if self.copy_config_files:
289 287 src = self.profile
290 288
291 289 cfg = self.config_file_name
292 290 if path and os.path.exists(os.path.join(path, cfg)):
293 291 self.log.warn("Staging %r from %s into %r [overwrite=%s]"%(
294 292 cfg, src, self.profile_dir.location, self.overwrite)
295 293 )
296 294 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
297 295 else:
298 296 self.stage_default_config_file()
299 297 else:
300 298 # Still stage *bundled* config files, but not generated ones
301 299 # This is necessary for `ipython profile=sympy` to load the profile
302 300 # on the first go
303 301 files = glob.glob(os.path.join(path, '*.py'))
304 302 for fullpath in files:
305 303 cfg = os.path.basename(fullpath)
306 304 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
307 305 # file was copied
308 306 self.log.warn("Staging bundled %s from %s into %r"%(
309 307 cfg, self.profile, self.profile_dir.location)
310 308 )
311 309
312 310
313 311 def stage_default_config_file(self):
314 312 """auto generate default config file, and stage it into the profile."""
315 313 s = self.generate_config_file()
316 314 fname = os.path.join(self.profile_dir.location, self.config_file_name)
317 315 if self.overwrite or not os.path.exists(fname):
318 316 self.log.warn("Generating default config file: %r"%(fname))
319 317 with open(fname, 'w') as f:
320 318 f.write(s)
321 319
322 320 @catch_config_error
323 321 def initialize(self, argv=None):
324 322 # don't hook up crash handler before parsing command-line
325 323 self.parse_command_line(argv)
326 324 self.init_crash_handler()
327 325 if self.subapp is not None:
328 326 # stop here if subapp is taking over
329 327 return
330 328 cl_config = self.config
331 329 self.init_profile_dir()
332 330 self.init_config_files()
333 331 self.load_config_file()
334 332 # enforce cl-opts override configfile opts:
335 333 self.update_config(cl_config)
336 334
General Comments 0
You need to be logged in to leave comments. Login now