Show More
@@ -0,0 +1,11 b'' | |||||
|
1 | This is the IPython startup directory | |||
|
2 | ||||
|
3 | .py and .ipy files in this directory will be run *prior* to any code or files specified | |||
|
4 | via the exec_lines or exec_files configurables whenever you load this profile. | |||
|
5 | ||||
|
6 | Files will be run in lexicographical order, so you can control the execution order of files | |||
|
7 | with a prefix, e.g.:: | |||
|
8 | ||||
|
9 | 00-first.py | |||
|
10 | 50-middle.py | |||
|
11 | 99-last.ipy |
@@ -0,0 +1,103 b'' | |||||
|
1 | """Tests for profile-related functions. | |||
|
2 | ||||
|
3 | Currently only the startup-dir functionality is tested, but more tests should | |||
|
4 | be added for: | |||
|
5 | ||||
|
6 | * ipython profile create | |||
|
7 | * ipython profile list | |||
|
8 | * ipython profile create --parallel | |||
|
9 | * security dir permissions | |||
|
10 | ||||
|
11 | Authors | |||
|
12 | ------- | |||
|
13 | ||||
|
14 | * MinRK | |||
|
15 | ||||
|
16 | """ | |||
|
17 | from __future__ import absolute_import | |||
|
18 | ||||
|
19 | #----------------------------------------------------------------------------- | |||
|
20 | # Imports | |||
|
21 | #----------------------------------------------------------------------------- | |||
|
22 | ||||
|
23 | import os | |||
|
24 | import shutil | |||
|
25 | import sys | |||
|
26 | import tempfile | |||
|
27 | ||||
|
28 | import nose.tools as nt | |||
|
29 | from nose import SkipTest | |||
|
30 | ||||
|
31 | from IPython.core.profiledir import ProfileDir | |||
|
32 | ||||
|
33 | from IPython.testing import decorators as dec | |||
|
34 | from IPython.testing import tools as tt | |||
|
35 | from IPython.utils import py3compat | |||
|
36 | ||||
|
37 | ||||
|
38 | #----------------------------------------------------------------------------- | |||
|
39 | # Globals | |||
|
40 | #----------------------------------------------------------------------------- | |||
|
41 | TMP_TEST_DIR = tempfile.mkdtemp() | |||
|
42 | HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir") | |||
|
43 | IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython') | |||
|
44 | ||||
|
45 | # | |||
|
46 | # Setup/teardown functions/decorators | |||
|
47 | # | |||
|
48 | ||||
|
49 | def setup(): | |||
|
50 | """Setup test environment for the module: | |||
|
51 | ||||
|
52 | - Adds dummy home dir tree | |||
|
53 | """ | |||
|
54 | # Do not mask exceptions here. In particular, catching WindowsError is a | |||
|
55 | # problem because that exception is only defined on Windows... | |||
|
56 | os.makedirs(IP_TEST_DIR) | |||
|
57 | ||||
|
58 | ||||
|
59 | def teardown(): | |||
|
60 | """Teardown test environment for the module: | |||
|
61 | ||||
|
62 | - Remove dummy home dir tree | |||
|
63 | """ | |||
|
64 | # Note: we remove the parent test dir, which is the root of all test | |||
|
65 | # subdirs we may have created. Use shutil instead of os.removedirs, so | |||
|
66 | # that non-empty directories are all recursively removed. | |||
|
67 | shutil.rmtree(TMP_TEST_DIR) | |||
|
68 | ||||
|
69 | ||||
|
70 | #----------------------------------------------------------------------------- | |||
|
71 | # Test functions | |||
|
72 | #----------------------------------------------------------------------------- | |||
|
73 | ||||
|
74 | def test_startup_py(): | |||
|
75 | # create profile dir | |||
|
76 | pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, 'test') | |||
|
77 | # write startup python file | |||
|
78 | with open(os.path.join(pd.startup_dir, '00-start.py'), 'w') as f: | |||
|
79 | f.write('zzz=123\n') | |||
|
80 | # write simple test file, to check that the startup file was run | |||
|
81 | fname = os.path.join(TMP_TEST_DIR, 'test.py') | |||
|
82 | with open(fname, 'w') as f: | |||
|
83 | f.write('print zzz\n') | |||
|
84 | # validate output | |||
|
85 | tt.ipexec_validate(fname, '123', '', | |||
|
86 | options=['--ipython-dir', IP_TEST_DIR, '--profile', 'test']) | |||
|
87 | ||||
|
88 | def test_startup_ipy(): | |||
|
89 | # create profile dir | |||
|
90 | pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, 'test') | |||
|
91 | # write startup ipython file | |||
|
92 | with open(os.path.join(pd.startup_dir, '00-start.ipy'), 'w') as f: | |||
|
93 | f.write('%profile\n') | |||
|
94 | # write empty script, because we don't need anything to happen | |||
|
95 | # after the startup file is run | |||
|
96 | fname = os.path.join(TMP_TEST_DIR, 'test.py') | |||
|
97 | with open(fname, 'w') as f: | |||
|
98 | f.write('') | |||
|
99 | # validate output | |||
|
100 | tt.ipexec_validate(fname, 'test', '', | |||
|
101 | options=['--ipython-dir', IP_TEST_DIR, '--profile', 'test']) | |||
|
102 | ||||
|
103 | No newline at end of file |
@@ -59,9 +59,11 b' class ProfileDir(LoggingConfigurable):' | |||||
59 |
|
59 | |||
60 | security_dir_name = Unicode('security') |
|
60 | security_dir_name = Unicode('security') | |
61 | log_dir_name = Unicode('log') |
|
61 | log_dir_name = Unicode('log') | |
|
62 | startup_dir_name = Unicode('startup') | |||
62 | pid_dir_name = Unicode('pid') |
|
63 | pid_dir_name = Unicode('pid') | |
63 | security_dir = Unicode(u'') |
|
64 | security_dir = Unicode(u'') | |
64 | log_dir = Unicode(u'') |
|
65 | log_dir = Unicode(u'') | |
|
66 | startup_dir = Unicode(u'') | |||
65 | pid_dir = Unicode(u'') |
|
67 | pid_dir = Unicode(u'') | |
66 |
|
68 | |||
67 | location = Unicode(u'', config=True, |
|
69 | location = Unicode(u'', config=True, | |
@@ -81,6 +83,7 b' class ProfileDir(LoggingConfigurable):' | |||||
81 | # ensure config files exist: |
|
83 | # ensure config files exist: | |
82 | self.security_dir = os.path.join(new, self.security_dir_name) |
|
84 | self.security_dir = os.path.join(new, self.security_dir_name) | |
83 | self.log_dir = os.path.join(new, self.log_dir_name) |
|
85 | self.log_dir = os.path.join(new, self.log_dir_name) | |
|
86 | self.startup_dir = os.path.join(new, self.startup_dir_name) | |||
84 | self.pid_dir = os.path.join(new, self.pid_dir_name) |
|
87 | self.pid_dir = os.path.join(new, self.pid_dir_name) | |
85 | self.check_dirs() |
|
88 | self.check_dirs() | |
86 |
|
89 | |||
@@ -91,6 +94,17 b' class ProfileDir(LoggingConfigurable):' | |||||
91 | if not os.path.isdir(self.log_dir): |
|
94 | if not os.path.isdir(self.log_dir): | |
92 | os.mkdir(self.log_dir) |
|
95 | os.mkdir(self.log_dir) | |
93 |
|
96 | |||
|
97 | def _startup_dir_changed(self, name, old, new): | |||
|
98 | self.check_startup_dir() | |||
|
99 | ||||
|
100 | def check_startup_dir(self): | |||
|
101 | if not os.path.isdir(self.startup_dir): | |||
|
102 | os.mkdir(self.startup_dir) | |||
|
103 | readme = os.path.join(self.startup_dir, 'README') | |||
|
104 | src = os.path.join(get_ipython_package_dir(), u'config', u'profile', u'README_STARTUP') | |||
|
105 | if not os.path.exists(readme): | |||
|
106 | shutil.copy(src, readme) | |||
|
107 | ||||
94 | def _security_dir_changed(self, name, old, new): |
|
108 | def _security_dir_changed(self, name, old, new): | |
95 | self.check_security_dir() |
|
109 | self.check_security_dir() | |
96 |
|
110 | |||
@@ -119,6 +133,7 b' class ProfileDir(LoggingConfigurable):' | |||||
119 | self.check_security_dir() |
|
133 | self.check_security_dir() | |
120 | self.check_log_dir() |
|
134 | self.check_log_dir() | |
121 | self.check_pid_dir() |
|
135 | self.check_pid_dir() | |
|
136 | self.check_startup_dir() | |||
122 |
|
137 | |||
123 | def copy_config_file(self, config_file, path=None, overwrite=False): |
|
138 | def copy_config_file(self, config_file, path=None, overwrite=False): | |
124 | """Copy a default config file into the active profile directory. |
|
139 | """Copy a default config file into the active profile directory. |
@@ -22,6 +22,7 b' Authors' | |||||
22 |
|
22 | |||
23 | from __future__ import absolute_import |
|
23 | from __future__ import absolute_import | |
24 |
|
24 | |||
|
25 | import glob | |||
25 | import os |
|
26 | import os | |
26 | import sys |
|
27 | import sys | |
27 |
|
28 | |||
@@ -175,6 +176,7 b' class InteractiveShellApp(Configurable):' | |||||
175 |
|
176 | |||
176 | def init_code(self): |
|
177 | def init_code(self): | |
177 | """run the pre-flight code, specified via exec_lines""" |
|
178 | """run the pre-flight code, specified via exec_lines""" | |
|
179 | self._run_startup_files() | |||
178 | self._run_exec_lines() |
|
180 | self._run_exec_lines() | |
179 | self._run_exec_files() |
|
181 | self._run_exec_files() | |
180 | self._run_cmd_line_code() |
|
182 | self._run_cmd_line_code() | |
@@ -230,6 +232,22 b' class InteractiveShellApp(Configurable):' | |||||
230 | finally: |
|
232 | finally: | |
231 | sys.argv = save_argv |
|
233 | sys.argv = save_argv | |
232 |
|
234 | |||
|
235 | def _run_startup_files(self): | |||
|
236 | """Run files from profile startup directory""" | |||
|
237 | startup_dir = self.profile_dir.startup_dir | |||
|
238 | startup_files = glob.glob(os.path.join(startup_dir, '*.py')) | |||
|
239 | startup_files += glob.glob(os.path.join(startup_dir, '*.ipy')) | |||
|
240 | if not startup_files: | |||
|
241 | return | |||
|
242 | ||||
|
243 | self.log.debug("Running startup files from %s...", startup_dir) | |||
|
244 | try: | |||
|
245 | for fname in sorted(startup_files): | |||
|
246 | self._exec_file(fname) | |||
|
247 | except: | |||
|
248 | self.log.warn("Unknown error in handling startup files:") | |||
|
249 | self.shell.showtraceback() | |||
|
250 | ||||
233 | def _run_exec_files(self): |
|
251 | def _run_exec_files(self): | |
234 | """Run files from IPythonApp.exec_files""" |
|
252 | """Run files from IPythonApp.exec_files""" | |
235 | if not self.exec_files: |
|
253 | if not self.exec_files: |
@@ -259,7 +259,7 b" def ipexec_validate(fname, expected_out, expected_err=''," | |||||
259 |
|
259 | |||
260 | import nose.tools as nt |
|
260 | import nose.tools as nt | |
261 |
|
261 | |||
262 | out, err = ipexec(fname) |
|
262 | out, err = ipexec(fname, options) | |
263 | #print 'OUT', out # dbg |
|
263 | #print 'OUT', out # dbg | |
264 | #print 'ERR', err # dbg |
|
264 | #print 'ERR', err # dbg | |
265 | # If there are any errors, we must check those befor stdout, as they may be |
|
265 | # If there are any errors, we must check those befor stdout, as they may be |
@@ -358,6 +358,35 b' you create profiles with the name of one of our shipped profiles, these config' | |||||
358 | files will be copied over instead of starting with the automatically generated |
|
358 | files will be copied over instead of starting with the automatically generated | |
359 | config files. |
|
359 | config files. | |
360 |
|
360 | |||
|
361 | Security Files | |||
|
362 | -------------- | |||
|
363 | ||||
|
364 | If you are using the notebook, qtconsole, or parallel code, IPython stores | |||
|
365 | connection information in small JSON files in the active profile's security | |||
|
366 | directory. This directory is made private, so only you can see the files inside. If | |||
|
367 | you need to move connection files around to other computers, this is where they will | |||
|
368 | be. If you want your code to be able to open security files by name, we have a | |||
|
369 | convenience function :func:`IPython.utils.path.get_security_file`, which will return | |||
|
370 | the absolute path to a security file from its filename and [optionally] profile | |||
|
371 | name. | |||
|
372 | ||||
|
373 | Startup Files | |||
|
374 | ------------- | |||
|
375 | ||||
|
376 | If you want some code to be run at the beginning of every IPython session with a | |||
|
377 | particular profile, the easiest way is to add Python (.py) or IPython (.ipy) scripts | |||
|
378 | to your :file:`<profile>/startup` directory. Files in this directory will always be | |||
|
379 | executed as soon as the IPython shell is constructed, and before any other code or | |||
|
380 | scripts you have specified. If you have multiple files in the startup directory, | |||
|
381 | they will be run in lexicographical order, so you can control the ordering by adding | |||
|
382 | a '00-' prefix. | |||
|
383 | ||||
|
384 | .. note:: | |||
|
385 | ||||
|
386 | Automatic startup files are new in IPython 0.12. Use the | |||
|
387 | InteractiveShellApp.exec_files configurable for similar behavior in 0.11. | |||
|
388 | ||||
|
389 | ||||
361 | .. _commandline: |
|
390 | .. _commandline: | |
362 |
|
391 | |||
363 | Command-line arguments |
|
392 | Command-line arguments |
@@ -142,4 +142,19 b' Profiles allow you to use IPython for different tasks, keeping separate config' | |||||
142 | files and history for each one. More details in :ref:`the profiles section |
|
142 | files and history for each one. More details in :ref:`the profiles section | |
143 | <profiles>`. |
|
143 | <profiles>`. | |
144 |
|
144 | |||
|
145 | Startup Files | |||
|
146 | ------------- | |||
|
147 | ||||
|
148 | If you want some code to be run at the beginning of every IPython session, the | |||
|
149 | easiest way is to add Python (.py) or IPython (.ipy) scripts to your | |||
|
150 | :file:`<profile>/startup` directory. Files in this directory will always be executed | |||
|
151 | as soon as the IPython shell is constructed, and before any other code or scripts | |||
|
152 | you have specified. If you have multiple files in the startup directory, they will | |||
|
153 | be run in lexicographical order, so you can control the ordering by adding a '00-' | |||
|
154 | prefix. | |||
|
155 | ||||
|
156 | .. note:: | |||
|
157 | ||||
|
158 | Automatic startup files are new in IPython 0.12. Use the | |||
|
159 | InteractiveShellApp.exec_files configurable for similar behavior in 0.11. | |||
145 |
|
160 |
@@ -132,7 +132,7 b' def find_package_data():' | |||||
132 | static_data.append(os.path.join(parent, f)) |
|
132 | static_data.append(os.path.join(parent, f)) | |
133 |
|
133 | |||
134 | package_data = { |
|
134 | package_data = { | |
135 | 'IPython.config.profile' : ['README', '*/*.py'], |
|
135 | 'IPython.config.profile' : ['README*', '*/*.py'], | |
136 | 'IPython.testing' : ['*.txt'], |
|
136 | 'IPython.testing' : ['*.txt'], | |
137 | 'IPython.frontend.html.notebook' : ['templates/*'] + static_data, |
|
137 | 'IPython.frontend.html.notebook' : ['templates/*'] + static_data, | |
138 | 'IPython.frontend.qt.console' : ['resources/icon/*.svg'], |
|
138 | 'IPython.frontend.qt.console' : ['resources/icon/*.svg'], |
General Comments 0
You need to be logged in to leave comments.
Login now