Skip to content
Merged
2 changes: 1 addition & 1 deletion Doc/library/hashlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ a file or file-like object.
Example:

>>> import io, hashlib, hmac
>>> with open(hashlib.__file__, "rb") as f:
>>> with open("library/hashlib.rst", "rb") as f:
... digest = hashlib.file_digest(f, "sha256")
...
>>> digest.hexdigest() # doctest: +ELLIPSIS
Expand Down
7 changes: 6 additions & 1 deletion Doc/tutorial/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
The Python Tutorial
######################

.. Tip:: This tutorial is designed for
*programmers* that are new to the Python language,
**not** *beginners* who are new to programming.

Python is an easy to learn, powerful programming language. It has efficient
high-level data structures and a simple but effective approach to
object-oriented programming. Python's elegant syntax and dynamic typing,
Expand All @@ -21,7 +25,8 @@ implemented in C or C++ (or other languages callable from C). Python is also
suitable as an extension language for customizable applications.

This tutorial introduces the reader informally to the basic concepts and
features of the Python language and system. It helps to have a Python
features of the Python language and system. Be aware that it expects you to
have a basic understanding of programming in general. It helps to have a Python
interpreter handy for hands-on experience, but all examples are self-contained,
so the tutorial can be read off-line as well.

Expand Down
58 changes: 8 additions & 50 deletions Include/internal/pycore_crossinterp.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,71 +335,29 @@ typedef struct _sharedexception {
PyAPI_FUNC(PyObject *) _PyXI_ApplyError(_PyXI_error *err);


typedef struct xi_session _PyXI_session;
typedef struct _sharedns _PyXI_namespace;

PyAPI_FUNC(void) _PyXI_FreeNamespace(_PyXI_namespace *ns);
PyAPI_FUNC(_PyXI_namespace *) _PyXI_NamespaceFromNames(PyObject *names);
PyAPI_FUNC(int) _PyXI_FillNamespaceFromDict(
_PyXI_namespace *ns,
PyObject *nsobj,
_PyXI_session *session);
PyAPI_FUNC(int) _PyXI_ApplyNamespace(
_PyXI_namespace *ns,
PyObject *nsobj,
PyObject *dflt);


// A cross-interpreter session involves entering an interpreter
// (_PyXI_Enter()), doing some work with it, and finally exiting
// that interpreter (_PyXI_Exit()).
// with _PyXI_Enter(), doing some work with it, and finally exiting
// that interpreter with _PyXI_Exit().
//
// At the boundaries of the session, both entering and exiting,
// data may be exchanged between the previous interpreter and the
// target one in a thread-safe way that does not violate the
// isolation between interpreters. This includes setting objects
// in the target's __main__ module on the way in, and capturing
// uncaught exceptions on the way out.
struct xi_session {
// Once a session has been entered, this is the tstate that was
// current before the session. If it is different from cur_tstate
// then we must have switched interpreters. Either way, this will
// be the current tstate once we exit the session.
PyThreadState *prev_tstate;
// Once a session has been entered, this is the current tstate.
// It must be current when the session exits.
PyThreadState *init_tstate;
// This is true if init_tstate needs cleanup during exit.
int own_init_tstate;

// This is true if, while entering the session, init_thread took
// "ownership" of the interpreter's __main__ module. This means
// it is the only thread that is allowed to run code there.
// (Caveat: for now, users may still run exec() against the
// __main__ module's dict, though that isn't advisable.)
int running;
// This is a cached reference to the __dict__ of the entered
// interpreter's __main__ module. It is looked up when at the
// beginning of the session as a convenience.
PyObject *main_ns;

// This is set if the interpreter is entered and raised an exception
// that needs to be handled in some special way during exit.
_PyXI_errcode *error_override;
// This is set if exit captured an exception to propagate.
_PyXI_error *error;

// -- pre-allocated memory --
_PyXI_error _error;
_PyXI_errcode _error_override;
};
typedef struct xi_session _PyXI_session;

PyAPI_FUNC(_PyXI_session *) _PyXI_NewSession(void);
PyAPI_FUNC(void) _PyXI_FreeSession(_PyXI_session *);

PyAPI_FUNC(int) _PyXI_Enter(
_PyXI_session *session,
PyInterpreterState *interp,
PyObject *nsupdates);
PyAPI_FUNC(void) _PyXI_Exit(_PyXI_session *session);

PyAPI_FUNC(PyObject *) _PyXI_GetMainNamespace(_PyXI_session *);

PyAPI_FUNC(PyObject *) _PyXI_ApplyCapturedException(_PyXI_session *session);
PyAPI_FUNC(int) _PyXI_HasCapturedException(_PyXI_session *session);

Expand Down
91 changes: 48 additions & 43 deletions Include/internal/pycore_uop_ids.h

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

26 changes: 23 additions & 3 deletions Include/internal/pycore_uop_metadata.h

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

3 changes: 0 additions & 3 deletions Include/pythonrun.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ PyAPI_DATA(int) (*PyOS_InputHook)(void);
# define PYOS_LOG2_STACK_MARGIN 12
#elif defined(Py_DEBUG) && defined(WIN32)
# define PYOS_LOG2_STACK_MARGIN 12
#elif defined(__wasi__)
/* Web assembly has two stacks, so this isn't really a size */
# define PYOS_LOG2_STACK_MARGIN 9
#else
# define PYOS_LOG2_STACK_MARGIN 11
#endif
Expand Down
20 changes: 20 additions & 0 deletions Lib/test/lock_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,26 @@ class RLockTests(BaseLockTests):
"""
Tests for recursive locks.
"""
def test_repr_count(self):
# see gh-134322: check that count values are correct:
# when a rlock is just created,
# in a second thread when rlock is acquired in the main thread.
lock = self.locktype()
self.assertIn("count=0", repr(lock))
self.assertIn("<unlocked", repr(lock))
lock.acquire()
lock.acquire()
self.assertIn("count=2", repr(lock))
self.assertIn("<locked", repr(lock))

result = []
def call_repr():
result.append(repr(lock))
with Bunch(call_repr, 1):
pass
self.assertIn("count=2", result[0])
self.assertIn("<locked", result[0])

def test_reacquire(self):
lock = self.locktype()
lock.acquire()
Expand Down
20 changes: 16 additions & 4 deletions Lib/test/test_capi/test_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2002,7 +2002,10 @@ def testfunc(n):
self.assertNotIn("_CALL_ISINSTANCE", uops)
self.assertNotIn("_GUARD_THIRD_NULL", uops)
self.assertNotIn("_GUARD_CALLABLE_ISINSTANCE", uops)
self.assertIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops)

def test_call_list_append(self):
def testfunc(n):
Expand Down Expand Up @@ -2035,7 +2038,10 @@ def testfunc(n):
self.assertNotIn("_CALL_ISINSTANCE", uops)
self.assertNotIn("_TO_BOOL_BOOL", uops)
self.assertNotIn("_GUARD_IS_TRUE_POP", uops)
self.assertIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops)

def test_call_isinstance_is_false(self):
def testfunc(n):
Expand All @@ -2053,7 +2059,10 @@ def testfunc(n):
self.assertNotIn("_CALL_ISINSTANCE", uops)
self.assertNotIn("_TO_BOOL_BOOL", uops)
self.assertNotIn("_GUARD_IS_FALSE_POP", uops)
self.assertIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops)

def test_call_isinstance_subclass(self):
def testfunc(n):
Expand All @@ -2071,7 +2080,10 @@ def testfunc(n):
self.assertNotIn("_CALL_ISINSTANCE", uops)
self.assertNotIn("_TO_BOOL_BOOL", uops)
self.assertNotIn("_GUARD_IS_TRUE_POP", uops)
self.assertIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops)
self.assertNotIn("_POP_CALL_TWO_LOAD_CONST_INLINE_BORROW", uops)

def test_call_isinstance_unknown_object(self):
def testfunc(n):
Expand Down
3 changes: 3 additions & 0 deletions Lib/test/test_copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ def test_deepcopy_list(self):
self.assertIsNot(x[0], y[0])

@support.skip_emscripten_stack_overflow()
@support.skip_wasi_stack_overflow()
def test_deepcopy_reflexive_list(self):
x = []
x.append(x)
Expand Down Expand Up @@ -400,6 +401,7 @@ def test_deepcopy_tuple_of_immutables(self):
self.assertIs(x, y)

@support.skip_emscripten_stack_overflow()
@support.skip_wasi_stack_overflow()
def test_deepcopy_reflexive_tuple(self):
x = ([],)
x[0].append(x)
Expand All @@ -418,6 +420,7 @@ def test_deepcopy_dict(self):
self.assertIsNot(x["foo"], y["foo"])

@support.skip_emscripten_stack_overflow()
@support.skip_wasi_stack_overflow()
def test_deepcopy_reflexive_dict(self):
x = {}
x['foo'] = x
Expand Down
Loading
Loading