- Add example idle response tuples, to make the minor difference from other
imaplib response tuples more obvious.
- Merge the idle context manager's burst() method docs with the IMAP
object's idle() method docs, for easier understanding.
- Upgrade the Windows note regarding lack of pipe timeouts to a warning.
- Rephrase various things for clarity.
This extends imaplib with support for the rfc2177 IMAP IDLE command,
as requested in #55454. It allows events to be pushed to a client as
they occur, rather than having to continually poll for mailbox changes.
The interface is a new idle() method, which returns an iterable context
manager. Entering the context starts IDLE mode, during which events
(untagged responses) can be retrieved using the iteration protocol.
Exiting the context sends DONE to the server, ending IDLE mode.
An optional time limit for the IDLE session is supported, for use with
servers that impose an inactivity timeout.
The context manager also offers a burst() method, designed for programs
wishing to process events in batch rather than one at a time.
Notable differences from other implementations:
- It's an extension to imaplib, rather than a replacement.
- It doesn't introduce additional threads.
- It doesn't impose new requirements on the use of imaplib's existing methods.
- It passes the unit tests in CPython's test/test_imaplib.py module
(and adds new ones).
- It works on Windows, Linux, and other unix-like systems.
- It makes IDLE available on all of imaplib's client variants
(including IMAP4_stream).
- The interface is pythonic and easy to use.
Caveats:
- Due to a Windows limitation, the special case of IMAP4_stream running
on Windows lacks a duration/timeout feature. (This is the stdin/stdout
pipe connection variant; timeouts work fine for socket-based
connections, even on Windows.) I have documented it where appropriate.
- The file-like imaplib instance attributes are changed from buffered to
unbuffered mode. This could potentially break any client code that
uses those objects directly without expecting partial reads/writes.
However, these attributes are undocumented. As such, I think (and
PEP 8 confirms) that they are fair game for changes.
https://peps.python.org/pep-0008/#public-and-internal-interfaces
Usage examples:
https://github.com/python/cpython/issues/55454#issuecomment-2227543041
Original discussion:
https://discuss.python.org/t/gauging-interest-in-my-imap4-idle-implementation-for-imaplib/59272
Earlier requests and suggestions:
https://github.com/python/cpython/issues/55454https://mail.python.org/archives/list/python-ideas@python.org/thread/C4TVEYL5IBESQQPPS5GBR7WFBXCLQMZ2/
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
* Remove backtracking when parsing tarfile headers
* Rewrite PAX header parsing to be stricter
* Optimize parsing of GNU extended sparse headers v0.0
Co-authored-by: Kirill Podoprigora <kirill.bast9@mail.ru>
Co-authored-by: Gregory P. Smith <greg@krypto.org>
* urljoin() with relative reference "?" sets empty query and removes fragment.
* Preserve empty components (authority, params, query, fragment) in urljoin().
* Preserve empty components (authority, params, query) in urldefrag().
Also refactor the code and get rid of double _coerce_args() and
_coerce_result() calls in urljoin(), urldefrag(), urlparse() and
urlunparse().
When checking if the registering browser is the "OS preferred browser", do not use a substring search - that makes no sense: one can have a preferred browser that looks like a super-string of a known browser, e.g. "firefox-nightly" vs "firefox".
https://github.com/python/cpython/issues/108172 explains in more detail, and lays out a potential better future enhancement for this case of just using xdg-open. We'll go with this for now.
---------
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
See https://github.com/python/cpython/issues/121313 for analysis, but this greatly reduces memory overallocation and overhead when multiprocessing is sending non-small data over its pipes between processes.
This checks are redundant in normal circumstances and can only work if
the extension registry was intentionally broken.
* The Python implementation now raises exception for the extension code
with false boolean value.
* Simplify the C code. RuntimeError is now raised in explicit checks.
* Add many tests.
* Replace PyLong_AS_LONG() with PyLong_AsLong().
* Call PyLong_AsLong() only once per the replacement code.
* Use PyMapping_GetOptionalItem() instead of PyObject_GetItem().
The `zip_next` function uses a common optimization technique for methods
that generate tuples. The iterator maintains an internal reference to
the returned tuple. When the method is called again, it checks if the
internal tuple's reference count is 1. If so, the tuple can be reused.
However, this approach is not safe under the free-threading build:
after checking the reference count, another thread may perform the same
check and also reuse the tuple. This can result in a double decref on
the items of the replaced tuple and a double incref (memory leak) on
the items of the tuple being set.
This adds a function, `_PyObject_IsUniquelyReferenced` that
encapsulates the stricter logic necessary for the free-threaded build:
the internal tuple must be owned by the current thread, have a local
refcount of one, and a shared refcount of zero.