def main(): try: args, kythe_args, options = parse_args.parse_args(sys.argv[1:]) except utils.UsageError as e: print(str(e), file=sys.stderr) sys.exit(1) if options.timeout is not None: signal.alarm(options.timeout) try: ix = indexer.process_file(options, generate_callgraphs=True) except indexer.PytypeError as e: print(e.args[0], file=sys.stderr) if args.debug: traceback.print_exc() else: print("Run with --debug to see a traceback.") sys.exit(1) if args.debug: debug.show_index(ix) else: kythe_graph = kythe.generate_graph(ix, kythe_args) output.output_kythe_graph(kythe_graph)
def main(): try: args, kythe_args, options = parse_args.parse_args(sys.argv[1:]) except utils.UsageError as e: print(str(e), file=sys.stderr) sys.exit(1) node.SetCheckPreconditions(options.check_preconditions) if options.timeout is not None: signal.alarm(options.timeout) try: ix, _ = indexer.process_file(options, kythe_args=kythe_args, keep_pytype_data=args.debug) except indexer.PytypeError as e: print(e.args[0], file=sys.stderr) if args.debug: traceback.print_exc() else: print("Run with --debug to see a traceback.") sys.exit(1) if args.debug: debug.show_index(ix, keep_pytype_data=True) else: output.output_kythe_graph(ix)
def test_resolved_imports(self): # We need all imports to be valid for pytype code = """\ import foo import x.y import a.b as c from a import b from p import q as r """ stub = "class X: pass" with file_utils.Tempdir() as d: d.create_file("t.py", code) d.create_file("foo.pyi", stub) d.create_file("x/y.pyi", stub) d.create_file("a/b.pyi", stub) d.create_file("p/q.pyi", stub) options = config.Options([d["t.py"]]) options.tweak(pythonpath=[d.path], version=self.python_version) ix = indexer.process_file(options) self.assertDef(ix, "module::foo", "foo", "Import") self.assertDef(ix, "module::x.y", "x.y", "Import") self.assertDef(ix, "module::c", "c", "Import") self.assertDef(ix, "module::b", "b", "ImportFrom") self.assertDef(ix, "module::r", "r", "ImportFrom") self.assertEqual(ix.modules["module::foo"], "foo") self.assertEqual(ix.modules["module::x.y"], "x.y") self.assertEqual(ix.modules["module::b"], "a.b") self.assertEqual(ix.modules["module::c"], "a.b") self.assertEqual(ix.modules["module::r"], "p.q")
def test_remote(self): code = """ import foo def f(a, b): x = foo.X(a) y = foo.Y(a, b) z = y.bar() """ stub = """ class X: def __init__(a: str) -> None: ... class Y: def __init__(a: str, b: int) -> None: ... def bar() -> int: ... """ with file_utils.Tempdir() as d: d.create_file("t.py", code) d.create_file("foo.pyi", stub) options = config.Options.create(d["t.py"], pythonpath=d.path, version=self.python_version) ix = indexer.process_file(options, generate_callgraphs=True) fns = ix.function_map self.assertHasFunctions(fns, ["f"]) f = fns["module.f"] self.assertAttrsEqual(f.param_attrs, []) self.assertAttrsEqual(f.local_attrs, [("y", "foo.Y", "y.bar")]) self.assertCallsEqual(f.calls, [("X", [("a", "Param", "typing.Any")]), ("Y", [("a", "Param", "typing.Any"), ("b", "Param", "typing.Any")]), ("Y.bar", [])])
def index_code(self, code, **kwargs): """Generate references from a code string.""" args = {"version": self.python_version} args.update(kwargs) with file_utils.Tempdir() as d: d.create_file("t.py", code) options = config.Options.create(d["t.py"]) options.tweak(**args) return indexer.process_file(options, generate_callgraphs=True)
def test_source_text(self): # Don't try to read from the filesystem if we supply source_text code = textwrap.dedent(""" def f(x): return 42 """) options = config.Options(["/path/to/nonexistent/file.py"]) options.tweak(version=self.python_version) ix = indexer.process_file(options, source_text=code) self.assertDef(ix, "module.f", "f", "FunctionDef")
def generate_kythe(self, code, **kwargs): """Generate a kythe index from a code string.""" with file_utils.Tempdir() as d: d.create_file("t.py", code) options = config.Options([d["t.py"]]) options.tweak(pythonpath=[d.path], version=self.python_version) kythe_args = kythe.Args(corpus="corpus", root="root") ix = indexer.process_file(options, kythe_args=kythe_args) # Collect all the references from the kythe graph. kythe_index = [json.loads(x) for x in output.json_kythe_graph(ix)] return kythe_index
def index_code(self, code, **kwargs): """Generate references from a code string.""" keep_pytype_data = kwargs.pop("keep_pytype_data", False) args = {"version": self.python_version} args.update(kwargs) with file_utils.Tempdir() as d: d.create_file("t.py", code) options = config.Options([d["t.py"]]) options.tweak(**args) return indexer.process_file(options, keep_pytype_data=keep_pytype_data)
def main(): try: options = config.Options(sys.argv[1:]) except utils.UsageError as e: print(str(e), file=sys.stderr) sys.exit(1) node.SetCheckPreconditions(options.check_preconditions) if options.timeout is not None: signal.alarm(options.timeout) v = indexer.process_file(options) output.output_kythe_graph(v)
def test_kythe_args(self): code = textwrap.dedent(""" def f(x): return 42 """) with file_utils.Tempdir() as d: d.create_file("t.py", code) options = config.Options([d["t.py"]]) options.tweak(pythonpath=[d.path], version=self.python_version) kythe_args = kythe.Args(corpus="corpus", root="root") ix = indexer.process_file(options, kythe_args=kythe_args) # Collect all the references from the kythe graph. kythe_index = [json.loads(x) for x in output.json_kythe_graph(ix)] k = kythe_index[0]["source"] self.assertEqual(k["corpus"], "corpus") self.assertEqual(k["root"], "root")
def main(): try: args, kythe_args, options = parse_args.parse_args(sys.argv[1:]) except utils.UsageError as e: print(str(e), file=sys.stderr) sys.exit(1) node.SetCheckPreconditions(options.check_preconditions) if options.timeout is not None: signal.alarm(options.timeout) ix = indexer.process_file(options, kythe_args=kythe_args) if args.debug: debug.show_index(ix) else: output.output_kythe_graph(ix)
def index_code(self, code, return_ast=False, **kwargs): """Generate references from a code string.""" ast_factory = kwargs.pop("ast_factory", None) keep_pytype_data = kwargs.pop("keep_pytype_data", False) annotate_ast = kwargs.pop("annotate_ast", False) args = {"version": self.python_version} args.update(kwargs) with file_utils.Tempdir() as d: d.create_file("t.py", code) options = config.Options([d["t.py"]]) options.tweak(**args) ix, ast_root = indexer.process_file( options, keep_pytype_data=keep_pytype_data, ast_factory=ast_factory, annotate_ast=annotate_ast) if return_ast: return ix, ast_root else: return ix
def test_import_ref(self): # We need all imports to be valid for pytype code = """\ import foo x = foo.Bar """ stub = "class Bar: pass" with file_utils.Tempdir() as d: d.create_file("t.py", code) d.create_file("foo.pyi", stub) options = config.Options([d["t.py"]]) options.tweak(pythonpath=[d.path], version=self.python_version) ix = indexer.process_file(options) self.assertDef(ix, "module::foo", "foo", "Import") self.assertDef(ix, "module::x", "x", "Store") self.assertEqual(ix.modules["module::foo"], "foo") expected = [({ "name": "foo", "typ": "Name", "scope": "module", "location": (2, 4) }, { "name": "foo", "scope": "module" }), ({ "name": "foo.Bar", "typ": "Attribute", "scope": "module", "location": (2, 4) }, { "name": "Bar", "scope": "foo/module" })] for (ref, defn), (expected_ref, expected_defn) in zip(ix.links, expected): self.assertAttrs(ref, expected_ref) self.assertAttrs(defn, expected_defn)
def test_resolved_imports(self): # We need all imports to be valid for pytype code = """\ import f import x.y import a.b as c from a import b from p import q as r fx = f.X() cx = c.X() bx = b.X() rx = r.X() yx = x.y.X() """ stub = "class X: pass" with file_utils.Tempdir() as d: d.create_file("t.py", code) d.create_file("f.pyi", stub) d.create_file("x/y.pyi", stub) d.create_file("a/b.pyi", stub) d.create_file("p/q.pyi", stub) options = config.Options([d["t.py"]]) options.tweak(pythonpath=[d.path], version=self.python_version) ix = indexer.process_file(options) self.assertDef(ix, "module.f", "f", "Import") self.assertDef(ix, "module.x.y", "x.y", "Import") self.assertDef(ix, "module.c", "c", "Import") self.assertDef(ix, "module.b", "b", "ImportFrom") self.assertDef(ix, "module.r", "r", "ImportFrom") self.assertEqual(ix.modules["module.f"], "f") self.assertEqual(ix.modules["module.x.y"], "x.y") self.assertEqual(ix.modules["module.b"], "a.b") self.assertEqual(ix.modules["module.c"], "a.b") self.assertEqual(ix.modules["module.r"], "p.q") # Collect all the references from the kythe graph. kythe_index = [json.loads(x) for x in output.json_kythe_graph(ix)] refs = [ x for x in kythe_index if x.get("edge_kind") == "/kythe/edge/ref" ] # Extract the span of text and the target symbol for each reference. src = ix.source.text out = [] for r in refs: pos = r["source"]["signature"] start, end = pos[1:].split(":") start, end = int(start), int(end) text = src[start:end] out.append( (text, r["target"]["signature"], r["target"]["path"])) expected = { # Imports as declarations in the source file ("f", "module.f", "t.py"), ("c", "module.c", "t.py"), ("b", "module.b", "t.py"), # Class X in remote files ("X", "module.X", "f.py"), ("X", "module.X", "a/b.py"), ("X", "module.X", "x/y.py"), ("X", "module.X", "p/q.py"), # Imports as references to remote files ("r", "module.r", "t.py"), ("b", ":module:", "a/b.py"), ("c", ":module:", "a/b.py"), ("f", ":module:", "f.py"), ("r", ":module:", "p/q.py"), ("x.y", ":module:", "x/y.py"), # x.y as references to remote files ("x", ":module:", "x/__init__.py"), ("y", ":module:", "x/y.py"), } # Resolve filepaths within the tempdir. expected = [(ref, target, d[path]) for (ref, target, path) in expected] self.assertEqual(set(out), set(expected))
def index_code(code): """Generate references from a code string.""" with file_utils.Tempdir() as d: d.create_file("t.py", code) options = config.Options([d["t.py"]]) return indexer.process_file(options)