Show More
@@ -0,0 +1,251 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | # encoding: utf-8 | |||
|
3 | """ | |||
|
4 | The IPython cluster directory | |||
|
5 | """ | |||
|
6 | ||||
|
7 | #----------------------------------------------------------------------------- | |||
|
8 | # Copyright (C) 2008-2009 The IPython Development Team | |||
|
9 | # | |||
|
10 | # Distributed under the terms of the BSD License. The full license is in | |||
|
11 | # the file COPYING, distributed as part of this software. | |||
|
12 | #----------------------------------------------------------------------------- | |||
|
13 | ||||
|
14 | #----------------------------------------------------------------------------- | |||
|
15 | # Imports | |||
|
16 | #----------------------------------------------------------------------------- | |||
|
17 | ||||
|
18 | import os | |||
|
19 | import shutil | |||
|
20 | ||||
|
21 | from IPython.core import release | |||
|
22 | from IPython.config.loader import PyFileConfigLoader | |||
|
23 | from IPython.core.application import Application | |||
|
24 | from IPython.core.component import Component | |||
|
25 | from IPython.config.loader import ArgParseConfigLoader, NoConfigDefault | |||
|
26 | from IPython.utils.traitlets import Unicode | |||
|
27 | ||||
|
28 | #----------------------------------------------------------------------------- | |||
|
29 | # Imports | |||
|
30 | #----------------------------------------------------------------------------- | |||
|
31 | ||||
|
32 | ||||
|
33 | class ClusterDir(Component): | |||
|
34 | """An object to manage the cluster directory and its resources. | |||
|
35 | ||||
|
36 | The cluster directory is used by :command:`ipcontroller`, | |||
|
37 | :command:`ipcontroller` and :command:`ipcontroller` to manage the | |||
|
38 | configuration, logging and security of these applications. | |||
|
39 | ||||
|
40 | This object knows how to find, create and manage these directories. This | |||
|
41 | should be used by any code that want's to handle cluster directories. | |||
|
42 | """ | |||
|
43 | ||||
|
44 | security_dir_name = Unicode('security') | |||
|
45 | log_dir_name = Unicode('log') | |||
|
46 | security_dir = Unicode() | |||
|
47 | log_dir = Unicode('') | |||
|
48 | location = Unicode('') | |||
|
49 | ||||
|
50 | def __init__(self, location): | |||
|
51 | super(ClusterDir, self).__init__(None) | |||
|
52 | self.location = location | |||
|
53 | ||||
|
54 | def _location_changed(self, name, old, new): | |||
|
55 | if not os.path.isdir(new): | |||
|
56 | os.makedirs(new, mode=0777) | |||
|
57 | else: | |||
|
58 | os.chmod(new, 0777) | |||
|
59 | self.security_dir = os.path.join(new, self.security_dir_name) | |||
|
60 | self.log_dir = os.path.join(new, self.log_dir_name) | |||
|
61 | ||||
|
62 | def _log_dir_changed(self, name, old, new): | |||
|
63 | if not os.path.isdir(new): | |||
|
64 | os.mkdir(new, 0777) | |||
|
65 | else: | |||
|
66 | os.chmod(new, 0777) | |||
|
67 | ||||
|
68 | def _security_dir_changed(self, name, old, new): | |||
|
69 | if not os.path.isdir(new): | |||
|
70 | os.mkdir(new, 0700) | |||
|
71 | else: | |||
|
72 | os.chmod(new, 0700) | |||
|
73 | ||||
|
74 | def load_config_file(self, filename): | |||
|
75 | """Load a config file from the top level of the cluster dir. | |||
|
76 | ||||
|
77 | Parameters | |||
|
78 | ---------- | |||
|
79 | filename : unicode or str | |||
|
80 | The filename only of the config file that must be located in | |||
|
81 | the top-level of the cluster directory. | |||
|
82 | """ | |||
|
83 | loader = PyFileConfigLoader(filename, self.location) | |||
|
84 | return loader.load_config() | |||
|
85 | ||||
|
86 | def copy_config_file(self, config_file, path=None): | |||
|
87 | """Copy a default config file into the active cluster directory. | |||
|
88 | ||||
|
89 | Default configuration files are kept in :mod:`IPython.config.default`. | |||
|
90 | This function moves these from that location to the working cluster | |||
|
91 | directory. | |||
|
92 | """ | |||
|
93 | if path is None: | |||
|
94 | import IPython.config.default | |||
|
95 | path = IPython.config.default.__file__.split(os.path.sep)[:-1] | |||
|
96 | path = os.path.sep.join(path) | |||
|
97 | src = os.path.join(path, config_file) | |||
|
98 | dst = os.path.join(self.location, config_file) | |||
|
99 | shutil.copy(src, dst) | |||
|
100 | ||||
|
101 | def copy_all_config_files(self): | |||
|
102 | """Copy all config files into the active cluster directory.""" | |||
|
103 | for f in ['ipcontroller_config.py', 'ipengine_config.py']: | |||
|
104 | self.copy_config_file(f) | |||
|
105 | ||||
|
106 | @classmethod | |||
|
107 | def find_cluster_dir_by_profile(cls, path, profile='default'): | |||
|
108 | """Find/create a cluster dir by profile name and return its ClusterDir. | |||
|
109 | ||||
|
110 | This will create the cluster directory if it doesn't exist. | |||
|
111 | ||||
|
112 | Parameters | |||
|
113 | ---------- | |||
|
114 | path : unicode or str | |||
|
115 | The directory path to look for the cluster directory in. | |||
|
116 | profile : unicode or str | |||
|
117 | The name of the profile. The name of the cluster directory | |||
|
118 | will be "cluster_<profile>". | |||
|
119 | """ | |||
|
120 | dirname = 'cluster_' + profile | |||
|
121 | cluster_dir = os.path.join(os.getcwd(), dirname) | |||
|
122 | if os.path.isdir(cluster_dir): | |||
|
123 | return ClusterDir(cluster_dir) | |||
|
124 | else: | |||
|
125 | if not os.path.isdir(path): | |||
|
126 | raise IOError("Directory doesn't exist: %s" % path) | |||
|
127 | cluster_dir = os.path.join(path, dirname) | |||
|
128 | return ClusterDir(cluster_dir) | |||
|
129 | ||||
|
130 | @classmethod | |||
|
131 | def find_cluster_dir(cls, cluster_dir): | |||
|
132 | """Find/create a cluster dir and return its ClusterDir. | |||
|
133 | ||||
|
134 | This will create the cluster directory if it doesn't exist. | |||
|
135 | ||||
|
136 | Parameters | |||
|
137 | ---------- | |||
|
138 | cluster_dir : unicode or str | |||
|
139 | The path of the cluster directory. This is expanded using | |||
|
140 | :func:`os.path.expandvars` and :func:`os.path.expanduser`. | |||
|
141 | """ | |||
|
142 | cluster_dir = os.path.expandvars(os.path.expanduser(cluster_dir)) | |||
|
143 | return ClusterDir(cluster_dir) | |||
|
144 | ||||
|
145 | ||||
|
146 | class AppWithClusterDirArgParseConfigLoader(ArgParseConfigLoader): | |||
|
147 | """Default command line options for IPython cluster applications.""" | |||
|
148 | ||||
|
149 | def _add_other_arguments(self): | |||
|
150 | self.parser.add_argument('-ipythondir', '--ipython-dir', | |||
|
151 | dest='Global.ipythondir',type=str, | |||
|
152 | help='Set to override default location of Global.ipythondir.', | |||
|
153 | default=NoConfigDefault, | |||
|
154 | metavar='Global.ipythondir') | |||
|
155 | self.parser.add_argument('-p','-profile', '--profile', | |||
|
156 | dest='Global.profile',type=str, | |||
|
157 | help='The string name of the profile to be used. This determines ' | |||
|
158 | 'the name of the cluster dir as: cluster_<profile>. The default profile ' | |||
|
159 | 'is named "default". The cluster directory is resolve this way ' | |||
|
160 | 'if the --cluster-dir option is not used.', | |||
|
161 | default=NoConfigDefault, | |||
|
162 | metavar='Global.profile') | |||
|
163 | self.parser.add_argument('-log_level', '--log-level', | |||
|
164 | dest="Global.log_level",type=int, | |||
|
165 | help='Set the log level (0,10,20,30,40,50). Default is 30.', | |||
|
166 | default=NoConfigDefault) | |||
|
167 | self.parser.add_argument('-cluster_dir', '--cluster-dir', | |||
|
168 | dest='Global.cluster_dir',type=str, | |||
|
169 | help='Set the cluster dir. This overrides the logic used by the ' | |||
|
170 | '--profile option.', | |||
|
171 | default=NoConfigDefault, | |||
|
172 | metavar='Global.cluster_dir') | |||
|
173 | ||||
|
174 | ||||
|
175 | class ApplicationWithClusterDir(Application): | |||
|
176 | """An application that puts everything into a cluster directory. | |||
|
177 | ||||
|
178 | Instead of looking for things in the ipythondir, this type of application | |||
|
179 | will use its own private directory called the "cluster directory" | |||
|
180 | for things like config files, log files, etc. | |||
|
181 | ||||
|
182 | The cluster directory is resolved as follows: | |||
|
183 | ||||
|
184 | * If the ``--cluster-dir`` option is given, it is used. | |||
|
185 | * If ``--cluster-dir`` is not given, the application directory is | |||
|
186 | resolve using the profile name as ``cluster_<profile>``. The search | |||
|
187 | path for this directory is then i) cwd if it is found there | |||
|
188 | and ii) in ipythondir otherwise. | |||
|
189 | ||||
|
190 | The config file for the application is to be put in the cluster | |||
|
191 | dir and named the value of the ``config_file_name`` class attribute. | |||
|
192 | """ | |||
|
193 | ||||
|
194 | def create_default_config(self): | |||
|
195 | super(ApplicationWithClusterDir, self).create_default_config() | |||
|
196 | self.default_config.Global.profile = 'default' | |||
|
197 | self.default_config.Global.cluster_dir = '' | |||
|
198 | ||||
|
199 | def create_command_line_config(self): | |||
|
200 | """Create and return a command line config loader.""" | |||
|
201 | return AppWithClusterDirArgParseConfigLoader( | |||
|
202 | description=self.description, | |||
|
203 | version=release.version | |||
|
204 | ) | |||
|
205 | ||||
|
206 | def find_config_file_name(self): | |||
|
207 | """Find the config file name for this application.""" | |||
|
208 | # For this type of Application it should be set as a class attribute. | |||
|
209 | if not hasattr(self, 'config_file_name'): | |||
|
210 | self.log.critical("No config filename found") | |||
|
211 | ||||
|
212 | def find_config_file_paths(self): | |||
|
213 | """This resolves the cluster directory and sets ``config_file_paths``. | |||
|
214 | ||||
|
215 | This does the following: | |||
|
216 | * Create the :class:`ClusterDir` object for the application. | |||
|
217 | * Set the ``cluster_dir`` attribute of the application and config | |||
|
218 | objects. | |||
|
219 | * Set ``config_file_paths`` to point to the cluster directory. | |||
|
220 | """ | |||
|
221 | ||||
|
222 | # Create the ClusterDir object for managing everything | |||
|
223 | try: | |||
|
224 | cluster_dir = self.command_line_config.Global.cluster_dir | |||
|
225 | except AttributeError: | |||
|
226 | cluster_dir = self.default_config.Global.cluster_dir | |||
|
227 | cluster_dir = os.path.expandvars(os.path.expanduser(cluster_dir)) | |||
|
228 | if cluster_dir: | |||
|
229 | # Just use cluster_dir | |||
|
230 | self.cluster_dir_obj = ClusterDir.find_cluster_dir(cluster_dir) | |||
|
231 | else: | |||
|
232 | # Then look for a profile | |||
|
233 | try: | |||
|
234 | self.profile = self.command_line_config.Global.profile | |||
|
235 | except AttributeError: | |||
|
236 | self.profile = self.default_config.Global.profile | |||
|
237 | self.cluster_dir_obj = ClusterDir.find_cluster_dir_by_profile( | |||
|
238 | self.ipythondir, self.profile) | |||
|
239 | ||||
|
240 | # Set the cluster directory | |||
|
241 | self.cluster_dir = self.cluster_dir_obj.location | |||
|
242 | ||||
|
243 | # These have to be set because they could be different from the one | |||
|
244 | # that we just computed. Because command line has the highest | |||
|
245 | # priority, this will always end up in the master_config. | |||
|
246 | self.default_config.Global.cluster_dir = self.cluster_dir | |||
|
247 | self.command_line_config.Global.cluster_dir = self.cluster_dir | |||
|
248 | self.log.info("Cluster directory set to: %s" % self.cluster_dir) | |||
|
249 | ||||
|
250 | # Set the search path to the cluster directory | |||
|
251 | self.config_file_paths = (self.cluster_dir,) |
@@ -1,7 +1,13 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # encoding: utf-8 |
|
2 | # encoding: utf-8 | |
3 | """ |
|
3 | """ | |
4 | An application for IPython |
|
4 | An application for IPython. | |
|
5 | ||||
|
6 | All top-level applications should use the classes in this module for | |||
|
7 | handling configuration and creating componenets. | |||
|
8 | ||||
|
9 | The job of an :class:`Application` is to create the master configuration | |||
|
10 | object and then create the components, passing the config to them. | |||
5 |
|
11 | |||
6 | Authors: |
|
12 | Authors: | |
7 |
|
13 | |||
@@ -25,13 +31,10 b' Notes' | |||||
25 |
|
31 | |||
26 | import logging |
|
32 | import logging | |
27 | import os |
|
33 | import os | |
28 |
|
||||
29 | import sys |
|
34 | import sys | |
30 | import traceback |
|
|||
31 | from copy import deepcopy |
|
|||
32 |
|
35 | |||
33 | from IPython.core import release |
|
36 | from IPython.core import release | |
34 |
from IPython.utils.genutils import get_ipython_dir |
|
37 | from IPython.utils.genutils import get_ipython_dir | |
35 | from IPython.config.loader import ( |
|
38 | from IPython.config.loader import ( | |
36 | PyFileConfigLoader, |
|
39 | PyFileConfigLoader, | |
37 | ArgParseConfigLoader, |
|
40 | ArgParseConfigLoader, | |
@@ -75,17 +78,17 b' class ApplicationError(Exception):' | |||||
75 |
|
78 | |||
76 |
|
79 | |||
77 | class Application(object): |
|
80 | class Application(object): | |
78 |
"""Load a config, construct |
|
81 | """Load a config, construct components and set them running.""" | |
79 | """ |
|
|||
80 |
|
82 | |||
81 | name = 'ipython' |
|
83 | name = 'ipython' | |
82 | description = 'IPython: an enhanced interactive Python shell.' |
|
84 | description = 'IPython: an enhanced interactive Python shell.' | |
83 | config_file_name = 'ipython_config.py' |
|
85 | config_file_name = 'ipython_config.py' | |
84 | default_log_level = logging.WARN |
|
86 | default_log_level = logging.WARN | |
85 |
|
||||
86 |
|
87 | |||
87 | def __init__(self): |
|
88 | def __init__(self): | |
88 | self.init_logger() |
|
89 | self.init_logger() | |
|
90 | # Track the default and actual separately because some messages are | |||
|
91 | # only printed if we aren't using the default. | |||
89 | self.default_config_file_name = self.config_file_name |
|
92 | self.default_config_file_name = self.config_file_name | |
90 |
|
93 | |||
91 | def init_logger(self): |
|
94 | def init_logger(self): | |
@@ -194,7 +197,7 b' class Application(object):' | |||||
194 |
|
197 | |||
195 | This sets ``self.ipythondir``, but the actual value that is passed |
|
198 | This sets ``self.ipythondir``, but the actual value that is passed | |
196 | to the application is kept in either ``self.default_config`` or |
|
199 | to the application is kept in either ``self.default_config`` or | |
197 |
``self.command_line_config``. This also add |
|
200 | ``self.command_line_config``. This also adds ``self.ipythondir`` to | |
198 | ``sys.path`` so config files there can be references by other config |
|
201 | ``sys.path`` so config files there can be references by other config | |
199 | files. |
|
202 | files. | |
200 | """ |
|
203 | """ | |
@@ -340,115 +343,3 b' class Application(object):' | |||||
340 | elif action == 'exit': |
|
343 | elif action == 'exit': | |
341 | self.exit() |
|
344 | self.exit() | |
342 |
|
345 | |||
343 |
|
||||
344 | class AppWithDirArgParseConfigLoader(ArgParseConfigLoader): |
|
|||
345 | """Default command line options for IPython based applications.""" |
|
|||
346 |
|
||||
347 | def _add_other_arguments(self): |
|
|||
348 | self.parser.add_argument('-ipythondir', '--ipython-dir', |
|
|||
349 | dest='Global.ipythondir',type=str, |
|
|||
350 | help='Set to override default location of Global.ipythondir.', |
|
|||
351 | default=NoConfigDefault, |
|
|||
352 | metavar='Global.ipythondir') |
|
|||
353 | self.parser.add_argument('-p','-profile', '--profile', |
|
|||
354 | dest='Global.profile',type=str, |
|
|||
355 | help='The string name of the profile to be used. This determines ' |
|
|||
356 | 'the name of the application dir: basename_<profile>. The basename is ' |
|
|||
357 | 'determined by the particular application. The default profile ' |
|
|||
358 | 'is named "default". This convention is used if the -app_dir ' |
|
|||
359 | 'option is not used.', |
|
|||
360 | default=NoConfigDefault, |
|
|||
361 | metavar='Global.profile') |
|
|||
362 | self.parser.add_argument('-log_level', '--log-level', |
|
|||
363 | dest="Global.log_level",type=int, |
|
|||
364 | help='Set the log level (0,10,20,30,40,50). Default is 30.', |
|
|||
365 | default=NoConfigDefault) |
|
|||
366 | self.parser.add_argument('-app_dir', '--app-dir', |
|
|||
367 | dest='Global.app_dir',type=str, |
|
|||
368 | help='Set the application dir where everything for this ' |
|
|||
369 | 'application will be found (including the config file). This ' |
|
|||
370 | 'overrides the logic used by the profile option.', |
|
|||
371 | default=NoConfigDefault, |
|
|||
372 | metavar='Global.app_dir') |
|
|||
373 |
|
||||
374 |
|
||||
375 | class ApplicationWithDir(Application): |
|
|||
376 | """An application that puts everything into a application directory. |
|
|||
377 |
|
||||
378 | Instead of looking for things in the ipythondir, this type of application |
|
|||
379 | will use its own private directory called the "application directory" |
|
|||
380 | for things like config files, log files, etc. |
|
|||
381 |
|
||||
382 | The application directory is resolved as follows: |
|
|||
383 |
|
||||
384 | * If the ``--app-dir`` option is given, it is used. |
|
|||
385 | * If ``--app-dir`` is not given, the application directory is resolve using |
|
|||
386 | ``app_dir_basename`` and ``profile`` as ``<app_dir_basename>_<profile>``. |
|
|||
387 | The search path for this directory is then i) cwd if it is found there |
|
|||
388 | and ii) in ipythondir otherwise. |
|
|||
389 |
|
||||
390 | The config file for the application is to be put in the application |
|
|||
391 | dir and named the value of the ``config_file_name`` class attribute. |
|
|||
392 | """ |
|
|||
393 |
|
||||
394 | # The basename used for the application dir: <app_dir_basename>_<profile> |
|
|||
395 | app_dir_basename = 'cluster' |
|
|||
396 |
|
||||
397 | def create_default_config(self): |
|
|||
398 | super(ApplicationWithDir, self).create_default_config() |
|
|||
399 | self.default_config.Global.profile = 'default' |
|
|||
400 | # The application dir. This is empty initially so the default is to |
|
|||
401 | # try to resolve this using the profile. |
|
|||
402 | self.default_config.Global.app_dir = '' |
|
|||
403 |
|
||||
404 | def create_command_line_config(self): |
|
|||
405 | """Create and return a command line config loader.""" |
|
|||
406 | return AppWithDirArgParseConfigLoader( |
|
|||
407 | description=self.description, |
|
|||
408 | version=release.version |
|
|||
409 | ) |
|
|||
410 |
|
||||
411 | def find_config_file_name(self): |
|
|||
412 | """Find the config file name for this application.""" |
|
|||
413 | self.find_app_dir() |
|
|||
414 | self.create_app_dir() |
|
|||
415 |
|
||||
416 | def find_app_dir(self): |
|
|||
417 | """This resolves the app directory. |
|
|||
418 |
|
||||
419 | This method must set ``self.app_dir`` to the location of the app |
|
|||
420 | dir. |
|
|||
421 | """ |
|
|||
422 | # Instead, first look for an explicit app_dir |
|
|||
423 | try: |
|
|||
424 | self.app_dir = self.command_line_config.Global.app_dir |
|
|||
425 | except AttributeError: |
|
|||
426 | self.app_dir = self.default_config.Global.app_dir |
|
|||
427 | self.app_dir = os.path.expandvars(os.path.expanduser(self.app_dir)) |
|
|||
428 | if not self.app_dir: |
|
|||
429 | # Then look for a profile |
|
|||
430 | try: |
|
|||
431 | self.profile = self.command_line_config.Global.profile |
|
|||
432 | except AttributeError: |
|
|||
433 | self.profile = self.default_config.Global.profile |
|
|||
434 | app_dir_name = self.app_dir_basename + '_' + self.profile |
|
|||
435 | try_this = os.path.join(os.getcwd(), app_dir_name) |
|
|||
436 | if os.path.isdir(try_this): |
|
|||
437 | self.app_dir = try_this |
|
|||
438 | else: |
|
|||
439 | self.app_dir = os.path.join(self.ipythondir, app_dir_name) |
|
|||
440 | # These have to be set because they could be different from the one |
|
|||
441 | # that we just computed. Because command line has the highest |
|
|||
442 | # priority, this will always end up in the master_config. |
|
|||
443 | self.default_config.Global.app_dir = self.app_dir |
|
|||
444 | self.command_line_config.Global.app_dir = self.app_dir |
|
|||
445 | self.log.info("Application directory set to: %s" % self.app_dir) |
|
|||
446 |
|
||||
447 | def create_app_dir(self): |
|
|||
448 | """Make sure that the app dir exists.""" |
|
|||
449 | if not os.path.isdir(self.app_dir): |
|
|||
450 | os.makedirs(self.app_dir, mode=0777) |
|
|||
451 |
|
||||
452 | def find_config_file_paths(self): |
|
|||
453 | """Set the search paths for resolving the config file.""" |
|
|||
454 | self.config_file_paths = (self.app_dir,) |
|
@@ -1,7 +1,8 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # encoding: utf-8 |
|
2 | # encoding: utf-8 | |
3 | """ |
|
3 | """ | |
4 | The main IPython application object |
|
4 | The :class:`~IPython.core.application.Application` object for the command | |
|
5 | line :command:`ipython` program. | |||
5 |
|
6 | |||
6 | Authors: |
|
7 | Authors: | |
7 |
|
8 | |||
@@ -34,13 +35,11 b' from IPython.core.iplib import InteractiveShell' | |||||
34 | from IPython.config.loader import ( |
|
35 | from IPython.config.loader import ( | |
35 | NoConfigDefault, |
|
36 | NoConfigDefault, | |
36 | Config, |
|
37 | Config, | |
37 | ConfigError, |
|
|||
38 | PyFileConfigLoader |
|
38 | PyFileConfigLoader | |
39 | ) |
|
39 | ) | |
40 |
|
40 | |||
41 | from IPython.lib import inputhook |
|
41 | from IPython.lib import inputhook | |
42 |
|
42 | |||
43 | from IPython.utils.ipstruct import Struct |
|
|||
44 | from IPython.utils.genutils import filefind, get_ipython_dir |
|
43 | from IPython.utils.genutils import filefind, get_ipython_dir | |
45 |
|
44 | |||
46 | #----------------------------------------------------------------------------- |
|
45 | #----------------------------------------------------------------------------- |
@@ -182,7 +182,7 b' class SeparateStr(Str):' | |||||
182 | class InteractiveShell(Component, Magic): |
|
182 | class InteractiveShell(Component, Magic): | |
183 | """An enhanced, interactive shell for Python.""" |
|
183 | """An enhanced, interactive shell for Python.""" | |
184 |
|
184 | |||
185 | autocall = Enum((0,1,2), config=True) |
|
185 | autocall = Enum((0,1,2), default_value=1, config=True) | |
186 | autoedit_syntax = CBool(False, config=True) |
|
186 | autoedit_syntax = CBool(False, config=True) | |
187 | autoindent = CBool(True, config=True) |
|
187 | autoindent = CBool(True, config=True) | |
188 | automagic = CBool(True, config=True) |
|
188 | automagic = CBool(True, config=True) |
@@ -53,7 +53,7 b' class ConfiguredObjectFactory(Component):' | |||||
53 | class IAdaptedConfiguredObjectFactory(zi.Interface): |
|
53 | class IAdaptedConfiguredObjectFactory(zi.Interface): | |
54 | """I am a component that adapts and configures an object. |
|
54 | """I am a component that adapts and configures an object. | |
55 |
|
55 | |||
56 | This class is useful if you have the adapt a instance and configure it. |
|
56 | This class is useful if you have the adapt an instance and configure it. | |
57 | """ |
|
57 | """ | |
58 |
|
58 | |||
59 | def __init__(config, adaptee=None): |
|
59 | def __init__(config, adaptee=None): |
@@ -1,7 +1,7 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # encoding: utf-8 |
|
2 | # encoding: utf-8 | |
3 | """ |
|
3 | """ | |
4 | The IPython controller application |
|
4 | The IPython controller application. | |
5 | """ |
|
5 | """ | |
6 |
|
6 | |||
7 | #----------------------------------------------------------------------------- |
|
7 | #----------------------------------------------------------------------------- | |
@@ -16,31 +16,25 b' The IPython controller application' | |||||
16 | #----------------------------------------------------------------------------- |
|
16 | #----------------------------------------------------------------------------- | |
17 |
|
17 | |||
18 | import copy |
|
18 | import copy | |
19 | import logging |
|
|||
20 | import os |
|
19 | import os | |
21 | import sys |
|
20 | import sys | |
22 |
|
21 | |||
23 | from twisted.application import service |
|
22 | from twisted.application import service | |
24 |
from twisted.internet import reactor |
|
23 | from twisted.internet import reactor | |
25 | from twisted.python import log |
|
24 | from twisted.python import log | |
26 |
|
25 | |||
27 | from IPython.config.loader import Config, NoConfigDefault |
|
26 | from IPython.config.loader import Config, NoConfigDefault | |
28 |
|
27 | |||
29 |
from IPython. |
|
28 | from IPython.kernel.clusterdir import ( | |
30 | ApplicationWithDir, |
|
29 | ApplicationWithClusterDir, | |
31 | AppWithDirArgParseConfigLoader |
|
30 | AppWithClusterDirArgParseConfigLoader | |
32 | ) |
|
31 | ) | |
33 |
|
32 | |||
34 | from IPython.core import release |
|
33 | from IPython.core import release | |
35 |
|
34 | |||
36 |
from IPython.utils.traitlets import |
|
35 | from IPython.utils.traitlets import Str, Instance | |
37 | from IPython.utils.importstring import import_item |
|
|||
38 |
|
36 | |||
39 | from IPython.kernel import controllerservice |
|
37 | from IPython.kernel import controllerservice | |
40 | from IPython.kernel.configobjfactory import ( |
|
|||
41 | ConfiguredObjectFactory, |
|
|||
42 | AdaptedConfiguredObjectFactory |
|
|||
43 | ) |
|
|||
44 |
|
38 | |||
45 | from IPython.kernel.fcutil import FCServiceFactory |
|
39 | from IPython.kernel.fcutil import FCServiceFactory | |
46 |
|
40 | |||
@@ -112,33 +106,45 b' cl_args = (' | |||||
112 | # Client config |
|
106 | # Client config | |
113 | (('--client-ip',), dict( |
|
107 | (('--client-ip',), dict( | |
114 | type=str, dest='FCClientServiceFactory.ip', default=NoConfigDefault, |
|
108 | type=str, dest='FCClientServiceFactory.ip', default=NoConfigDefault, | |
115 |
help='The IP address or hostname the controller will listen on for |
|
109 | help='The IP address or hostname the controller will listen on for ' | |
|
110 | 'client connections.', | |||
116 | metavar='FCClientServiceFactory.ip') |
|
111 | metavar='FCClientServiceFactory.ip') | |
117 | ), |
|
112 | ), | |
118 | (('--client-port',), dict( |
|
113 | (('--client-port',), dict( | |
119 | type=int, dest='FCClientServiceFactory.port', default=NoConfigDefault, |
|
114 | type=int, dest='FCClientServiceFactory.port', default=NoConfigDefault, | |
120 |
help='The port the controller will listen on for client connections.' |
|
115 | help='The port the controller will listen on for client connections. ' | |
|
116 | 'The default is to use 0, which will autoselect an open port.', | |||
121 | metavar='FCClientServiceFactory.port') |
|
117 | metavar='FCClientServiceFactory.port') | |
122 | ), |
|
118 | ), | |
123 | (('--client-location',), dict( |
|
119 | (('--client-location',), dict( | |
124 | type=str, dest='FCClientServiceFactory.location', default=NoConfigDefault, |
|
120 | type=str, dest='FCClientServiceFactory.location', default=NoConfigDefault, | |
125 |
help='The hostname or |
|
121 | help='The hostname or IP that clients should connect to. This does ' | |
|
122 | 'not control which interface the controller listens on. Instead, this ' | |||
|
123 | 'determines the hostname/IP that is listed in the FURL, which is how ' | |||
|
124 | 'clients know where to connect. Useful if the controller is listening ' | |||
|
125 | 'on multiple interfaces.', | |||
126 | metavar='FCClientServiceFactory.location') |
|
126 | metavar='FCClientServiceFactory.location') | |
127 | ), |
|
127 | ), | |
128 | # Engine config |
|
128 | # Engine config | |
129 | (('--engine-ip',), dict( |
|
129 | (('--engine-ip',), dict( | |
130 | type=str, dest='FCEngineServiceFactory.ip', default=NoConfigDefault, |
|
130 | type=str, dest='FCEngineServiceFactory.ip', default=NoConfigDefault, | |
131 |
help='The IP address or hostname the controller will listen on for |
|
131 | help='The IP address or hostname the controller will listen on for ' | |
|
132 | 'engine connections.', | |||
132 | metavar='FCEngineServiceFactory.ip') |
|
133 | metavar='FCEngineServiceFactory.ip') | |
133 | ), |
|
134 | ), | |
134 | (('--engine-port',), dict( |
|
135 | (('--engine-port',), dict( | |
135 | type=int, dest='FCEngineServiceFactory.port', default=NoConfigDefault, |
|
136 | type=int, dest='FCEngineServiceFactory.port', default=NoConfigDefault, | |
136 |
help='The port the controller will listen on for engine connections.' |
|
137 | help='The port the controller will listen on for engine connections. ' | |
|
138 | 'The default is to use 0, which will autoselect an open port.', | |||
137 | metavar='FCEngineServiceFactory.port') |
|
139 | metavar='FCEngineServiceFactory.port') | |
138 | ), |
|
140 | ), | |
139 | (('--engine-location',), dict( |
|
141 | (('--engine-location',), dict( | |
140 | type=str, dest='FCEngineServiceFactory.location', default=NoConfigDefault, |
|
142 | type=str, dest='FCEngineServiceFactory.location', default=NoConfigDefault, | |
141 |
help='The hostname or |
|
143 | help='The hostname or IP that engines should connect to. This does ' | |
|
144 | 'not control which interface the controller listens on. Instead, this ' | |||
|
145 | 'determines the hostname/IP that is listed in the FURL, which is how ' | |||
|
146 | 'engines know where to connect. Useful if the controller is listening ' | |||
|
147 | 'on multiple interfaces.', | |||
142 | metavar='FCEngineServiceFactory.location') |
|
148 | metavar='FCEngineServiceFactory.location') | |
143 | ), |
|
149 | ), | |
144 | # Global config |
|
150 | # Global config | |
@@ -148,7 +154,9 b' cl_args = (' | |||||
148 | ), |
|
154 | ), | |
149 | (('-r','--reuse-furls'), dict( |
|
155 | (('-r','--reuse-furls'), dict( | |
150 | action='store_true', dest='Global.reuse_furls', default=NoConfigDefault, |
|
156 | action='store_true', dest='Global.reuse_furls', default=NoConfigDefault, | |
151 |
help='Try to reuse all FURL files.' |
|
157 | help='Try to reuse all FURL files. If this is not set all FURL files ' | |
|
158 | 'are deleted before the controller starts. This must be set if ' | |||
|
159 | 'specific ports are specified by --engine-port or --client-port.') | |||
152 | ), |
|
160 | ), | |
153 | (('-ns','--no-security'), dict( |
|
161 | (('-ns','--no-security'), dict( | |
154 | action='store_false', dest='Global.secure', default=NoConfigDefault, |
|
162 | action='store_false', dest='Global.secure', default=NoConfigDefault, | |
@@ -157,7 +165,7 b' cl_args = (' | |||||
157 | ) |
|
165 | ) | |
158 |
|
166 | |||
159 |
|
167 | |||
160 | class IPControllerAppCLConfigLoader(AppWithDirArgParseConfigLoader): |
|
168 | class IPControllerAppCLConfigLoader(AppWithClusterDirArgParseConfigLoader): | |
161 |
|
169 | |||
162 | arguments = cl_args |
|
170 | arguments = cl_args | |
163 |
|
171 | |||
@@ -165,10 +173,9 b' class IPControllerAppCLConfigLoader(AppWithDirArgParseConfigLoader):' | |||||
165 | default_config_file_name = 'ipcontroller_config.py' |
|
173 | default_config_file_name = 'ipcontroller_config.py' | |
166 |
|
174 | |||
167 |
|
175 | |||
168 | class IPControllerApp(ApplicationWithDir): |
|
176 | class IPControllerApp(ApplicationWithClusterDir): | |
169 |
|
177 | |||
170 | name = 'ipcontroller' |
|
178 | name = 'ipcontroller' | |
171 | app_dir_basename = 'cluster' |
|
|||
172 | description = 'Start the IPython controller for parallel computing.' |
|
179 | description = 'Start the IPython controller for parallel computing.' | |
173 | config_file_name = default_config_file_name |
|
180 | config_file_name = default_config_file_name | |
174 |
|
181 | |||
@@ -177,8 +184,6 b' class IPControllerApp(ApplicationWithDir):' | |||||
177 | self.default_config.Global.reuse_furls = False |
|
184 | self.default_config.Global.reuse_furls = False | |
178 | self.default_config.Global.secure = True |
|
185 | self.default_config.Global.secure = True | |
179 | self.default_config.Global.import_statements = [] |
|
186 | self.default_config.Global.import_statements = [] | |
180 | self.default_config.Global.log_dir_name = 'log' |
|
|||
181 | self.default_config.Global.security_dir_name = 'security' |
|
|||
182 | self.default_config.Global.log_to_file = False |
|
187 | self.default_config.Global.log_to_file = False | |
183 |
|
188 | |||
184 | def create_command_line_config(self): |
|
189 | def create_command_line_config(self): | |
@@ -190,36 +195,24 b' class IPControllerApp(ApplicationWithDir):' | |||||
190 |
|
195 | |||
191 | def post_load_command_line_config(self): |
|
196 | def post_load_command_line_config(self): | |
192 | # Now setup reuse_furls |
|
197 | # Now setup reuse_furls | |
193 |
|
|
198 | c = self.command_line_config | |
194 | self.command_line_config.FCClientServiceFactory.reuse_furls = \ |
|
199 | if hasattr(c.Global, 'reuse_furls'): | |
195 | self.command_line_config.Global.reuse_furls |
|
200 | c.FCClientServiceFactory.reuse_furls = c.Global.reuse_furls | |
196 |
|
|
201 | c.FCEngineServiceFactory.reuse_furls = c.Global.reuse_furls | |
197 |
|
|
202 | del c.Global.reuse_furls | |
198 | del self.command_line_config.Global.reuse_furls |
|
203 | if hasattr(c.Global, 'secure'): | |
199 | if hasattr(self.command_line_config.Global, 'secure'): |
|
204 | c.FCClientServiceFactory.secure = c.Global.secure | |
200 |
|
|
205 | c.FCEngineServiceFactory.secure = c.Global.secure | |
201 |
|
|
206 | del c.Global.secure | |
202 | self.command_line_config.FCEngineServiceFactory.secure = \ |
|
|||
203 | self.command_line_config.Global.secure |
|
|||
204 | del self.command_line_config.Global.secure |
|
|||
205 |
|
207 | |||
206 | def pre_construct(self): |
|
208 | def pre_construct(self): | |
|
209 | # The log and security dirs were set earlier, but here we put them | |||
|
210 | # into the config and log them. | |||
207 | config = self.master_config |
|
211 | config = self.master_config | |
208 | # Now set the security_dir and log_dir and create them. We use |
|
212 | sdir = self.cluster_dir_obj.security_dir | |
209 | # the names an construct the absolute paths. |
|
213 | self.security_dir = config.Global.security_dir = sdir | |
210 | security_dir = os.path.join(config.Global.app_dir, |
|
214 | ldir = self.cluster_dir_obj.log_dir | |
211 | config.Global.security_dir_name) |
|
215 | self.log_dir = config.Global.log_dir = ldir | |
212 | log_dir = os.path.join(config.Global.app_dir, |
|
|||
213 | config.Global.log_dir_name) |
|
|||
214 | if not os.path.isdir(security_dir): |
|
|||
215 | os.mkdir(security_dir, 0700) |
|
|||
216 | else: |
|
|||
217 | os.chmod(security_dir, 0700) |
|
|||
218 | if not os.path.isdir(log_dir): |
|
|||
219 | os.mkdir(log_dir, 0777) |
|
|||
220 |
|
||||
221 | self.security_dir = config.Global.security_dir = security_dir |
|
|||
222 | self.log_dir = config.Global.log_dir = log_dir |
|
|||
223 | self.log.info("Log directory set to: %s" % self.log_dir) |
|
216 | self.log.info("Log directory set to: %s" % self.log_dir) | |
224 | self.log.info("Security directory set to: %s" % self.security_dir) |
|
217 | self.log.info("Security directory set to: %s" % self.security_dir) | |
225 |
|
218 |
@@ -24,9 +24,9 b' from twisted.python import log' | |||||
24 |
|
24 | |||
25 | from IPython.config.loader import NoConfigDefault |
|
25 | from IPython.config.loader import NoConfigDefault | |
26 |
|
26 | |||
27 |
from IPython. |
|
27 | from IPython.kernel.clusterdir import ( | |
28 | ApplicationWithDir, |
|
28 | ApplicationWithClusterDir, | |
29 | AppWithDirArgParseConfigLoader |
|
29 | AppWithClusterDirArgParseConfigLoader | |
30 | ) |
|
30 | ) | |
31 | from IPython.core import release |
|
31 | from IPython.core import release | |
32 |
|
32 | |||
@@ -65,7 +65,7 b' cl_args = (' | |||||
65 | ) |
|
65 | ) | |
66 |
|
66 | |||
67 |
|
67 | |||
68 | class IPEngineAppCLConfigLoader(AppWithDirArgParseConfigLoader): |
|
68 | class IPEngineAppCLConfigLoader(AppWithClusterDirArgParseConfigLoader): | |
69 |
|
69 | |||
70 | arguments = cl_args |
|
70 | arguments = cl_args | |
71 |
|
71 | |||
@@ -87,10 +87,9 b' mpi.size = 0' | |||||
87 | default_config_file_name = 'ipengine_config.py' |
|
87 | default_config_file_name = 'ipengine_config.py' | |
88 |
|
88 | |||
89 |
|
89 | |||
90 | class IPEngineApp(ApplicationWithDir): |
|
90 | class IPEngineApp(ApplicationWithClusterDir): | |
91 |
|
91 | |||
92 | name = 'ipengine' |
|
92 | name = 'ipengine' | |
93 | app_dir_basename = 'cluster' |
|
|||
94 | description = 'Start the IPython engine for parallel computing.' |
|
93 | description = 'Start the IPython engine for parallel computing.' | |
95 | config_file_name = default_config_file_name |
|
94 | config_file_name = default_config_file_name | |
96 |
|
95 | |||
@@ -130,21 +129,10 b' class IPEngineApp(ApplicationWithDir):' | |||||
130 |
|
129 | |||
131 | def pre_construct(self): |
|
130 | def pre_construct(self): | |
132 | config = self.master_config |
|
131 | config = self.master_config | |
133 | # Now set the security_dir and log_dir and create them. We use |
|
132 | sdir = self.cluster_dir_obj.security_dir | |
134 | # the names an construct the absolute paths. |
|
133 | self.security_dir = config.Global.security_dir = sdir | |
135 | security_dir = os.path.join(config.Global.app_dir, |
|
134 | ldir = self.cluster_dir_obj.log_dir | |
136 | config.Global.security_dir_name) |
|
135 | self.log_dir = config.Global.log_dir = ldir | |
137 | log_dir = os.path.join(config.Global.app_dir, |
|
|||
138 | config.Global.log_dir_name) |
|
|||
139 | if not os.path.isdir(security_dir): |
|
|||
140 | os.mkdir(security_dir, 0700) |
|
|||
141 | else: |
|
|||
142 | os.chmod(security_dir, 0700) |
|
|||
143 | if not os.path.isdir(log_dir): |
|
|||
144 | os.mkdir(log_dir, 0777) |
|
|||
145 |
|
||||
146 | self.security_dir = config.Global.security_dir = security_dir |
|
|||
147 | self.log_dir = config.Global.log_dir = log_dir |
|
|||
148 | self.log.info("Log directory set to: %s" % self.log_dir) |
|
136 | self.log.info("Log directory set to: %s" % self.log_dir) | |
149 | self.log.info("Security directory set to: %s" % self.security_dir) |
|
137 | self.log.info("Security directory set to: %s" % self.security_dir) | |
150 |
|
138 | |||
@@ -158,7 +146,7 b' class IPEngineApp(ApplicationWithDir):' | |||||
158 | else: |
|
146 | else: | |
159 | # We should know what the app dir is |
|
147 | # We should know what the app dir is | |
160 | try_this = os.path.join( |
|
148 | try_this = os.path.join( | |
161 |
config.Global. |
|
149 | config.Global.cluster_dir, | |
162 | config.Global.security_dir, |
|
150 | config.Global.security_dir, | |
163 | config.Global.furl_file_name |
|
151 | config.Global.furl_file_name | |
164 | ) |
|
152 | ) |
@@ -736,14 +736,14 b' def get_home_dir():' | |||||
736 | root=os.path.abspath(root).rstrip('\\') |
|
736 | root=os.path.abspath(root).rstrip('\\') | |
737 | if isdir(os.path.join(root, '_ipython')): |
|
737 | if isdir(os.path.join(root, '_ipython')): | |
738 | os.environ["IPYKITROOT"] = root |
|
738 | os.environ["IPYKITROOT"] = root | |
739 | return root |
|
739 | return root.decode(sys.getfilesystemencoding()) | |
740 | try: |
|
740 | try: | |
741 | homedir = env['HOME'] |
|
741 | homedir = env['HOME'] | |
742 | if not isdir(homedir): |
|
742 | if not isdir(homedir): | |
743 | # in case a user stuck some string which does NOT resolve to a |
|
743 | # in case a user stuck some string which does NOT resolve to a | |
744 | # valid path, it's as good as if we hadn't foud it |
|
744 | # valid path, it's as good as if we hadn't foud it | |
745 | raise KeyError |
|
745 | raise KeyError | |
746 | return homedir |
|
746 | return homedir.decode(sys.getfilesystemencoding()) | |
747 | except KeyError: |
|
747 | except KeyError: | |
748 | if os.name == 'posix': |
|
748 | if os.name == 'posix': | |
749 | raise HomeDirError,'undefined $HOME, IPython can not proceed.' |
|
749 | raise HomeDirError,'undefined $HOME, IPython can not proceed.' | |
@@ -755,7 +755,7 b' def get_home_dir():' | |||||
755 | homedir = os.path.join(env['USERPROFILE']) |
|
755 | homedir = os.path.join(env['USERPROFILE']) | |
756 | if not isdir(homedir): |
|
756 | if not isdir(homedir): | |
757 | raise HomeDirError |
|
757 | raise HomeDirError | |
758 | return homedir |
|
758 | return homedir.decode(sys.getfilesystemencoding()) | |
759 | except KeyError: |
|
759 | except KeyError: | |
760 | try: |
|
760 | try: | |
761 | # Use the registry to get the 'My Documents' folder. |
|
761 | # Use the registry to get the 'My Documents' folder. | |
@@ -771,14 +771,14 b' def get_home_dir():' | |||||
771 | 'This is not a valid directory on your system.' % |
|
771 | 'This is not a valid directory on your system.' % | |
772 | homedir) |
|
772 | homedir) | |
773 | raise HomeDirError(e) |
|
773 | raise HomeDirError(e) | |
774 | return homedir |
|
774 | return homedir.decode(sys.getfilesystemencoding()) | |
775 | except HomeDirError: |
|
775 | except HomeDirError: | |
776 | raise |
|
776 | raise | |
777 | except: |
|
777 | except: | |
778 | return 'C:\\' |
|
778 | return 'C:\\'.decode(sys.getfilesystemencoding()) | |
779 | elif os.name == 'dos': |
|
779 | elif os.name == 'dos': | |
780 | # Desperate, may do absurd things in classic MacOS. May work under DOS. |
|
780 | # Desperate, may do absurd things in classic MacOS. May work under DOS. | |
781 | return 'C:\\' |
|
781 | return 'C:\\'.decode(sys.getfilesystemencoding()) | |
782 | else: |
|
782 | else: | |
783 | raise HomeDirError,'support for your operating system not implemented.' |
|
783 | raise HomeDirError,'support for your operating system not implemented.' | |
784 |
|
784 | |||
@@ -795,31 +795,6 b' def get_ipython_dir():' | |||||
795 | os.path.join(home_dir, ipdir_def))) |
|
795 | os.path.join(home_dir, ipdir_def))) | |
796 | return ipdir.decode(sys.getfilesystemencoding()) |
|
796 | return ipdir.decode(sys.getfilesystemencoding()) | |
797 |
|
797 | |||
798 | def get_security_dir(): |
|
|||
799 | """Get the IPython security directory. |
|
|||
800 |
|
||||
801 | This directory is the default location for all security related files, |
|
|||
802 | including SSL/TLS certificates and FURL files. |
|
|||
803 |
|
||||
804 | If the directory does not exist, it is created with 0700 permissions. |
|
|||
805 | If it exists, permissions are set to 0700. |
|
|||
806 | """ |
|
|||
807 | security_dir = os.path.join(get_ipython_dir(), 'security') |
|
|||
808 | if not os.path.isdir(security_dir): |
|
|||
809 | os.mkdir(security_dir, 0700) |
|
|||
810 | else: |
|
|||
811 | os.chmod(security_dir, 0700) |
|
|||
812 | return security_dir |
|
|||
813 |
|
||||
814 | def get_log_dir(): |
|
|||
815 | """Get the IPython log directory. |
|
|||
816 |
|
||||
817 | If the log directory does not exist, it is created. |
|
|||
818 | """ |
|
|||
819 | log_dir = os.path.join(get_ipython_dir(), 'log') |
|
|||
820 | if not os.path.isdir(log_dir): |
|
|||
821 | os.mkdir(log_dir, 0777) |
|
|||
822 | return log_dir |
|
|||
823 |
|
798 | |||
824 | #**************************************************************************** |
|
799 | #**************************************************************************** | |
825 | # strings and text |
|
800 | # strings and text |
General Comments 0
You need to be logged in to leave comments.
Login now