Navegador

navegador / tests / test_python_parser.py
Source Blame History 418 lines
b663b12… lmata 1 """Tests for navegador.ingestion.python — PythonParser internal methods."""
b663b12… lmata 2
b663b12… lmata 3 from unittest.mock import MagicMock, patch
b663b12… lmata 4
b663b12… lmata 5 import pytest
b663b12… lmata 6
b663b12… lmata 7 from navegador.graph.schema import NodeLabel
b663b12… lmata 8
b663b12… lmata 9 # ── Mock tree-sitter node ──────────────────────────────────────────────────────
b663b12… lmata 10
b663b12… lmata 11 class MockNode:
b663b12… lmata 12 """Minimal mock of a tree-sitter Node."""
b663b12… lmata 13 def __init__(self, type_: str, text: bytes = b"", children: list = None,
b663b12… lmata 14 start_byte: int = 0, end_byte: int = 0,
b663b12… lmata 15 start_point: tuple = (0, 0), end_point: tuple = (0, 0)):
b663b12… lmata 16 self.type = type_
b663b12… lmata 17 self._text = text
b663b12… lmata 18 self.children = children or []
b663b12… lmata 19 self.start_byte = start_byte
b663b12… lmata 20 self.end_byte = end_byte
b663b12… lmata 21 self.start_point = start_point
b663b12… lmata 22 self.end_point = end_point
b663b12… lmata 23
b663b12… lmata 24
b663b12… lmata 25 def _text_node(text: bytes, type_: str = "identifier") -> MockNode:
b663b12… lmata 26 return MockNode(type_, text, start_byte=0, end_byte=len(text))
b663b12… lmata 27
b663b12… lmata 28
b663b12… lmata 29 def _make_store():
b663b12… lmata 30 store = MagicMock()
b663b12… lmata 31 store.query.return_value = MagicMock(result_set=[])
b663b12… lmata 32 return store
b663b12… lmata 33
b663b12… lmata 34
b663b12… lmata 35 # ── _node_text ────────────────────────────────────────────────────────────────
b663b12… lmata 36
b663b12… lmata 37 class TestNodeText:
b663b12… lmata 38 def test_extracts_text_from_source(self):
b663b12… lmata 39 from navegador.ingestion.python import _node_text
b663b12… lmata 40 source = b"hello world"
b663b12… lmata 41 node = MockNode("identifier", start_byte=6, end_byte=11)
b663b12… lmata 42 assert _node_text(node, source) == "world"
b663b12… lmata 43
b663b12… lmata 44 def test_full_source(self):
b663b12… lmata 45 from navegador.ingestion.python import _node_text
b663b12… lmata 46 source = b"foo_bar"
b663b12… lmata 47 node = MockNode("identifier", start_byte=0, end_byte=7)
b663b12… lmata 48 assert _node_text(node, source) == "foo_bar"
b663b12… lmata 49
b663b12… lmata 50 def test_handles_utf8(self):
b663b12… lmata 51 from navegador.ingestion.python import _node_text
b663b12… lmata 52 source = "héllo".encode("utf-8")
b663b12… lmata 53 node = MockNode("identifier", start_byte=0, end_byte=len(source))
b663b12… lmata 54 assert "llo" in _node_text(node, source)
b663b12… lmata 55
b663b12… lmata 56
b663b12… lmata 57 # ── _get_docstring ────────────────────────────────────────────────────────────
b663b12… lmata 58
b663b12… lmata 59 class TestGetDocstring:
b663b12… lmata 60 def test_returns_none_when_no_block(self):
b663b12… lmata 61 from navegador.ingestion.python import _get_docstring
b663b12… lmata 62 node = MockNode("function_definition", children=[
b663b12… lmata 63 MockNode("identifier")
b663b12… lmata 64 ])
b663b12… lmata 65 assert _get_docstring(node, b"def foo(): pass") is None
b663b12… lmata 66
b663b12… lmata 67 def test_returns_none_when_no_expression_stmt(self):
b663b12… lmata 68 from navegador.ingestion.python import _get_docstring
b663b12… lmata 69 block = MockNode("block", children=[
b663b12… lmata 70 MockNode("return_statement")
b663b12… lmata 71 ])
b663b12… lmata 72 fn = MockNode("function_definition", children=[block])
b663b12… lmata 73 assert _get_docstring(fn, b"") is None
b663b12… lmata 74
b663b12… lmata 75 def test_returns_none_when_no_string_in_expr(self):
b663b12… lmata 76 from navegador.ingestion.python import _get_docstring
b663b12… lmata 77 expr_stmt = MockNode("expression_statement", children=[
b663b12… lmata 78 MockNode("assignment")
b663b12… lmata 79 ])
b663b12… lmata 80 block = MockNode("block", children=[expr_stmt])
b663b12… lmata 81 fn = MockNode("function_definition", children=[block])
b663b12… lmata 82 assert _get_docstring(fn, b"") is None
b663b12… lmata 83
b663b12… lmata 84 def test_extracts_docstring(self):
b663b12… lmata 85 from navegador.ingestion.python import _get_docstring
b663b12… lmata 86 source = b'"""My docstring."""'
b663b12… lmata 87 string_node = MockNode("string", start_byte=0, end_byte=len(source))
b663b12… lmata 88 expr_stmt = MockNode("expression_statement", children=[string_node])
b663b12… lmata 89 block = MockNode("block", children=[expr_stmt])
b663b12… lmata 90 fn = MockNode("function_definition", children=[block])
b663b12… lmata 91 result = _get_docstring(fn, source)
b663b12… lmata 92 assert "My docstring." in result
b663b12… lmata 93
b663b12… lmata 94
b663b12… lmata 95 # ── _get_python_language error ─────────────────────────────────────────────────
b663b12… lmata 96
b663b12… lmata 97 class TestGetPythonLanguage:
b663b12… lmata 98 def test_raises_import_error_when_not_installed(self):
b663b12… lmata 99 from navegador.ingestion.python import _get_python_language
b663b12… lmata 100 with patch.dict("sys.modules", {"tree_sitter_python": None, "tree_sitter": None}):
b663b12… lmata 101 with pytest.raises(ImportError, match="tree-sitter-python"):
b663b12… lmata 102 _get_python_language()
b663b12… lmata 103
b663b12… lmata 104
b663b12… lmata 105 # ── PythonParser with mocked parser ──────────────────────────────────────────
b663b12… lmata 106
b663b12… lmata 107 class TestPythonParserHandlers:
b663b12… lmata 108 def _make_parser(self):
b663b12… lmata 109 """Create PythonParser bypassing tree-sitter init."""
b663b12… lmata 110 from navegador.ingestion.python import PythonParser
b663b12… lmata 111 with patch("navegador.ingestion.python._get_parser") as mock_get:
b663b12… lmata 112 mock_get.return_value = MagicMock()
b663b12… lmata 113 parser = PythonParser()
b663b12… lmata 114 return parser
b663b12… lmata 115
b663b12… lmata 116 def test_handle_import(self):
b663b12… lmata 117 parser = self._make_parser()
b663b12… lmata 118 store = _make_store()
b663b12… lmata 119 source = b"import os.path"
b663b12… lmata 120
b663b12… lmata 121 dotted = _text_node(b"os.path", "dotted_name")
b663b12… lmata 122 import_node = MockNode("import_statement", children=[dotted],
b663b12… lmata 123 start_point=(0, 0))
b663b12… lmata 124 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 125 parser._handle_import(import_node, source, "app.py", store, stats)
b663b12… lmata 126 store.create_node.assert_called_once()
b663b12… lmata 127 store.create_edge.assert_called_once()
b663b12… lmata 128 assert stats["edges"] == 1
b663b12… lmata 129
b663b12… lmata 130 def test_handle_import_no_dotted_name(self):
b663b12… lmata 131 parser = self._make_parser()
b663b12… lmata 132 store = _make_store()
b663b12… lmata 133 import_node = MockNode("import_statement", children=[
b663b12… lmata 134 MockNode("keyword", b"import")
b663b12… lmata 135 ], start_point=(0, 0))
b663b12… lmata 136 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 137 parser._handle_import(import_node, b"import x", "app.py", store, stats)
b663b12… lmata 138 store.create_node.assert_not_called()
b663b12… lmata 139
b663b12… lmata 140 def test_handle_class(self):
b663b12… lmata 141 parser = self._make_parser()
b663b12… lmata 142 store = _make_store()
b663b12… lmata 143 source = b"class MyClass: pass"
b663b12… lmata 144 name_node = _text_node(b"MyClass")
b663b12… lmata 145 class_node = MockNode("class_definition",
b663b12… lmata 146 children=[name_node],
b663b12… lmata 147 start_point=(0, 0), end_point=(0, 18))
b663b12… lmata 148 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 149 parser._handle_class(class_node, source, "app.py", store, stats)
b663b12… lmata 150 assert stats["classes"] == 1
b663b12… lmata 151 assert stats["edges"] == 1
b663b12… lmata 152 store.create_node.assert_called()
b663b12… lmata 153
b663b12… lmata 154 def test_handle_class_no_identifier(self):
b663b12… lmata 155 parser = self._make_parser()
b663b12… lmata 156 store = _make_store()
b663b12… lmata 157 class_node = MockNode("class_definition", children=[
b663b12… lmata 158 MockNode("keyword", b"class")
b663b12… lmata 159 ], start_point=(0, 0), end_point=(0, 0))
b663b12… lmata 160 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 161 parser._handle_class(class_node, b"class: pass", "app.py", store, stats)
b663b12… lmata 162 assert stats["classes"] == 0
b663b12… lmata 163
b663b12… lmata 164 def test_handle_class_with_inheritance(self):
b663b12… lmata 165 parser = self._make_parser()
b663b12… lmata 166 store = _make_store()
b663b12… lmata 167 source = b"class Child(Parent): pass"
b663b12… lmata 168 name_node = _text_node(b"Child")
b663b12… lmata 169 parent_id = _text_node(b"Parent")
b663b12… lmata 170 arg_list = MockNode("argument_list", children=[parent_id])
b663b12… lmata 171 class_node = MockNode("class_definition",
b663b12… lmata 172 children=[name_node, arg_list],
b663b12… lmata 173 start_point=(0, 0), end_point=(0, 24))
b663b12… lmata 174 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 175 parser._handle_class(class_node, source, "app.py", store, stats)
b663b12… lmata 176 # Should create class node + CONTAINS edge + INHERITS edge
b663b12… lmata 177 assert stats["edges"] == 2
b663b12… lmata 178
b663b12… lmata 179 def test_handle_function(self):
b663b12… lmata 180 parser = self._make_parser()
b663b12… lmata 181 store = _make_store()
b663b12… lmata 182 source = b"def foo(): pass"
b663b12… lmata 183 name_node = _text_node(b"foo")
b663b12… lmata 184 fn_node = MockNode("function_definition", children=[name_node],
b663b12… lmata 185 start_point=(0, 0), end_point=(0, 14))
b663b12… lmata 186 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 187 parser._handle_function(fn_node, source, "app.py", store, stats, class_name=None)
b663b12… lmata 188 assert stats["functions"] == 1
b663b12… lmata 189 assert stats["edges"] == 1
b663b12… lmata 190 store.create_node.assert_called_once()
b663b12… lmata 191 label = store.create_node.call_args[0][0]
b663b12… lmata 192 assert label == NodeLabel.Function
b663b12… lmata 193
b663b12… lmata 194 def test_handle_method(self):
b663b12… lmata 195 parser = self._make_parser()
b663b12… lmata 196 store = _make_store()
b663b12… lmata 197 source = b"def my_method(self): pass"
b663b12… lmata 198 name_node = _text_node(b"my_method")
b663b12… lmata 199 fn_node = MockNode("function_definition", children=[name_node],
b663b12… lmata 200 start_point=(0, 0), end_point=(0, 24))
b663b12… lmata 201 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 202 parser._handle_function(fn_node, source, "app.py", store, stats, class_name="MyClass")
b663b12… lmata 203 label = store.create_node.call_args[0][0]
b663b12… lmata 204 assert label == NodeLabel.Method
b663b12… lmata 205
b663b12… lmata 206 def test_handle_function_no_identifier(self):
b663b12… lmata 207 parser = self._make_parser()
b663b12… lmata 208 store = _make_store()
b663b12… lmata 209 fn_node = MockNode("function_definition", children=[
b663b12… lmata 210 MockNode("keyword", b"def")
b663b12… lmata 211 ], start_point=(0, 0), end_point=(0, 0))
b663b12… lmata 212 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 213 parser._handle_function(fn_node, b"def", "app.py", store, stats, class_name=None)
b663b12… lmata 214 assert stats["functions"] == 0
b663b12… lmata 215
b663b12… lmata 216 def test_extract_calls(self):
b663b12… lmata 217 parser = self._make_parser()
b663b12… lmata 218 store = _make_store()
b663b12… lmata 219 source = b"def foo():\n bar()\n"
b663b12… lmata 220
b663b12… lmata 221 callee = _text_node(b"bar")
b663b12… lmata 222 call_node = MockNode("call", children=[callee])
b663b12… lmata 223 block = MockNode("block", children=[call_node])
b663b12… lmata 224 fn_node = MockNode("function_definition", children=[block])
b663b12… lmata 225
b663b12… lmata 226 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 227 parser._extract_calls(fn_node, source, "app.py", "foo", NodeLabel.Function, store, stats)
b663b12… lmata 228 store.create_edge.assert_called_once()
b663b12… lmata 229 assert stats["edges"] == 1
b663b12… lmata 230
b663b12… lmata 231 def test_extract_calls_no_block(self):
b663b12… lmata 232 parser = self._make_parser()
b663b12… lmata 233 store = _make_store()
b663b12… lmata 234 fn_node = MockNode("function_definition", children=[])
b663b12… lmata 235 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 236 parser._extract_calls(fn_node, b"", "app.py", "foo", NodeLabel.Function, store, stats)
b663b12… lmata 237 store.create_edge.assert_not_called()
b663b12… lmata 238
b663b12… lmata 239 def test_walk_dispatches_import(self):
b663b12… lmata 240 parser = self._make_parser()
b663b12… lmata 241 store = _make_store()
b663b12… lmata 242 dotted = _text_node(b"sys", "dotted_name")
b663b12… lmata 243 import_node = MockNode("import_statement", children=[dotted], start_point=(0, 0))
b663b12… lmata 244 root = MockNode("module", children=[import_node])
b663b12… lmata 245 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 246 parser._walk(root, b"import sys", "app.py", store, stats, class_name=None)
b663b12… lmata 247 assert stats["edges"] == 1
b663b12… lmata 248
b663b12… lmata 249 def test_walk_dispatches_class(self):
b663b12… lmata 250 parser = self._make_parser()
b663b12… lmata 251 store = _make_store()
b663b12… lmata 252 name_node = _text_node(b"MyClass")
b663b12… lmata 253 class_node = MockNode("class_definition", children=[name_node],
b663b12… lmata 254 start_point=(0, 0), end_point=(0, 0))
b663b12… lmata 255 root = MockNode("module", children=[class_node])
b663b12… lmata 256 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 257 parser._walk(root, b"class MyClass: pass", "app.py", store, stats, class_name=None)
b663b12… lmata 258 assert stats["classes"] == 1
b663b12… lmata 259
b663b12… lmata 260 def test_walk_dispatches_function(self):
b663b12… lmata 261 parser = self._make_parser()
b663b12… lmata 262 store = _make_store()
b663b12… lmata 263 name_node = _text_node(b"my_fn")
b663b12… lmata 264 fn_node = MockNode("function_definition", children=[name_node],
b663b12… lmata 265 start_point=(0, 0), end_point=(0, 0))
b663b12… lmata 266 root = MockNode("module", children=[fn_node])
b663b12… lmata 267 stats = {"functions": 0, "classes": 0, "edges": 0}
b663b12… lmata 268 parser._walk(root, b"def my_fn(): pass", "app.py", store, stats, class_name=None)
7ae0080… lmata 269 assert stats["functions"] == 1
7ae0080… lmata 270
7ae0080… lmata 271
7ae0080… lmata 272 # ── _get_python_language happy path ──────────────────────────────────────────
7ae0080… lmata 273
7ae0080… lmata 274 class TestGetPythonLanguageHappyPath:
7ae0080… lmata 275 def test_returns_language_object(self):
7ae0080… lmata 276 from navegador.ingestion.python import _get_python_language
7ae0080… lmata 277 mock_tspy = MagicMock()
7ae0080… lmata 278 mock_ts = MagicMock()
7ae0080… lmata 279 with patch.dict("sys.modules", {
7ae0080… lmata 280 "tree_sitter_python": mock_tspy,
7ae0080… lmata 281 "tree_sitter": mock_ts,
7ae0080… lmata 282 }):
7ae0080… lmata 283 result = _get_python_language()
7ae0080… lmata 284 assert result is mock_ts.Language.return_value
7ae0080… lmata 285
7ae0080… lmata 286
7ae0080… lmata 287 # ── _get_parser ───────────────────────────────────────────────────────────────
7ae0080… lmata 288
7ae0080… lmata 289 class TestGetParserHappyPath:
7ae0080… lmata 290 def test_returns_parser(self):
7ae0080… lmata 291 from navegador.ingestion.python import _get_parser
7ae0080… lmata 292 mock_tspy = MagicMock()
7ae0080… lmata 293 mock_ts = MagicMock()
7ae0080… lmata 294 with patch.dict("sys.modules", {
7ae0080… lmata 295 "tree_sitter_python": mock_tspy,
7ae0080… lmata 296 "tree_sitter": mock_ts,
7ae0080… lmata 297 }):
7ae0080… lmata 298 result = _get_parser()
7ae0080… lmata 299 assert result is mock_ts.Parser.return_value
7ae0080… lmata 300
7ae0080… lmata 301
7ae0080… lmata 302 # ── parse_file ────────────────────────────────────────────────────────────────
7ae0080… lmata 303
7ae0080… lmata 304 class TestPythonParseFile:
7ae0080… lmata 305 def _make_parser(self):
7ae0080… lmata 306 from navegador.ingestion.python import PythonParser
7ae0080… lmata 307 with patch("navegador.ingestion.python._get_parser") as mock_get:
7ae0080… lmata 308 mock_get.return_value = MagicMock()
7ae0080… lmata 309 parser = PythonParser()
7ae0080… lmata 310 return parser
7ae0080… lmata 311
7ae0080… lmata 312 def test_parse_file_creates_file_node(self):
7ae0080… lmata 313 import tempfile
7ae0080… lmata 314 from pathlib import Path
7ae0080… lmata 315 parser = self._make_parser()
7ae0080… lmata 316 store = MagicMock()
7ae0080… lmata 317 store.query.return_value = MagicMock(result_set=[])
7ae0080… lmata 318 mock_tree = MagicMock()
7ae0080… lmata 319 mock_tree.root_node.type = "module"
7ae0080… lmata 320 mock_tree.root_node.children = []
7ae0080… lmata 321 parser._parser.parse.return_value = mock_tree
7ae0080… lmata 322 with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as f:
7ae0080… lmata 323 f.write(b"x = 1\n")
7ae0080… lmata 324 fpath = Path(f.name)
7ae0080… lmata 325 try:
7ae0080… lmata 326 stats = parser.parse_file(fpath, fpath.parent, store)
7ae0080… lmata 327 store.create_node.assert_called_once()
7ae0080… lmata 328 call = store.create_node.call_args[0]
7ae0080… lmata 329 from navegador.graph.schema import NodeLabel
7ae0080… lmata 330 assert call[0] == NodeLabel.File
7ae0080… lmata 331 assert call[1]["language"] == "python"
7ae0080… lmata 332 assert isinstance(stats, dict)
7ae0080… lmata 333 finally:
7ae0080… lmata 334 fpath.unlink()
7ae0080… lmata 335
7ae0080… lmata 336
7ae0080… lmata 337 # ── _handle_import_from ───────────────────────────────────────────────────────
7ae0080… lmata 338
7ae0080… lmata 339 class TestHandleImportFrom:
7ae0080… lmata 340 def _make_parser(self):
7ae0080… lmata 341 from navegador.ingestion.python import PythonParser
7ae0080… lmata 342 with patch("navegador.ingestion.python._get_parser") as mock_get:
7ae0080… lmata 343 mock_get.return_value = MagicMock()
7ae0080… lmata 344 parser = PythonParser()
7ae0080… lmata 345 return parser
7ae0080… lmata 346
7ae0080… lmata 347 def test_handle_import_from_with_member(self):
7ae0080… lmata 348 parser = self._make_parser()
7ae0080… lmata 349 store = MagicMock()
7ae0080… lmata 350 stats = {"functions": 0, "classes": 0, "edges": 0}
7ae0080… lmata 351 combined = b"os.pathjoin"
7ae0080… lmata 352 module_node3 = MockNode("dotted_name", start_byte=0, end_byte=7)
7ae0080… lmata 353 member_node3 = MockNode("import_from_member", start_byte=7, end_byte=11)
7ae0080… lmata 354 node3 = MockNode("import_from_statement",
7ae0080… lmata 355 children=[module_node3, member_node3],
7ae0080… lmata 356 start_point=(0, 0))
7ae0080… lmata 357 parser._handle_import_from(node3, combined, "app.py", store, stats)
7ae0080… lmata 358 store.create_node.assert_called_once()
7ae0080… lmata 359 store.create_edge.assert_called_once()
7ae0080… lmata 360 assert stats["edges"] == 1
7ae0080… lmata 361
7ae0080… lmata 362 def test_handle_import_from_no_member(self):
7ae0080… lmata 363 parser = self._make_parser()
7ae0080… lmata 364 store = MagicMock()
7ae0080… lmata 365 # No import_from_member children — nothing should be created
7ae0080… lmata 366 module_node = MockNode("dotted_name", start_byte=0, end_byte=7)
7ae0080… lmata 367 node = MockNode("import_from_statement",
7ae0080… lmata 368 children=[module_node],
7ae0080… lmata 369 start_point=(0, 0))
7ae0080… lmata 370 stats = {"functions": 0, "classes": 0, "edges": 0}
7ae0080… lmata 371 parser._handle_import_from(node, b"os.path", "app.py", store, stats)
7ae0080… lmata 372 store.create_node.assert_not_called()
7ae0080… lmata 373 assert stats["edges"] == 0
7ae0080… lmata 374
7ae0080… lmata 375 def test_walk_dispatches_import_from(self):
7ae0080… lmata 376 parser = self._make_parser()
7ae0080… lmata 377 store = MagicMock()
7ae0080… lmata 378 source = b"os.pathjoin"
7ae0080… lmata 379 module_node = MockNode("dotted_name", start_byte=0, end_byte=7)
7ae0080… lmata 380 member_node = MockNode("import_from_member", start_byte=7, end_byte=11)
7ae0080… lmata 381 import_from = MockNode("import_from_statement",
7ae0080… lmata 382 children=[module_node, member_node],
7ae0080… lmata 383 start_point=(0, 0))
7ae0080… lmata 384 root = MockNode("module", children=[import_from])
7ae0080… lmata 385 stats = {"functions": 0, "classes": 0, "edges": 0}
7ae0080… lmata 386 parser._walk(root, source, "app.py", store, stats, class_name=None)
7ae0080… lmata 387 assert stats["edges"] == 1
7ae0080… lmata 388
7ae0080… lmata 389
7ae0080… lmata 390 # ── _handle_class with body ───────────────────────────────────────────────────
7ae0080… lmata 391
7ae0080… lmata 392 class TestHandleClassWithBody:
7ae0080… lmata 393 def _make_parser(self):
7ae0080… lmata 394 from navegador.ingestion.python import PythonParser
7ae0080… lmata 395 with patch("navegador.ingestion.python._get_parser") as mock_get:
7ae0080… lmata 396 mock_get.return_value = MagicMock()
7ae0080… lmata 397 parser = PythonParser()
7ae0080… lmata 398 return parser
7ae0080… lmata 399
7ae0080… lmata 400 def test_handle_class_with_method_in_body(self):
7ae0080… lmata 401 parser = self._make_parser()
7ae0080… lmata 402 store = MagicMock()
7ae0080… lmata 403 source = b"method"
7ae0080… lmata 404 name_node = MockNode("identifier", start_byte=0, end_byte=5)
7ae0080… lmata 405 # Method inside the class body
7ae0080… lmata 406 method_name = MockNode("identifier", start_byte=0, end_byte=6)
7ae0080… lmata 407 fn_node = MockNode("function_definition",
7ae0080… lmata 408 children=[method_name],
7ae0080… lmata 409 start_point=(1, 4), end_point=(1, 20))
7ae0080… lmata 410 body = MockNode("block", children=[fn_node])
7ae0080… lmata 411 class_node = MockNode("class_definition",
7ae0080… lmata 412 children=[name_node, body],
7ae0080… lmata 413 start_point=(0, 0), end_point=(2, 0))
7ae0080… lmata 414 stats = {"functions": 0, "classes": 0, "edges": 0}
7ae0080… lmata 415 parser._handle_class(class_node, source, "app.py", store, stats)
7ae0080… lmata 416 # class node + method node both created
7ae0080… lmata 417 assert stats["classes"] == 1
b663b12… lmata 418 assert stats["functions"] == 1

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button