Skip to content

Commit

Permalink
Merge branch 'main' into docs-floating-point
Browse files Browse the repository at this point in the history
  • Loading branch information
serhiy-storchaka committed Jul 18, 2024
2 parents f57032a + 94e6644 commit 3069f43
Show file tree
Hide file tree
Showing 19 changed files with 533 additions and 298 deletions.
14 changes: 14 additions & 0 deletions Doc/library/unittest.mock.rst
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,20 @@ object::
3
>>> p.assert_called_once_with()

.. caution::

If an :exc:`AttributeError` is raised by :class:`PropertyMock`,
it will be interpreted as a missing descriptor and
:meth:`~object.__getattr__` will be called on the parent mock::

>>> m = MagicMock()
>>> no_attribute = PropertyMock(side_effect=AttributeError)
>>> type(m).my_property = no_attribute
>>> m.my_property
<MagicMock name='mock.my_property' id='140165240345424'>

See :meth:`~object.__getattr__` for details.


.. class:: AsyncMock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, unsafe=False, **kwargs)

Expand Down
45 changes: 25 additions & 20 deletions Include/internal/pycore_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ typedef struct _PyInterpreterFrame {
PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */
PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */
_Py_CODEUNIT *instr_ptr; /* Instruction currently executing (or about to begin) */
int stacktop; /* Offset of TOS from localsplus */
_PyStackRef *stackpointer;
uint16_t return_offset; /* Only relevant during a function call */
char owner;
/* Locals and stack */
Expand All @@ -88,20 +88,20 @@ static inline _PyStackRef *_PyFrame_Stackbase(_PyInterpreterFrame *f) {
}

static inline _PyStackRef _PyFrame_StackPeek(_PyInterpreterFrame *f) {
assert(f->stacktop > _PyFrame_GetCode(f)->co_nlocalsplus);
assert(!PyStackRef_IsNull(f->localsplus[f->stacktop-1]));
return f->localsplus[f->stacktop-1];
assert(f->stackpointer > f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus);
assert(!PyStackRef_IsNull(f->stackpointer[-1]));
return f->stackpointer[-1];
}

static inline _PyStackRef _PyFrame_StackPop(_PyInterpreterFrame *f) {
assert(f->stacktop > _PyFrame_GetCode(f)->co_nlocalsplus);
f->stacktop--;
return f->localsplus[f->stacktop];
assert(f->stackpointer > f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus);
f->stackpointer--;
return *f->stackpointer;
}

static inline void _PyFrame_StackPush(_PyInterpreterFrame *f, _PyStackRef value) {
f->localsplus[f->stacktop] = value;
f->stacktop++;
*f->stackpointer = value;
f->stackpointer++;
}

#define FRAME_SPECIALS_SIZE ((int)((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *)))
Expand All @@ -117,9 +117,12 @@ _PyFrame_NumSlotsForCodeObject(PyCodeObject *code)

static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
{
assert(src->stacktop >= _PyFrame_GetCode(src)->co_nlocalsplus);
*dest = *src;
for (int i = 1; i < src->stacktop; i++) {
assert(src->stackpointer != NULL);
int stacktop = (int)(src->stackpointer - src->localsplus);
assert(stacktop >= _PyFrame_GetCode(src)->co_nlocalsplus);
dest->stackpointer = dest->localsplus + stacktop;
for (int i = 1; i < stacktop; i++) {
dest->localsplus[i] = src->localsplus[i];
}
// Don't leave a dangling pointer to the old frame when creating generators
Expand All @@ -141,7 +144,7 @@ _PyFrame_Initialize(
frame->f_builtins = func->func_builtins;
frame->f_globals = func->func_globals;
frame->f_locals = locals;
frame->stacktop = code->co_nlocalsplus;
frame->stackpointer = frame->localsplus + code->co_nlocalsplus;
frame->frame_obj = NULL;
frame->instr_ptr = _PyCode_CODE(code);
frame->return_offset = 0;
Expand All @@ -161,22 +164,23 @@ _PyFrame_GetLocalsArray(_PyInterpreterFrame *frame)
return frame->localsplus;
}

/* Fetches the stack pointer, and sets stacktop to -1.
Having stacktop <= 0 ensures that invalid
values are not visible to the cycle GC.
We choose -1 rather than 0 to assist debugging. */
/* Fetches the stack pointer, and sets stackpointer to NULL.
Having stackpointer == NULL ensures that invalid
values are not visible to the cycle GC. */
static inline _PyStackRef*
_PyFrame_GetStackPointer(_PyInterpreterFrame *frame)
{
_PyStackRef *sp = frame->localsplus + frame->stacktop;
frame->stacktop = -1;
assert(frame->stackpointer != NULL);
_PyStackRef *sp = frame->stackpointer;
frame->stackpointer = NULL;
return sp;
}

static inline void
_PyFrame_SetStackPointer(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer)
{
frame->stacktop = (int)(stack_pointer - frame->localsplus);
assert(frame->stackpointer == NULL);
frame->stackpointer = stack_pointer;
}

/* Determine whether a frame is incomplete.
Expand Down Expand Up @@ -304,7 +308,8 @@ _PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int
frame->f_globals = NULL;
#endif
frame->f_locals = NULL;
frame->stacktop = code->co_nlocalsplus + stackdepth;
assert(stackdepth <= code->co_stacksize);
frame->stackpointer = frame->localsplus + code->co_nlocalsplus + stackdepth;
frame->frame_obj = NULL;
frame->instr_ptr = _PyCode_CODE(code);
frame->owner = FRAME_OWNED_BY_THREAD;
Expand Down
1 change: 1 addition & 0 deletions Lib/email/_header_value_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2988,6 +2988,7 @@ def _fold_as_ew(to_encode, lines, maxlen, last_ew, ew_combine_allowed, charset,
excess = len(encoded_word) - remaining_space
lines[-1] += encoded_word
to_encode = to_encode[len(to_encode_word):]
leading_whitespace = ''

if to_encode:
lines.append(' ')
Expand Down
13 changes: 13 additions & 0 deletions Lib/test/test_email/test_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,19 @@ def test_defaults_handle_spaces_between_encoded_words_when_folded(self):
g.flatten(msg)
self.assertEqual(s.getvalue(), expected)

def test_defaults_handle_spaces_when_encoded_words_is_folded_in_middle(self):
source = ('A very long long long long long long long long long long long long '
'long long long long long long long long long long long súmmäry')
expected = ('Subject: A very long long long long long long long long long long long long\n'
' long long long long long long long long long long long =?utf-8?q?s=C3=BAmm?=\n'
' =?utf-8?q?=C3=A4ry?=\n\n').encode('ascii')
msg = EmailMessage()
msg['Subject'] = source
s = io.BytesIO()
g = BytesGenerator(s)
g.flatten(msg)
self.assertEqual(s.getvalue(), expected)

def test_defaults_handle_spaces_at_start_of_subject(self):
source = " Уведомление"
expected = b"Subject: =?utf-8?b?0KPQstC10LTQvtC80LvQtdC90LjQtQ==?=\n\n"
Expand Down
Loading

0 comments on commit 3069f43

Please sign in to comment.