##// END OF EJS Templates
use App.instance() in launch_new_instance...
MinRK -
Show More
@@ -1,356 +1,354 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The :class:`~IPython.core.newapplication.Application` object for the command
4 The :class:`~IPython.core.newapplication.Application` object for the command
5 line :command:`ipython` program.
5 line :command:`ipython` program.
6
6
7 Authors
7 Authors
8 -------
8 -------
9
9
10 * Brian Granger
10 * Brian Granger
11 * Fernando Perez
11 * Fernando Perez
12 * Min Ragan-Kelley
12 * Min Ragan-Kelley
13 """
13 """
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Copyright (C) 2008-2010 The IPython Development Team
16 # Copyright (C) 2008-2010 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 from __future__ import absolute_import
26 from __future__ import absolute_import
27
27
28 import logging
28 import logging
29 import os
29 import os
30 import sys
30 import sys
31
31
32 from IPython.config.loader import (
32 from IPython.config.loader import (
33 Config, PyFileConfigLoader
33 Config, PyFileConfigLoader
34 )
34 )
35 from IPython.config.application import boolean_flag
35 from IPython.config.application import boolean_flag
36 from IPython.core import release
36 from IPython.core import release
37 from IPython.core import usage
37 from IPython.core import usage
38 from IPython.core.crashhandler import CrashHandler
38 from IPython.core.crashhandler import CrashHandler
39 from IPython.core.formatters import PlainTextFormatter
39 from IPython.core.formatters import PlainTextFormatter
40 from IPython.core.newapplication import (
40 from IPython.core.newapplication import (
41 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
41 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
42 )
42 )
43 from IPython.core.shellapp import (
43 from IPython.core.shellapp import (
44 InteractiveShellApp, shell_flags, shell_aliases
44 InteractiveShellApp, shell_flags, shell_aliases
45 )
45 )
46 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
46 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
47 from IPython.lib import inputhook
47 from IPython.lib import inputhook
48 from IPython.utils.path import get_ipython_dir, check_for_old_config
48 from IPython.utils.path import get_ipython_dir, check_for_old_config
49 from IPython.utils.traitlets import (
49 from IPython.utils.traitlets import (
50 Bool, Dict, CaselessStrEnum
50 Bool, Dict, CaselessStrEnum
51 )
51 )
52
52
53 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
54 # Globals, utilities and helpers
54 # Globals, utilities and helpers
55 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
56
56
57 #: The default config file name for this application.
57 #: The default config file name for this application.
58 default_config_file_name = u'ipython_config.py'
58 default_config_file_name = u'ipython_config.py'
59
59
60
60
61 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
62 # Crash handler for this application
62 # Crash handler for this application
63 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
64
64
65 _message_template = """\
65 _message_template = """\
66 Oops, $self.app_name crashed. We do our best to make it stable, but...
66 Oops, $self.app_name crashed. We do our best to make it stable, but...
67
67
68 A crash report was automatically generated with the following information:
68 A crash report was automatically generated with the following information:
69 - A verbatim copy of the crash traceback.
69 - A verbatim copy of the crash traceback.
70 - A copy of your input history during this session.
70 - A copy of your input history during this session.
71 - Data on your current $self.app_name configuration.
71 - Data on your current $self.app_name configuration.
72
72
73 It was left in the file named:
73 It was left in the file named:
74 \t'$self.crash_report_fname'
74 \t'$self.crash_report_fname'
75 If you can email this file to the developers, the information in it will help
75 If you can email this file to the developers, the information in it will help
76 them in understanding and correcting the problem.
76 them in understanding and correcting the problem.
77
77
78 You can mail it to: $self.contact_name at $self.contact_email
78 You can mail it to: $self.contact_name at $self.contact_email
79 with the subject '$self.app_name Crash Report'.
79 with the subject '$self.app_name Crash Report'.
80
80
81 If you want to do it now, the following command will work (under Unix):
81 If you want to do it now, the following command will work (under Unix):
82 mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname
82 mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname
83
83
84 To ensure accurate tracking of this issue, please file a report about it at:
84 To ensure accurate tracking of this issue, please file a report about it at:
85 $self.bug_tracker
85 $self.bug_tracker
86 """
86 """
87
87
88 class IPAppCrashHandler(CrashHandler):
88 class IPAppCrashHandler(CrashHandler):
89 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
89 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
90
90
91 message_template = _message_template
91 message_template = _message_template
92
92
93 def __init__(self, app):
93 def __init__(self, app):
94 contact_name = release.authors['Fernando'][0]
94 contact_name = release.authors['Fernando'][0]
95 contact_email = release.authors['Fernando'][1]
95 contact_email = release.authors['Fernando'][1]
96 bug_tracker = 'http://github.com/ipython/ipython/issues'
96 bug_tracker = 'http://github.com/ipython/ipython/issues'
97 super(IPAppCrashHandler,self).__init__(
97 super(IPAppCrashHandler,self).__init__(
98 app, contact_name, contact_email, bug_tracker
98 app, contact_name, contact_email, bug_tracker
99 )
99 )
100
100
101 def make_report(self,traceback):
101 def make_report(self,traceback):
102 """Return a string containing a crash report."""
102 """Return a string containing a crash report."""
103
103
104 sec_sep = self.section_sep
104 sec_sep = self.section_sep
105 # Start with parent report
105 # Start with parent report
106 report = [super(IPAppCrashHandler, self).make_report(traceback)]
106 report = [super(IPAppCrashHandler, self).make_report(traceback)]
107 # Add interactive-specific info we may have
107 # Add interactive-specific info we may have
108 rpt_add = report.append
108 rpt_add = report.append
109 try:
109 try:
110 rpt_add(sec_sep+"History of session input:")
110 rpt_add(sec_sep+"History of session input:")
111 for line in self.app.shell.user_ns['_ih']:
111 for line in self.app.shell.user_ns['_ih']:
112 rpt_add(line)
112 rpt_add(line)
113 rpt_add('\n*** Last line of input (may not be in above history):\n')
113 rpt_add('\n*** Last line of input (may not be in above history):\n')
114 rpt_add(self.app.shell._last_input_line+'\n')
114 rpt_add(self.app.shell._last_input_line+'\n')
115 except:
115 except:
116 pass
116 pass
117
117
118 return ''.join(report)
118 return ''.join(report)
119
119
120 #-----------------------------------------------------------------------------
120 #-----------------------------------------------------------------------------
121 # Aliases and Flags
121 # Aliases and Flags
122 #-----------------------------------------------------------------------------
122 #-----------------------------------------------------------------------------
123 flags = dict(base_flags)
123 flags = dict(base_flags)
124 flags.update(shell_flags)
124 flags.update(shell_flags)
125 addflag = lambda *args: flags.update(boolean_flag(*args))
125 addflag = lambda *args: flags.update(boolean_flag(*args))
126 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
126 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
127 'Turn on auto editing of files with syntax errors.',
127 'Turn on auto editing of files with syntax errors.',
128 'Turn off auto editing of files with syntax errors.'
128 'Turn off auto editing of files with syntax errors.'
129 )
129 )
130 addflag('banner', 'TerminalIPythonApp.display_banner',
130 addflag('banner', 'TerminalIPythonApp.display_banner',
131 "Display a banner upon starting IPython.",
131 "Display a banner upon starting IPython.",
132 "Don't display a banner upon starting IPython."
132 "Don't display a banner upon starting IPython."
133 )
133 )
134 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
134 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
135 """Set to confirm when you try to exit IPython with an EOF (Control-D
135 """Set to confirm when you try to exit IPython with an EOF (Control-D
136 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
136 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
137 you can force a direct exit without any confirmation.""",
137 you can force a direct exit without any confirmation.""",
138 "Don't prompt the user when exiting."
138 "Don't prompt the user when exiting."
139 )
139 )
140 addflag('term-title', 'TerminalInteractiveShell.term_title',
140 addflag('term-title', 'TerminalInteractiveShell.term_title',
141 "Enable auto setting the terminal title.",
141 "Enable auto setting the terminal title.",
142 "Disable auto setting the terminal title."
142 "Disable auto setting the terminal title."
143 )
143 )
144 classic_config = Config()
144 classic_config = Config()
145 classic_config.InteractiveShell.cache_size = 0
145 classic_config.InteractiveShell.cache_size = 0
146 classic_config.PlainTextFormatter.pprint = False
146 classic_config.PlainTextFormatter.pprint = False
147 classic_config.InteractiveShell.prompt_in1 = '>>> '
147 classic_config.InteractiveShell.prompt_in1 = '>>> '
148 classic_config.InteractiveShell.prompt_in2 = '... '
148 classic_config.InteractiveShell.prompt_in2 = '... '
149 classic_config.InteractiveShell.prompt_out = ''
149 classic_config.InteractiveShell.prompt_out = ''
150 classic_config.InteractiveShell.separate_in = ''
150 classic_config.InteractiveShell.separate_in = ''
151 classic_config.InteractiveShell.separate_out = ''
151 classic_config.InteractiveShell.separate_out = ''
152 classic_config.InteractiveShell.separate_out2 = ''
152 classic_config.InteractiveShell.separate_out2 = ''
153 classic_config.InteractiveShell.colors = 'NoColor'
153 classic_config.InteractiveShell.colors = 'NoColor'
154 classic_config.InteractiveShell.xmode = 'Plain'
154 classic_config.InteractiveShell.xmode = 'Plain'
155
155
156 flags['classic']=(
156 flags['classic']=(
157 classic_config,
157 classic_config,
158 "Gives IPython a similar feel to the classic Python prompt."
158 "Gives IPython a similar feel to the classic Python prompt."
159 )
159 )
160 # # log doesn't make so much sense this way anymore
160 # # log doesn't make so much sense this way anymore
161 # paa('--log','-l',
161 # paa('--log','-l',
162 # action='store_true', dest='InteractiveShell.logstart',
162 # action='store_true', dest='InteractiveShell.logstart',
163 # help="Start logging to the default log file (./ipython_log.py).")
163 # help="Start logging to the default log file (./ipython_log.py).")
164 #
164 #
165 # # quick is harder to implement
165 # # quick is harder to implement
166 flags['quick']=(
166 flags['quick']=(
167 {'TerminalIPythonApp' : {'quick' : True}},
167 {'TerminalIPythonApp' : {'quick' : True}},
168 "Enable quick startup with no config files."
168 "Enable quick startup with no config files."
169 )
169 )
170
170
171 nosep_config = Config()
171 nosep_config = Config()
172 nosep_config.InteractiveShell.separate_in = ''
172 nosep_config.InteractiveShell.separate_in = ''
173 nosep_config.InteractiveShell.separate_out = ''
173 nosep_config.InteractiveShell.separate_out = ''
174 nosep_config.InteractiveShell.separate_out2 = ''
174 nosep_config.InteractiveShell.separate_out2 = ''
175
175
176 flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
176 flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
177
177
178 flags['i'] = (
178 flags['i'] = (
179 {'TerminalIPythonApp' : {'force_interact' : True}},
179 {'TerminalIPythonApp' : {'force_interact' : True}},
180 "If running code from the command line, become interactive afterwards."
180 "If running code from the command line, become interactive afterwards."
181 )
181 )
182 flags['pylab'] = (
182 flags['pylab'] = (
183 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
183 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
184 """Pre-load matplotlib and numpy for interactive use with
184 """Pre-load matplotlib and numpy for interactive use with
185 the default matplotlib backend."""
185 the default matplotlib backend."""
186 )
186 )
187
187
188 aliases = dict(base_aliases)
188 aliases = dict(base_aliases)
189 aliases.update(shell_aliases)
189 aliases.update(shell_aliases)
190
190
191 # it's possible we don't want short aliases for *all* of these:
191 # it's possible we don't want short aliases for *all* of these:
192 aliases.update(dict(
192 aliases.update(dict(
193 editor='TerminalInteractiveShell.editor',
193 editor='TerminalInteractiveShell.editor',
194 sl='TerminalInteractiveShell.screen_length',
194 sl='TerminalInteractiveShell.screen_length',
195 gui='TerminalIPythonApp.gui',
195 gui='TerminalIPythonApp.gui',
196 pylab='TerminalIPythonApp.pylab',
196 pylab='TerminalIPythonApp.pylab',
197 ))
197 ))
198
198
199 #-----------------------------------------------------------------------------
199 #-----------------------------------------------------------------------------
200 # Main classes and functions
200 # Main classes and functions
201 #-----------------------------------------------------------------------------
201 #-----------------------------------------------------------------------------
202
202
203 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
203 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
204 name = u'ipython'
204 name = u'ipython'
205 description = usage.cl_usage
205 description = usage.cl_usage
206 # command_line_loader = IPAppConfigLoader
206 # command_line_loader = IPAppConfigLoader
207 default_config_file_name = default_config_file_name
207 default_config_file_name = default_config_file_name
208 crash_handler_class = IPAppCrashHandler
208 crash_handler_class = IPAppCrashHandler
209 flags = Dict(flags)
209 flags = Dict(flags)
210 aliases = Dict(aliases)
210 aliases = Dict(aliases)
211 classes = [InteractiveShellApp, TerminalInteractiveShell, ProfileDir, PlainTextFormatter]
211 classes = [InteractiveShellApp, TerminalInteractiveShell, ProfileDir, PlainTextFormatter]
212 # *do* autocreate requested profile
212 # *do* autocreate requested profile
213 auto_create=Bool(True)
213 auto_create=Bool(True)
214 copy_config_files=Bool(True)
214 copy_config_files=Bool(True)
215 # configurables
215 # configurables
216 ignore_old_config=Bool(False, config=True,
216 ignore_old_config=Bool(False, config=True,
217 help="Suppress warning messages about legacy config files"
217 help="Suppress warning messages about legacy config files"
218 )
218 )
219 quick = Bool(False, config=True,
219 quick = Bool(False, config=True,
220 help="""Start IPython quickly by skipping the loading of config files."""
220 help="""Start IPython quickly by skipping the loading of config files."""
221 )
221 )
222 def _quick_changed(self, name, old, new):
222 def _quick_changed(self, name, old, new):
223 if new:
223 if new:
224 self.load_config_file = lambda *a, **kw: None
224 self.load_config_file = lambda *a, **kw: None
225 self.ignore_old_config=True
225 self.ignore_old_config=True
226
226
227 gui = CaselessStrEnum(('qt','wx','gtk'), config=True,
227 gui = CaselessStrEnum(('qt','wx','gtk'), config=True,
228 help="Enable GUI event loop integration ('qt', 'wx', 'gtk')."
228 help="Enable GUI event loop integration ('qt', 'wx', 'gtk')."
229 )
229 )
230 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
230 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
231 config=True,
231 config=True,
232 help="""Pre-load matplotlib and numpy for interactive use,
232 help="""Pre-load matplotlib and numpy for interactive use,
233 selecting a particular matplotlib backend and loop integration.
233 selecting a particular matplotlib backend and loop integration.
234 """
234 """
235 )
235 )
236 display_banner = Bool(True, config=True,
236 display_banner = Bool(True, config=True,
237 help="Whether to display a banner upon starting IPython."
237 help="Whether to display a banner upon starting IPython."
238 )
238 )
239
239
240 # if there is code of files to run from the cmd line, don't interact
240 # if there is code of files to run from the cmd line, don't interact
241 # unless the --i flag (App.force_interact) is true.
241 # unless the --i flag (App.force_interact) is true.
242 force_interact = Bool(False, config=True,
242 force_interact = Bool(False, config=True,
243 help="""If a command or file is given via the command-line,
243 help="""If a command or file is given via the command-line,
244 e.g. 'ipython foo.py"""
244 e.g. 'ipython foo.py"""
245 )
245 )
246 def _force_interact_changed(self, name, old, new):
246 def _force_interact_changed(self, name, old, new):
247 if new:
247 if new:
248 self.interact = True
248 self.interact = True
249
249
250 def _file_to_run_changed(self, name, old, new):
250 def _file_to_run_changed(self, name, old, new):
251 if new and not self.force_interact:
251 if new and not self.force_interact:
252 self.interact = False
252 self.interact = False
253 _code_to_run_changed = _file_to_run_changed
253 _code_to_run_changed = _file_to_run_changed
254
254
255 # internal, not-configurable
255 # internal, not-configurable
256 interact=Bool(True)
256 interact=Bool(True)
257
257
258
258
259 def initialize(self, argv=None):
259 def initialize(self, argv=None):
260 """Do actions after construct, but before starting the app."""
260 """Do actions after construct, but before starting the app."""
261 super(TerminalIPythonApp, self).initialize(argv)
261 super(TerminalIPythonApp, self).initialize(argv)
262 if not self.ignore_old_config:
262 if not self.ignore_old_config:
263 check_for_old_config(self.ipython_dir)
263 check_for_old_config(self.ipython_dir)
264
264
265 # print self.extra_args
265 # print self.extra_args
266 if self.extra_args:
266 if self.extra_args:
267 self.file_to_run = self.extra_args[0]
267 self.file_to_run = self.extra_args[0]
268 # create the shell
268 # create the shell
269 self.init_shell()
269 self.init_shell()
270 # and draw the banner
270 # and draw the banner
271 self.init_banner()
271 self.init_banner()
272 # Now a variety of things that happen after the banner is printed.
272 # Now a variety of things that happen after the banner is printed.
273 self.init_gui_pylab()
273 self.init_gui_pylab()
274 self.init_extensions()
274 self.init_extensions()
275 self.init_code()
275 self.init_code()
276
276
277 def init_shell(self):
277 def init_shell(self):
278 """initialize the InteractiveShell instance"""
278 """initialize the InteractiveShell instance"""
279 # I am a little hesitant to put these into InteractiveShell itself.
279 # I am a little hesitant to put these into InteractiveShell itself.
280 # But that might be the place for them
280 # But that might be the place for them
281 sys.path.insert(0, '')
281 sys.path.insert(0, '')
282
282
283 # Create an InteractiveShell instance.
283 # Create an InteractiveShell instance.
284 # shell.display_banner should always be False for the terminal
284 # shell.display_banner should always be False for the terminal
285 # based app, because we call shell.show_banner() by hand below
285 # based app, because we call shell.show_banner() by hand below
286 # so the banner shows *before* all extension loading stuff.
286 # so the banner shows *before* all extension loading stuff.
287 self.shell = TerminalInteractiveShell.instance(config=self.config,
287 self.shell = TerminalInteractiveShell.instance(config=self.config,
288 display_banner=False, profile_dir=self.profile_dir,
288 display_banner=False, profile_dir=self.profile_dir,
289 ipython_dir=self.ipython_dir)
289 ipython_dir=self.ipython_dir)
290
290
291 def init_banner(self):
291 def init_banner(self):
292 """optionally display the banner"""
292 """optionally display the banner"""
293 if self.display_banner and self.interact:
293 if self.display_banner and self.interact:
294 self.shell.show_banner()
294 self.shell.show_banner()
295 # Make sure there is a space below the banner.
295 # Make sure there is a space below the banner.
296 if self.log_level <= logging.INFO: print
296 if self.log_level <= logging.INFO: print
297
297
298
298
299 def init_gui_pylab(self):
299 def init_gui_pylab(self):
300 """Enable GUI event loop integration, taking pylab into account."""
300 """Enable GUI event loop integration, taking pylab into account."""
301 gui = self.gui
301 gui = self.gui
302
302
303 # Using `pylab` will also require gui activation, though which toolkit
303 # Using `pylab` will also require gui activation, though which toolkit
304 # to use may be chosen automatically based on mpl configuration.
304 # to use may be chosen automatically based on mpl configuration.
305 if self.pylab:
305 if self.pylab:
306 activate = self.shell.enable_pylab
306 activate = self.shell.enable_pylab
307 if self.pylab == 'auto':
307 if self.pylab == 'auto':
308 gui = None
308 gui = None
309 else:
309 else:
310 gui = self.pylab
310 gui = self.pylab
311 else:
311 else:
312 # Enable only GUI integration, no pylab
312 # Enable only GUI integration, no pylab
313 activate = inputhook.enable_gui
313 activate = inputhook.enable_gui
314
314
315 if gui or self.pylab:
315 if gui or self.pylab:
316 try:
316 try:
317 self.log.info("Enabling GUI event loop integration, "
317 self.log.info("Enabling GUI event loop integration, "
318 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
318 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
319 activate(gui)
319 activate(gui)
320 except:
320 except:
321 self.log.warn("Error in enabling GUI event loop integration:")
321 self.log.warn("Error in enabling GUI event loop integration:")
322 self.shell.showtraceback()
322 self.shell.showtraceback()
323
323
324 def start(self):
324 def start(self):
325 # perform any prexec steps:
325 # perform any prexec steps:
326 if self.interact:
326 if self.interact:
327 self.log.debug("Starting IPython's mainloop...")
327 self.log.debug("Starting IPython's mainloop...")
328 self.shell.mainloop()
328 self.shell.mainloop()
329 else:
329 else:
330 self.log.debug("IPython not interactive...")
330 self.log.debug("IPython not interactive...")
331
331
332
332
333 def load_default_config(ipython_dir=None):
333 def load_default_config(ipython_dir=None):
334 """Load the default config file from the default ipython_dir.
334 """Load the default config file from the default ipython_dir.
335
335
336 This is useful for embedded shells.
336 This is useful for embedded shells.
337 """
337 """
338 if ipython_dir is None:
338 if ipython_dir is None:
339 ipython_dir = get_ipython_dir()
339 ipython_dir = get_ipython_dir()
340 profile_dir = os.path.join(ipython_dir, 'profile_default')
340 profile_dir = os.path.join(ipython_dir, 'profile_default')
341 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
341 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
342 config = cl.load_config()
342 config = cl.load_config()
343 return config
343 return config
344
344
345
345
346 def launch_new_instance():
346 def launch_new_instance():
347 """Create and run a full blown IPython instance"""
347 """Create and run a full blown IPython instance"""
348 app = TerminalIPythonApp()
348 app = TerminalIPythonApp.instance()
349 app.initialize()
349 app.initialize()
350 # print app.config
351 # print app.profile_dir.location
352 app.start()
350 app.start()
353
351
354
352
355 if __name__ == '__main__':
353 if __name__ == '__main__':
356 launch_new_instance()
354 launch_new_instance()
General Comments 0
You need to be logged in to leave comments. Login now