Skip to content

Commit

Permalink
Merge branch 'main' into inlinecomp2
Browse files Browse the repository at this point in the history
* main:
  pythongh-101810: Remove duplicated st_ino calculation (pythonGH-101811)
  pythongh-92547: Purge sqlite3_enable_shared_cache() detection from configure (python#101873)
  pythonGH-100987: Refactor `_PyInterpreterFrame` a bit, to assist generator improvement. (pythonGH-100988)
  pythonGH-87849: Simplify stack effect of SEND and specialize it for generators and coroutines. (pythonGH-101788)
  Correct trivial grammar in reset_mock docs (python#101861)
  pythongh-101845: pyspecific: Fix i18n for availability directive (pythonGH-101846)
  pythongh-89792: Limit test_tools freeze test build parallelism based on the number of cores (python#101841)
  pythongh-85984: Utilize new "winsize" functions from termios in pty tests. (python#101831)
  pythongh-89792: Prevent test_tools from copying 1000M of "source" in freeze test (python#101837)
  Fix typo in test_fstring.py (python#101823)
  pythonGH-101797: allocate `PyExpat_CAPI` capsule on heap (python#101798)
  pythongh-101390: Fix docs for `imporlib.util.LazyLoader.factory` to properly call it a class method (pythonGH-101391)
  • Loading branch information
carljm committed Feb 13, 2023
2 parents 36b2917 + 95cbb3d commit ae0bd02
Show file tree
Hide file tree
Showing 28 changed files with 306 additions and 272 deletions.
2 changes: 1 addition & 1 deletion Doc/library/importlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1387,7 +1387,7 @@ an :term:`importer`.

.. classmethod:: factory(loader)

A static method which returns a callable that creates a lazy loader. This
A class method which returns a callable that creates a lazy loader. This
is meant to be used in situations where the loader is passed by class
instead of by instance.
::
Expand Down
6 changes: 3 additions & 3 deletions Doc/library/unittest.mock.rst
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ the *new_callable* argument to :func:`patch`.
False

.. versionchanged:: 3.6
Added two keyword only argument to the reset_mock function.
Added two keyword-only arguments to the reset_mock function.

This can be useful where you want to make a series of assertions that
reuse the same object. Note that :meth:`reset_mock` *doesn't* clear the
Expand All @@ -416,8 +416,8 @@ the *new_callable* argument to :func:`patch`.
parameter as ``True``. Child mocks and the return value mock
(if any) are reset as well.

.. note:: *return_value*, and :attr:`side_effect` are keyword only
argument.
.. note:: *return_value*, and :attr:`side_effect` are keyword-only
arguments.


.. method:: mock_add_spec(spec, spec_set=False)
Expand Down
20 changes: 11 additions & 9 deletions Doc/tools/extensions/pyspecific.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from sphinx.environment import NoUri
from sphinx.locale import _ as sphinx_gettext
from sphinx.util import status_iterator, logging
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import split_explicit_title
from sphinx.writers.text import TextWriter, TextTranslator

Expand Down Expand Up @@ -119,7 +120,7 @@ def run(self):

# Support for documenting platform availability

class Availability(Directive):
class Availability(SphinxDirective):

has_content = True
required_arguments = 1
Expand All @@ -139,18 +140,19 @@ class Availability(Directive):

def run(self):
availability_ref = ':ref:`Availability <availability>`: '
avail_nodes, avail_msgs = self.state.inline_text(
availability_ref + self.arguments[0],
self.lineno)
pnode = nodes.paragraph(availability_ref + self.arguments[0],
classes=["availability"],)
n, m = self.state.inline_text(availability_ref, self.lineno)
pnode.extend(n + m)
n, m = self.state.inline_text(self.arguments[0], self.lineno)
pnode.extend(n + m)
'', *avail_nodes, *avail_msgs)
self.set_source_info(pnode)
cnode = nodes.container("", pnode, classes=["availability"])
self.set_source_info(cnode)
if self.content:
self.state.nested_parse(self.content, self.content_offset, pnode)

self.state.nested_parse(self.content, self.content_offset, cnode)
self.parse_platforms()

return [pnode]
return [cnode]

def parse_platforms(self):
"""Parse platform information from arguments
Expand Down
7 changes: 7 additions & 0 deletions Include/internal/pycore_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ typedef struct {

#define INLINE_CACHE_ENTRIES_FOR_ITER CACHE_ENTRIES(_PyForIterCache)

typedef struct {
uint16_t counter;
} _PySendCache;

#define INLINE_CACHE_ENTRIES_SEND CACHE_ENTRIES(_PySendCache)

// Borrowed references to common callables:
struct callable_cache {
PyObject *isinstance;
Expand Down Expand Up @@ -233,6 +239,7 @@ extern void _Py_Specialize_CompareAndBranch(PyObject *lhs, PyObject *rhs,
extern void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr,
int oparg);
extern void _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int oparg);
extern void _Py_Specialize_Send(PyObject *receiver, _Py_CODEUNIT *instr);

/* Finalizer function for static codeobjects used in deepfreeze.py */
extern void _PyStaticCode_Fini(PyCodeObject *co);
Expand Down
6 changes: 2 additions & 4 deletions Include/internal/pycore_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,13 @@ enum _frameowner {
};

typedef struct _PyInterpreterFrame {
/* "Specials" section */
PyCodeObject *f_code; /* Strong reference */
struct _PyInterpreterFrame *previous;
PyObject *f_funcobj; /* Strong reference. Only valid if not on C stack */
PyObject *f_globals; /* Borrowed reference. Only valid if not on C stack */
PyObject *f_builtins; /* Borrowed reference. Only valid if not on C stack */
PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */
PyCodeObject *f_code; /* Strong reference */
PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */
/* Linkage section */
struct _PyInterpreterFrame *previous;
// NOTE: This is not necessarily the last instruction started in the given
// frame. Rather, it is the code unit *prior to* the *next* instruction. For
// example, it may be an inline CACHE entry, an instruction we just jumped
Expand Down
5 changes: 3 additions & 2 deletions Include/internal/pycore_opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Include/opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions Lib/dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
BINARY_OP = opmap['BINARY_OP']
JUMP_BACKWARD = opmap['JUMP_BACKWARD']
FOR_ITER = opmap['FOR_ITER']
SEND = opmap['SEND']
LOAD_ATTR = opmap['LOAD_ATTR']

CACHE = opmap["CACHE"]
Expand Down Expand Up @@ -453,6 +454,7 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
argrepr = ''
positions = Positions(*next(co_positions, ()))
deop = _deoptop(op)
caches = _inline_cache_entries[deop]
if arg is not None:
# Set argval to the dereferenced value of the argument when
# available, and argrepr to the string representation of argval.
Expand All @@ -478,8 +480,7 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
elif deop in hasjrel:
signed_arg = -arg if _is_backward_jump(deop) else arg
argval = offset + 2 + signed_arg*2
if deop == FOR_ITER:
argval += 2
argval += 2 * caches
argrepr = "to " + repr(argval)
elif deop in haslocal or deop in hasfree:
argval, argrepr = _get_name_info(arg, varname_from_oparg)
Expand Down Expand Up @@ -633,12 +634,12 @@ def findlabels(code):
for offset, op, arg in _unpack_opargs(code):
if arg is not None:
deop = _deoptop(op)
caches = _inline_cache_entries[deop]
if deop in hasjrel:
if _is_backward_jump(deop):
arg = -arg
label = offset + 2 + arg*2
if deop == FOR_ITER:
label += 2
label += 2 * caches
elif deop in hasjabs:
label = arg*2
else:
Expand Down
5 changes: 3 additions & 2 deletions Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,8 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.12a5 3516 (Add COMPARE_AND_BRANCH instruction)
# Python 3.12a5 3517 (Change YIELD_VALUE oparg to exception block depth)
# Python 3.12a5 3518 (Add RETURN_CONST instruction)
# Python 3.12a5 3519 (Inline list/dict/set comprehensions)
# Python 3.12a5 3519 (Modify SEND instruction)
# Python 3.12a5 3520 (Inline list/dict/set comprehensions)

# Python 3.13 will start with 3550

Expand All @@ -445,7 +446,7 @@ def _write_atomic(path, data, mode=0o666):
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.

MAGIC_NUMBER = (3519).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3520).to_bytes(2, 'little') + b'\r\n'

_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c

Expand Down
8 changes: 7 additions & 1 deletion Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def pseudo_op(name, op, real_ops):
def_op('RETURN_CONST', 121)
hasconst.append(121)
def_op('BINARY_OP', 122)
jrel_op('SEND', 123) # Number of bytes to skip
jrel_op('SEND', 123) # Number of words to skip
def_op('LOAD_FAST', 124) # Local variable number, no null check
haslocal.append(124)
def_op('STORE_FAST', 125) # Local variable number
Expand Down Expand Up @@ -374,6 +374,9 @@ def pseudo_op(name, op, real_ops):
"UNPACK_SEQUENCE_TUPLE",
"UNPACK_SEQUENCE_TWO_TUPLE",
],
"SEND": [
"SEND_GEN",
],
}
_specialized_instructions = [
opcode for family in _specializations.values() for opcode in family
Expand Down Expand Up @@ -433,6 +436,9 @@ def pseudo_op(name, op, real_ops):
"STORE_SUBSCR": {
"counter": 1,
},
"SEND": {
"counter": 1,
},
}

_inline_cache_entries = [
Expand Down
25 changes: 15 additions & 10 deletions Lib/test/test_dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,11 +475,13 @@ async def _asyncwith(c):
BEFORE_ASYNC_WITH
GET_AWAITABLE 1
LOAD_CONST 0 (None)
>> SEND 3 (to 22)
>> SEND 3 (to 24)
YIELD_VALUE 2
RESUME 3
JUMP_BACKWARD_NO_INTERRUPT 4 (to 14)
>> POP_TOP
JUMP_BACKWARD_NO_INTERRUPT 5 (to 14)
>> SWAP 2
POP_TOP
POP_TOP
%3d LOAD_CONST 1 (1)
STORE_FAST 1 (x)
Expand All @@ -490,30 +492,33 @@ async def _asyncwith(c):
CALL 2
GET_AWAITABLE 2
LOAD_CONST 0 (None)
>> SEND 3 (to 56)
>> SEND 3 (to 64)
YIELD_VALUE 2
RESUME 3
JUMP_BACKWARD_NO_INTERRUPT 4 (to 48)
JUMP_BACKWARD_NO_INTERRUPT 5 (to 54)
>> POP_TOP
POP_TOP
%3d LOAD_CONST 2 (2)
STORE_FAST 2 (y)
RETURN_CONST 0 (None)
%3d >> CLEANUP_THROW
JUMP_BACKWARD 23 (to 22)
JUMP_BACKWARD 27 (to 24)
>> CLEANUP_THROW
JUMP_BACKWARD 8 (to 56)
JUMP_BACKWARD 9 (to 64)
>> PUSH_EXC_INFO
WITH_EXCEPT_START
GET_AWAITABLE 2
LOAD_CONST 0 (None)
>> SEND 4 (to 90)
>> SEND 4 (to 102)
YIELD_VALUE 3
RESUME 3
JUMP_BACKWARD_NO_INTERRUPT 4 (to 80)
JUMP_BACKWARD_NO_INTERRUPT 5 (to 90)
>> CLEANUP_THROW
>> POP_JUMP_IF_TRUE 1 (to 94)
>> SWAP 2
POP_TOP
POP_JUMP_IF_TRUE 1 (to 110)
RERAISE 2
>> POP_TOP
POP_EXCEPT
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_fstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ def test_missing_expression(self):
"f'''{\t\f\r\n}'''",
])

# Different error messages are raised when a specfier ('!', ':' or '=') is used after an empty expression
# Different error messages are raised when a specifier ('!', ':' or '=') is used after an empty expression
self.assertAllRaise(SyntaxError, "f-string: expression required before '!'",
["f'{!r}'",
"f'{ !r}'",
Expand Down
Loading

0 comments on commit ae0bd02

Please sign in to comment.