98 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
from __future__ import absolute_import, division, print_function
 | 
						|
import py
 | 
						|
import pytest
 | 
						|
 | 
						|
# test for _argcomplete but not specific for any application
 | 
						|
 | 
						|
 | 
						|
def equal_with_bash(prefix, ffc, fc, out=None):
 | 
						|
    res = ffc(prefix)
 | 
						|
    res_bash = set(fc(prefix))
 | 
						|
    retval = set(res) == res_bash
 | 
						|
    if out:
 | 
						|
        out.write('equal_with_bash %s %s\n' % (retval, res))
 | 
						|
        if not retval:
 | 
						|
            out.write(' python - bash: %s\n' % (set(res) - res_bash))
 | 
						|
            out.write(' bash - python: %s\n' % (res_bash - set(res)))
 | 
						|
    return retval
 | 
						|
 | 
						|
# copied from argcomplete.completers as import from there
 | 
						|
# also pulls in argcomplete.__init__ which opens filedescriptor 9
 | 
						|
# this gives an IOError at the end of testrun
 | 
						|
 | 
						|
 | 
						|
def _wrapcall(*args, **kargs):
 | 
						|
    try:
 | 
						|
        if py.std.sys.version_info > (2, 7):
 | 
						|
            return py.std.subprocess.check_output(*args, **kargs).decode().splitlines()
 | 
						|
        if 'stdout' in kargs:
 | 
						|
            raise ValueError('stdout argument not allowed, it will be overridden.')
 | 
						|
        process = py.std.subprocess.Popen(
 | 
						|
            stdout=py.std.subprocess.PIPE, *args, **kargs)
 | 
						|
        output, unused_err = process.communicate()
 | 
						|
        retcode = process.poll()
 | 
						|
        if retcode:
 | 
						|
            cmd = kargs.get("args")
 | 
						|
            if cmd is None:
 | 
						|
                cmd = args[0]
 | 
						|
            raise py.std.subprocess.CalledProcessError(retcode, cmd)
 | 
						|
        return output.decode().splitlines()
 | 
						|
    except py.std.subprocess.CalledProcessError:
 | 
						|
        return []
 | 
						|
 | 
						|
 | 
						|
class FilesCompleter(object):
 | 
						|
    'File completer class, optionally takes a list of allowed extensions'
 | 
						|
 | 
						|
    def __init__(self, allowednames=(), directories=True):
 | 
						|
        # Fix if someone passes in a string instead of a list
 | 
						|
        if type(allowednames) is str:
 | 
						|
            allowednames = [allowednames]
 | 
						|
 | 
						|
        self.allowednames = [x.lstrip('*').lstrip('.') for x in allowednames]
 | 
						|
        self.directories = directories
 | 
						|
 | 
						|
    def __call__(self, prefix, **kwargs):
 | 
						|
        completion = []
 | 
						|
        if self.allowednames:
 | 
						|
            if self.directories:
 | 
						|
                files = _wrapcall(['bash', '-c',
 | 
						|
                                   "compgen -A directory -- '{p}'".format(p=prefix)])
 | 
						|
                completion += [f + '/' for f in files]
 | 
						|
            for x in self.allowednames:
 | 
						|
                completion += _wrapcall(['bash', '-c',
 | 
						|
                                         "compgen -A file -X '!*.{0}' -- '{p}'".format(x, p=prefix)])
 | 
						|
        else:
 | 
						|
            completion += _wrapcall(['bash', '-c',
 | 
						|
                                     "compgen -A file -- '{p}'".format(p=prefix)])
 | 
						|
 | 
						|
            anticomp = _wrapcall(['bash', '-c',
 | 
						|
                                  "compgen -A directory -- '{p}'".format(p=prefix)])
 | 
						|
 | 
						|
            completion = list(set(completion) - set(anticomp))
 | 
						|
 | 
						|
            if self.directories:
 | 
						|
                completion += [f + '/' for f in anticomp]
 | 
						|
        return completion
 | 
						|
 | 
						|
 | 
						|
class TestArgComplete(object):
 | 
						|
    @pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
 | 
						|
    def test_compare_with_compgen(self):
 | 
						|
        from _pytest._argcomplete import FastFilesCompleter
 | 
						|
        ffc = FastFilesCompleter()
 | 
						|
        fc = FilesCompleter()
 | 
						|
        for x in ['/', '/d', '/data', 'qqq', '']:
 | 
						|
            assert equal_with_bash(x, ffc, fc, out=py.std.sys.stdout)
 | 
						|
 | 
						|
    @pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
 | 
						|
    def test_remove_dir_prefix(self):
 | 
						|
        """this is not compatible with compgen but it is with bash itself:
 | 
						|
        ls /usr/<TAB>
 | 
						|
        """
 | 
						|
        from _pytest._argcomplete import FastFilesCompleter
 | 
						|
        ffc = FastFilesCompleter()
 | 
						|
        fc = FilesCompleter()
 | 
						|
        for x in '/usr/'.split():
 | 
						|
            assert not equal_with_bash(x, ffc, fc, out=py.std.sys.stdout)
 |