mirror of
https://github.com/certbot/certbot.git
synced 2026-07-28 00:35:50 +02:00
Added completer.py and tests for FileDisplay
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
"""Provides tab autocompletion when prompting users for a path."""
|
||||
import glob
|
||||
import readline
|
||||
|
||||
|
||||
class Completer(object):
|
||||
"""Provides tab autocompletion when prompting users for a path.
|
||||
|
||||
This class is meant to be used with readline to provide tab
|
||||
autocompletion for users entering paths. The complete method can
|
||||
be passed to readline.set_completer directly, however, this function
|
||||
works best as a context manager. For example:
|
||||
|
||||
with Completer():
|
||||
raw_input()
|
||||
|
||||
In this example, tab autocompletion will be available during
|
||||
the call to raw_input above, however, readline will be restored to
|
||||
its previous state when exiting the body of the with statement.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._completer = self._delims = self._iter = None
|
||||
|
||||
def complete(self, text, state):
|
||||
"""Provides path autocompletion for use with readline.
|
||||
|
||||
:param str text: text to offer completions for
|
||||
:param int state: which completion to return
|
||||
|
||||
:returns: possible completion for text or ``None`` if all
|
||||
completions have been returned
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
if state == 0:
|
||||
self._iter = glob.iglob(text + '*')
|
||||
return next(self._iter, None)
|
||||
|
||||
def __enter__(self):
|
||||
self._completer = readline.get_completer()
|
||||
self._delims = readline.get_completer_delims()
|
||||
|
||||
readline.set_completer(self.complete)
|
||||
readline.set_completer_delims(' \t\n;')
|
||||
readline.parse_and_bind('tab: complete')
|
||||
|
||||
def __exit__(self, unused_type, unused_value, unused_traceback):
|
||||
readline.set_completer_delims(self._delims)
|
||||
readline.set_completer(self._completer)
|
||||
@@ -0,0 +1,64 @@
|
||||
"""Test letsencrypt.display.completer."""
|
||||
import os
|
||||
import readline
|
||||
import shutil
|
||||
import string
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
|
||||
class CompleterTest(unittest.TestCase):
|
||||
"""Test letsencrypt.display.completer.Completer."""
|
||||
|
||||
def setUp(self):
|
||||
self.temp_dir = tempfile.mkdtemp()
|
||||
|
||||
# directories must end with os.sep for completer to
|
||||
# search inside the directory for possible completions
|
||||
if self.temp_dir[-1] != os.sep:
|
||||
self.temp_dir += os.sep
|
||||
|
||||
self.paths = []
|
||||
# create some files and directories in temp_dir
|
||||
for c in string.ascii_lowercase:
|
||||
path = os.path.join(self.temp_dir, c)
|
||||
self.paths.append(path)
|
||||
if ord(c) % 2:
|
||||
os.mkdir(path)
|
||||
else:
|
||||
with open(path, 'w'):
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.temp_dir)
|
||||
|
||||
def test_context_manager(self):
|
||||
from letsencrypt.display import completer
|
||||
|
||||
original_completer = readline.get_completer()
|
||||
original_delims = readline.get_completer_delims()
|
||||
|
||||
with completer.Completer():
|
||||
pass
|
||||
|
||||
self.assertEqual(readline.get_completer(), original_completer)
|
||||
self.assertEqual(readline.get_completer_delims(), original_delims)
|
||||
|
||||
def test_complete(self):
|
||||
from letsencrypt.display import completer
|
||||
|
||||
my_completer = completer.Completer()
|
||||
num_paths = len(self.paths)
|
||||
|
||||
for i in range(num_paths):
|
||||
completion = my_completer.complete(self.temp_dir, i)
|
||||
self.assertTrue(completion in self.paths)
|
||||
self.paths.remove(completion)
|
||||
|
||||
self.assertFalse(self.paths)
|
||||
completion = my_completer.complete(self.temp_dir, num_paths)
|
||||
self.assertEqual(completion, None)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main() # pragma: no cover
|
||||
Reference in New Issue
Block a user