Skip to content

fix(deps): update poetry dependencies (master) (major) - #2428

Open
red-hat-konflux[bot] wants to merge 1 commit into
masterfrom
konflux/mintmaker/master-master/major-poetry-deps
Open

fix(deps): update poetry dependencies (master) (major)#2428
red-hat-konflux[bot] wants to merge 1 commit into
masterfrom
konflux/mintmaker/master-master/major-poetry-deps

Conversation

@red-hat-konflux

@red-hat-konflux red-hat-konflux Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
gunicorn (changelog) ^23.0.0^26.0.0 age confidence
peewee (changelog) ^3.18.1^4.0.0 age confidence
prometheus-async (changelog) ^25.0.0^26.0.0 age confidence
pytz (source) 2025.22026.3 age confidence

Release Notes

benoitc/gunicorn (gunicorn)

v26.1.0: gunicorn 26.1.0

Compare Source

New Features
  • Glob patterns in reload_extra_files: entries containing *, ? or [
    are treated as patterns, so ui/*/config.json watches every view's config
    without listing them one by one. Patterns are re-expanded on every reload
    check rather than once at startup, so a file created later starts being
    watched without restarting gunicorn, and ** recurses. A pattern matching
    nothing warns instead of failing, since with live expansion it may match later
    (#​1643,
    #​3662).
Security
  • Dependency floors raised past known advisories: every declared floor was
    checked against the advisory database. tornado, h2, setuptools and
    pymdown-extensions permitted vulnerable versions and now require the first
    clean release; pytest and httpx were unpinned and now carry floors. The
    tornado example pinned tornado<6, which was both the source of several
    advisories and older than the >=6.5.0 the tornado worker needs, so the
    example could not run as pinned.
Bug Fixes
  • SIGHUP did not reload the logger configuration: Arbiter.reload()
    re-read the configuration file but kept using the logger built at startup,
    calling only reopen_files() on its existing handlers. Changes to
    logconfig, logconfig_dict, logconfig_json and loglevel were ignored
    until a full restart, which in containers meant replacing the pod. The
    existing logger now re-runs its setup on reload, so new handlers, formats
    and levels take effect while the process identity and its listeners are
    preserved, and re-running the setup no longer stacks duplicate syslog
    handlers. An invalid log configuration on reload is not fatal either: the
    error is reported on stderr, the previous working configuration is restored
    and the master keeps running with it
    (#​3353).

  • Truncated chunked bodies accepted: RFC 9112 section 7.1.2 ends a chunked
    body with 0 CRLF CRLF, the second CRLF being the mandatory empty trailer
    section. ChunkedReader.parse_chunk_size() swallowed the NoMoreData raised
    while scanning for it, so a body cut short right after the last chunk line was
    treated as complete instead of rejected. It now raises
    ChunkMissingTerminator
    (#​3382,
    #​3685).

  • --spew crashed on dynamically generated code: the trace hook indexed the
    2-tuple returned by inspect.getsourcelines() by line number rather than
    indexing the list of lines, so a frame with no __file__ raised
    AttributeError: 'int' object has no attribute 'rstrip' on line 1 and
    IndexError beyond it. The tuple is now unpacked and offset by the source's
    starting line (#​3344,
    #​3495).

  • Duplicate Host and Content-Type headers accepted: RFC 9110 section 5.3
    allows only one of each, and a repeat cannot be merged into a list, so the
    message means different things to gunicorn and to anything downstream. Both
    are now rejected with InvalidHeader. The check lives in the policy hook
    shared by both parsers, so the pure-Python and fast parsers agree. Duplicate
    Content-Length was already rejected and is unchanged
    (#​3366,
    #​3548).

  • Non-worker children reported as failed workers: reap_workers() reaps
    every child through waitpid(-1), including processes the kernel reparented
    onto gunicorn when it runs as PID 1 in a container, but it logged the exit
    status before checking whether the pid was ever a worker. An unrelated process
    produced Worker (pid:N) exited with code M and triggered alerts. More
    seriously, such a process exiting with code 3 or 4 raised HaltServer and shut
    the server down. Ownership is now established first: the dirty arbiter is
    reported as itself, unknown children are reaped silently at debug level, and
    only real workers can halt the server
    (#​3220,
    #​3566).

  • Dirty arbiter exits were invisible on SIGCHLD: handle_chld() called
    reap_workers() first, whose waitpid(-1) claimed the dirty arbiter before
    reap_dirty_arbiter() could identify it, so the latter always hit ECHILD and
    its reporting never ran. The dirty arbiter is now reaped first, and
    reap_workers() recognises it if it exits mid-loop.

  • Dirty arbiter returned stale responses after a worker timeout: when a
    request reached dirty_timeout the arbiter answered the client with a timeout
    error but kept the worker connection open. The worker's late response was then
    the first message waiting on that socket, so the next request routed to the
    same worker received the previous request's result, and every request after it
    stayed one response behind. The connection is now closed on timeout, so the
    late answer is discarded with it
    (#​3626).

  • ASGI connection count leaked on server-initiated close: nr_conns was
    only decremented in connection_lost(), behind a guard keyed on the same
    flag _close_transport() sets first. Every close the server started (a
    Connection: close response, a keepalive timeout, an error abort) leaked one
    count, so ASGIWorker._shutdown() ran the full graceful_timeout and warned
    about connections that were already gone. The guard now uses its own flag, so
    the decrement and the rest of the cleanup run exactly once whichever side
    closes first (#​3661).

  • Inotify reloader on cwd-relative extra files: reload_extra_files entries
    with no directory part (for example .env) produced an empty dirname, and
    watching it raised InotifyError with ENOENT. The current directory is now
    watched as . (#​3377,
    #​3667).

  • StatsD zero-valued metrics: gauges, counters, histograms and timers
    reporting 0 were silently dropped because the value was tested for
    truthiness. Only None is skipped now
    (#​3676).

  • Spurious no-body warning from sendfile(): a HEAD, 204 or 304 response
    served through sendfile() warned about dropped body bytes even when the
    file was empty and nothing was dropped. It now warns only when there are
    bytes to drop, matching write()
    (#​3684).

  • Bare except in the gevent websocket example: narrowed to
    except Exception (#​3683).

  • ASGI receive() cancellation: Let asyncio.CancelledError propagate
    from BodyReceiver instead of swallowing it and returning
    http.disconnect. Frameworks that cancel their disconnect listener after
    the response completes (Django) no longer see the cancel masked, so
    request_finished fires and close_old_connections() runs. Fixes idle
    database connections leaking since 25.1.0
    (#​3627,
    #​3654).

  • Control socket leak on SIGHUP reload: The control thread is now marked
    ready once its loop and server are live, and the stop paths wait on that
    readiness before scheduling shutdown. Reloads no longer leak one thread and
    its selector fd plus unix socket per worker, which eventually raised
    "too many open files"
    (#​3648).

  • WSGI body framing on HEAD/1xx/204/304: Mirror the ASGI strip-and-warn
    behavior on the WSGI path. Content-Length is stripped on 1xx/204 per
    RFC 9110 section 6.4.2, body bytes are dropped for no-body responses in
    both write() and sendfile(), and a single warning is logged per request
    (#​3413).

Refactoring
  • Pass log arguments to the logger instead of pre-formatting the worker
    termination message in Arbiter.reap_workers()
    (#​3678).
Changes
  • packaging is no longer a runtime dependency: it was only ever imported by
    the gevent worker, to compare gevent's version. It moved to the gevent and
    testing extras, so a plain pip install gunicorn pulls in nothing
    (#​3643).

  • Fast HTTP Parser: Require gunicorn_h1c >= 0.6.6, which rejects duplicate
    Host and Content-Type headers in the C parser itself. Gunicorn already
    refuses them on both the WSGI and ASGI paths, so this changes nothing that is
    reachable; it moves the rejection to where the bytes are read and lets the
    ASGI corpus exercise those cases against the fast parser directly.

Full changelog: https://gunicorn.org/2026-news/

v26.0.0

Compare Source

Breaking Changes

  • Eventlet worker removed: The eventlet worker class has been dropped. Migrate to gevent, gthread, or tornado.

New Features

  • ASGI Framework Compatibility Suite: New end-to-end compatibility test harness covering Starlette, FastAPI, Litestar, Quart, Sanic, and BlackSheep. Current grid passes 438/444 tests (98%).
  • ASGI Test Suite Expansion: 134 additional ASGI unit tests covering protocol semantics, lifespan, websockets, and chunked framing.

Security

  • HTTP/1.1 Request-Target Validation (RFC 9112 sections 3.2.3, 3.2.4):
    • Reject authority-form request-target outside CONNECT
    • Reject asterisk-form request-target outside OPTIONS
    • Reject relative-reference request-targets
  • Header Field Hardening (RFC 9110):
    • Reject control characters in header field-value (section 5.5)
    • Reject forbidden trailer field-names (section 6.5.1)
    • Reject Content-Length list form (RFC 9112 section 6.3)
  • Request Smuggling Hardening:
    • Tighten keepalive gate and scope finish_body byte cap
    • Keep _body_receiver alive across the keepalive smuggling gate so pipelined requests cannot re-enter a closed body
    • Address parser/protocol findings from a six-point WSGI/ASGI audit
  • PROXY Protocol (ASGI): Enforce proxy_allow_ips and tighten v1/v2 parsing in the ASGI callback parser.
  • Connection Draining: Drain the connection on close per RFC 9112 section 9.6 to prevent reset-on-close truncation.

Bug Fixes

  • Body Framing on HEAD/204/304:
    • Keep Content-Length on HEAD and 304 responses (#​3621)
    • Drop body framing on HEAD/204/304 even when the framework set it
    • Warn once when an ASGI app emits a body for a no-body response
  • HTTP/2 ASGI:
    • Fix _handle_stream_ended to set _body_complete in the async HTTP/2 handler so request bodies finalize correctly on stream end
    • Add InvalidChunkExtension mapping and fast-parser support in ASGI tests (#​3565)
  • HTTP/1.1 100-Continue: Stop adding Transfer-Encoding: chunked to 100-Continue interim responses.
  • WebSocket Close Handshake (RFC 6455):
    • Comply with the close handshake state machine
    • Close the transport after the close handshake completes
    • Fix binary send when the text key is None
  • Early Hints: Validate headers in the early_hints callback to match process_headers; pass only the header name to InvalidHeader (#​3588).
  • ASGI Framework Fixes:
    • Fix ASGI disconnect handling for Django-style apps
    • Fix Litestar request handling (use raw ASGI receive for body/headers)
    • Fix Litestar HTTP endpoints for compatibility tests
    • Fix Quart headers endpoint to normalize keys to lowercase
    • Fix Quart WebSocket close test app (missing accept())
    • Fix duplicate Transfer-Encoding header for BlackSheep streaming

Refactoring

  • Split BodyReceiver._closed into separate transport and body-wait flags for clearer keepalive/EOF semantics.

Changes

  • Fast HTTP Parser: Require gunicorn_h1c >= 0.6.5. Drop the last python_only test markers; the C extension is now used wherever available (CPython only; PyPy continues to use the Python parser).
  • Test Dependencies: Add h2 and uvloop to the testing extra; remove eventlet.
  • Docker Build: Bump GitHub Actions docker/setup-qemu-action, docker/setup-buildx-action, docker/login-action, docker/build-push-action, and docker/metadata-action to current major versions.

Full changelog: benoitc/gunicorn@25.3.0...26.0.0

v25.3.0: Gunicorn 25.3.0

Compare Source

Bug Fixes

  • HTTP/2 ASGI Body Duplication: Fix request body being received twice in HTTP/2
    ASGI requests, causing JSON parsing errors with "Extra data" messages
    (#​3558)

  • ASGI Chunked EOF Handling: Add finish() method to callback parser to handle
    chunked encoding edge case where connection closes before final CRLF after zero-chunk

  • HTTP/2 Documentation: Fix http_protocols examples to use comma-separated string
    instead of list syntax (#​3561)

  • Chunked Encoding: Reject chunk extensions containing bare CR bytes per RFC 9112
    (#​3556)

  • Request Line Limit: Fix --limit-request-line 0 to mean unlimited as documented,
    instead of using default maximum. Works with both Python and fast C parser.
    (#​3563)

Security

  • ASGI Parser Header Validation: Add security checks per RFC 9110/9112:
    • Reject duplicate Content-Length headers
    • Reject requests with both Content-Length and Transfer-Encoding
    • Reject chunked transfer encoding in HTTP/1.0
    • Reject stacked chunked encoding
    • Validate Transfer-Encoding values
    • Strict chunk size validation

Changes

  • Fast HTTP Parser: Update to gunicorn_h1c >= 0.6.3 for asgi_headers property
    and InvalidChunkExtension validation for bare CR rejection

  • ASGI PROXY Protocol: Add PROXY protocol v1/v2 support to callback parser

  • Docker Images: Update to Python 3.14

v25.2.0: Gunicorn 25.2.0

Compare Source

New Features
  • Fast HTTP Parser (gunicorn_h1c 0.4.1): Integrate new exception types and limit parameters from gunicorn_h1c 0.4.1 for both WSGI and ASGI workers
    • Requires gunicorn_h1c >= 0.4.1 for http_parser='fast'
    • Falls back to Python parser in auto mode if version not met
    • Proper HTTP status codes for limit errors (414, 431)
Bug Fixes
  • uWSGI Async Workers: Fix InvalidUWSGIHeader: incomplete header error when using gevent or gthread workers with uwsgi protocol behind nginx. (#​3552, PR #​3554)

  • FileWrapper Iterator Protocol: Add __iter__ and __next__ methods to FileWrapper for full PEP 3333 compliance. (#​3396, PR #​3550)

Performance
  • ASGI HTTP Parser Optimizations: Improve ASGI worker HTTP parsing performance
    • Callback-based parsing with direct bytearray buffer operations
    • Use bytearray.find() directly instead of converting to bytes first
    • Use index-based iteration for header parsing instead of list.pop(0) (O(1) vs O(n))

v25.1.0: Gunicorn 25.1.0

Compare Source

New Features
  • Control Interface (gunicornc): Add interactive control interface for managing
    running Gunicorn instances, similar to birdc for BIRD routing daemon
    (PR #​3505)

    • Unix socket-based communication with JSON protocol
    • Interactive mode with readline support and command history
    • Commands: show all/workers/dirty/config/stats/listeners
    • Worker management: worker add/remove/kill, dirty add/remove
    • Server control: reload, reopen, shutdown
    • New settings: --control-socket, --control-socket-mode, --no-control-socket
    • New CLI tool: gunicornc for connecting to control socket
    • See Control Interface Guide for details
  • Dirty Stash: Add global shared state between workers via dirty.stash
    (PR #​3503)

    • In-memory key-value store accessible by all workers
    • Supports get, set, delete, clear, keys, and has operations
    • Useful for sharing state like feature flags, rate limits, or cached data
  • Dirty Binary Protocol: Implement efficient binary protocol for dirty arbiter IPC
    using TLV (Type-Length-Value) encoding
    (PR #​3500)

    • More efficient than JSON for binary data
    • Supports all Python types: str, bytes, int, float, bool, None, list, dict
    • Better performance for large payloads
  • Dirty TTIN/TTOU Signals: Add dynamic worker scaling for dirty arbiters
    (PR #​3504)

    • Send SIGTTIN to increase dirty workers
    • Send SIGTTOU to decrease dirty workers
    • Respects minimum worker constraints from app configurations
Changes
  • ASGI Worker: Promoted from beta to stable
  • Dirty Arbiters: Now marked as beta feature
Documentation
  • Fix Markdown formatting in /configure documentation

v25.0.3

Compare Source

What's Changed

Bug Fixes
  • Fix RuntimeError when StopIteration raised in ASGI coroutine (#​3484)
  • Fix passing maxsplit in re.split() as positional argument (deprecated in Python 3.13)
Documentation
  • Updated sponsorship section and homepage

Full Changelog: benoitc/gunicorn@25.0.2...25.0.3

v25.0.2

Compare Source

What's Changed

Bug Fixes
  • Fix ASGI concurrent request failures through nginx proxy
  • Graceful disconnect handling for ASGI worker
  • Lazy import dirty module for gevent compatibility
Other
  • Increase CI timeout for signal tests on PyPy
  • Remove trailing blank line in instrument/init.py

Full Changelog: benoitc/gunicorn@25.0.1...25.0.2

v25.0.1

Compare Source

Bug Fixes

  • Fix ASGI streaming responses (SSE) hanging: add chunked transfer encoding for
    HTTP/1.1 responses without Content-Length header. Without chunked encoding,
    clients wait for connection close to determine end-of-response.

Changes

  • Update celery_alternative example to use FastAPI with native ASGI worker and
    uvloop for async task execution

Testing

  • Add ASGI compliance test suite with Docker-based integration tests covering HTTP,
    WebSocket, streaming, lifespan, framework integration (Starlette, FastAPI),
    HTTP/2, and concurrency scenarios

v25.0.0: Gunicorn 25.0.0

Compare Source

New Features

  • Dirty Arbiters: Separate process pool for executing long-running, blocking
    operations (AI model loading, heavy computation) without blocking HTTP workers
    (PR #​3460)

    • Inspired by Erlang's dirty schedulers
    • Asyncio-based with Unix socket IPC
    • Stateful workers that persist loaded resources
    • New settings: --dirty-app, --dirty-workers, --dirty-timeout,
      --dirty-threads, --dirty-graceful-timeout
    • Lifecycle hooks: on_dirty_starting, dirty_post_fork,
      dirty_worker_init, dirty_worker_exit
  • Per-App Worker Allocation for Dirty Arbiters: Control how many dirty workers
    load each app for memory optimization with heavy models
    (PR #​3473)

    • Set workers class attribute on DirtyApp (e.g., workers = 2)
    • Or use config format module:class:N (e.g., myapp:HeavyModel:2)
    • Requests automatically routed to workers with the target app
    • New exception DirtyNoWorkersAvailableError for graceful error handling
    • Example: 8 workers × 10GB model = 80GB → with workers=2: 20GB (75% savings)
  • HTTP/2 Support (Beta): Native HTTP/2 (RFC 7540) support for improved performance
    with modern clients (PR #​3468)

    • Multiplexed streams over a single connection
    • Header compression (HPACK)
    • Flow control and stream prioritization
    • Works with gthread, gevent, and ASGI workers
    • New settings: --http-protocols, --http2-max-concurrent-streams,
      --http2-initial-window-size, --http2-max-frame-size, --http2-max-header-list-size
    • Requires SSL/TLS and h2 library: pip install gunicorn[http2]
    • New example: examples/http2_gevent/ with Docker and tests
  • HTTP 103 Early Hints: Support for RFC 8297 Early Hints to enable browsers to
    preload resources before the final response
    (PR #​3468)

    • WSGI: environ['wsgi.early_hints'](headers) callback
    • ASGI: http.response.informational message type
    • Works with both HTTP/1.1 and HTTP/2
  • uWSGI Protocol for ASGI Worker: The ASGI worker now supports receiving requests
    via the uWSGI binary protocol from nginx
    (PR #​3467)

Bug Fixes

  • Fix HTTP/2 ALPN negotiation for gevent and eventlet workers when
    do_handshake_on_connect is False (the default). The TLS handshake is now
    explicitly performed before checking selected_alpn_protocol().

  • Fix setproctitle initialization with systemd socket activation
    (#​3465)

  • Fix Expect: 100-continue handling: ignore the header for HTTP/1.0 requests
    since 100-continue is only valid for HTTP/1.1+
    (PR #​3463)

  • Fix missing _expected_100_continue attribute in UWSGIRequest

  • Disable setproctitle on macOS to prevent segfaults during process title updates

  • Publish full exception traceback when the application fails to load
    (#​3462)

  • Fix ASGI: quick shutdown on SIGINT/SIGQUIT, graceful on SIGTERM

Deprecations

  • Eventlet Worker: The eventlet worker is deprecated and will be removed in
    Gunicorn 26.0. Eventlet itself is no longer actively maintained.
    Please migrate to gevent, gthread, or another supported worker type.

Changes

  • Remove obsolete Makefile targets
    (PR #​3471)
  • Replace RST with markdown documentation format

v24.1.1

Compare Source

Bug Fixes

  • Fix forwarded_allow_ips and proxy_allow_ips to remain as strings for backward
    compatibility with external tools like uvicorn. Network validation now uses strict
    mode to detect invalid CIDR notation (e.g., 192.168.1.1/24 where host bits are set)
    (#​3458,
    PR #​3459)

Full Changelog: benoitc/gunicorn@24.1.0...24.1.1

v24.1.0: Gunicorn 24.1.0

Compare Source

New Features

  • Official Docker Image: Gunicorn now publishes official Docker images to GitHub Container Registry (PR #​3454)

    • Available at ghcr.io/benoitc/gunicorn
    • Based on Python 3.12 slim image
    • Uses recommended worker formula (2 × CPU + 1)
    • Configurable via environment variables
  • PROXY Protocol v2 Support: Extended PROXY protocol implementation to support the binary v2 format in addition to the existing text-based v1 format (PR #​3451)

    • New --proxy-protocol modes: off, v1, v2, auto
    • auto mode (default when enabled) detects v1 or v2 automatically
    • v2 binary format is more efficient and supports additional metadata
    • Works with HAProxy, AWS NLB/ALB, and other PROXY protocol v2 sources
  • CIDR Network Support: --forwarded-allow-ips and --proxy-allow-from now accept CIDR notation (e.g., 192.168.0.0/16) for specifying trusted networks (PR #​3449)

  • Socket Backlog Metric: New gunicorn.socket.backlog gauge metric reports the current socket backlog size on Linux systems (PR #​3450)

  • InotifyReloader Enhancement: The inotify-based reloader now watches newly imported modules, not just those loaded at startup (PR #​3447)

Bug Fixes

  • Fix signal handling regression where SIGCLD alias caused "Unhandled signal: cld" errors on Linux when workers fail during boot (#​3453)
  • Fix socket blocking mode on keepalive connections preventing SSL handshake failures with async workers (PR #​3452)
  • Use smaller buffer size in finish_body() for faster timeout detection on slow or abandoned connections (PR #​3453)
  • Handle SSLWantReadError in finish_body() to prevent worker hangs during SSL renegotiation (PR #​3448)
  • Log SIGTERM as info level instead of warning to reduce noise in orchestrated environments (PR #​3446)
  • Print exception details to stderr when worker fails to boot (PR #​3443)
  • Fix unreader.unread() to prepend data to buffer instead of appending (PR #​3442)
  • Prevent RecursionError when pickling Config objects (PR #​3441)
  • Use proper exception chaining with raise from in glogging.py (PR #​3440)

Installation

pip install gunicorn==24.1.0

Or use the official Docker image:

docker pull ghcr.io/benoitc/gunicorn:24.1.0

v24.0.0

Compare Source

New Features

  • ASGI Worker (Beta): Native asyncio-based ASGI support for running async Python frameworks like FastAPI, Starlette, and Quart without external dependencies

    • HTTP/1.1 with keepalive connections
    • WebSocket support
    • Lifespan protocol for startup/shutdown hooks
    • Optional uvloop for improved performance
  • uWSGI Binary Protocol: Support for receiving requests from nginx via uwsgi_pass directive

  • Documentation Migration: Migrated to MkDocs with Material theme

Security

Install

pip install gunicorn==24.0.0
coleifer/peewee (peewee)

v4.3.0

Compare Source

Backwards-incompatible:

  • Specify requires-python >= 3.8. I've been putting off committing to
    anything like this, since technically we still work on 3.7, but 3.8 is the
    minimum we run on CI so it felt correct.
  • Replace docid implicit primary key on legacy FTSModel (FTS4) with
    rowid, which is equivalent. Using docid presents no benefit and
    switching to rowid makes operations more consistent. Users have a couple
    options when updating:
    • Explicitly add docid = DocIDField() to your FTSModel classes.
    • Update your code, replacing docid with rowid. The underlying data
      does not require a migration, as docid was just an alias for rowid.
  • When a RETURNING-clause insert of a single row inserts nothing, e.g. a
    conflict was ignored, execute() returns None on every backend.

Improvements:

  • Connection pools roll back transactions left open on check-in.
  • Pooled Postgres probes idle connections with SELECT 1 and discards dead
    ones, matching the MySQL pool's ping. Previously a connection terminated
    server-side while parked in the pool was handed out and failed on first use.
  • close_pool() in pwasyncio no longer spins the event loop on Python
    3.13+ attempting to reclaim connections in use, and pool creation is now
    bounded by acquire_timeout. Connections terminated during shutdown are
    detected as stale and discarded at the next checkout.
  • JSONField negative path indexes render as $[last] / $[last-n] on
    MySQL/MariaDB. Previously the sqlite-only $[#-n] form was emitted, which
    MariaDB evaluates to NULL (overwriting the column when used with set())
    and MySQL rejects as an invalid path.
  • JSONField mutators (set(), insert(), etc) store Python booleans as
    json true/false instead of the driver's 0/1, so values written by create()
    and by mutators compare consistently. Floats on MySQL/MariaDB likewise take
    their json text form, as MariaDB reformats driver floats in a way that
    breaks equality against the stored document.
  • Reflection/pwiz map MySQL JSON columns to the core JSONField instead of
    emitting from playhouse.mysql_ext import * for a re-exported field.
  • playhouse.pwasyncio logs to the peewee.pwasyncio logger rather than
    playhouse.pwasyncio.
  • Fix dataset freeze/thaw of NULL blob and datetime values. Empty CSV cells
    now import as NULL for non-text fields.
  • Lateral joins honor a user-supplied on= predicate instead of silently
    replacing it with true, and default to ON true when on= is omitted.
  • The SQLite FTS content option must be a Model or table-name string.
    Passing a Field now raises ImproperlyConfigured: it generated DDL that
    fts5 rejects outright and that fts4 silently truncated to the table name.
  • Fix FTS5Model.VocabModel(): term/col/offset were declared as virtual
    fields and omitted from default SELECTs, the instance-type model had the
    wrong column set, all three table-types shared one default table name, and
    the generated class was cached with whatever database was bound at first
    call. Vocab models are now built fresh per call with real fields, correct
    columns and per-type default names.
  • Add FTS5Model.web_query(), which translates the query syntax users expect
    from a search box (quoted phrases, AND/OR/NOT, -exclusion, column:
    filters and parentheses) into an FTS5 query. Anything else is searched as
    text, so covid-19 or c++ need no escaping, and the translation is always
    a valid query. The parser lives in the new playhouse.fts_parser module.
    Use it with search: Doc.search(Doc.web_query(user_input)).
  • Add FTS5Model.delete_command(), which removes a row using the fts5 delete
    command. This is how rows are removed from external-content and contentless
    tables, which need the originally-indexed values supplied back to them:
    sqlite treats an omitted column as NULL, and values that do not match what
    was indexed leave stale entries behind (undetectably so on a contentless
    table). Peewee therefore requires a value for every indexed column; pass
    None where NULL was indexed. The command exists only for those two
    configurations - default-storage and contentless_delete=1 tables reject
    it and use ordinary DELETE.
  • Add support for cysqlite's sick table func decorator syntax.
  • Better behavior for INSERT when as_rowcount() is specified, along with
    proper return of all parts of a composite PK instead of just the 1st column.
  • last_insert_id() is implemented once on Database, with backends
    overriding _last_insert_rowid() where the driver differs. APSW and the
    MariaDB connector inherit composite primary-key support as a result, having
    previously returned only the first column.
  • Don't apply field kwargs to barefield instances w/reflection, #​3064.

View commits

v4.2.6

Compare Source

  • A missed outer join is now cached as an absent relation instead of being
    written through the foreign-key descriptor. The fk id on the source
    instance keeps the column's value (previously it was overwritten with
    None), and accessing the attribute on a non-null fk returns None
    instead of raising DoesNotExist.

View commits

v4.2.5

Compare Source

  • Fix anonymous sub-select keeping a stale id()-based hash after clone().

View commits

v4.2.4

Compare Source

  • Fix derived table joined in an expression subquery losing its FROM alias.
  • Fix default Model.select() used as a FROM/JOIN source reduced to its pk.
  • Fix compound/subquery SELECT-list column emitting a phantom alias.
  • Fix fn.EXISTS(compound) double-parenthesizing.
  • Fix x.in_(ValuesList(...)) dropping parens around VALUES.
  • Fix two-FK .join(on=...) mis-attaching rows when the fk is on the rhs.
  • Fix ON CONFLICT ... DO NOTHING dropping the target/where/constraint.

View commits

v4.2.3

Compare Source

  • Fix a compound select (UNION/INTERSECT/EXCEPT) used as a correlated
    subquery emitting a phantom alias for the correlated outer table in every
    branch but the left-most, producing invalid SQL (e.g. no such column: t4.id). The right-hand branch renders in a fresh alias scope that no longer
    resolved the outer source's existing alias, it now inherits the enclosing
    scope's aliases while still assigning fresh aliases to its own sources.
  • Fix full-text search weights passed as a dict being mis-applied to the
    wrong columns. For FTS3/4 the implicit docid primary-key was included when
    building the weight list, shifting every column by one (raising IndexError
    with the Python ranking UDF, silently mis-scoring with the Cython one), for
    FTS5, UNINDEXED columns were skipped even though bm25() weights are
    positional across all columns. The list form of weights was unaffected.
  • Fix .cte() clearing the source query's CTE list in place: converting a query
    that carried a with_cte(...) clause into a CTE stripped the clause from that
    query, so reusing it afterward referenced an undeclared CTE. The query is now
    cloned before its CTE list is reset.
  • Fix Table.select() with no arguments on a Table declared without columns
    emitting an empty projection (SELECT FROM ...) instead of SELECT *.
  • Fix Table.insert(select_query) with no columns raising TypeError instead
    of rendering INSERT INTO t SELECT ....
  • Fix the MySQL migrator dropping a foreign key's ON DELETE/ON UPDATE action
    when add_not_null() or rename_column() rebuilds the constraint, silently
    downgrading e.g. CASCADE to RESTRICT. The actions reported by
    get_foreign_keys() are now carried through to the rebuilt constraint.
  • Fix the legacy postgres_ext JSON contains/contained_by/concat raising
    AttributeError, and remove() silently rewriting the entire column, when
    applied to a .path()-chained lookup (e.g. Model.data['a'].path('b')). All
    four now resolve the root field and full path via _resolve_root(), matching
    the sibling set/replace/insert/append/update mutators.
  • Correct the postgres_ext.JSONField docs: the json-column field does not
    support the jsonb-based mutation/concatenation builders (they raise
    ProgrammingError), so the misleading "Postgres casts implicitly" claim was
    removed and new code is steered to the built-in JSONField.
  • Fix the SQLite migrator treating a bare table-level UNIQUE (a, b) constraint
    as a column when rebuilding a table (add_not_null, drop_column, ...),
    raising no column named UNIQUE; unique is now recognized as a constraint.
  • Fix the SQLite migrator's table rebuild corrupting the CREATE TABLE keywords
    for a table whose name is a case-insensitive substring of them (e.g. ab,
    t, tab) -- the table-name substitution is now anchored to the trailing
    name token.

View commits

v4.2.2

Compare Source

  • Change Field.__hash__ again... fml. Use (model_cls, field name).
  • Fix Metadata.remove_ref() removing the wrong foreign-key when a model
    has multiple foreign-keys to the same target, as list.remove() matched
    the first entry via the overloaded Field.__eq__.
  • Fix a scalar subquery nested inside a function, Case or Cast collapsing
    to its alias in an UPDATE ... SET value and in ON CONFLICT DO UPDATE,
    as qualify_names() wrapped the value at SCOPE_COLUMN.
  • Fix namedtuples() on a query-builder (Table) query raising ValueError
    when a column name is not a valid identifier. The plain
    NamedTupleCursorWrapper now passes rename=True, matching the model path.
  • Fix outer joins in a joined model graph not hydrating a missing related
    object as None, so accessing the attribute raised AttributeError. The
    outer-join test had regressed to endswith('OUTER') (never true). It now
    also recognizes FULL JOIN and LEFT JOIN LATERAL.
  • Fix ModelSelect.select_extend() mutating its receiver's default-projection
    flag, so a base Model.select() reused as a subquery stopped collapsing to
    its primary key. It now flags the returned clone, matching select().
  • Fix distinct(True) and distinct(False) not clearing a prior
    distinct(*columns), so the query kept rendering DISTINCT ON (...) instead
    of a plain DISTINCT or no distinct at all.
  • Fix Postgres get_indexes() shredding an expression index whose key contains
    a comma, e.g. COALESCE(a, 0) split into two bogus columns. It joined the
    per-key definitions into a comma-delimited string and split on the comma. It
    now reads the key array directly.
  • Fix an empty insert (Model.insert(), insert({})) emitting DEFAULT VALUES
    and dropping python-side field defaults, inconsistent with a partial insert
    which backfills them. A model with no python defaults still uses DEFAULT VALUES.

View commits

v4.2.1

Compare Source

Can't ship a stub that's not complete. Missed moving server_side_cursor()
helper into the core psycopg helper.

View commits

v4.2.0

Compare Source

  • Add django-style filter lookups: contains, startswith, endswith,
    between, is_null, not_in and iregexp.
  • Fix SQLite index value inlining to apply properly.
  • Fix PostgresqlDatabase(isolation_level=...) having no effect on
    transactions. Previously only atomic(isolation_level=...) worked.
  • Fix Ordering.collate() dropping the nulls= ordering.
  • Fix double-escaping of backticks in MySQL get_indexes().
  • Honor the windows= parameter of the Select constructor.
  • Remove vestigial Python 2 compat (reraise(), __div__, __nonzero__)
    and assorted dead internal code.
  • Remove TimestampField.local_to_utc() and TimestampField.utc_to_local().
  • Select.columns() no longer accepts and ignores keyword arguments.
  • Remove unused Metadata.get_rel_for_model().
  • Fix SelectBase.exists() ignoring its database argument.
  • Fix CursorWrapper indexing: cursor[n] raised IndexError for uncached
    rows and cursor[0] fetched the entire result set.
  • Fix .namedtuples() crashing on selected columns that are not valid
    Python identifiers.
  • Preserve materialized= when compounding CTEs via union()/union_all().
  • Fix ManyToManyField reads when the through-model foreign keys use the
    '!' backref sentinel.
  • Fix connection pooling with the mariadb connector - pooled connections
    were discarded on every checkout.
  • Fix sqliteq stop() to drain the write queue and return True.
  • Fix apsw aggregate registration binding every name to the last-registered
    aggregate class.
  • Fix two NameErrors in cysqlite_ext: blob_open() and progress().
  • Fix pwiz emitting an invalid attr= keyword instead of
    on_delete/on_update for reflected foreign keys.
  • Fix dataset infinite loop on self-referential foreign keys, crash on
    headerless CSV import, thaw() validating against export rather than
    import formats, and the importer mutating live model metadata.
  • Fix model_to_dict to honor only=/exclude= for many-to-many fields,
    fix resolve_multimodel_query on queries with narrowed selections.
  • Fix signals.Model.save(True) reporting created=False when
    force_insert is passed positionally.
  • Fix CompressedField crashing on str values.
  • Fix psycopg3 server-side cursors (missing withhold) and CockroachDB
    run_transaction retry detection under psycopg3.
  • Async queries are now logged to the peewee logger.
  • Remove dead code and unused imports throughout playhouse, remove the
    broken, unused get_current_url/get_next_url helpers from
    flask_utils.
  • Fix delete_instance(recursive=True) failing to cascade to the children
    of a model reachable through both nullable and non-nullable foreign-keys.
  • Fix subqueries losing their parentheses when used as a CASE value inside
    a single-argument function call, e.g. fn.SUM(Case(...)).
  • Fix plain-Table inserts on returning-clause databases binding the
    primary-key name as a parameter and returning None instead of the new id.
  • CompositeKey comparisons raise ValueError when the value's length does
    not match the key, rather than silently matching on a prefix.
  • Async: connection-acquisition errors are translated to peewee exception
    types, matching query execution.
  • Fix FieldAlias.model to reference the model alias rather than the aliased
    model, alias-rooted join queries no longer construct and discard a spurious
    instance of the aliased model for every result row.
  • Fix playhouse.postgres_ext.JSONField creating jsonb columns after the
    core postgres backend began mapping the JSON field-type to JSONB, its DDL
    is json again, and json-vs-jsonb function selection for chained lookups
    now follows the field's declared datatype.
  • Unaliased expressions in join queries now hydrate using the same cleaned
    attribute name as flat queries (e.g. COUNT rather than COUNT(1).
  • Field.__hash__ is keyed on the model's schema and table-name rather than
    its class name, so same-named model classes (factories, separate modules,
    schema-per-tenant layouts) no longer collide in field-keyed registries such
    as backrefs, redefining or re-importing a model in place still replaces
    its entries.
  • Fix UnboundLocalError when joining from a model-less source to a model,
    e.g. join_from(cte, SomeModel, on=...), the joined instance is stored in
    the source's row dict, keyed by the model name.
  • BlobField, CompressedField and the sqlite_udf.gzip() function encode
    str values using utf-8 instead of raw_unicode_escape. Behavior change
    for non-ASCII strings: characters
    above the latin-1 range are no longer mangled into literal escape
    sequences, but blobs written from non-ASCII strings by earlier versions
    will not compare equal to newly-written ones.

View commits

v4.1.2

Compare Source

  • Ensure quotes escaped in SQLite introspection methods, thanks @​greymoth-jp
    for reporting and the initial patch.
  • Allow TimestampField to accept an iso-formatted str.
  • Add key-existence predicates (has_key, has_keys, has_any_keys) to the
    core JSONField on SQLite, implemented with json_type().
  • Add containment predicates (contains, contained_by) to the core
    JSONField on SQLite via a registered _pw_json_contains UDF that emulates
    Postgres' @> semantics (structural, level-aligned). The core JSONField
    now has full predicate parity across SQLite, Postgres, and MySQL/MariaDB.

View commits

v4.1.1

Compare Source

  • New declarative API for pre-fetching related instances (Load()). See
    documentation.
    This replaces prefetch(), is more flexible and also supports options for
    applying a row limit to sub-results, and a strategy that materializes the ID
    list (in addition to SELECT IN and JOIN strategies).
  • Add MySQLJSONField (playhouse.mysql_ext) with contains_any() for the
    JSON_OVERLAPS/"match any" counterpart to contains for JSON arrays.
  • Do not traverse foreign-key fields where lazy_load=False when serializing
    recursively with model_to_dict(), #​3055.
  • Add vendored typeshed stub with improvements.

View commits

v4.1.0

Compare Source

  • Unfortunately, the new JSONField did not play nice w/MySQL when query was
    generated before a conn was opened. We were trying to do some introspection
    on the server version, but I've decided instead to make mariadb= be a
    database param, per @​alisonatwork's suggestion, with the default being
    "MySQL" flavored JSON. Refs #​3053
  • JSONField containment (contains, contained_by) no longer wraps its
    argument in CAST / JSON_COMPACT on MySQL/MariaDB, #​3053.

View commits

v4.0.9

Compare Source

  • Ensure new JSONField can be inherited, #​3052

View commits

v4.0.8

Compare Source

  • Add BaseQuery.aexecute() - an async twin of execute() available on all
    query types, executing through the query's bound async database:
    await User.select().aexecute(), await user.tweets.aexecute(). Returns
    exactly what execute() returns, including result rows for DML with
    RETURNING. Queries remain non-awaitable, this is an ordinary coroutine
    method and the only async method on queries.
  • Add async model methods to playhouse.pwasyncio using "a"-prefixed coroutine
    counterparts of the row-level Model methods (acreate, aget,
    aget_or_none, aget_by_id, aget_or_create, aset_by_id,
    adelete_by_id, abulk_create, abulk_update, asave,
    adelete_instance), available via the new AsyncModel /
    AsyncModelMixin classes. Each is a thin delegation through the greenlet
    bridge, so behavior is identical to the synchronous implementation.
    Note: the Model property of async databases now returns a base class
    that includes these methods - relevant only if you introspect the base
    class of db.Model subclasses.
  • Add afetch() for explicit, awaitable lazy foreign-key resolution:
    user = await tweet.afetch(Tweet.user). Already-loaded relations (via
    join or prefetch) return immediately without a query.
  • Add db.first(query, n=1) async helper.
  • MissingGreenletBridge errors now include a hint describing the async
    APIs to use.
  • The asyncio extension is no longer considered preliminary - the async
    APIs documented in the docs
    are stable. The asyncio stress test now also runs in CI.

View commits

v4.0.7

Compare Source

  • Fixes for playhouse.pwasyncio: report correct UPDATE / DELETE rowcounts on
    asyncpg, roll back open transactions when connections are returned to the
    pool, raise instead of deadlocking when querying during iterate(), and
    detect the MySQL / MariaDB server version.
  • Additional playhouse.pwasyncio fixes: a second iterate() on a busy
    connection raises instead of deadlocking, asyncpg exceptions are translated
    to peewee exception types, registered aggregates / collations / window
    functions / extensions and timeout are applied to async SQLite
    connections, :memory: databases use a single connection, atomic()
    accepts transaction arguments (e.g. lock_type), postgres connection URLs
    and isolation_level are supported, %% in raw SQL is unescaped, and
    attempting a query outside the greenlet bridge no longer emits "never
    awaited" warnings.
  • Fixes for playhouse.pydantic_utils: JSON fields validate as Any (now
    including the sqlite_ext JSONField), foreign keys may be included /
    excluded by field name or column name, server-side defaults like
    SQL('CURRENT_TIMESTAMP') are no longer emitted as schema defaults, and
    relationships keys are validated.
  • Add a new cross-backend JSONField to core that provides basic operations
    and also more consistent behavior when reading data. By default the new core
    JSONField treats extracted values as JSON, which is generally the correct
    thing, but "text-mode" is available as a chained .as_text() method. See
    docs.
    May eventually replace the backend-specific implementations with subclasses
    that inherit semantics of this new field.
    Note: playhouse.mysql_ext.JSONField is now the core field. The old
    json_dumps / json_loads arguments are renamed dumps / loads, the
    extract() method is removed (use item-access or path()), and MySQL
    tables are now created with JSON columns rather than TEXT.
  • Eliminate use of deprecated params when connecting to MySQL databases, thanks

Note

PR body was truncated to here.


Configuration

📅 Schedule: (in timezone Europe/Prague)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 Immortal: This PR will be recreated if closed unmerged. Get config help if that's undesired.


  • If you want to rebase/retry this PR, check this box

To execute skipped test pipelines write comment /ok-to-test.


Documentation

Find out how to configure dependency updates in MintMaker documentation or see all available configuration options in Renovate documentation.

@sourcery-ai

sourcery-ai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Dependency update PR bumping major versions of gunicorn, peewee, prometheus-async, and pytz in pyproject.toml, with corresponding changes in poetry.lock.

File-Level Changes

Change Details Files
Upgrade gunicorn to 26.x with associated lockfile updates.
  • Update gunicorn version constraint from 23.x to 26.x in pyproject dependency list.
  • Refresh poetry.lock entries for gunicorn and transitive dependencies to match the new version.
pyproject.toml
poetry.lock
Upgrade peewee ORM to 4.x with associated lockfile updates.
  • Update peewee version constraint from 3.18.x to 4.x in pyproject dependency list.
  • Refresh poetry.lock entries for peewee and its transitive dependencies to match the new major version.
pyproject.toml
poetry.lock
Upgrade prometheus-async to 26.x with associated lockfile updates.
  • Update prometheus-async version constraint from 25.x to 26.x in pyproject dependency list.
  • Refresh poetry.lock entries for prometheus-async and transitive dependencies to match the new version.
pyproject.toml
poetry.lock
Upgrade pytz to the latest 2026.2 release in lockfile (if pinned there).
  • Ensure pytz is bumped from 2025.2 to 2026.2 in dependency resolution metadata, likely within poetry.lock.
poetry.lock

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@red-hat-konflux
red-hat-konflux Bot force-pushed the konflux/mintmaker/master-master/major-poetry-deps branch from 717f91f to a6eed2a Compare August 3, 2026 18:58
Signed-off-by: red-hat-konflux <126015336+red-hat-konflux[bot]@users.noreply.github.com>
@red-hat-konflux
red-hat-konflux Bot force-pushed the konflux/mintmaker/master-master/major-poetry-deps branch from a6eed2a to af3fb9d Compare August 22, 2026 01:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants