1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
5 Test cases for twisted.python.zshcomp
9 from cStringIO import StringIO
11 from twisted.trial import unittest
12 from twisted.python import zshcomp, usage
16 class ZshcompTestCase(unittest.TestCase):
18 Tests for the zsh completion function builder in twisted/python/zshcomp.py
20 def test_buildAll(self):
22 Build all the completion functions for twisted commands - no errors
25 dirname = self.mktemp()
27 skippedCmds = [x[0] for x in zshcomp.makeCompFunctionFiles(dirname)]
29 # verify a zsh function was created for each twisted command
30 for info in zshcomp.generateFor:
31 if info[0] in skippedCmds:
33 funcPath = os.path.join(dirname, '_' + info[0])
34 self.assertTrue(os.path.exists(funcPath))
37 def test_accumulateMetadata(self):
39 The zsh_* variables you can place on Options classes are
42 opts = FighterAceExtendedOptions()
43 ag = zshcomp.ArgumentsGenerator('dummy_cmd', opts, 'dummy_value')
45 altArgDescr = FighterAceOptions.zsh_altArgDescr.copy()
46 altArgDescr.update(FighterAceExtendedOptions.zsh_altArgDescr)
48 actionDescr = FighterAceOptions.zsh_actionDescr.copy()
49 actionDescr.update(FighterAceExtendedOptions.zsh_actionDescr)
51 self.assertEqual(ag.altArgDescr, altArgDescr)
52 self.assertEqual(ag.actionDescr, actionDescr)
53 self.assertEqual(ag.multiUse, FighterAceOptions.zsh_multiUse)
54 self.assertEqual(ag.mutuallyExclusive,
55 FighterAceOptions.zsh_mutuallyExclusive)
56 self.assertEqual(ag.actions, FighterAceOptions.zsh_actions)
57 self.assertEqual(ag.extras, FighterAceOptions.zsh_extras)
60 def test_accumulateAdditionalOptions(self):
62 We pick up options that are only defined by having an
63 appropriately named method on your Options class,
64 e.g. def opt_foo(self, foo)
66 opts = FighterAceExtendedOptions()
67 ag = zshcomp.ArgumentsGenerator('dummy_cmd', opts, 'dummy_value')
69 self.assertIn('nocrash', ag.optFlags_d)
70 self.assertIn('nocrash', ag.optAll_d)
72 self.assertIn('difficulty', ag.optParams_d)
73 self.assertIn('difficulty', ag.optAll_d)
76 def test_verifyZshNames(self):
78 Using a parameter/flag name that doesn't exist
81 class TmpOptions(FighterAceExtendedOptions):
82 zsh_actions = {'detaill' : 'foo'} # Note typo of detail
85 self.assertRaises(ValueError, zshcomp.ArgumentsGenerator,
86 'dummy_cmd', opts, 'dummy_value')
89 def test_zshCode(self):
91 Generate a completion function, and test the textual output
92 against a known correct output
97 b = zshcomp.Builder(cmd_name, opts, f)
100 self.assertEqual(f.read(), testOutput1)
103 def test_skipBuild(self):
105 makeCompFunctionFiles skips building for commands whos
106 script module cannot be imported
108 generateFor = [('test_cmd', 'no.way.your.gonna.import.this', 'Foo')]
109 skips = zshcomp.makeCompFunctionFiles('out_dir', generateFor, {})
110 # no exceptions should be raised. hooray.
111 self.assertEqual(len(skips), 1)
112 self.assertEqual(len(skips[0]), 2)
113 self.assertEqual(skips[0][0], 'test_cmd')
114 self.assertTrue(isinstance(skips[0][1], ImportError))
118 class FighterAceOptions(usage.Options):
120 Command-line options for an imaginary "Fighter Ace" game
122 optFlags = [['fokker', 'f',
123 'Select the Fokker Dr.I as your dogfighter aircraft'],
125 'Select the Albatros D-III as your dogfighter aircraft'],
127 'Select the SPAD S.VII as your dogfighter aircraft'],
129 'Select the Bristol Scout as your dogfighter aircraft'],
131 'Enable secret Twisted physics engine'],
133 'Enable a small chance that your machine guns will jam!'],
135 'Verbose logging (may be specified more than once)'],
138 optParameters = [['pilot-name', None, "What's your name, Ace?",
139 'Manfred von Richthofen'],
141 'Select the level of rendering detail (1-5)', '3'],
144 zsh_altArgDescr = {'physics' : 'Twisted-Physics',
145 'detail' : 'Rendering detail level'}
146 zsh_actionDescr = {'detail' : 'Pick your detail'}
147 zsh_multiUse = ['verbose']
148 zsh_mutuallyExclusive = [['fokker', 'albatros', 'spad', 'bristol']]
149 zsh_actions = {'detail' : '(1 2 3 4 5)'}
150 zsh_extras = [':saved game file to load:_files']
154 class FighterAceExtendedOptions(FighterAceOptions):
156 Extend the options and zsh metadata provided by FighterAceOptions. zshcomp
157 must accumulate options and metadata from all classes in the hiearchy so
158 this is important for testing
160 optFlags = [['no-stalls', None,
161 'Turn off the ability to stall your aircraft']]
162 optParameters = [['reality-level', None,
163 'Select the level of physics reality (1-5)', '5']]
165 zsh_altArgDescr = {'no-stalls' : 'Can\'t stall your plane'}
166 zsh_actionDescr = {'reality-level' : 'Physics reality level'}
169 def opt_nocrash(self):
170 """Select that you can't crash your plane"""
173 def opt_difficulty(self, difficulty):
174 """How tough are you? (1-10)"""
178 def _accuracyAction():
183 class SillyOptions(usage.Options):
185 Command-line options for a "silly" program
187 optFlags = [['color', 'c', 'Turn on color output'],
188 ['gray', 'g', 'Turn on gray-scale output'],
190 'Verbose logging (may be specified more than once)'],
193 optParameters = [['optimization', None,
194 'Select the level of optimization (1-5)', '5'],
196 'Select the level of accuracy (1-3)', '3'],
200 zsh_altArgDescr = {'color' : 'Color on',
201 'optimization' : 'Optimization level'}
202 zsh_actionDescr = {'optimization' : 'Optimization?',
203 'accuracy' : 'Accuracy?'}
204 zsh_multiUse = ['verbose']
205 zsh_mutuallyExclusive = [['color', 'gray']]
206 zsh_actions = {'optimization' : '(1 2 3 4 5)',
207 'accuracy' : _accuracyAction}
208 zsh_extras = [':output file:_files']
212 testOutput1 = """#compdef testprog
213 _arguments -s -A "-*" \\
214 ':output file:_files' \\
215 '(--accuracy)-a[3]:Accuracy?:(1 2 3)' \\
216 '(-a)--accuracy=[3]:Accuracy?:(1 2 3)' \\
217 '(--gray -g --color)-c[Color on]' \\
218 '(--gray -g -c)--color[Color on]' \\
219 '(--color -c --gray)-g[Turn on gray-scale output]' \\
220 '(--color -c -g)--gray[Turn on gray-scale output]' \\
221 '--help[Display this help and exit.]' \\
222 '--optimization=[Optimization level]:Optimization?:(1 2 3 4 5)' \\
223 '*-v[Verbose logging (may be specified more than once)]' \\
224 '*--verbose[Verbose logging (may be specified more than once)]' \\
225 '--version[Display Twisted version and exit.]' \\