mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	GH-100117: Make co_lines more efficient (GH-100447)
				
					
				
			This commit is contained in:
		
							parent
							
								
									b2f7b2ef0b
								
							
						
					
					
						commit
						f07daaf4f7
					
				
					 4 changed files with 26 additions and 38 deletions
				
			
		|  | @ -702,7 +702,8 @@ def test_positions(self): | ||||||
| 
 | 
 | ||||||
|     def check_lines(self, func): |     def check_lines(self, func): | ||||||
|         co = func.__code__ |         co = func.__code__ | ||||||
|         lines1 = list(dedup(l for (_, _, l) in co.co_lines())) |         lines1 = [line for _, _, line in co.co_lines()] | ||||||
|  |         self.assertEqual(lines1, list(dedup(lines1))) | ||||||
|         lines2 = list(lines_from_postions(positions_from_location_table(co))) |         lines2 = list(lines_from_postions(positions_from_location_table(co))) | ||||||
|         for l1, l2 in zip(lines1, lines2): |         for l1, l2 in zip(lines1, lines2): | ||||||
|             self.assertEqual(l1, l2) |             self.assertEqual(l1, l2) | ||||||
|  |  | ||||||
|  | @ -161,9 +161,8 @@ def test_leading_newlines(self): | ||||||
|         s256 = "".join(["\n"] * 256 + ["spam"]) |         s256 = "".join(["\n"] * 256 + ["spam"]) | ||||||
|         co = compile(s256, 'fn', 'exec') |         co = compile(s256, 'fn', 'exec') | ||||||
|         self.assertEqual(co.co_firstlineno, 1) |         self.assertEqual(co.co_firstlineno, 1) | ||||||
|         lines = list(co.co_lines()) |         lines = [line for _, _, line in co.co_lines()] | ||||||
|         self.assertEqual(lines[0][2], 0) |         self.assertEqual(lines, [0, 257]) | ||||||
|         self.assertEqual(lines[1][2], 257) |  | ||||||
| 
 | 
 | ||||||
|     def test_literals_with_leading_zeroes(self): |     def test_literals_with_leading_zeroes(self): | ||||||
|         for arg in ["077787", "0xj", "0x.", "0e",  "090000000000000", |         for arg in ["077787", "0xj", "0x.", "0e",  "090000000000000", | ||||||
|  | @ -955,9 +954,9 @@ def no_code2(): | ||||||
|         for func in (no_code1, no_code2): |         for func in (no_code1, no_code2): | ||||||
|             with self.subTest(func=func): |             with self.subTest(func=func): | ||||||
|                 code = func.__code__ |                 code = func.__code__ | ||||||
|                 lines = list(code.co_lines()) |                 [(start, end, line)] = code.co_lines() | ||||||
|                 start, end, line = lines[0] |  | ||||||
|                 self.assertEqual(start, 0) |                 self.assertEqual(start, 0) | ||||||
|  |                 self.assertEqual(end, len(code.co_code)) | ||||||
|                 self.assertEqual(line, code.co_firstlineno) |                 self.assertEqual(line, code.co_firstlineno) | ||||||
| 
 | 
 | ||||||
|     def get_code_lines(self, code): |     def get_code_lines(self, code): | ||||||
|  |  | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | Improve the output of ``co_lines`` by emitting only one entry for each line | ||||||
|  | range. | ||||||
|  | @ -1183,6 +1183,14 @@ lineiter_dealloc(lineiterator *li) | ||||||
|     Py_TYPE(li)->tp_free(li); |     Py_TYPE(li)->tp_free(li); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static PyObject * | ||||||
|  | _source_offset_converter(int *value) { | ||||||
|  |     if (*value == -1) { | ||||||
|  |         Py_RETURN_NONE; | ||||||
|  |     } | ||||||
|  |     return PyLong_FromLong(*value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static PyObject * | static PyObject * | ||||||
| lineiter_next(lineiterator *li) | lineiter_next(lineiterator *li) | ||||||
| { | { | ||||||
|  | @ -1190,31 +1198,17 @@ lineiter_next(lineiterator *li) | ||||||
|     if (!_PyLineTable_NextAddressRange(bounds)) { |     if (!_PyLineTable_NextAddressRange(bounds)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|     PyObject *start = NULL; |     int start = bounds->ar_start; | ||||||
|     PyObject *end = NULL; |     int line = bounds->ar_line; | ||||||
|     PyObject *line = NULL; |     // Merge overlapping entries:
 | ||||||
|     PyObject *result = PyTuple_New(3); |     while (_PyLineTable_NextAddressRange(bounds)) { | ||||||
|     start = PyLong_FromLong(bounds->ar_start); |         if (bounds->ar_line != line) { | ||||||
|     end = PyLong_FromLong(bounds->ar_end); |             _PyLineTable_PreviousAddressRange(bounds); | ||||||
|     if (bounds->ar_line < 0) { |             break; | ||||||
|         line = Py_NewRef(Py_None); |         } | ||||||
|     } |     } | ||||||
|     else { |     return Py_BuildValue("iiO&", start, bounds->ar_end, | ||||||
|         line = PyLong_FromLong(bounds->ar_line); |                          _source_offset_converter, &line); | ||||||
|     } |  | ||||||
|     if (result == NULL || start == NULL || end == NULL || line == NULL) { |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
|     PyTuple_SET_ITEM(result, 0, start); |  | ||||||
|     PyTuple_SET_ITEM(result, 1, end); |  | ||||||
|     PyTuple_SET_ITEM(result, 2, line); |  | ||||||
|     return result; |  | ||||||
| error: |  | ||||||
|     Py_XDECREF(start); |  | ||||||
|     Py_XDECREF(end); |  | ||||||
|     Py_XDECREF(line); |  | ||||||
|     Py_XDECREF(result); |  | ||||||
|     return result; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PyTypeObject _PyLineIterator = { | PyTypeObject _PyLineIterator = { | ||||||
|  | @ -1290,14 +1284,6 @@ positionsiter_dealloc(positionsiterator* pi) | ||||||
|     Py_TYPE(pi)->tp_free(pi); |     Py_TYPE(pi)->tp_free(pi); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static PyObject* |  | ||||||
| _source_offset_converter(int* value) { |  | ||||||
|     if (*value == -1) { |  | ||||||
|         Py_RETURN_NONE; |  | ||||||
|     } |  | ||||||
|     return PyLong_FromLong(*value); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyObject* | static PyObject* | ||||||
| positionsiter_next(positionsiterator* pi) | positionsiter_next(positionsiterator* pi) | ||||||
| { | { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Brandt Bucher
						Brandt Bucher