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