##// END OF EJS Templates
`ipython profile create` respects `--ipython-dir`...
MinRK -
Show More
@@ -1,315 +1,315 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for managing IPython profiles.
3 An application for managing IPython profiles.
4
4
5 To be invoked as the `ipython profile` subcommand.
5 To be invoked as the `ipython profile` subcommand.
6
6
7 Authors:
7 Authors:
8
8
9 * Min RK
9 * Min RK
10
10
11 """
11 """
12 from __future__ import print_function
12 from __future__ import print_function
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Copyright (C) 2008 The IPython Development Team
15 # Copyright (C) 2008 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 import os
25 import os
26
26
27 from IPython.config.application import Application
27 from IPython.config.application import Application
28 from IPython.core.application import (
28 from IPython.core.application import (
29 BaseIPythonApplication, base_flags
29 BaseIPythonApplication, base_flags
30 )
30 )
31 from IPython.core.profiledir import ProfileDir
31 from IPython.core.profiledir import ProfileDir
32 from IPython.utils.importstring import import_item
32 from IPython.utils.importstring import import_item
33 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir
33 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from IPython.utils.traitlets import Unicode, Bool, Dict
35 from IPython.utils.traitlets import Unicode, Bool, Dict
36
36
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38 # Constants
38 # Constants
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40
40
41 create_help = """Create an IPython profile by name
41 create_help = """Create an IPython profile by name
42
42
43 Create an ipython profile directory by its name or
43 Create an ipython profile directory by its name or
44 profile directory path. Profile directories contain
44 profile directory path. Profile directories contain
45 configuration, log and security related files and are named
45 configuration, log and security related files and are named
46 using the convention 'profile_<name>'. By default they are
46 using the convention 'profile_<name>'. By default they are
47 located in your ipython directory. Once created, you will
47 located in your ipython directory. Once created, you will
48 can edit the configuration files in the profile
48 can edit the configuration files in the profile
49 directory to configure IPython. Most users will create a
49 directory to configure IPython. Most users will create a
50 profile directory by name,
50 profile directory by name,
51 `ipython profile create myprofile`, which will put the directory
51 `ipython profile create myprofile`, which will put the directory
52 in `<ipython_dir>/profile_myprofile`.
52 in `<ipython_dir>/profile_myprofile`.
53 """
53 """
54 list_help = """List available IPython profiles
54 list_help = """List available IPython profiles
55
55
56 List all available profiles, by profile location, that can
56 List all available profiles, by profile location, that can
57 be found in the current working directly or in the ipython
57 be found in the current working directly or in the ipython
58 directory. Profile directories are named using the convention
58 directory. Profile directories are named using the convention
59 'profile_<profile>'.
59 'profile_<profile>'.
60 """
60 """
61 profile_help = """Manage IPython profiles
61 profile_help = """Manage IPython profiles
62
62
63 Profile directories contain
63 Profile directories contain
64 configuration, log and security related files and are named
64 configuration, log and security related files and are named
65 using the convention 'profile_<name>'. By default they are
65 using the convention 'profile_<name>'. By default they are
66 located in your ipython directory. You can create profiles
66 located in your ipython directory. You can create profiles
67 with `ipython profile create <name>`, or see the profiles you
67 with `ipython profile create <name>`, or see the profiles you
68 already have with `ipython profile list`
68 already have with `ipython profile list`
69
69
70 To get started configuring IPython, simply do:
70 To get started configuring IPython, simply do:
71
71
72 $> ipython profile create
72 $> ipython profile create
73
73
74 and IPython will create the default profile in <ipython_dir>/profile_default,
74 and IPython will create the default profile in <ipython_dir>/profile_default,
75 where you can edit ipython_config.py to start configuring IPython.
75 where you can edit ipython_config.py to start configuring IPython.
76
76
77 """
77 """
78
78
79 _list_examples = "ipython profile list # list all profiles"
79 _list_examples = "ipython profile list # list all profiles"
80
80
81 _create_examples = """
81 _create_examples = """
82 ipython profile create foo # create profile foo w/ default config files
82 ipython profile create foo # create profile foo w/ default config files
83 ipython profile create foo --reset # restage default config files over current
83 ipython profile create foo --reset # restage default config files over current
84 ipython profile create foo --parallel # also stage parallel config files
84 ipython profile create foo --parallel # also stage parallel config files
85 """
85 """
86
86
87 _main_examples = """
87 _main_examples = """
88 ipython profile create -h # show the help string for the create subcommand
88 ipython profile create -h # show the help string for the create subcommand
89 ipython profile list -h # show the help string for the list subcommand
89 ipython profile list -h # show the help string for the list subcommand
90
90
91 ipython locate profile foo # print the path to the directory for profile 'foo'
91 ipython locate profile foo # print the path to the directory for profile 'foo'
92 """
92 """
93
93
94 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
95 # Profile Application Class (for `ipython profile` subcommand)
95 # Profile Application Class (for `ipython profile` subcommand)
96 #-----------------------------------------------------------------------------
96 #-----------------------------------------------------------------------------
97
97
98
98
99 def list_profiles_in(path):
99 def list_profiles_in(path):
100 """list profiles in a given root directory"""
100 """list profiles in a given root directory"""
101 files = os.listdir(path)
101 files = os.listdir(path)
102 profiles = []
102 profiles = []
103 for f in files:
103 for f in files:
104 try:
104 try:
105 full_path = os.path.join(path, f)
105 full_path = os.path.join(path, f)
106 except UnicodeError:
106 except UnicodeError:
107 continue
107 continue
108 if os.path.isdir(full_path) and f.startswith('profile_'):
108 if os.path.isdir(full_path) and f.startswith('profile_'):
109 profiles.append(f.split('_',1)[-1])
109 profiles.append(f.split('_',1)[-1])
110 return profiles
110 return profiles
111
111
112
112
113 def list_bundled_profiles():
113 def list_bundled_profiles():
114 """list profiles that are bundled with IPython."""
114 """list profiles that are bundled with IPython."""
115 path = os.path.join(get_ipython_package_dir(), u'config', u'profile')
115 path = os.path.join(get_ipython_package_dir(), u'config', u'profile')
116 files = os.listdir(path)
116 files = os.listdir(path)
117 profiles = []
117 profiles = []
118 for profile in files:
118 for profile in files:
119 full_path = os.path.join(path, profile)
119 full_path = os.path.join(path, profile)
120 if os.path.isdir(full_path) and profile != "__pycache__":
120 if os.path.isdir(full_path) and profile != "__pycache__":
121 profiles.append(profile)
121 profiles.append(profile)
122 return profiles
122 return profiles
123
123
124
124
125 class ProfileLocate(BaseIPythonApplication):
125 class ProfileLocate(BaseIPythonApplication):
126 description = """print the path to an IPython profile dir"""
126 description = """print the path to an IPython profile dir"""
127
127
128 def parse_command_line(self, argv=None):
128 def parse_command_line(self, argv=None):
129 super(ProfileLocate, self).parse_command_line(argv)
129 super(ProfileLocate, self).parse_command_line(argv)
130 if self.extra_args:
130 if self.extra_args:
131 self.profile = self.extra_args[0]
131 self.profile = self.extra_args[0]
132
132
133 def start(self):
133 def start(self):
134 print(self.profile_dir.location)
134 print(self.profile_dir.location)
135
135
136
136
137 class ProfileList(Application):
137 class ProfileList(Application):
138 name = u'ipython-profile'
138 name = u'ipython-profile'
139 description = list_help
139 description = list_help
140 examples = _list_examples
140 examples = _list_examples
141
141
142 aliases = Dict({
142 aliases = Dict({
143 'ipython-dir' : 'ProfileList.ipython_dir',
143 'ipython-dir' : 'ProfileList.ipython_dir',
144 'log-level' : 'Application.log_level',
144 'log-level' : 'Application.log_level',
145 })
145 })
146 flags = Dict(dict(
146 flags = Dict(dict(
147 debug = ({'Application' : {'log_level' : 0}},
147 debug = ({'Application' : {'log_level' : 0}},
148 "Set Application.log_level to 0, maximizing log output."
148 "Set Application.log_level to 0, maximizing log output."
149 )
149 )
150 ))
150 ))
151
151
152 ipython_dir = Unicode(get_ipython_dir(), config=True,
152 ipython_dir = Unicode(get_ipython_dir(), config=True,
153 help="""
153 help="""
154 The name of the IPython directory. This directory is used for logging
154 The name of the IPython directory. This directory is used for logging
155 configuration (through profiles), history storage, etc. The default
155 configuration (through profiles), history storage, etc. The default
156 is usually $HOME/.ipython. This options can also be specified through
156 is usually $HOME/.ipython. This options can also be specified through
157 the environment variable IPYTHONDIR.
157 the environment variable IPYTHONDIR.
158 """
158 """
159 )
159 )
160
160
161
161
162 def _print_profiles(self, profiles):
162 def _print_profiles(self, profiles):
163 """print list of profiles, indented."""
163 """print list of profiles, indented."""
164 for profile in profiles:
164 for profile in profiles:
165 print(' %s' % profile)
165 print(' %s' % profile)
166
166
167 def list_profile_dirs(self):
167 def list_profile_dirs(self):
168 profiles = list_bundled_profiles()
168 profiles = list_bundled_profiles()
169 if profiles:
169 if profiles:
170 print()
170 print()
171 print("Available profiles in IPython:")
171 print("Available profiles in IPython:")
172 self._print_profiles(profiles)
172 self._print_profiles(profiles)
173 print()
173 print()
174 print(" The first request for a bundled profile will copy it")
174 print(" The first request for a bundled profile will copy it")
175 print(" into your IPython directory (%s)," % self.ipython_dir)
175 print(" into your IPython directory (%s)," % self.ipython_dir)
176 print(" where you can customize it.")
176 print(" where you can customize it.")
177
177
178 profiles = list_profiles_in(self.ipython_dir)
178 profiles = list_profiles_in(self.ipython_dir)
179 if profiles:
179 if profiles:
180 print()
180 print()
181 print("Available profiles in %s:" % self.ipython_dir)
181 print("Available profiles in %s:" % self.ipython_dir)
182 self._print_profiles(profiles)
182 self._print_profiles(profiles)
183
183
184 profiles = list_profiles_in(py3compat.getcwd())
184 profiles = list_profiles_in(py3compat.getcwd())
185 if profiles:
185 if profiles:
186 print()
186 print()
187 print("Available profiles in current directory (%s):" % py3compat.getcwd())
187 print("Available profiles in current directory (%s):" % py3compat.getcwd())
188 self._print_profiles(profiles)
188 self._print_profiles(profiles)
189
189
190 print()
190 print()
191 print("To use any of the above profiles, start IPython with:")
191 print("To use any of the above profiles, start IPython with:")
192 print(" ipython --profile=<name>")
192 print(" ipython --profile=<name>")
193 print()
193 print()
194
194
195 def start(self):
195 def start(self):
196 self.list_profile_dirs()
196 self.list_profile_dirs()
197
197
198
198
199 create_flags = {}
199 create_flags = {}
200 create_flags.update(base_flags)
200 create_flags.update(base_flags)
201 # don't include '--init' flag, which implies running profile create in other apps
201 # don't include '--init' flag, which implies running profile create in other apps
202 create_flags.pop('init')
202 create_flags.pop('init')
203 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
203 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
204 "reset config files in this profile to the defaults.")
204 "reset config files in this profile to the defaults.")
205 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
205 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
206 "Include the config files for parallel "
206 "Include the config files for parallel "
207 "computing apps (ipengine, ipcontroller, etc.)")
207 "computing apps (ipengine, ipcontroller, etc.)")
208
208
209
209
210 class ProfileCreate(BaseIPythonApplication):
210 class ProfileCreate(BaseIPythonApplication):
211 name = u'ipython-profile'
211 name = u'ipython-profile'
212 description = create_help
212 description = create_help
213 examples = _create_examples
213 examples = _create_examples
214 auto_create = Bool(True, config=False)
214 auto_create = Bool(True, config=False)
215 def _log_format_default(self):
215 def _log_format_default(self):
216 return "[%(name)s] %(message)s"
216 return "[%(name)s] %(message)s"
217
217
218 def _copy_config_files_default(self):
218 def _copy_config_files_default(self):
219 return True
219 return True
220
220
221 parallel = Bool(False, config=True,
221 parallel = Bool(False, config=True,
222 help="whether to include parallel computing config files")
222 help="whether to include parallel computing config files")
223 def _parallel_changed(self, name, old, new):
223 def _parallel_changed(self, name, old, new):
224 parallel_files = [ 'ipcontroller_config.py',
224 parallel_files = [ 'ipcontroller_config.py',
225 'ipengine_config.py',
225 'ipengine_config.py',
226 'ipcluster_config.py'
226 'ipcluster_config.py'
227 ]
227 ]
228 if new:
228 if new:
229 for cf in parallel_files:
229 for cf in parallel_files:
230 self.config_files.append(cf)
230 self.config_files.append(cf)
231 else:
231 else:
232 for cf in parallel_files:
232 for cf in parallel_files:
233 if cf in self.config_files:
233 if cf in self.config_files:
234 self.config_files.remove(cf)
234 self.config_files.remove(cf)
235
235
236 def parse_command_line(self, argv):
236 def parse_command_line(self, argv):
237 super(ProfileCreate, self).parse_command_line(argv)
237 super(ProfileCreate, self).parse_command_line(argv)
238 # accept positional arg as profile name
238 # accept positional arg as profile name
239 if self.extra_args:
239 if self.extra_args:
240 self.profile = self.extra_args[0]
240 self.profile = self.extra_args[0]
241
241
242 flags = Dict(create_flags)
242 flags = Dict(create_flags)
243
243
244 classes = [ProfileDir]
244 classes = [ProfileDir]
245
245
246 def _import_app(self, app_path):
246 def _import_app(self, app_path):
247 """import an app class"""
247 """import an app class"""
248 app = None
248 app = None
249 name = app_path.rsplit('.', 1)[-1]
249 name = app_path.rsplit('.', 1)[-1]
250 try:
250 try:
251 app = import_item(app_path)
251 app = import_item(app_path)
252 except ImportError:
252 except ImportError:
253 self.log.info("Couldn't import %s, config file will be excluded", name)
253 self.log.info("Couldn't import %s, config file will be excluded", name)
254 except Exception:
254 except Exception:
255 self.log.warn('Unexpected error importing %s', name, exc_info=True)
255 self.log.warn('Unexpected error importing %s', name, exc_info=True)
256 return app
256 return app
257
257
258 def init_config_files(self):
258 def init_config_files(self):
259 super(ProfileCreate, self).init_config_files()
259 super(ProfileCreate, self).init_config_files()
260 # use local imports, since these classes may import from here
260 # use local imports, since these classes may import from here
261 from IPython.terminal.ipapp import TerminalIPythonApp
261 from IPython.terminal.ipapp import TerminalIPythonApp
262 apps = [TerminalIPythonApp]
262 apps = [TerminalIPythonApp]
263 for app_path in (
263 for app_path in (
264 'IPython.qt.console.qtconsoleapp.IPythonQtConsoleApp',
264 'IPython.qt.console.qtconsoleapp.IPythonQtConsoleApp',
265 'IPython.html.notebookapp.NotebookApp',
265 'IPython.html.notebookapp.NotebookApp',
266 'IPython.nbconvert.nbconvertapp.NbConvertApp',
266 'IPython.nbconvert.nbconvertapp.NbConvertApp',
267 ):
267 ):
268 app = self._import_app(app_path)
268 app = self._import_app(app_path)
269 if app is not None:
269 if app is not None:
270 apps.append(app)
270 apps.append(app)
271 if self.parallel:
271 if self.parallel:
272 from IPython.parallel.apps.ipcontrollerapp import IPControllerApp
272 from IPython.parallel.apps.ipcontrollerapp import IPControllerApp
273 from IPython.parallel.apps.ipengineapp import IPEngineApp
273 from IPython.parallel.apps.ipengineapp import IPEngineApp
274 from IPython.parallel.apps.ipclusterapp import IPClusterStart
274 from IPython.parallel.apps.ipclusterapp import IPClusterStart
275 from IPython.parallel.apps.iploggerapp import IPLoggerApp
275 from IPython.parallel.apps.iploggerapp import IPLoggerApp
276 apps.extend([
276 apps.extend([
277 IPControllerApp,
277 IPControllerApp,
278 IPEngineApp,
278 IPEngineApp,
279 IPClusterStart,
279 IPClusterStart,
280 IPLoggerApp,
280 IPLoggerApp,
281 ])
281 ])
282 for App in apps:
282 for App in apps:
283 app = App()
283 app = App()
284 app.config.update(self.config)
284 app.config.update(self.config)
285 app.log = self.log
285 app.log = self.log
286 app.overwrite = self.overwrite
286 app.overwrite = self.overwrite
287 app.copy_config_files=True
287 app.copy_config_files=True
288 app.profile = self.profile
288 app.ipython_dir=self.ipython_dir
289 app.init_profile_dir()
289 app.profile_dir=self.profile_dir
290 app.init_config_files()
290 app.init_config_files()
291
291
292 def stage_default_config_file(self):
292 def stage_default_config_file(self):
293 pass
293 pass
294
294
295
295
296 class ProfileApp(Application):
296 class ProfileApp(Application):
297 name = u'ipython-profile'
297 name = u'ipython-profile'
298 description = profile_help
298 description = profile_help
299 examples = _main_examples
299 examples = _main_examples
300
300
301 subcommands = Dict(dict(
301 subcommands = Dict(dict(
302 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
302 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
303 list = (ProfileList, ProfileList.description.splitlines()[0]),
303 list = (ProfileList, ProfileList.description.splitlines()[0]),
304 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
304 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
305 ))
305 ))
306
306
307 def start(self):
307 def start(self):
308 if self.subapp is None:
308 if self.subapp is None:
309 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
309 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
310 print()
310 print()
311 self.print_description()
311 self.print_description()
312 self.print_subcommands()
312 self.print_subcommands()
313 self.exit(1)
313 self.exit(1)
314 else:
314 else:
315 return self.subapp.start()
315 return self.subapp.start()
@@ -1,153 +1,166 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for profile-related functions.
2 """Tests for profile-related functions.
3
3
4 Currently only the startup-dir functionality is tested, but more tests should
4 Currently only the startup-dir functionality is tested, but more tests should
5 be added for:
5 be added for:
6
6
7 * ipython profile create
7 * ipython profile create
8 * ipython profile list
8 * ipython profile list
9 * ipython profile create --parallel
9 * ipython profile create --parallel
10 * security dir permissions
10 * security dir permissions
11
11
12 Authors
12 Authors
13 -------
13 -------
14
14
15 * MinRK
15 * MinRK
16
16
17 """
17 """
18 from __future__ import absolute_import
18 from __future__ import absolute_import
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 import os
24 import os
25 import shutil
25 import shutil
26 import sys
26 import sys
27 import tempfile
27 import tempfile
28
28
29 from unittest import TestCase
29 from unittest import TestCase
30
30
31 import nose.tools as nt
31 import nose.tools as nt
32
32
33 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
33 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
34 from IPython.core.profiledir import ProfileDir
34 from IPython.core.profiledir import ProfileDir
35
35
36 from IPython.testing import decorators as dec
36 from IPython.testing import decorators as dec
37 from IPython.testing import tools as tt
37 from IPython.testing import tools as tt
38 from IPython.utils import py3compat
38 from IPython.utils import py3compat
39
39 from IPython.utils.process import getoutput
40 from IPython.utils.tempdir import TemporaryDirectory
40
41
41 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
42 # Globals
43 # Globals
43 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
44 TMP_TEST_DIR = tempfile.mkdtemp()
45 TMP_TEST_DIR = tempfile.mkdtemp()
45 HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
46 HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
46 IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
47 IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
47
48
48 #
49 #
49 # Setup/teardown functions/decorators
50 # Setup/teardown functions/decorators
50 #
51 #
51
52
52 def setup():
53 def setup():
53 """Setup test environment for the module:
54 """Setup test environment for the module:
54
55
55 - Adds dummy home dir tree
56 - Adds dummy home dir tree
56 """
57 """
57 # Do not mask exceptions here. In particular, catching WindowsError is a
58 # Do not mask exceptions here. In particular, catching WindowsError is a
58 # problem because that exception is only defined on Windows...
59 # problem because that exception is only defined on Windows...
59 os.makedirs(IP_TEST_DIR)
60 os.makedirs(IP_TEST_DIR)
60
61
61
62
62 def teardown():
63 def teardown():
63 """Teardown test environment for the module:
64 """Teardown test environment for the module:
64
65
65 - Remove dummy home dir tree
66 - Remove dummy home dir tree
66 """
67 """
67 # Note: we remove the parent test dir, which is the root of all test
68 # Note: we remove the parent test dir, which is the root of all test
68 # subdirs we may have created. Use shutil instead of os.removedirs, so
69 # subdirs we may have created. Use shutil instead of os.removedirs, so
69 # that non-empty directories are all recursively removed.
70 # that non-empty directories are all recursively removed.
70 shutil.rmtree(TMP_TEST_DIR)
71 shutil.rmtree(TMP_TEST_DIR)
71
72
72
73
73 #-----------------------------------------------------------------------------
74 #-----------------------------------------------------------------------------
74 # Test functions
75 # Test functions
75 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
76 def win32_without_pywin32():
77 def win32_without_pywin32():
77 if sys.platform == 'win32':
78 if sys.platform == 'win32':
78 try:
79 try:
79 import pywin32
80 import pywin32
80 except ImportError:
81 except ImportError:
81 return True
82 return True
82 return False
83 return False
83
84
84
85
85 class ProfileStartupTest(TestCase):
86 class ProfileStartupTest(TestCase):
86 def setUp(self):
87 def setUp(self):
87 # create profile dir
88 # create profile dir
88 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, 'test')
89 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, 'test')
89 self.options = ['--ipython-dir', IP_TEST_DIR, '--profile', 'test']
90 self.options = ['--ipython-dir', IP_TEST_DIR, '--profile', 'test']
90 self.fname = os.path.join(TMP_TEST_DIR, 'test.py')
91 self.fname = os.path.join(TMP_TEST_DIR, 'test.py')
91
92
92 def tearDown(self):
93 def tearDown(self):
93 # We must remove this profile right away so its presence doesn't
94 # We must remove this profile right away so its presence doesn't
94 # confuse other tests.
95 # confuse other tests.
95 shutil.rmtree(self.pd.location)
96 shutil.rmtree(self.pd.location)
96
97
97 def init(self, startup_file, startup, test):
98 def init(self, startup_file, startup, test):
98 # write startup python file
99 # write startup python file
99 with open(os.path.join(self.pd.startup_dir, startup_file), 'w') as f:
100 with open(os.path.join(self.pd.startup_dir, startup_file), 'w') as f:
100 f.write(startup)
101 f.write(startup)
101 # write simple test file, to check that the startup file was run
102 # write simple test file, to check that the startup file was run
102 with open(self.fname, 'w') as f:
103 with open(self.fname, 'w') as f:
103 f.write(py3compat.doctest_refactor_print(test))
104 f.write(py3compat.doctest_refactor_print(test))
104
105
105 def validate(self, output):
106 def validate(self, output):
106 tt.ipexec_validate(self.fname, output, '', options=self.options)
107 tt.ipexec_validate(self.fname, output, '', options=self.options)
107
108
108 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
109 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
109 def test_startup_py(self):
110 def test_startup_py(self):
110 self.init('00-start.py', 'zzz=123\n',
111 self.init('00-start.py', 'zzz=123\n',
111 py3compat.doctest_refactor_print('print zzz\n'))
112 py3compat.doctest_refactor_print('print zzz\n'))
112 self.validate('123')
113 self.validate('123')
113
114
114 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
115 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
115 def test_startup_ipy(self):
116 def test_startup_ipy(self):
116 self.init('00-start.ipy', '%xmode plain\n', '')
117 self.init('00-start.ipy', '%xmode plain\n', '')
117 self.validate('Exception reporting mode: Plain')
118 self.validate('Exception reporting mode: Plain')
118
119
119
120
120 def test_list_profiles_in():
121 def test_list_profiles_in():
121 # No need to remove these directories and files, as they will get nuked in
122 # No need to remove these directories and files, as they will get nuked in
122 # the module-level teardown.
123 # the module-level teardown.
123 td = tempfile.mkdtemp(dir=TMP_TEST_DIR)
124 td = tempfile.mkdtemp(dir=TMP_TEST_DIR)
124 td = py3compat.str_to_unicode(td)
125 td = py3compat.str_to_unicode(td)
125 for name in ('profile_foo', 'profile_hello', 'not_a_profile'):
126 for name in ('profile_foo', 'profile_hello', 'not_a_profile'):
126 os.mkdir(os.path.join(td, name))
127 os.mkdir(os.path.join(td, name))
127 if dec.unicode_paths:
128 if dec.unicode_paths:
128 os.mkdir(os.path.join(td, u'profile_ΓΌnicode'))
129 os.mkdir(os.path.join(td, u'profile_ΓΌnicode'))
129
130
130 with open(os.path.join(td, 'profile_file'), 'w') as f:
131 with open(os.path.join(td, 'profile_file'), 'w') as f:
131 f.write("I am not a profile directory")
132 f.write("I am not a profile directory")
132 profiles = list_profiles_in(td)
133 profiles = list_profiles_in(td)
133
134
134 # unicode normalization can turn u'ΓΌnicode' into u'u\0308nicode',
135 # unicode normalization can turn u'ΓΌnicode' into u'u\0308nicode',
135 # so only check for *nicode, and that creating a ProfileDir from the
136 # so only check for *nicode, and that creating a ProfileDir from the
136 # name remains valid
137 # name remains valid
137 found_unicode = False
138 found_unicode = False
138 for p in list(profiles):
139 for p in list(profiles):
139 if p.endswith('nicode'):
140 if p.endswith('nicode'):
140 pd = ProfileDir.find_profile_dir_by_name(td, p)
141 pd = ProfileDir.find_profile_dir_by_name(td, p)
141 profiles.remove(p)
142 profiles.remove(p)
142 found_unicode = True
143 found_unicode = True
143 break
144 break
144 if dec.unicode_paths:
145 if dec.unicode_paths:
145 nt.assert_true(found_unicode)
146 nt.assert_true(found_unicode)
146 nt.assert_equal(set(profiles), set(['foo', 'hello']))
147 nt.assert_equal(set(profiles), set(['foo', 'hello']))
147
148
148
149
149 def test_list_bundled_profiles():
150 def test_list_bundled_profiles():
150 # This variable will need to be updated when a new profile gets bundled
151 # This variable will need to be updated when a new profile gets bundled
151 bundled_true = [u'cluster', u'math', u'pysh', u'sympy']
152 bundled_true = [u'cluster', u'math', u'pysh', u'sympy']
152 bundled = sorted(list_bundled_profiles())
153 bundled = sorted(list_bundled_profiles())
153 nt.assert_equal(bundled, bundled_true)
154 nt.assert_equal(bundled, bundled_true)
155
156
157 def test_profile_create_ipython_dir():
158 """ipython profile create respects --ipython-dir"""
159 with TemporaryDirectory() as td:
160 getoutput([sys.executable, '-m', 'IPython', 'profile', 'create',
161 'foo', '--ipython-dir=%s' % td])
162 profile_dir = os.path.join(td, 'profile_foo')
163 assert os.path.exists(profile_dir)
164 ipython_config = os.path.join(profile_dir, 'ipython_config.py')
165 assert os.path.exists(ipython_config)
166 No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now