def test_get_offset_multibyte(self): # With single-byte characters src = source.Code(""" # coding=utf-8 line1 # a line2 """, [], _FakeTrace, "") self.assertEqual(src.get_offset(source.Location(4, 3)), 41) # With a multibyte character the byte offset should change src = source.Code(""" # coding=utf-8 line1 # ツ line2 """, [], _FakeTrace, "") self.assertEqual(src.get_offset(source.Location(4, 3)), 43)
def trace(src, options=None): """Generates type traces for the given source code. Args: src: The source text. options: A pytype.config.Options object that can be used to specify options such as the target Python version. Returns: A source.Code object. """ errorlog = errors.ErrorLog() options = options or config.Options.create() loader = load_pytd.create_loader(options) vm = analyze.CallTracer( errorlog=errorlog, options=options, generate_unknowns=options.protocols, loader=loader) pytd_module, _ = analyze.infer_types( src=src, filename=options.input, errorlog=errorlog, options=options, loader=loader, tracer_vm=vm) raw_traces = [] for op, symbol, data in vm.opcode_traces: raw_traces.append( (op, symbol, tuple(_to_pytd(d, loader, pytd_module) for d in data))) return source.Code(src, raw_traces, TypeTrace, options.input)
def test_basic(self): raw_traces = [(_FakeOpcode("op1", 1), "symbol1", (["data1"], )), (_FakeOpcode("op2", 4), "symbol2", (["data2"], )), (_FakeOpcode("op3", 1), "symbol3", (["data3"], ))] src = source.Code("text", raw_traces, _FakeTrace, "name") self.assertEqual(src.text, "text") self.assertEqual(src.filename, "name") six.assertCountEqual(self, src.traces, [1, 4]) self.assertEqual(src.traces[1], [("op1", "symbol1", (["data1"], )), ("op3", "symbol3", (["data3"], ))]) self.assertEqual(src.traces[4], [("op2", "symbol2", (["data2"], ))]) for trace in sum(src.traces.values(), []): self.assertIsInstance(trace, _FakeTrace)
def test_one_line(self): src = source.Code("foo.bar", [], _FakeTrace, "") self.assertEqual( src.get_attr_location("foo.bar", source.Location(1, 0)), (source.Location(1, 4), 3))
def test_display_traces(self): raw_traces = [(_FakeOpcode("op1", 1), "symbol1", (["data1"], )), (_FakeOpcode("op2", 3), "symbol2", (None, ))] src = source.Code("line1\nline2\nline3", raw_traces, _FakeTrace, "") src.display_traces() # smoke test
def test_next_non_comment_line(self): src = source.Code("line1\n# line2\nline3", [], _FakeTrace, "") self.assertEqual(src.next_non_comment_line(1), 3) self.assertIsNone(src.next_non_comment_line(3))
def test_find_first_text(self): src = source.Code("line1\nline2\nline3", [], _FakeTrace, "") self.assertEqual(src.find_first_text(2, 5, "line"), source.Location(2, 0)) self.assertIsNone(src.find_first_text(2, 5, "duck"))
def test_get_closest_line_range(self): src = source.Code("line1\nline2\nline3", [], _FakeTrace, "") six.assertCountEqual(self, src.get_closest_line_range(1, 3), [1, 2]) six.assertCountEqual(self, src.get_closest_line_range(2, 5), [2, 3])
def test_line(self): src = source.Code("line1\nline2", [], _FakeTrace, "") self.assertEqual(src.line(2), "line2")
def test_get_offset(self): src = source.Code("line1\nline2", [], _FakeTrace, "") self.assertEqual(src.get_offset(source.Location(2, 3)), 9)
def test_not_found(self): src = source.Code("foo.bar", [], _FakeTrace, "") self.assertEqual( src.get_attr_location("foo.baz", source.Location(1, 0)), (source.Location(1, 0), 7))
def test_dot_attr(self): src = source.Code("foo\n.bar", [], _FakeTrace, "") self.assertEqual( src.get_attr_location("foo.bar", source.Location(1, 0)), (source.Location(2, 1), 3))
def process_file(options, source_text=None, generate_callgraphs=False, preserve_pytype_vm=False): """Process a single file and return cross references. Args: options: A dictionary of pytype options. source_text: Optional text of the file; will be read from the file pointed to by options.input if not supplied. generate_callgraphs: Collect call graph information preserve_pytype_vm: Preserve the pytype vm in the indexer Returns: The Indexer object used for indexing. Raises: PytypeError if pytype fails. """ errorlog = errors.ErrorLog() loader = load_pytd.create_loader(options) src = source_text or io.read_source_file(options.input) vm = analyze.CallTracer(errorlog=errorlog, options=options, generate_unknowns=options.protocols, store_all_calls=True, loader=loader) with io.wrap_pytype_exceptions(PytypeError, filename=options.input): pytd_module, _ = analyze.infer_types(src=src, filename=options.input, errorlog=errorlog, options=options, loader=loader, tracer_vm=vm) major, minor = options.python_version if major == 2: # python2.7 is the only supported py2 version. ast_root_node = ast27.parse(src, options.input) ast = ast27 else: ast_root_node = ast3.parse(src, options.input, feature_version=minor) ast = ast3 # TODO(mdemello): Get from args module_name = "module" src_code = source.Code(src, vm.opcode_traces, VmTrace, filename=options.input) ix = Indexer(ast=ast, src=src_code, loader=vm.loader, module_name=module_name, pytd_module=pytd_module) ix.index(ast_root_node) ix.finalize() # Make the vm available via indexer.vm for post-finalize() functions. ix.vm = vm # Use the indexer as a single object to hold data for calling processes. if generate_callgraphs: ix.function_map = callgraph.collect_function_map(ix) # Release the vm before returning if not preserve_pytype_vm: ix.vm = None return ix