def test_validate_bazel_deps_valid() -> None: result = validate_bazel_deps( py2_compatible=False, py3_compatible=True, imports=[ Import( module="dropbox.runfiles", location=SourceLocation(source_file=Path("foo.py"), lineno=5), is_from=False, ), Import( module="asyncio", location=SourceLocation(source_file=Path("foo.py"), lineno=6), is_from=False, ), Import( module="grpc.codes", location=SourceLocation(source_file=Path("foo.py"), lineno=7), is_from=False, ), ], primary_target="//target", provides_map={"dropbox.runfiles": "//dropbox/runfiles"}, prefix_provides_map={"grpc": "//pip/grpc"}, ) assert not result.unresolved_imports assert not result.unused_targets
def test_validate_bazel_deps_invalid_with_identifier() -> None: result = validate_bazel_deps( py2_compatible=False, py3_compatible=True, imports=[ Import( module="dropbox.runfiles.data_path", location=SourceLocation(source_file=Path("foo.py"), lineno=5), is_from=False, ), Import( module="asyncio", location=SourceLocation(source_file=Path("foo.py"), lineno=6), is_from=False, ), ], primary_target="//target", provides_map={"dropbox.runfiles": "//dropbox/runfiles"}, prefix_provides_map={}, ) assert [i.module for i in result.unresolved_imports ] == ["dropbox.runfiles.data_path"] assert result.unused_targets == {"//dropbox/runfiles"}
def main() -> None: parser = argparse.ArgumentParser() parser.add_argument("--src", action="append", help="a file to check the imports of") parser.add_argument( "--py3-compatible", action="store_true", help="source is py3 compatible" ) parser.add_argument( "--py2-compatible", action="store_true", help="source is py2 compatible" ) parser.add_argument( "--target-provides", action="append", help="Format target=module. Indicates that a target provides a module", ) parser.add_argument( "--target-provides-prefix", action="append", help="Format target=moduleprefix" ) parser.add_argument("--target", help="name of actual target") parser.add_argument("--pythonpath", help="pythonpath of bazel target") parser.add_argument( "--allow-unused-targets", action="store_true", help="Allow unused depndencies, useful when using additional_deps for automagically imported things", ) args = parser.parse_args() primary_target = args.target imports = [] # type: List[Import] for src in args.src: imports.extend( parse_imports( source_file=Path(src), py2_compatible=args.py2_compatible, py3_compatible=args.py3_compatible, pythonpath=args.pythonpath, ) ) result = validate_bazel_deps( py2_compatible=args.py2_compatible, py3_compatible=args.py3_compatible, imports=imports, primary_target=primary_target, provides_map=flatten_provides( primary_target, [_split_equal(t) for t in args.target_provides or []] ), prefix_provides_map=flatten_provides( primary_target, [_split_equal(t) for t in args.target_provides_prefix or []] ), ) if ( result.unresolved_imports or result.unused_targets and not args.allow_unused_targets ): # Force a newline so that the output stands out better, making it easier to # reads the logs from bazel output print("") print( "=========== import validation failures (target {})".format(primary_target) ) print("to run locally, try using:") print( "bazel build --aspects=build_tools/py/bazel_validation/import_validation.bzl%dbx_py_validate_imports --output_groups=py_import_validation_files {}".format( primary_target ) ) for i in result.unresolved_imports: print( " unresolved import ({}:{}): {}".format( i.location.source_file, i.location.lineno, i.module ) ) if not args.allow_unused_targets: for t in result.unused_targets: print(" unused dependency: {}".format(t)) print("") sys.exit(1)