##// END OF EJS Templates
catch up tests to recent changes...
MinRK -
Show More
@@ -1,164 +1,166 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 Tests for IPython.config.configurable
5 5
6 6 Authors:
7 7
8 8 * Brian Granger
9 9 * Fernando Perez (design help)
10 10 """
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Copyright (C) 2008-2010 The IPython Development Team
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 from unittest import TestCase
24 24
25 25 from IPython.config.configurable import (
26 26 Configurable,
27 27 SingletonConfigurable
28 28 )
29 29
30 30 from IPython.utils.traitlets import (
31 31 Int, Float, Str
32 32 )
33 33
34 34 from IPython.config.loader import Config
35 35
36 36
37 37 #-----------------------------------------------------------------------------
38 38 # Test cases
39 39 #-----------------------------------------------------------------------------
40 40
41 41
42 42 class MyConfigurable(Configurable):
43 43 a = Int(1, config=True, help="The integer a.")
44 44 b = Float(1.0, config=True, help="The integer b.")
45 45 c = Str('no config')
46 46
47 47
48 48 mc_help=u"""MyConfigurable options
49 49 ----------------------
50 MyConfigurable.a : Int [default: 1]
50 MyConfigurable.a : Int
51 Default: 1
51 52 The integer a.
52 MyConfigurable.b : Float [default: 1.0]
53 MyConfigurable.b : Float
54 Default: 1.0
53 55 The integer b."""
54 56
55 57 class Foo(Configurable):
56 58 a = Int(0, config=True, help="The integer a.")
57 59 b = Str('nope', config=True)
58 60
59 61
60 62 class Bar(Foo):
61 63 b = Str('gotit', config=False, help="The string b.")
62 64 c = Float(config=True, help="The string c.")
63 65
64 66
65 67 class TestConfigurable(TestCase):
66 68
67 69 def test_default(self):
68 70 c1 = Configurable()
69 71 c2 = Configurable(config=c1.config)
70 72 c3 = Configurable(config=c2.config)
71 73 self.assertEquals(c1.config, c2.config)
72 74 self.assertEquals(c2.config, c3.config)
73 75
74 76 def test_custom(self):
75 77 config = Config()
76 78 config.foo = 'foo'
77 79 config.bar = 'bar'
78 80 c1 = Configurable(config=config)
79 81 c2 = Configurable(config=c1.config)
80 82 c3 = Configurable(config=c2.config)
81 83 self.assertEquals(c1.config, config)
82 84 self.assertEquals(c2.config, config)
83 85 self.assertEquals(c3.config, config)
84 86 # Test that copies are not made
85 87 self.assert_(c1.config is config)
86 88 self.assert_(c2.config is config)
87 89 self.assert_(c3.config is config)
88 90 self.assert_(c1.config is c2.config)
89 91 self.assert_(c2.config is c3.config)
90 92
91 93 def test_inheritance(self):
92 94 config = Config()
93 95 config.MyConfigurable.a = 2
94 96 config.MyConfigurable.b = 2.0
95 97 c1 = MyConfigurable(config=config)
96 98 c2 = MyConfigurable(config=c1.config)
97 99 self.assertEquals(c1.a, config.MyConfigurable.a)
98 100 self.assertEquals(c1.b, config.MyConfigurable.b)
99 101 self.assertEquals(c2.a, config.MyConfigurable.a)
100 102 self.assertEquals(c2.b, config.MyConfigurable.b)
101 103
102 104 def test_parent(self):
103 105 config = Config()
104 106 config.Foo.a = 10
105 107 config.Foo.b = "wow"
106 108 config.Bar.b = 'later'
107 109 config.Bar.c = 100.0
108 110 f = Foo(config=config)
109 111 b = Bar(config=f.config)
110 112 self.assertEquals(f.a, 10)
111 113 self.assertEquals(f.b, 'wow')
112 114 self.assertEquals(b.b, 'gotit')
113 115 self.assertEquals(b.c, 100.0)
114 116
115 117 def test_override1(self):
116 118 config = Config()
117 119 config.MyConfigurable.a = 2
118 120 config.MyConfigurable.b = 2.0
119 121 c = MyConfigurable(a=3, config=config)
120 122 self.assertEquals(c.a, 3)
121 123 self.assertEquals(c.b, config.MyConfigurable.b)
122 124 self.assertEquals(c.c, 'no config')
123 125
124 126 def test_override2(self):
125 127 config = Config()
126 128 config.Foo.a = 1
127 129 config.Bar.b = 'or' # Up above b is config=False, so this won't do it.
128 130 config.Bar.c = 10.0
129 131 c = Bar(config=config)
130 132 self.assertEquals(c.a, config.Foo.a)
131 133 self.assertEquals(c.b, 'gotit')
132 134 self.assertEquals(c.c, config.Bar.c)
133 135 c = Bar(a=2, b='and', c=20.0, config=config)
134 136 self.assertEquals(c.a, 2)
135 137 self.assertEquals(c.b, 'and')
136 138 self.assertEquals(c.c, 20.0)
137 139
138 140 def test_help(self):
139 141 self.assertEquals(MyConfigurable.class_get_help(), mc_help)
140 142
141 143
142 144 class TestSingletonConfigurable(TestCase):
143 145
144 146 def test_instance(self):
145 147 from IPython.config.configurable import SingletonConfigurable
146 148 class Foo(SingletonConfigurable): pass
147 149 self.assertEquals(Foo.initialized(), False)
148 150 foo = Foo.instance()
149 151 self.assertEquals(Foo.initialized(), True)
150 152 self.assertEquals(foo, Foo.instance())
151 153 self.assertEquals(SingletonConfigurable._instance, None)
152 154
153 155 def test_inheritance(self):
154 156 class Bar(SingletonConfigurable): pass
155 157 class Bam(Bar): pass
156 158 self.assertEquals(Bar.initialized(), False)
157 159 self.assertEquals(Bam.initialized(), False)
158 160 bam = Bam.instance()
159 161 bam == Bar.instance()
160 162 self.assertEquals(Bar.initialized(), True)
161 163 self.assertEquals(Bam.initialized(), True)
162 164 self.assertEquals(bam, Bam._instance)
163 165 self.assertEquals(bam, Bar._instance)
164 166 self.assertEquals(SingletonConfigurable._instance, None)
@@ -1,280 +1,283 b''
1 1 """Generic testing tools that do NOT depend on Twisted.
2 2
3 3 In particular, this module exposes a set of top-level assert* functions that
4 4 can be used in place of nose.tools.assert* in method generators (the ones in
5 5 nose can not, at least as of nose 0.10.4).
6 6
7 7 Note: our testing package contains testing.util, which does depend on Twisted
8 8 and provides utilities for tests that manage Deferreds. All testing support
9 9 tools that only depend on nose, IPython or the standard library should go here
10 10 instead.
11 11
12 12
13 13 Authors
14 14 -------
15 15 - Fernando Perez <Fernando.Perez@berkeley.edu>
16 16 """
17 17
18 18 from __future__ import absolute_import
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Copyright (C) 2009 The IPython Development Team
22 22 #
23 23 # Distributed under the terms of the BSD License. The full license is in
24 24 # the file COPYING, distributed as part of this software.
25 25 #-----------------------------------------------------------------------------
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Imports
29 29 #-----------------------------------------------------------------------------
30 30
31 31 import os
32 32 import re
33 33 import sys
34 34
35 35 try:
36 36 # These tools are used by parts of the runtime, so we make the nose
37 37 # dependency optional at this point. Nose is a hard dependency to run the
38 38 # test suite, but NOT to use ipython itself.
39 39 import nose.tools as nt
40 40 has_nose = True
41 41 except ImportError:
42 42 has_nose = False
43 43
44 44 from IPython.config.loader import Config
45 45 from IPython.utils.process import find_cmd, getoutputerror
46 46 from IPython.utils.text import list_strings
47 47 from IPython.utils.io import temp_pyfile
48 48
49 49 from . import decorators as dec
50 50 from . import skipdoctest
51 51
52 52 #-----------------------------------------------------------------------------
53 53 # Globals
54 54 #-----------------------------------------------------------------------------
55 55
56 56 # Make a bunch of nose.tools assert wrappers that can be used in test
57 57 # generators. This will expose an assert* function for each one in nose.tools.
58 58
59 59 _tpl = """
60 60 def %(name)s(*a,**kw):
61 61 return nt.%(name)s(*a,**kw)
62 62 """
63 63
64 64 if has_nose:
65 65 for _x in [a for a in dir(nt) if a.startswith('assert')]:
66 66 exec _tpl % dict(name=_x)
67 67
68 68 #-----------------------------------------------------------------------------
69 69 # Functions and classes
70 70 #-----------------------------------------------------------------------------
71 71
72 72 # The docstring for full_path doctests differently on win32 (different path
73 73 # separator) so just skip the doctest there. The example remains informative.
74 74 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
75 75
76 76 @doctest_deco
77 77 def full_path(startPath,files):
78 78 """Make full paths for all the listed files, based on startPath.
79 79
80 80 Only the base part of startPath is kept, since this routine is typically
81 81 used with a script's __file__ variable as startPath. The base of startPath
82 82 is then prepended to all the listed files, forming the output list.
83 83
84 84 Parameters
85 85 ----------
86 86 startPath : string
87 87 Initial path to use as the base for the results. This path is split
88 88 using os.path.split() and only its first component is kept.
89 89
90 90 files : string or list
91 91 One or more files.
92 92
93 93 Examples
94 94 --------
95 95
96 96 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
97 97 ['/foo/a.txt', '/foo/b.txt']
98 98
99 99 >>> full_path('/foo',['a.txt','b.txt'])
100 100 ['/a.txt', '/b.txt']
101 101
102 102 If a single file is given, the output is still a list:
103 103 >>> full_path('/foo','a.txt')
104 104 ['/a.txt']
105 105 """
106 106
107 107 files = list_strings(files)
108 108 base = os.path.split(startPath)[0]
109 109 return [ os.path.join(base,f) for f in files ]
110 110
111 111
112 112 def parse_test_output(txt):
113 113 """Parse the output of a test run and return errors, failures.
114 114
115 115 Parameters
116 116 ----------
117 117 txt : str
118 118 Text output of a test run, assumed to contain a line of one of the
119 119 following forms::
120 120 'FAILED (errors=1)'
121 121 'FAILED (failures=1)'
122 122 'FAILED (errors=1, failures=1)'
123 123
124 124 Returns
125 125 -------
126 126 nerr, nfail: number of errors and failures.
127 127 """
128 128
129 129 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
130 130 if err_m:
131 131 nerr = int(err_m.group(1))
132 132 nfail = 0
133 133 return nerr, nfail
134 134
135 135 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
136 136 if fail_m:
137 137 nerr = 0
138 138 nfail = int(fail_m.group(1))
139 139 return nerr, nfail
140 140
141 141 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
142 142 re.MULTILINE)
143 143 if both_m:
144 144 nerr = int(both_m.group(1))
145 145 nfail = int(both_m.group(2))
146 146 return nerr, nfail
147 147
148 148 # If the input didn't match any of these forms, assume no error/failures
149 149 return 0, 0
150 150
151 151
152 152 # So nose doesn't think this is a test
153 153 parse_test_output.__test__ = False
154 154
155 155
156 156 def default_argv():
157 157 """Return a valid default argv for creating testing instances of ipython"""
158 158
159 159 return ['--quick', # so no config file is loaded
160 160 # Other defaults to minimize side effects on stdout
161 161 'colors=NoColor', '--no-term-title','--no-banner',
162 162 'autocall=0']
163 163
164 164
165 165 def default_config():
166 166 """Return a config object with good defaults for testing."""
167 167 config = Config()
168 168 config.TerminalInteractiveShell.colors = 'NoColor'
169 169 config.TerminalTerminalInteractiveShell.term_title = False,
170 170 config.TerminalInteractiveShell.autocall = 0
171 171 config.HistoryManager.hist_file = u'test_hist.sqlite'
172 172 config.HistoryManager.db_cache_size = 10000
173 173 return config
174 174
175 175
176 176 def ipexec(fname, options=None):
177 177 """Utility to call 'ipython filename'.
178 178
179 179 Starts IPython witha minimal and safe configuration to make startup as fast
180 180 as possible.
181 181
182 182 Note that this starts IPython in a subprocess!
183 183
184 184 Parameters
185 185 ----------
186 186 fname : str
187 187 Name of file to be executed (should have .py or .ipy extension).
188 188
189 189 options : optional, list
190 190 Extra command-line flags to be passed to IPython.
191 191
192 192 Returns
193 193 -------
194 194 (stdout, stderr) of ipython subprocess.
195 195 """
196 196 if options is None: options = []
197 197
198 198 # For these subprocess calls, eliminate all prompt printing so we only see
199 199 # output from script execution
200 prompt_opts = ['pi1=""', 'pi2=""', 'po=""']
200 prompt_opts = [ 'InteractiveShell.prompt_in1=""',
201 'InteractiveShell.prompt_in2=""',
202 'InteractiveShell.prompt_out=""'
203 ]
201 204 cmdargs = ' '.join(default_argv() + prompt_opts + options)
202 205
203 206 _ip = get_ipython()
204 207 test_dir = os.path.dirname(__file__)
205 208
206 209 ipython_cmd = find_cmd('ipython')
207 210 # Absolute path for filename
208 211 full_fname = os.path.join(test_dir, fname)
209 212 full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname)
210 213 #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg
211 214 return getoutputerror(full_cmd)
212 215
213 216
214 217 def ipexec_validate(fname, expected_out, expected_err='',
215 218 options=None):
216 219 """Utility to call 'ipython filename' and validate output/error.
217 220
218 221 This function raises an AssertionError if the validation fails.
219 222
220 223 Note that this starts IPython in a subprocess!
221 224
222 225 Parameters
223 226 ----------
224 227 fname : str
225 228 Name of the file to be executed (should have .py or .ipy extension).
226 229
227 230 expected_out : str
228 231 Expected stdout of the process.
229 232
230 233 expected_err : optional, str
231 234 Expected stderr of the process.
232 235
233 236 options : optional, list
234 237 Extra command-line flags to be passed to IPython.
235 238
236 239 Returns
237 240 -------
238 241 None
239 242 """
240 243
241 244 import nose.tools as nt
242 245
243 246 out, err = ipexec(fname)
244 247 #print 'OUT', out # dbg
245 248 #print 'ERR', err # dbg
246 249 # If there are any errors, we must check those befor stdout, as they may be
247 250 # more informative than simply having an empty stdout.
248 251 if err:
249 252 if expected_err:
250 253 nt.assert_equals(err.strip(), expected_err.strip())
251 254 else:
252 255 raise ValueError('Running file %r produced error: %r' %
253 256 (fname, err))
254 257 # If no errors or output on stderr was expected, match stdout
255 258 nt.assert_equals(out.strip(), expected_out.strip())
256 259
257 260
258 261 class TempFileMixin(object):
259 262 """Utility class to create temporary Python/IPython files.
260 263
261 264 Meant as a mixin class for test cases."""
262 265
263 266 def mktmp(self, src, ext='.py'):
264 267 """Make a valid python temp file."""
265 268 fname, f = temp_pyfile(src, ext)
266 269 self.tmpfile = f
267 270 self.fname = fname
268 271
269 272 def tearDown(self):
270 273 if hasattr(self, 'tmpfile'):
271 274 # If the tmpfile wasn't made because of skipped tests, like in
272 275 # win32, there's nothing to cleanup.
273 276 self.tmpfile.close()
274 277 try:
275 278 os.unlink(self.fname)
276 279 except:
277 280 # On Windows, even though we close the file, we still can't
278 281 # delete it. I have no clue why
279 282 pass
280 283
General Comments 0
You need to be logged in to leave comments. Login now