##// END OF EJS Templates
Work on Application and loader testing.
Brian Granger -
Show More
@@ -0,0 +1,92
1 #!/usr/bin/env python
2 # encoding: utf-8
3 """
4 Tests for IPython.config.loader
5
6 Authors:
7
8 * Brian Granger
9 * Fernando Perez (design help)
10 """
11
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2009 The IPython Development Team
14 #
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
18
19 #-----------------------------------------------------------------------------
20 # Imports
21 #-----------------------------------------------------------------------------
22
23 import os
24 from tempfile import mkstemp
25 from unittest import TestCase
26
27 from IPython.config.loader import PyFileConfigLoader, ArgParseConfigLoader
28
29 #-----------------------------------------------------------------------------
30 # Actual tests
31 #-----------------------------------------------------------------------------
32
33
34 pyfile = """
35 A = 10
36 B = range(10)
37 C = True
38 D = 'hi there'
39 """
40
41 class TestPyFileCL(TestCase):
42
43 def test_basic(self):
44 fd, fname = mkstemp()
45 f = os.fdopen(fd, 'w')
46 f.write(pyfile)
47 f.close()
48 cl = PyFileConfigLoader(fname)
49 config = cl.load_config()
50 self.assertEquals(config.A, 10)
51 self.assertEquals(config.B, range(10))
52 self.assertEquals(config.C, True)
53 self.assertEquals(config.D, 'hi there')
54
55
56 class TestArgParseCL(TestCase):
57
58 def test_basic(self):
59
60 class MyLoader(ArgParseConfigLoader):
61 arguments = [
62 (('-f','--foo'), dict(dest='FOO', type=str)),
63 (('-b',), dict(dest='BAR', type=int)),
64 (('-n',), dict(dest='N', action='store_true')),
65 (('BAM',), dict(type=str))
66 ]
67
68 cl = MyLoader()
69 config = cl.load_config('-f hi -b 10 -n wow'.split())
70 self.assertEquals(config.FOO, 'hi')
71 self.assertEquals(config.BAR, 10)
72 self.assertEquals(config.N, True)
73 self.assertEquals(config.BAM, 'wow')
74
75 def test_add_arguments(self):
76
77 class MyLoader(ArgParseConfigLoader):
78 def _add_arguments(self):
79 subparsers = self.parser.add_subparsers(dest='subparser_name')
80 subparser1 = subparsers.add_parser('1')
81 subparser1.add_argument('-x')
82 subparser2 = subparsers.add_parser('2')
83 subparser2.add_argument('y')
84
85 cl = MyLoader()
86 config = cl.load_config('2 frobble'.split())
87 self.assertEquals(config.subparser_name, '2')
88 self.assertEquals(config.y, 'frobble')
89 config = cl.load_config('1 -x frobble'.split())
90 self.assertEquals(config.subparser_name, '1')
91 self.assertEquals(config.x, 'frobble')
92
@@ -1,174 +1,159
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
5
6 Authors:
6 Authors:
7
7
8 * Brian Granger
8 * Brian Granger
9 * Fernando Perez
9 * Fernando Perez
10
10
11 Notes
11 Notes
12 -----
12 -----
13
13
14 The following directories are relevant in the startup of an app:
14 The following directories are relevant in the startup of an app:
15
15
16 * The ipythondir. This has a default, but can be set by IPYTHONDIR or at
16 * The ipythondir. This has a default, but can be set by IPYTHONDIR or at
17 the command line.
17 the command line.
18 * The current working directory.
18 * The current working directory.
19 * Another runtime directory. With some applications (engine, controller) we
19 * Another runtime directory. With some applications (engine, controller) we
20 need the ability to have different cluster configs. Each of these needs
20 need the ability to have different cluster configs. Each of these needs
21 to have its own config, security dir and log dir. We could simply treat
21 to have its own config, security dir and log dir. We could simply treat
22 these as regular ipython dirs.
22 these as regular ipython dirs.
23
23
24 There are number of ways in which these directories are used:
24 There are number of ways in which these directories are used:
25
25
26 * For config files.
26 * For config files.
27 * For other assets and resources needed to run. These include
27 * For other assets and resources needed to run. These include
28 plugins, magics, furls files.
28 plugins, magics, furls files.
29 * For writing various things created at runtime like logs, furl files, etc.
29 * For writing various things created at runtime like logs, furl files, etc.
30
30
31 Questions:
31 Questions:
32
32
33 1. Can we limit ourselves to 1 config file or do we want to have a sequence
33
34 * Can we limit ourselves to 1 config file or do we want to have a sequence
34 of them like IPYTHONDIR->RUNTIMEDIR->CWD?
35 of them like IPYTHONDIR->RUNTIMEDIR->CWD?
35 2. Do we need a debug mode that has custom exception handling and can drop
36 * Do we need a debug mode that has custom exception handling and can drop
36 into pdb upno startup?
37 into pdb upno startup?
37 3. Do we need to use an OutputTrap to capture output and then present it
38 * Do we need to use an OutputTrap to capture output and then present it
38 to a user if startup fails?
39 to a user if startup fails?
39 4. Do we want the location of the config file(s) to be independent of the
40 * Do we want the location of the config file(s) to be independent of the
40 ipython/runtime dir or coupled to it. In other words, can the user select
41 ipython/runtime dir or coupled to it. In other words, can the user select
41 a config file that is outside their runtime/ipython dir. One model is
42 a config file that is outside their runtime/ipython dir. One model is
42 that we could have a very strict model of IPYTHONDIR=runtimed dir=
43 that we could have a very strict model of IPYTHONDIR=runtimed dir=
43 dir used for all config.
44 dir used for all config.
45 * Do we install default config files or not?
44 """
46 """
45
47
46 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
47 # Copyright (C) 2008-2009 The IPython Development Team
49 # Copyright (C) 2008-2009 The IPython Development Team
48 #
50 #
49 # Distributed under the terms of the BSD License. The full license is in
51 # Distributed under the terms of the BSD License. The full license is in
50 # the file COPYING, distributed as part of this software.
52 # the file COPYING, distributed as part of this software.
51 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
52
54
53 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
54 # Imports
56 # Imports
55 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
56
58
57 import sys
59 import sys
58 from copy import deepcopy
60 from copy import deepcopy
59 from IPython.utils.ipstruct import Struct
61 from IPython.utils.ipstruct import Struct
60
62
61 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
62 # Classes and functions
64 # Classes and functions
63 #-----------------------------------------------------------------------------
65 #-----------------------------------------------------------------------------
64
66
65
67
66 class ApplicationError(Exception):
68 class ApplicationError(Exception):
67 pass
69 pass
68
70
69
71
70 class Application(object):
72 class Application(object):
71
73
72 runtime_dirs = []
74 runtime_dirs = []
73 default_config = Struct()
75 default_config = Struct()
74 runtime_dir = ''
76 runtime_dir = ''
75 config_file = ''
77 config_file = ''
76 name = ''
78 name = ''
77
79
78 def __init__(self):
80 def __init__(self):
79 pass
81 pass
80
82
81 def find_runtime_dir(self):
83 def start(self):
84 """Start the application."""
85 self.attempt(self.create_command_line_config)
86 self.attempt(self.find_runtime_dirs)
87 self.attempt(self.create_runtime_dirs)
88 self.attempt(self.find_config_files)
89 self.attempt(self.create_file_configs)
90 self.attempt(self.merge_configs)
91 self.attempt(self.construct)
92 self.attempt(self.start_logging)
93 self.attempt(self.start_app)
94
95 #-------------------------------------------------------------------------
96 # Various stages of Application creation
97 #-------------------------------------------------------------------------
98
99 def create_command_line_config(self):
100 """Read the command line args and return its config object."""
101 self.command_line_config = Struct()
102
103 def find_runtime_dirs(self):
82 """Find the runtime directory for this application.
104 """Find the runtime directory for this application.
83
105
84 This should set self.runtime_dir.
106 This should set self.runtime_dir.
85 """
107 """
86 pass
108 pass
87
109
88 def create_runtime_dirs(self):
110 def create_runtime_dirs(self):
89 """Create the runtime dirs if they dont exist."""
111 """Create the runtime dirs if they don't exist."""
90 pass
112 pass
91
113
92 def find_config_file(self):
114 def find_config_files(self):
93 """Find the config file for this application."""
115 """Find the config file for this application."""
94 pass
116 pass
95
117
96 def create_config(self):
118 def create_file_configs(self):
97 self.config = deepcopy(self.default_config)
119 self.file_configs = [Struct()]
98
99 self.pre_file_config()
100 self.file_config = self.create_file_config()
101 self.post_file_config()
102
103 self.pre_command_line_config()
104 self.command_line_config = create_command_line_config()
105 self.post_command_line_config()
106
120
107 master_config = self.merge_configs(config, file_config, cl_config)
121 def merge_configs(self):
108 self.master_config = master_config
122 config = Struct()
109 return master_config
123 all_configs = self.file_configs + self.command_line_config
110
124 for c in all_configs:
111 def pre_file_config(self):
125 config.update(c)
112 pass
126 self.master_config = config
113
114 def create_file_config(self):
115 """Read the config file and return its config object."""
116 return Struct()
117
118 def post_file_config(self):
119 pass
120
121 def pre_command_line_config(self):
122 pass
123
124 def create_command_line_config(self):
125 """Read the command line args and return its config object."""
126 return Struct()
127
128 def post_command_line_config(self):
129 pass
130
131 def merge_configs(self, config, file_config, cl_config):
132 config.update(file_config)
133 config.update(cl_config)
134 return config
135
136 def start(self):
137 """Start the application."""
138 self.attempt(self.find_runtime_dir)
139 self.attempt(self.find_runtime_dir)
140 self.attempt(self.create_runtime_dirs)
141 self.attempt(self.find_config_file)
142 self.attempt(self.create_config)
143 self.attempt(self.construct)
144 self.attempt(self.start_logging)
145 self.attempt(self.start_app)
146
127
147 def construct(self, config):
128 def construct(self, config):
148 """Construct the main components that make up this app."""
129 """Construct the main components that make up this app."""
149 pass
130 pass
150
131
151 def start_logging(self):
132 def start_logging(self):
152 """Start logging, if needed, at the last possible moment."""
133 """Start logging, if needed, at the last possible moment."""
153 pass
134 pass
154
135
155 def start_app(self):
136 def start_app(self):
156 """Actually start the app."""
137 """Actually start the app."""
157 pass
138 pass
158
139
140 #-------------------------------------------------------------------------
141 # Utility methods
142 #-------------------------------------------------------------------------
143
159 def abort(self):
144 def abort(self):
160 """Abort the starting of the application."""
145 """Abort the starting of the application."""
161 print "Aborting application: ", self.name
146 print "Aborting application: ", self.name
162 sys.exit(1)
147 sys.exit(1)
163
148
164 def attempt(self, func):
149 def attempt(self, func):
165 try:
150 try:
166 func()
151 func()
167 except:
152 except:
168 self.handle_error()
153 self.handle_error()
169 self.abort()
154 self.abort()
170
155
171 def handle_error(self):
156 def handle_error(self):
172 print "I am dying!"
157 print "I am dying!"
173
158
174 No newline at end of file
159
General Comments 0
You need to be logged in to leave comments. Login now