Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/python/cpython into issue11…
Browse files Browse the repository at this point in the history
…5979-test_importlib-wasi-sdk-21
  • Loading branch information
brettcannon committed Mar 13, 2024
2 parents 786adbc + 7f418fb commit 8db8e1c
Show file tree
Hide file tree
Showing 39 changed files with 709 additions and 423 deletions.
11 changes: 8 additions & 3 deletions Doc/faq/design.rst
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,11 @@ is evaluated in all cases.
Why isn't there a switch or case statement in Python?
-----------------------------------------------------

You can do this easily enough with a sequence of ``if... elif... elif... else``.
For literal values, or constants within a namespace, you can also use a
``match ... case`` statement.
In general, structured switch statements execute one block of code
when an expression has a particular value or set of values.
Since Python 3.10 one can easily match literal values, or constants
within a namespace, with a ``match ... case`` statement.
An older alternative is a sequence of ``if... elif... elif... else``.

For cases where you need to choose from a very large number of possibilities,
you can create a dictionary mapping case values to functions to call. For
Expand Down Expand Up @@ -290,6 +292,9 @@ It's suggested that you use a prefix for the method names, such as ``visit_`` in
this example. Without such a prefix, if values are coming from an untrusted
source, an attacker would be able to call any method on your object.

Imitating switch with fallthrough, as with C's switch-case-default,
is possible, much harder, and less needed.


Can't you emulate threads in the interpreter instead of relying on an OS-specific thread implementation?
--------------------------------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion Doc/faq/extending.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ to learn Python's C API.
If you need to interface to some C or C++ library for which no Python extension
currently exists, you can try wrapping the library's data types and functions
with a tool such as `SWIG <https://www.swig.org>`_. `SIP
<https://riverbankcomputing.com/software/sip/intro>`__, `CXX
<https://github.com/Python-SIP/sip>`__, `CXX
<https://cxx.sourceforge.net/>`_ `Boost
<https://www.boost.org/libs/python/doc/index.html>`_, or `Weave
<https://github.com/scipy/weave>`_ are also
Expand Down
49 changes: 36 additions & 13 deletions Doc/howto/logging-cookbook.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3418,9 +3418,10 @@ The worker thread is implemented using Qt's ``QThread`` class rather than the
:mod:`threading` module, as there are circumstances where one has to use
``QThread``, which offers better integration with other ``Qt`` components.

The code should work with recent releases of either ``PySide2`` or ``PyQt5``.
You should be able to adapt the approach to earlier versions of Qt. Please
refer to the comments in the code snippet for more detailed information.
The code should work with recent releases of either ``PySide6``, ``PyQt6``,
``PySide2`` or ``PyQt5``. You should be able to adapt the approach to earlier
versions of Qt. Please refer to the comments in the code snippet for more
detailed information.

.. code-block:: python3
Expand All @@ -3430,16 +3431,25 @@ refer to the comments in the code snippet for more detailed information.
import sys
import time
# Deal with minor differences between PySide2 and PyQt5
# Deal with minor differences between different Qt packages
try:
from PySide2 import QtCore, QtGui, QtWidgets
from PySide6 import QtCore, QtGui, QtWidgets
Signal = QtCore.Signal
Slot = QtCore.Slot
except ImportError:
from PyQt5 import QtCore, QtGui, QtWidgets
Signal = QtCore.pyqtSignal
Slot = QtCore.pyqtSlot
try:
from PyQt6 import QtCore, QtGui, QtWidgets
Signal = QtCore.pyqtSignal
Slot = QtCore.pyqtSlot
except ImportError:
try:
from PySide2 import QtCore, QtGui, QtWidgets
Signal = QtCore.Signal
Slot = QtCore.Slot
except ImportError:
from PyQt5 import QtCore, QtGui, QtWidgets
Signal = QtCore.pyqtSignal
Slot = QtCore.pyqtSlot
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -3511,8 +3521,14 @@ refer to the comments in the code snippet for more detailed information.
while not QtCore.QThread.currentThread().isInterruptionRequested():
delay = 0.5 + random.random() * 2
time.sleep(delay)
level = random.choice(LEVELS)
logger.log(level, 'Message after delay of %3.1f: %d', delay, i, extra=extra)
try:
if random.random() < 0.1:
raise ValueError('Exception raised: %d' % i)
else:
level = random.choice(LEVELS)
logger.log(level, 'Message after delay of %3.1f: %d', delay, i, extra=extra)
except ValueError as e:
logger.exception('Failed: %s', e, extra=extra)
i += 1
#
Expand All @@ -3539,7 +3555,10 @@ refer to the comments in the code snippet for more detailed information.
self.textedit = te = QtWidgets.QPlainTextEdit(self)
# Set whatever the default monospace font is for the platform
f = QtGui.QFont('nosuchfont')
f.setStyleHint(f.Monospace)
if hasattr(f, 'Monospace'):
f.setStyleHint(f.Monospace)
else:
f.setStyleHint(f.StyleHint.Monospace) # for Qt6
te.setFont(f)
te.setReadOnly(True)
PB = QtWidgets.QPushButton
Expand Down Expand Up @@ -3626,7 +3645,11 @@ refer to the comments in the code snippet for more detailed information.
app = QtWidgets.QApplication(sys.argv)
example = Window(app)
example.show()
sys.exit(app.exec_())
if hasattr(app, 'exec'):
rc = app.exec()
else:
rc = app.exec_()
sys.exit(rc)
if __name__=='__main__':
main()
Expand Down
118 changes: 41 additions & 77 deletions Doc/howto/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ or *severity*.
When to use logging
^^^^^^^^^^^^^^^^^^^

Logging provides a set of convenience functions for simple logging usage. These
are :func:`debug`, :func:`info`, :func:`warning`, :func:`error` and
:func:`critical`. To determine when to use logging, see the table below, which
states, for each of a set of common tasks, the best tool to use for it.
You can access logging functionality by creating a logger via ``logger =
getLogger(__name__)``, and then calling the logger's :meth:`~Logger.debug`,
:meth:`~Logger.info`, :meth:`~Logger.warning`, :meth:`~Logger.error` and
:meth:`~Logger.critical` methods. To determine when to use logging, and to see
which logger methods to use when, see the table below. It states, for each of a
set of common tasks, the best tool to use for that task.

+-------------------------------------+--------------------------------------+
| Task you want to perform | The best tool for the task |
Expand All @@ -37,8 +39,8 @@ states, for each of a set of common tasks, the best tool to use for it.
| usage of a command line script or | |
| program | |
+-------------------------------------+--------------------------------------+
| Report events that occur during | :func:`logging.info` (or |
| normal operation of a program (e.g. | :func:`logging.debug` for very |
| Report events that occur during | A logger's :meth:`~Logger.info` (or |
| normal operation of a program (e.g. | :meth:`~Logger.debug` method for very|
| for status monitoring or fault | detailed output for diagnostic |
| investigation) | purposes) |
+-------------------------------------+--------------------------------------+
Expand All @@ -47,22 +49,23 @@ states, for each of a set of common tasks, the best tool to use for it.
| | the client application should be |
| | modified to eliminate the warning |
| | |
| | :func:`logging.warning` if there is |
| | nothing the client application can do|
| | about the situation, but the event |
| | should still be noted |
| | A logger's :meth:`~Logger.warning` |
| | method if there is nothing the client|
| | application can do about the |
| | situation, but the event should still|
| | be noted |
+-------------------------------------+--------------------------------------+
| Report an error regarding a | Raise an exception |
| particular runtime event | |
+-------------------------------------+--------------------------------------+
| Report suppression of an error | :func:`logging.error`, |
| without raising an exception (e.g. | :func:`logging.exception` or |
| error handler in a long-running | :func:`logging.critical` as |
| Report suppression of an error | A logger's :meth:`~Logger.error`, |
| without raising an exception (e.g. | :meth:`~Logger.exception` or |
| error handler in a long-running | :meth:`~Logger.critical` method as |
| server process) | appropriate for the specific error |
| | and application domain |
+-------------------------------------+--------------------------------------+

The logging functions are named after the level or severity of the events
The logger methods are named after the level or severity of the events
they are used to track. The standard levels and their applicability are
described below (in increasing order of severity):

Expand Down Expand Up @@ -115,12 +118,18 @@ If you type these lines into a script and run it, you'll see:
WARNING:root:Watch out!
printed out on the console. The ``INFO`` message doesn't appear because the
default level is ``WARNING``. The printed message includes the indication of
the level and the description of the event provided in the logging call, i.e.
'Watch out!'. Don't worry about the 'root' part for now: it will be explained
later. The actual output can be formatted quite flexibly if you need that;
formatting options will also be explained later.

default level is ``WARNING``. The printed message includes the indication of the
level and the description of the event provided in the logging call, i.e.
'Watch out!'. The actual output can be formatted quite flexibly if you need
that; formatting options will also be explained later.

Notice that in this example, we use functions directly on the ``logging``
module, like ``logging.debug``, rather than creating a logger and calling
functions on it. These functions operation on the root logger, but can be useful
as they will call :func:`~logging.basicConfig` for you if it has not been called yet, like in
this example. In larger programs you'll usually want to control the logging
configuration explicitly however - so for that reason as well as others, it's
better to create loggers and call their methods.

Logging to a file
^^^^^^^^^^^^^^^^^
Expand All @@ -130,11 +139,12 @@ look at that next. Be sure to try the following in a newly started Python
interpreter, and don't just continue from the session described above::

import logging
logger = logging.getLogger(__name__)
logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
logging.error('And non-ASCII stuff, too, like Øresund and Malmö')
logger.debug('This message should go to the log file')
logger.info('So should this')
logger.warning('And this, too')
logger.error('And non-ASCII stuff, too, like Øresund and Malmö')

.. versionchanged:: 3.9
The *encoding* argument was added. In earlier Python versions, or if not
Expand All @@ -148,10 +158,10 @@ messages:

.. code-block:: none
DEBUG:root:This message should go to the log file
INFO:root:So should this
WARNING:root:And this, too
ERROR:root:And non-ASCII stuff, too, like Øresund and Malmö
DEBUG:__main__:This message should go to the log file
INFO:__main__:So should this
WARNING:__main__:And this, too
ERROR:__main__:And non-ASCII stuff, too, like Øresund and Malmö
This example also shows how you can set the logging level which acts as the
threshold for tracking. In this case, because we set the threshold to
Expand Down Expand Up @@ -180,11 +190,9 @@ following example::
raise ValueError('Invalid log level: %s' % loglevel)
logging.basicConfig(level=numeric_level, ...)

The call to :func:`basicConfig` should come *before* any calls to
:func:`debug`, :func:`info`, etc. Otherwise, those functions will call
:func:`basicConfig` for you with the default options. As it's intended as a
one-off simple configuration facility, only the first call will actually do
anything: subsequent calls are effectively no-ops.
The call to :func:`basicConfig` should come *before* any calls to a logger's
methods such as :meth:`~Logger.debug`, :meth:`~Logger.info`, etc. Otherwise,
that logging event may not be handled in the desired manner.

If you run the above script several times, the messages from successive runs
are appended to the file *example.log*. If you want each run to start afresh,
Expand All @@ -197,50 +205,6 @@ The output will be the same as before, but the log file is no longer appended
to, so the messages from earlier runs are lost.


Logging from multiple modules
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If your program consists of multiple modules, here's an example of how you
could organize logging in it::

# myapp.py
import logging
import mylib

def main():
logging.basicConfig(filename='myapp.log', level=logging.INFO)
logging.info('Started')
mylib.do_something()
logging.info('Finished')

if __name__ == '__main__':
main()

::

# mylib.py
import logging

def do_something():
logging.info('Doing something')

If you run *myapp.py*, you should see this in *myapp.log*:

.. code-block:: none
INFO:root:Started
INFO:root:Doing something
INFO:root:Finished
which is hopefully what you were expecting to see. You can generalize this to
multiple modules, using the pattern in *mylib.py*. Note that for this simple
usage pattern, you won't know, by looking in the log file, *where* in your
application your messages came from, apart from looking at the event
description. If you want to track the location of your messages, you'll need
to refer to the documentation beyond the tutorial level -- see
:ref:`logging-advanced-tutorial`.


Logging variable data
^^^^^^^^^^^^^^^^^^^^^

Expand Down
Loading

0 comments on commit 8db8e1c

Please sign in to comment.