aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Doc/howto
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/howto')
-rw-r--r--Doc/howto/annotations.rst7
-rw-r--r--Doc/howto/cporting.rst6
-rw-r--r--Doc/howto/curses.rst2
-rw-r--r--Doc/howto/free-threading-extensions.rst10
-rw-r--r--Doc/howto/free-threading-python.rst2
-rw-r--r--Doc/howto/functional.rst2
-rw-r--r--Doc/howto/isolating-extensions.rst19
-rw-r--r--Doc/howto/urllib2.rst86
8 files changed, 58 insertions, 76 deletions
diff --git a/Doc/howto/annotations.rst b/Doc/howto/annotations.rst
index 78f3704ba5d..d7deb6c6bc1 100644
--- a/Doc/howto/annotations.rst
+++ b/Doc/howto/annotations.rst
@@ -248,4 +248,9 @@ quirks by using :func:`annotationlib.get_annotations` on Python 3.14+ or
:func:`inspect.get_annotations` on Python 3.10+. On earlier versions of
Python, you can avoid these bugs by accessing the annotations from the
class's :attr:`~type.__dict__`
-(e.g., ``cls.__dict__.get('__annotations__', None)``).
+(for example, ``cls.__dict__.get('__annotations__', None)``).
+
+In some versions of Python, instances of classes may have an ``__annotations__``
+attribute. However, this is not supported functionality. If you need the
+annotations of an instance, you can use :func:`type` to access its class
+(for example, ``annotationlib.get_annotations(type(myinstance))`` on Python 3.14+).
diff --git a/Doc/howto/cporting.rst b/Doc/howto/cporting.rst
index 7773620b40b..cf857aed042 100644
--- a/Doc/howto/cporting.rst
+++ b/Doc/howto/cporting.rst
@@ -14,13 +14,11 @@ We recommend the following resources for porting extension modules to Python 3:
module.
* The `Porting guide`_ from the *py3c* project provides opinionated
suggestions with supporting code.
-* The `Cython`_ and `CFFI`_ libraries offer abstractions over
- Python's C API.
+* :ref:`Recommended third party tools <c-api-tools>` offer abstractions over
+ the Python's C API.
Extensions generally need to be re-written to use one of them,
but the library then handles differences between various Python
versions and implementations.
.. _Migrating C extensions: http://python3porting.com/cextensions.html
.. _Porting guide: https://py3c.readthedocs.io/en/latest/guide.html
-.. _Cython: https://cython.org/
-.. _CFFI: https://cffi.readthedocs.io/en/latest/
diff --git a/Doc/howto/curses.rst b/Doc/howto/curses.rst
index 6994a5328e8..816639552d7 100644
--- a/Doc/howto/curses.rst
+++ b/Doc/howto/curses.rst
@@ -161,6 +161,8 @@ your terminal won't be left in a funny state on exception and you'll be
able to read the exception's message and traceback.
+.. _windows-and-pads:
+
Windows and Pads
================
diff --git a/Doc/howto/free-threading-extensions.rst b/Doc/howto/free-threading-extensions.rst
index 3f6ee517050..175bb5dc831 100644
--- a/Doc/howto/free-threading-extensions.rst
+++ b/Doc/howto/free-threading-extensions.rst
@@ -23,6 +23,14 @@ You can use it to enable code that only runs under the free-threaded build::
/* code that only runs in the free-threaded build */
#endif
+.. note::
+
+ On Windows, this macro is not defined automatically, but must be specified
+ to the compiler when building. The :func:`sysconfig.get_config_var` function
+ can be used to determine whether the current running interpreter had the
+ macro defined.
+
+
Module Initialization
=====================
@@ -388,7 +396,7 @@ The wheels, shared libraries, and binaries are indicated by a ``t`` suffix.
free-threaded build, with the ``t`` suffix, such as ``python3.13t``.
* `pypa/cibuildwheel <https://github.com/pypa/cibuildwheel>`_ supports the
free-threaded build if you set
- `CIBW_FREE_THREADED_SUPPORT <https://cibuildwheel.pypa.io/en/stable/options/#free-threaded-support>`_.
+ `CIBW_ENABLE to cpython-freethreading <https://cibuildwheel.pypa.io/en/stable/options/#enable>`_.
Limited C API and Stable ABI
............................
diff --git a/Doc/howto/free-threading-python.rst b/Doc/howto/free-threading-python.rst
index f7a894ac2cd..c33cef2c8e9 100644
--- a/Doc/howto/free-threading-python.rst
+++ b/Doc/howto/free-threading-python.rst
@@ -32,7 +32,7 @@ optionally support installing free-threaded Python binaries. The installers
are available at https://www.python.org/downloads/.
For information on other platforms, see the `Installing a Free-Threaded Python
-<https://py-free-threading.github.io/installing_cpython/>`_, a
+<https://py-free-threading.github.io/installing-cpython/>`_, a
community-maintained installation guide for installing free-threaded Python.
When building CPython from source, the :option:`--disable-gil` configure option
diff --git a/Doc/howto/functional.rst b/Doc/howto/functional.rst
index 1f0608fb0fc..b4f3463afee 100644
--- a/Doc/howto/functional.rst
+++ b/Doc/howto/functional.rst
@@ -372,8 +372,8 @@ have the form::
for expr2 in sequence2
if condition2
for expr3 in sequence3
- ...
if condition3
+ ...
for exprN in sequenceN
if conditionN )
diff --git a/Doc/howto/isolating-extensions.rst b/Doc/howto/isolating-extensions.rst
index a636e06bda8..b2109b15039 100644
--- a/Doc/howto/isolating-extensions.rst
+++ b/Doc/howto/isolating-extensions.rst
@@ -168,7 +168,7 @@ possible, consider explicit locking.
If it is necessary to use process-global state, the simplest way to
avoid issues with multiple interpreters is to explicitly prevent a
module from being loaded more than once per process—see
-`Opt-Out: Limiting to One Module Object per Process`_.
+:ref:`isolating-extensions-optout`.
Managing Per-Module State
@@ -207,6 +207,8 @@ An example of a module with per-module state is currently available as
example module initialization shown at the bottom of the file.
+.. _isolating-extensions-optout:
+
Opt-Out: Limiting to One Module Object per Process
--------------------------------------------------
@@ -215,21 +217,36 @@ multiple interpreters correctly. If this is not yet the case for your
module, you can explicitly make your module loadable only once per
process. For example::
+ // A process-wide flag
static int loaded = 0;
+ // Mutex to provide thread safety (only needed for free-threaded Python)
+ static PyMutex modinit_mutex = {0};
+
static int
exec_module(PyObject* module)
{
+ PyMutex_Lock(&modinit_mutex);
if (loaded) {
+ PyMutex_Unlock(&modinit_mutex);
PyErr_SetString(PyExc_ImportError,
"cannot load module more than once per process");
return -1;
}
loaded = 1;
+ PyMutex_Unlock(&modinit_mutex);
// ... rest of initialization
}
+If your module's :c:member:`PyModuleDef.m_clear` function is able to prepare
+for future re-initialization, it should clear the ``loaded`` flag.
+In this case, your module won't support multiple instances existing
+*concurrently*, but it will, for example, support being loaded after
+Python runtime shutdown (:c:func:`Py_FinalizeEx`) and re-initialization
+(:c:func:`Py_Initialize`).
+
+
Module State Access from Functions
----------------------------------
diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst
index 33a2a7ea89e..d79d1abe8d0 100644
--- a/Doc/howto/urllib2.rst
+++ b/Doc/howto/urllib2.rst
@@ -245,75 +245,27 @@ codes in the 100--299 range indicate success, you will usually only see error
codes in the 400--599 range.
:attr:`http.server.BaseHTTPRequestHandler.responses` is a useful dictionary of
-response codes in that shows all the response codes used by :rfc:`2616`. The
-dictionary is reproduced here for convenience ::
+response codes that shows all the response codes used by :rfc:`2616`.
+An excerpt from the dictionary is shown below ::
- # Table mapping response codes to messages; entries have the
- # form {code: (shortmessage, longmessage)}.
responses = {
- 100: ('Continue', 'Request received, please continue'),
- 101: ('Switching Protocols',
- 'Switching to new protocol; obey Upgrade header'),
-
- 200: ('OK', 'Request fulfilled, document follows'),
- 201: ('Created', 'Document created, URL follows'),
- 202: ('Accepted',
- 'Request accepted, processing continues off-line'),
- 203: ('Non-Authoritative Information', 'Request fulfilled from cache'),
- 204: ('No Content', 'Request fulfilled, nothing follows'),
- 205: ('Reset Content', 'Clear input form for further input.'),
- 206: ('Partial Content', 'Partial content follows.'),
-
- 300: ('Multiple Choices',
- 'Object has several resources -- see URI list'),
- 301: ('Moved Permanently', 'Object moved permanently -- see URI list'),
- 302: ('Found', 'Object moved temporarily -- see URI list'),
- 303: ('See Other', 'Object moved -- see Method and URL list'),
- 304: ('Not Modified',
- 'Document has not changed since given time'),
- 305: ('Use Proxy',
- 'You must use proxy specified in Location to access this '
- 'resource.'),
- 307: ('Temporary Redirect',
- 'Object moved temporarily -- see URI list'),
-
- 400: ('Bad Request',
- 'Bad request syntax or unsupported method'),
- 401: ('Unauthorized',
- 'No permission -- see authorization schemes'),
- 402: ('Payment Required',
- 'No payment -- see charging schemes'),
- 403: ('Forbidden',
- 'Request forbidden -- authorization will not help'),
- 404: ('Not Found', 'Nothing matches the given URI'),
- 405: ('Method Not Allowed',
- 'Specified method is invalid for this server.'),
- 406: ('Not Acceptable', 'URI not available in preferred format.'),
- 407: ('Proxy Authentication Required', 'You must authenticate with '
- 'this proxy before proceeding.'),
- 408: ('Request Timeout', 'Request timed out; try again later.'),
- 409: ('Conflict', 'Request conflict.'),
- 410: ('Gone',
- 'URI no longer exists and has been permanently removed.'),
- 411: ('Length Required', 'Client must specify Content-Length.'),
- 412: ('Precondition Failed', 'Precondition in headers is false.'),
- 413: ('Request Entity Too Large', 'Entity is too large.'),
- 414: ('Request-URI Too Long', 'URI is too long.'),
- 415: ('Unsupported Media Type', 'Entity body in unsupported format.'),
- 416: ('Requested Range Not Satisfiable',
- 'Cannot satisfy request range.'),
- 417: ('Expectation Failed',
- 'Expect condition could not be satisfied.'),
-
- 500: ('Internal Server Error', 'Server got itself in trouble'),
- 501: ('Not Implemented',
- 'Server does not support this operation'),
- 502: ('Bad Gateway', 'Invalid responses from another server/proxy.'),
- 503: ('Service Unavailable',
- 'The server cannot process the request due to a high load'),
- 504: ('Gateway Timeout',
- 'The gateway server did not receive a timely response'),
- 505: ('HTTP Version Not Supported', 'Cannot fulfill request.'),
+ ...
+ <HTTPStatus.OK: 200>: ('OK', 'Request fulfilled, document follows'),
+ ...
+ <HTTPStatus.FORBIDDEN: 403>: ('Forbidden',
+ 'Request forbidden -- authorization will '
+ 'not help'),
+ <HTTPStatus.NOT_FOUND: 404>: ('Not Found',
+ 'Nothing matches the given URI'),
+ ...
+ <HTTPStatus.IM_A_TEAPOT: 418>: ("I'm a Teapot",
+ 'Server refuses to brew coffee because '
+ 'it is a teapot'),
+ ...
+ <HTTPStatus.SERVICE_UNAVAILABLE: 503>: ('Service Unavailable',
+ 'The server cannot process the '
+ 'request due to a high load'),
+ ...
}
When an error is raised the server responds by returning an HTTP error code