##// 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
@@ -30,17 +30,19 b' There are number of ways in which these directories are used:'
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 #-----------------------------------------------------------------------------
@@ -78,7 +80,27 b' class Application(object):'
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.
@@ -86,63 +108,22 b' class Application(object):'
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."""
@@ -156,6 +137,10 b' class Application(object):'
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
General Comments 0
You need to be logged in to leave comments. Login now