Skip to content

Commit dd65849

Browse files
committed
Revert "pythongh-101865: Remove deprecated co_lnotab from code objects as per PEP626"
This reverts commit 06a79d9.
1 parent 06a79d9 commit dd65849

File tree

9 files changed

+340
-12
lines changed

9 files changed

+340
-12
lines changed

Doc/library/inspect.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ attributes (see :ref:`import-mod-attrs` for module attributes):
164164
| | | read more :ref:`here |
165165
| | | <inspect-module-co-flags>`|
166166
+-----------+-------------------+---------------------------+
167+
| | co_lnotab | encoded mapping of line |
168+
| | | numbers to bytecode |
169+
| | | indices |
170+
+-----------+-------------------+---------------------------+
167171
| | co_freevars | tuple of names of free |
168172
| | | variables (referenced via |
169173
| | | a function's closure) |

Doc/reference/datamodel.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,7 @@ Internal types
962962
single: co_filename (code object attribute)
963963
single: co_firstlineno (code object attribute)
964964
single: co_flags (code object attribute)
965+
single: co_lnotab (code object attribute)
965966
single: co_name (code object attribute)
966967
single: co_names (code object attribute)
967968
single: co_nlocals (code object attribute)
@@ -988,7 +989,9 @@ Internal types
988989
a tuple containing the literals used by the bytecode; :attr:`co_names` is
989990
a tuple containing the names used by the bytecode; :attr:`co_filename` is
990991
the filename from which the code was compiled; :attr:`co_firstlineno` is
991-
the first line number of the function; :attr:`co_stacksize` is the
992+
the first line number of the function; :attr:`co_lnotab` is a string
993+
encoding the mapping from bytecode offsets to line numbers (for details
994+
see the source code of the interpreter); :attr:`co_stacksize` is the
992995
required stack size; :attr:`co_flags` is an integer encoding a number
993996
of flags for the interpreter.
994997

Doc/whatsnew/3.12.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -700,10 +700,6 @@ Removed
700700
*context* parameter instead.
701701
(Contributed by Victor Stinner in :gh:`94172`.)
702702

703-
* Remove ``co_lnotab`` attribute from code objects per :pep:`626`:
704-
use ``co_lines`` method instead.
705-
(Contributed by Nikita Sobolev in :gh:`101865`.)
706-
707703

708704
Porting to Python 3.12
709705
======================

Lib/inspect.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ def iscode(object):
499499
co_freevars tuple of names of free variables
500500
co_posonlyargcount number of positional only arguments
501501
co_kwonlyargcount number of keyword only arguments (not including ** arg)
502+
co_lnotab encoded mapping of line numbers to bytecode indices
502503
co_name name with which this code object was defined
503504
co_names tuple of names other than arguments and function locals
504505
co_nlocals number of local variables
@@ -1707,6 +1708,7 @@ def getframeinfo(frame, context=1):
17071708

17081709
def getlineno(frame):
17091710
"""Get the line number from a frame object, allowing for optimization."""
1711+
# FrameType.f_lineno is now a descriptor that grovels co_lnotab
17101712
return frame.f_lineno
17111713

17121714
_FrameInfo = namedtuple('_FrameInfo', ('frame',) + Traceback._fields)

Lib/pydoc_data/topics.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
# Autogenerated by Sphinx on Mon Feb 13 10:21:05 2023
2+
# Autogenerated by Sphinx on Tue Feb 7 13:18:04 2023
33
topics = {'assert': 'The "assert" statement\n'
44
'**********************\n'
55
'\n'
@@ -13704,10 +13704,13 @@
1370413704
' bytecode; "co_filename" is the filename from which the code '
1370513705
'was\n'
1370613706
' compiled; "co_firstlineno" is the first line number of the\n'
13707-
' function; "co_stacksize" is the required stack size; '
13708-
'"co_flags"\n'
13709-
' is an integer encoding a number of flags for the '
13710-
'interpreter.\n'
13707+
' function; "co_lnotab" is a string encoding the mapping from\n'
13708+
' bytecode offsets to line numbers (for details see the source\n'
13709+
' code of the interpreter); "co_stacksize" is the required '
13710+
'stack\n'
13711+
' size; "co_flags" is an integer encoding a number of flags '
13712+
'for\n'
13713+
' the interpreter.\n'
1371113714
'\n'
1371213715
' The following flag bits are defined for "co_flags": bit '
1371313716
'"0x04"\n'

Misc/NEWS.d/next/Core and Builtins/2023-02-13-10-35-52.gh-issue-101865.2kjTxP.rst

Lines changed: 0 additions & 1 deletion
This file was deleted.

Misc/gdbinit

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,25 @@ end
5454
# A rewrite of the Python interpreter's line number calculator in GDB's
5555
# command language
5656
define lineno
57-
printf "%d", f->f_lineno
57+
set $__continue = 1
58+
set $__co = f->f_code
59+
set $__lasti = f->f_lasti
60+
set $__sz = ((PyVarObject *)$__co->co_lnotab)->ob_size/2
61+
set $__p = (unsigned char *)((PyBytesObject *)$__co->co_lnotab)->ob_sval
62+
set $__li = $__co->co_firstlineno
63+
set $__ad = 0
64+
while ($__sz-1 >= 0 && $__continue)
65+
set $__sz = $__sz - 1
66+
set $__ad = $__ad + *$__p
67+
set $__p = $__p + 1
68+
if ($__ad > $__lasti)
69+
set $__continue = 0
70+
else
71+
set $__li = $__li + *$__p
72+
set $__p = $__p + 1
73+
end
74+
end
75+
printf "%d", $__li
5876
end
5977

6078
define pyframev

Objects/codeobject.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,77 @@ _PyLineTable_NextAddressRange(PyCodeAddressRange *range)
10971097
return 1;
10981098
}
10991099

1100+
static int
1101+
emit_pair(PyObject **bytes, int *offset, int a, int b)
1102+
{
1103+
Py_ssize_t len = PyBytes_GET_SIZE(*bytes);
1104+
if (*offset + 2 >= len) {
1105+
if (_PyBytes_Resize(bytes, len * 2) < 0)
1106+
return 0;
1107+
}
1108+
unsigned char *lnotab = (unsigned char *) PyBytes_AS_STRING(*bytes);
1109+
lnotab += *offset;
1110+
*lnotab++ = a;
1111+
*lnotab++ = b;
1112+
*offset += 2;
1113+
return 1;
1114+
}
1115+
1116+
static int
1117+
emit_delta(PyObject **bytes, int bdelta, int ldelta, int *offset)
1118+
{
1119+
while (bdelta > 255) {
1120+
if (!emit_pair(bytes, offset, 255, 0)) {
1121+
return 0;
1122+
}
1123+
bdelta -= 255;
1124+
}
1125+
while (ldelta > 127) {
1126+
if (!emit_pair(bytes, offset, bdelta, 127)) {
1127+
return 0;
1128+
}
1129+
bdelta = 0;
1130+
ldelta -= 127;
1131+
}
1132+
while (ldelta < -128) {
1133+
if (!emit_pair(bytes, offset, bdelta, -128)) {
1134+
return 0;
1135+
}
1136+
bdelta = 0;
1137+
ldelta += 128;
1138+
}
1139+
return emit_pair(bytes, offset, bdelta, ldelta);
1140+
}
1141+
1142+
static PyObject *
1143+
decode_linetable(PyCodeObject *code)
1144+
{
1145+
PyCodeAddressRange bounds;
1146+
PyObject *bytes;
1147+
int table_offset = 0;
1148+
int code_offset = 0;
1149+
int line = code->co_firstlineno;
1150+
bytes = PyBytes_FromStringAndSize(NULL, 64);
1151+
if (bytes == NULL) {
1152+
return NULL;
1153+
}
1154+
_PyCode_InitAddressRange(code, &bounds);
1155+
while (_PyLineTable_NextAddressRange(&bounds)) {
1156+
if (bounds.opaque.computed_line != line) {
1157+
int bdelta = bounds.ar_start - code_offset;
1158+
int ldelta = bounds.opaque.computed_line - line;
1159+
if (!emit_delta(&bytes, bdelta, ldelta, &table_offset)) {
1160+
Py_DECREF(bytes);
1161+
return NULL;
1162+
}
1163+
code_offset = bounds.ar_start;
1164+
line = bounds.opaque.computed_line;
1165+
}
1166+
}
1167+
_PyBytes_Resize(&bytes, table_offset);
1168+
return bytes;
1169+
}
1170+
11001171

11011172
typedef struct {
11021173
PyObject_HEAD
@@ -1810,6 +1881,12 @@ static PyMemberDef code_memberlist[] = {
18101881
};
18111882

18121883

1884+
static PyObject *
1885+
code_getlnotab(PyCodeObject *code, void *closure)
1886+
{
1887+
return decode_linetable(code);
1888+
}
1889+
18131890
static PyObject *
18141891
code_getvarnames(PyCodeObject *code, void *closure)
18151892
{
@@ -1842,6 +1919,7 @@ code_getcode(PyCodeObject *code, void *closure)
18421919
}
18431920

18441921
static PyGetSetDef code_getsetlist[] = {
1922+
{"co_lnotab", (getter)code_getlnotab, NULL, NULL},
18451923
{"_co_code_adaptive", (getter)code_getcodeadaptive, NULL, NULL},
18461924
// The following old names are kept for backward compatibility.
18471925
{"co_varnames", (getter)code_getvarnames, NULL, NULL},

0 commit comments

Comments
 (0)