Skip to content

Commit 10ee198

Browse files
committed
Merge branch 'main' into monitoring-branch-taken
2 parents 8ea64b2 + 427b106 commit 10ee198

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1081
-454
lines changed

Doc/deprecations/pending-removal-in-3.16.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@ Pending Removal in Python 3.16
88
* :mod:`symtable`:
99
Deprecate :meth:`symtable.Class.get_methods` due to the lack of interest.
1010
(Contributed by Bénédikt Tran in :gh:`119698`.)
11+
12+
* :mod:`shutil`: Deprecate :class:`!shutil.ExecError`, which hasn't
13+
been raised by any :mod:`!shutil` function since Python 3.4. It's
14+
now an alias for :exc:`RuntimeError`.
15+

Doc/library/dis.rst

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ interpreter.
5656
for jump targets and exception handlers. The ``-O`` command line
5757
option and the ``show_offsets`` argument were added.
5858

59+
.. versionchanged:: 3.14
60+
The :option:`-P <dis --show-positions>` command-line option
61+
and the ``show_positions`` argument were added.
62+
5963
Example: Given the function :func:`!myfunc`::
6064

6165
def myfunc(alist):
@@ -85,7 +89,7 @@ The :mod:`dis` module can be invoked as a script from the command line:
8589

8690
.. code-block:: sh
8791
88-
python -m dis [-h] [-C] [-O] [infile]
92+
python -m dis [-h] [-C] [-O] [-P] [infile]
8993
9094
The following options are accepted:
9195

@@ -103,6 +107,10 @@ The following options are accepted:
103107

104108
Show offsets of instructions.
105109

110+
.. cmdoption:: -P, --show-positions
111+
112+
Show positions of instructions in the source code.
113+
106114
If :file:`infile` is specified, its disassembled code will be written to stdout.
107115
Otherwise, disassembly is performed on compiled source code received from stdin.
108116

@@ -116,7 +124,8 @@ The bytecode analysis API allows pieces of Python code to be wrapped in a
116124
code.
117125

118126
.. class:: Bytecode(x, *, first_line=None, current_offset=None,\
119-
show_caches=False, adaptive=False, show_offsets=False)
127+
show_caches=False, adaptive=False, show_offsets=False,\
128+
show_positions=False)
120129

121130
Analyse the bytecode corresponding to a function, generator, asynchronous
122131
generator, coroutine, method, string of source code, or a code object (as
@@ -144,6 +153,9 @@ code.
144153
If *show_offsets* is ``True``, :meth:`.dis` will include instruction
145154
offsets in the output.
146155

156+
If *show_positions* is ``True``, :meth:`.dis` will include instruction
157+
source code positions in the output.
158+
147159
.. classmethod:: from_traceback(tb, *, show_caches=False)
148160

149161
Construct a :class:`Bytecode` instance from the given traceback, setting
@@ -173,6 +185,12 @@ code.
173185
.. versionchanged:: 3.11
174186
Added the *show_caches* and *adaptive* parameters.
175187

188+
.. versionchanged:: 3.13
189+
Added the *show_offsets* parameter
190+
191+
.. versionchanged:: 3.14
192+
Added the *show_positions* parameter.
193+
176194
Example:
177195

178196
.. doctest::
@@ -226,7 +244,8 @@ operation is being performed, so the intermediate analysis object isn't useful:
226244
Added *file* parameter.
227245

228246

229-
.. function:: dis(x=None, *, file=None, depth=None, show_caches=False, adaptive=False)
247+
.. function:: dis(x=None, *, file=None, depth=None, show_caches=False,\
248+
adaptive=False, show_offsets=False, show_positions=False)
230249

231250
Disassemble the *x* object. *x* can denote either a module, a class, a
232251
method, a function, a generator, an asynchronous generator, a coroutine,
@@ -265,9 +284,14 @@ operation is being performed, so the intermediate analysis object isn't useful:
265284
.. versionchanged:: 3.11
266285
Added the *show_caches* and *adaptive* parameters.
267286

287+
.. versionchanged:: 3.13
288+
Added the *show_offsets* parameter.
289+
290+
.. versionchanged:: 3.14
291+
Added the *show_positions* parameter.
268292

269-
.. function:: distb(tb=None, *, file=None, show_caches=False, adaptive=False,
270-
show_offset=False)
293+
.. function:: distb(tb=None, *, file=None, show_caches=False, adaptive=False,\
294+
show_offset=False, show_positions=False)
271295

272296
Disassemble the top-of-stack function of a traceback, using the last
273297
traceback if none was passed. The instruction causing the exception is
@@ -285,14 +309,19 @@ operation is being performed, so the intermediate analysis object isn't useful:
285309
.. versionchanged:: 3.13
286310
Added the *show_offsets* parameter.
287311

312+
.. versionchanged:: 3.14
313+
Added the *show_positions* parameter.
314+
288315
.. function:: disassemble(code, lasti=-1, *, file=None, show_caches=False, adaptive=False)
289-
disco(code, lasti=-1, *, file=None, show_caches=False, adaptive=False,
290-
show_offsets=False)
316+
disco(code, lasti=-1, *, file=None, show_caches=False, adaptive=False,\
317+
show_offsets=False, show_positions=False)
291318
292319
Disassemble a code object, indicating the last instruction if *lasti* was
293320
provided. The output is divided in the following columns:
294321

295-
#. the line number, for the first instruction of each line
322+
#. the source code location of the instruction. Complete location information
323+
is shown if *show_positions* is true. Otherwise (the default) only the
324+
line number is displayed.
296325
#. the current instruction, indicated as ``-->``,
297326
#. a labelled instruction, indicated with ``>>``,
298327
#. the address of the instruction,
@@ -315,6 +344,9 @@ operation is being performed, so the intermediate analysis object isn't useful:
315344
.. versionchanged:: 3.13
316345
Added the *show_offsets* parameter.
317346

347+
.. versionchanged:: 3.14
348+
Added the *show_positions* parameter.
349+
318350
.. function:: get_instructions(x, *, first_line=None, show_caches=False, adaptive=False)
319351

320352
Return an iterator over the instructions in the supplied function, method,

Doc/whatsnew/3.14.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,22 @@ ast
110110

111111
(Contributed by Bénédikt Tran in :gh:`121141`.)
112112

113+
dis
114+
---
115+
116+
* Added support for rendering full source location information of
117+
:class:`instructions <dis.Instruction>`, rather than only the line number.
118+
This feature is added to the following interfaces via the ``show_positions``
119+
keyword argument:
120+
121+
- :class:`dis.Bytecode`,
122+
- :func:`dis.dis`, :func:`dis.distb`, and
123+
- :func:`dis.disassemble`.
124+
125+
This feature is also exposed via :option:`dis --show-positions`.
126+
127+
(Contributed by Bénédikt Tran in :gh:`123165`.)
128+
113129
fractions
114130
---------
115131

Include/internal/pycore_code.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,10 @@ extern int _PyInstruction_GetLength(PyCodeObject *code, int offset);
595595

596596
extern PyObject *_PyInstrumentation_BranchesIterator(PyCodeObject *code);
597597

598+
struct _PyCode8 _PyCode_DEF(8);
599+
600+
PyAPI_DATA(const struct _PyCode8) _Py_InitCleanup;
601+
598602
#ifdef __cplusplus
599603
}
600604
#endif

Include/internal/pycore_frame.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *
144144
static inline void
145145
_PyFrame_Initialize(
146146
_PyInterpreterFrame *frame, PyFunctionObject *func,
147-
PyObject *locals, PyCodeObject *code, int null_locals_from)
147+
PyObject *locals, PyCodeObject *code, int null_locals_from, _PyInterpreterFrame *previous)
148148
{
149+
frame->previous = previous;
149150
frame->f_funcobj = (PyObject *)func;
150151
frame->f_executable = Py_NewRef(code);
151152
frame->f_builtins = func->func_builtins;
@@ -298,26 +299,27 @@ PyAPI_FUNC(void) _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFr
298299
* Must be guarded by _PyThreadState_HasStackSpace()
299300
* Consumes reference to func. */
300301
static inline _PyInterpreterFrame *
301-
_PyFrame_PushUnchecked(PyThreadState *tstate, PyFunctionObject *func, int null_locals_from)
302+
_PyFrame_PushUnchecked(PyThreadState *tstate, PyFunctionObject *func, int null_locals_from, _PyInterpreterFrame * previous)
302303
{
303304
CALL_STAT_INC(frames_pushed);
304305
PyCodeObject *code = (PyCodeObject *)func->func_code;
305306
_PyInterpreterFrame *new_frame = (_PyInterpreterFrame *)tstate->datastack_top;
306307
tstate->datastack_top += code->co_framesize;
307308
assert(tstate->datastack_top < tstate->datastack_limit);
308-
_PyFrame_Initialize(new_frame, func, NULL, code, null_locals_from);
309+
_PyFrame_Initialize(new_frame, func, NULL, code, null_locals_from, previous);
309310
return new_frame;
310311
}
311312

312313
/* Pushes a trampoline frame without checking for space.
313314
* Must be guarded by _PyThreadState_HasStackSpace() */
314315
static inline _PyInterpreterFrame *
315-
_PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int stackdepth)
316+
_PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int stackdepth, _PyInterpreterFrame * previous)
316317
{
317318
CALL_STAT_INC(frames_pushed);
318319
_PyInterpreterFrame *frame = (_PyInterpreterFrame *)tstate->datastack_top;
319320
tstate->datastack_top += code->co_framesize;
320321
assert(tstate->datastack_top < tstate->datastack_limit);
322+
frame->previous = previous;
321323
frame->f_funcobj = Py_None;
322324
frame->f_executable = Py_NewRef(code);
323325
#ifdef Py_DEBUG
@@ -344,7 +346,8 @@ _PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int
344346
PyAPI_FUNC(_PyInterpreterFrame *)
345347
_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
346348
PyObject *locals, _PyStackRef const* args,
347-
size_t argcount, PyObject *kwnames);
349+
size_t argcount, PyObject *kwnames,
350+
_PyInterpreterFrame *previous);
348351

349352
#ifdef __cplusplus
350353
}

Include/internal/pycore_object.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ static inline int _PyType_SUPPORTS_WEAKREFS(PyTypeObject *type) {
761761
}
762762

763763
extern PyObject* _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems);
764-
extern PyObject *_PyType_NewManagedObject(PyTypeObject *type);
764+
PyAPI_FUNC(PyObject *) _PyType_NewManagedObject(PyTypeObject *type);
765765

766766
extern PyTypeObject* _PyType_CalculateMetaclass(PyTypeObject *, PyObject *);
767767
extern PyObject* _PyType_GetDocFromInternalDoc(const char *, const char *);
@@ -803,10 +803,11 @@ _PyObject_GetManagedDict(PyObject *obj)
803803
static inline PyDictValues *
804804
_PyObject_InlineValues(PyObject *obj)
805805
{
806+
PyTypeObject *tp = Py_TYPE(obj);
807+
assert(tp->tp_basicsize > 0 && tp->tp_basicsize % sizeof(PyObject *) == 0);
806808
assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES);
807809
assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
808-
assert(Py_TYPE(obj)->tp_basicsize == sizeof(PyObject));
809-
return (PyDictValues *)((char *)obj + sizeof(PyObject));
810+
return (PyDictValues *)((char *)obj + tp->tp_basicsize);
810811
}
811812

812813
extern PyObject ** _PyObject_ComputedDictPointer(PyObject *);

Include/internal/pycore_opcode_metadata.h

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)