Skip to content

Commit

Permalink
Revert "pythongh-101865: Remove deprecated co_lnotab from code obje…
Browse files Browse the repository at this point in the history
…cts as per PEP626"

This reverts commit 06a79d9.
  • Loading branch information
sobolevn committed Feb 21, 2023
1 parent 06a79d9 commit dd65849
Show file tree
Hide file tree
Showing 9 changed files with 340 additions and 12 deletions.
4 changes: 4 additions & 0 deletions Doc/library/inspect.rst
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ attributes (see :ref:`import-mod-attrs` for module attributes):
| | | read more :ref:`here |
| | | <inspect-module-co-flags>`|
+-----------+-------------------+---------------------------+
| | co_lnotab | encoded mapping of line |
| | | numbers to bytecode |
| | | indices |
+-----------+-------------------+---------------------------+
| | co_freevars | tuple of names of free |
| | | variables (referenced via |
| | | a function's closure) |
Expand Down
5 changes: 4 additions & 1 deletion Doc/reference/datamodel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,7 @@ Internal types
single: co_filename (code object attribute)
single: co_firstlineno (code object attribute)
single: co_flags (code object attribute)
single: co_lnotab (code object attribute)
single: co_name (code object attribute)
single: co_names (code object attribute)
single: co_nlocals (code object attribute)
Expand All @@ -988,7 +989,9 @@ Internal types
a tuple containing the literals used by the bytecode; :attr:`co_names` is
a tuple containing the names used by the bytecode; :attr:`co_filename` is
the filename from which the code was compiled; :attr:`co_firstlineno` is
the first line number of the function; :attr:`co_stacksize` is the
the first line number of the function; :attr:`co_lnotab` is a string
encoding the mapping from bytecode offsets to line numbers (for details
see the source code of the interpreter); :attr:`co_stacksize` is the
required stack size; :attr:`co_flags` is an integer encoding a number
of flags for the interpreter.

Expand Down
4 changes: 0 additions & 4 deletions Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -700,10 +700,6 @@ Removed
*context* parameter instead.
(Contributed by Victor Stinner in :gh:`94172`.)

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


Porting to Python 3.12
======================
Expand Down
2 changes: 2 additions & 0 deletions Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ def iscode(object):
co_freevars tuple of names of free variables
co_posonlyargcount number of positional only arguments
co_kwonlyargcount number of keyword only arguments (not including ** arg)
co_lnotab encoded mapping of line numbers to bytecode indices
co_name name with which this code object was defined
co_names tuple of names other than arguments and function locals
co_nlocals number of local variables
Expand Down Expand Up @@ -1707,6 +1708,7 @@ def getframeinfo(frame, context=1):

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

_FrameInfo = namedtuple('_FrameInfo', ('frame',) + Traceback._fields)
Expand Down
13 changes: 8 additions & 5 deletions Lib/pydoc_data/topics.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Autogenerated by Sphinx on Mon Feb 13 10:21:05 2023
# Autogenerated by Sphinx on Tue Feb 7 13:18:04 2023
topics = {'assert': 'The "assert" statement\n'
'**********************\n'
'\n'
Expand Down Expand Up @@ -13704,10 +13704,13 @@
' bytecode; "co_filename" is the filename from which the code '
'was\n'
' compiled; "co_firstlineno" is the first line number of the\n'
' function; "co_stacksize" is the required stack size; '
'"co_flags"\n'
' is an integer encoding a number of flags for the '
'interpreter.\n'
' function; "co_lnotab" is a string encoding the mapping from\n'
' bytecode offsets to line numbers (for details see the source\n'
' code of the interpreter); "co_stacksize" is the required '
'stack\n'
' size; "co_flags" is an integer encoding a number of flags '
'for\n'
' the interpreter.\n'
'\n'
' The following flag bits are defined for "co_flags": bit '
'"0x04"\n'
Expand Down

This file was deleted.

20 changes: 19 additions & 1 deletion Misc/gdbinit
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,25 @@ end
# A rewrite of the Python interpreter's line number calculator in GDB's
# command language
define lineno
printf "%d", f->f_lineno
set $__continue = 1
set $__co = f->f_code
set $__lasti = f->f_lasti
set $__sz = ((PyVarObject *)$__co->co_lnotab)->ob_size/2
set $__p = (unsigned char *)((PyBytesObject *)$__co->co_lnotab)->ob_sval
set $__li = $__co->co_firstlineno
set $__ad = 0
while ($__sz-1 >= 0 && $__continue)
set $__sz = $__sz - 1
set $__ad = $__ad + *$__p
set $__p = $__p + 1
if ($__ad > $__lasti)
set $__continue = 0
else
set $__li = $__li + *$__p
set $__p = $__p + 1
end
end
printf "%d", $__li
end

define pyframev
Expand Down
78 changes: 78 additions & 0 deletions Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,77 @@ _PyLineTable_NextAddressRange(PyCodeAddressRange *range)
return 1;
}

static int
emit_pair(PyObject **bytes, int *offset, int a, int b)
{
Py_ssize_t len = PyBytes_GET_SIZE(*bytes);
if (*offset + 2 >= len) {
if (_PyBytes_Resize(bytes, len * 2) < 0)
return 0;
}
unsigned char *lnotab = (unsigned char *) PyBytes_AS_STRING(*bytes);
lnotab += *offset;
*lnotab++ = a;
*lnotab++ = b;
*offset += 2;
return 1;
}

static int
emit_delta(PyObject **bytes, int bdelta, int ldelta, int *offset)
{
while (bdelta > 255) {
if (!emit_pair(bytes, offset, 255, 0)) {
return 0;
}
bdelta -= 255;
}
while (ldelta > 127) {
if (!emit_pair(bytes, offset, bdelta, 127)) {
return 0;
}
bdelta = 0;
ldelta -= 127;
}
while (ldelta < -128) {
if (!emit_pair(bytes, offset, bdelta, -128)) {
return 0;
}
bdelta = 0;
ldelta += 128;
}
return emit_pair(bytes, offset, bdelta, ldelta);
}

static PyObject *
decode_linetable(PyCodeObject *code)
{
PyCodeAddressRange bounds;
PyObject *bytes;
int table_offset = 0;
int code_offset = 0;
int line = code->co_firstlineno;
bytes = PyBytes_FromStringAndSize(NULL, 64);
if (bytes == NULL) {
return NULL;
}
_PyCode_InitAddressRange(code, &bounds);
while (_PyLineTable_NextAddressRange(&bounds)) {
if (bounds.opaque.computed_line != line) {
int bdelta = bounds.ar_start - code_offset;
int ldelta = bounds.opaque.computed_line - line;
if (!emit_delta(&bytes, bdelta, ldelta, &table_offset)) {
Py_DECREF(bytes);
return NULL;
}
code_offset = bounds.ar_start;
line = bounds.opaque.computed_line;
}
}
_PyBytes_Resize(&bytes, table_offset);
return bytes;
}


typedef struct {
PyObject_HEAD
Expand Down Expand Up @@ -1810,6 +1881,12 @@ static PyMemberDef code_memberlist[] = {
};


static PyObject *
code_getlnotab(PyCodeObject *code, void *closure)
{
return decode_linetable(code);
}

static PyObject *
code_getvarnames(PyCodeObject *code, void *closure)
{
Expand Down Expand Up @@ -1842,6 +1919,7 @@ code_getcode(PyCodeObject *code, void *closure)
}

static PyGetSetDef code_getsetlist[] = {
{"co_lnotab", (getter)code_getlnotab, NULL, NULL},
{"_co_code_adaptive", (getter)code_getcodeadaptive, NULL, NULL},
// The following old names are kept for backward compatibility.
{"co_varnames", (getter)code_getvarnames, NULL, NULL},
Expand Down
Loading

0 comments on commit dd65849

Please sign in to comment.