def gen_test_spec_completion(prefix, parsed_args): spec = prefix.split(".") assert len(spec) > 0 if len(spec) == 1: yield from argcomplete_top_package(spec[0], parsed_args.top_level_directory) yield from argcomplete_top_module(spec[0], parsed_args.top_level_directory, parsed_args.pattern) else: test_spec = spec[:-1] rest = spec[-1] LOGGER.debug("TEST SPEC: %s", test_spec) try: tst, obj = get_test_spec_type(test_spec, parsed_args.top_level_directory) except: warn("failed to load test spec {!r} (prefix={!r})" .format(pyname_join(test_spec), prefix)) else: if tst is TestSpecType.package: yield from argcomplete_modules(obj, parsed_args.pattern, rest) elif tst is TestSpecType.module: yield from argcomplete_test_cases(obj, rest) elif tst is TestSpecType.test_case: yield from argcomplete_test_methods(obj, rest) elif tst is TestSpecType.test_method: pass # nothing to complete else: raise RuntimeError("unsupported test spec type: {}" .format(tst))
def argcomplete_test_methods(test_case, prefix): for test_method in collect_test_names(test_case): name = test_method.__name__ if name.startswith(prefix): yield pyname_join((test_case.__module__, test_case.__name__, name))
def rec(test_suite): for t in test_suite: if isinstance(t, unittest.TestSuite): yield from rec(t._tests) elif isinstance(t, unittest.TestCase): yield pyname_join((t.__module__, t.__class__.__name__, t._testMethodName)) else: raise RuntimeError("do not know what to do with {!r}".format(t))
def build_test_name(test_module, test_case=None, test_method=None): l = [test_module] if test_case is not None: l.append(test_case) if test_method is not None: l.append(test_method) def transform(x): if hasattr(x, "__name__"): return x.__name__ else: return x return pyname_join(map(transform, l))
def argcomplete_modules(package, pattern, prefix): directory = os.path.dirname(package.__file__) for _, name, ispkg in pkgutil.iter_modules(path=[directory]): if not name.startswith(prefix): continue if ispkg or fnmatch(name+".py", pattern): fullname = pyname_join((package.__name__, name)) try: import_module(fullname) except unittest.SkipTest: pass except: warn("failed to load module {!r}".format(fullname)) else: yield fullname
def get_test_spec_last_pkg(test_spec): last_pkg = None for part in test_spec.split("."): try: obj = import_module(part) except ImportError: break else: if is_pkg(obj): if last_pkg is None: last_pkg = part else: last_pkg = pyname_join((last_pkg, part)) else: break return last_pkg
def argcomplete_test_cases(module, prefix): for test_case in collect_test_cases(module): name = test_case.__name__ if name.startswith(prefix): yield pyname_join((module.__name__, name))
def get_test_spec_type(test_spec, top_level_directory): _check_top_level_directory(top_level_directory) if not test_spec: raise ValueError("empty test spec") if isinstance(test_spec, str): spec = test_spec.split(".") elif isinstance(test_spec, (list, tuple)): spec = test_spec test_spec = pyname_join(spec) else: raise TypeError("must be a str, list or tuple, not {!r}" .format(type(test_spec).__name__)) assert len(spec) > 0 mod = None first_import_err = None for i in range(len(spec)-1, -1, -1): name_to_import = pyname_join(spec[:i+1]) try: mod = import_module(name_to_import) except unittest.SkipTest as e: return (TestSpecType.skipped, SkippedTestSpec(name_to_import, str(e))) skipped = True break except ImportError as e: if first_import_err is None: first_import_err = e pass else: break if mod is None: # It happens when we failed to import the first package/module # of the test spec. assert first_import_err is not None raise first_import_err modpath = os.path.realpath(mod.__file__) moddir = os.path.dirname(modpath) if moddir != top_level_directory \ and not issubdir(moddir, top_level_directory): raise InvalidTestSpecError( test_spec, "package or module '{modname}' (from '{moddir}'), " "refers outside of your top level directory '{top_level_dir}'" .format(modname=mod.__name__, moddir=moddir, top_level_dir=top_level_directory, )) mods = spec[:i+1] attrs = spec[i+1:] if not attrs: if is_pkg(mod): # Package return (TestSpecType.package, mod) else: # module return (TestSpecType.module, mod) else: obj = mod for i in range(len(attrs)): attr = attrs[i] try: obj = getattr(obj, attr) except AttributeError as e: if is_pkg(obj): # Normally we stop importing package, sub-packages and # modules when we reach the TestCase class. If there # is an error when importing the module we stop earlier # and the error shows up again here. import_module(pyname_join((obj.__name__, attr))) assert False, \ "an ImportError exception should have been raised" else: raise InvalidTestSpecError( test_spec, "cannot get attribute '{}' from '{}'" .format(attr, pyname_join(mods+attrs[:i]))) if is_test_case(obj): return (TestSpecType.test_case, obj) else: return (TestSpecType.test_method, obj)