Compare commits

..
Author SHA1 Message Date
Elior Nataf LackritzandGitHub 2d942085e2 fix(langgraph): fork before replaying an update checkpoint the thread moved past (#9170)
Depends on #9165

A replay saves a fork checkpoint first, so its writes land on the fork. Two things still reached the checkpoint it replayed from, and through it every branch that already grew from that checkpoint.

It skips the fork for an update or fork checkpoint, which is already a branch of its own. Once the thread has moved past such a checkpoint it can have children, and the replay's writes stored on it reach every one of them. Edit a checkpoint, continue from it, then replay the edit, and the branch you continued reads back a write it never ran:

```
plain channel: ['in1', 'a', 'b', 'edit', 'in2', 'a', 'b']
DeltaChannel:  ['in1', 'a', 'b', 'edit', 'b', 'in2', 'a', 'b']
                                         ^ the replay's b
```

And a `Command(update=...)` or `Command(goto=...)` replayed from any checkpoint stored its writes there before the run saved its fork. The branches that grew from that checkpoint replayed the update into a `DeltaChannel`, and a later replay of the same checkpoint repeated the old `Command`: the update again, in every channel, or the `goto`'s node again.

Both happen on `main`.

## Fix

Loading a checkpoint addressed by `checkpoint_id` checks, for update and fork checkpoints only, whether the thread has moved past it, with #9165's `checkpoint_superseded`. If it has, the replay saves its fork checkpoint as it does from any other checkpoint. Subgraphs keep replaying from the edit's parent, as they did without the fork.

The run decides on the fork before it stores anything. When it forks, it keeps the `Command`'s writes in memory and applies them, and the fork snapshots the delta channels they write, so the fork carries them and nothing lands on the checkpoint the run addressed.

Cost: one extra `get_tuple` when a run addresses an update or fork checkpoint by `checkpoint_id`, such as resuming with the config `update_state` returned. A replay from an edit the thread moved past stores one more checkpoint, and a forked `Command` that writes a delta channel stores a snapshot of it.

## Limits

- A `Command(resume=...)` addressed at a checkpoint the thread moved past doesn't fork, so its run's writes still land there, and a branch that grew from that checkpoint without answering the interrupt replays them. Same on `main`. A fork would give the tasks new ids, and interrupt ids and resume-map keys are hashes of the task's namespace, which includes the task id, so a resume map built from the interrupts the caller just read would stop matching. This needs writes that record their branch (#9174).

## Tests

`test_delta_channel_fork.py`, on the shared checkpointer fixtures in all durabilities:

- replay from an edit the thread moved past, with and without a subgraph, sync and async, with no input and with `Command(update=...)`
- a `Command(update=...)` or `Command(goto=...)` replay of a plain checkpoint the thread moved past: the branch that grew from it reads back unchanged, and a later replay of the checkpoint doesn't repeat the `Command`

124 of the 186 cases fail on #9165; the exit ones pass either way.
2026-10-05 13:46:44 -04:00
456e2b1acc fix(langgraph): keep an update_state on an older checkpoint out of its other branches (#9165)
Fixes #8551

`update_state` stores its writes on the checkpoint it addresses. A
`DeltaChannel` rebuilds its value by replaying the writes stored on its
ancestors, so when that checkpoint already has another child, the edit
shows up in that branch too. #8551's repro, editing an earlier turn and
then reading the branch that already existed:

```
before the edit: ['in-1', 'first-out', 'in-2', 'second-out']
after the edit:  ['in-1', 'first-out', 'patched', 'in-2', 'second-out']
```

The plain reducer channel in the same graph is unaffected. #8548 already
keeps the edited branch itself correct; this is the other direction.

## Fix

When `update_state` addresses a checkpoint that is not the thread's
latest, the checkpoint it creates snapshots the delta channels the
update writes, through the same snapshot #8548 adds for forks, and none
of the update's writes are stored on the addressed checkpoint, whatever
channels it writes. The edited branch reads the snapshot, and the other
branches have nothing new to replay. The addressed checkpoint stays as
it was, so a later `as_node=END` update on it doesn't take the edit in,
and the edit doesn't show as that checkpoint's task result. On `main`
both can happen in any graph, with or without a `DeltaChannel`, and a
`DeltaChannel` also takes in the other branch's writes.

"Not the latest" is one extra `get_tuple` for the thread, made when the
config names a `checkpoint_id`. It compares with the latest put, so a
checkpoint that has a child always counts. So does a leaf of an
abandoned branch, such as the old head after a fork elsewhere, where
nothing could leak; telling the two apart would mean listing the thread,
since savers have no lookup by parent. The addressed checkpoint's
pending writes can't answer it either: a finished turn that a later run
continued from has none, which is #8551's case.

Updates on the latest checkpoint are unchanged: no snapshot, same
writes.

## Cost

Editing an older checkpoint stores one snapshot per delta channel the
update writes, the size of that channel's regular snapshot. That
includes editing a leaf of an abandoned branch, as above.

## Limits

- Threads that already leaked keep the leaked write, since it is stored
on the old checkpoint.
- The second report in #8551, `RemoveMessage(id=REMOVE_ALL_MESSAGES)`
through `_messages_delta_reducer`, is that reducer's documented limit
and isn't changed here.

## Tests

`test_delta_channel_fork.py`, on the shared checkpointer fixtures:

- `update_state` / `aupdate_state` on an older checkpoint, both a
finished turn and one whose next node already ran there: the other
branch reads back unchanged, and continuing it stays clean
- `bulk_update_state` with two supersteps from an older checkpoint
- `update_state` with the head's `checkpoint_id` still stores no
snapshot
- `update_state(None, as_node=END)` on an edited checkpoint: an older
one leaves the edit out, also when it wrote only plain channels, and the
latest one keeps it in both channels

33 of the 59 cases fail on `main`. The rest pass either way: the head
case, the case whose next node already ran, where the saver keeps that
node's own write and drops the edit's, and `as_node=END` on the latest
checkpoint.

Thanks to @AnnaSuSu for the report, the repro, tracing the leak to the
writes landing on the addressed checkpoint, and the note that the fix
needs a snapshot on the new checkpoint first.

---------

Co-authored-by: Wenchao An <64579968+AnnaSuSu@users.noreply.github.com>
2026-10-05 17:40:47 +00:00
Elior Nataf LackritzandGitHub 1b84cb0873 fix(langgraph): keep DeltaChannel counters on every update_state path (#9142)
`update_state` saves `counters_since_delta_snapshot` on the checkpoint
it creates, except on three paths: `update_state(None, as_node=END)`,
`as_node="__input__"` and `as_node="__copy__"`. Those save their
checkpoint without it, so the next checkpoint restarts every delta
channel's counters from zero:

```
before update_state(None, END): [6, 9]
after it:                       (none)
after the next run:             [2, 3]   (with this change: [6, 10], then [8, 13])
```

The counters decide when a channel snapshots, so after any of these
updates the next snapshot comes later than `snapshot_frequency` and
reads walk further back. A thread driven only by these updates never
snapshots, so its walk keeps growing. The field's docstring says it is
absent only on threads that don't use delta channels.

## Fix

`END` and `__input__` build their checkpoint with
`create_checkpoint_plan_for_update_state_api`, the plan an update as a
node already uses, which now takes the checkpoint's `source`. The
counters advance by one superstep (`END` counts the channels its
absorbed writes touched as updated), and a channel that reaches its
bound snapshots right there. `__copy__` saves a checkpoint with the same
values on the same parent, so it keeps the copied checkpoint's counters.

## Tests

`test_delta_channel_supersteps_bound.py`, sync and async:
- each of the three paths saves the base's counters advanced by one
superstep (or unchanged for `__copy__`).
- `END` and `__input__` snapshot a channel that reaches its supersteps
bound.

All 10 fail on main.
2026-10-05 13:04:30 -04:00
Igor SoarezandGitHub 8e15e0d0bc release(langgraph): 1.2.13 (#9205)
Bumps langgraph from 1.2.12 to 1.2.13.

Stops reporting answered interrupts in `get_state()` (#9103, fixes
#6956,
fixes #8579): latest-state reads now omit interrupts from finished
tasks,
and `Command(resume=value)` without an interrupt id raises when more
than one
interrupt is pending.

Also fixes DeltaChannel history handling: subgraph delta channels now
hydrate with the caller-resolved saver (#8538), an abandoned branch is
no
longer replayed into a DeltaChannel fork (#8548), and history is no
longer
walked for a DeltaChannel that was never written (#9141).

Dependency updates in `libs/langgraph`: pyjwt 2.13.0 → 2.15.1,
urllib3 2.7.0 → 2.8.0, tornado 6.5.8 → 6.5.9, notebook 7.5.6 → 7.5.7.
2026-10-05 12:13:11 -04:00
Elior Nataf LackritzandGitHub 524b320e30 fix(langgraph): don't walk history for a DeltaChannel that was never written (#9141)
A `DeltaChannel` with no version at a checkpoint was never written, so
its value is empty. `channels_from_checkpoint` still asked the saver for
its history, and with no snapshot to stop at, the walk reads every
ancestor of the thread, on every run and every `get_state`. A channel
that never gets written is common: deepagents' `files` channel when an
agent doesn't use files.

On SQLite the walk fails outright once the thread is long enough,
because stage 2 binds one variable per ancestor. With one never-written
channel on a 33,000-step thread:

```
main:   get_state  -> OperationalError: too many SQL variables
        next run   -> OperationalError: too many SQL variables
branch: get_state ok in 1 ms, next run ok
```

## Fix

Only channels that have a version at the checkpoint are walked. A
channel without one hydrates empty without asking the saver.

A version is assigned whenever a channel is written (by a task, an
input, `update_state` or a migration from a plain channel), so no
version means no write on this branch. The walk could only have found
writes this branch never applied.

Snapshotting such a channel instead would also bound the walk, but it
writes a blob for an empty value on every thread. Today
`create_checkpoint` skips any channel without a version, so even the
forced `DELTA_MAX_SUPERSTEPS_SINCE_SNAPSHOT` snapshot never lands for
it, and the walk has no bound.

## Tests

`test_delta_channel_supersteps_bound.py`: a graph whose second delta
channel is never written asks the saver only for the written channel's
history, sync and async. Both fail on main (`asked for [['a', 'b'],
['a', 'b']]`). A third test covers the case the skip must not break: a
delta channel's first write, left pending on an interrupted head before
the channel has a version, lands exactly once on resume. It passes on
main too.

JS twin: langchain-ai/langgraphjs#2927.
2026-10-05 11:20:32 -04:00
9a0394d88b fix(langgraph): don't replay an abandoned branch into a DeltaChannel fork (#8548)
Fixes #8443
Fixes #9089

A checkpoint keeps the pending writes that produced its child, and
nothing records which child consumed them. When a new branch starts from
a checkpoint that already has pending writes (going back in time, or new
input on an interrupted head), the `DeltaChannel` ancestor walk replays
those writes into the new branch too. The live run is correct; only a
reload is wrong:

```
fork base:     ['in-1', 'first-out']
fork returns:  ['in-1', 'first-out', 'in-3', 'third-out']
reload gives:  ['in-1', 'first-out', 'in-2', 'in-3', 'third-out']
                                     ^^^^^^ from the branch the fork replaced
```

Plain channels store their full value and are unaffected, so the tests
use one as the oracle.

## Fix

The first checkpoint of a new branch snapshots the delta channels its
base has pending writes for, so the walk stops inside the branch. Only
the base's own writes are branch-specific; everything above it is shared
history. A base with no pending writes has nothing to leak, so an
ordinary turn that addresses the head (as clients commonly do) stores
nothing. `bulk_update_state` takes the set from its first superstep
only: a `__copy__` is stored under the base's parent, so nothing after
it walks the base's writes. A resume that is not replaying reuses the
head's pending writes instead of rerunning their tasks, so it seals only
the loaded writes that don't go back to their task: a finished task
whose `Send` a `Command(goto=...)` replaced, or an error handler that
runs again. A plain resume stores nothing. A resume addressed by
`checkpoint_id` reruns them, so it still seals.

`put` only stores a blob for a channel whose version moved since the
last stored checkpoint, so a snapshot of one that didn't move needs a
version bump, and scheduling reads versions. `create_checkpoint`
therefore advances every `versions_seen` entry that had seen the old
version, including the interrupt tracker. Without the advance, the bump
re-fires `interrupt_before` on resume and reruns the channel's
subscribers. For each entry it advances, `SNAPSHOT_BUMPS` keeps the
version the node really read, so `update_state`'s `as_node` inference
reads `versions_seen` as if the bump never happened. A never-written
channel gets a version only for the seal; the cadence and a fresh
thread's first `update_state` skip it.

`update_state` no longer records its narrower `updated_channels` when it
snapshots; it skipped a deferred node listed in `next` on resume
(#9089).

The same seal fixes two `update_state` calls on one checkpoint (editing
the same message twice): both store their writes there under the same
task id, the saver keeps the first, and the second branch read back the
first one's edit.

Two things this touches were also wrong on `main`: a resumed error
handler that runs again left its stored writes on the head (an exit
reload read them twice), and `aupdate_state` on a thread seeded only by
updates raised "Ambiguous update" where `update_state` applied the
update as the input. `update_state` and `aupdate_state` now share one
`as_node` inference.

Exit durability has a separate replay bug on `main` when a resumed
checkpoint already holds writes (duplicated or reordered replay),
unrelated to forks. It's fixed in #9114; the resume test here marks exit
durability as a strict expected failure until then.

`tests/memory_assert.py` now compares against the checkpoint as read
back: a delta channel a step didn't write is refilled on read, which the
old comparison reported as a mutation.

Cost: 300 turns addressing the head store no snapshots, as on `main`. A
resume that reruns finished tasks seals every time. After a parallel
task finished, 30 turns of resuming with the head's `checkpoint_id`
(what Studio sends) stored 30 snapshots, 191 KB, against 12 KB of delta
writes, and a subgraph resume with a finished sibling does the same,
since a subgraph loop always counts as replaying. That seal is what
keeps a rerun task's new write from being replayed as its old one:
without it, a subgraph task that returns something different on the
rerun reads back its first result. The reruns happen on `main` too, and
stopping them would remove this cost.

276 of 464 cases in `test_delta_channel_fork.py` fail on `main` and pass
here (memory, sqlite and postgres, all durabilities). #9089's own case
is in `test_delta_channel_update_state.py`, the cadence case in
`test_delta_channel_supersteps_bound.py`, and the `as_node` cases in
`test_pregel.py`.

## Limits

- Threads forked before this change keep their state: the ownership was
never recorded, so there is nothing to recover.
- With exit durability, a fork at a finished turn stores its writes on
the shared base, so the original branch then replays them too (`['h1',
'ai', 'h2-edited', 'ai', 'h2', 'ai']`). Same on `main`.
- `Command(update=..., goto=...)` sent to an old checkpoint stores the
update there, so the original branch replays it too. The fork itself is
correct now; the original branch is the same as on `main`.
- #8551 (the mirror case: `update_state`'s own writes leaking into the
abandoned branch) is fixed in #9165, stacked on this PR. It builds on
this snapshot, but keys off whether the addressed checkpoint is the
thread's latest rather than on pending writes, which a finished turn
that a later run continued from doesn't have.

Thanks to @AnnaSuSu for the report, the reproduction and the snapshot
approach, and to @UditDewan for the implementation in #8476. Both are
co-authors.

---------

Co-authored-by: AnnaSuSu <64579968+AnnaSuSu@users.noreply.github.com>
Co-authored-by: UditDewan <194863456+UditDewan@users.noreply.github.com>
2026-10-03 08:55:59 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
7dc9195e41 chore(deps): bump notebook from 7.5.6 to 7.5.7 in /libs/langgraph (#9168)
Bumps [notebook](https://github.com/jupyter/notebook) from 7.5.6 to
7.5.7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jupyter/notebook/releases">notebook's
releases</a>.</em></p>
<blockquote>
<h2>v7.5.7</h2>
<h2>7.5.7</h2>
<p>(<a
href="https://github.com/jupyter/notebook/compare/@jupyter-notebook/application-extension@7.5.6...af55f111d335315edd9e5eab472c9c1bbbb17b27">Full
Changelog</a>)</p>
<h3>Maintenance and upkeep improvements</h3>
<ul>
<li>Pin Node to 22.x in UI tests <a
href="https://redirect.github.com/jupyter/notebook/pull/7940">#7940</a>
(<a href="https://github.com/jtpio"><code>@​jtpio</code></a>)</li>
<li>Update to JupyterLab v4.5.8 <a
href="https://redirect.github.com/jupyter/notebook/pull/7939">#7939</a>
(<a href="https://github.com/jtpio"><code>@​jtpio</code></a>)</li>
</ul>
<h3>Contributors to this release</h3>
<p>The following people contributed discussions, new ideas, code and
documentation contributions, and review.
See <a
href="https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports">our
definition of contributors</a>.</p>
<p>(<a
href="https://github.com/jupyter/notebook/graphs/contributors?from=2026-04-30&amp;to=2026-06-04&amp;type=c">GitHub
contributors page for this release</a>)</p>
<p><a href="https://github.com/jtpio"><code>@​jtpio</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnotebook+involves%3Ajtpio+updated%3A2026-04-30..2026-06-04&amp;type=Issues">activity</a>)</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jupyter/notebook/blob/@jupyter-notebook/tree@7.5.7/CHANGELOG.md">notebook's
changelog</a>.</em></p>
<blockquote>
<h2>7.5.7</h2>
<p>(<a
href="https://github.com/jupyter/notebook/compare/@jupyter-notebook/application-extension@7.5.6...af55f111d335315edd9e5eab472c9c1bbbb17b27">Full
Changelog</a>)</p>
<h3>Maintenance and upkeep improvements</h3>
<ul>
<li>Pin Node to 22.x in UI tests <a
href="https://redirect.github.com/jupyter/notebook/pull/7940">#7940</a>
(<a href="https://github.com/jtpio"><code>@​jtpio</code></a>)</li>
<li>Update to JupyterLab v4.5.8 <a
href="https://redirect.github.com/jupyter/notebook/pull/7939">#7939</a>
(<a href="https://github.com/jtpio"><code>@​jtpio</code></a>)</li>
</ul>
<h3>Contributors to this release</h3>
<p>The following people contributed discussions, new ideas, code and
documentation contributions, and review.
See <a
href="https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports">our
definition of contributors</a>.</p>
<p>(<a
href="https://github.com/jupyter/notebook/graphs/contributors?from=2026-04-30&amp;to=2026-06-04&amp;type=c">GitHub
contributors page for this release</a>)</p>
<p><a href="https://github.com/jtpio"><code>@​jtpio</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnotebook+involves%3Ajtpio+updated%3A2026-04-30..2026-06-04&amp;type=Issues">activity</a>)</p>
<!-- raw HTML omitted -->
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/jupyter/notebook/commit/a25fa5eda09ef85984ddafe4a5def427bf34912b"><code>a25fa5e</code></a>
Publish 7.5.7</li>
<li><a
href="https://github.com/jupyter/notebook/commit/af55f111d335315edd9e5eab472c9c1bbbb17b27"><code>af55f11</code></a>
Update to JupyterLab v4.5.8 (<a
href="https://redirect.github.com/jupyter/notebook/issues/7939">#7939</a>)</li>
<li><a
href="https://github.com/jupyter/notebook/commit/1f7059106ebdd038ecd30512295e2d1f77b7d698"><code>1f70591</code></a>
Pin Node to 22.x in UI tests to avoid Playwright install hang (<a
href="https://redirect.github.com/jupyter/notebook/issues/7940">#7940</a>)</li>
<li>See full diff in <a
href="https://github.com/jupyter/notebook/compare/@jupyter-notebook/tree@7.5.6...@jupyter-notebook/tree@7.5.7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=notebook&package-manager=uv&previous-version=7.5.6&new-version=7.5.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-02 14:14:46 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1fd716c44a chore(deps): bump virtualenv from 21.7.12 to 21.7.13 in /libs/cli (#9167)
Bumps [virtualenv](https://github.com/pypa/virtualenv) from 21.7.12 to
21.7.13.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pypa/virtualenv/releases">virtualenv's
releases</a>.</em></p>
<blockquote>
<h2>21.7.13</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>👷 ci: correct a stale checkout pin comment by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3254">pypa/virtualenv#3254</a></li>
<li>🔧 chore: drop misc as a changelog fragment type by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3255">pypa/virtualenv#3255</a></li>
<li>👷 ci: scope the nushell apt key to its own repo by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3253">pypa/virtualenv#3253</a></li>
<li>🐛 fix(activation): stop path command injection in bash and fish by
<a href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a>
in <a
href="https://redirect.github.com/pypa/virtualenv/pull/3252">pypa/virtualenv#3252</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/pypa/virtualenv/compare/21.7.12...21.7.13">https://github.com/pypa/virtualenv/compare/21.7.12...21.7.13</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pypa/virtualenv/blob/main/docs/changelog.rst">virtualenv's
changelog</a>.</em></p>
<blockquote>
<h1>Bugfixes - 21.7.13</h1>
<ul>
<li>Fix <code>activate</code> and <code>activate.fish</code> running
commands embedded in the virtual environment path or in the
interpreter's Tcl/Tk library paths. (:issue:<code>3252</code>)</li>
</ul>
<hr />
<p>v21.7.12 (2026-09-18)</p>
<hr />
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pypa/virtualenv/commit/0c295ff1a5f298e8e11935e3588f59f7455c1f8f"><code>0c295ff</code></a>
release 21.7.13</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/4d5a105ec2a2723b8c7f4571bb68f4f71d01e3f6"><code>4d5a105</code></a>
🐛 fix(activation): stop path command injection in bash and fish (<a
href="https://redirect.github.com/pypa/virtualenv/issues/3252">#3252</a>)</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/0525dcea21865059ffedc70054f6f982be723992"><code>0525dce</code></a>
👷 ci: scope the nushell apt key to its own repo (<a
href="https://redirect.github.com/pypa/virtualenv/issues/3253">#3253</a>)</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/aa8323a907834e9c16fb734613ce41a6d7e27260"><code>aa8323a</code></a>
🔧 chore: drop misc as a changelog fragment type (<a
href="https://redirect.github.com/pypa/virtualenv/issues/3255">#3255</a>)</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/a43547765e017f3a13f029e24c6e6f73882e15bc"><code>a435477</code></a>
👷 ci: correct a stale checkout pin comment (<a
href="https://redirect.github.com/pypa/virtualenv/issues/3254">#3254</a>)</li>
<li>See full diff in <a
href="https://github.com/pypa/virtualenv/compare/21.7.12...21.7.13">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=virtualenv&package-manager=uv&previous-version=21.7.12&new-version=21.7.13)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-02 14:14:30 -07:00
3af263175f fix(langgraph): hydrate subgraph delta channels with the caller-resolved saver (#8538)
Fixes langchain-ai/langgraph#8470
Fixes langchain-ai/langgraph#8653

Reported by @gururafiki, with a self-contained `InMemorySaver` repro and
the observation that non-delta channels in the same namespace hydrate
fine, which is what makes the failure silent. @doniyor2109 reported
#8653, the same missing saver at the root: a graph compiled without a
checkpointer, whose saver arrives through the config, read the channel
back empty in `get_state`, `get_state_history` and `update_state`.

### The bug, in one read

One subgraph state, two channels written by the same nodes: `delta` is a
`DeltaChannel`, `plain` is an `operator.add` list. Pause the subgraph
before its second node and read it through the documented
`get_state(config, subgraphs=True).tasks[0].state`:

```
main:   {'delta': [],     'plain': ['a1']}
branch: {'delta': ['a1'], 'plain': ['a1']}
```

Same call, same instant, same state object. If this were a rule about
how subgraphs manage state, both channels would be empty. Only the delta
one is, because it is the one channel type that stores nothing in
`channel_values` and has to replay its writes through a saver.

### Why only the delta channel

A subgraph has no saver of its own. It either inherits the parent's (the
default, "per-invocation") or opts in with `checkpointer=True`
("per-thread"), and in both cases the saver reaches it through
`CONFIG_KEY_CHECKPOINTER`. All four public readers resolve it from
there. `_prepare_state_snapshot` then ignored that and re-derived the
saver from `self.checkpointer`:

- per-invocation: `self.checkpointer` is `None`
- per-thread: `self.checkpointer` is `True`, and `isinstance(True,
BaseCheckpointSaver)` is `False`

So the explicit per-thread opt-in, the mode that exists to make subgraph
state readable across invocations, was broken too. With no saver the
ancestor walk never runs and the channel falls through to
`from_checkpoint(MISSING)`: an empty value, indistinguishable from never
written, raising nothing.

The saver can't be recovered inside the function: `get_state_history`
passes the checkpointer's stored config, which never carries a live
saver. The caller is the only place it exists, so the caller passes it,
as a required keyword argument.

### What stays unchanged

The two modes from the [subgraph persistence
docs](https://docs.langchain.com/oss/python/langgraph/use-subgraphs#subgraph-persistence)
where an empty read is correct are pinned by tests that pass before and
after:

- `checkpointer=False` persists nothing, so there is no subgraph
namespace to read.
- after a subgraph completes, `subgraphs=True` has no pending task to
attach state to, for every channel type alike.

### The write path loses data on disk

`bulk_update_state` / `abulk_update_state` carried the same expression.
When an update reaches the channel's snapshot cadence,
`create_checkpoint` persists a `_DeltaSnapshot` built from the empty
hydration, so `update_state` on a subgraph namespace replaces `['a1',
'b1', 'b2']` with `['manual']` permanently. At the default
`snapshot_frequency=1000` no snapshot is written and the loss stays
latent; the tests use `snapshot_frequency=2` to reach it.

`prepare_next_tasks` in `_prepare_state_snapshot` now receives the same
saver too. It was inert there (the task config falls back to
`CONFIG_KEY_CHECKPOINTER`, and `PregelTask` exposes no config), but one
expression is easier to trust than two.

### One saver lookup and namespace rule

The run loop and all six state methods now share one saver lookup
(`_resolve_checkpointer`) and one namespace rule for `checkpointer=True`
subgraphs, and the state methods find the subgraph a namespaced config
addresses through one helper (`_subgraph_for_namespace`). Before, only
`get_state` / `aget_state` stripped the task id, so `get_state_history`
and `update_state` given the subgraph task's config looked under
`name:<task_id>`, where the run never stores anything: the history came
back empty and the update was silently lost.

The namespace rule strips only the task ids: a task that calls the same
`checkpointer=True` subgraph twice stores the second call under
`<node>|1`, and `recast_checkpoint_ns` would drop that counter.

Sharing the lookup with runs also fixes two places where a state method
disagreed with a run: a `checkpointer=False` graph ignores a saver lent
through the config, so `update_state` raises "No checkpointer set"
instead of writing a checkpoint no run reads, and a `checkpointer=True`
graph used as root raises the run's `checkpointer=True cannot be used
for root graphs.` instead of an AttributeError.

`channels_from_checkpoint` now raises when a `DeltaChannel` has a
version but no stored value and no saver or config was passed, so a
caller that forgets either fails instead of reading `[]`. Keying on the
version keeps a never-written channel reading as empty.

### Verification

`tests/test_delta_channel_subgraph.py` runs against the shared
`sync_checkpointer` / `async_checkpointer` fixtures (memory, sqlite,
postgres), and every assertion compares both channels:

| surface | on main |
| -- | -- |
| `get_state` / `aget_state` on a subgraph ns | `delta: []` |
| `get_state_history` / `aget_state_history` | every snapshot `delta:
[]` |
| two levels of nesting | `delta: []` |
| `get_state(subgraphs=True)` / async, interrupted, per-invocation and
per-thread | `delta: []` |
| `update_state` / `aupdate_state` | `delta: ['manual']`, prior history
lost |
| `get_state_history` / `update_state` from a `checkpointer=True`
subgraph's task config, sync and async | no snapshots / update lost |
| `channels_from_checkpoint` with a written delta channel and no saver
or config | silent `[]` |
| `get_state` / `update_state` / `get_state_history` on a graph compiled
without a checkpointer, saver lent through the config (#8653), sync and
async | `delta: []` |
| `get_state` of a `checkpointer=True` subgraph's second call in one
task (`node\|1`), sync and async | the first call's state |

159 cases: 144 fail on main, all 159 pass here. The 15 that pass on main
are the two unchanged-mode controls and the never-written case.

---------

Co-authored-by: gururafiki <22777967+gururafiki@users.noreply.github.com>
Co-authored-by: Yuan Gao <119447586+DavidGao520@users.noreply.github.com>
2026-10-02 15:26:54 +00:00
Igor SoarezandGitHub e6cf9ea667 fix(langgraph): stop reporting answered interrupts in get_state (#9103)
Execution, snapshots, and resume checks interpreted the same pending
writes separately.

When one of several interrupted tasks finished after resuming,
`get_state()` still reported its answered question as pending.

Use `read_task_statuses()` across execution, state reads, and resume
checks.
An output write marks a task finished; `RESUME` alone does not, since
the
task may pause again. Record `NO_WRITES` when a resumed task completes
without output, so it isn't run again.

Latest-state reads now omit interrupts from finished tasks. History and
explicit checkpoint reads still show the last recorded interrupt per
task. A task paused at its second interrupt appears in `next` with
`result=None`. `Command(resume=value)` without an id now raises when
more than one interrupt is pending, including in a subgraph.

Threads paused before this change, where a resumed task finished without
output, still show that task as unfinished. It appears in `next` and its
answered interrupt counts as pending, so if another interrupt is also
pending, `Command(resume=value)` without an id raises. Resume these
threads by interrupt id. On SQLite and Postgres, insert-ignore can leave
an old `RESUME` value for a finished task; that task does not run again.

Fixes #6956
Fixes #8579

Thanks to @gautamvarmadatla and @russeell for reporting these.
2026-10-02 11:02:27 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedyopen-swe[bot] <open-swe@users.noreply.github.com>
157a06dda9 chore(deps-dev): bump the minor-and-patch group across 1 directory with 5 updates (#9155)
Bumps the minor-and-patch group with 5 updates in the /libs/langgraph
directory:

| Package | From | To |
| --- | --- | --- |
| [langchain-core](https://github.com/langchain-ai/langchain) | `1.6.1`
| `1.6.5` |
| [pytest-mock](https://github.com/pytest-dev/pytest-mock) | `3.15.1` |
`3.16.0` |
| [syrupy](https://github.com/syrupy-project/syrupy) | `6.0.0` | `6.1.1`
|
| [ruff](https://github.com/astral-sh/ruff) | `0.16.5` | `0.16.9` |
| [ty](https://github.com/astral-sh/ty) | `0.0.75` | `0.0.84` |


Updates `langchain-core` from 1.6.1 to 1.6.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/langchain-ai/langchain/releases">langchain-core's
releases</a>.</em></p>
<blockquote>
<h2>langchain-core==1.6.5</h2>
<p>Changes since langchain-core==1.6.4</p>
<p>release(core): 1.6.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40816">#40816</a>)
fix(core): abbreviate long tool IDs in XML buffer strings (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40792">#40792</a>)</p>
<h2>langchain-core==1.6.4</h2>
<p>Changes since langchain-core==1.6.3</p>
<p>release(core): 1.6.4 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40718">#40718</a>)
chore(core): deprecate chat message history (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40711">#40711</a>)
chore(deps): bump anyio from 4.12.0 to 4.14.2 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40634">#40634</a>)
chore(deps): bump soupsieve from 2.8.4 to 2.9 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40574">#40574</a>)</p>
<h2>langchain-core==1.6.3</h2>
<p>Changes since langchain-core==1.6.2</p>
<p>release(core): 1.6.3 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40407">#40407</a>)
feat(core): Allow model name and provider tracing metadata override
based on gateway response (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40406">#40406</a>)
test(core): cover the deprecated <code>.text()</code> access path (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40243">#40243</a>)
docs(core): remove stale Args/Raises entries from
FileCallbackHandler._write and ChatGeneration.set_text (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40211">#40211</a>)</p>
<h2>langchain-core==1.6.2</h2>
<p>Changes since langchain-core==1.6.1</p>
<p>release(core): 1.6.2 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40209">#40209</a>)
feat(openai): support async tools (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40208">#40208</a>)
chore(deps): bump mistune from 3.3.0 to 3.3.3 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40150">#40150</a>)
chore(deps): bump tornado from 6.5.7 to 6.5.8 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40113">#40113</a>)
fix(core): avoid mutation in google-genai standard content (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40023">#40023</a>)
fix(core): avoid mutation in bedrock converse standard content (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40022">#40022</a>)</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/c5ab14d42a3e22865c9def909de0b11d70b0bbf0"><code>c5ab14d</code></a>
release(core): 1.6.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40816">#40816</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/5704d9d4813f8c0527f04e2662cf313e1350f96f"><code>5704d9d</code></a>
chore(model-profiles): refresh model profile data (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40804">#40804</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/7622d3dce760ac4be6d9aef4c653277e06064aea"><code>7622d3d</code></a>
release(openai): 1.6.6 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40800">#40800</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/2dd956b8add667dac4f97605ae441d75b8ae228e"><code>2dd956b</code></a>
docs(infra): fix AGENTS.md root setup guidance and package doc accuracy
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40794">#40794</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/49f4b4016b82513c3dc1623bf3daa10453861621"><code>49f4b40</code></a>
fix(openai): raise on error events in stream path (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40791">#40791</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/19cadaa1a1e0cac71f3148e2f18b414dcab17426"><code>19cadaa</code></a>
fix(core): abbreviate long tool IDs in XML buffer strings (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40792">#40792</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/798441e8b07e88e79db355db452cd9492f9628f2"><code>798441e</code></a>
chore(anthropic): fix integration test cassette (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40790">#40790</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/a476942bac3fe5e521676d0f53fabafcb7ba71b1"><code>a476942</code></a>
release(openai): 1.6.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40787">#40787</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/46c6bdf1b4e23028a5acc060d8b2797dbf200291"><code>46c6bdf</code></a>
release(anthropic): 1.7.4 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40786">#40786</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/290dabaff27ee379920d55d155d5055d2fe29cc8"><code>290daba</code></a>
fix(anthropic): add Opus 5.5 and GPT-6 profile augmentations (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40785">#40785</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.6.1...langchain-core==1.6.5">compare
view</a></li>
</ul>
</details>
<br />

Updates `pytest-mock` from 3.15.1 to 3.16.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/releases">pytest-mock's
releases</a>.</em></p>
<blockquote>
<h2>v3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/604">#604</a>:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/611">#611</a>:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/606">#606</a>:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/547">#547</a>:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/147">#147</a>:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst">pytest-mock's
changelog</a>.</em></p>
<blockquote>
<h2>3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><code>[#604](https://github.com/pytest-dev/pytest-mock/issues/604)
&lt;https://github.com/pytest-dev/pytest-mock/pull/604&gt;</code>_:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><code>[#611](https://github.com/pytest-dev/pytest-mock/issues/611)
&lt;https://github.com/pytest-dev/pytest-mock/pull/611&gt;</code>_:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><code>[#606](https://github.com/pytest-dev/pytest-mock/issues/606)
&lt;https://github.com/pytest-dev/pytest-mock/pull/606&gt;</code>_:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><code>[#547](https://github.com/pytest-dev/pytest-mock/issues/547)
&lt;https://github.com/pytest-dev/pytest-mock/issues/547&gt;</code>_:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><code>[#147](https://github.com/pytest-dev/pytest-mock/issues/147)
&lt;https://github.com/pytest-dev/pytest-mock/issues/147&gt;</code>_:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/f3b531f93c6d9837edc87ea1a6f4324dc9a2cdf3"><code>f3b531f</code></a>
Release 3.16.0</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/71ed67309520be160f3e100368705b58758d237a"><code>71ed673</code></a>
Fix duplicate_iterators for async spies (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/604">#604</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/0797e3d303cc5bbe0a3514b0625f7aeb3fa350b0"><code>0797e3d</code></a>
Fix async assertion argument introspection (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/611">#611</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/e24c334d573cfbf6989a31f4e3346676d9d31598"><code>e24c334</code></a>
docs: import os in the opening usage example (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/612">#612</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/9e7eb7b59cde362c1c8ace2d18ca00fe2d7a1cd1"><code>9e7eb7b</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/613">#613</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/445fd4d3daa8ed4c6d5428a77880da2e03d2f721"><code>445fd4d</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/610">#610</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/a8bd0b147afdf6b4bb1a1a3c3c088f32b0240091"><code>a8bd0b1</code></a>
Honour resetall() arguments for non-callable mocks (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/606">#606</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/6559fdfd5b67f096423e604a3a5a7045db2486a0"><code>6559fdf</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/608">#608</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/466d026254c949a8fbba8626b894308827be81cf"><code>466d026</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/605">#605</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/164defebde25bc31d53a2a64943c5c9aac43b57e"><code>164defe</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/603">#603</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pytest-dev/pytest-mock/compare/v3.15.1...v3.16.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `syrupy` from 6.0.0 to 6.1.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/syrupy-project/syrupy/releases">syrupy's
releases</a>.</em></p>
<blockquote>
<h2>v6.1.1</h2>
<blockquote>
<p><strong>Note:</strong> 6.1.0 was skipped due to a CI issue. Use
<strong>6.1.1</strong>.</p>
</blockquote>
<h3>Experimental <code>--snapshot-file-lock</code> for pytest-xdist</h3>
<p><code>--snapshot-update</code> under pytest-xdist can race when
multiple workers rewrite the same multi-entry amber (<code>.ambr</code>)
file, silently dropping snapshots (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1237">#1237</a>).</p>
<p>This release adds an <strong>experimental</strong> opt-in:</p>
<ul>
<li><code>--snapshot-file-lock</code> — exclusive file lock + atomic
replace around amber writes</li>
<li><code>--snapshot-file-lock-timeout</code> — max wait for the lock
(default <strong>60s</strong>)</li>
</ul>
<p>Same-machine workers only; not reliable across remote workers / NFS.
See <a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1239">#1239</a>.</p>
<blockquote>
<p><strong>Callout for pytest-xdist users:</strong> please try
<code>--snapshot-file-lock</code> with <code>--snapshot-update</code>
and <a href="https://github.com/syrupy-project/syrupy/issues">open an
issue</a> if you hit problems. Locking is expected to become the default
in a future minor release.</p>
</blockquote>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/shipbyaeron"><code>@​shipbyaeron</code></a>
made their first contribution in <a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1236">syrupy-project/syrupy#1236</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.1">https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.1</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/syrupy-project/syrupy/blob/main/CHANGELOG.md">syrupy's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/syrupy-project/syrupy/releases/tag/v6.1.1">v6.1.1</a>
(2026-09-13)</h2>
<h2>What's Changed</h2>
<ul>
<li>chore(deps): update dependency ruff to v0.16.4 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1225">syrupy-project/syrupy#1225</a></li>
<li>chore(deps): update dependency pytest-benchmark to v5.3.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1226">syrupy-project/syrupy#1226</a></li>
<li>chore(deps): update dependency ruff to v0.16.5 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1227">syrupy-project/syrupy#1227</a></li>
<li>chore(deps): update dependency pydantic to v2.13.5 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1228">syrupy-project/syrupy#1228</a></li>
<li>chore(deps): update dependency coverage to v7.16.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1229">syrupy-project/syrupy#1229</a></li>
<li>chore(deps): update dependency hypothesis to v6.166.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1230">syrupy-project/syrupy#1230</a></li>
<li>chore(deps): update dependency hypothesis to v6.167.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1231">syrupy-project/syrupy#1231</a></li>
<li>chore(deps): update dependency hypothesis to v6.167.1 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1232">syrupy-project/syrupy#1232</a></li>
<li>chore(deps): update actions/deploy-pages action to v5.0.1 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1234">syrupy-project/syrupy#1234</a></li>
<li>chore(deps): update dependency ruff to v0.16.6 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1235">syrupy-project/syrupy#1235</a></li>
<li>test: add coverage for read_snapshot_data_from_location returning
None by <a
href="https://github.com/shipbyaeron"><code>@​shipbyaeron</code></a> in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1236">syrupy-project/syrupy#1236</a></li>
<li>chore(deps): update dependency hypothesis to v6.168.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1238">syrupy-project/syrupy#1238</a></li>
<li>fix: opt-in file lock for concurrent amber writes under xdist by <a
href="https://github.com/noahnu"><code>@​noahnu</code></a> in <a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1239">syrupy-project/syrupy#1239</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/shipbyaeron"><code>@​shipbyaeron</code></a>
made their first contribution in <a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1236">syrupy-project/syrupy#1236</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.1">https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.1</a></p>
<h2><a
href="https://github.com/syrupy-project/syrupy/releases/tag/v6.1.0">v6.1.0</a>
(2026-09-13)</h2>
<h2>What's Changed</h2>
<ul>
<li>chore(deps): update dependency ruff to v0.16.4 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1225">syrupy-project/syrupy#1225</a></li>
<li>chore(deps): update dependency pytest-benchmark to v5.3.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1226">syrupy-project/syrupy#1226</a></li>
<li>chore(deps): update dependency ruff to v0.16.5 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1227">syrupy-project/syrupy#1227</a></li>
<li>chore(deps): update dependency pydantic to v2.13.5 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1228">syrupy-project/syrupy#1228</a></li>
<li>chore(deps): update dependency coverage to v7.16.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1229">syrupy-project/syrupy#1229</a></li>
<li>chore(deps): update dependency hypothesis to v6.166.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1230">syrupy-project/syrupy#1230</a></li>
<li>chore(deps): update dependency hypothesis to v6.167.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1231">syrupy-project/syrupy#1231</a></li>
<li>chore(deps): update dependency hypothesis to v6.167.1 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1232">syrupy-project/syrupy#1232</a></li>
<li>chore(deps): update actions/deploy-pages action to v5.0.1 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1234">syrupy-project/syrupy#1234</a></li>
<li>chore(deps): update dependency ruff to v0.16.6 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1235">syrupy-project/syrupy#1235</a></li>
<li>test: add coverage for read_snapshot_data_from_location returning
None by <a
href="https://github.com/shipbyaeron"><code>@​shipbyaeron</code></a> in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1236">syrupy-project/syrupy#1236</a></li>
<li>chore(deps): update dependency hypothesis to v6.168.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1238">syrupy-project/syrupy#1238</a></li>
<li>fix: opt-in file lock for concurrent amber writes under xdist by <a
href="https://github.com/noahnu"><code>@​noahnu</code></a> in <a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1239">syrupy-project/syrupy#1239</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/shipbyaeron"><code>@​shipbyaeron</code></a>
made their first contribution in <a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1236">syrupy-project/syrupy#1236</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.0">https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/2d251e73f1ebe47fe83ed71d835d3ae8580e8313"><code>2d251e7</code></a>
chore(release): 6.1.1 [skip ci]</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/9b64ec05752586c45d1097e9d25f9ee1d4e93219"><code>9b64ec0</code></a>
chore(release): 6.1.0 [skip ci]</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/5b4256eac8720075f25b0fa8491f75948001b983"><code>5b4256e</code></a>
fix: opt-in file lock for concurrent amber writes under xdist (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1239">#1239</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/d4cb1513b5d2b1b18c3b407150db22d2d8604ddd"><code>d4cb151</code></a>
chore(deps): update dependency hypothesis to v6.168.0 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1238">#1238</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/16c4cb5b8785d89e49b8076a99f58d810e02fcce"><code>16c4cb5</code></a>
test: add coverage for read_snapshot_data_from_location returning None
(<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1236">#1236</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/2e1d3ba0d39a1d87735213a32de9dd9cdb929690"><code>2e1d3ba</code></a>
chore(deps): update dependency ruff to v0.16.6 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1235">#1235</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/fcc929d4deb2302f2d37e6511015ef43a0841bc2"><code>fcc929d</code></a>
chore(deps): update actions/deploy-pages action to v5.0.1 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1234">#1234</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/4f1bad75777ecc9d916a648dd3669b2844d08f7d"><code>4f1bad7</code></a>
chore(deps): update dependency hypothesis to v6.167.1 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1232">#1232</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/24eda28579f5761cbc64713ffcee41cc73602010"><code>24eda28</code></a>
chore(deps): update dependency hypothesis to v6.167.0 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1231">#1231</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/0d7e46f9431e07810da4ef90dbe861b85fbc8469"><code>0d7e46f</code></a>
chore(deps): update dependency hypothesis to v6.166.0 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1230">#1230</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.16.5 to 0.16.9
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>Install ruff 0.16.9</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-installer.sh
| sh
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>0.16.8</h2>
<p>Released on 2026-09-16.</p>
<h3>Bug fixes</h3>
<ul>
<li>Visit functional <code>TypedDict</code> keyword arguments correctly
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28584">#28584</a>)</li>
<li>[<code>flake8-simplify</code>] Detect nested <code>async with</code>
under sync parent (<code>SIM117</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27821">#27821</a>)</li>
<li>[<code>flake8-simplify</code>] Preserve operand order in
<code>SIM109</code> fix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27824">#27824</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/0be08a206f9c3180afd3e93bcc792ed5cb1f4db1"><code>0be08a2</code></a>
Bump version to 0.16.9 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28882">#28882</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/b4920b72b354e7c715ab861ae23458874683bb02"><code>b4920b7</code></a>
Rename <code>ruff_cli</code> to <code>ruff_command_line</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28881">#28881</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/47c751b95908a4d1f95f9ef8723036aae9da0b18"><code>47c751b</code></a>
Update dependency astral-sh/uv to v0.12.18 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28880">#28880</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c244e56a1aeac31c26d2371ef26588e0632235c"><code>8c244e5</code></a>
[<code>flake8-comprehensions</code>] Document <code>map</code>/generator
exception behavior (<code>C417</code>...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/5edf5a1d0a84663079e46983216059f06acea87d"><code>5edf5a1</code></a>
Use <code>target</code> form in <code>rooster.version_files</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28876">#28876</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/915bb2b4bf9ae7eee47cf55646bbfebae254a23b"><code>915bb2b</code></a>
[ty] Prefer existing @ paths over response files in Ruff and ty (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28877">#28877</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4710e1aa962b13720cf64aa84eb279c5333896d7"><code>4710e1a</code></a>
ci(github): update version number in placeholder of issue template (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28871">#28871</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/eedfc62a75bf1ba86d48959b00eea75ae87eadca"><code>eedfc62</code></a>
[ty] Propagate outer type context through cast calls (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28855">#28855</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/ceaa6a00830e1e350b8a23977a1a10ac467920a1"><code>ceaa6a0</code></a>
[ty] Contain rendered code within Markdown fences (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28869">#28869</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/dba0f30615424b94f94a174bba6ce6cce4bf11ff"><code>dba0f30</code></a>
authorize ruff-pre-commit dispatch via OIDC (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28867">#28867</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.16.5...0.16.9">compare
view</a></li>
</ul>
</details>
<br />

Updates `ty` from 0.0.75 to 0.0.84
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/releases">ty's
releases</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/blob/main/CHANGELOG.md">ty's
changelog</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ty/commit/8dd9a7f7fa35a18275d82117e6593ba45507065f"><code>8dd9a7f</code></a>
Bump version to 0.0.84 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4585">#4585</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/d4e4bf90906c7677049bc3a29d1735de7d22052d"><code>d4e4bf9</code></a>
publish to astral-sh/versions via OIDC (<a
href="https://redirect.github.com/astral-sh/ty/issues/4581">#4581</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/94ce7333abb356b2068dc98d37a68c993da6d09b"><code>94ce733</code></a>
use oidc issued token for docs publication (<a
href="https://redirect.github.com/astral-sh/ty/issues/4579">#4579</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/901eeaa9cd9ac06f34e85e4f721f76a0dc36e217"><code>901eeaa</code></a>
Update prek dependencies (<a
href="https://redirect.github.com/astral-sh/ty/issues/4576">#4576</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/09bf0b1b2114a628f3e2296d3d9d28245066c98b"><code>09bf0b1</code></a>
Update docker/setup-buildx-action action to v4.3.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4575">#4575</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/89d6ffe529dd44f64adc0d28f80744b7c7ab217f"><code>89d6ffe</code></a>
Update astral-sh/setup-uv action to v10.2.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4574">#4574</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/9c214798cfcc59069e986876564638fadf32d774"><code>9c21479</code></a>
Bump version to 0.0.83 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4569">#4569</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/04c69110b391e96310e6892cbed9936c4f31d7aa"><code>04c6911</code></a>
Sync the ty security mirror (<a
href="https://redirect.github.com/astral-sh/ty/issues/4549">#4549</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/3fa57a25767c619dbeba697c2acfbb8eb291519a"><code>3fa57a2</code></a>
Grant the versions workflow repository read access (<a
href="https://redirect.github.com/astral-sh/ty/issues/4550">#4550</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/a15b35389b44db57f718fd4e19e093481747c53e"><code>a15b353</code></a>
use scoped token for release workflow (<a
href="https://redirect.github.com/astral-sh/ty/issues/4506">#4506</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ty/compare/0.0.75...0.0.84">compare
view</a></li>
</ul>
</details>
<br />

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: John Kennedy <jkennedyvz@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-10-01 11:57:28 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedyopen-swe[bot] <open-swe@users.noreply.github.com>
5204e60579 chore(deps-dev): bump the minor-and-patch group in /libs/checkpoint-sqlite with 3 updates (#9146)
Bumps the minor-and-patch group in /libs/checkpoint-sqlite with 3
updates: [pytest-mock](https://github.com/pytest-dev/pytest-mock),
[ruff](https://github.com/astral-sh/ruff) and
[ty](https://github.com/astral-sh/ty).

Updates `pytest-mock` from 3.15.1 to 3.16.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/releases">pytest-mock's
releases</a>.</em></p>
<blockquote>
<h2>v3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/604">#604</a>:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/611">#611</a>:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/606">#606</a>:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/547">#547</a>:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/147">#147</a>:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst">pytest-mock's
changelog</a>.</em></p>
<blockquote>
<h2>3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><code>[#604](https://github.com/pytest-dev/pytest-mock/issues/604)
&lt;https://github.com/pytest-dev/pytest-mock/pull/604&gt;</code>_:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><code>[#611](https://github.com/pytest-dev/pytest-mock/issues/611)
&lt;https://github.com/pytest-dev/pytest-mock/pull/611&gt;</code>_:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><code>[#606](https://github.com/pytest-dev/pytest-mock/issues/606)
&lt;https://github.com/pytest-dev/pytest-mock/pull/606&gt;</code>_:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><code>[#547](https://github.com/pytest-dev/pytest-mock/issues/547)
&lt;https://github.com/pytest-dev/pytest-mock/issues/547&gt;</code>_:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><code>[#147](https://github.com/pytest-dev/pytest-mock/issues/147)
&lt;https://github.com/pytest-dev/pytest-mock/issues/147&gt;</code>_:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/f3b531f93c6d9837edc87ea1a6f4324dc9a2cdf3"><code>f3b531f</code></a>
Release 3.16.0</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/71ed67309520be160f3e100368705b58758d237a"><code>71ed673</code></a>
Fix duplicate_iterators for async spies (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/604">#604</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/0797e3d303cc5bbe0a3514b0625f7aeb3fa350b0"><code>0797e3d</code></a>
Fix async assertion argument introspection (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/611">#611</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/e24c334d573cfbf6989a31f4e3346676d9d31598"><code>e24c334</code></a>
docs: import os in the opening usage example (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/612">#612</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/9e7eb7b59cde362c1c8ace2d18ca00fe2d7a1cd1"><code>9e7eb7b</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/613">#613</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/445fd4d3daa8ed4c6d5428a77880da2e03d2f721"><code>445fd4d</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/610">#610</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/a8bd0b147afdf6b4bb1a1a3c3c088f32b0240091"><code>a8bd0b1</code></a>
Honour resetall() arguments for non-callable mocks (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/606">#606</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/6559fdfd5b67f096423e604a3a5a7045db2486a0"><code>6559fdf</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/608">#608</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/466d026254c949a8fbba8626b894308827be81cf"><code>466d026</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/605">#605</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/164defebde25bc31d53a2a64943c5c9aac43b57e"><code>164defe</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/603">#603</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pytest-dev/pytest-mock/compare/v3.15.1...v3.16.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.16.5 to 0.16.9
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>Install ruff 0.16.9</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-installer.sh
| sh
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>0.16.8</h2>
<p>Released on 2026-09-16.</p>
<h3>Bug fixes</h3>
<ul>
<li>Visit functional <code>TypedDict</code> keyword arguments correctly
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28584">#28584</a>)</li>
<li>[<code>flake8-simplify</code>] Detect nested <code>async with</code>
under sync parent (<code>SIM117</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27821">#27821</a>)</li>
<li>[<code>flake8-simplify</code>] Preserve operand order in
<code>SIM109</code> fix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27824">#27824</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/0be08a206f9c3180afd3e93bcc792ed5cb1f4db1"><code>0be08a2</code></a>
Bump version to 0.16.9 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28882">#28882</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/b4920b72b354e7c715ab861ae23458874683bb02"><code>b4920b7</code></a>
Rename <code>ruff_cli</code> to <code>ruff_command_line</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28881">#28881</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/47c751b95908a4d1f95f9ef8723036aae9da0b18"><code>47c751b</code></a>
Update dependency astral-sh/uv to v0.12.18 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28880">#28880</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c244e56a1aeac31c26d2371ef26588e0632235c"><code>8c244e5</code></a>
[<code>flake8-comprehensions</code>] Document <code>map</code>/generator
exception behavior (<code>C417</code>...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/5edf5a1d0a84663079e46983216059f06acea87d"><code>5edf5a1</code></a>
Use <code>target</code> form in <code>rooster.version_files</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28876">#28876</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/915bb2b4bf9ae7eee47cf55646bbfebae254a23b"><code>915bb2b</code></a>
[ty] Prefer existing @ paths over response files in Ruff and ty (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28877">#28877</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4710e1aa962b13720cf64aa84eb279c5333896d7"><code>4710e1a</code></a>
ci(github): update version number in placeholder of issue template (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28871">#28871</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/eedfc62a75bf1ba86d48959b00eea75ae87eadca"><code>eedfc62</code></a>
[ty] Propagate outer type context through cast calls (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28855">#28855</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/ceaa6a00830e1e350b8a23977a1a10ac467920a1"><code>ceaa6a0</code></a>
[ty] Contain rendered code within Markdown fences (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28869">#28869</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/dba0f30615424b94f94a174bba6ce6cce4bf11ff"><code>dba0f30</code></a>
authorize ruff-pre-commit dispatch via OIDC (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28867">#28867</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.16.5...0.16.9">compare
view</a></li>
</ul>
</details>
<br />

Updates `ty` from 0.0.75 to 0.0.84
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/releases">ty's
releases</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/blob/main/CHANGELOG.md">ty's
changelog</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ty/commit/8dd9a7f7fa35a18275d82117e6593ba45507065f"><code>8dd9a7f</code></a>
Bump version to 0.0.84 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4585">#4585</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/d4e4bf90906c7677049bc3a29d1735de7d22052d"><code>d4e4bf9</code></a>
publish to astral-sh/versions via OIDC (<a
href="https://redirect.github.com/astral-sh/ty/issues/4581">#4581</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/94ce7333abb356b2068dc98d37a68c993da6d09b"><code>94ce733</code></a>
use oidc issued token for docs publication (<a
href="https://redirect.github.com/astral-sh/ty/issues/4579">#4579</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/901eeaa9cd9ac06f34e85e4f721f76a0dc36e217"><code>901eeaa</code></a>
Update prek dependencies (<a
href="https://redirect.github.com/astral-sh/ty/issues/4576">#4576</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/09bf0b1b2114a628f3e2296d3d9d28245066c98b"><code>09bf0b1</code></a>
Update docker/setup-buildx-action action to v4.3.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4575">#4575</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/89d6ffe529dd44f64adc0d28f80744b7c7ab217f"><code>89d6ffe</code></a>
Update astral-sh/setup-uv action to v10.2.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4574">#4574</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/9c214798cfcc59069e986876564638fadf32d774"><code>9c21479</code></a>
Bump version to 0.0.83 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4569">#4569</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/04c69110b391e96310e6892cbed9936c4f31d7aa"><code>04c6911</code></a>
Sync the ty security mirror (<a
href="https://redirect.github.com/astral-sh/ty/issues/4549">#4549</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/3fa57a25767c619dbeba697c2acfbb8eb291519a"><code>3fa57a2</code></a>
Grant the versions workflow repository read access (<a
href="https://redirect.github.com/astral-sh/ty/issues/4550">#4550</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/a15b35389b44db57f718fd4e19e093481747c53e"><code>a15b353</code></a>
use scoped token for release workflow (<a
href="https://redirect.github.com/astral-sh/ty/issues/4506">#4506</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ty/compare/0.0.75...0.0.84">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: John Kennedy <jkennedyvz@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-10-01 11:54:00 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedyopen-swe[bot] <open-swe@users.noreply.github.com>
2053f0b176 chore(deps-dev): bump the minor-and-patch group in /libs/checkpoint-conformance with 2 updates (#9145)
Bumps the minor-and-patch group in /libs/checkpoint-conformance with 2
updates: [ruff](https://github.com/astral-sh/ruff) and
[ty](https://github.com/astral-sh/ty).

Updates `ruff` from 0.16.5 to 0.16.9
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>Install ruff 0.16.9</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-installer.sh
| sh
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>0.16.8</h2>
<p>Released on 2026-09-16.</p>
<h3>Bug fixes</h3>
<ul>
<li>Visit functional <code>TypedDict</code> keyword arguments correctly
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28584">#28584</a>)</li>
<li>[<code>flake8-simplify</code>] Detect nested <code>async with</code>
under sync parent (<code>SIM117</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27821">#27821</a>)</li>
<li>[<code>flake8-simplify</code>] Preserve operand order in
<code>SIM109</code> fix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27824">#27824</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/0be08a206f9c3180afd3e93bcc792ed5cb1f4db1"><code>0be08a2</code></a>
Bump version to 0.16.9 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28882">#28882</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/b4920b72b354e7c715ab861ae23458874683bb02"><code>b4920b7</code></a>
Rename <code>ruff_cli</code> to <code>ruff_command_line</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28881">#28881</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/47c751b95908a4d1f95f9ef8723036aae9da0b18"><code>47c751b</code></a>
Update dependency astral-sh/uv to v0.12.18 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28880">#28880</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c244e56a1aeac31c26d2371ef26588e0632235c"><code>8c244e5</code></a>
[<code>flake8-comprehensions</code>] Document <code>map</code>/generator
exception behavior (<code>C417</code>...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/5edf5a1d0a84663079e46983216059f06acea87d"><code>5edf5a1</code></a>
Use <code>target</code> form in <code>rooster.version_files</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28876">#28876</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/915bb2b4bf9ae7eee47cf55646bbfebae254a23b"><code>915bb2b</code></a>
[ty] Prefer existing @ paths over response files in Ruff and ty (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28877">#28877</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4710e1aa962b13720cf64aa84eb279c5333896d7"><code>4710e1a</code></a>
ci(github): update version number in placeholder of issue template (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28871">#28871</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/eedfc62a75bf1ba86d48959b00eea75ae87eadca"><code>eedfc62</code></a>
[ty] Propagate outer type context through cast calls (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28855">#28855</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/ceaa6a00830e1e350b8a23977a1a10ac467920a1"><code>ceaa6a0</code></a>
[ty] Contain rendered code within Markdown fences (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28869">#28869</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/dba0f30615424b94f94a174bba6ce6cce4bf11ff"><code>dba0f30</code></a>
authorize ruff-pre-commit dispatch via OIDC (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28867">#28867</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.16.5...0.16.9">compare
view</a></li>
</ul>
</details>
<br />

Updates `ty` from 0.0.75 to 0.0.84
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/releases">ty's
releases</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/blob/main/CHANGELOG.md">ty's
changelog</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ty/commit/8dd9a7f7fa35a18275d82117e6593ba45507065f"><code>8dd9a7f</code></a>
Bump version to 0.0.84 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4585">#4585</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/d4e4bf90906c7677049bc3a29d1735de7d22052d"><code>d4e4bf9</code></a>
publish to astral-sh/versions via OIDC (<a
href="https://redirect.github.com/astral-sh/ty/issues/4581">#4581</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/94ce7333abb356b2068dc98d37a68c993da6d09b"><code>94ce733</code></a>
use oidc issued token for docs publication (<a
href="https://redirect.github.com/astral-sh/ty/issues/4579">#4579</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/901eeaa9cd9ac06f34e85e4f721f76a0dc36e217"><code>901eeaa</code></a>
Update prek dependencies (<a
href="https://redirect.github.com/astral-sh/ty/issues/4576">#4576</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/09bf0b1b2114a628f3e2296d3d9d28245066c98b"><code>09bf0b1</code></a>
Update docker/setup-buildx-action action to v4.3.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4575">#4575</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/89d6ffe529dd44f64adc0d28f80744b7c7ab217f"><code>89d6ffe</code></a>
Update astral-sh/setup-uv action to v10.2.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4574">#4574</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/9c214798cfcc59069e986876564638fadf32d774"><code>9c21479</code></a>
Bump version to 0.0.83 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4569">#4569</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/04c69110b391e96310e6892cbed9936c4f31d7aa"><code>04c6911</code></a>
Sync the ty security mirror (<a
href="https://redirect.github.com/astral-sh/ty/issues/4549">#4549</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/3fa57a25767c619dbeba697c2acfbb8eb291519a"><code>3fa57a2</code></a>
Grant the versions workflow repository read access (<a
href="https://redirect.github.com/astral-sh/ty/issues/4550">#4550</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/a15b35389b44db57f718fd4e19e093481747c53e"><code>a15b353</code></a>
use scoped token for release workflow (<a
href="https://redirect.github.com/astral-sh/ty/issues/4506">#4506</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ty/compare/0.0.75...0.0.84">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: John Kennedy <jkennedyvz@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-10-01 11:53:48 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedyopen-swe[bot] <open-swe@users.noreply.github.com>
c4f55715ec chore(deps): bump the minor-and-patch group in /libs/sdk-py with 5 updates (#9149)
Bumps the minor-and-patch group in /libs/sdk-py with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [langchain-core](https://github.com/langchain-ai/langchain) | `1.6.1`
| `1.6.5` |
| [pytest-mock](https://github.com/pytest-dev/pytest-mock) | `3.15.1` |
`3.16.0` |
| [ruff](https://github.com/astral-sh/ruff) | `0.16.5` | `0.16.9` |
| [ty](https://github.com/astral-sh/ty) | `0.0.75` | `0.0.84` |
| [starlette](https://github.com/Kludex/starlette) | `1.6.0` | `1.7.0` |

Updates `langchain-core` from 1.6.1 to 1.6.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/langchain-ai/langchain/releases">langchain-core's
releases</a>.</em></p>
<blockquote>
<h2>langchain-core==1.6.5</h2>
<p>Changes since langchain-core==1.6.4</p>
<p>release(core): 1.6.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40816">#40816</a>)
fix(core): abbreviate long tool IDs in XML buffer strings (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40792">#40792</a>)</p>
<h2>langchain-core==1.6.4</h2>
<p>Changes since langchain-core==1.6.3</p>
<p>release(core): 1.6.4 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40718">#40718</a>)
chore(core): deprecate chat message history (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40711">#40711</a>)
chore(deps): bump anyio from 4.12.0 to 4.14.2 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40634">#40634</a>)
chore(deps): bump soupsieve from 2.8.4 to 2.9 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40574">#40574</a>)</p>
<h2>langchain-core==1.6.3</h2>
<p>Changes since langchain-core==1.6.2</p>
<p>release(core): 1.6.3 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40407">#40407</a>)
feat(core): Allow model name and provider tracing metadata override
based on gateway response (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40406">#40406</a>)
test(core): cover the deprecated <code>.text()</code> access path (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40243">#40243</a>)
docs(core): remove stale Args/Raises entries from
FileCallbackHandler._write and ChatGeneration.set_text (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40211">#40211</a>)</p>
<h2>langchain-core==1.6.2</h2>
<p>Changes since langchain-core==1.6.1</p>
<p>release(core): 1.6.2 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40209">#40209</a>)
feat(openai): support async tools (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40208">#40208</a>)
chore(deps): bump mistune from 3.3.0 to 3.3.3 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40150">#40150</a>)
chore(deps): bump tornado from 6.5.7 to 6.5.8 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40113">#40113</a>)
fix(core): avoid mutation in google-genai standard content (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40023">#40023</a>)
fix(core): avoid mutation in bedrock converse standard content (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40022">#40022</a>)</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/c5ab14d42a3e22865c9def909de0b11d70b0bbf0"><code>c5ab14d</code></a>
release(core): 1.6.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40816">#40816</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/5704d9d4813f8c0527f04e2662cf313e1350f96f"><code>5704d9d</code></a>
chore(model-profiles): refresh model profile data (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40804">#40804</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/7622d3dce760ac4be6d9aef4c653277e06064aea"><code>7622d3d</code></a>
release(openai): 1.6.6 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40800">#40800</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/2dd956b8add667dac4f97605ae441d75b8ae228e"><code>2dd956b</code></a>
docs(infra): fix AGENTS.md root setup guidance and package doc accuracy
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40794">#40794</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/49f4b4016b82513c3dc1623bf3daa10453861621"><code>49f4b40</code></a>
fix(openai): raise on error events in stream path (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40791">#40791</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/19cadaa1a1e0cac71f3148e2f18b414dcab17426"><code>19cadaa</code></a>
fix(core): abbreviate long tool IDs in XML buffer strings (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40792">#40792</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/798441e8b07e88e79db355db452cd9492f9628f2"><code>798441e</code></a>
chore(anthropic): fix integration test cassette (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40790">#40790</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/a476942bac3fe5e521676d0f53fabafcb7ba71b1"><code>a476942</code></a>
release(openai): 1.6.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40787">#40787</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/46c6bdf1b4e23028a5acc060d8b2797dbf200291"><code>46c6bdf</code></a>
release(anthropic): 1.7.4 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40786">#40786</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/290dabaff27ee379920d55d155d5055d2fe29cc8"><code>290daba</code></a>
fix(anthropic): add Opus 5.5 and GPT-6 profile augmentations (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40785">#40785</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.6.1...langchain-core==1.6.5">compare
view</a></li>
</ul>
</details>
<br />

Updates `pytest-mock` from 3.15.1 to 3.16.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/releases">pytest-mock's
releases</a>.</em></p>
<blockquote>
<h2>v3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/604">#604</a>:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/611">#611</a>:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/606">#606</a>:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/547">#547</a>:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/147">#147</a>:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst">pytest-mock's
changelog</a>.</em></p>
<blockquote>
<h2>3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><code>[#604](https://github.com/pytest-dev/pytest-mock/issues/604)
&lt;https://github.com/pytest-dev/pytest-mock/pull/604&gt;</code>_:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><code>[#611](https://github.com/pytest-dev/pytest-mock/issues/611)
&lt;https://github.com/pytest-dev/pytest-mock/pull/611&gt;</code>_:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><code>[#606](https://github.com/pytest-dev/pytest-mock/issues/606)
&lt;https://github.com/pytest-dev/pytest-mock/pull/606&gt;</code>_:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><code>[#547](https://github.com/pytest-dev/pytest-mock/issues/547)
&lt;https://github.com/pytest-dev/pytest-mock/issues/547&gt;</code>_:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><code>[#147](https://github.com/pytest-dev/pytest-mock/issues/147)
&lt;https://github.com/pytest-dev/pytest-mock/issues/147&gt;</code>_:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/f3b531f93c6d9837edc87ea1a6f4324dc9a2cdf3"><code>f3b531f</code></a>
Release 3.16.0</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/71ed67309520be160f3e100368705b58758d237a"><code>71ed673</code></a>
Fix duplicate_iterators for async spies (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/604">#604</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/0797e3d303cc5bbe0a3514b0625f7aeb3fa350b0"><code>0797e3d</code></a>
Fix async assertion argument introspection (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/611">#611</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/e24c334d573cfbf6989a31f4e3346676d9d31598"><code>e24c334</code></a>
docs: import os in the opening usage example (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/612">#612</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/9e7eb7b59cde362c1c8ace2d18ca00fe2d7a1cd1"><code>9e7eb7b</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/613">#613</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/445fd4d3daa8ed4c6d5428a77880da2e03d2f721"><code>445fd4d</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/610">#610</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/a8bd0b147afdf6b4bb1a1a3c3c088f32b0240091"><code>a8bd0b1</code></a>
Honour resetall() arguments for non-callable mocks (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/606">#606</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/6559fdfd5b67f096423e604a3a5a7045db2486a0"><code>6559fdf</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/608">#608</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/466d026254c949a8fbba8626b894308827be81cf"><code>466d026</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/605">#605</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/164defebde25bc31d53a2a64943c5c9aac43b57e"><code>164defe</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/603">#603</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pytest-dev/pytest-mock/compare/v3.15.1...v3.16.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.16.5 to 0.16.9
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>Install ruff 0.16.9</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-installer.sh
| sh
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>0.16.8</h2>
<p>Released on 2026-09-16.</p>
<h3>Bug fixes</h3>
<ul>
<li>Visit functional <code>TypedDict</code> keyword arguments correctly
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28584">#28584</a>)</li>
<li>[<code>flake8-simplify</code>] Detect nested <code>async with</code>
under sync parent (<code>SIM117</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27821">#27821</a>)</li>
<li>[<code>flake8-simplify</code>] Preserve operand order in
<code>SIM109</code> fix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27824">#27824</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/0be08a206f9c3180afd3e93bcc792ed5cb1f4db1"><code>0be08a2</code></a>
Bump version to 0.16.9 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28882">#28882</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/b4920b72b354e7c715ab861ae23458874683bb02"><code>b4920b7</code></a>
Rename <code>ruff_cli</code> to <code>ruff_command_line</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28881">#28881</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/47c751b95908a4d1f95f9ef8723036aae9da0b18"><code>47c751b</code></a>
Update dependency astral-sh/uv to v0.12.18 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28880">#28880</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c244e56a1aeac31c26d2371ef26588e0632235c"><code>8c244e5</code></a>
[<code>flake8-comprehensions</code>] Document <code>map</code>/generator
exception behavior (<code>C417</code>...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/5edf5a1d0a84663079e46983216059f06acea87d"><code>5edf5a1</code></a>
Use <code>target</code> form in <code>rooster.version_files</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28876">#28876</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/915bb2b4bf9ae7eee47cf55646bbfebae254a23b"><code>915bb2b</code></a>
[ty] Prefer existing @ paths over response files in Ruff and ty (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28877">#28877</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4710e1aa962b13720cf64aa84eb279c5333896d7"><code>4710e1a</code></a>
ci(github): update version number in placeholder of issue template (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28871">#28871</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/eedfc62a75bf1ba86d48959b00eea75ae87eadca"><code>eedfc62</code></a>
[ty] Propagate outer type context through cast calls (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28855">#28855</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/ceaa6a00830e1e350b8a23977a1a10ac467920a1"><code>ceaa6a0</code></a>
[ty] Contain rendered code within Markdown fences (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28869">#28869</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/dba0f30615424b94f94a174bba6ce6cce4bf11ff"><code>dba0f30</code></a>
authorize ruff-pre-commit dispatch via OIDC (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28867">#28867</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.16.5...0.16.9">compare
view</a></li>
</ul>
</details>
<br />

Updates `ty` from 0.0.75 to 0.0.84
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/releases">ty's
releases</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/blob/main/CHANGELOG.md">ty's
changelog</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ty/commit/8dd9a7f7fa35a18275d82117e6593ba45507065f"><code>8dd9a7f</code></a>
Bump version to 0.0.84 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4585">#4585</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/d4e4bf90906c7677049bc3a29d1735de7d22052d"><code>d4e4bf9</code></a>
publish to astral-sh/versions via OIDC (<a
href="https://redirect.github.com/astral-sh/ty/issues/4581">#4581</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/94ce7333abb356b2068dc98d37a68c993da6d09b"><code>94ce733</code></a>
use oidc issued token for docs publication (<a
href="https://redirect.github.com/astral-sh/ty/issues/4579">#4579</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/901eeaa9cd9ac06f34e85e4f721f76a0dc36e217"><code>901eeaa</code></a>
Update prek dependencies (<a
href="https://redirect.github.com/astral-sh/ty/issues/4576">#4576</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/09bf0b1b2114a628f3e2296d3d9d28245066c98b"><code>09bf0b1</code></a>
Update docker/setup-buildx-action action to v4.3.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4575">#4575</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/89d6ffe529dd44f64adc0d28f80744b7c7ab217f"><code>89d6ffe</code></a>
Update astral-sh/setup-uv action to v10.2.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4574">#4574</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/9c214798cfcc59069e986876564638fadf32d774"><code>9c21479</code></a>
Bump version to 0.0.83 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4569">#4569</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/04c69110b391e96310e6892cbed9936c4f31d7aa"><code>04c6911</code></a>
Sync the ty security mirror (<a
href="https://redirect.github.com/astral-sh/ty/issues/4549">#4549</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/3fa57a25767c619dbeba697c2acfbb8eb291519a"><code>3fa57a2</code></a>
Grant the versions workflow repository read access (<a
href="https://redirect.github.com/astral-sh/ty/issues/4550">#4550</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/a15b35389b44db57f718fd4e19e093481747c53e"><code>a15b353</code></a>
use scoped token for release workflow (<a
href="https://redirect.github.com/astral-sh/ty/issues/4506">#4506</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ty/compare/0.0.75...0.0.84">compare
view</a></li>
</ul>
</details>
<br />

Updates `starlette` from 1.6.0 to 1.7.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/Kludex/starlette/releases">starlette's
releases</a>.</em></p>
<blockquote>
<h2>Version 1.7.0</h2>
<p>This release adds experimental OpenTelemetry tracing, HTTP
<code>QUERY</code> support, and response trailers in
<code>TestClient</code>. Starlette now requires AnyIO 4.</p>
<blockquote>
<p>[!WARNING]
<code>OpenTelemetryMiddleware</code> is experimental. Its API and
emitted telemetry may change in minor releases without a deprecation
period.</p>
</blockquote>
<h2>Added</h2>
<ul>
<li>Add experimental <code>OpenTelemetryMiddleware</code> for HTTP
server spans, with URL exclusions and custom tracer providers <a
href="https://redirect.github.com/Kludex/starlette/pull/3438">#3438</a>,
<a
href="https://redirect.github.com/Kludex/starlette/pull/3463">#3463</a>,
and <a
href="https://redirect.github.com/Kludex/starlette/pull/3520">#3520</a>.</li>
<li>Expose the matched route through
<code>scope[&quot;route&quot;]</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3438">#3438</a>.</li>
<li>Support the <code>QUERY</code> HTTP method in
<code>HTTPEndpoint</code>, CORS, and OpenAPI 3.2 schema generation <a
href="https://redirect.github.com/Kludex/starlette/pull/3489">#3489</a>.</li>
<li>Capture HTTP response trailers in <code>TestClient</code> and expose
them through
<code>response.extensions[&quot;http.response.trailers&quot;]</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3563">#3563</a>.</li>
<li>Support partitioned cookies in <code>SessionMiddleware</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3510">#3510</a>.</li>
<li>Add <code>partitioned</code> to
<code>Response.delete_cookie()</code> on Python 3.14 and later <a
href="https://redirect.github.com/Kludex/starlette/pull/3376">#3376</a>.</li>
<li>Support IPv6 hosts in <code>TrustedHostMiddleware</code> and
<code>TestClient</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3471">#3471</a>.</li>
<li>Support Python 3.15 <a
href="https://redirect.github.com/Kludex/starlette/pull/3508">#3508</a>.</li>
</ul>
<h2>Changed</h2>
<ul>
<li>Require <code>anyio&gt;=4.0.0,&lt;5</code>, dropping support for
AnyIO 3 <a
href="https://redirect.github.com/Kludex/starlette/pull/3512">#3512</a>.</li>
<li>Raise <code>WebSocketDisconnected</code>, a
<code>RuntimeError</code> subclass, for disconnected WebSocket
operations <a
href="https://redirect.github.com/Kludex/starlette/pull/2767">#2767</a>.</li>
<li>Accept <code>Collection[str]</code> in <code>CORSMiddleware</code>
configuration annotations, including sets and frozensets <a
href="https://redirect.github.com/Kludex/starlette/pull/3518">#3518</a>.</li>
</ul>
<h2>Fixed</h2>
<ul>
<li>Run background tasks only after the response is sent when using
<code>BaseHTTPMiddleware</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3476">#3476</a>.</li>
<li>Return <code>400</code> for invalid multipart parser input <a
href="https://redirect.github.com/Kludex/starlette/pull/3492">#3492</a>.</li>
<li>Include <code>Vary: Origin</code> on all normal CORS responses and
vary preflight responses by all request headers that affect them <a
href="https://redirect.github.com/Kludex/starlette/pull/3516">#3516</a>
and <a
href="https://redirect.github.com/Kludex/starlette/pull/3517">#3517</a>.</li>
<li>Handle malformed <code>Host</code> headers and IPv6 authorities
consistently across URL construction, host routing, and redirect
middleware <a
href="https://redirect.github.com/Kludex/starlette/pull/3472">#3472</a>.</li>
<li>Ignore <code>Range</code> headers when <code>FileResponse</code> has
a status other than <code>200</code>, preserving its status and full
body <a
href="https://redirect.github.com/Kludex/starlette/pull/3568">#3568</a>.</li>
<li>Handle standalone <code>If-None-Match: *</code> in
<code>StaticFiles</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3201">#3201</a>.</li>
<li>Reject WebSocket requests to <code>StaticFiles</code> without
raising an assertion error <a
href="https://redirect.github.com/Kludex/starlette/pull/3532">#3532</a>.</li>
<li>Persist session mutations made with <code>popitem()</code> and
<code>|=</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3436">#3436</a>.</li>
<li>Handle empty and absent payloads in
<code>WebSocketEndpoint.decode()</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3372">#3372</a>.</li>
<li>Implement <code>identity</code> on <code>SimpleUser</code> and
<code>UnauthenticatedUser</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3271">#3271</a>.</li>
<li>Allow <code>HTTPException</code> to use non-standard status codes
without an explicit <code>detail</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3545">#3545</a>.</li>
<li>Avoid deprecated AnyIO imports in <code>TestClient</code> and add
explicit imports in <code>WSGIMiddleware</code> for AnyIO 4.15
compatibility <a
href="https://redirect.github.com/Kludex/starlette/pull/3498">#3498</a>
and <a
href="https://redirect.github.com/Kludex/starlette/pull/3501">#3501</a>.</li>
<li>Offload debug traceback rendering to a worker thread in
<code>ServerErrorMiddleware</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/2858">#2858</a>.</li>
</ul>
<p><strong>Full changelog:</strong> <a
href="https://github.com/Kludex/starlette/compare/1.6.0...1.7.0">1.6.0...1.7.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/Kludex/starlette/blob/main/docs/release-notes.md">starlette's
changelog</a>.</em></p>
<blockquote>
<h2>1.7.0 (September 23, 2026)</h2>
<p>This release adds experimental OpenTelemetry tracing and requires
AnyIO 4.</p>
<p>!!! warning &quot;OpenTelemetryMiddleware is experimental&quot;
Its API and emitted telemetry may change in minor releases without a
deprecation period
<a
href="https://redirect.github.com/Kludex/starlette/pull/3574">#3574</a>.</p>
<h4>Added</h4>
<ul>
<li>Add experimental <code>OpenTelemetryMiddleware</code> for HTTP
server spans, with URL exclusions and custom tracer providers <a
href="https://redirect.github.com/Kludex/starlette/pull/3438">#3438</a>,
<a
href="https://redirect.github.com/Kludex/starlette/pull/3463">#3463</a>,
and <a
href="https://redirect.github.com/Kludex/starlette/pull/3520">#3520</a>.</li>
<li>Expose the matched route through
<code>scope[&quot;route&quot;]</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3438">#3438</a>.</li>
<li>Support the <code>QUERY</code> HTTP method in
<code>HTTPEndpoint</code>, CORS, and OpenAPI 3.2 schema generation <a
href="https://redirect.github.com/Kludex/starlette/pull/3489">#3489</a>.</li>
<li>Capture HTTP response trailers in <code>TestClient</code> and expose
them through
<code>response.extensions[&quot;http.response.trailers&quot;]</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3563">#3563</a>.</li>
<li>Support partitioned cookies in <code>SessionMiddleware</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3510">#3510</a>.</li>
<li>Add <code>partitioned</code> to
<code>Response.delete_cookie()</code> on Python 3.14 and later <a
href="https://redirect.github.com/Kludex/starlette/pull/3376">#3376</a>.</li>
<li>Support IPv6 hosts in <code>TrustedHostMiddleware</code> and
<code>TestClient</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3471">#3471</a>.</li>
<li>Support Python 3.15 <a
href="https://redirect.github.com/Kludex/starlette/pull/3508">#3508</a>.</li>
</ul>
<h4>Changed</h4>
<ul>
<li>Require <code>anyio&gt;=4.0.0,&lt;5</code>, dropping support for
AnyIO 3 <a
href="https://redirect.github.com/Kludex/starlette/pull/3512">#3512</a>.</li>
<li>Raise <code>WebSocketDisconnected</code>, a
<code>RuntimeError</code> subclass, for disconnected WebSocket
operations <a
href="https://redirect.github.com/Kludex/starlette/pull/2767">#2767</a>.</li>
<li>Accept <code>Collection[str]</code> in <code>CORSMiddleware</code>
configuration annotations, including sets and frozensets <a
href="https://redirect.github.com/Kludex/starlette/pull/3518">#3518</a>.</li>
</ul>
<h4>Fixed</h4>
<ul>
<li>Run background tasks only after the response is sent when using
<code>BaseHTTPMiddleware</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3476">#3476</a>.</li>
<li>Return <code>400</code> for invalid multipart parser input <a
href="https://redirect.github.com/Kludex/starlette/pull/3492">#3492</a>.</li>
<li>Include <code>Vary: Origin</code> on all normal CORS responses and
vary preflight responses by all request headers that affect them <a
href="https://redirect.github.com/Kludex/starlette/pull/3516">#3516</a>
and <a
href="https://redirect.github.com/Kludex/starlette/pull/3517">#3517</a>.</li>
<li>Handle malformed <code>Host</code> headers and IPv6 authorities
consistently across URL construction, host routing, and redirect
middleware <a
href="https://redirect.github.com/Kludex/starlette/pull/3472">#3472</a>.</li>
<li>Ignore <code>Range</code> headers when <code>FileResponse</code> has
a status other than <code>200</code>, preserving its status and full
body <a
href="https://redirect.github.com/Kludex/starlette/pull/3568">#3568</a>.</li>
<li>Handle standalone <code>If-None-Match: *</code> in
<code>StaticFiles</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3201">#3201</a>.</li>
<li>Reject WebSocket requests to <code>StaticFiles</code> without
raising an assertion error <a
href="https://redirect.github.com/Kludex/starlette/pull/3532">#3532</a>.</li>
<li>Persist session mutations made with <code>popitem()</code> and
<code>|=</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3436">#3436</a>.</li>
<li>Handle empty and absent payloads in
<code>WebSocketEndpoint.decode()</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3372">#3372</a>.</li>
<li>Implement <code>identity</code> on <code>SimpleUser</code> and
<code>UnauthenticatedUser</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3271">#3271</a>.</li>
<li>Allow <code>HTTPException</code> to use non-standard status codes
without an explicit <code>detail</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/3545">#3545</a>.</li>
<li>Avoid deprecated AnyIO imports in <code>TestClient</code> and add
explicit imports in <code>WSGIMiddleware</code> for AnyIO 4.15
compatibility <a
href="https://redirect.github.com/Kludex/starlette/pull/3498">#3498</a>
and <a
href="https://redirect.github.com/Kludex/starlette/pull/3501">#3501</a>.</li>
<li>Offload debug traceback rendering to a worker thread in
<code>ServerErrorMiddleware</code> <a
href="https://redirect.github.com/Kludex/starlette/pull/2858">#2858</a>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/Kludex/starlette/commit/2269e9a08c1edd3dfdea865710f40f84c857b623"><code>2269e9a</code></a>
Version 1.7.0 (<a
href="https://redirect.github.com/Kludex/starlette/issues/3575">#3575</a>)</li>
<li><a
href="https://github.com/Kludex/starlette/commit/4fe55eb2649e74fb01472bad9a1bc54fc3495904"><code>4fe55eb</code></a>
Preserve <code>FileResponse</code> status for range requests (<a
href="https://redirect.github.com/Kludex/starlette/issues/3568">#3568</a>)</li>
<li><a
href="https://github.com/Kludex/starlette/commit/1f08daf1627c866a4244418ea6da673d272fc8bb"><code>1f08daf</code></a>
Mark OpenTelemetryMiddleware as experimental (<a
href="https://redirect.github.com/Kludex/starlette/issues/3574">#3574</a>)</li>
<li><a
href="https://github.com/Kludex/starlette/commit/57de5fa9c2a98089a78d32d560e9b23e62560d5f"><code>57de5fa</code></a>
Support HTTP response trailers in TestClient (<a
href="https://redirect.github.com/Kludex/starlette/issues/3563">#3563</a>)</li>
<li><a
href="https://github.com/Kludex/starlette/commit/03f12b7fcf0a3e21a8da648ca0900c79472e9efe"><code>03f12b7</code></a>
Allow HTTPException to use non-standard status codes (<a
href="https://redirect.github.com/Kludex/starlette/issues/3545">#3545</a>)</li>
<li><a
href="https://github.com/Kludex/starlette/commit/76fd00f1e293990ea41555946a6b0f58901eaca1"><code>76fd00f</code></a>
Reject <code>WebSocket</code> requests to <code>StaticFiles</code> (<a
href="https://redirect.github.com/Kludex/starlette/issues/3532">#3532</a>)</li>
<li><a
href="https://github.com/Kludex/starlette/commit/f03f65c2f98c592773d691b4d309c68b83e568ef"><code>f03f65c</code></a>
docs: fix 'its not available' and 'This ensure' wording (<a
href="https://redirect.github.com/Kludex/starlette/issues/3526">#3526</a>)</li>
<li><a
href="https://github.com/Kludex/starlette/commit/485aca4e797d41849743cf73d5adcfd699695467"><code>485aca4</code></a>
docs: the test client is built on httpx2, not httpx (<a
href="https://redirect.github.com/Kludex/starlette/issues/3525">#3525</a>)</li>
<li><a
href="https://github.com/Kludex/starlette/commit/fd662b17b9cc41dca32a03509305619643f2dd61"><code>fd662b1</code></a>
Implement <code>identity</code> on <code>SimpleUser</code> and
<code>UnauthenticatedUser</code> (<a
href="https://redirect.github.com/Kludex/starlette/issues/3271">#3271</a>)</li>
<li><a
href="https://github.com/Kludex/starlette/commit/41db6a707f2636526847dbda0e5610e732e6b4fc"><code>41db6a7</code></a>
Stabilize CodSpeed upload buffer allocations (<a
href="https://redirect.github.com/Kludex/starlette/issues/3524">#3524</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/Kludex/starlette/compare/1.6.0...1.7.0">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: John Kennedy <jkennedyvz@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-10-01 11:28:27 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b36b1d58a8 chore(deps): bump tornado from 6.5.8 to 6.5.9 in /libs/langgraph (#9160)
Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.5.8 to
6.5.9.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst">tornado's
changelog</a>.</em></p>
<blockquote>
<h1>Release notes</h1>
<p>.. toctree::
:maxdepth: 2</p>
<p>releases/v6.6.0
releases/v6.5.10
releases/v6.5.9
releases/v6.5.8
releases/v6.5.7
releases/v6.5.6
releases/v6.5.5
releases/v6.5.4
releases/v6.5.3
releases/v6.5.2
releases/v6.5.1
releases/v6.5.0
releases/v6.4.2
releases/v6.4.1
releases/v6.4.0
releases/v6.3.3
releases/v6.3.2
releases/v6.3.1
releases/v6.3.0
releases/v6.2.0
releases/v6.1.0
releases/v6.0.4
releases/v6.0.3
releases/v6.0.2
releases/v6.0.1
releases/v6.0.0
releases/v5.1.1
releases/v5.1.0
releases/v5.0.2
releases/v5.0.1
releases/v5.0.0
releases/v4.5.3
releases/v4.5.2
releases/v4.5.1
releases/v4.5.0
releases/v4.4.3
releases/v4.4.2
releases/v4.4.1
releases/v4.4.0
releases/v4.3.0
releases/v4.2.1
releases/v4.2.0
releases/v4.1.0
releases/v4.0.2</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/tornadoweb/tornado/commit/75ef8b1cfa0e658aceb17c5a810ad1c74dc69bc7"><code>75ef8b1</code></a>
Merge pull request <a
href="https://redirect.github.com/tornadoweb/tornado/issues/3719">#3719</a>
from bdarnell/fixes-659</li>
<li><a
href="https://github.com/tornadoweb/tornado/commit/3590cb4566d363331c294cfa63c5035ae2c32c87"><code>3590cb4</code></a>
test: Hardcode SimpleAsyncHTTPClient in HTTP1xxLimitTestCase</li>
<li><a
href="https://github.com/tornadoweb/tornado/commit/9fc5d6d9fff435066836d165d0f1f6ebb067fb9e"><code>9fc5d6d</code></a>
test: Make tracemalloc optional in httpclient_test</li>
<li><a
href="https://github.com/tornadoweb/tornado/commit/555a2ee9a20275d6dfde879977fce58d02e7898a"><code>555a2ee</code></a>
iostream: Treat connection resets as a clean close in
read_until_close</li>
<li><a
href="https://github.com/tornadoweb/tornado/commit/3ba622f2ecb75226a8e64d4ee96b7045fc4c8a64"><code>3ba622f</code></a>
Release notes and version bump for 6.5.9</li>
<li><a
href="https://github.com/tornadoweb/tornado/commit/41eea68aba54e8ecaafc1b777dc5c104d289a290"><code>41eea68</code></a>
test: Fix some test issues only found by our custom tox config</li>
<li><a
href="https://github.com/tornadoweb/tornado/commit/ab1a778defaccd0dde9c1c419578e3a1777a9eeb"><code>ab1a778</code></a>
Merge remote-tracking branch
'bdarnell/claude/asynchttpclient-streaming-memor...</li>
<li><a
href="https://github.com/tornadoweb/tornado/commit/437ab5f76565403b3403438d2e555d11f8128d32"><code>437ab5f</code></a>
web: Do not follow symlinks out of the static directory</li>
<li><a
href="https://github.com/tornadoweb/tornado/commit/03945136ea9746eccf61caf88edae39642e59c93"><code>0394513</code></a>
httputil: Apply the argument count limit to query strings</li>
<li><a
href="https://github.com/tornadoweb/tornado/commit/b798f8322a15ba8b6ef725d698d1037024139714"><code>b798f83</code></a>
http1connection: Return after reading the response that follows a
1xx</li>
<li>Additional commits viewable in <a
href="https://github.com/tornadoweb/tornado/compare/v6.5.8...v6.5.9">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tornado&package-manager=uv&previous-version=6.5.8&new-version=6.5.9)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-01 09:00:10 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
9829ef9e64 chore(deps): bump virtualenv from 21.2.4 to 21.7.12 in /libs/cli (#9159)
Bumps [virtualenv](https://github.com/pypa/virtualenv) from 21.2.4 to
21.7.12.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pypa/virtualenv/releases">virtualenv's
releases</a>.</em></p>
<blockquote>
<h2>21.7.12</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>🔧 chore(changelog): drop dead CVE-2026-24049 fragment by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3249">pypa/virtualenv#3249</a></li>
<li>🐛 fix(activation): escape batch quote() against injection by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3250">pypa/virtualenv#3250</a></li>
<li>🐛 fix(seed): verify downloaded wheel digests by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3251">pypa/virtualenv#3251</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/pypa/virtualenv/compare/21.7.11...21.7.12">https://github.com/pypa/virtualenv/compare/21.7.11...21.7.12</a></p>
<h2>21.7.11</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>Add OpenSSF Scorecard workflow by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3238">pypa/virtualenv#3238</a></li>
<li>Document AI-assisted contributions and licensing policy by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3239">pypa/virtualenv#3239</a></li>
<li>👷 ci(release): attest and sign release provenance by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3242">pypa/virtualenv#3242</a></li>
<li>👷 ci: harden Scorecard-scored checks in CI by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3241">pypa/virtualenv#3241</a></li>
<li>🐛 fix(ci): parallelize graalpy tests, recover crashed workers by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3240">pypa/virtualenv#3240</a></li>
<li>🐛 fix(ci): mark real-shell activation tests as slow by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3243">pypa/virtualenv#3243</a></li>
<li>👷 ci: run macOS jobs on macos-26 by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3244">pypa/virtualenv#3244</a></li>
<li>🐛 fix(activation): undo a live activation before activate.bat saves
values by <a
href="https://github.com/darrenhuai"><code>@​darrenhuai</code></a> in <a
href="https://redirect.github.com/pypa/virtualenv/pull/3245">pypa/virtualenv#3245</a></li>
<li>🐛 fix(create): keep pyvenv.cfg values on a single line by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3247">pypa/virtualenv#3247</a></li>
<li>🔧 chore(test): add opt-in Atheris fuzz harness by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3246">pypa/virtualenv#3246</a></li>
<li>📝 docs(readme): add OpenSSF Best Practices badge by <a
href="https://github.com/gaborbernat"><code>@​gaborbernat</code></a> in
<a
href="https://redirect.github.com/pypa/virtualenv/pull/3248">pypa/virtualenv#3248</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/pypa/virtualenv/compare/21.7.10...21.7.11">https://github.com/pypa/virtualenv/compare/21.7.10...21.7.11</a></p>
<h2>21.7.10</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>🔧 chore: check spelling with typos in pre-commit by <a
href="https://github.com/even-even"><code>@​even-even</code></a> in <a
href="https://redirect.github.com/pypa/virtualenv/pull/3235">pypa/virtualenv#3235</a></li>
<li>🐛 fix(activation): keep and restore the user's TCL_LIBRARY and
TK_LIBRARY by <a
href="https://github.com/darrenhuai"><code>@​darrenhuai</code></a> in <a
href="https://redirect.github.com/pypa/virtualenv/pull/3234">pypa/virtualenv#3234</a></li>
<li>🐛 fix(create): skip blank and comment lines in pyvenv.cfg by <a
href="https://github.com/r3wretrhy"><code>@​r3wretrhy</code></a> in <a
href="https://redirect.github.com/pypa/virtualenv/pull/3232">pypa/virtualenv#3232</a></li>
<li>🐛 fix(activation): restore PKG_CONFIG_PATH that was not set before
by <a href="https://github.com/darrenhuai"><code>@​darrenhuai</code></a>
in <a
href="https://redirect.github.com/pypa/virtualenv/pull/3233">pypa/virtualenv#3233</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/r3wretrhy"><code>@​r3wretrhy</code></a>
made their first contribution in <a
href="https://redirect.github.com/pypa/virtualenv/pull/3232">pypa/virtualenv#3232</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/pypa/virtualenv/compare/21.7.9...21.7.10">https://github.com/pypa/virtualenv/compare/21.7.9...21.7.10</a></p>
<h2>21.7.9</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>fix(test): EncodingWarning: 'encoding' argument not specified by <a
href="https://github.com/even-even"><code>@​even-even</code></a> in <a
href="https://redirect.github.com/pypa/virtualenv/pull/3228">pypa/virtualenv#3228</a></li>
<li>🐛 fix(config): ignore a config file that fails to parse instead of
crashing by <a
href="https://github.com/darrenhuai"><code>@​darrenhuai</code></a> in <a
href="https://redirect.github.com/pypa/virtualenv/pull/3230">pypa/virtualenv#3230</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pypa/virtualenv/blob/main/docs/changelog.rst">virtualenv's
changelog</a>.</em></p>
<blockquote>
<h1>Bugfixes - 21.7.12</h1>
<ul>
<li>Fix <code>activate.bat</code> running arbitrary commands from a
crafted <code>--prompt</code>, <code>VIRTUALENV_PROMPT</code>, or config
file
value. (:issue:<code>3250</code>)</li>
<li>Verify a downloaded seed wheel's sha256 against PyPI before seeding
it into a virtual environment, skipped when a
custom pip index is configured. (:issue:<code>3251</code>)</li>
</ul>
<hr />
<p>v21.7.11 (2026-09-17)</p>
<hr />
<h1>Bugfixes - 21.7.11</h1>
<ul>
<li>Running <code>activate.bat</code> again before
<code>deactivate</code> no longer makes <code>deactivate</code> leave
the environment's
<code>PKG_CONFIG_PATH</code>, <code>TCL_LIBRARY</code> and
<code>TK_LIBRARY</code> behind, or lose values the user had set before
the first
activation - by :user:<code>darrenhuai</code>.
(:issue:<code>3245</code>)</li>
<li>Write <code>pyvenv.cfg</code> values on a single line, so a prompt
carrying a line boundary can no longer inject configuration.
<code>--prompt</code>, the <code>VIRTUALENV_PROMPT</code> environment
variable and the config file all set the prompt, and
<code>pyvenv.cfg</code> has no escape syntax, so a newline, a carriage
return, or any other boundary <code>str.splitlines</code>
recognizes, such as <code>U+2028</code>, started a new configuration
line. Reading the file back picked up those lines as keys,
and since the last value for a key wins, they replaced anything written
earlier, including <code>home</code>. (:issue:<code>3247</code>)</li>
</ul>
<h1>Improved Documentation - 21.7.11</h1>
<ul>
<li>Document the policy for AI-assisted contributions and the licensing
rules for dependencies. (:issue:<code>3239</code>)</li>
</ul>
<h1>Misc - 21.7.11</h1>
<ul>
<li>:issue:<code>3238</code>, :issue:<code>3240</code>,
:issue:<code>3241</code>, :issue:<code>3242</code>,
:issue:<code>3243</code>, :issue:<code>3244</code>,
:issue:<code>3246</code></li>
</ul>
<hr />
<p>v21.7.10 (2026-09-15)</p>
<hr />
<h1>Bugfixes - 21.7.10</h1>
<ul>
<li>Skip blank lines, <code>#</code> comments and lines without
<code>=</code> in <code>pyvenv.cfg</code> instead of raising
<code>ValueError</code> - by
:user:<code>r3wretrhy</code>. (:issue:<code>3232</code>)</li>
<li><code>deactivate</code> in bash, fish and PowerShell unsets
<code>PKG_CONFIG_PATH</code> when activation found it unset, instead of
keeping the environment's <code>lib/pkgconfig</code>. csh activation no
longer drops a <code>PKG_CONFIG_PATH</code> the user had set.
Activation in batch, fish, nushell and PowerShell no longer adds a
trailing separator when <code>PKG_CONFIG_PATH</code> is
unset, and PowerShell and nushell build the value with the host's path
separators - by :user:<code>darrenhuai</code>.
(:issue:<code>3233</code>)</li>
<li>Activation in bash, csh, fish and PowerShell keeps the user's
<code>TCL_LIBRARY</code> and <code>TK_LIBRARY</code>, and
<code>deactivate</code>
restores them. csh and PowerShell removed both variables on every
activation, fish did so when the interpreter has</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pypa/virtualenv/commit/9666b42afc8d6103e765d77958d7bae782f5406e"><code>9666b42</code></a>
release 21.7.12</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/a01ed3e2f239d6ab1fce62c5c7664ccf268fff6d"><code>a01ed3e</code></a>
🐛 fix(seed): verify downloaded wheel digests (<a
href="https://redirect.github.com/pypa/virtualenv/issues/3251">#3251</a>)</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/d721ff140ce4afdc2a9b76751e4584e25d9fbea6"><code>d721ff1</code></a>
🐛 fix(activation): escape batch quote() against injection (<a
href="https://redirect.github.com/pypa/virtualenv/issues/3250">#3250</a>)</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/087a2ef8bd3aa15b562a3558b1068f603e50f77a"><code>087a2ef</code></a>
🔧 chore(changelog): drop dead CVE-2026-24049 fragment (<a
href="https://redirect.github.com/pypa/virtualenv/issues/3249">#3249</a>)</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/73e352ae02bfa52ffc0e307b04f1b6a7168c4eb0"><code>73e352a</code></a>
release 21.7.11</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/68ee5a3f27ca44912af9bd73c4c87e41978a8c08"><code>68ee5a3</code></a>
📝 docs(readme): add OpenSSF Best Practices badge (<a
href="https://redirect.github.com/pypa/virtualenv/issues/3248">#3248</a>)</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/787d1c9a0843310200f37861e6b2744a7d1e5364"><code>787d1c9</code></a>
🔧 chore(test): add opt-in Atheris fuzz harness (<a
href="https://redirect.github.com/pypa/virtualenv/issues/3246">#3246</a>)</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/a30f995461043acb6cacbf3a890951563ccf7140"><code>a30f995</code></a>
🐛 fix(create): keep pyvenv.cfg values on a single line (<a
href="https://redirect.github.com/pypa/virtualenv/issues/3247">#3247</a>)</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/469dd28e659f7cd3e7d8cdb3f1245c125d32e817"><code>469dd28</code></a>
🐛 fix(activation): undo a live activation before activate.bat saves
values (#...</li>
<li><a
href="https://github.com/pypa/virtualenv/commit/a045a14c76dcb71d1811fe57aa6c5f4fad2357cd"><code>a045a14</code></a>
👷 ci: run macOS jobs on macos-26 (<a
href="https://redirect.github.com/pypa/virtualenv/issues/3244">#3244</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pypa/virtualenv/compare/21.2.4...21.7.12">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=virtualenv&package-manager=uv&previous-version=21.2.4&new-version=21.7.12)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-01 08:59:43 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
f6e9ace639 chore(deps): bump actions/deploy-pages from 5.0.0 to 5.0.1 in the minor-and-patch group (#9144)
Bumps the minor-and-patch group with 1 update:
[actions/deploy-pages](https://github.com/actions/deploy-pages).

Updates `actions/deploy-pages` from 5.0.0 to 5.0.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/deploy-pages/releases">actions/deploy-pages's
releases</a>.</em></p>
<blockquote>
<h2>v5.0.1</h2>
<h1>Changelog</h1>
<ul>
<li>Add backoff and jitter to deployment polling <a
href="https://github.com/yoannchaudet"><code>@​yoannchaudet</code></a>
(<a
href="https://redirect.github.com/actions/deploy-pages/issues/444">#444</a>)</li>
<li>Improve deployment request test coverage <a
href="https://github.com/adwitiyagoyal"><code>@​adwitiyagoyal</code></a>
(<a
href="https://redirect.github.com/actions/deploy-pages/issues/440">#440</a>)</li>
</ul>
<hr />
<p>See details of <a
href="https://github.com/actions/deploy-pages/compare/v5.0.0...v5.0.1">all
code changes</a> since previous release.</p>
<p>⚠️ For use with products other than GitHub.com, such as GitHub
Enterprise Server, please consult the <a
href="https://github.com/actions/deploy-pages/#compatibility">compatibility
table</a>.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/deploy-pages/commit/368f82528645a54fb793d4d04e342629a3f51346"><code>368f825</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/deploy-pages/issues/444">#444</a>
from actions/yoannchaudet-deployment-polling-backoff</li>
<li><a
href="https://github.com/actions/deploy-pages/commit/7e97763d1f8271fc88f351a0c275f37de7f32094"><code>7e97763</code></a>
Validate deployment polling intervals</li>
<li><a
href="https://github.com/actions/deploy-pages/commit/0143e11abb4ace1f6858cb44b2ab99eae8a40b45"><code>0143e11</code></a>
Add backoff and jitter to deployment polling</li>
<li><a
href="https://github.com/actions/deploy-pages/commit/5e98f10ce206463e411e82ac66ef0f2df79c5499"><code>5e98f10</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/deploy-pages/issues/440">#440</a>
from actions/user/adwitiya</li>
<li><a
href="https://github.com/actions/deploy-pages/commit/8b0625abb54462fce279dc6ce57ef7ce0fb8b8fc"><code>8b0625a</code></a>
Improve deployment request test coverage</li>
<li>See full diff in <a
href="https://github.com/actions/deploy-pages/compare/cd2ce8fcbc39b97be8ca5fce6e763baed58fa128...368f82528645a54fb793d4d04e342629a3f51346">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/deploy-pages&package-manager=github_actions&previous-version=5.0.0&new-version=5.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-01 01:52:22 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b1765f3d0f chore(deps): bump the minor-and-patch group in /libs/checkpoint-postgres with 6 updates (#9147)
Bumps the minor-and-patch group in /libs/checkpoint-postgres with 6
updates:

| Package | From | To |
| --- | --- | --- |
| [psycopg](https://github.com/psycopg/psycopg) | `3.3.4` | `3.3.6` |
| [psycopg-pool](https://github.com/psycopg/psycopg) | `3.3.1` | `3.3.3`
|
| [anyio](https://github.com/agronholm/anyio) | `4.14.2` | `4.15.1` |
| [pytest-mock](https://github.com/pytest-dev/pytest-mock) | `3.15.1` |
`3.16.0` |
| [ruff](https://github.com/astral-sh/ruff) | `0.16.5` | `0.16.9` |
| [ty](https://github.com/astral-sh/ty) | `0.0.75` | `0.0.84` |

Updates `psycopg` from 3.3.4 to 3.3.6
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/psycopg/psycopg/blob/master/docs/news.rst">psycopg's
changelog</a>.</em></p>
<blockquote>
<p>.. currentmodule:: psycopg</p>
<p>.. index::
single: Release notes
single: News</p>
<h1><code>psycopg</code> release notes</h1>
<h2>Future releases</h2>
<p>Psycopg 3.3.7 (unreleased)
^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<ul>
<li>Fix segfault fetching arrays of strings or timestamps after closing
the
connection
(🎫<code>[#1428](https://github.com/psycopg/psycopg/issues/1428)</code>).</li>
</ul>
<h2>Current release</h2>
<p>Psycopg 3.3.6
^^^^^^^^^^^^^</p>
<ul>
<li>Add support for Python 3.15
(🎫<code>[#1245](https://github.com/psycopg/psycopg/issues/1245)</code>).</li>
<li>Improve performance of async queries by reducing the overhead of the
<code>!wait_async()</code> function
(🎫<code>[#1331](https://github.com/psycopg/psycopg/issues/1331)</code>).</li>
<li>Don't wait forever for a query to terminate after interrupting it,
for
instance if the server is unresponsive. The fix requires libpq 17 or
newer

(🎫<code>[#1371](https://github.com/psycopg/psycopg/issues/1371)</code>).</li>
<li>Cancel a running query upon receiving <code>!SystemExit</code>
(🎫<code>[#1384](https://github.com/psycopg/psycopg/issues/1384)</code>).</li>
<li>Report <code>!None</code> instead of <code>65535</code> as the
<code>Column.precision</code> of an
:sql:<code>interval</code> column declared with a fields restriction and
no explicit
precision, such as e.g. :sql:<code>interval day to second</code>
(🎫<code>[#1397](https://github.com/psycopg/psycopg/issues/1397)</code>).</li>
<li>Fix dumping of nested subclasses of lists as arrays
(🎫<code>[#1398](https://github.com/psycopg/psycopg/issues/1398)</code>).</li>
<li>Discard prepared statements upon :sql:<code>DEALLOCATE ALL</code>
(🎫<code>[#1408](https://github.com/psycopg/psycopg/issues/1408)</code>).</li>
<li>Better guards dumping large Python <code>!int</code> to binary
numeric
(🎫<code>[#1414](https://github.com/psycopg/psycopg/issues/1414)</code>).</li>
</ul>
<p>Psycopg 3.3.5
^^^^^^^^^^^^^</p>
<ul>
<li>Discard prepared statements upon :sql:<code>ALTER *</code> or
<code>DISCARD *</code>

(🎫<code>[#1307](https://github.com/psycopg/psycopg/issues/1307)</code>).</li>
<li>Fix <code>!ProgrammingError</code> when dumping
non-<code>!None</code> values with
no <code>!NoneType</code> dumper registered in python implementation
(🎫<code>[#1325](https://github.com/psycopg/psycopg/issues/1325)</code>).</li>
<li>Fix <code>!wait_selector</code> wait function to not raise
<code>!KeyError</code>

(🎫<code>[#1327](https://github.com/psycopg/psycopg/issues/1327)</code>).</li>
<li>Fix <code>!DataError</code> messages leaking the literal
<code>{...}</code> placeholder instead</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/psycopg/psycopg/commit/a67654d1e7afbf9b3a619557838f62de1c790e7c"><code>a67654d</code></a>
chore: bump psycopg package version to 3.3.6</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/443814b3b111ac678a39fd523c1a826266fb69b5"><code>443814b</code></a>
Merge pull request <a
href="https://redirect.github.com/psycopg/psycopg/issues/1416">#1416</a>
from dvarrazzo/wait-async-perf</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/42966e9ebbda3b9c69b15c5588543c15f2aae5dd"><code>42966e9</code></a>
test: add helpful comments to some tests</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/5e8797f0c8003d8cd12a1e5c13f05fbb94c1c1d2"><code>5e8797f</code></a>
test: add reasonable connect_timeout to most tests</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/c81ba62442dfbd69e207d6914e6ae2aa27e56886"><code>c81ba62</code></a>
perf: reduce the overhead of wait_async()</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/d2bbfe4e2b1e36a20e72a18097f35a3db27296e3"><code>d2bbfe4</code></a>
refactor: use get_running_loop() in the async wait functions</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/2b1484a550e01c88fda077099678f0abb9217ecb"><code>2b1484a</code></a>
test: add a script to measure the async wait functions</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/573cf4aa70d8fdefc9d5f3eb69d5419cd6d3cd51"><code>573cf4a</code></a>
test: fix incorrect wait timing test</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/2b68990874175b8d97269218d4963b2d5c8656f3"><code>2b68990</code></a>
refactor: drop leftovers of waiting with inf interval in
wait_conn_async</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/60765dd8fc7d8df03cd75efcff485bfb3c83a0ed"><code>60765dd</code></a>
Merge pull request <a
href="https://redirect.github.com/psycopg/psycopg/issues/1414">#1414</a>
from dvarrazzo/fix-decimal-overflow</li>
<li>Additional commits viewable in <a
href="https://github.com/psycopg/psycopg/compare/3.3.4...3.3.6">compare
view</a></li>
</ul>
</details>
<br />

Updates `psycopg-pool` from 3.3.1 to 3.3.3
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/psycopg/psycopg/blob/master/docs/news.rst">psycopg-pool's
changelog</a>.</em></p>
<blockquote>
<p>.. currentmodule:: psycopg</p>
<p>.. index::
single: Release notes
single: News</p>
<h1><code>psycopg</code> release notes</h1>
<h2>Future releases</h2>
<p>Psycopg 3.3.7 (unreleased)
^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<ul>
<li>Fix segfault fetching arrays of strings or timestamps after closing
the
connection
(🎫<code>[#1428](https://github.com/psycopg/psycopg/issues/1428)</code>).</li>
</ul>
<h2>Current release</h2>
<p>Psycopg 3.3.6
^^^^^^^^^^^^^</p>
<ul>
<li>Add support for Python 3.15
(🎫<code>[#1245](https://github.com/psycopg/psycopg/issues/1245)</code>).</li>
<li>Improve performance of async queries by reducing the overhead of the
<code>!wait_async()</code> function
(🎫<code>[#1331](https://github.com/psycopg/psycopg/issues/1331)</code>).</li>
<li>Don't wait forever for a query to terminate after interrupting it,
for
instance if the server is unresponsive. The fix requires libpq 17 or
newer

(🎫<code>[#1371](https://github.com/psycopg/psycopg/issues/1371)</code>).</li>
<li>Cancel a running query upon receiving <code>!SystemExit</code>
(🎫<code>[#1384](https://github.com/psycopg/psycopg/issues/1384)</code>).</li>
<li>Report <code>!None</code> instead of <code>65535</code> as the
<code>Column.precision</code> of an
:sql:<code>interval</code> column declared with a fields restriction and
no explicit
precision, such as e.g. :sql:<code>interval day to second</code>
(🎫<code>[#1397](https://github.com/psycopg/psycopg/issues/1397)</code>).</li>
<li>Fix dumping of nested subclasses of lists as arrays
(🎫<code>[#1398](https://github.com/psycopg/psycopg/issues/1398)</code>).</li>
<li>Discard prepared statements upon :sql:<code>DEALLOCATE ALL</code>
(🎫<code>[#1408](https://github.com/psycopg/psycopg/issues/1408)</code>).</li>
<li>Better guards dumping large Python <code>!int</code> to binary
numeric
(🎫<code>[#1414](https://github.com/psycopg/psycopg/issues/1414)</code>).</li>
</ul>
<p>Psycopg 3.3.5
^^^^^^^^^^^^^</p>
<ul>
<li>Discard prepared statements upon :sql:<code>ALTER *</code> or
<code>DISCARD *</code>

(🎫<code>[#1307](https://github.com/psycopg/psycopg/issues/1307)</code>).</li>
<li>Fix <code>!ProgrammingError</code> when dumping
non-<code>!None</code> values with
no <code>!NoneType</code> dumper registered in python implementation
(🎫<code>[#1325](https://github.com/psycopg/psycopg/issues/1325)</code>).</li>
<li>Fix <code>!wait_selector</code> wait function to not raise
<code>!KeyError</code>

(🎫<code>[#1327](https://github.com/psycopg/psycopg/issues/1327)</code>).</li>
<li>Fix <code>!DataError</code> messages leaking the literal
<code>{...}</code> placeholder instead</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/psycopg/psycopg/commit/1a8f65a371da3c691111cd4a81141f2cb698eafa"><code>1a8f65a</code></a>
chore: bump psycopg package version to 3.3.3</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/db3c43584320ab5d97e49378e5c9dc09a560b031"><code>db3c435</code></a>
Merge pull request <a
href="https://redirect.github.com/psycopg/psycopg/issues/1260">#1260</a>
from ggevay/sync-error-fix</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/0237586c415ece15102742f5941874c29fb1221c"><code>0237586</code></a>
Fix ValueError when server sends ErrorResponse during Sync after
Parse</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/cb97ef7063520cb8a0cb5236bb9791f8dc4cc454"><code>cb97ef7</code></a>
docs: fix typos</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/09c89180f94606dc70475ed863e135f021a11038"><code>09c8918</code></a>
Merge pull request <a
href="https://redirect.github.com/psycopg/psycopg/issues/1256">#1256</a>
from veeceey/fix/tstrings-error-msg-and-docs-improve...</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/9e74d9646cc3fcbb9d8940182dcdb41119c3fda7"><code>9e74d96</code></a>
fix: fix error message incorrectly generated by Claude AI</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/0db9d8bb76c48e70dffd48776406fd3ffdc89b5a"><code>0db9d8b</code></a>
fix: correct typo in tstrings error message and fix sql.rst docs</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/86a0e1b2bbf30c564c59bf3497d499e2f220ce0f"><code>86a0e1b</code></a>
chore(deps): bump pypa/cibuildwheel in the actions group</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/f5d90fa2a7836c1268c1d43d0d77c431434ad191"><code>f5d90fa</code></a>
Merge pull request <a
href="https://redirect.github.com/psycopg/psycopg/issues/1233">#1233</a>
from lysnikolaou/pgconn-critical-section</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/d7dc6c7cacc2832fffa0d7e607b5fc171424571d"><code>d7dc6c7</code></a>
Merge critical section and nogil blocks into one context manager</li>
<li>Additional commits viewable in <a
href="https://github.com/psycopg/psycopg/compare/3.3.1...3.3.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `anyio` from 4.14.2 to 4.15.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/agronholm/anyio/releases">anyio's
releases</a>.</em></p>
<blockquote>
<h2>4.15.1</h2>
<ul>
<li>Implemented a compatibility fix for supporting direct access of
<code>anyio.*</code> submodules from the main package even when those
submodules were not directly imported first (<!-- raw HTML omitted --><a
href="https://redirect.github.com/agronholm/anyio/issues/1311">#1311</a>
&lt;<a
href="https://redirect.github.com/agronholm/anyio/issues/1311%5C%3E">agronholm/anyio#1311</a><!--
raw HTML omitted -->)</li>
</ul>
<h2>4.15.0</h2>
<ul>
<li>
<p>Added support for the newer keyword-only arguments on
<code>anyio.Path</code> methods to match the standard library
<code>pathlib.Path</code>:</p>
<ul>
<li><code>follow_symlinks</code> on <code>exists()</code> (Python
3.12+)</li>
<li><code>follow_symlinks</code> on <code>is_dir()</code> (Python
3.13+)</li>
<li><code>follow_symlinks</code> on <code>is_file()</code> (Python
3.13+)</li>
<li><code>follow_symlinks</code> on <code>owner()</code> (Python
3.13+)</li>
<li><code>follow_symlinks</code> on <code>group()</code> (Python
3.13+)</li>
<li><code>newline</code> on <code>read_text()</code> (Python 3.13+)</li>
</ul>
<p>(<a
href="https://redirect.github.com/agronholm/anyio/pull/1286">#1286</a>,
<a
href="https://redirect.github.com/agronholm/anyio/pull/1293">#1293</a>;
PR by <a
href="https://github.com/jaideeppyne"><code>@​jaideeppyne</code></a>)</p>
</li>
<li>
<p>Added <code>amap</code>, <code>gather</code>, and
<code>as_completed</code> utility functions to simplify common patterns
(<a
href="https://redirect.github.com/agronholm/anyio/pull/1173">#1173</a>;
PR by <a
href="https://github.com/Graeme22"><code>@​Graeme22</code></a>)</p>
</li>
<li>
<p>Added <code>--anyio-mode</code> command-line option as an alternative
to the <code>anyio_mode</code> ini setting, and fix the pytest plugin's
auto mode detection to recognize the mode when set via either
mechanism(e.g: <code>pytest_asyncio</code>). (<a
href="https://redirect.github.com/agronholm/anyio/pull/1242">#1242</a>;
PR by <a
href="https://github.com/EmmanuelNiyonshuti"><code>@​EmmanuelNiyonshuti</code></a>)</p>
</li>
<li>
<p>Added the <code>anyio.Future</code> synchronization primitive which
behaves similar to <code>asyncio.Future</code>, allowing tasks to wait
for a value (or exception) from another task (<a
href="https://redirect.github.com/agronholm/anyio/pull/1146">#1146</a>;
PR by <a
href="https://github.com/Vizonex"><code>@​Vizonex</code></a>)</p>
</li>
<li>
<p>Added guidance for managing multiple memory object stream producers
and consumers with cloned streams (<a
href="https://redirect.github.com/agronholm/anyio/issues/330">#330</a>;
PR by <a
href="https://github.com/nightcityblade"><code>@​nightcityblade</code></a>)</p>
</li>
<li>
<p>Added <code>StapledObjectStream.send_nowait()</code> that delegates
to the underlying <code>ObjectSendStream</code>, if it implements it (<a
href="https://redirect.github.com/agronholm/anyio/pull/1241">#1241</a>;
PR by <a
href="https://github.com/davidbrochart"><code>@​davidbrochart</code></a>)</p>
</li>
<li>
<p>Added the <code>move_on_at()</code> and <code>fail_at()</code>
functions to complement <code>move_on_after()</code> and
<code>fail_after()</code></p>
</li>
<li>
<p>Changed the default name for a task spawned with
<code>TaskGroup.create_task(func())</code> to match the default task
name for the analogous task spawned with
<code>TaskGroup.start_soon(func)</code> or
<code>TaskGroup.start(func)</code> in more situations. Previously, the
default name of a <code>TaskGroup.create_task</code> task never included
the module name. (The default name for a task spawned with
<code>TaskGroup.start_soon</code> or <code>TaskGroup.start</code>
typically includes the module name.) (<a
href="https://redirect.github.com/agronholm/anyio/pull/1234">#1234</a>;
PR by <a
href="https://github.com/gschaffner"><code>@​gschaffner</code></a>)</p>
</li>
<li>
<p>Changed the <code>anyio</code> and <code>anyio.abc</code> modules to
lazily (much like <code>810</code>) import the necessary submodules.
This is done by parsing the AST of the module and building a lookup
table from the <code>if TYPE_CHECKING:</code> block. A fallback mode has
been provided for installations where the source code is unavailable
(e.g. PyInstaller). (<a
href="https://redirect.github.com/agronholm/anyio/pull/1169">#1169</a>)</p>
</li>
<li>
<p>Fixed free-threading compatibility issues arising from the fact that
on Python 3.14 free-threading builds, newly created threads inherit the
current context by default, causing AnyIO to behave erroneously in
relation to <code>start_blocking_portal()</code> and
<code>anyio.to_thread.run_sync()</code> (<a
href="https://redirect.github.com/agronholm/anyio/pull/1224">#1224</a>;
PR by <a
href="https://github.com/EmmanuelNiyonshuti"><code>@​EmmanuelNiyonshuti</code></a>)</p>
</li>
<li>
<p>Fixed <code>SpooledTemporaryFile.readinto()</code> and
<code>readinto1()</code> reading twice before rollover, so the
destination buffer was overwritten by the second read and the file
position advanced twice, silently losing data (<a
href="https://redirect.github.com/agronholm/anyio/pull/1215">#1215</a>;
PR by <a
href="https://github.com/c-tonneslan"><code>@​c-tonneslan</code></a>)</p>
</li>
<li>
<p>Added a <code>reason</code> parameter to <code>fail_after</code> (and
the new <code>fail_at</code>) allowing for added exception context when
raising <code>TimeoutError</code> (<a
href="https://redirect.github.com/agronholm/anyio/pull/1227">#1227</a>;
PR by <a
href="https://github.com/Graeme22"><code>@​Graeme22</code></a>)</p>
</li>
<li>
<p>Fixed the default <code>TaskHandle.name</code> missing part of the
task name for tasks started with <code>TaskGroup.start</code> on Trio
(<a
href="https://redirect.github.com/agronholm/anyio/issues/1231">#1231</a>;
PR by <a
href="https://github.com/gschaffner"><code>@​gschaffner</code></a>)</p>
</li>
<li>
<p>Fixed <code>anyio.run</code> leaking, or at least, delaying
collection of loop and root_task due to the root task being cached in a
<code>RunVar</code>. (<a
href="https://redirect.github.com/agronholm/anyio/issues/1203">#1203</a>;
PR by <a
href="https://github.com/tapetersen"><code>@​tapetersen</code></a>)</p>
</li>
<li>
<p>Fixed <code>anyio.Path.with_stem()</code> silently producing a wrong
path (e.g. <code>Path(&quot;.txt&quot;)</code>) instead of raising
<code>ValueError</code> when given an empty stem on a path with a
non-empty suffix, unlike <code>pathlib.PurePath.with_stem</code> (<a
href="https://redirect.github.com/agronholm/anyio/pull/1200">#1200</a>;
PR by <a
href="https://github.com/Sanjays2402"><code>@​Sanjays2402</code></a>)</p>
</li>
<li>
<p>Fixed <code>UNIXSocketStream.aclose()</code> raising
<code>asyncio.InvalidStateError</code> when a concurrent receive or send
operation had just been cancelled on the asyncio backend (<a
href="https://redirect.github.com/agronholm/anyio/issues/1267">#1267</a>;
PR by <a
href="https://github.com/alloutflo"><code>@​alloutflo</code></a>)</p>
</li>
<li>
<p>Fixed the pytest plugin importing the deprecated
<code>_pytest.python.CallSpec2</code> alias, which triggers
<code>PytestRemovedIn10Warning</code> on <code>pytest&gt;=9.2</code> and
crashes pytest at startup when <code>filterwarnings = error</code> is
configured (<a
href="https://redirect.github.com/agronholm/anyio/issues/1271">#1271</a>;
PR by <a
href="https://github.com/matthewfeickert"><code>@​matthewfeickert</code></a>)</p>
</li>
<li>
<p>Fixed an asyncio worker thread race that could raise
<code>RuntimeError</code> when the event loop closed between checking
its state and scheduling the worker result (<a
href="https://redirect.github.com/agronholm/anyio/issues/1265">#1265</a>;
PR by <a
href="https://github.com/hansu650"><code>@​hansu650</code></a>)</p>
</li>
<li>
<p>Fixed <code>CapacityLimiter</code> on the asyncio backend
over-granting tokens when <code>total_tokens</code> was raised while the
limiter was over-subscribed (<a
href="https://redirect.github.com/agronholm/anyio/pull/1223">#1223</a>;
PR by <a
href="https://github.com/zelinewang"><code>@​zelinewang</code></a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/agronholm/anyio/commit/ffcd1542cd6d127980205f90a0100078849dd703"><code>ffcd154</code></a>
Bumped up the version</li>
<li><a
href="https://github.com/agronholm/anyio/commit/0ecf5ed98d294242509b043ebd1a0843e52d892f"><code>0ecf5ed</code></a>
Added a workaround for third party code accessing unimported submodules
(<a
href="https://redirect.github.com/agronholm/anyio/issues/1309">#1309</a>)</li>
<li><a
href="https://github.com/agronholm/anyio/commit/928366259543412a2deb1e2ba09ea45ffa92ef4f"><code>9283662</code></a>
Bumped up the version</li>
<li><a
href="https://github.com/agronholm/anyio/commit/d137692a90f76e4f71605e32ea5ca94cab3a539d"><code>d137692</code></a>
Improved the instructions for AI agents</li>
<li><a
href="https://github.com/agronholm/anyio/commit/033fc52b8fa8e90c5d0ef24b10b3860e974a6265"><code>033fc52</code></a>
Shield TemporaryDirectory cleanup from cancellation (<a
href="https://redirect.github.com/agronholm/anyio/issues/1304">#1304</a>)</li>
<li><a
href="https://github.com/agronholm/anyio/commit/942e9a6552cc10b5aaa779d84bfc8e2c3d5fcffc"><code>942e9a6</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/agronholm/anyio/issues/1305">#1305</a>)</li>
<li><a
href="https://github.com/agronholm/anyio/commit/b825c3be7cb4ca1a8000b8065d4e147843deb704"><code>b825c3b</code></a>
Fixed pyproject.toml changes not triggering the test suite</li>
<li><a
href="https://github.com/agronholm/anyio/commit/9727dc504681e2986b5bc285de9571fb467539af"><code>9727dc5</code></a>
Fixed start inconsistencies between trio and asyncio (<a
href="https://redirect.github.com/agronholm/anyio/issues/1198">#1198</a>)</li>
<li><a
href="https://github.com/agronholm/anyio/commit/b05fe6d160a640355c201363cab286a7d2581da8"><code>b05fe6d</code></a>
Fixed wrong type in move_on_after (<a
href="https://redirect.github.com/agronholm/anyio/issues/1297">#1297</a>)</li>
<li><a
href="https://github.com/agronholm/anyio/commit/44d0c93cc20079acbf38ba4dbed5ab9df323f153"><code>44d0c93</code></a>
Fixed asyncio task group coroutine cleanup (<a
href="https://redirect.github.com/agronholm/anyio/issues/1275">#1275</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/agronholm/anyio/compare/4.14.2...4.15.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `pytest-mock` from 3.15.1 to 3.16.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/releases">pytest-mock's
releases</a>.</em></p>
<blockquote>
<h2>v3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/604">#604</a>:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/611">#611</a>:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/606">#606</a>:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/547">#547</a>:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/147">#147</a>:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst">pytest-mock's
changelog</a>.</em></p>
<blockquote>
<h2>3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><code>[#604](https://github.com/pytest-dev/pytest-mock/issues/604)
&lt;https://github.com/pytest-dev/pytest-mock/pull/604&gt;</code>_:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><code>[#611](https://github.com/pytest-dev/pytest-mock/issues/611)
&lt;https://github.com/pytest-dev/pytest-mock/pull/611&gt;</code>_:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><code>[#606](https://github.com/pytest-dev/pytest-mock/issues/606)
&lt;https://github.com/pytest-dev/pytest-mock/pull/606&gt;</code>_:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><code>[#547](https://github.com/pytest-dev/pytest-mock/issues/547)
&lt;https://github.com/pytest-dev/pytest-mock/issues/547&gt;</code>_:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><code>[#147](https://github.com/pytest-dev/pytest-mock/issues/147)
&lt;https://github.com/pytest-dev/pytest-mock/issues/147&gt;</code>_:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/f3b531f93c6d9837edc87ea1a6f4324dc9a2cdf3"><code>f3b531f</code></a>
Release 3.16.0</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/71ed67309520be160f3e100368705b58758d237a"><code>71ed673</code></a>
Fix duplicate_iterators for async spies (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/604">#604</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/0797e3d303cc5bbe0a3514b0625f7aeb3fa350b0"><code>0797e3d</code></a>
Fix async assertion argument introspection (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/611">#611</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/e24c334d573cfbf6989a31f4e3346676d9d31598"><code>e24c334</code></a>
docs: import os in the opening usage example (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/612">#612</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/9e7eb7b59cde362c1c8ace2d18ca00fe2d7a1cd1"><code>9e7eb7b</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/613">#613</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/445fd4d3daa8ed4c6d5428a77880da2e03d2f721"><code>445fd4d</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/610">#610</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/a8bd0b147afdf6b4bb1a1a3c3c088f32b0240091"><code>a8bd0b1</code></a>
Honour resetall() arguments for non-callable mocks (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/606">#606</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/6559fdfd5b67f096423e604a3a5a7045db2486a0"><code>6559fdf</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/608">#608</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/466d026254c949a8fbba8626b894308827be81cf"><code>466d026</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/605">#605</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/164defebde25bc31d53a2a64943c5c9aac43b57e"><code>164defe</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/603">#603</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pytest-dev/pytest-mock/compare/v3.15.1...v3.16.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.16.5 to 0.16.9
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>Install ruff 0.16.9</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-installer.sh
| sh
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>0.16.8</h2>
<p>Released on 2026-09-16.</p>
<h3>Bug fixes</h3>
<ul>
<li>Visit functional <code>TypedDict</code> keyword arguments correctly
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28584">#28584</a>)</li>
<li>[<code>flake8-simplify</code>] Detect nested <code>async with</code>
under sync parent (<code>SIM117</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27821">#27821</a>)</li>
<li>[<code>flake8-simplify</code>] Preserve operand order in
<code>SIM109</code> fix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27824">#27824</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/0be08a206f9c3180afd3e93bcc792ed5cb1f4db1"><code>0be08a2</code></a>
Bump version to 0.16.9 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28882">#28882</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/b4920b72b354e7c715ab861ae23458874683bb02"><code>b4920b7</code></a>
Rename <code>ruff_cli</code> to <code>ruff_command_line</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28881">#28881</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/47c751b95908a4d1f95f9ef8723036aae9da0b18"><code>47c751b</code></a>
Update dependency astral-sh/uv to v0.12.18 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28880">#28880</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c244e56a1aeac31c26d2371ef26588e0632235c"><code>8c244e5</code></a>
[<code>flake8-comprehensions</code>] Document <code>map</code>/generator
exception behavior (<code>C417</code>...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/5edf5a1d0a84663079e46983216059f06acea87d"><code>5edf5a1</code></a>
Use <code>target</code> form in <code>rooster.version_files</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28876">#28876</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/915bb2b4bf9ae7eee47cf55646bbfebae254a23b"><code>915bb2b</code></a>
[ty] Prefer existing @ paths over response files in Ruff and ty (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28877">#28877</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4710e1aa962b13720cf64aa84eb279c5333896d7"><code>4710e1a</code></a>
ci(github): update version number in placeholder of issue template (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28871">#28871</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/eedfc62a75bf1ba86d48959b00eea75ae87eadca"><code>eedfc62</code></a>
[ty] Propagate outer type context through cast calls (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28855">#28855</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/ceaa6a00830e1e350b8a23977a1a10ac467920a1"><code>ceaa6a0</code></a>
[ty] Contain rendered code within Markdown fences (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28869">#28869</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/dba0f30615424b94f94a174bba6ce6cce4bf11ff"><code>dba0f30</code></a>
authorize ruff-pre-commit dispatch via OIDC (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28867">#28867</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.16.5...0.16.9">compare
view</a></li>
</ul>
</details>
<br />

Updates `ty` from 0.0.75 to 0.0.84
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/releases">ty's
releases</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/blob/main/CHANGELOG.md">ty's
changelog</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ty/commit/8dd9a7f7fa35a18275d82117e6593ba45507065f"><code>8dd9a7f</code></a>
Bump version to 0.0.84 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4585">#4585</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/d4e4bf90906c7677049bc3a29d1735de7d22052d"><code>d4e4bf9</code></a>
publish to astral-sh/versions via OIDC (<a
href="https://redirect.github.com/astral-sh/ty/issues/4581">#4581</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/94ce7333abb356b2068dc98d37a68c993da6d09b"><code>94ce733</code></a>
use oidc issued token for docs publication (<a
href="https://redirect.github.com/astral-sh/ty/issues/4579">#4579</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/901eeaa9cd9ac06f34e85e4f721f76a0dc36e217"><code>901eeaa</code></a>
Update prek dependencies (<a
href="https://redirect.github.com/astral-sh/ty/issues/4576">#4576</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/09bf0b1b2114a628f3e2296d3d9d28245066c98b"><code>09bf0b1</code></a>
Update docker/setup-buildx-action action to v4.3.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4575">#4575</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/89d6ffe529dd44f64adc0d28f80744b7c7ab217f"><code>89d6ffe</code></a>
Update astral-sh/setup-uv action to v10.2.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4574">#4574</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/9c214798cfcc59069e986876564638fadf32d774"><code>9c21479</code></a>
Bump version to 0.0.83 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4569">#4569</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/04c69110b391e96310e6892cbed9936c4f31d7aa"><code>04c6911</code></a>
Sync the ty security mirror (<a
href="https://redirect.github.com/astral-sh/ty/issues/4549">#4549</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/3fa57a25767c619dbeba697c2acfbb8eb291519a"><code>3fa57a2</code></a>
Grant the versions workflow repository read access (<a
href="https://redirect.github.com/astral-sh/ty/issues/4550">#4550</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/a15b35389b44db57f718fd4e19e093481747c53e"><code>a15b353</code></a>
use scoped token for release workflow (<a
href="https://redirect.github.com/astral-sh/ty/issues/4506">#4506</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ty/compare/0.0.75...0.0.84">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-01 01:52:12 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3a2501e8c5 chore(deps): bump the minor-and-patch group in /libs/checkpoint with 4 updates (#9148)
Bumps the minor-and-patch group in /libs/checkpoint with 4 updates:
[langchain-core](https://github.com/langchain-ai/langchain),
[pytest-mock](https://github.com/pytest-dev/pytest-mock),
[ruff](https://github.com/astral-sh/ruff) and
[ty](https://github.com/astral-sh/ty).

Updates `langchain-core` from 1.6.1 to 1.6.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/langchain-ai/langchain/releases">langchain-core's
releases</a>.</em></p>
<blockquote>
<h2>langchain-core==1.6.5</h2>
<p>Changes since langchain-core==1.6.4</p>
<p>release(core): 1.6.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40816">#40816</a>)
fix(core): abbreviate long tool IDs in XML buffer strings (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40792">#40792</a>)</p>
<h2>langchain-core==1.6.4</h2>
<p>Changes since langchain-core==1.6.3</p>
<p>release(core): 1.6.4 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40718">#40718</a>)
chore(core): deprecate chat message history (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40711">#40711</a>)
chore(deps): bump anyio from 4.12.0 to 4.14.2 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40634">#40634</a>)
chore(deps): bump soupsieve from 2.8.4 to 2.9 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40574">#40574</a>)</p>
<h2>langchain-core==1.6.3</h2>
<p>Changes since langchain-core==1.6.2</p>
<p>release(core): 1.6.3 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40407">#40407</a>)
feat(core): Allow model name and provider tracing metadata override
based on gateway response (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40406">#40406</a>)
test(core): cover the deprecated <code>.text()</code> access path (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40243">#40243</a>)
docs(core): remove stale Args/Raises entries from
FileCallbackHandler._write and ChatGeneration.set_text (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40211">#40211</a>)</p>
<h2>langchain-core==1.6.2</h2>
<p>Changes since langchain-core==1.6.1</p>
<p>release(core): 1.6.2 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40209">#40209</a>)
feat(openai): support async tools (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40208">#40208</a>)
chore(deps): bump mistune from 3.3.0 to 3.3.3 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40150">#40150</a>)
chore(deps): bump tornado from 6.5.7 to 6.5.8 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40113">#40113</a>)
fix(core): avoid mutation in google-genai standard content (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40023">#40023</a>)
fix(core): avoid mutation in bedrock converse standard content (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40022">#40022</a>)</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/c5ab14d42a3e22865c9def909de0b11d70b0bbf0"><code>c5ab14d</code></a>
release(core): 1.6.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40816">#40816</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/5704d9d4813f8c0527f04e2662cf313e1350f96f"><code>5704d9d</code></a>
chore(model-profiles): refresh model profile data (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40804">#40804</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/7622d3dce760ac4be6d9aef4c653277e06064aea"><code>7622d3d</code></a>
release(openai): 1.6.6 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40800">#40800</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/2dd956b8add667dac4f97605ae441d75b8ae228e"><code>2dd956b</code></a>
docs(infra): fix AGENTS.md root setup guidance and package doc accuracy
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40794">#40794</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/49f4b4016b82513c3dc1623bf3daa10453861621"><code>49f4b40</code></a>
fix(openai): raise on error events in stream path (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40791">#40791</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/19cadaa1a1e0cac71f3148e2f18b414dcab17426"><code>19cadaa</code></a>
fix(core): abbreviate long tool IDs in XML buffer strings (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40792">#40792</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/798441e8b07e88e79db355db452cd9492f9628f2"><code>798441e</code></a>
chore(anthropic): fix integration test cassette (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40790">#40790</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/a476942bac3fe5e521676d0f53fabafcb7ba71b1"><code>a476942</code></a>
release(openai): 1.6.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40787">#40787</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/46c6bdf1b4e23028a5acc060d8b2797dbf200291"><code>46c6bdf</code></a>
release(anthropic): 1.7.4 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40786">#40786</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/290dabaff27ee379920d55d155d5055d2fe29cc8"><code>290daba</code></a>
fix(anthropic): add Opus 5.5 and GPT-6 profile augmentations (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40785">#40785</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.6.1...langchain-core==1.6.5">compare
view</a></li>
</ul>
</details>
<br />

Updates `pytest-mock` from 3.15.1 to 3.16.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/releases">pytest-mock's
releases</a>.</em></p>
<blockquote>
<h2>v3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/604">#604</a>:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/611">#611</a>:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/606">#606</a>:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/547">#547</a>:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/147">#147</a>:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst">pytest-mock's
changelog</a>.</em></p>
<blockquote>
<h2>3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><code>[#604](https://github.com/pytest-dev/pytest-mock/issues/604)
&lt;https://github.com/pytest-dev/pytest-mock/pull/604&gt;</code>_:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><code>[#611](https://github.com/pytest-dev/pytest-mock/issues/611)
&lt;https://github.com/pytest-dev/pytest-mock/pull/611&gt;</code>_:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><code>[#606](https://github.com/pytest-dev/pytest-mock/issues/606)
&lt;https://github.com/pytest-dev/pytest-mock/pull/606&gt;</code>_:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><code>[#547](https://github.com/pytest-dev/pytest-mock/issues/547)
&lt;https://github.com/pytest-dev/pytest-mock/issues/547&gt;</code>_:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><code>[#147](https://github.com/pytest-dev/pytest-mock/issues/147)
&lt;https://github.com/pytest-dev/pytest-mock/issues/147&gt;</code>_:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/f3b531f93c6d9837edc87ea1a6f4324dc9a2cdf3"><code>f3b531f</code></a>
Release 3.16.0</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/71ed67309520be160f3e100368705b58758d237a"><code>71ed673</code></a>
Fix duplicate_iterators for async spies (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/604">#604</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/0797e3d303cc5bbe0a3514b0625f7aeb3fa350b0"><code>0797e3d</code></a>
Fix async assertion argument introspection (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/611">#611</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/e24c334d573cfbf6989a31f4e3346676d9d31598"><code>e24c334</code></a>
docs: import os in the opening usage example (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/612">#612</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/9e7eb7b59cde362c1c8ace2d18ca00fe2d7a1cd1"><code>9e7eb7b</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/613">#613</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/445fd4d3daa8ed4c6d5428a77880da2e03d2f721"><code>445fd4d</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/610">#610</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/a8bd0b147afdf6b4bb1a1a3c3c088f32b0240091"><code>a8bd0b1</code></a>
Honour resetall() arguments for non-callable mocks (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/606">#606</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/6559fdfd5b67f096423e604a3a5a7045db2486a0"><code>6559fdf</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/608">#608</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/466d026254c949a8fbba8626b894308827be81cf"><code>466d026</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/605">#605</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/164defebde25bc31d53a2a64943c5c9aac43b57e"><code>164defe</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/603">#603</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pytest-dev/pytest-mock/compare/v3.15.1...v3.16.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.16.5 to 0.16.9
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>Install ruff 0.16.9</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-installer.sh
| sh
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>0.16.8</h2>
<p>Released on 2026-09-16.</p>
<h3>Bug fixes</h3>
<ul>
<li>Visit functional <code>TypedDict</code> keyword arguments correctly
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28584">#28584</a>)</li>
<li>[<code>flake8-simplify</code>] Detect nested <code>async with</code>
under sync parent (<code>SIM117</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27821">#27821</a>)</li>
<li>[<code>flake8-simplify</code>] Preserve operand order in
<code>SIM109</code> fix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27824">#27824</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/0be08a206f9c3180afd3e93bcc792ed5cb1f4db1"><code>0be08a2</code></a>
Bump version to 0.16.9 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28882">#28882</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/b4920b72b354e7c715ab861ae23458874683bb02"><code>b4920b7</code></a>
Rename <code>ruff_cli</code> to <code>ruff_command_line</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28881">#28881</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/47c751b95908a4d1f95f9ef8723036aae9da0b18"><code>47c751b</code></a>
Update dependency astral-sh/uv to v0.12.18 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28880">#28880</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c244e56a1aeac31c26d2371ef26588e0632235c"><code>8c244e5</code></a>
[<code>flake8-comprehensions</code>] Document <code>map</code>/generator
exception behavior (<code>C417</code>...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/5edf5a1d0a84663079e46983216059f06acea87d"><code>5edf5a1</code></a>
Use <code>target</code> form in <code>rooster.version_files</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28876">#28876</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/915bb2b4bf9ae7eee47cf55646bbfebae254a23b"><code>915bb2b</code></a>
[ty] Prefer existing @ paths over response files in Ruff and ty (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28877">#28877</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4710e1aa962b13720cf64aa84eb279c5333896d7"><code>4710e1a</code></a>
ci(github): update version number in placeholder of issue template (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28871">#28871</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/eedfc62a75bf1ba86d48959b00eea75ae87eadca"><code>eedfc62</code></a>
[ty] Propagate outer type context through cast calls (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28855">#28855</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/ceaa6a00830e1e350b8a23977a1a10ac467920a1"><code>ceaa6a0</code></a>
[ty] Contain rendered code within Markdown fences (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28869">#28869</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/dba0f30615424b94f94a174bba6ce6cce4bf11ff"><code>dba0f30</code></a>
authorize ruff-pre-commit dispatch via OIDC (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28867">#28867</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.16.5...0.16.9">compare
view</a></li>
</ul>
</details>
<br />

Updates `ty` from 0.0.75 to 0.0.84
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/releases">ty's
releases</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/blob/main/CHANGELOG.md">ty's
changelog</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ty/commit/8dd9a7f7fa35a18275d82117e6593ba45507065f"><code>8dd9a7f</code></a>
Bump version to 0.0.84 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4585">#4585</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/d4e4bf90906c7677049bc3a29d1735de7d22052d"><code>d4e4bf9</code></a>
publish to astral-sh/versions via OIDC (<a
href="https://redirect.github.com/astral-sh/ty/issues/4581">#4581</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/94ce7333abb356b2068dc98d37a68c993da6d09b"><code>94ce733</code></a>
use oidc issued token for docs publication (<a
href="https://redirect.github.com/astral-sh/ty/issues/4579">#4579</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/901eeaa9cd9ac06f34e85e4f721f76a0dc36e217"><code>901eeaa</code></a>
Update prek dependencies (<a
href="https://redirect.github.com/astral-sh/ty/issues/4576">#4576</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/09bf0b1b2114a628f3e2296d3d9d28245066c98b"><code>09bf0b1</code></a>
Update docker/setup-buildx-action action to v4.3.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4575">#4575</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/89d6ffe529dd44f64adc0d28f80744b7c7ab217f"><code>89d6ffe</code></a>
Update astral-sh/setup-uv action to v10.2.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4574">#4574</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/9c214798cfcc59069e986876564638fadf32d774"><code>9c21479</code></a>
Bump version to 0.0.83 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4569">#4569</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/04c69110b391e96310e6892cbed9936c4f31d7aa"><code>04c6911</code></a>
Sync the ty security mirror (<a
href="https://redirect.github.com/astral-sh/ty/issues/4549">#4549</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/3fa57a25767c619dbeba697c2acfbb8eb291519a"><code>3fa57a2</code></a>
Grant the versions workflow repository read access (<a
href="https://redirect.github.com/astral-sh/ty/issues/4550">#4550</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/a15b35389b44db57f718fd4e19e093481747c53e"><code>a15b353</code></a>
use scoped token for release workflow (<a
href="https://redirect.github.com/astral-sh/ty/issues/4506">#4506</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ty/compare/0.0.75...0.0.84">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-01 01:52:01 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3474bbff29 chore(deps): bump the minor-and-patch group in /libs/cli/js-monorepo-example with 8 updates (#9151)
Bumps the minor-and-patch group in /libs/cli/js-monorepo-example with 8
updates:

| Package | From | To |
| --- | --- | --- |
| [turbo](https://github.com/vercel/turborepo) | `2.10.12` | `2.11.5` |
| [@eslint/eslintrc](https://github.com/eslint/eslintrc) | `3.3.6` |
`3.3.7` |
| [eslint](https://github.com/eslint/eslint) | `10.9.1` | `10.11.0` |
|
[@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin)
| `8.68.0` | `8.70.1` |
|
[@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser)
| `8.68.0` | `8.70.1` |
| [prettier](https://github.com/prettier/prettier) | `3.9.6` | `3.9.9` |
| [@langchain/core](https://github.com/langchain-ai/langchainjs) |
`1.2.9` | `1.2.13` |
|
[@langchain/langgraph](https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core)
| `1.4.13` | `1.4.18` |

Updates `turbo` from 2.10.12 to 2.11.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vercel/turborepo/releases">turbo's
releases</a>.</em></p>
<blockquote>
<h2>Turborepo v2.11.5</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Changelog</h3>
<ul>
<li>chore: Release Turborepo 2.11.4 by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/vercel/turborepo/pull/14231">vercel/turborepo#14231</a></li>
<li>test: Move Python opt-in hint into filter contracts by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14228">vercel/turborepo#14228</a></li>
<li>test: Move dependency-output summary assertion into contract by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14230">vercel/turborepo#14230</a></li>
<li>test: Move dependency-output selection and validation cases to
engine contracts by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14232">vercel/turborepo#14232</a></li>
<li>test: Move Cargo exclude-only scope coverage by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14238">vercel/turborepo#14238</a></li>
<li>test: Move Cargo cache-authority cases to contracts by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14240">vercel/turborepo#14240</a></li>
<li>test: Move JIT dependency graph scenario into engine contract by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14235">vercel/turborepo#14235</a></li>
<li>test: Move dependency-output hash cases into task-hash contracts by
<a href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a>
in <a
href="https://redirect.github.com/vercel/turborepo/pull/14233">vercel/turborepo#14233</a></li>
<li>test: Move Cargo task-filter cases into crate contracts by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14239">vercel/turborepo#14239</a></li>
<li>test: Move JIT input hash timing cases into task-hash contracts by
<a href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a>
in <a
href="https://redirect.github.com/vercel/turborepo/pull/14234">vercel/turborepo#14234</a></li>
<li>test: Move package input normalization cases into engine contracts
by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14236">vercel/turborepo#14236</a></li>
<li>test: Move structured startup and JIT input cases into contracts by
<a href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a>
in <a
href="https://redirect.github.com/vercel/turborepo/pull/14237">vercel/turborepo#14237</a></li>
<li>fix: Back off remote artifact requests during outages by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14222">vercel/turborepo#14222</a></li>
<li>chore: Release Turborepo 2.11.5-canary.1 by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/vercel/turborepo/pull/14245">vercel/turborepo#14245</a></li>
<li>test: Make new-package lockfile filter deterministic by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14241">vercel/turborepo#14241</a></li>
<li>test: Trim redundant Go cache builds by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14242">vercel/turborepo#14242</a></li>
<li>test: Reduce Go versioned-name test matrix by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14243">vercel/turborepo#14243</a></li>
<li>test: Move Go binary checks into contracts by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14246">vercel/turborepo#14246</a></li>
<li>test: Consolidate Go format smokes by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14244">vercel/turborepo#14244</a></li>
<li>test: Reuse Cargo build artifacts safely by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14247">vercel/turborepo#14247</a></li>
<li>test: Separate prune planning matrix from buildability smoke by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14248">vercel/turborepo#14248</a></li>
<li>feat: Bundle docs in <code>turbo</code> npm package by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14108">vercel/turborepo#14108</a></li>
<li>chore: Release Turborepo 2.11.5-canary.2 by <a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/vercel/turborepo/pull/14249">vercel/turborepo#14249</a></li>
<li>fix: Stabilize pnpm per-workspace lockfile hashes by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14253">vercel/turborepo#14253</a></li>
<li>chore: Upgrade factory Next.js to 16.3.3 by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14254">vercel/turborepo#14254</a></li>
<li>fix: Update js-yaml to address CVE-2026-84375 by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14255">vercel/turborepo#14255</a></li>
<li>chore: Upgrade Next.js in docs and factory for CVE-2026-94545 by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14256">vercel/turborepo#14256</a></li>
<li>fix: Remove unmaintained proc-macro-error2 by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14257">vercel/turborepo#14257</a></li>
<li>refactor: Replace clap in production CLIs with usage-rs by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14259">vercel/turborepo#14259</a></li>
<li>chore: Remove tiny-gradient dependency by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14260">vercel/turborepo#14260</a></li>
<li>refactor: Replace human-panic with local crash reporting by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14261">vercel/turborepo#14261</a></li>
<li>chore: Remove unused struct_iterable dependency by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14258">vercel/turborepo#14258</a></li>
<li>fix: Sign complete on-disk artifacts after local cache writes by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14265">vercel/turborepo#14265</a></li>
<li>chore: Remove <code>derive_setters</code> dependency by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14266">vercel/turborepo#14266</a></li>
<li>chore: Remove port_scanner dependency by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14267">vercel/turborepo#14267</a></li>
<li>chore: Remove unused Rust dependency declarations by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14268">vercel/turborepo#14268</a></li>
<li>refactor: Remove unused public Rust APIs by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14269">vercel/turborepo#14269</a></li>
<li>refactor: Use workspace Rust edition across crates by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14270">vercel/turborepo#14270</a></li>
<li>chore: Clean up Rust Clippy exceptions by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14271">vercel/turborepo#14271</a></li>
<li>refactor: Group task-hash and uv generation context by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14279">vercel/turborepo#14279</a></li>
<li>refactor: Remove unused global hash wrapper by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14281">vercel/turborepo#14281</a></li>
<li>refactor: Remove unused file-hash telemetry argument by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14282">vercel/turborepo#14282</a></li>
<li>refactor: Remove dead CLI code and crate-wide allowance by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14283">vercel/turborepo#14283</a></li>
<li>refactor: Remove dead Microfrontends config code by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14284">vercel/turborepo#14284</a></li>
<li>refactor: Remove unused UI task types and dead-code allowance by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/14286">vercel/turborepo#14286</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vercel/turborepo/commit/8492b42667210270f4169f0df8c0edf725ff2f41"><code>8492b42</code></a>
publish 2.11.5 to registry</li>
<li><a
href="https://github.com/vercel/turborepo/commit/a50ee6536eac2f7f3168cc38087ee7d8397fc0e9"><code>a50ee65</code></a>
chore: Release Turborepo 2.11.5-canary.5 (<a
href="https://redirect.github.com/vercel/turborepo/issues/14328">#14328</a>)</li>
<li><a
href="https://github.com/vercel/turborepo/commit/c9602f339008964f8dfaf6329491c374cf2f0a60"><code>c9602f3</code></a>
fix: Pass repository to release asset commands (<a
href="https://redirect.github.com/vercel/turborepo/issues/14327">#14327</a>)</li>
<li><a
href="https://github.com/vercel/turborepo/commit/8cb67669e73cf73bde0a8a9e0a9a829ddd34993f"><code>8cb6766</code></a>
fix: Isolate installer test environment (<a
href="https://redirect.github.com/vercel/turborepo/issues/14326">#14326</a>)</li>
<li><a
href="https://github.com/vercel/turborepo/commit/5108f6c9fda7a7aeb2d2f31c46a44bbe966970c7"><code>5108f6c</code></a>
feat: Add standalone installers URLs for <code>curl | bash</code> (<a
href="https://redirect.github.com/vercel/turborepo/issues/14325">#14325</a>)</li>
<li><a
href="https://github.com/vercel/turborepo/commit/a46f82a2742ef0f8e1b5f9acebfbe2544c34c528"><code>a46f82a</code></a>
chore: Release Turborepo 2.11.5-canary.4 (<a
href="https://redirect.github.com/vercel/turborepo/issues/14324">#14324</a>)</li>
<li><a
href="https://github.com/vercel/turborepo/commit/8427e6e5dd7efc7afdf5a332502551fc8f2eabc8"><code>8427e6e</code></a>
fix: Run standalone archive job on manual releases (<a
href="https://redirect.github.com/vercel/turborepo/issues/14323">#14323</a>)</li>
<li><a
href="https://github.com/vercel/turborepo/commit/7f57aa38406027a30a77d46489ebbdf9dd3ef0e5"><code>7f57aa3</code></a>
feat: Publish versioned standalone turbo archives (<a
href="https://redirect.github.com/vercel/turborepo/issues/14322">#14322</a>)</li>
<li><a
href="https://github.com/vercel/turborepo/commit/d6b852c53c8473ec88081e826b357feb35938e5e"><code>d6b852c</code></a>
docs: Update Turborepo schema URL example (<a
href="https://redirect.github.com/vercel/turborepo/issues/14321">#14321</a>)</li>
<li><a
href="https://github.com/vercel/turborepo/commit/c76ac66c4447bfe35301bee0a002d3c60e163342"><code>c76ac66</code></a>
chore: Release Turborepo 2.11.5-canary.3 (<a
href="https://redirect.github.com/vercel/turborepo/issues/14320">#14320</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/vercel/turborepo/compare/v2.10.12...v2.11.5">compare
view</a></li>
</ul>
</details>
<br />

Updates `@eslint/eslintrc` from 3.3.6 to 3.3.7
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslintrc/releases">@​eslint/eslintrc's
releases</a>.</em></p>
<blockquote>
<h2>eslintrc: v3.3.7</h2>
<h2><a
href="https://github.com/eslint/eslintrc/compare/eslintrc-v3.3.6...eslintrc-v3.3.7">3.3.7</a>
(2026-09-01)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Bump js-yaml to 4.3.1 (<a
href="https://redirect.github.com/eslint/eslintrc/issues/239">#239</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/f27e7c94e6d9438bd51cb483d8d5da768e1cc0b9">f27e7c9</a>)</li>
<li>update js-yaml to 4.3.2 to address security vulnerability (<a
href="https://redirect.github.com/eslint/eslintrc/issues/243">#243</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/bb0d97a338937b88fa99d6bbc0a904e34eda3d5f">bb0d97a</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslintrc/blob/main/CHANGELOG.md">@​eslint/eslintrc's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/eslint/eslintrc/compare/eslintrc-v3.3.6...eslintrc-v3.3.7">3.3.7</a>
(2026-09-01)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Bump js-yaml to 4.3.1 (<a
href="https://redirect.github.com/eslint/eslintrc/issues/239">#239</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/f27e7c94e6d9438bd51cb483d8d5da768e1cc0b9">f27e7c9</a>)</li>
<li>update js-yaml to 4.3.2 to address security vulnerability (<a
href="https://redirect.github.com/eslint/eslintrc/issues/243">#243</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/bb0d97a338937b88fa99d6bbc0a904e34eda3d5f">bb0d97a</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/eslint/eslintrc/commit/7943fa6dd55b236a539f658b88c763a4f9fbb38d"><code>7943fa6</code></a>
chore: release 3.3.7 🚀 (<a
href="https://redirect.github.com/eslint/eslintrc/issues/240">#240</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/bb0d97a338937b88fa99d6bbc0a904e34eda3d5f"><code>bb0d97a</code></a>
fix: update js-yaml to 4.3.2 to address security vulnerability (<a
href="https://redirect.github.com/eslint/eslintrc/issues/243">#243</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/5b4abc9c74dd92b9eb782ca81d559a88906509e9"><code>5b4abc9</code></a>
docs: Update README sponsors</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/f27e7c94e6d9438bd51cb483d8d5da768e1cc0b9"><code>f27e7c9</code></a>
fix: Bump js-yaml to 4.3.1 (<a
href="https://redirect.github.com/eslint/eslintrc/issues/239">#239</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/b75e1d2425deebfd1ec7f952dda7d0c4f4d65d5c"><code>b75e1d2</code></a>
docs: Update README sponsors</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/302c13310e148268f990df3edbfd10dab44f2678"><code>302c133</code></a>
docs: Update README sponsors</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/e62e7661b0d9063e42a37af5551bbcb1897e188d"><code>e62e766</code></a>
docs: Update README sponsors</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/cf27f9fd8f775d94500f2569a5bfb6a7de9cdb33"><code>cf27f9f</code></a>
docs: Update README sponsors</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/c7f4cdf1ffa86e28b5b8bf09f9e8bc7fadbf87ff"><code>c7f4cdf</code></a>
docs: Update README sponsors</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/3319822ac925e018c47fcafa351b20ea0bf6eeff"><code>3319822</code></a>
docs: Update README sponsors</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/eslintrc/compare/eslintrc-v3.3.6...eslintrc-v3.3.7">compare
view</a></li>
</ul>
</details>
<br />

Updates `eslint` from 10.9.1 to 10.11.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslint/releases">eslint's
releases</a>.</em></p>
<blockquote>
<h2>v10.11.0</h2>
<h2>Features</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/d136fa4b0d2dd4a9e738ca1c012cc674d1441127"><code>d136fa4</code></a>
feat: object-shorthand handle quoted properties for
<code>ignoreConstructors</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21271">#21271</a>)
(Pavel)</li>
<li><a
href="https://github.com/eslint/eslint/commit/397b3b8134b8ce1a61cbf414d4c29c945ba25690"><code>397b3b8</code></a>
feat: report unsafe labeled <code>continue</code> in
<code>no-unsafe-finally</code> rule (<a
href="https://redirect.github.com/eslint/eslint/issues/21316">#21316</a>)
(electrohyun)</li>
<li><a
href="https://github.com/eslint/eslint/commit/d3dd47f42e4cb5f9da27e3a2e741aa21e02ea1a4"><code>d3dd47f</code></a>
feat: only exempt <code>new-cap</code> built-ins that reference the
global (<a
href="https://redirect.github.com/eslint/eslint/issues/21290">#21290</a>)
(sethamus)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/22b09f54f67a9512d4cea39ddbab9b6973d5c476"><code>22b09f5</code></a>
fix: ignore <code>__proto__</code> properties in
<code>prefer-object-spread</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21311">#21311</a>)
(xbinaryx)</li>
<li><a
href="https://github.com/eslint/eslint/commit/b684bb1cd7e6be03ad1b7a951baead936d9c2166"><code>b684bb1</code></a>
fix: make TimePass.parse optional in types and docs (<a
href="https://redirect.github.com/eslint/eslint/issues/21313">#21313</a>)
(ntnyq)</li>
<li><a
href="https://github.com/eslint/eslint/commit/26d11bce3e0e21f223613d4bb4be3423839b229e"><code>26d11bc</code></a>
fix: don't report <code>__proto__</code> properties in
<code>object-shorthand</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21310">#21310</a>)
(xbinaryx)</li>
</ul>
<h2>Documentation</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/9ecfdc5319f83580cf3b81beab7e936015fef2fa"><code>9ecfdc5</code></a>
docs: note that --cache can serve stale results for cross-file rules (<a
href="https://redirect.github.com/eslint/eslint/issues/21312">#21312</a>)
(bytedoe)</li>
<li><a
href="https://github.com/eslint/eslint/commit/6c789ff39bc5420e94e8dafeb328bf2b7e3d35ab"><code>6c789ff</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="https://github.com/eslint/eslint/commit/5997825635dc9c4e81434894607ef2e3887e0ea3"><code>5997825</code></a>
docs: clarify preserve-caught-error known limitation (<a
href="https://redirect.github.com/eslint/eslint/issues/21294">#21294</a>)
(Akinyemi Toluwalase)</li>
</ul>
<h2>Chores</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/520dd77a35922fb537e2dbfb3c839d047acbdd68"><code>520dd77</code></a>
perf: Implement fast paths in critical areas (<a
href="https://redirect.github.com/eslint/eslint/issues/21210">#21210</a>)
(Nicholas C. Zakas)</li>
<li><a
href="https://github.com/eslint/eslint/commit/92086c87e042413a3d0363d8fc3fbb11db98d06a"><code>92086c8</code></a>
test: update <code>EMFILE</code> error generation for Node.js 26.9.0
compatibility (<a
href="https://redirect.github.com/eslint/eslint/issues/21330">#21330</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/9ac7eb60525ec768c2fdc6699e5a292aa913ce9e"><code>9ac7eb6</code></a>
chore: update github/codeql-action action to v4.38.0 (<a
href="https://redirect.github.com/eslint/eslint/issues/21331">#21331</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/24310e3a0e22b3c086ca402f88448676f2e1cfcd"><code>24310e3</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/21324">#21324</a>)
(ESLint Bot)</li>
<li><a
href="https://github.com/eslint/eslint/commit/45ad79e54a39b54b4ce8eb47e612bd2f72a7a651"><code>45ad79e</code></a>
ci: bump pnpm/action-setup from 6.0.10 to 6.1.0 (<a
href="https://redirect.github.com/eslint/eslint/issues/21318">#21318</a>)
(dependabot[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/ac74e37322ebf122ada676f153dc55c81f3caab0"><code>ac74e37</code></a>
chore: Add AGENTS.md with AI disclosure requirements (<a
href="https://redirect.github.com/eslint/eslint/issues/21221">#21221</a>)
(Nicholas C. Zakas)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c8326608e710e670beaf982501aed80ea104919a"><code>c832660</code></a>
chore: Upgrade Stylelint to the latest version in docs (<a
href="https://redirect.github.com/eslint/eslint/issues/21245">#21245</a>)
(Jung Hyeon Jun)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f9f88fcccd965fdc162b89c4615dd4018e3cabdf"><code>f9f88fc</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/21308">#21308</a>)
(ESLint Bot)</li>
<li><a
href="https://github.com/eslint/eslint/commit/fc81076a5b8145360654d81cbc130cf7d25dca77"><code>fc81076</code></a>
ci: add more types integration tests (<a
href="https://redirect.github.com/eslint/eslint/issues/20395">#20395</a>)
(Nitin Kumar)</li>
</ul>
<h2>v10.10.0</h2>
<h2>Features</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/264b4346d1963701df0c398b4aeb2f6e8b2af93e"><code>264b434</code></a>
feat: add <code>d</code> and <code>v</code> flags to
<code>no-unexpected-multiline</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21305">#21305</a>)
(Gihyeon Jeong / 정기현)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c6cc6c592f30901345d94ef75e0d42c1894fae6c"><code>c6cc6c5</code></a>
feat: check <code>Object.prototype</code> property names in
<code>new-cap</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21269">#21269</a>)
(crimsonjay0)</li>
<li><a
href="https://github.com/eslint/eslint/commit/5661fa65fde9fd4c14f0b730e3cee6a42fc657c1"><code>5661fa6</code></a>
feat: no-extra-bind false negatives with class fields and static blocks
(<a
href="https://redirect.github.com/eslint/eslint/issues/21260">#21260</a>)
(synthex-byte)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/bb47dc6da2399a8f76c0c0c3273e6bc314c480e5"><code>bb47dc6</code></a>
fix: update dependency file-entry-cache to v11 (<a
href="https://redirect.github.com/eslint/eslint/issues/20801">#20801</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/427ac0a014066c36aa57fa8fa9af20fd9fb591e1"><code>427ac0a</code></a>
fix: use format strings in debug calls (<a
href="https://redirect.github.com/eslint/eslint/issues/21247">#21247</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/9d8153223dbf47b9aecdc1474202aaee4845f146"><code>9d81532</code></a>
fix: support <code>__proto__</code> in <code>/* exported */</code>
comments (<a
href="https://redirect.github.com/eslint/eslint/issues/21261">#21261</a>)
(sethamus)</li>
<li><a
href="https://github.com/eslint/eslint/commit/87e0a082438264ad90b87fd74165ab4fd90f63ef"><code>87e0a08</code></a>
fix: prefer-object-has-own autofix breaks when Object is shadowed (<a
href="https://redirect.github.com/eslint/eslint/issues/21282">#21282</a>)
(김채영)</li>
<li><a
href="https://github.com/eslint/eslint/commit/8e2cb142217f2efee1d10dcc02bfb75145ae775d"><code>8e2cb14</code></a>
fix: <code>new-cap</code> false positive for <code>UTC</code> calls with
<code>properties: false</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21275">#21275</a>)
(Pixel)</li>
<li><a
href="https://github.com/eslint/eslint/commit/9f4a364ab0ade048dfce1f37792b1d461d866e55"><code>9f4a364</code></a>
fix: Ignore static imports in no-unreachable (<a
href="https://redirect.github.com/eslint/eslint/issues/21276">#21276</a>)
(Taha Kotil)</li>
</ul>
<h2>Documentation</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/2417cad57d7d1bc4cf3ecf0f0575cfb10ff2011c"><code>2417cad</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="https://github.com/eslint/eslint/commit/9cecb8a0a2348070abf72321965d41919c7cc626"><code>9cecb8a</code></a>
docs: document <code>\c</code> control letter escapes in
no-control-regex (<a
href="https://redirect.github.com/eslint/eslint/issues/21286">#21286</a>)
(한국)</li>
<li><a
href="https://github.com/eslint/eslint/commit/8724829f69f8ed80c876e3a5a017da199ce78739"><code>8724829</code></a>
docs: update compat table links (<a
href="https://redirect.github.com/eslint/eslint/issues/21263">#21263</a>)
(fnx)</li>
<li><a
href="https://github.com/eslint/eslint/commit/5634542be580750ffb1a5766470f9e9c72719696"><code>5634542</code></a>
docs: Clarify eqeqeq suggestion behavior (<a
href="https://redirect.github.com/eslint/eslint/issues/21256">#21256</a>)
(Müslüm Yılmaz)</li>
</ul>
<h2>Chores</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/b3d876b46083d67899eb1d9613118c1c583632a2"><code>b3d876b</code></a>
chore: disable npm audit in ecosystem tests (<a
href="https://redirect.github.com/eslint/eslint/issues/21306">#21306</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/1696682791661c13167eb905da2f38d1b8f4a3bf"><code>1696682</code></a>
ci: restore EMFILE test on Node.js 26 (<a
href="https://redirect.github.com/eslint/eslint/issues/21297">#21297</a>)
(Marry (Subin Yang))</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/3c0b7c6e1fe2dec778b97a996018126f22d437ae"><code>3c0b7c6</code></a>
10.11.0</li>
<li><a
href="https://github.com/eslint/eslint/commit/321f0a70dd908ed461b11142e17fbdc0c0f1f198"><code>321f0a7</code></a>
Build: changelog update for 10.11.0</li>
<li><a
href="https://github.com/eslint/eslint/commit/520dd77a35922fb537e2dbfb3c839d047acbdd68"><code>520dd77</code></a>
perf: Implement fast paths in critical areas (<a
href="https://redirect.github.com/eslint/eslint/issues/21210">#21210</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/9ecfdc5319f83580cf3b81beab7e936015fef2fa"><code>9ecfdc5</code></a>
docs: note that --cache can serve stale results for cross-file rules (<a
href="https://redirect.github.com/eslint/eslint/issues/21312">#21312</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/92086c87e042413a3d0363d8fc3fbb11db98d06a"><code>92086c8</code></a>
test: update <code>EMFILE</code> error generation for Node.js 26.9.0
compatibility (<a
href="https://redirect.github.com/eslint/eslint/issues/21330">#21330</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/9ac7eb60525ec768c2fdc6699e5a292aa913ce9e"><code>9ac7eb6</code></a>
chore: update github/codeql-action action to v4.38.0 (<a
href="https://redirect.github.com/eslint/eslint/issues/21331">#21331</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/22b09f54f67a9512d4cea39ddbab9b6973d5c476"><code>22b09f5</code></a>
fix: ignore <code>__proto__</code> properties in
<code>prefer-object-spread</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21311">#21311</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/24310e3a0e22b3c086ca402f88448676f2e1cfcd"><code>24310e3</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/21324">#21324</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/d136fa4b0d2dd4a9e738ca1c012cc674d1441127"><code>d136fa4</code></a>
feat: object-shorthand handle quoted properties for
<code>ignoreConstructors</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21">#21</a>...</li>
<li><a
href="https://github.com/eslint/eslint/commit/45ad79e54a39b54b4ce8eb47e612bd2f72a7a651"><code>45ad79e</code></a>
ci: bump pnpm/action-setup from 6.0.10 to 6.1.0 (<a
href="https://redirect.github.com/eslint/eslint/issues/21318">#21318</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/eslint/compare/v10.9.1...v10.11.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `@typescript-eslint/eslint-plugin` from 8.68.0 to 8.70.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/releases">@​typescript-eslint/eslint-plugin's
releases</a>.</em></p>
<blockquote>
<h2>v8.70.1</h2>
<h2>8.70.1 (2026-09-21)</h2>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>ast-spec:</strong> narrow import attribute keys to
identifiers and strings (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12879">#12879</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
avoid false positives on tuples with a rest element (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12768">#12768</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-type-parameters]
handle type precedence in the suggestion fixer (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12637">#12637</a>)</li>
<li><strong>eslint-plugin:</strong> [no-explicit-any] use unknown[] for
bare any rest parameters (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12818">#12818</a>)</li>
<li><strong>eslint-plugin:</strong> [no-generated-empty-object-type]
don't report a mapped type whose keys are not resolved yet (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12854">#12854</a>)</li>
<li><strong>eslint-plugin:</strong> [no-misused-spread] omit WeakMap
spread suggestions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12850">#12850</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-type-assertion]
false positive for empty object asserted to a type alias of Record (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12869">#12869</a>)</li>
<li><strong>eslint-plugin:</strong> [no-meaningless-void-operator] allow
void on assignment expressions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12873">#12873</a>)</li>
<li><strong>eslint-plugin:</strong> [await-thenable] prevent autofix
from breaking code when removing <code>await</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12716">#12716</a>)</li>
<li><strong>eslint-plugin:</strong>
[no-unnecessary-parameter-property-assignment] account for parameter
reassignment (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12880">#12880</a>)</li>
<li><strong>eslint-plugin:</strong> [unbound-method] treat
Intl.Collator.prototype.compare as spec-bound (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12845">#12845</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-condition] handle
union-keyed index access on the left-hand side of nullish assignment (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12747">#12747</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
convert the fixer to a suggestion fixer (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12826">#12826</a>)</li>
<li><strong>eslint-plugin:</strong> [no-misused-promises] handle
multiple Promise constituents (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12904">#12904</a>)</li>
<li><strong>rule-tester:</strong> test the final autofix output instead
of the first pass (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12867">#12867</a>)</li>
<li><strong>scope-manager:</strong> merge implicit global definitions
(<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12809">#12809</a>)</li>
<li><strong>type-utils:</strong> match package specifiers on whole path
components (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12838">#12838</a>)</li>
<li><strong>typescript-estree:</strong> resolve symlinked paths when
matching files to projects (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12725">#12725</a>)</li>
<li><strong>typescript-estree:</strong> add missing <code>&lt;</code>
token opening type arguments (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12821">#12821</a>)</li>
<li><strong>typescript-estree:</strong> require string literal import
attribute values (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12894">#12894</a>)</li>
<li><strong>website:</strong> prevent playground from breaking down
after opening link with the .js file type (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12777">#12777</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Amin <a
href="https://github.com/amiin-dev"><code>@​amiin-dev</code></a></li>
<li>Brad Zacher <a
href="https://github.com/bradzacher"><code>@​bradzacher</code></a></li>
<li>Cameron</li>
<li>Diptajoy Mistry <a
href="https://github.com/diptomistry"><code>@​diptomistry</code></a></li>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>Grit <a
href="https://github.com/Grit03"><code>@​Grit03</code></a></li>
<li>Hugo <a
href="https://github.com/hugop95"><code>@​hugop95</code></a></li>
<li>Josh Goldberg ✨</li>
<li>Michael Naumov <a
href="https://github.com/mnaoumov"><code>@​mnaoumov</code></a></li>
<li>Mikhail Baev <a
href="https://github.com/baevm"><code>@​baevm</code></a></li>
<li>Om Rawat</li>
<li>overlookmotel</li>
<li>Sanath <a
href="https://github.com/sansynx"><code>@​sansynx</code></a></li>
<li>Shinji</li>
<li>stoicism <a
href="https://github.com/stoicism02"><code>@​stoicism02</code></a></li>
<li>Vinccool96</li>
<li>Younsang Na <a
href="https://github.com/nayounsang"><code>@​nayounsang</code></a></li>
<li>김채영 <a
href="https://github.com/cchaeyoung"><code>@​cchaeyoung</code></a></li>
<li>송재욱</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.70.1">GitHub
Releases</a> for more information.</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md">@​typescript-eslint/eslint-plugin's
changelog</a>.</em></p>
<blockquote>
<h2>8.70.1 (2026-09-21)</h2>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-misused-promises] handle
multiple Promise constituents (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12904">#12904</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
convert the fixer to a suggestion fixer (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12826">#12826</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-condition] handle
union-keyed index access on the left-hand side of nullish assignment (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12747">#12747</a>)</li>
<li><strong>eslint-plugin:</strong> [unbound-method] treat
Intl.Collator.prototype.compare as spec-bound (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12845">#12845</a>)</li>
<li><strong>eslint-plugin:</strong>
[no-unnecessary-parameter-property-assignment] account for parameter
reassignment (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12880">#12880</a>)</li>
<li><strong>eslint-plugin:</strong> [await-thenable] prevent autofix
from breaking code when removing <code>await</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12716">#12716</a>)</li>
<li><strong>eslint-plugin:</strong> [no-meaningless-void-operator] allow
void on assignment expressions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12873">#12873</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-type-assertion]
false positive for empty object asserted to a type alias of Record (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12869">#12869</a>)</li>
<li><strong>eslint-plugin:</strong> [no-misused-spread] omit WeakMap
spread suggestions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12850">#12850</a>)</li>
<li><strong>eslint-plugin:</strong> [no-generated-empty-object-type]
don't report a mapped type whose keys are not resolved yet (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12854">#12854</a>)</li>
<li><strong>eslint-plugin:</strong> [no-explicit-any] use unknown[] for
bare any rest parameters (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12818">#12818</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-type-parameters]
handle type precedence in the suggestion fixer (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12637">#12637</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
avoid false positives on tuples with a rest element (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12768">#12768</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Brad Zacher <a
href="https://github.com/bradzacher"><code>@​bradzacher</code></a></li>
<li>Diptajoy Mistry <a
href="https://github.com/diptomistry"><code>@​diptomistry</code></a></li>
<li>Grit <a
href="https://github.com/Grit03"><code>@​Grit03</code></a></li>
<li>Hugo <a
href="https://github.com/hugop95"><code>@​hugop95</code></a></li>
<li>Michael Naumov <a
href="https://github.com/mnaoumov"><code>@​mnaoumov</code></a></li>
<li>Mikhail Baev <a
href="https://github.com/baevm"><code>@​baevm</code></a></li>
<li>Om Rawat</li>
<li>Sanath <a
href="https://github.com/sansynx"><code>@​sansynx</code></a></li>
<li>Shinji</li>
<li>Vinccool96</li>
<li>김채영 <a
href="https://github.com/cchaeyoung"><code>@​cchaeyoung</code></a></li>
<li>송재욱</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.70.1">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.70.0 (2026-09-07)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-generated-empty-object-type] add
rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12730">#12730</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-deprecated] report deprecated
imported values used in object shorthand properties (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12780">#12780</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-condition] no false
positive on RHS of a nested logical expression (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12728">#12728</a>)</li>
<li><strong>eslint-plugin:</strong> [member-ordering] don't report
fields that read fields declared before them (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12729">#12729</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/23d38ceeb8fb1237f55cb62fc2b54419e1fa1ed7"><code>23d38ce</code></a>
chore(release): publish 8.70.1</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/9d82e4b1d9011da31d62d14387bb5a539853fafa"><code>9d82e4b</code></a>
chore: expand eslint-plugin rules test files glob (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin/issues/12878">#12878</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/f7482f636b89b8eab966b4191ce4a53a3f4b4d9c"><code>f7482f6</code></a>
fix(eslint-plugin): [no-misused-promises] handle multiple Promise
constituent...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/267304477e04538614fe72ad71e7e13082eb7a90"><code>2673044</code></a>
docs(eslint-plugin): [prefer-promise-reject-errors] add option sections
and e...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/8f141a2ba63d539465eb4e4604f7d79f6f50ce14"><code>8f141a2</code></a>
fix(eslint-plugin): [no-useless-default-assignment] convert the fixer to
a su...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/479cd85ff82b81dbec9989621681257ebc317a69"><code>479cd85</code></a>
chore: enable assertion option <code>requireData</code> for all rule
tests (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin/issues/12816">#12816</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/f3c190c5b5cfa9edaba15fa3f944a76a7364b3ed"><code>f3c190c</code></a>
fix(eslint-plugin): [no-unnecessary-condition] handle union-keyed index
acces...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/b1993dfd3c45b2c2d83058627499f1dfec5d6d2c"><code>b1993df</code></a>
fix(eslint-plugin): [unbound-method] treat
Intl.Collator.prototype.compare as...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/da394bc9c21afe97f456040da723d2c558f99658"><code>da394bc</code></a>
fix(eslint-plugin): [no-unnecessary-parameter-property-assignment]
account fo...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/4a742ff890b7cca8cbf79e78a9a3b345913094c6"><code>4a742ff</code></a>
fix(eslint-plugin): [await-thenable] prevent autofix from breaking code
when ...</li>
<li>Additional commits viewable in <a
href="https://github.com/typescript-eslint/typescript-eslint/commits/v8.70.1/packages/eslint-plugin">compare
view</a></li>
</ul>
</details>
<br />

Updates `@typescript-eslint/parser` from 8.68.0 to 8.70.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/releases">@​typescript-eslint/parser's
releases</a>.</em></p>
<blockquote>
<h2>v8.70.1</h2>
<h2>8.70.1 (2026-09-21)</h2>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>ast-spec:</strong> narrow import attribute keys to
identifiers and strings (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12879">#12879</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
avoid false positives on tuples with a rest element (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12768">#12768</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-type-parameters]
handle type precedence in the suggestion fixer (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12637">#12637</a>)</li>
<li><strong>eslint-plugin:</strong> [no-explicit-any] use unknown[] for
bare any rest parameters (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12818">#12818</a>)</li>
<li><strong>eslint-plugin:</strong> [no-generated-empty-object-type]
don't report a mapped type whose keys are not resolved yet (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12854">#12854</a>)</li>
<li><strong>eslint-plugin:</strong> [no-misused-spread] omit WeakMap
spread suggestions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12850">#12850</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-type-assertion]
false positive for empty object asserted to a type alias of Record (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12869">#12869</a>)</li>
<li><strong>eslint-plugin:</strong> [no-meaningless-void-operator] allow
void on assignment expressions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12873">#12873</a>)</li>
<li><strong>eslint-plugin:</strong> [await-thenable] prevent autofix
from breaking code when removing <code>await</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12716">#12716</a>)</li>
<li><strong>eslint-plugin:</strong>
[no-unnecessary-parameter-property-assignment] account for parameter
reassignment (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12880">#12880</a>)</li>
<li><strong>eslint-plugin:</strong> [unbound-method] treat
Intl.Collator.prototype.compare as spec-bound (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12845">#12845</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-condition] handle
union-keyed index access on the left-hand side of nullish assignment (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12747">#12747</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
convert the fixer to a suggestion fixer (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12826">#12826</a>)</li>
<li><strong>eslint-plugin:</strong> [no-misused-promises] handle
multiple Promise constituents (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12904">#12904</a>)</li>
<li><strong>rule-tester:</strong> test the final autofix output instead
of the first pass (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12867">#12867</a>)</li>
<li><strong>scope-manager:</strong> merge implicit global definitions
(<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12809">#12809</a>)</li>
<li><strong>type-utils:</strong> match package specifiers on whole path
components (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12838">#12838</a>)</li>
<li><strong>typescript-estree:</strong> resolve symlinked paths when
matching files to projects (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12725">#12725</a>)</li>
<li><strong>typescript-estree:</strong> add missing <code>&lt;</code>
token opening type arguments (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12821">#12821</a>)</li>
<li><strong>typescript-estree:</strong> require string literal import
attribute values (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12894">#12894</a>)</li>
<li><strong>website:</strong> prevent playground from breaking down
after opening link with the .js file type (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12777">#12777</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Amin <a
href="https://github.com/amiin-dev"><code>@​amiin-dev</code></a></li>
<li>Brad Zacher <a
href="https://github.com/bradzacher"><code>@​bradzacher</code></a></li>
<li>Cameron</li>
<li>Diptajoy Mistry <a
href="https://github.com/diptomistry"><code>@​diptomistry</code></a></li>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>Grit <a
href="https://github.com/Grit03"><code>@​Grit03</code></a></li>
<li>Hugo <a
href="https://github.com/hugop95"><code>@​hugop95</code></a></li>
<li>Josh Goldberg ✨</li>
<li>Michael Naumov <a
href="https://github.com/mnaoumov"><code>@​mnaoumov</code></a></li>
<li>Mikhail Baev <a
href="https://github.com/baevm"><code>@​baevm</code></a></li>
<li>Om Rawat</li>
<li>overlookmotel</li>
<li>Sanath <a
href="https://github.com/sansynx"><code>@​sansynx</code></a></li>
<li>Shinji</li>
<li>stoicism <a
href="https://github.com/stoicism02"><code>@​stoicism02</code></a></li>
<li>Vinccool96</li>
<li>Younsang Na <a
href="https://github.com/nayounsang"><code>@​nayounsang</code></a></li>
<li>김채영 <a
href="https://github.com/cchaeyoung"><code>@​cchaeyoung</code></a></li>
<li>송재욱</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.70.1">GitHub
Releases</a> for more information.</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md">@​typescript-eslint/parser's
changelog</a>.</em></p>
<blockquote>
<h2>8.70.1 (2026-09-21)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.70.1">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.70.0 (2026-09-07)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.70.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.69.0 (2026-08-31)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.69.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/23d38ceeb8fb1237f55cb62fc2b54419e1fa1ed7"><code>23d38ce</code></a>
chore(release): publish 8.70.1</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/7ee76085c22e923c0036b8e0733a3ca7dfd82b60"><code>7ee7608</code></a>
chore(release): publish 8.70.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/9a6e546823e5d8f2dc015df2aa66c0230615e209"><code>9a6e546</code></a>
chore(release): publish 8.69.0</li>
<li>See full diff in <a
href="https://github.com/typescript-eslint/typescript-eslint/commits/v8.70.1/packages/parser">compare
view</a></li>
</ul>
</details>
<br />

Updates `prettier` from 3.9.6 to 3.9.9
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/prettier/prettier/releases">prettier's
releases</a>.</em></p>
<blockquote>
<h2>3.9.9</h2>
<ul>
<li>Markdown: Fix text with <code>$</code> been incorrectly parsed as
math syntax (<a
href="https://redirect.github.com/prettier/prettier/pull/20140">#20140</a>
by <a href="https://github.com/fisker"><code>@​fisker</code></a>)</li>
</ul>
<p>🔗 <a
href="https://github.com/prettier/prettier/blob/3.9.9/CHANGELOG.md#399">Changelog</a></p>
<h2>3.9.8</h2>
<ul>
<li>Markdown: Don't let Liquid objects interrupt paragraphs (<a
href="https://redirect.github.com/prettier/prettier/pull/20087">#20087</a>
by <a href="https://github.com/seiyab"><code>@​seiyab</code></a>)</li>
</ul>
<p>🔗 <a
href="https://github.com/prettier/prettier/blob/3.9.8/CHANGELOG.md#398">Changelog</a></p>
<h2>3.9.7</h2>
<ul>
<li>Support Angular 22.2</li>
<li>Fix regressions in v3.9</li>
</ul>
<p>🔗 <a
href="https://github.com/prettier/prettier/blob/3.9.7/CHANGELOG.md#397">Changelog</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/prettier/prettier/blob/main/CHANGELOG.md">prettier's
changelog</a>.</em></p>
<blockquote>
<h1>3.9.9</h1>
<p><a
href="https://github.com/prettier/prettier/compare/3.9.8...3.9.9">diff</a></p>
<h4>Markdown: Fix text with <code>$</code> been incorrectly parsed as
math syntax (<a
href="https://redirect.github.com/prettier/prettier/pull/20140">#20140</a>
by <a href="https://github.com/fisker"><code>@​fisker</code></a>)</h4>
<!-- raw HTML omitted -->
<pre lang="md"><code>&lt;!-- Input --&gt;
**Uses $FOO** from `a.sh` and `b.sh`, plus `$BAR` from `c.sh`, before
anything else runs here.
<p>&lt;!-- Prettier 3.9.8 --&gt;
<strong>Uses $FOO</strong> from <code>a.sh</code> and <code>b.sh</code>,
plus <code>$BAR</code>from<code>c.sh</code>, before anything else runs
here.</p>
<p>&lt;!-- Prettier 3.9.9 --&gt;
<strong>Uses $FOO</strong> from <code>a.sh</code> and <code>b.sh</code>,
plus <code>$BAR</code> from <code>c.sh</code>, before anything else runs
here.
</code></pre></p>
<h1>3.9.8</h1>
<p><a
href="https://github.com/prettier/prettier/compare/3.9.7...3.9.8">diff</a></p>
<h4>Markdown: Don't let Liquid objects interrupt paragraphs (<a
href="https://redirect.github.com/prettier/prettier/pull/20087">#20087</a>
by <a href="https://github.com/seiyab"><code>@​seiyab</code></a>)</h4>
<!-- raw HTML omitted -->
<pre lang="markdown"><code>&lt;!-- Input --&gt;
If `module` is not a
[`WebAssembly.Module`](https://github.com/prettier/prettier/blob/main/en-US/docs/WebAssembly/Reference/JavaScript_interface/Module)
object instance, a
{{jsxref(&quot;TypeError&quot;)}} is thrown.
<p>&lt;!-- Prettier 3.9.7 --&gt;
If <code>module</code> is not a <a
href="https://github.com/prettier/prettier/blob/main/en-US/docs/WebAssembly/Reference/JavaScript_interface/Module"><code>WebAssembly.Module</code></a>
object instance, a</p>
<p>{{jsxref(&quot;TypeError&quot;)}} is thrown.</p>
<p>&lt;!-- Prettier 3.9.8 --&gt;
If <code>module</code> is not a <a
href="https://github.com/prettier/prettier/blob/main/en-US/docs/WebAssembly/Reference/JavaScript_interface/Module"><code>WebAssembly.Module</code></a>
object instance, a
{{jsxref(&quot;TypeError&quot;)}} is thrown.
</code></pre></p>
<h1>3.9.7</h1>
<p><a
href="https://github.com/prettier/prettier/compare/3.9.6...3.9.7">diff</a></p>
<h4>Markdown: Prevent indentation drift in list-item code blocks (<a
href="https://redirect.github.com/prettier/prettier/pull/19647">#19647</a>,
<a
href="https://redirect.github.com/prettier/prettier/pull/19990">#19990</a>
by <a
href="https://github.com/Austin1serb"><code>@​Austin1serb</code></a>, <a
href="https://github.com/giaBaoJS"><code>@​giaBaoJS</code></a>)</h4>
<!-- raw HTML omitted -->
<pre lang="markdown"><code>&lt;!-- Input --&gt;
- [x] short first line.
&lt;/tr&gt;&lt;/table&gt; 
</code></pre>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/prettier/prettier/commit/cdd17f2288b28b170a76416c72dac56e3ea5daff"><code>cdd17f2</code></a>
Release 3.9.9</li>
<li><a
href="https://github.com/prettier/prettier/commit/dc7b8968e678f51ea00e2be3fe8c717d114691a3"><code>dc7b896</code></a>
Disable <code>singleDollarTextMath</code> in
<code>mdast-util-math</code> (<a
href="https://redirect.github.com/prettier/prettier/issues/20140">#20140</a>)</li>
<li><a
href="https://github.com/prettier/prettier/commit/f9be58fb8ec62dd47197ea19a30aac5ad26dfee0"><code>f9be58f</code></a>
Git blame ignore 3.9.8</li>
<li><a
href="https://github.com/prettier/prettier/commit/88470cb79ca3b757dd6b93906d9a992aa1a456c3"><code>88470cb</code></a>
Bump Prettier dependency to 3.9.8</li>
<li><a
href="https://github.com/prettier/prettier/commit/9559cab39eb5082c99a27e8829760c055adba841"><code>9559cab</code></a>
Clean changelog_unreleased</li>
<li><a
href="https://github.com/prettier/prettier/commit/4fc8ee87465de8d54780273a6996d74e8e9da827"><code>4fc8ee8</code></a>
Update dependents count</li>
<li><a
href="https://github.com/prettier/prettier/commit/4f2ab6765d7cb29408a2abdac75d023d64d44107"><code>4f2ab67</code></a>
Release 3.9.8</li>
<li><a
href="https://github.com/prettier/prettier/commit/3d82af8b15b8e89de20dd05cc65f66ab6d4ce8b0"><code>3d82af8</code></a>
Update Regex related dependencies (<a
href="https://redirect.github.com/prettier/prettier/issues/20082">#20082</a>)</li>
<li><a
href="https://github.com/prettier/prettier/commit/5ec8db1745c2bdcca3706ab8cfbbe5c11fc457c1"><code>5ec8db1</code></a>
[3.9.x] Markdown: Don't let Liquid objects interrupt paragraphs (<a
href="https://redirect.github.com/prettier/prettier/issues/20087">#20087</a>)</li>
<li><a
href="https://github.com/prettier/prettier/commit/5b142ed2bce0095161bf6865af30df2d5ba99466"><code>5b142ed</code></a>
Release Release <code>@​prettier/plugin-hermes</code><a
href="https://github.com/0"><code>@​0</code></a>.2.3,
<code>@​prettier/plugin-oxc</code><a
href="https://github.com/0"><code>@​0</code></a>.2.3, an...</li>
<li>Additional commits viewable in <a
href="https://github.com/prettier/prettier/compare/3.9.6...3.9.9">compare
view</a></li>
</ul>
</details>
<br />

Updates `@langchain/core` from 1.2.9 to 1.2.13
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/langchain-ai/langchainjs/releases">@​langchain/core's
releases</a>.</em></p>
<blockquote>
<h2><code>@​langchain/core</code><a
href="https://github.com/1"><code>@​1</code></a>.2.13</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/11714">#11714</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/a83dfb14f8e17fcb66dc7a915f0cf8ed7b0dffa1"><code>a83dfb1</code></a>
Thanks <a href="https://github.com/ccurme"><code>@​ccurme</code></a>! -
Abbreviate long tool-call IDs when formatting chat messages as strings,
keeping original messages unchanged.</li>
</ul>
<h2><code>@​langchain/core</code><a
href="https://github.com/1"><code>@​1</code></a>.2.12</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/11675">#11675</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/030a726639e0147488bc8c23c063a2e72b004c2e"><code>030a726</code></a>
Thanks <a href="https://github.com/hntrl"><code>@​hntrl</code></a>! -
Preserve structured tool arguments in tracer run inputs.</li>
</ul>
<h2><code>@​langchain/core</code><a
href="https://github.com/1"><code>@​1</code></a>.2.11</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/11603">#11603</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/fec9cd87b01976014dd549bd2cf7849aee89a566"><code>fec9cd8</code></a>
Thanks <a
href="https://github.com/thushanth-bengre-langchain"><code>@​thushanth-bengre-langchain</code></a>!
- fix(core): build streaming <code>llmOutput.tokenUsage</code> from the
fully-accumulated chunk instead of whichever individual chunk's
<code>usage_metadata</code> arrived last</p>
<p>Affects both core streaming paths —
<code>.stream()</code>/<code>.streamEvents()</code>
(<code>_streamIterator</code>) and
<code>.invoke()</code>/<code>.generate()</code> when a
streaming-preferring callback is attached
(<code>_generateWithCache</code>'s <code>hasStreamingHandler</code>
branch). Previously, <code>llmOutput.tokenUsage</code> was overwritten
by each chunk in turn, so only the last chunk carrying
<code>usage_metadata</code> won — correct for providers that emit one
cumulative total on a final chunk, but wrong for providers (e.g.
<code>@langchain/google</code>, <code>@langchain/anthropic</code>) that
emit <code>usage_metadata</code> as a per-chunk delta across multiple
chunks, where the values must be summed.</p>
<p>Note for provider authors: this assumes each streamed chunk's
<code>usage_metadata</code> is either a per-chunk delta or appears only
on a single final chunk. A provider that instead repeats a cumulative
total on every chunk will now see it summed (and inflated) in
<code>llmOutput.tokenUsage</code>, matching the existing behavior of the
correctly-working <code>message.usage_metadata</code> field.</p>
<p>Also fixes <code>@langchain/google</code>'s <code>invoke({streaming:
true})</code> path (no streaming-preferring callback attached), where
<code>llmOutput</code> was never populated at all.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/11590">#11590</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/ffebdc2f00f3290d19f85e5afd6a297920ae584c"><code>ffebdc2</code></a>
Thanks <a
href="https://github.com/thushanth-bengre-langchain"><code>@​thushanth-bengre-langchain</code></a>!
- Fix OpenAI Responses API replay under Zero Data Retention when a
response contains more than one reasoning item, for both v0 and v1. In
v0, the default replay path now reuses
<code>response_metadata.output</code> directly, preserving every
reasoning item's <code>id</code>/<code>encrypted_content</code> in
original order. In v1, <code>AIMessage.contentBlocks</code>
(<code>outputVersion: &quot;v1&quot;</code>) is fixed the same way.
<code>additional_kwargs.reasoning</code> is unchanged.</p>
</li>
</ul>
<h2><code>@​langchain/core</code><a
href="https://github.com/1"><code>@​1</code></a>.2.10</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/10047">#10047</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/ff1248fd49dacdb35f5da128278cd777068481d7"><code>ff1248f</code></a>
Thanks <a
href="https://github.com/afirstenberg"><code>@​afirstenberg</code></a>!
- fix(core): BaseMessage.text use contentBlocks</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/c8d12783ecc31a0816f3a47da1040fbd3c08fdbc"><code>c8d1278</code></a>
chore: version packages (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/11729">#11729</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/5d509ad4b8a5ed9dd4b83020b4c103ac8a69859c"><code>5d509ad</code></a>
fix(openai): send in-memory prompt cache retention as in_memory (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/11735">#11735</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/663b9a2076c5b274435c77524ad7730450b34f34"><code>663b9a2</code></a>
feat(openai): support explicit prompt caching (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/11232">#11232</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/7735b219221d6ae63eb5445fb67d26c18fce9c46"><code>7735b21</code></a>
chore(infra): drop held mcp-adapters 2.0 changeset to unblock main
releases (...</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/34edee1153f0fa40ba6997c8ff7bd45834ca8ce8"><code>34edee1</code></a>
fix(langchain): return failed returnDirect tool calls to the model (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/11712">#11712</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/0fcb98b4306a771c940e78d6881d0be9f88507c1"><code>0fcb98b</code></a>
fix(textsplitters): use char length for loc.lines with custom
lengthFunction ...</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/e4a3d1bd0c6753d4e1739a7f10064f48e6bc49ec"><code>e4a3d1b</code></a>
chore: version packages (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/11683">#11683</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/a9ada857f22c4b746801e77...

_Description has been truncated_

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-01 01:51:50 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
7c8be00fd6 chore(deps): bump the minor-and-patch group in /libs/cli with 5 updates (#9153)
Bumps the minor-and-patch group in /libs/cli with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [langgraph-sdk](https://github.com/langchain-ai/langgraph) | `0.4.4` |
`0.4.5` |
| [pytest-mock](https://github.com/pytest-dev/pytest-mock) | `3.15.1` |
`3.16.0` |
| [ruff](https://github.com/astral-sh/ruff) | `0.16.5` | `0.16.9` |
| [ty](https://github.com/astral-sh/ty) | `0.0.75` | `0.0.84` |
| [hatch](https://github.com/pypa/hatch) | `1.18.0` | `1.18.1` |

Updates `langgraph-sdk` from 0.4.4 to 0.4.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/langchain-ai/langgraph/releases">langgraph-sdk's
releases</a>.</em></p>
<blockquote>
<h2>langgraph-sdk==0.4.5</h2>
<p>Changes since sdk==0.4.4</p>
<ul>
<li>release(sdk-py): 0.4.5 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8988">#8988</a>)</li>
<li>release(langgraph): 1.2.12 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8987">#8987</a>)</li>
<li>chore(deps): bump anyio from 4.14.2 to 4.15.1 in /libs/sdk-py (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8997">#8997</a>)</li>
<li>chore(deps): bump anyio from 4.13.0 to 4.14.2 in /libs/cli (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8998">#8998</a>)</li>
<li>chore(deps): bump anyio from 4.12.1 to 4.14.2 in /libs/sdk-py (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8994">#8994</a>)</li>
<li>feat(langgraph): add response_schema to interrupt() (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8886">#8886</a>)</li>
<li>chore(deps): bump the minor-and-patch group across 1 directory with
7 updates (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8779">#8779</a>)</li>
<li>chore(deps): bump websockets from 16.0 to 16.1.1 in /libs/sdk-py in
the major group (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/8781">#8781</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/6fb2a93212ceeb432c13148849082af0775318a1"><code>6fb2a93</code></a>
langgraph: release 0.4.5 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/4709">#4709</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/3f8944c1fc560c6b8d700110c7b7764e5c769beb"><code>3f8944c</code></a>
checkpoint: release 2.0.26 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/4708">#4708</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/e79f3ceedc2508e18b7753d793a90e60ffad0b74"><code>e79f3ce</code></a>
Improve how we match cached writes for async imperative tasks (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/4691">#4691</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/3bdb7d09beae7e1fcfebe86aa91b18e5a93d2cc1"><code>3bdb7d0</code></a>
Lint</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/3acf63a918c6f5f59e9a3a4e2c629314e4f6099a"><code>3acf63a</code></a>
Lint</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/f51e5e2bd73f1678353bf7e01b09daf1c67cbd0f"><code>f51e5e2</code></a>
Improve how we match cached writes for async imperative tasks</li>
<li>See full diff in <a
href="https://github.com/langchain-ai/langgraph/compare/0.4.4...0.4.5">compare
view</a></li>
</ul>
</details>
<br />

Updates `pytest-mock` from 3.15.1 to 3.16.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/releases">pytest-mock's
releases</a>.</em></p>
<blockquote>
<h2>v3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/604">#604</a>:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/611">#611</a>:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/606">#606</a>:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/547">#547</a>:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/147">#147</a>:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst">pytest-mock's
changelog</a>.</em></p>
<blockquote>
<h2>3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><code>[#604](https://github.com/pytest-dev/pytest-mock/issues/604)
&lt;https://github.com/pytest-dev/pytest-mock/pull/604&gt;</code>_:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><code>[#611](https://github.com/pytest-dev/pytest-mock/issues/611)
&lt;https://github.com/pytest-dev/pytest-mock/pull/611&gt;</code>_:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><code>[#606](https://github.com/pytest-dev/pytest-mock/issues/606)
&lt;https://github.com/pytest-dev/pytest-mock/pull/606&gt;</code>_:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><code>[#547](https://github.com/pytest-dev/pytest-mock/issues/547)
&lt;https://github.com/pytest-dev/pytest-mock/issues/547&gt;</code>_:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><code>[#147](https://github.com/pytest-dev/pytest-mock/issues/147)
&lt;https://github.com/pytest-dev/pytest-mock/issues/147&gt;</code>_:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/f3b531f93c6d9837edc87ea1a6f4324dc9a2cdf3"><code>f3b531f</code></a>
Release 3.16.0</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/71ed67309520be160f3e100368705b58758d237a"><code>71ed673</code></a>
Fix duplicate_iterators for async spies (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/604">#604</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/0797e3d303cc5bbe0a3514b0625f7aeb3fa350b0"><code>0797e3d</code></a>
Fix async assertion argument introspection (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/611">#611</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/e24c334d573cfbf6989a31f4e3346676d9d31598"><code>e24c334</code></a>
docs: import os in the opening usage example (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/612">#612</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/9e7eb7b59cde362c1c8ace2d18ca00fe2d7a1cd1"><code>9e7eb7b</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/613">#613</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/445fd4d3daa8ed4c6d5428a77880da2e03d2f721"><code>445fd4d</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/610">#610</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/a8bd0b147afdf6b4bb1a1a3c3c088f32b0240091"><code>a8bd0b1</code></a>
Honour resetall() arguments for non-callable mocks (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/606">#606</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/6559fdfd5b67f096423e604a3a5a7045db2486a0"><code>6559fdf</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/608">#608</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/466d026254c949a8fbba8626b894308827be81cf"><code>466d026</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/605">#605</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/164defebde25bc31d53a2a64943c5c9aac43b57e"><code>164defe</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/603">#603</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pytest-dev/pytest-mock/compare/v3.15.1...v3.16.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.16.5 to 0.16.9
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>Install ruff 0.16.9</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-installer.sh
| sh
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>0.16.8</h2>
<p>Released on 2026-09-16.</p>
<h3>Bug fixes</h3>
<ul>
<li>Visit functional <code>TypedDict</code> keyword arguments correctly
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28584">#28584</a>)</li>
<li>[<code>flake8-simplify</code>] Detect nested <code>async with</code>
under sync parent (<code>SIM117</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27821">#27821</a>)</li>
<li>[<code>flake8-simplify</code>] Preserve operand order in
<code>SIM109</code> fix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27824">#27824</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/0be08a206f9c3180afd3e93bcc792ed5cb1f4db1"><code>0be08a2</code></a>
Bump version to 0.16.9 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28882">#28882</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/b4920b72b354e7c715ab861ae23458874683bb02"><code>b4920b7</code></a>
Rename <code>ruff_cli</code> to <code>ruff_command_line</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28881">#28881</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/47c751b95908a4d1f95f9ef8723036aae9da0b18"><code>47c751b</code></a>
Update dependency astral-sh/uv to v0.12.18 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28880">#28880</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c244e56a1aeac31c26d2371ef26588e0632235c"><code>8c244e5</code></a>
[<code>flake8-comprehensions</code>] Document <code>map</code>/generator
exception behavior (<code>C417</code>...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/5edf5a1d0a84663079e46983216059f06acea87d"><code>5edf5a1</code></a>
Use <code>target</code> form in <code>rooster.version_files</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28876">#28876</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/915bb2b4bf9ae7eee47cf55646bbfebae254a23b"><code>915bb2b</code></a>
[ty] Prefer existing @ paths over response files in Ruff and ty (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28877">#28877</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4710e1aa962b13720cf64aa84eb279c5333896d7"><code>4710e1a</code></a>
ci(github): update version number in placeholder of issue template (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28871">#28871</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/eedfc62a75bf1ba86d48959b00eea75ae87eadca"><code>eedfc62</code></a>
[ty] Propagate outer type context through cast calls (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28855">#28855</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/ceaa6a00830e1e350b8a23977a1a10ac467920a1"><code>ceaa6a0</code></a>
[ty] Contain rendered code within Markdown fences (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28869">#28869</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/dba0f30615424b94f94a174bba6ce6cce4bf11ff"><code>dba0f30</code></a>
authorize ruff-pre-commit dispatch via OIDC (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28867">#28867</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.16.5...0.16.9">compare
view</a></li>
</ul>
</details>
<br />

Updates `ty` from 0.0.75 to 0.0.84
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/releases">ty's
releases</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/blob/main/CHANGELOG.md">ty's
changelog</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ty/commit/8dd9a7f7fa35a18275d82117e6593ba45507065f"><code>8dd9a7f</code></a>
Bump version to 0.0.84 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4585">#4585</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/d4e4bf90906c7677049bc3a29d1735de7d22052d"><code>d4e4bf9</code></a>
publish to astral-sh/versions via OIDC (<a
href="https://redirect.github.com/astral-sh/ty/issues/4581">#4581</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/94ce7333abb356b2068dc98d37a68c993da6d09b"><code>94ce733</code></a>
use oidc issued token for docs publication (<a
href="https://redirect.github.com/astral-sh/ty/issues/4579">#4579</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/901eeaa9cd9ac06f34e85e4f721f76a0dc36e217"><code>901eeaa</code></a>
Update prek dependencies (<a
href="https://redirect.github.com/astral-sh/ty/issues/4576">#4576</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/09bf0b1b2114a628f3e2296d3d9d28245066c98b"><code>09bf0b1</code></a>
Update docker/setup-buildx-action action to v4.3.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4575">#4575</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/89d6ffe529dd44f64adc0d28f80744b7c7ab217f"><code>89d6ffe</code></a>
Update astral-sh/setup-uv action to v10.2.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4574">#4574</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/9c214798cfcc59069e986876564638fadf32d774"><code>9c21479</code></a>
Bump version to 0.0.83 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4569">#4569</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/04c69110b391e96310e6892cbed9936c4f31d7aa"><code>04c6911</code></a>
Sync the ty security mirror (<a
href="https://redirect.github.com/astral-sh/ty/issues/4549">#4549</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/3fa57a25767c619dbeba697c2acfbb8eb291519a"><code>3fa57a2</code></a>
Grant the versions workflow repository read access (<a
href="https://redirect.github.com/astral-sh/ty/issues/4550">#4550</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/a15b35389b44db57f718fd4e19e093481747c53e"><code>a15b353</code></a>
use scoped token for release workflow (<a
href="https://redirect.github.com/astral-sh/ty/issues/4506">#4506</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ty/compare/0.0.75...0.0.84">compare
view</a></li>
</ul>
</details>
<br />

Updates `hatch` from 1.18.0 to 1.18.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pypa/hatch/releases">hatch's
releases</a>.</em></p>
<blockquote>
<h2>Hatch v1.18.1</h2>
<p><em><strong>Added:</strong></em></p>
<ul>
<li>Apply context formatting to the <code>lock-filename</code>
environment option so fields such as <code>{env_name}</code> and
<code>{matrix:...}</code> are resolved when computing the lock file
path.</li>
</ul>
<p><em><strong>Fixed:</strong></em></p>
<ul>
<li>
<p>Consolidate extras and feature resolution into a single code path,
fixing regressions where environment and project extras could be dropped
or resolved inconsistently, and always validate undefined features.</p>
</li>
<li>
<p>Normalize hyphens in the plugin name when building environment option
environment variable names in <code>get_env_var()</code>, so options for
hyphenated plugins resolve to the correct variable.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pypa/hatch/commit/4b17561f822b1b416403a61855374892ecbe11de"><code>4b17561</code></a>
release Hatch v1.18.1 (<a
href="https://redirect.github.com/pypa/hatch/issues/2426">#2426</a>)</li>
<li><a
href="https://github.com/pypa/hatch/commit/b6aaa1a3cac6be652ac90c8c79612bddcca733ea"><code>b6aaa1a</code></a>
release Hatchling v1.32.1 (<a
href="https://redirect.github.com/pypa/hatch/issues/2425">#2425</a>)</li>
<li><a
href="https://github.com/pypa/hatch/commit/47f333a98228c326786d3919f346bd7b74d9cf8f"><code>47f333a</code></a>
Prepare for hatch and hatchling releases (<a
href="https://redirect.github.com/pypa/hatch/issues/2424">#2424</a>)</li>
<li><a
href="https://github.com/pypa/hatch/commit/d5f7bfe813dd4d81520def23b43f5d46aad1899c"><code>d5f7bfe</code></a>
Fix version metadata to preserve leading zeros in CalVer (<a
href="https://redirect.github.com/pypa/hatch/issues/2398">#2398</a>)</li>
<li><a
href="https://github.com/pypa/hatch/commit/cbfc465e019ff51460f80ebbc35370e476aed6b9"><code>cbfc465</code></a>
Context formatting support for <code>lock-filename</code> (<a
href="https://redirect.github.com/pypa/hatch/issues/2412">#2412</a>)</li>
<li><a
href="https://github.com/pypa/hatch/commit/929362c909899556ae4efd1f61a3b078677ad235"><code>929362c</code></a>
Mark a few more tests that require Internet access (<a
href="https://redirect.github.com/pypa/hatch/issues/2400">#2400</a>)</li>
<li><a
href="https://github.com/pypa/hatch/commit/c9d4e8a82a81835e1ed8b29e6885631d7f5aecb3"><code>c9d4e8a</code></a>
Fix env var formatting in <code>get_env_var()</code> function (<a
href="https://redirect.github.com/pypa/hatch/issues/2397">#2397</a>)</li>
<li><a
href="https://github.com/pypa/hatch/commit/84023e0b77ddec3aa3015cd9b57f78f00da2cb18"><code>84023e0</code></a>
Some type fixes (<a
href="https://redirect.github.com/pypa/hatch/issues/1138">#1138</a>)</li>
<li><a
href="https://github.com/pypa/hatch/commit/ed8e30bebf98f2fe4d70c18a32a50a8160c391cb"><code>ed8e30b</code></a>
Refactor extras so that the logic is in one place (<a
href="https://redirect.github.com/pypa/hatch/issues/2382">#2382</a>)</li>
<li>See full diff in <a
href="https://github.com/pypa/hatch/compare/hatch-v1.18.0...hatch-v1.18.1">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-01 01:51:40 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e9bde462f2 chore(deps-dev): bump types-requests from 2.33.0.20260712 to 2.33.0.20260906 in /libs/langgraph (#9156)
Bumps [types-requests](https://github.com/python/typeshed) from
2.33.0.20260712 to 2.33.0.20260906.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/python/typeshed/commits">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=types-requests&package-manager=uv&previous-version=2.33.0.20260712&new-version=2.33.0.20260906)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-01 01:51:29 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4be610c6bc chore(deps): bump pyjwt from 2.15.0 to 2.15.1 in /libs/langgraph (#9140)
Bumps [pyjwt](https://github.com/jpadilla/pyjwt) from 2.15.0 to 2.15.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jpadilla/pyjwt/releases">pyjwt's
releases</a>.</em></p>
<blockquote>
<h2>2.15.1</h2>
<p>See the <a
href="https://github.com/jpadilla/pyjwt/blob/2.15.1/CHANGELOG.rst">2.15.1
changelog</a> for complete release details.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst">pyjwt's
changelog</a>.</em></p>
<blockquote>
<h2><code>v2.15.1
&lt;https://github.com/jpadilla/pyjwt/compare/2.15.0...2.15.1&gt;</code>__</h2>
<p>Fixed</p>
<pre><code>
- Accept trailing Base64URL ``=`` padding when decoding JWS segments, so
  tokens issued by AWS ALB and similar systems verify instead of raising
  ``DecodeError: Invalid crypto padding``. Non-alphabet junk such as
``!!!!`` remains rejected
(`[#1209](https://github.com/jpadilla/pyjwt/issues/1209)
&lt;https://github.com/jpadilla/pyjwt/issues/1209&gt;`__).
</code></pre>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/jpadilla/pyjwt/commit/7d5ef55e42ce42221f58dc49943e92ccad1fa66a"><code>7d5ef55</code></a>
chore: prepare 2.15.1 release</li>
<li><a
href="https://github.com/jpadilla/pyjwt/commit/7bf32526738fe837387bdedd4849a4a525c33a79"><code>7bf3252</code></a>
Accept canonical Base64URL padding in JWT segments (<a
href="https://redirect.github.com/jpadilla/pyjwt/issues/1216">#1216</a>)</li>
<li>See full diff in <a
href="https://github.com/jpadilla/pyjwt/compare/2.15.0...2.15.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pyjwt&package-manager=uv&previous-version=2.15.0&new-version=2.15.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 12:28:57 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedy
98b10ba0ff chore(deps): bump urllib3 from 2.7.0 to 2.8.0 in /libs/checkpoint-conformance (#9133)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.8.0</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project. If your company or
organization uses Python and would benefit from HTTP/2 support in
Requests, pip, cloud SDKs, and thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden. (High severity, GHSA-8988-9cw3-xx77)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size line of unbounded length in memory. (High
severity, GHSA-vxq7-64xx-v4gw)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity, GHSA-gh4c-6fx4-qh6g)</li>
</ul>
<blockquote>
<p>[!IMPORTANT]
urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.</p>
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>. Destination client certificates
and identity overrides no longer apply to HTTPS forwarding proxy
connections.</p>
</blockquote>
<blockquote>
<p>[!NOTE]
CVE IDs had not yet been assigned to these advisories at the time of
release due to a backlog at GitHub's CNA.</p>
</blockquote>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option <code>allowed_methods</code> to retry any verb. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5044">#5044</a>)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience properties to the
result of <code>parse_url()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4945">#4945</a>)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5092">#5092</a>)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>
<p>Fixed response header handling to replace obsolete folded header
lines (<code>obs-fold</code>) with spaces in accordance with RFC 9112,
preventing raw CRLF sequences from appearing in header values such as
<code>Set-Cookie</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/1362">#1362</a>)</p>
</li>
<li>
<p>Fixed usage of <code>proxy_ssl_context</code> with
<code>ProxyManager</code> when
<code>use_forwarding_for_https=True</code>. Passing
<code>ssl_context</code> instead of <code>proxy_ssl_context</code> for
HTTPS proxies in this configuration now emits a
<code>FutureWarning</code> and will raise an error in v3.0. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/2577">#2577</a>)</p>
</li>
<li>
<p>Changed behavior of the default <code>ConnectionPool.pool</code>
initialization. <code>LifoQueue</code> is now resolved from the
<code>queue</code> module after the <code>ConnectionPool</code> is
instantiated instead of using the default cached <code>QueueCls</code>
class property. This is done because sometimes the
<code>queue.LifoQueue</code> is monkey-patched late in the program, such
as by gevent. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3289">#3289</a>)</p>
</li>
<li>
<p>Raised <code>UnrewindableBodyError</code> instead of
<code>ValueError</code> when retrying a request whose body had
<code>tell()</code> but not <code>seek()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3779">#3779</a>)</p>
</li>
<li>
<p>Decoded percent-encoded SOCKS proxy credentials before authenticating
with the proxy server. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3785">#3785</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPResponse.drain_conn()</code> to discard unread
response data in 64 KiB chunks (same as the default <code>amt</code>
when doing <code>HTTPResponse.stream(...)</code>). (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5019">#5019</a>)</p>
</li>
<li>
<p>Fixed <code>is_ipaddress()</code> to detect non-standard IPv4 forms
accepted by <code>socket.connect</code>, such as hex
(<code>0x7f000001</code>), octal (<code>0177.0.0.1</code>), and decimal
integers (<code>2130706433</code>), ensuring SSL certificate
verification uses the correct mode for these addresses. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5029">#5029</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen</code> raising a misleading
<code>FullPoolError</code> instead of <code>ValueError</code> when
called with an invalid <code>timeout</code> argument on a pool created
with <code>block=True</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5059">#5059</a>)</p>
</li>
<li>
<p>Fixed port-zero handling to preserve explicit <code>:0</code> values
instead of substituting the default ports 80 or 443 in URL parsing, pool
selection, proxy configuration, <code>connection_from_url()</code>, and
HTTP/2 request authority. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5071">#5071</a>,
<a
href="https://redirect.github.com/urllib3/urllib3/issues/5101">#5101</a>)</p>
</li>
<li>
<p>Fixed a bug where <code>PoolManager</code> passed the
<code>assert_hostname</code> and <code>assert_fingerprint</code>
parameters to HTTP connection pools. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5077">#5077</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen()</code> and HTTP proxy
forwarding to strip URL fragments from absolute request targets before
sending requests. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5079">#5079</a>)</p>
</li>
<li>
<p>Added safeguards to the proxy tunneling code to prevent potential
security issues when handling invalid characters in the proxy host and
HTTP headers. This change affects users of Python 3.10, Python 3.11, and
Python 3.12 when the standard library does not contain the fix; those on
newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the
same security fixes. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5091">#5091</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPSConnection.connect()</code> overriding
<code>ProxyConfig.ssl_context</code>'s certificate policy and proxy
identity checks with the target connection's TLS settings when
forwarding through an HTTPS proxy.</p>
<p><code>HTTPSConnection</code> no longer applies target SNI,
assertions, or client credentials to forwarding proxy handshakes and
continues to use its <code>ssl_context</code> as a fallback when an
HTTPS proxy forwards an HTTP target. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5093">#5093</a>)</p>
</li>
<li>
<p>Fixed URL parsing to more strictly enforce RFC 3986 host syntax,
rejecting invalid host input such as raw spaces and control characters,
malformed percent-encodings, and percent-encoded control characters in
HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel
targets. Host normalization now also follows RFC 3986 normalization
rules for percent-encoded octets by decoding percent-encoded unreserved
characters and uppercasing the hexadecimal digits of retained
percent-encoded octets. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5095">#5095</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.8.0 (2026-09-15)</h1>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden.
(High severity, <code>GHSA-8988-9cw3-xx77
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77&gt;</code>__)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size
line of unbounded length in memory. (High severity,
<code>GHSA-vxq7-64xx-v4gw
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw&gt;</code>__)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity,
<code>GHSA-gh4c-6fx4-qh6g
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g&gt;</code>__)</li>
</ul>
<p>.. caution::</p>
<pre><code>urllib3 2.8.0 fixes HTTPS proxy TLS configuration being
ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>.
Destination client certificates and identity overrides no longer
apply to HTTPS forwarding proxy connections.
</code></pre></p>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option
<code>allowed_methods</code> to retry any verb.
(<code>[#5044](https://github.com/urllib3/urllib3/issues/5044)
&lt;https://github.com/urllib3/urllib3/issues/5044&gt;</code>__)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience
properties to the result of <code>parse_url()</code>.
(<code>[#4945](https://github.com/urllib3/urllib3/issues/4945)
&lt;https://github.com/urllib3/urllib3/issues/4945&gt;</code>__)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>.
(<code>[#5092](https://github.com/urllib3/urllib3/issues/5092)
&lt;https://github.com/urllib3/urllib3/issues/5092&gt;</code>__)</li>
</ul>
<h2>Bugfixes</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/urllib3/urllib3/commit/b1d30ab61fe0db8f11092805e8c5ac43e091064a"><code>b1d30ab</code></a>
Release 2.8.0</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9016d7e8afc68185496ef07f3c3a4a743d04922e"><code>9016d7e</code></a>
Skip <code>test_read_chunked_with_trailing_data_does_not_hang</code> for
brotlicffi (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5258">#5258</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9101f581a8b3659af23b6ff335ae77200ca33533"><code>9101f58</code></a>
Fix <code>nox -s docs</code> warning (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5256">#5256</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/cd770b059b543be29298ea5c52afb0b1b090f5ed"><code>cd770b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/ea2ad7b21a80da3632f80016526a18864586077f"><code>ea2ad7b</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/0716e31534345dc1599ea95d903c79f276239bd8"><code>0716e31</code></a>
Fix loading unencrypted client keys with a password in pyOpenSSL (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5255">#5255</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/43c68c8b43a9dcb44ed2cf4ec91384ca0d46b37d"><code>43c68c8</code></a>
Test pickling of <code>InvalidChunkLength</code> (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5247">#5247</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/308b279b3fb28e7bee952e152ec5baeb5bfd0817"><code>308b279</code></a>
Share security policy between GitHub and Read the Docs (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5253">#5253</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/53fa0731b27d4b71ab0755ea5b896422d005d706"><code>53fa073</code></a>
Add policy on duplicate pull requests (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5252">#5252</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/5f2a6a843d0100d1351c3f94d58581ca98d17267"><code>5f2a6a8</code></a>
Assert on the ALPN extension in test_tunnel_sets_http_11_alpn (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5232">#5232</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=uv&previous-version=2.7.0&new-version=2.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: John Kennedy <65985482+jkennedyvz@users.noreply.github.com>
2026-09-30 18:50:53 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ffe4e8cd6d chore(deps): bump urllib3 from 2.7.0 to 2.8.0 in /libs/langgraph (#9138)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.8.0</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project. If your company or
organization uses Python and would benefit from HTTP/2 support in
Requests, pip, cloud SDKs, and thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden. (High severity, GHSA-8988-9cw3-xx77)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size line of unbounded length in memory. (High
severity, GHSA-vxq7-64xx-v4gw)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity, GHSA-gh4c-6fx4-qh6g)</li>
</ul>
<blockquote>
<p>[!IMPORTANT]
urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.</p>
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>. Destination client certificates
and identity overrides no longer apply to HTTPS forwarding proxy
connections.</p>
</blockquote>
<blockquote>
<p>[!NOTE]
CVE IDs had not yet been assigned to these advisories at the time of
release due to a backlog at GitHub's CNA.</p>
</blockquote>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option <code>allowed_methods</code> to retry any verb. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5044">#5044</a>)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience properties to the
result of <code>parse_url()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4945">#4945</a>)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5092">#5092</a>)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>
<p>Fixed response header handling to replace obsolete folded header
lines (<code>obs-fold</code>) with spaces in accordance with RFC 9112,
preventing raw CRLF sequences from appearing in header values such as
<code>Set-Cookie</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/1362">#1362</a>)</p>
</li>
<li>
<p>Fixed usage of <code>proxy_ssl_context</code> with
<code>ProxyManager</code> when
<code>use_forwarding_for_https=True</code>. Passing
<code>ssl_context</code> instead of <code>proxy_ssl_context</code> for
HTTPS proxies in this configuration now emits a
<code>FutureWarning</code> and will raise an error in v3.0. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/2577">#2577</a>)</p>
</li>
<li>
<p>Changed behavior of the default <code>ConnectionPool.pool</code>
initialization. <code>LifoQueue</code> is now resolved from the
<code>queue</code> module after the <code>ConnectionPool</code> is
instantiated instead of using the default cached <code>QueueCls</code>
class property. This is done because sometimes the
<code>queue.LifoQueue</code> is monkey-patched late in the program, such
as by gevent. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3289">#3289</a>)</p>
</li>
<li>
<p>Raised <code>UnrewindableBodyError</code> instead of
<code>ValueError</code> when retrying a request whose body had
<code>tell()</code> but not <code>seek()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3779">#3779</a>)</p>
</li>
<li>
<p>Decoded percent-encoded SOCKS proxy credentials before authenticating
with the proxy server. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3785">#3785</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPResponse.drain_conn()</code> to discard unread
response data in 64 KiB chunks (same as the default <code>amt</code>
when doing <code>HTTPResponse.stream(...)</code>). (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5019">#5019</a>)</p>
</li>
<li>
<p>Fixed <code>is_ipaddress()</code> to detect non-standard IPv4 forms
accepted by <code>socket.connect</code>, such as hex
(<code>0x7f000001</code>), octal (<code>0177.0.0.1</code>), and decimal
integers (<code>2130706433</code>), ensuring SSL certificate
verification uses the correct mode for these addresses. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5029">#5029</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen</code> raising a misleading
<code>FullPoolError</code> instead of <code>ValueError</code> when
called with an invalid <code>timeout</code> argument on a pool created
with <code>block=True</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5059">#5059</a>)</p>
</li>
<li>
<p>Fixed port-zero handling to preserve explicit <code>:0</code> values
instead of substituting the default ports 80 or 443 in URL parsing, pool
selection, proxy configuration, <code>connection_from_url()</code>, and
HTTP/2 request authority. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5071">#5071</a>,
<a
href="https://redirect.github.com/urllib3/urllib3/issues/5101">#5101</a>)</p>
</li>
<li>
<p>Fixed a bug where <code>PoolManager</code> passed the
<code>assert_hostname</code> and <code>assert_fingerprint</code>
parameters to HTTP connection pools. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5077">#5077</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen()</code> and HTTP proxy
forwarding to strip URL fragments from absolute request targets before
sending requests. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5079">#5079</a>)</p>
</li>
<li>
<p>Added safeguards to the proxy tunneling code to prevent potential
security issues when handling invalid characters in the proxy host and
HTTP headers. This change affects users of Python 3.10, Python 3.11, and
Python 3.12 when the standard library does not contain the fix; those on
newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the
same security fixes. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5091">#5091</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPSConnection.connect()</code> overriding
<code>ProxyConfig.ssl_context</code>'s certificate policy and proxy
identity checks with the target connection's TLS settings when
forwarding through an HTTPS proxy.</p>
<p><code>HTTPSConnection</code> no longer applies target SNI,
assertions, or client credentials to forwarding proxy handshakes and
continues to use its <code>ssl_context</code> as a fallback when an
HTTPS proxy forwards an HTTP target. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5093">#5093</a>)</p>
</li>
<li>
<p>Fixed URL parsing to more strictly enforce RFC 3986 host syntax,
rejecting invalid host input such as raw spaces and control characters,
malformed percent-encodings, and percent-encoded control characters in
HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel
targets. Host normalization now also follows RFC 3986 normalization
rules for percent-encoded octets by decoding percent-encoded unreserved
characters and uppercasing the hexadecimal digits of retained
percent-encoded octets. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5095">#5095</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.8.0 (2026-09-15)</h1>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden.
(High severity, <code>GHSA-8988-9cw3-xx77
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77&gt;</code>__)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size
line of unbounded length in memory. (High severity,
<code>GHSA-vxq7-64xx-v4gw
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw&gt;</code>__)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity,
<code>GHSA-gh4c-6fx4-qh6g
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g&gt;</code>__)</li>
</ul>
<p>.. caution::</p>
<pre><code>urllib3 2.8.0 fixes HTTPS proxy TLS configuration being
ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>.
Destination client certificates and identity overrides no longer
apply to HTTPS forwarding proxy connections.
</code></pre></p>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option
<code>allowed_methods</code> to retry any verb.
(<code>[#5044](https://github.com/urllib3/urllib3/issues/5044)
&lt;https://github.com/urllib3/urllib3/issues/5044&gt;</code>__)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience
properties to the result of <code>parse_url()</code>.
(<code>[#4945](https://github.com/urllib3/urllib3/issues/4945)
&lt;https://github.com/urllib3/urllib3/issues/4945&gt;</code>__)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>.
(<code>[#5092](https://github.com/urllib3/urllib3/issues/5092)
&lt;https://github.com/urllib3/urllib3/issues/5092&gt;</code>__)</li>
</ul>
<h2>Bugfixes</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/urllib3/urllib3/commit/b1d30ab61fe0db8f11092805e8c5ac43e091064a"><code>b1d30ab</code></a>
Release 2.8.0</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9016d7e8afc68185496ef07f3c3a4a743d04922e"><code>9016d7e</code></a>
Skip <code>test_read_chunked_with_trailing_data_does_not_hang</code> for
brotlicffi (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5258">#5258</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9101f581a8b3659af23b6ff335ae77200ca33533"><code>9101f58</code></a>
Fix <code>nox -s docs</code> warning (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5256">#5256</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/cd770b059b543be29298ea5c52afb0b1b090f5ed"><code>cd770b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/ea2ad7b21a80da3632f80016526a18864586077f"><code>ea2ad7b</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/0716e31534345dc1599ea95d903c79f276239bd8"><code>0716e31</code></a>
Fix loading unencrypted client keys with a password in pyOpenSSL (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5255">#5255</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/43c68c8b43a9dcb44ed2cf4ec91384ca0d46b37d"><code>43c68c8</code></a>
Test pickling of <code>InvalidChunkLength</code> (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5247">#5247</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/308b279b3fb28e7bee952e152ec5baeb5bfd0817"><code>308b279</code></a>
Share security policy between GitHub and Read the Docs (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5253">#5253</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/53fa0731b27d4b71ab0755ea5b896422d005d706"><code>53fa073</code></a>
Add policy on duplicate pull requests (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5252">#5252</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/5f2a6a843d0100d1351c3f94d58581ca98d17267"><code>5f2a6a8</code></a>
Assert on the ALPN extension in test_tunnel_sets_http_11_alpn (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5232">#5232</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=uv&previous-version=2.7.0&new-version=2.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 11:43:51 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
f75add0ee9 chore(deps): bump urllib3 from 2.7.0 to 2.8.0 in /libs/cli (#9137)
[//]: # (dependabot-start)
⚠️  **Dependabot is rebasing this PR** ⚠️ 

Rebasing might not happen immediately, so don't worry if this takes some
time.

Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.

---

[//]: # (dependabot-end)

Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.8.0</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project. If your company or
organization uses Python and would benefit from HTTP/2 support in
Requests, pip, cloud SDKs, and thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden. (High severity, GHSA-8988-9cw3-xx77)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size line of unbounded length in memory. (High
severity, GHSA-vxq7-64xx-v4gw)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity, GHSA-gh4c-6fx4-qh6g)</li>
</ul>
<blockquote>
<p>[!IMPORTANT]
urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.</p>
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>. Destination client certificates
and identity overrides no longer apply to HTTPS forwarding proxy
connections.</p>
</blockquote>
<blockquote>
<p>[!NOTE]
CVE IDs had not yet been assigned to these advisories at the time of
release due to a backlog at GitHub's CNA.</p>
</blockquote>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option <code>allowed_methods</code> to retry any verb. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5044">#5044</a>)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience properties to the
result of <code>parse_url()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4945">#4945</a>)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5092">#5092</a>)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>
<p>Fixed response header handling to replace obsolete folded header
lines (<code>obs-fold</code>) with spaces in accordance with RFC 9112,
preventing raw CRLF sequences from appearing in header values such as
<code>Set-Cookie</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/1362">#1362</a>)</p>
</li>
<li>
<p>Fixed usage of <code>proxy_ssl_context</code> with
<code>ProxyManager</code> when
<code>use_forwarding_for_https=True</code>. Passing
<code>ssl_context</code> instead of <code>proxy_ssl_context</code> for
HTTPS proxies in this configuration now emits a
<code>FutureWarning</code> and will raise an error in v3.0. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/2577">#2577</a>)</p>
</li>
<li>
<p>Changed behavior of the default <code>ConnectionPool.pool</code>
initialization. <code>LifoQueue</code> is now resolved from the
<code>queue</code> module after the <code>ConnectionPool</code> is
instantiated instead of using the default cached <code>QueueCls</code>
class property. This is done because sometimes the
<code>queue.LifoQueue</code> is monkey-patched late in the program, such
as by gevent. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3289">#3289</a>)</p>
</li>
<li>
<p>Raised <code>UnrewindableBodyError</code> instead of
<code>ValueError</code> when retrying a request whose body had
<code>tell()</code> but not <code>seek()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3779">#3779</a>)</p>
</li>
<li>
<p>Decoded percent-encoded SOCKS proxy credentials before authenticating
with the proxy server. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3785">#3785</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPResponse.drain_conn()</code> to discard unread
response data in 64 KiB chunks (same as the default <code>amt</code>
when doing <code>HTTPResponse.stream(...)</code>). (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5019">#5019</a>)</p>
</li>
<li>
<p>Fixed <code>is_ipaddress()</code> to detect non-standard IPv4 forms
accepted by <code>socket.connect</code>, such as hex
(<code>0x7f000001</code>), octal (<code>0177.0.0.1</code>), and decimal
integers (<code>2130706433</code>), ensuring SSL certificate
verification uses the correct mode for these addresses. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5029">#5029</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen</code> raising a misleading
<code>FullPoolError</code> instead of <code>ValueError</code> when
called with an invalid <code>timeout</code> argument on a pool created
with <code>block=True</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5059">#5059</a>)</p>
</li>
<li>
<p>Fixed port-zero handling to preserve explicit <code>:0</code> values
instead of substituting the default ports 80 or 443 in URL parsing, pool
selection, proxy configuration, <code>connection_from_url()</code>, and
HTTP/2 request authority. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5071">#5071</a>,
<a
href="https://redirect.github.com/urllib3/urllib3/issues/5101">#5101</a>)</p>
</li>
<li>
<p>Fixed a bug where <code>PoolManager</code> passed the
<code>assert_hostname</code> and <code>assert_fingerprint</code>
parameters to HTTP connection pools. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5077">#5077</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen()</code> and HTTP proxy
forwarding to strip URL fragments from absolute request targets before
sending requests. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5079">#5079</a>)</p>
</li>
<li>
<p>Added safeguards to the proxy tunneling code to prevent potential
security issues when handling invalid characters in the proxy host and
HTTP headers. This change affects users of Python 3.10, Python 3.11, and
Python 3.12 when the standard library does not contain the fix; those on
newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the
same security fixes. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5091">#5091</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPSConnection.connect()</code> overriding
<code>ProxyConfig.ssl_context</code>'s certificate policy and proxy
identity checks with the target connection's TLS settings when
forwarding through an HTTPS proxy.</p>
<p><code>HTTPSConnection</code> no longer applies target SNI,
assertions, or client credentials to forwarding proxy handshakes and
continues to use its <code>ssl_context</code> as a fallback when an
HTTPS proxy forwards an HTTP target. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5093">#5093</a>)</p>
</li>
<li>
<p>Fixed URL parsing to more strictly enforce RFC 3986 host syntax,
rejecting invalid host input such as raw spaces and control characters,
malformed percent-encodings, and percent-encoded control characters in
HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel
targets. Host normalization now also follows RFC 3986 normalization
rules for percent-encoded octets by decoding percent-encoded unreserved
characters and uppercasing the hexadecimal digits of retained
percent-encoded octets. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5095">#5095</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.8.0 (2026-09-15)</h1>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden.
(High severity, <code>GHSA-8988-9cw3-xx77
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77&gt;</code>__)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size
line of unbounded length in memory. (High severity,
<code>GHSA-vxq7-64xx-v4gw
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw&gt;</code>__)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity,
<code>GHSA-gh4c-6fx4-qh6g
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g&gt;</code>__)</li>
</ul>
<p>.. caution::</p>
<pre><code>urllib3 2.8.0 fixes HTTPS proxy TLS configuration being
ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>.
Destination client certificates and identity overrides no longer
apply to HTTPS forwarding proxy connections.
</code></pre></p>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option
<code>allowed_methods</code> to retry any verb.
(<code>[#5044](https://github.com/urllib3/urllib3/issues/5044)
&lt;https://github.com/urllib3/urllib3/issues/5044&gt;</code>__)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience
properties to the result of <code>parse_url()</code>.
(<code>[#4945](https://github.com/urllib3/urllib3/issues/4945)
&lt;https://github.com/urllib3/urllib3/issues/4945&gt;</code>__)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>.
(<code>[#5092](https://github.com/urllib3/urllib3/issues/5092)
&lt;https://github.com/urllib3/urllib3/issues/5092&gt;</code>__)</li>
</ul>
<h2>Bugfixes</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/urllib3/urllib3/commit/b1d30ab61fe0db8f11092805e8c5ac43e091064a"><code>b1d30ab</code></a>
Release 2.8.0</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9016d7e8afc68185496ef07f3c3a4a743d04922e"><code>9016d7e</code></a>
Skip <code>test_read_chunked_with_trailing_data_does_not_hang</code> for
brotlicffi (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5258">#5258</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9101f581a8b3659af23b6ff335ae77200ca33533"><code>9101f58</code></a>
Fix <code>nox -s docs</code> warning (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5256">#5256</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/cd770b059b543be29298ea5c52afb0b1b090f5ed"><code>cd770b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/ea2ad7b21a80da3632f80016526a18864586077f"><code>ea2ad7b</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/0716e31534345dc1599ea95d903c79f276239bd8"><code>0716e31</code></a>
Fix loading unencrypted client keys with a password in pyOpenSSL (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5255">#5255</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/43c68c8b43a9dcb44ed2cf4ec91384ca0d46b37d"><code>43c68c8</code></a>
Test pickling of <code>InvalidChunkLength</code> (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5247">#5247</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/308b279b3fb28e7bee952e152ec5baeb5bfd0817"><code>308b279</code></a>
Share security policy between GitHub and Read the Docs (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5253">#5253</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/53fa0731b27d4b71ab0755ea5b896422d005d706"><code>53fa073</code></a>
Add policy on duplicate pull requests (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5252">#5252</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/5f2a6a843d0100d1351c3f94d58581ca98d17267"><code>5f2a6a8</code></a>
Assert on the ALPN extension in test_tunnel_sets_http_11_alpn (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5232">#5232</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=uv&previous-version=2.7.0&new-version=2.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 11:43:37 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
902be1eb2b chore(deps): bump the uv group across 2 directories with 1 update (#9136)
Bumps the uv group with 1 update in the /libs/cli/uv-examples/monorepo
directory: [urllib3](https://github.com/urllib3/urllib3).
Bumps the uv group with 1 update in the /libs/cli/uv-examples/simple
directory: [urllib3](https://github.com/urllib3/urllib3).

Updates `urllib3` from 2.7.0 to 2.8.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.8.0</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project. If your company or
organization uses Python and would benefit from HTTP/2 support in
Requests, pip, cloud SDKs, and thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden. (High severity, GHSA-8988-9cw3-xx77)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size line of unbounded length in memory. (High
severity, GHSA-vxq7-64xx-v4gw)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity, GHSA-gh4c-6fx4-qh6g)</li>
</ul>
<blockquote>
<p>[!IMPORTANT]
urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.</p>
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>. Destination client certificates
and identity overrides no longer apply to HTTPS forwarding proxy
connections.</p>
</blockquote>
<blockquote>
<p>[!NOTE]
CVE IDs had not yet been assigned to these advisories at the time of
release due to a backlog at GitHub's CNA.</p>
</blockquote>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option <code>allowed_methods</code> to retry any verb. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5044">#5044</a>)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience properties to the
result of <code>parse_url()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4945">#4945</a>)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5092">#5092</a>)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>
<p>Fixed response header handling to replace obsolete folded header
lines (<code>obs-fold</code>) with spaces in accordance with RFC 9112,
preventing raw CRLF sequences from appearing in header values such as
<code>Set-Cookie</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/1362">#1362</a>)</p>
</li>
<li>
<p>Fixed usage of <code>proxy_ssl_context</code> with
<code>ProxyManager</code> when
<code>use_forwarding_for_https=True</code>. Passing
<code>ssl_context</code> instead of <code>proxy_ssl_context</code> for
HTTPS proxies in this configuration now emits a
<code>FutureWarning</code> and will raise an error in v3.0. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/2577">#2577</a>)</p>
</li>
<li>
<p>Changed behavior of the default <code>ConnectionPool.pool</code>
initialization. <code>LifoQueue</code> is now resolved from the
<code>queue</code> module after the <code>ConnectionPool</code> is
instantiated instead of using the default cached <code>QueueCls</code>
class property. This is done because sometimes the
<code>queue.LifoQueue</code> is monkey-patched late in the program, such
as by gevent. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3289">#3289</a>)</p>
</li>
<li>
<p>Raised <code>UnrewindableBodyError</code> instead of
<code>ValueError</code> when retrying a request whose body had
<code>tell()</code> but not <code>seek()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3779">#3779</a>)</p>
</li>
<li>
<p>Decoded percent-encoded SOCKS proxy credentials before authenticating
with the proxy server. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3785">#3785</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPResponse.drain_conn()</code> to discard unread
response data in 64 KiB chunks (same as the default <code>amt</code>
when doing <code>HTTPResponse.stream(...)</code>). (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5019">#5019</a>)</p>
</li>
<li>
<p>Fixed <code>is_ipaddress()</code> to detect non-standard IPv4 forms
accepted by <code>socket.connect</code>, such as hex
(<code>0x7f000001</code>), octal (<code>0177.0.0.1</code>), and decimal
integers (<code>2130706433</code>), ensuring SSL certificate
verification uses the correct mode for these addresses. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5029">#5029</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen</code> raising a misleading
<code>FullPoolError</code> instead of <code>ValueError</code> when
called with an invalid <code>timeout</code> argument on a pool created
with <code>block=True</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5059">#5059</a>)</p>
</li>
<li>
<p>Fixed port-zero handling to preserve explicit <code>:0</code> values
instead of substituting the default ports 80 or 443 in URL parsing, pool
selection, proxy configuration, <code>connection_from_url()</code>, and
HTTP/2 request authority. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5071">#5071</a>,
<a
href="https://redirect.github.com/urllib3/urllib3/issues/5101">#5101</a>)</p>
</li>
<li>
<p>Fixed a bug where <code>PoolManager</code> passed the
<code>assert_hostname</code> and <code>assert_fingerprint</code>
parameters to HTTP connection pools. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5077">#5077</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen()</code> and HTTP proxy
forwarding to strip URL fragments from absolute request targets before
sending requests. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5079">#5079</a>)</p>
</li>
<li>
<p>Added safeguards to the proxy tunneling code to prevent potential
security issues when handling invalid characters in the proxy host and
HTTP headers. This change affects users of Python 3.10, Python 3.11, and
Python 3.12 when the standard library does not contain the fix; those on
newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the
same security fixes. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5091">#5091</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPSConnection.connect()</code> overriding
<code>ProxyConfig.ssl_context</code>'s certificate policy and proxy
identity checks with the target connection's TLS settings when
forwarding through an HTTPS proxy.</p>
<p><code>HTTPSConnection</code> no longer applies target SNI,
assertions, or client credentials to forwarding proxy handshakes and
continues to use its <code>ssl_context</code> as a fallback when an
HTTPS proxy forwards an HTTP target. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5093">#5093</a>)</p>
</li>
<li>
<p>Fixed URL parsing to more strictly enforce RFC 3986 host syntax,
rejecting invalid host input such as raw spaces and control characters,
malformed percent-encodings, and percent-encoded control characters in
HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel
targets. Host normalization now also follows RFC 3986 normalization
rules for percent-encoded octets by decoding percent-encoded unreserved
characters and uppercasing the hexadecimal digits of retained
percent-encoded octets. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5095">#5095</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.8.0 (2026-09-15)</h1>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden.
(High severity, <code>GHSA-8988-9cw3-xx77
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77&gt;</code>__)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size
line of unbounded length in memory. (High severity,
<code>GHSA-vxq7-64xx-v4gw
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw&gt;</code>__)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity,
<code>GHSA-gh4c-6fx4-qh6g
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g&gt;</code>__)</li>
</ul>
<p>.. caution::</p>
<pre><code>urllib3 2.8.0 fixes HTTPS proxy TLS configuration being
ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>.
Destination client certificates and identity overrides no longer
apply to HTTPS forwarding proxy connections.
</code></pre></p>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option
<code>allowed_methods</code> to retry any verb.
(<code>[#5044](https://github.com/urllib3/urllib3/issues/5044)
&lt;https://github.com/urllib3/urllib3/issues/5044&gt;</code>__)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience
properties to the result of <code>parse_url()</code>.
(<code>[#4945](https://github.com/urllib3/urllib3/issues/4945)
&lt;https://github.com/urllib3/urllib3/issues/4945&gt;</code>__)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>.
(<code>[#5092](https://github.com/urllib3/urllib3/issues/5092)
&lt;https://github.com/urllib3/urllib3/issues/5092&gt;</code>__)</li>
</ul>
<h2>Bugfixes</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/urllib3/urllib3/commit/b1d30ab61fe0db8f11092805e8c5ac43e091064a"><code>b1d30ab</code></a>
Release 2.8.0</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9016d7e8afc68185496ef07f3c3a4a743d04922e"><code>9016d7e</code></a>
Skip <code>test_read_chunked_with_trailing_data_does_not_hang</code> for
brotlicffi (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5258">#5258</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9101f581a8b3659af23b6ff335ae77200ca33533"><code>9101f58</code></a>
Fix <code>nox -s docs</code> warning (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5256">#5256</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/cd770b059b543be29298ea5c52afb0b1b090f5ed"><code>cd770b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/ea2ad7b21a80da3632f80016526a18864586077f"><code>ea2ad7b</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/0716e31534345dc1599ea95d903c79f276239bd8"><code>0716e31</code></a>
Fix loading unencrypted client keys with a password in pyOpenSSL (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5255">#5255</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/43c68c8b43a9dcb44ed2cf4ec91384ca0d46b37d"><code>43c68c8</code></a>
Test pickling of <code>InvalidChunkLength</code> (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5247">#5247</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/308b279b3fb28e7bee952e152ec5baeb5bfd0817"><code>308b279</code></a>
Share security policy between GitHub and Read the Docs (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5253">#5253</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/53fa0731b27d4b71ab0755ea5b896422d005d706"><code>53fa073</code></a>
Add policy on duplicate pull requests (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5252">#5252</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/5f2a6a843d0100d1351c3f94d58581ca98d17267"><code>5f2a6a8</code></a>
Assert on the ALPN extension in test_tunnel_sets_http_11_alpn (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5232">#5232</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `urllib3` from 2.7.0 to 2.8.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.8.0</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project. If your company or
organization uses Python and would benefit from HTTP/2 support in
Requests, pip, cloud SDKs, and thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden. (High severity, GHSA-8988-9cw3-xx77)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size line of unbounded length in memory. (High
severity, GHSA-vxq7-64xx-v4gw)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity, GHSA-gh4c-6fx4-qh6g)</li>
</ul>
<blockquote>
<p>[!IMPORTANT]
urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.</p>
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>. Destination client certificates
and identity overrides no longer apply to HTTPS forwarding proxy
connections.</p>
</blockquote>
<blockquote>
<p>[!NOTE]
CVE IDs had not yet been assigned to these advisories at the time of
release due to a backlog at GitHub's CNA.</p>
</blockquote>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option <code>allowed_methods</code> to retry any verb. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5044">#5044</a>)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience properties to the
result of <code>parse_url()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4945">#4945</a>)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5092">#5092</a>)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>
<p>Fixed response header handling to replace obsolete folded header
lines (<code>obs-fold</code>) with spaces in accordance with RFC 9112,
preventing raw CRLF sequences from appearing in header values such as
<code>Set-Cookie</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/1362">#1362</a>)</p>
</li>
<li>
<p>Fixed usage of <code>proxy_ssl_context</code> with
<code>ProxyManager</code> when
<code>use_forwarding_for_https=True</code>. Passing
<code>ssl_context</code> instead of <code>proxy_ssl_context</code> for
HTTPS proxies in this configuration now emits a
<code>FutureWarning</code> and will raise an error in v3.0. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/2577">#2577</a>)</p>
</li>
<li>
<p>Changed behavior of the default <code>ConnectionPool.pool</code>
initialization. <code>LifoQueue</code> is now resolved from the
<code>queue</code> module after the <code>ConnectionPool</code> is
instantiated instead of using the default cached <code>QueueCls</code>
class property. This is done because sometimes the
<code>queue.LifoQueue</code> is monkey-patched late in the program, such
as by gevent. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3289">#3289</a>)</p>
</li>
<li>
<p>Raised <code>UnrewindableBodyError</code> instead of
<code>ValueError</code> when retrying a request whose body had
<code>tell()</code> but not <code>seek()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3779">#3779</a>)</p>
</li>
<li>
<p>Decoded percent-encoded SOCKS proxy credentials before authenticating
with the proxy server. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3785">#3785</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPResponse.drain_conn()</code> to discard unread
response data in 64 KiB chunks (same as the default <code>amt</code>
when doing <code>HTTPResponse.stream(...)</code>). (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5019">#5019</a>)</p>
</li>
<li>
<p>Fixed <code>is_ipaddress()</code> to detect non-standard IPv4 forms
accepted by <code>socket.connect</code>, such as hex
(<code>0x7f000001</code>), octal (<code>0177.0.0.1</code>), and decimal
integers (<code>2130706433</code>), ensuring SSL certificate
verification uses the correct mode for these addresses. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5029">#5029</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen</code> raising a misleading
<code>FullPoolError</code> instead of <code>ValueError</code> when
called with an invalid <code>timeout</code> argument on a pool created
with <code>block=True</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5059">#5059</a>)</p>
</li>
<li>
<p>Fixed port-zero handling to preserve explicit <code>:0</code> values
instead of substituting the default ports 80 or 443 in URL parsing, pool
selection, proxy configuration, <code>connection_from_url()</code>, and
HTTP/2 request authority. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5071">#5071</a>,
<a
href="https://redirect.github.com/urllib3/urllib3/issues/5101">#5101</a>)</p>
</li>
<li>
<p>Fixed a bug where <code>PoolManager</code> passed the
<code>assert_hostname</code> and <code>assert_fingerprint</code>
parameters to HTTP connection pools. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5077">#5077</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen()</code> and HTTP proxy
forwarding to strip URL fragments from absolute request targets before
sending requests. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5079">#5079</a>)</p>
</li>
<li>
<p>Added safeguards to the proxy tunneling code to prevent potential
security issues when handling invalid characters in the proxy host and
HTTP headers. This change affects users of Python 3.10, Python 3.11, and
Python 3.12 when the standard library does not contain the fix; those on
newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the
same security fixes. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5091">#5091</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPSConnection.connect()</code> overriding
<code>ProxyConfig.ssl_context</code>'s certificate policy and proxy
identity checks with the target connection's TLS settings when
forwarding through an HTTPS proxy.</p>
<p><code>HTTPSConnection</code> no longer applies target SNI,
assertions, or client credentials to forwarding proxy handshakes and
continues to use its <code>ssl_context</code> as a fallback when an
HTTPS proxy forwards an HTTP target. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5093">#5093</a>)</p>
</li>
<li>
<p>Fixed URL parsing to more strictly enforce RFC 3986 host syntax,
rejecting invalid host input such as raw spaces and control characters,
malformed percent-encodings, and percent-encoded control characters in
HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel
targets. Host normalization now also follows RFC 3986 normalization
rules for percent-encoded octets by decoding percent-encoded unreserved
characters and uppercasing the hexadecimal digits of retained
percent-encoded octets. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5095">#5095</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.8.0 (2026-09-15)</h1>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden.
(High severity, <code>GHSA-8988-9cw3-xx77
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77&gt;</code>__)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size
line of unbounded length in memory. (High severity,
<code>GHSA-vxq7-64xx-v4gw
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw&gt;</code>__)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity,
<code>GHSA-gh4c-6fx4-qh6g
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g&gt;</code>__)</li>
</ul>
<p>.. caution::</p>
<pre><code>urllib3 2.8.0 fixes HTTPS proxy TLS configuration being
ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>.
Destination client certificates and identity overrides no longer
apply to HTTPS forwarding proxy connections.
</code></pre></p>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option
<code>allowed_methods</code> to retry any verb.
(<code>[#5044](https://github.com/urllib3/urllib3/issues/5044)
&lt;https://github.com/urllib3/urllib3/issues/5044&gt;</code>__)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience
properties to the result of <code>parse_url()</code>.
(<code>[#4945](https://github.com/urllib3/urllib3/issues/4945)
&lt;https://github.com/urllib3/urllib3/issues/4945&gt;</code>__)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>.
(<code>[#5092](https://github.com/urllib3/urllib3/issues/5092)
&lt;https://github.com/urllib3/urllib3/issues/5092&gt;</code>__)</li>
</ul>
<h2>Bugfixes</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/urllib3/urllib3/commit/b1d30ab61fe0db8f11092805e8c5ac43e091064a"><code>b1d30ab</code></a>
Release 2.8.0</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9016d7e8afc68185496ef07f3c3a4a743d04922e"><code>9016d7e</code></a>
Skip <code>test_read_chunked_with_trailing_data_does_not_hang</code> for
brotlicffi (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5258">#5258</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9101f581a8b3659af23b6ff335ae77200ca33533"><code>9101f58</code></a>
Fix <code>nox -s docs</code> warning (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5256">#5256</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/cd770b059b543be29298ea5c52afb0b1b090f5ed"><code>cd770b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/ea2ad7b21a80da3632f80016526a18864586077f"><code>ea2ad7b</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/0716e31534345dc1599ea95d903c79f276239bd8"><code>0716e31</code></a>
Fix loading unencrypted client keys with a password in pyOpenSSL (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5255">#5255</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/43c68c8b43a9dcb44ed2cf4ec91384ca0d46b37d"><code>43c68c8</code></a>
Test pickling of <code>InvalidChunkLength</code> (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5247">#5247</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/308b279b3fb28e7bee952e152ec5baeb5bfd0817"><code>308b279</code></a>
Share security policy between GitHub and Read the Docs (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5253">#5253</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/53fa0731b27d4b71ab0755ea5b896422d005d706"><code>53fa073</code></a>
Add policy on duplicate pull requests (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5252">#5252</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/5f2a6a843d0100d1351c3f94d58581ca98d17267"><code>5f2a6a8</code></a>
Assert on the ALPN extension in test_tunnel_sets_http_11_alpn (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5232">#5232</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 11:43:23 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3b969324db chore(deps): bump urllib3 from 2.7.0 to 2.8.0 in /libs/checkpoint-sqlite (#9135)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.8.0</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project. If your company or
organization uses Python and would benefit from HTTP/2 support in
Requests, pip, cloud SDKs, and thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden. (High severity, GHSA-8988-9cw3-xx77)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size line of unbounded length in memory. (High
severity, GHSA-vxq7-64xx-v4gw)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity, GHSA-gh4c-6fx4-qh6g)</li>
</ul>
<blockquote>
<p>[!IMPORTANT]
urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.</p>
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>. Destination client certificates
and identity overrides no longer apply to HTTPS forwarding proxy
connections.</p>
</blockquote>
<blockquote>
<p>[!NOTE]
CVE IDs had not yet been assigned to these advisories at the time of
release due to a backlog at GitHub's CNA.</p>
</blockquote>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option <code>allowed_methods</code> to retry any verb. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5044">#5044</a>)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience properties to the
result of <code>parse_url()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4945">#4945</a>)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5092">#5092</a>)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>
<p>Fixed response header handling to replace obsolete folded header
lines (<code>obs-fold</code>) with spaces in accordance with RFC 9112,
preventing raw CRLF sequences from appearing in header values such as
<code>Set-Cookie</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/1362">#1362</a>)</p>
</li>
<li>
<p>Fixed usage of <code>proxy_ssl_context</code> with
<code>ProxyManager</code> when
<code>use_forwarding_for_https=True</code>. Passing
<code>ssl_context</code> instead of <code>proxy_ssl_context</code> for
HTTPS proxies in this configuration now emits a
<code>FutureWarning</code> and will raise an error in v3.0. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/2577">#2577</a>)</p>
</li>
<li>
<p>Changed behavior of the default <code>ConnectionPool.pool</code>
initialization. <code>LifoQueue</code> is now resolved from the
<code>queue</code> module after the <code>ConnectionPool</code> is
instantiated instead of using the default cached <code>QueueCls</code>
class property. This is done because sometimes the
<code>queue.LifoQueue</code> is monkey-patched late in the program, such
as by gevent. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3289">#3289</a>)</p>
</li>
<li>
<p>Raised <code>UnrewindableBodyError</code> instead of
<code>ValueError</code> when retrying a request whose body had
<code>tell()</code> but not <code>seek()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3779">#3779</a>)</p>
</li>
<li>
<p>Decoded percent-encoded SOCKS proxy credentials before authenticating
with the proxy server. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3785">#3785</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPResponse.drain_conn()</code> to discard unread
response data in 64 KiB chunks (same as the default <code>amt</code>
when doing <code>HTTPResponse.stream(...)</code>). (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5019">#5019</a>)</p>
</li>
<li>
<p>Fixed <code>is_ipaddress()</code> to detect non-standard IPv4 forms
accepted by <code>socket.connect</code>, such as hex
(<code>0x7f000001</code>), octal (<code>0177.0.0.1</code>), and decimal
integers (<code>2130706433</code>), ensuring SSL certificate
verification uses the correct mode for these addresses. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5029">#5029</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen</code> raising a misleading
<code>FullPoolError</code> instead of <code>ValueError</code> when
called with an invalid <code>timeout</code> argument on a pool created
with <code>block=True</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5059">#5059</a>)</p>
</li>
<li>
<p>Fixed port-zero handling to preserve explicit <code>:0</code> values
instead of substituting the default ports 80 or 443 in URL parsing, pool
selection, proxy configuration, <code>connection_from_url()</code>, and
HTTP/2 request authority. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5071">#5071</a>,
<a
href="https://redirect.github.com/urllib3/urllib3/issues/5101">#5101</a>)</p>
</li>
<li>
<p>Fixed a bug where <code>PoolManager</code> passed the
<code>assert_hostname</code> and <code>assert_fingerprint</code>
parameters to HTTP connection pools. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5077">#5077</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen()</code> and HTTP proxy
forwarding to strip URL fragments from absolute request targets before
sending requests. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5079">#5079</a>)</p>
</li>
<li>
<p>Added safeguards to the proxy tunneling code to prevent potential
security issues when handling invalid characters in the proxy host and
HTTP headers. This change affects users of Python 3.10, Python 3.11, and
Python 3.12 when the standard library does not contain the fix; those on
newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the
same security fixes. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5091">#5091</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPSConnection.connect()</code> overriding
<code>ProxyConfig.ssl_context</code>'s certificate policy and proxy
identity checks with the target connection's TLS settings when
forwarding through an HTTPS proxy.</p>
<p><code>HTTPSConnection</code> no longer applies target SNI,
assertions, or client credentials to forwarding proxy handshakes and
continues to use its <code>ssl_context</code> as a fallback when an
HTTPS proxy forwards an HTTP target. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5093">#5093</a>)</p>
</li>
<li>
<p>Fixed URL parsing to more strictly enforce RFC 3986 host syntax,
rejecting invalid host input such as raw spaces and control characters,
malformed percent-encodings, and percent-encoded control characters in
HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel
targets. Host normalization now also follows RFC 3986 normalization
rules for percent-encoded octets by decoding percent-encoded unreserved
characters and uppercasing the hexadecimal digits of retained
percent-encoded octets. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5095">#5095</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.8.0 (2026-09-15)</h1>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden.
(High severity, <code>GHSA-8988-9cw3-xx77
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77&gt;</code>__)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size
line of unbounded length in memory. (High severity,
<code>GHSA-vxq7-64xx-v4gw
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw&gt;</code>__)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity,
<code>GHSA-gh4c-6fx4-qh6g
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g&gt;</code>__)</li>
</ul>
<p>.. caution::</p>
<pre><code>urllib3 2.8.0 fixes HTTPS proxy TLS configuration being
ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>.
Destination client certificates and identity overrides no longer
apply to HTTPS forwarding proxy connections.
</code></pre></p>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option
<code>allowed_methods</code> to retry any verb.
(<code>[#5044](https://github.com/urllib3/urllib3/issues/5044)
&lt;https://github.com/urllib3/urllib3/issues/5044&gt;</code>__)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience
properties to the result of <code>parse_url()</code>.
(<code>[#4945](https://github.com/urllib3/urllib3/issues/4945)
&lt;https://github.com/urllib3/urllib3/issues/4945&gt;</code>__)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>.
(<code>[#5092](https://github.com/urllib3/urllib3/issues/5092)
&lt;https://github.com/urllib3/urllib3/issues/5092&gt;</code>__)</li>
</ul>
<h2>Bugfixes</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/urllib3/urllib3/commit/b1d30ab61fe0db8f11092805e8c5ac43e091064a"><code>b1d30ab</code></a>
Release 2.8.0</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9016d7e8afc68185496ef07f3c3a4a743d04922e"><code>9016d7e</code></a>
Skip <code>test_read_chunked_with_trailing_data_does_not_hang</code> for
brotlicffi (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5258">#5258</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9101f581a8b3659af23b6ff335ae77200ca33533"><code>9101f58</code></a>
Fix <code>nox -s docs</code> warning (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5256">#5256</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/cd770b059b543be29298ea5c52afb0b1b090f5ed"><code>cd770b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/ea2ad7b21a80da3632f80016526a18864586077f"><code>ea2ad7b</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/0716e31534345dc1599ea95d903c79f276239bd8"><code>0716e31</code></a>
Fix loading unencrypted client keys with a password in pyOpenSSL (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5255">#5255</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/43c68c8b43a9dcb44ed2cf4ec91384ca0d46b37d"><code>43c68c8</code></a>
Test pickling of <code>InvalidChunkLength</code> (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5247">#5247</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/308b279b3fb28e7bee952e152ec5baeb5bfd0817"><code>308b279</code></a>
Share security policy between GitHub and Read the Docs (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5253">#5253</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/53fa0731b27d4b71ab0755ea5b896422d005d706"><code>53fa073</code></a>
Add policy on duplicate pull requests (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5252">#5252</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/5f2a6a843d0100d1351c3f94d58581ca98d17267"><code>5f2a6a8</code></a>
Assert on the ALPN extension in test_tunnel_sets_http_11_alpn (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5232">#5232</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=uv&previous-version=2.7.0&new-version=2.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 11:43:08 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e43f0f5f1e chore(deps): bump urllib3 from 2.7.0 to 2.8.0 in /libs/sdk-py (#9134)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.8.0</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project. If your company or
organization uses Python and would benefit from HTTP/2 support in
Requests, pip, cloud SDKs, and thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden. (High severity, GHSA-8988-9cw3-xx77)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size line of unbounded length in memory. (High
severity, GHSA-vxq7-64xx-v4gw)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity, GHSA-gh4c-6fx4-qh6g)</li>
</ul>
<blockquote>
<p>[!IMPORTANT]
urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.</p>
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>. Destination client certificates
and identity overrides no longer apply to HTTPS forwarding proxy
connections.</p>
</blockquote>
<blockquote>
<p>[!NOTE]
CVE IDs had not yet been assigned to these advisories at the time of
release due to a backlog at GitHub's CNA.</p>
</blockquote>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option <code>allowed_methods</code> to retry any verb. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5044">#5044</a>)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience properties to the
result of <code>parse_url()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4945">#4945</a>)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5092">#5092</a>)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>
<p>Fixed response header handling to replace obsolete folded header
lines (<code>obs-fold</code>) with spaces in accordance with RFC 9112,
preventing raw CRLF sequences from appearing in header values such as
<code>Set-Cookie</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/1362">#1362</a>)</p>
</li>
<li>
<p>Fixed usage of <code>proxy_ssl_context</code> with
<code>ProxyManager</code> when
<code>use_forwarding_for_https=True</code>. Passing
<code>ssl_context</code> instead of <code>proxy_ssl_context</code> for
HTTPS proxies in this configuration now emits a
<code>FutureWarning</code> and will raise an error in v3.0. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/2577">#2577</a>)</p>
</li>
<li>
<p>Changed behavior of the default <code>ConnectionPool.pool</code>
initialization. <code>LifoQueue</code> is now resolved from the
<code>queue</code> module after the <code>ConnectionPool</code> is
instantiated instead of using the default cached <code>QueueCls</code>
class property. This is done because sometimes the
<code>queue.LifoQueue</code> is monkey-patched late in the program, such
as by gevent. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3289">#3289</a>)</p>
</li>
<li>
<p>Raised <code>UnrewindableBodyError</code> instead of
<code>ValueError</code> when retrying a request whose body had
<code>tell()</code> but not <code>seek()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3779">#3779</a>)</p>
</li>
<li>
<p>Decoded percent-encoded SOCKS proxy credentials before authenticating
with the proxy server. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3785">#3785</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPResponse.drain_conn()</code> to discard unread
response data in 64 KiB chunks (same as the default <code>amt</code>
when doing <code>HTTPResponse.stream(...)</code>). (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5019">#5019</a>)</p>
</li>
<li>
<p>Fixed <code>is_ipaddress()</code> to detect non-standard IPv4 forms
accepted by <code>socket.connect</code>, such as hex
(<code>0x7f000001</code>), octal (<code>0177.0.0.1</code>), and decimal
integers (<code>2130706433</code>), ensuring SSL certificate
verification uses the correct mode for these addresses. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5029">#5029</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen</code> raising a misleading
<code>FullPoolError</code> instead of <code>ValueError</code> when
called with an invalid <code>timeout</code> argument on a pool created
with <code>block=True</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5059">#5059</a>)</p>
</li>
<li>
<p>Fixed port-zero handling to preserve explicit <code>:0</code> values
instead of substituting the default ports 80 or 443 in URL parsing, pool
selection, proxy configuration, <code>connection_from_url()</code>, and
HTTP/2 request authority. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5071">#5071</a>,
<a
href="https://redirect.github.com/urllib3/urllib3/issues/5101">#5101</a>)</p>
</li>
<li>
<p>Fixed a bug where <code>PoolManager</code> passed the
<code>assert_hostname</code> and <code>assert_fingerprint</code>
parameters to HTTP connection pools. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5077">#5077</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen()</code> and HTTP proxy
forwarding to strip URL fragments from absolute request targets before
sending requests. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5079">#5079</a>)</p>
</li>
<li>
<p>Added safeguards to the proxy tunneling code to prevent potential
security issues when handling invalid characters in the proxy host and
HTTP headers. This change affects users of Python 3.10, Python 3.11, and
Python 3.12 when the standard library does not contain the fix; those on
newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the
same security fixes. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5091">#5091</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPSConnection.connect()</code> overriding
<code>ProxyConfig.ssl_context</code>'s certificate policy and proxy
identity checks with the target connection's TLS settings when
forwarding through an HTTPS proxy.</p>
<p><code>HTTPSConnection</code> no longer applies target SNI,
assertions, or client credentials to forwarding proxy handshakes and
continues to use its <code>ssl_context</code> as a fallback when an
HTTPS proxy forwards an HTTP target. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5093">#5093</a>)</p>
</li>
<li>
<p>Fixed URL parsing to more strictly enforce RFC 3986 host syntax,
rejecting invalid host input such as raw spaces and control characters,
malformed percent-encodings, and percent-encoded control characters in
HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel
targets. Host normalization now also follows RFC 3986 normalization
rules for percent-encoded octets by decoding percent-encoded unreserved
characters and uppercasing the hexadecimal digits of retained
percent-encoded octets. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5095">#5095</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.8.0 (2026-09-15)</h1>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden.
(High severity, <code>GHSA-8988-9cw3-xx77
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77&gt;</code>__)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size
line of unbounded length in memory. (High severity,
<code>GHSA-vxq7-64xx-v4gw
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw&gt;</code>__)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity,
<code>GHSA-gh4c-6fx4-qh6g
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g&gt;</code>__)</li>
</ul>
<p>.. caution::</p>
<pre><code>urllib3 2.8.0 fixes HTTPS proxy TLS configuration being
ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>.
Destination client certificates and identity overrides no longer
apply to HTTPS forwarding proxy connections.
</code></pre></p>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option
<code>allowed_methods</code> to retry any verb.
(<code>[#5044](https://github.com/urllib3/urllib3/issues/5044)
&lt;https://github.com/urllib3/urllib3/issues/5044&gt;</code>__)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience
properties to the result of <code>parse_url()</code>.
(<code>[#4945](https://github.com/urllib3/urllib3/issues/4945)
&lt;https://github.com/urllib3/urllib3/issues/4945&gt;</code>__)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>.
(<code>[#5092](https://github.com/urllib3/urllib3/issues/5092)
&lt;https://github.com/urllib3/urllib3/issues/5092&gt;</code>__)</li>
</ul>
<h2>Bugfixes</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/urllib3/urllib3/commit/b1d30ab61fe0db8f11092805e8c5ac43e091064a"><code>b1d30ab</code></a>
Release 2.8.0</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9016d7e8afc68185496ef07f3c3a4a743d04922e"><code>9016d7e</code></a>
Skip <code>test_read_chunked_with_trailing_data_does_not_hang</code> for
brotlicffi (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5258">#5258</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9101f581a8b3659af23b6ff335ae77200ca33533"><code>9101f58</code></a>
Fix <code>nox -s docs</code> warning (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5256">#5256</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/cd770b059b543be29298ea5c52afb0b1b090f5ed"><code>cd770b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/ea2ad7b21a80da3632f80016526a18864586077f"><code>ea2ad7b</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/0716e31534345dc1599ea95d903c79f276239bd8"><code>0716e31</code></a>
Fix loading unencrypted client keys with a password in pyOpenSSL (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5255">#5255</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/43c68c8b43a9dcb44ed2cf4ec91384ca0d46b37d"><code>43c68c8</code></a>
Test pickling of <code>InvalidChunkLength</code> (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5247">#5247</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/308b279b3fb28e7bee952e152ec5baeb5bfd0817"><code>308b279</code></a>
Share security policy between GitHub and Read the Docs (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5253">#5253</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/53fa0731b27d4b71ab0755ea5b896422d005d706"><code>53fa073</code></a>
Add policy on duplicate pull requests (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5252">#5252</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/5f2a6a843d0100d1351c3f94d58581ca98d17267"><code>5f2a6a8</code></a>
Assert on the ALPN extension in test_tunnel_sets_http_11_alpn (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5232">#5232</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=uv&previous-version=2.7.0&new-version=2.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 11:42:51 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8ccdedcc1b chore(deps): bump urllib3 from 2.7.0 to 2.8.0 in /libs/checkpoint-postgres (#9132)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.8.0</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project. If your company or
organization uses Python and would benefit from HTTP/2 support in
Requests, pip, cloud SDKs, and thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden. (High severity, GHSA-8988-9cw3-xx77)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size line of unbounded length in memory. (High
severity, GHSA-vxq7-64xx-v4gw)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity, GHSA-gh4c-6fx4-qh6g)</li>
</ul>
<blockquote>
<p>[!IMPORTANT]
urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.</p>
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>. Destination client certificates
and identity overrides no longer apply to HTTPS forwarding proxy
connections.</p>
</blockquote>
<blockquote>
<p>[!NOTE]
CVE IDs had not yet been assigned to these advisories at the time of
release due to a backlog at GitHub's CNA.</p>
</blockquote>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option <code>allowed_methods</code> to retry any verb. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5044">#5044</a>)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience properties to the
result of <code>parse_url()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4945">#4945</a>)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5092">#5092</a>)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>
<p>Fixed response header handling to replace obsolete folded header
lines (<code>obs-fold</code>) with spaces in accordance with RFC 9112,
preventing raw CRLF sequences from appearing in header values such as
<code>Set-Cookie</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/1362">#1362</a>)</p>
</li>
<li>
<p>Fixed usage of <code>proxy_ssl_context</code> with
<code>ProxyManager</code> when
<code>use_forwarding_for_https=True</code>. Passing
<code>ssl_context</code> instead of <code>proxy_ssl_context</code> for
HTTPS proxies in this configuration now emits a
<code>FutureWarning</code> and will raise an error in v3.0. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/2577">#2577</a>)</p>
</li>
<li>
<p>Changed behavior of the default <code>ConnectionPool.pool</code>
initialization. <code>LifoQueue</code> is now resolved from the
<code>queue</code> module after the <code>ConnectionPool</code> is
instantiated instead of using the default cached <code>QueueCls</code>
class property. This is done because sometimes the
<code>queue.LifoQueue</code> is monkey-patched late in the program, such
as by gevent. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3289">#3289</a>)</p>
</li>
<li>
<p>Raised <code>UnrewindableBodyError</code> instead of
<code>ValueError</code> when retrying a request whose body had
<code>tell()</code> but not <code>seek()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3779">#3779</a>)</p>
</li>
<li>
<p>Decoded percent-encoded SOCKS proxy credentials before authenticating
with the proxy server. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3785">#3785</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPResponse.drain_conn()</code> to discard unread
response data in 64 KiB chunks (same as the default <code>amt</code>
when doing <code>HTTPResponse.stream(...)</code>). (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5019">#5019</a>)</p>
</li>
<li>
<p>Fixed <code>is_ipaddress()</code> to detect non-standard IPv4 forms
accepted by <code>socket.connect</code>, such as hex
(<code>0x7f000001</code>), octal (<code>0177.0.0.1</code>), and decimal
integers (<code>2130706433</code>), ensuring SSL certificate
verification uses the correct mode for these addresses. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5029">#5029</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen</code> raising a misleading
<code>FullPoolError</code> instead of <code>ValueError</code> when
called with an invalid <code>timeout</code> argument on a pool created
with <code>block=True</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5059">#5059</a>)</p>
</li>
<li>
<p>Fixed port-zero handling to preserve explicit <code>:0</code> values
instead of substituting the default ports 80 or 443 in URL parsing, pool
selection, proxy configuration, <code>connection_from_url()</code>, and
HTTP/2 request authority. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5071">#5071</a>,
<a
href="https://redirect.github.com/urllib3/urllib3/issues/5101">#5101</a>)</p>
</li>
<li>
<p>Fixed a bug where <code>PoolManager</code> passed the
<code>assert_hostname</code> and <code>assert_fingerprint</code>
parameters to HTTP connection pools. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5077">#5077</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen()</code> and HTTP proxy
forwarding to strip URL fragments from absolute request targets before
sending requests. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5079">#5079</a>)</p>
</li>
<li>
<p>Added safeguards to the proxy tunneling code to prevent potential
security issues when handling invalid characters in the proxy host and
HTTP headers. This change affects users of Python 3.10, Python 3.11, and
Python 3.12 when the standard library does not contain the fix; those on
newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the
same security fixes. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5091">#5091</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPSConnection.connect()</code> overriding
<code>ProxyConfig.ssl_context</code>'s certificate policy and proxy
identity checks with the target connection's TLS settings when
forwarding through an HTTPS proxy.</p>
<p><code>HTTPSConnection</code> no longer applies target SNI,
assertions, or client credentials to forwarding proxy handshakes and
continues to use its <code>ssl_context</code> as a fallback when an
HTTPS proxy forwards an HTTP target. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5093">#5093</a>)</p>
</li>
<li>
<p>Fixed URL parsing to more strictly enforce RFC 3986 host syntax,
rejecting invalid host input such as raw spaces and control characters,
malformed percent-encodings, and percent-encoded control characters in
HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel
targets. Host normalization now also follows RFC 3986 normalization
rules for percent-encoded octets by decoding percent-encoded unreserved
characters and uppercasing the hexadecimal digits of retained
percent-encoded octets. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5095">#5095</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.8.0 (2026-09-15)</h1>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden.
(High severity, <code>GHSA-8988-9cw3-xx77
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77&gt;</code>__)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size
line of unbounded length in memory. (High severity,
<code>GHSA-vxq7-64xx-v4gw
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw&gt;</code>__)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity,
<code>GHSA-gh4c-6fx4-qh6g
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g&gt;</code>__)</li>
</ul>
<p>.. caution::</p>
<pre><code>urllib3 2.8.0 fixes HTTPS proxy TLS configuration being
ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>.
Destination client certificates and identity overrides no longer
apply to HTTPS forwarding proxy connections.
</code></pre></p>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option
<code>allowed_methods</code> to retry any verb.
(<code>[#5044](https://github.com/urllib3/urllib3/issues/5044)
&lt;https://github.com/urllib3/urllib3/issues/5044&gt;</code>__)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience
properties to the result of <code>parse_url()</code>.
(<code>[#4945](https://github.com/urllib3/urllib3/issues/4945)
&lt;https://github.com/urllib3/urllib3/issues/4945&gt;</code>__)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>.
(<code>[#5092](https://github.com/urllib3/urllib3/issues/5092)
&lt;https://github.com/urllib3/urllib3/issues/5092&gt;</code>__)</li>
</ul>
<h2>Bugfixes</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/urllib3/urllib3/commit/b1d30ab61fe0db8f11092805e8c5ac43e091064a"><code>b1d30ab</code></a>
Release 2.8.0</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9016d7e8afc68185496ef07f3c3a4a743d04922e"><code>9016d7e</code></a>
Skip <code>test_read_chunked_with_trailing_data_does_not_hang</code> for
brotlicffi (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5258">#5258</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9101f581a8b3659af23b6ff335ae77200ca33533"><code>9101f58</code></a>
Fix <code>nox -s docs</code> warning (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5256">#5256</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/cd770b059b543be29298ea5c52afb0b1b090f5ed"><code>cd770b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/ea2ad7b21a80da3632f80016526a18864586077f"><code>ea2ad7b</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/0716e31534345dc1599ea95d903c79f276239bd8"><code>0716e31</code></a>
Fix loading unencrypted client keys with a password in pyOpenSSL (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5255">#5255</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/43c68c8b43a9dcb44ed2cf4ec91384ca0d46b37d"><code>43c68c8</code></a>
Test pickling of <code>InvalidChunkLength</code> (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5247">#5247</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/308b279b3fb28e7bee952e152ec5baeb5bfd0817"><code>308b279</code></a>
Share security policy between GitHub and Read the Docs (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5253">#5253</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/53fa0731b27d4b71ab0755ea5b896422d005d706"><code>53fa073</code></a>
Add policy on duplicate pull requests (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5252">#5252</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/5f2a6a843d0100d1351c3f94d58581ca98d17267"><code>5f2a6a8</code></a>
Assert on the ALPN extension in test_tunnel_sets_http_11_alpn (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5232">#5232</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=uv&previous-version=2.7.0&new-version=2.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 11:42:38 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
7ea31e5e45 chore(deps): bump urllib3 from 2.7.0 to 2.8.0 in /libs/checkpoint (#9131)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.8.0</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project. If your company or
organization uses Python and would benefit from HTTP/2 support in
Requests, pip, cloud SDKs, and thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden. (High severity, GHSA-8988-9cw3-xx77)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size line of unbounded length in memory. (High
severity, GHSA-vxq7-64xx-v4gw)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity, GHSA-gh4c-6fx4-qh6g)</li>
</ul>
<blockquote>
<p>[!IMPORTANT]
urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.</p>
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>. Destination client certificates
and identity overrides no longer apply to HTTPS forwarding proxy
connections.</p>
</blockquote>
<blockquote>
<p>[!NOTE]
CVE IDs had not yet been assigned to these advisories at the time of
release due to a backlog at GitHub's CNA.</p>
</blockquote>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option <code>allowed_methods</code> to retry any verb. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5044">#5044</a>)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience properties to the
result of <code>parse_url()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4945">#4945</a>)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5092">#5092</a>)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>
<p>Fixed response header handling to replace obsolete folded header
lines (<code>obs-fold</code>) with spaces in accordance with RFC 9112,
preventing raw CRLF sequences from appearing in header values such as
<code>Set-Cookie</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/1362">#1362</a>)</p>
</li>
<li>
<p>Fixed usage of <code>proxy_ssl_context</code> with
<code>ProxyManager</code> when
<code>use_forwarding_for_https=True</code>. Passing
<code>ssl_context</code> instead of <code>proxy_ssl_context</code> for
HTTPS proxies in this configuration now emits a
<code>FutureWarning</code> and will raise an error in v3.0. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/2577">#2577</a>)</p>
</li>
<li>
<p>Changed behavior of the default <code>ConnectionPool.pool</code>
initialization. <code>LifoQueue</code> is now resolved from the
<code>queue</code> module after the <code>ConnectionPool</code> is
instantiated instead of using the default cached <code>QueueCls</code>
class property. This is done because sometimes the
<code>queue.LifoQueue</code> is monkey-patched late in the program, such
as by gevent. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3289">#3289</a>)</p>
</li>
<li>
<p>Raised <code>UnrewindableBodyError</code> instead of
<code>ValueError</code> when retrying a request whose body had
<code>tell()</code> but not <code>seek()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3779">#3779</a>)</p>
</li>
<li>
<p>Decoded percent-encoded SOCKS proxy credentials before authenticating
with the proxy server. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3785">#3785</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPResponse.drain_conn()</code> to discard unread
response data in 64 KiB chunks (same as the default <code>amt</code>
when doing <code>HTTPResponse.stream(...)</code>). (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5019">#5019</a>)</p>
</li>
<li>
<p>Fixed <code>is_ipaddress()</code> to detect non-standard IPv4 forms
accepted by <code>socket.connect</code>, such as hex
(<code>0x7f000001</code>), octal (<code>0177.0.0.1</code>), and decimal
integers (<code>2130706433</code>), ensuring SSL certificate
verification uses the correct mode for these addresses. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5029">#5029</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen</code> raising a misleading
<code>FullPoolError</code> instead of <code>ValueError</code> when
called with an invalid <code>timeout</code> argument on a pool created
with <code>block=True</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5059">#5059</a>)</p>
</li>
<li>
<p>Fixed port-zero handling to preserve explicit <code>:0</code> values
instead of substituting the default ports 80 or 443 in URL parsing, pool
selection, proxy configuration, <code>connection_from_url()</code>, and
HTTP/2 request authority. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5071">#5071</a>,
<a
href="https://redirect.github.com/urllib3/urllib3/issues/5101">#5101</a>)</p>
</li>
<li>
<p>Fixed a bug where <code>PoolManager</code> passed the
<code>assert_hostname</code> and <code>assert_fingerprint</code>
parameters to HTTP connection pools. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5077">#5077</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen()</code> and HTTP proxy
forwarding to strip URL fragments from absolute request targets before
sending requests. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5079">#5079</a>)</p>
</li>
<li>
<p>Added safeguards to the proxy tunneling code to prevent potential
security issues when handling invalid characters in the proxy host and
HTTP headers. This change affects users of Python 3.10, Python 3.11, and
Python 3.12 when the standard library does not contain the fix; those on
newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the
same security fixes. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5091">#5091</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPSConnection.connect()</code> overriding
<code>ProxyConfig.ssl_context</code>'s certificate policy and proxy
identity checks with the target connection's TLS settings when
forwarding through an HTTPS proxy.</p>
<p><code>HTTPSConnection</code> no longer applies target SNI,
assertions, or client credentials to forwarding proxy handshakes and
continues to use its <code>ssl_context</code> as a fallback when an
HTTPS proxy forwards an HTTP target. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5093">#5093</a>)</p>
</li>
<li>
<p>Fixed URL parsing to more strictly enforce RFC 3986 host syntax,
rejecting invalid host input such as raw spaces and control characters,
malformed percent-encodings, and percent-encoded control characters in
HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel
targets. Host normalization now also follows RFC 3986 normalization
rules for percent-encoded octets by decoding percent-encoded unreserved
characters and uppercasing the hexadecimal digits of retained
percent-encoded octets. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5095">#5095</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.8.0 (2026-09-15)</h1>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden.
(High severity, <code>GHSA-8988-9cw3-xx77
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77&gt;</code>__)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size
line of unbounded length in memory. (High severity,
<code>GHSA-vxq7-64xx-v4gw
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw&gt;</code>__)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity,
<code>GHSA-gh4c-6fx4-qh6g
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g&gt;</code>__)</li>
</ul>
<p>.. caution::</p>
<pre><code>urllib3 2.8.0 fixes HTTPS proxy TLS configuration being
ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>.
Destination client certificates and identity overrides no longer
apply to HTTPS forwarding proxy connections.
</code></pre></p>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option
<code>allowed_methods</code> to retry any verb.
(<code>[#5044](https://github.com/urllib3/urllib3/issues/5044)
&lt;https://github.com/urllib3/urllib3/issues/5044&gt;</code>__)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience
properties to the result of <code>parse_url()</code>.
(<code>[#4945](https://github.com/urllib3/urllib3/issues/4945)
&lt;https://github.com/urllib3/urllib3/issues/4945&gt;</code>__)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>.
(<code>[#5092](https://github.com/urllib3/urllib3/issues/5092)
&lt;https://github.com/urllib3/urllib3/issues/5092&gt;</code>__)</li>
</ul>
<h2>Bugfixes</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/urllib3/urllib3/commit/b1d30ab61fe0db8f11092805e8c5ac43e091064a"><code>b1d30ab</code></a>
Release 2.8.0</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9016d7e8afc68185496ef07f3c3a4a743d04922e"><code>9016d7e</code></a>
Skip <code>test_read_chunked_with_trailing_data_does_not_hang</code> for
brotlicffi (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5258">#5258</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9101f581a8b3659af23b6ff335ae77200ca33533"><code>9101f58</code></a>
Fix <code>nox -s docs</code> warning (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5256">#5256</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/cd770b059b543be29298ea5c52afb0b1b090f5ed"><code>cd770b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/ea2ad7b21a80da3632f80016526a18864586077f"><code>ea2ad7b</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/0716e31534345dc1599ea95d903c79f276239bd8"><code>0716e31</code></a>
Fix loading unencrypted client keys with a password in pyOpenSSL (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5255">#5255</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/43c68c8b43a9dcb44ed2cf4ec91384ca0d46b37d"><code>43c68c8</code></a>
Test pickling of <code>InvalidChunkLength</code> (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5247">#5247</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/308b279b3fb28e7bee952e152ec5baeb5bfd0817"><code>308b279</code></a>
Share security policy between GitHub and Read the Docs (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5253">#5253</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/53fa0731b27d4b71ab0755ea5b896422d005d706"><code>53fa073</code></a>
Add policy on duplicate pull requests (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5252">#5252</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/5f2a6a843d0100d1351c3f94d58581ca98d17267"><code>5f2a6a8</code></a>
Assert on the ALPN extension in test_tunnel_sets_http_11_alpn (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5232">#5232</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=uv&previous-version=2.7.0&new-version=2.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 11:42:23 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
313e0e7e0a chore(deps): bump urllib3 from 2.7.0 to 2.8.0 in /libs/prebuilt (#9130)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.8.0</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project. If your company or
organization uses Python and would benefit from HTTP/2 support in
Requests, pip, cloud SDKs, and thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden. (High severity, GHSA-8988-9cw3-xx77)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size line of unbounded length in memory. (High
severity, GHSA-vxq7-64xx-v4gw)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity, GHSA-gh4c-6fx4-qh6g)</li>
</ul>
<blockquote>
<p>[!IMPORTANT]
urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.</p>
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>. Destination client certificates
and identity overrides no longer apply to HTTPS forwarding proxy
connections.</p>
</blockquote>
<blockquote>
<p>[!NOTE]
CVE IDs had not yet been assigned to these advisories at the time of
release due to a backlog at GitHub's CNA.</p>
</blockquote>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option <code>allowed_methods</code> to retry any verb. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5044">#5044</a>)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience properties to the
result of <code>parse_url()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/4945">#4945</a>)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5092">#5092</a>)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>
<p>Fixed response header handling to replace obsolete folded header
lines (<code>obs-fold</code>) with spaces in accordance with RFC 9112,
preventing raw CRLF sequences from appearing in header values such as
<code>Set-Cookie</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/1362">#1362</a>)</p>
</li>
<li>
<p>Fixed usage of <code>proxy_ssl_context</code> with
<code>ProxyManager</code> when
<code>use_forwarding_for_https=True</code>. Passing
<code>ssl_context</code> instead of <code>proxy_ssl_context</code> for
HTTPS proxies in this configuration now emits a
<code>FutureWarning</code> and will raise an error in v3.0. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/2577">#2577</a>)</p>
</li>
<li>
<p>Changed behavior of the default <code>ConnectionPool.pool</code>
initialization. <code>LifoQueue</code> is now resolved from the
<code>queue</code> module after the <code>ConnectionPool</code> is
instantiated instead of using the default cached <code>QueueCls</code>
class property. This is done because sometimes the
<code>queue.LifoQueue</code> is monkey-patched late in the program, such
as by gevent. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3289">#3289</a>)</p>
</li>
<li>
<p>Raised <code>UnrewindableBodyError</code> instead of
<code>ValueError</code> when retrying a request whose body had
<code>tell()</code> but not <code>seek()</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3779">#3779</a>)</p>
</li>
<li>
<p>Decoded percent-encoded SOCKS proxy credentials before authenticating
with the proxy server. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3785">#3785</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPResponse.drain_conn()</code> to discard unread
response data in 64 KiB chunks (same as the default <code>amt</code>
when doing <code>HTTPResponse.stream(...)</code>). (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5019">#5019</a>)</p>
</li>
<li>
<p>Fixed <code>is_ipaddress()</code> to detect non-standard IPv4 forms
accepted by <code>socket.connect</code>, such as hex
(<code>0x7f000001</code>), octal (<code>0177.0.0.1</code>), and decimal
integers (<code>2130706433</code>), ensuring SSL certificate
verification uses the correct mode for these addresses. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5029">#5029</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen</code> raising a misleading
<code>FullPoolError</code> instead of <code>ValueError</code> when
called with an invalid <code>timeout</code> argument on a pool created
with <code>block=True</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5059">#5059</a>)</p>
</li>
<li>
<p>Fixed port-zero handling to preserve explicit <code>:0</code> values
instead of substituting the default ports 80 or 443 in URL parsing, pool
selection, proxy configuration, <code>connection_from_url()</code>, and
HTTP/2 request authority. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5071">#5071</a>,
<a
href="https://redirect.github.com/urllib3/urllib3/issues/5101">#5101</a>)</p>
</li>
<li>
<p>Fixed a bug where <code>PoolManager</code> passed the
<code>assert_hostname</code> and <code>assert_fingerprint</code>
parameters to HTTP connection pools. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5077">#5077</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPConnectionPool.urlopen()</code> and HTTP proxy
forwarding to strip URL fragments from absolute request targets before
sending requests. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5079">#5079</a>)</p>
</li>
<li>
<p>Added safeguards to the proxy tunneling code to prevent potential
security issues when handling invalid characters in the proxy host and
HTTP headers. This change affects users of Python 3.10, Python 3.11, and
Python 3.12 when the standard library does not contain the fix; those on
newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the
same security fixes. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5091">#5091</a>)</p>
</li>
<li>
<p>Fixed <code>HTTPSConnection.connect()</code> overriding
<code>ProxyConfig.ssl_context</code>'s certificate policy and proxy
identity checks with the target connection's TLS settings when
forwarding through an HTTPS proxy.</p>
<p><code>HTTPSConnection</code> no longer applies target SNI,
assertions, or client credentials to forwarding proxy handshakes and
continues to use its <code>ssl_context</code> as a fallback when an
HTTPS proxy forwards an HTTP target. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5093">#5093</a>)</p>
</li>
<li>
<p>Fixed URL parsing to more strictly enforce RFC 3986 host syntax,
rejecting invalid host input such as raw spaces and control characters,
malformed percent-encodings, and percent-encoded control characters in
HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel
targets. Host normalization now also follows RFC 3986 normalization
rules for percent-encoded octets by decoding percent-encoded unreserved
characters and uppercasing the hexadecimal digits of retained
percent-encoded octets. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5095">#5095</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.8.0 (2026-09-15)</h1>
<h2>Security</h2>
<p>Fixed the following security issues:</p>
<ul>
<li>The TLS configuration for HTTPS proxies could be ignored or
overridden.
(High severity, <code>GHSA-8988-9cw3-xx77
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77&gt;</code>__)</li>
<li><code>HTTPResponse.stream()</code> and <code>read_chunked()</code>
could buffer a chunk-size
line of unbounded length in memory. (High severity,
<code>GHSA-vxq7-64xx-v4gw
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw&gt;</code>__)</li>
<li>Chunked Deflate streaming could enter an infinite loop. (Medium
severity,
<code>GHSA-gh4c-6fx4-qh6g
&lt;https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g&gt;</code>__)</li>
</ul>
<p>.. caution::</p>
<pre><code>urllib3 2.8.0 fixes HTTPS proxy TLS configuration being
ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.
<p>Configure proxy CA certificates and client certificates in
<code>proxy_ssl_context</code>, and proxy identity checks with
<code>proxy_assert_hostname</code> or
<code>proxy_assert_fingerprint</code>.
Destination client certificates and identity overrides no longer
apply to HTTPS forwarding proxy connections.
</code></pre></p>
<h2>Deprecations &amp; Removals</h2>
<ul>
<li>Deprecated using an empty collection as the <code>Retry</code>
option
<code>allowed_methods</code> to retry any verb.
(<code>[#5044](https://github.com/urllib3/urllib3/issues/5044)
&lt;https://github.com/urllib3/urllib3/issues/5044&gt;</code>__)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Added <code>Url.auth_decoded</code> and
<code>Url.auth_decoded_joined</code> convenience
properties to the result of <code>parse_url()</code>.
(<code>[#4945](https://github.com/urllib3/urllib3/issues/4945)
&lt;https://github.com/urllib3/urllib3/issues/4945&gt;</code>__)</li>
<li>Added <code>basic_auth_encoding</code> and
<code>proxy_basic_auth_encoding</code> parameters to
<code>urllib3.util.make_headers()</code>.
(<code>[#5092](https://github.com/urllib3/urllib3/issues/5092)
&lt;https://github.com/urllib3/urllib3/issues/5092&gt;</code>__)</li>
</ul>
<h2>Bugfixes</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/urllib3/urllib3/commit/b1d30ab61fe0db8f11092805e8c5ac43e091064a"><code>b1d30ab</code></a>
Release 2.8.0</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9016d7e8afc68185496ef07f3c3a4a743d04922e"><code>9016d7e</code></a>
Skip <code>test_read_chunked_with_trailing_data_does_not_hang</code> for
brotlicffi (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5258">#5258</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9101f581a8b3659af23b6ff335ae77200ca33533"><code>9101f58</code></a>
Fix <code>nox -s docs</code> warning (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5256">#5256</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/cd770b059b543be29298ea5c52afb0b1b090f5ed"><code>cd770b0</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/ea2ad7b21a80da3632f80016526a18864586077f"><code>ea2ad7b</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/0716e31534345dc1599ea95d903c79f276239bd8"><code>0716e31</code></a>
Fix loading unencrypted client keys with a password in pyOpenSSL (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5255">#5255</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/43c68c8b43a9dcb44ed2cf4ec91384ca0d46b37d"><code>43c68c8</code></a>
Test pickling of <code>InvalidChunkLength</code> (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5247">#5247</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/308b279b3fb28e7bee952e152ec5baeb5bfd0817"><code>308b279</code></a>
Share security policy between GitHub and Read the Docs (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5253">#5253</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/53fa0731b27d4b71ab0755ea5b896422d005d706"><code>53fa073</code></a>
Add policy on duplicate pull requests (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5252">#5252</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/5f2a6a843d0100d1351c3f94d58581ca98d17267"><code>5f2a6a8</code></a>
Assert on the ALPN extension in test_tunnel_sets_http_11_alpn (<a
href="https://redirect.github.com/urllib3/urllib3/issues/5232">#5232</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=uv&previous-version=2.7.0&new-version=2.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 11:42:08 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b9919ace32 chore(deps): bump pyjwt from 2.13.0 to 2.15.0 in /libs/cli (#9129)
Bumps [pyjwt](https://github.com/jpadilla/pyjwt) from 2.13.0 to 2.15.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jpadilla/pyjwt/releases">pyjwt's
releases</a>.</em></p>
<blockquote>
<h2>2.15.0</h2>
<p>See the <a
href="https://github.com/jpadilla/pyjwt/blob/2.15.0/CHANGELOG.rst">2.15.0
changelog</a> for complete release details.</p>
<h2>2.14.0</h2>
<p>See the <a
href="https://github.com/jpadilla/pyjwt/blob/2.14.0/CHANGELOG.rst">2.14.0
changelog</a> for the complete release details and related security
advisories.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst">pyjwt's
changelog</a>.</em></p>
<blockquote>
<h2><code>v2.15.0
&lt;https://github.com/jpadilla/pyjwt/compare/2.14.0...2.15.0&gt;</code>__</h2>
<p>Security</p>
<pre><code>
- Wrap recursion errors from deeply nested JWT payloads in
``DecodeError``
  instead of exposing a raw ``RecursionError``.
<p>Added</p>
<pre><code>
- Support Python 3.15 by @kytta in
`[#1202](https://github.com/jpadilla/pyjwt/issues/1202)
&amp;lt;https://github.com/jpadilla/pyjwt/pull/1202&amp;gt;`__

Changed
</code></pre>
<ul>
<li><code>JWKSetCache</code> now stores the parsed <code>PyJWKSet</code>
rather than the raw JWKS
payload, so a cache hit no longer re-parses every key.
<code>JWKSetCache.put()</code>
accepts either form and raises <code>PyJWKSetError</code> for anything
else. As a
result, <code>PyJWKClient.get_jwk_set()</code> returns the same
<code>PyJWKSet</code> instance
for as long as it stays cached, rather than a freshly built one per call
in
<code>[#1208](https://github.com/jpadilla/pyjwt/issues/1208)
&amp;lt;https://github.com/jpadilla/pyjwt/pull/1208&amp;gt;</code>__</li>
<li><code>PyJWKClient.fetch_data()</code> now raises
<code>PyJWKClientError(&amp;quot;The JWKS endpoint did not return a JSON
object&amp;quot;)</code> when
the endpoint response is not a JSON object, instead of returning it for
<code>get_jwk_set()</code> to reject. Callers reaching the JWKS through
<code>get_jwk_set()</code> see the same error as before in
<code>[#1208](https://github.com/jpadilla/pyjwt/issues/1208)
&amp;lt;https://github.com/jpadilla/pyjwt/pull/1208&amp;gt;</code>__</li>
</ul>
<p>Fixed</p>
<pre><code>
- Return cached ``PyJWKSet`` values from ``PyJWKClient.get_jwk_set()``
instead
of raising ``PyJWKClientError(&amp;quot;The JWKS endpoint did not return
a JSON
object&amp;quot;)``. ``JWKSetCache.put()`` documents ``PyJWKSet`` as the
cached value,
so callers pre-populating the cache to avoid a network round-trip could
not
read it back in `[#914](https://github.com/jpadilla/pyjwt/issues/914)
&amp;lt;https://github.com/jpadilla/pyjwt/issues/914&amp;gt;`__ and
`[#1208](https://github.com/jpadilla/pyjwt/issues/1208)
&amp;lt;https://github.com/jpadilla/pyjwt/pull/1208&amp;gt;`__
- ``PyJWKClient.get_jwk_set()`` now caches the key set it returns, so a
``fetch_data()`` override that filters or transforms the JWKS is no
longer
  undone by the next cache hit in
`[#1208](https://github.com/jpadilla/pyjwt/issues/1208)
&amp;lt;https://github.com/jpadilla/pyjwt/pull/1208&amp;gt;`__
- Raise the documented ``PyJWTError`` subclass instead of leaking a
  ``TypeError`` when the ``exp``, ``nbf``, or ``iat`` claim decodes to a
  non-numeric, non-string value such as a list, dict, or ``null``.
- Reject OKP JWK private keys when their public ``x`` component does not
  match the private ``d`` component.
- Treat malformed JWK Set members as unusable keys rather than letting
``AttributeError`` or ``TypeError`` escape ``PyJWKSet``. A member that
is not
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;... (truncated)&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;Commits&lt;/summary&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/1d41a6478e1562e68ff667fcd703356acf085f68&quot;&gt;&lt;code&gt;1d41a64&lt;/code&gt;&lt;/a&gt;
chore: prepare 2.15.0 release&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/9bc06658f875b9b40091539140bbbdc4639161c3&quot;&gt;&lt;code&gt;9bc0665&lt;/code&gt;&lt;/a&gt;
fix: make recursive payload tests deterministic&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/5fde08a6cf906aa7698de2d6391d88b73006b17b&quot;&gt;&lt;code&gt;5fde08a&lt;/code&gt;&lt;/a&gt;
fix: normalize recursive JWT payload errors&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/171062d2d734315272a901100aa4b109f2fc3c19&quot;&gt;&lt;code&gt;171062d&lt;/code&gt;&lt;/a&gt;
utils: mention bytes in force_bytes type error (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1173&quot;&gt;#1173&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/c9d4d5375bf464ef363506fed9eb6e7f33217ab6&quot;&gt;&lt;code&gt;c9d4d53&lt;/code&gt;&lt;/a&gt;
docs/conf: drop duplicate 'and' from read() docstring (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1174&quot;&gt;#1174&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/2763752196113e1473b0ed7905aa6034aedfbe53&quot;&gt;&lt;code&gt;2763752&lt;/code&gt;&lt;/a&gt;
Add support for Python 3.15 (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1202&quot;&gt;#1202&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/4adcd02722f5011c60079d3978dfc167b9a8eaa5&quot;&gt;&lt;code&gt;4adcd02&lt;/code&gt;&lt;/a&gt;
Catch http.client.HTTPException in PyJWKClient.fetch_data (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1201&quot;&gt;#1201&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/9e501d993b4d3e7dba14bdb1722b1d993ac75097&quot;&gt;&lt;code&gt;9e501d9&lt;/code&gt;&lt;/a&gt;
fix: correct docstring typo in _validate_jti (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1179&quot;&gt;#1179&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/4047c44d51950ffda15f40054508d3f17c43b1e2&quot;&gt;&lt;code&gt;4047c44&lt;/code&gt;&lt;/a&gt;
docs: clarify JWK certificate member handling (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1212&quot;&gt;#1212&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/f4e2b59f543cc82d46d9d69922bba59e804216b9&quot;&gt;&lt;code&gt;f4e2b59&lt;/code&gt;&lt;/a&gt;
[pre-commit.ci] pre-commit autoupdate (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1210&quot;&gt;#1210&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Additional commits viewable in &lt;a
href=&quot;https://github.com/jpadilla/pyjwt/compare/2.13.0...2.15.0&quot;&gt;compare
view&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;

&lt;br /&gt;</code></pre>


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pyjwt&package-manager=uv&previous-version=2.13.0&new-version=2.15.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 11:41:54 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4217373227 chore(deps): bump pyjwt from 2.14.0 to 2.15.0 in /libs/langgraph (#9139)
Bumps [pyjwt](https://github.com/jpadilla/pyjwt) from 2.14.0 to 2.15.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jpadilla/pyjwt/releases">pyjwt's
releases</a>.</em></p>
<blockquote>
<h2>2.15.0</h2>
<p>See the <a
href="https://github.com/jpadilla/pyjwt/blob/2.15.0/CHANGELOG.rst">2.15.0
changelog</a> for complete release details.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst">pyjwt's
changelog</a>.</em></p>
<blockquote>
<h2><code>v2.15.0
&lt;https://github.com/jpadilla/pyjwt/compare/2.14.0...2.15.0&gt;</code>__</h2>
<p>Security</p>
<pre><code>
- Wrap recursion errors from deeply nested JWT payloads in
``DecodeError``
  instead of exposing a raw ``RecursionError``.
<p>Added</p>
<pre><code>
- Support Python 3.15 by @kytta in
`[#1202](https://github.com/jpadilla/pyjwt/issues/1202)
&amp;lt;https://github.com/jpadilla/pyjwt/pull/1202&amp;gt;`__

Changed
</code></pre>
<ul>
<li><code>JWKSetCache</code> now stores the parsed <code>PyJWKSet</code>
rather than the raw JWKS
payload, so a cache hit no longer re-parses every key.
<code>JWKSetCache.put()</code>
accepts either form and raises <code>PyJWKSetError</code> for anything
else. As a
result, <code>PyJWKClient.get_jwk_set()</code> returns the same
<code>PyJWKSet</code> instance
for as long as it stays cached, rather than a freshly built one per call
in
<code>[#1208](https://github.com/jpadilla/pyjwt/issues/1208)
&amp;lt;https://github.com/jpadilla/pyjwt/pull/1208&amp;gt;</code>__</li>
<li><code>PyJWKClient.fetch_data()</code> now raises
<code>PyJWKClientError(&amp;quot;The JWKS endpoint did not return a JSON
object&amp;quot;)</code> when
the endpoint response is not a JSON object, instead of returning it for
<code>get_jwk_set()</code> to reject. Callers reaching the JWKS through
<code>get_jwk_set()</code> see the same error as before in
<code>[#1208](https://github.com/jpadilla/pyjwt/issues/1208)
&amp;lt;https://github.com/jpadilla/pyjwt/pull/1208&amp;gt;</code>__</li>
</ul>
<p>Fixed</p>
<pre><code>
- Return cached ``PyJWKSet`` values from ``PyJWKClient.get_jwk_set()``
instead
of raising ``PyJWKClientError(&amp;quot;The JWKS endpoint did not return
a JSON
object&amp;quot;)``. ``JWKSetCache.put()`` documents ``PyJWKSet`` as the
cached value,
so callers pre-populating the cache to avoid a network round-trip could
not
read it back in `[#914](https://github.com/jpadilla/pyjwt/issues/914)
&amp;lt;https://github.com/jpadilla/pyjwt/issues/914&amp;gt;`__ and
`[#1208](https://github.com/jpadilla/pyjwt/issues/1208)
&amp;lt;https://github.com/jpadilla/pyjwt/pull/1208&amp;gt;`__
- ``PyJWKClient.get_jwk_set()`` now caches the key set it returns, so a
``fetch_data()`` override that filters or transforms the JWKS is no
longer
  undone by the next cache hit in
`[#1208](https://github.com/jpadilla/pyjwt/issues/1208)
&amp;lt;https://github.com/jpadilla/pyjwt/pull/1208&amp;gt;`__
- Raise the documented ``PyJWTError`` subclass instead of leaking a
  ``TypeError`` when the ``exp``, ``nbf``, or ``iat`` claim decodes to a
  non-numeric, non-string value such as a list, dict, or ``null``.
- Reject OKP JWK private keys when their public ``x`` component does not
  match the private ``d`` component.
- Treat malformed JWK Set members as unusable keys rather than letting
``AttributeError`` or ``TypeError`` escape ``PyJWKSet``. A member that
is not
&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;... (truncated)&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;Commits&lt;/summary&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/1d41a6478e1562e68ff667fcd703356acf085f68&quot;&gt;&lt;code&gt;1d41a64&lt;/code&gt;&lt;/a&gt;
chore: prepare 2.15.0 release&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/9bc06658f875b9b40091539140bbbdc4639161c3&quot;&gt;&lt;code&gt;9bc0665&lt;/code&gt;&lt;/a&gt;
fix: make recursive payload tests deterministic&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/5fde08a6cf906aa7698de2d6391d88b73006b17b&quot;&gt;&lt;code&gt;5fde08a&lt;/code&gt;&lt;/a&gt;
fix: normalize recursive JWT payload errors&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/171062d2d734315272a901100aa4b109f2fc3c19&quot;&gt;&lt;code&gt;171062d&lt;/code&gt;&lt;/a&gt;
utils: mention bytes in force_bytes type error (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1173&quot;&gt;#1173&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/c9d4d5375bf464ef363506fed9eb6e7f33217ab6&quot;&gt;&lt;code&gt;c9d4d53&lt;/code&gt;&lt;/a&gt;
docs/conf: drop duplicate 'and' from read() docstring (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1174&quot;&gt;#1174&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/2763752196113e1473b0ed7905aa6034aedfbe53&quot;&gt;&lt;code&gt;2763752&lt;/code&gt;&lt;/a&gt;
Add support for Python 3.15 (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1202&quot;&gt;#1202&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/4adcd02722f5011c60079d3978dfc167b9a8eaa5&quot;&gt;&lt;code&gt;4adcd02&lt;/code&gt;&lt;/a&gt;
Catch http.client.HTTPException in PyJWKClient.fetch_data (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1201&quot;&gt;#1201&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/9e501d993b4d3e7dba14bdb1722b1d993ac75097&quot;&gt;&lt;code&gt;9e501d9&lt;/code&gt;&lt;/a&gt;
fix: correct docstring typo in _validate_jti (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1179&quot;&gt;#1179&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/4047c44d51950ffda15f40054508d3f17c43b1e2&quot;&gt;&lt;code&gt;4047c44&lt;/code&gt;&lt;/a&gt;
docs: clarify JWK certificate member handling (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1212&quot;&gt;#1212&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/f4e2b59f543cc82d46d9d69922bba59e804216b9&quot;&gt;&lt;code&gt;f4e2b59&lt;/code&gt;&lt;/a&gt;
[pre-commit.ci] pre-commit autoupdate (&lt;a
href=&quot;https://redirect.github.com/jpadilla/pyjwt/issues/1210&quot;&gt;#1210&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Additional commits viewable in &lt;a
href=&quot;https://github.com/jpadilla/pyjwt/compare/2.14.0...2.15.0&quot;&gt;compare
view&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;

&lt;br /&gt;</code></pre>


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pyjwt&package-manager=uv&previous-version=2.14.0&new-version=2.15.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 11:39:14 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
65ab10f017 chore(deps): bump pyjwt from 2.13.0 to 2.14.0 in /libs/langgraph (#9126)
Bumps [pyjwt](https://github.com/jpadilla/pyjwt) from 2.13.0 to 2.14.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jpadilla/pyjwt/releases">pyjwt's
releases</a>.</em></p>
<blockquote>
<h2>2.14.0</h2>
<p>See the <a
href="https://github.com/jpadilla/pyjwt/blob/2.14.0/CHANGELOG.rst">2.14.0
changelog</a> for the complete release details and related security
advisories.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst">pyjwt's
changelog</a>.</em></p>
<blockquote>
<h2><code>v2.14.0
&lt;https://github.com/jpadilla/pyjwt/compare/2.13.0...2.14.0&gt;</code>__</h2>
<p>Security</p>
<pre><code>
- Harden HMAC key validation against public-key material supplied as
JWK,
  JWKS, array, encoded, BOM-prefixed, DER, or PEM input. See
`GHSA-r6x4-923q-g947
&lt;https://github.com/jpadilla/pyjwt/security/advisories/GHSA-r6x4-923q-g947&gt;`__,
`GHSA-ffc3-869f-jxw9
&lt;https://github.com/jpadilla/pyjwt/security/advisories/GHSA-ffc3-869f-jxw9&gt;`__,
`GHSA-p4g4-x82p-q773
&lt;https://github.com/jpadilla/pyjwt/security/advisories/GHSA-p4g4-x82p-q773&gt;`__,
and `GHSA-w2cx-738m-mc7w
&lt;https://github.com/jpadilla/pyjwt/security/advisories/GHSA-w2cx-738m-mc7w&gt;`__.
- Reject automatic redirects when ``PyJWKClient`` fetches a JWKS,
preventing
  redirected destinations from being treated as trusted key sources. See
`GHSA-9v7f-9g4p-ffgj
&lt;https://github.com/jpadilla/pyjwt/security/advisories/GHSA-9v7f-9g4p-ffgj&gt;`__.
- Limit repeated JWKS refreshes caused by unknown key IDs while
preserving
  normal key-rotation behavior. See
`GHSA-2gx3-rcp4-g85q
&lt;https://github.com/jpadilla/pyjwt/security/advisories/GHSA-2gx3-rcp4-g85q&gt;`__.
- Handle deeply nested and malformed JWS/JWK input without uncaught
recursion
  errors or whole-set parsing failures. See
`GHSA-8wjv-2p76-3863
&lt;https://github.com/jpadilla/pyjwt/security/advisories/GHSA-8wjv-2p76-3863&gt;`__
and `GHSA-w6j9-cwv2-h6wq
&lt;https://github.com/jpadilla/pyjwt/security/advisories/GHSA-w6j9-cwv2-h6wq&gt;`__.
- Enforce compact JWS encoding rules during decoding. See
`GHSA-hxm8-2xgr-2p9m
&lt;https://github.com/jpadilla/pyjwt/security/advisories/GHSA-hxm8-2xgr-2p9m&gt;`__.
- Reject detached-payload arguments for attached JWS inputs. Thanks to
`@xclow3n
&lt;https://github.com/xclow3n&gt;`__ for reporting this behavior; fixed
in commit
`37b54877
&lt;https://github.com/jpadilla/pyjwt/commit/37b54877bf7bea67e8149130e96929e3ec798122&gt;`__.
<p>Fixed</p>
<pre><code>
- Apply HMAC key validation consistently when keys are loaded through
  ``PyJWK`` and ``PyJWKClient``. See
`GHSA-pxh4-856f-4h89
&amp;lt;https://github.com/jpadilla/pyjwt/security/advisories/GHSA-pxh4-856f-4h89&amp;gt;`__.
- Reject empty HMAC keys when represented as JWKs.
See `GHSA-pxh4-856f-4h89
&amp;lt;https://github.com/jpadilla/pyjwt/security/advisories/GHSA-pxh4-856f-4h89&amp;gt;`__.
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;Commits&lt;/summary&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/c6fe464b356ff4b1ebc9ba62172d331a40aa27df&quot;&gt;&lt;code&gt;c6fe464&lt;/code&gt;&lt;/a&gt;
release: prepare v2.14.0&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/f5413029ae7a2e31b1367b5303ea86a2f54ccf42&quot;&gt;&lt;code&gt;f541302&lt;/code&gt;&lt;/a&gt;
style: apply Ruff formatting&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/801cd128528c62d9b23fcd161d1a2e1c17982f95&quot;&gt;&lt;code&gt;801cd12&lt;/code&gt;&lt;/a&gt;
fix: reject public JWK container HMAC keys&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/af8181ca0bec5e6b372fbba9afbe23702b787ceb&quot;&gt;&lt;code&gt;af8181c&lt;/code&gt;&lt;/a&gt;
fix: reject empty HMAC keys from JWKs&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/ba4853a75fb9676362da17f67d0f64bd18afd4e1&quot;&gt;&lt;code&gt;ba4853a&lt;/code&gt;&lt;/a&gt;
Throttle repeated PyJWKClient refreshes&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/2798504fa2663364573cf2d1043d8d7fef389499&quot;&gt;&lt;code&gt;2798504&lt;/code&gt;&lt;/a&gt;
fix: reject DER public keys as HMAC secrets&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/8b4e233a22206b34ec1186e912e75c0b2396ac07&quot;&gt;&lt;code&gt;8b4e233&lt;/code&gt;&lt;/a&gt;
fix: reject loader-accepted PEM variants&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/1f8180a211256dfe5cf32294b6753f554a5a4258&quot;&gt;&lt;code&gt;1f8180a&lt;/code&gt;&lt;/a&gt;
fix: format JWS tests&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/cff1ac55fe5f1096fd05295b269fce053ee290ab&quot;&gt;&lt;code&gt;cff1ac5&lt;/code&gt;&lt;/a&gt;
Fix redirect handler return annotation&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/jpadilla/pyjwt/commit/0a795b8e1f6ef08f634aa7086fc41cc6d5ce3e56&quot;&gt;&lt;code&gt;0a795b8&lt;/code&gt;&lt;/a&gt;
Reject redirects in PyJWKClient fetches&lt;/li&gt;
&lt;li&gt;Additional commits viewable in &lt;a
href=&quot;https://github.com/jpadilla/pyjwt/compare/2.13.0...2.14.0&quot;&gt;compare
view&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;

&lt;br /&gt;</code></pre>


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pyjwt&package-manager=uv&previous-version=2.13.0&new-version=2.14.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 09:53:24 -07:00
eb69f67b65 fix(checkpoint-sqlite): walk delta ancestors by parent pointer (#8557)
## Summary

The sqlite delta history silently drops a parent checkpoint whose id sorts above its child's,
losing that parent's stored value and its pending writes. The channel hydrates short with no error.

Fixes #8550

## Problem

Stage 1 walked ancestors with:

```sql
WHERE thread_id = ? AND checkpoint_ns = ? AND checkpoint_id <= ?
ORDER BY checkpoint_id DESC
```

Ancestry is defined by the `parent_checkpoint_id` column. These two predicates add a second
requirement: that every child's id sorts above its parent's. The contract promises monotonic ids,
but that only holds within one process, so ids from processes with different clocks can break it.

When the requirement is violated the parent is excluded from the stream and its seed and writes go
with it. Dropping the range filter alone does not fix it: in `checkpoint_id DESC` order that parent
arrives *before* the target, so the walk streams past it before it has started.

## Fix

A recursive CTE anchored at the target, following `parent_checkpoint_id`:

```sql
WITH RECURSIVE ancestors(checkpoint_id, parent_checkpoint_id, type, checkpoint) AS (
    SELECT ... FROM checkpoints
    WHERE thread_id = ? AND checkpoint_ns = ? AND checkpoint_id = ?
    UNION ALL
    SELECT c.... FROM ancestors a CROSS JOIN checkpoints c
      ON c.checkpoint_id = a.parent_checkpoint_id
    WHERE c.thread_id = ? AND c.checkpoint_ns = ?
)
SELECT checkpoint_id, type, checkpoint FROM ancestors
```

Rows now arrive in walk order (target, parent, grandparent, ...), so `step_walk_with_row` no longer
needs its off-path skip or its `parent_cid` tracking; both are removed. The query reads only true
ancestors, where the old one read every row at or below the target including sibling branches.

`CROSS JOIN` pins the join order. The saver never runs `ANALYZE`, and with a plain `JOIN` sqlite put
`checkpoints` as the outer loop, scanning the whole thread on every recursion step. With `ancestors`
outside, each step is one primary key lookup. Through `get_delta_channel_history`:

| chain length | plain `JOIN` | `CROSS JOIN` |
| -- | -- | -- |
| 1000 | 0.032s | 0.001s |
| 2000 | 0.124s | 0.003s |
| 4000 | 0.475s | 0.006s |

## Cycle guard

Following pointers can loop where a bounded id scan could not, and a loop is reachable through
`put` alone: `put` writes with `INSERT OR REPLACE`, so re-putting an existing checkpoint id under a
descendant's config repoints that checkpoint at its own descendant. The walk stops on a repeated
`checkpoint_id` (one set insert per row, no depth ceiling that could truncate a long migrated
thread). sqlite yields recursive rows lazily, so abandoning the cursor ends the recursion.

`test_walk_terminates_when_put_makes_the_parent_chain_cycle` fails by hanging, not by asserting, if
the guard regresses (confirmed by deleting the guard locally). The package has no `pytest-timeout`,
so the CI job timeout is the backstop.

## Postgres

No equivalent change needed. It pages the whole thread with no id bound and follows parent pointers
in Python, and its upsert never rewrites `parent_checkpoint_id`, so it can neither miss this parent
nor form the loop. `BaseCheckpointSaver` and `InMemorySaver` also walk parent pointers.

## Test plan

New `libs/checkpoint-sqlite/tests/test_delta_parent_walk.py`:

- [x] Sync and async, parametrised over both id orders; the sync case also asserts equality with
      `BaseCheckpointSaver` on the same rows. `parent_id_sorts_above_child` is the bug,
      `parent_id_sorts_below_child` the control.
- [x] `test_walk_reaches_root_of_long_chain_with_descending_ids`: 40 checkpoints, only stored value
      at the root.
- [x] `test_walk_terminates_when_put_makes_the_parent_chain_cycle`.
- [x] `test_walk_step_looks_up_the_parent_by_primary_key`: asserts the recursive step's
      `EXPLAIN QUERY PLAN` is a key lookup, so a plain `JOIN` can't come back. Fails with it.
- [x] On `main`: 3 of the 6 walk tests fail (both `parent_id_sorts_above_child` cases and the long
      chain). The cycle test passes on `main` too, since the old bounded scan could not loop; it
      guards the new path.
- [x] #8550's repro returns `{'writes': [('task', 'ch', 'write-root')], 'seed': 'seed'}` sync and
      async (was `{'writes': []}` on `main`).
- [x] `libs/checkpoint-sqlite`: `make format`, `make lint` clean; full suite 125 passed, 2 skipped.
- [x] `libs/langgraph`: `-k "delta or sqlite"` 739 passed, 1 skipped.

Thanks to @lylelllll for the report, the minimal repro, the base-saver comparison that isolated it
to the fast path, and for suggesting the recursive CTE.




Co-authored-by: lylelllll <59271327+lylelllll@users.noreply.github.com>
2026-09-30 12:17:02 -04:00
c0279f0910 fix(checkpoint-postgres): derive the delta walk cursor once the target loads (#8556)
## Summary

`get_delta_channel_history` on Postgres returns an empty history for any `DeltaChannel` on a
target checkpoint that is not within the first stage-1 pagination page (1024 rows) of the thread.
No exception, no warning: the channel just hydrates empty.

Fixes #8448

## Problem

Stage 1 pages `checkpoints` newest-first from the head of the thread, and after each page
`_try_advance_walks` tries to move every not-yet-seeded channel's walk along the partial
`parent_of` map accumulated so far. The walk starts at the target's parent:

```python
if ch not in walk_cursor_by_ch:
    walk_cursor_by_ch[ch] = parent_of.get(target_id)
```

The target can be any checkpoint in the thread, not just the head, so on the first page
`parent_of` frequently has no row for it yet. `.get` then returns `None`, which is also what a
target with no parent returns, and the two are stored identically. Because the initialisation is
guarded by `ch not in walk_cursor_by_ch`, it never runs again: once the walk is parked at `None`
it stays there even after the target's real row and real parent load on a later page.

The result is an empty chain and no seed. Downstream `channels_from_checkpoint` does

```python
replay_ch = delta_spec.from_checkpoint(history.get("seed", MISSING))
replay_ch.replay_writes(history["writes"])
```

so `get_state`, `get_state_history` and `update_state` against an older checkpoint reconstruct a
`messages` channel as `[]` on a thread with hundreds of real messages.

## Fix

Start the walk only once `target_id` is actually present in `parent_of`, so "the target has not
loaded yet" stops sharing a representation with "the target is a root":

```python
if ch not in walk_cursor_by_ch:
    if target_id not in parent_of:
        continue
    walk_cursor_by_ch[ch] = parent_of[target_id]
```

`_try_advance_walks` is a static method on `BasePostgresSaver`, so `PostgresSaver` and
`AsyncPostgresSaver` are both covered by the one change.

## Why it's safe

`continue` leaves the channel exactly as it was, so a later page retries. The three existing
stop conditions are untouched: a channel that finds its seed still seeds, one that reaches a real
root still parks at `None`, and one waiting on an ancestor still keeps its cursor. Paging still
terminates on a short page, which is what ends the run for a target that really is a root.

## Long-term

The sibling sqlite implementation avoids this class of bug differently, by starting its stage-1
scan at the target (`checkpoint_id <= ?`) instead of at the head. Postgres could adopt the same
bound and would then never fetch a checkpoint newer than the target at all, which looks like the
bigger win on a long thread. It makes the read path depend on ancestors always sorting below their
descendants, though, which sqlite already assumes but the Postgres fast path currently does not.
#8550 now reports that assumption as a bug in sqlite, on the grounds that ancestry is defined by
`parent_checkpoint_id` and the contract does not require ids to be monotonic, so the bound is the
wrong direction to move Postgres in. Paging the full thread and following parent pointers is what
keeps this path correct when ids are not monotonic, and with this fix Postgres returns the right
history for #8550's scenario at every page size.

## Test plan

New `libs/checkpoint-postgres/tests/test_delta_pagination.py`. Page size is monkeypatched rather
than writing 1024+ real checkpoints per case, since the only thing that decides the behaviour is
which page the target lands on.

- [x] `test_async_target_older_than_the_first_page` and its sync twin, parametrised over page
      sizes `[_DELTA_PAGE_SIZE, 3, 2, 1]`. The thread has 8 checkpoints with a snapshot at step 1
      and the target at step 4, so every size at or below 3 leaves the target off the first page.
      The real page size is the control.
- [x] `test_root_target_has_no_history_and_still_terminates` covers the case where a `None` cursor
      is the correct answer, at page size 1 so the paging loop runs the length of the thread.
- [x] 6 of the 9 fail on `main` (`expected a snapshot seed, got '<missing>'`); the 3 that pass are
      the two controls and the root case.
- [x] `make format`, `make lint_package`, `make lint_tests` clean.
- [x] Full `libs/checkpoint-postgres` suite, rebased on current `main`: 279 passed, 3 skipped on Postgres 16.
- [x] Graph-level repro with `_DELTA_PAGE_SIZE = 5`: 10 invocations, then `get_state` on the 8th-newest
      checkpoint returns `[]` on `main` and the full history on this branch.

Thanks to @Navneet-Scaler for the report, the mechanism write-up, and the fix in #8453, which this
matches.




Co-authored-by: Navneet-Scaler <147032454+Navneet-Scaler@users.noreply.github.com>
2026-09-30 12:16:55 -04:00
ccurmeandGitHub f5804a5bf5 fix(ci): test locally-built wheel and publish to test pypi after pre-release checks (#9124) 2026-09-30 09:30:34 -04:00
John KennedyGitHubopen-swe[bot] <open-swe@users.noreply.github.com>
07b33185ea fix: reject credential-bearing Git dependencies (#8542)
## Description
Reject Git HTTP dependency URLs containing userinfo before Docker
generation so credentials cannot persist in Dockerfiles or image layers.
Validation now covers local requirement/package metadata and uv
pyproject/lock inputs while keeping errors token-free.

## Test Plan
- [x] Validate credentialed raw, local-manifest, and uv-managed Git URLs
are rejected without echoing secrets
- [x] Validate credential-free HTTPS and SSH Git URLs remain supported

Made by [Open
SWE](https://openswe.vercel.app/agents/81b07455-ece4-3ddc-9955-d7a5bea78d2c)

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-09-27 21:34:53 +00:00
53 changed files with 4784 additions and 1271 deletions
+1 -1
View File
@@ -50,4 +50,4 @@ jobs:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
+23 -36
View File
@@ -139,23 +139,10 @@ jobs:
echo EOF
} >> "$GITHUB_OUTPUT"
test-pypi-publish:
needs:
- build
- release-notes
permissions:
contents: read
id-token: write
uses: ./.github/workflows/_test_release.yml
with:
working-directory: ${{ inputs.working-directory }}
secrets: inherit
pre-release-checks:
needs:
- build
- release-notes
- test-pypi-publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -180,31 +167,20 @@ jobs:
enable-cache: false
working-directory: ${{ inputs.working-directory }}
- name: Import published package
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: dist
path: ${{ inputs.working-directory }}/dist/
- name: Import dist package
shell: bash
working-directory: ${{ inputs.working-directory }}
env:
PKG_NAME: ${{ needs.build.outputs.pkg-name }}
VERSION: ${{ needs.build.outputs.version }}
# Here we use:
# - The default regular PyPI index as the *primary* index, meaning
# that it takes priority (https://pypi.org/simple)
# - The test PyPI index as an extra index, so that any dependencies that
# are not found on test PyPI can be resolved and installed anyway.
# (https://test.pypi.org/simple). This will include the PKG_NAME==VERSION
# package because VERSION will not have been uploaded to regular PyPI yet.
# - attempt install again after 5 seconds if it fails because there is
# sometimes a delay in availability on test pypi
# Install directly from the locally-built wheel (no index resolution needed).
run: |
uv run pip install \
--extra-index-url https://test.pypi.org/simple/ \
"$PKG_NAME==$VERSION" || \
( \
sleep 5 && \
uv run pip install \
--extra-index-url https://test.pypi.org/simple/ \
"$PKG_NAME==$VERSION" \
)
uv run pip install dist/*.whl
if [[ "$PKG_NAME" == *prebuilt* ]]; then
uv run pip install langgraph
@@ -226,7 +202,7 @@ jobs:
run: uv sync --group test
working-directory: ${{ inputs.working-directory }}
# Overwrite the local version of the package with the test PyPI version.
# Overwrite the local version of the package with the built version
- name: Import published package (again)
working-directory: ${{ inputs.working-directory }}
shell: bash
@@ -234,14 +210,25 @@ jobs:
PKG_NAME: ${{ needs.build.outputs.pkg-name }}
VERSION: ${{ needs.build.outputs.version }}
run: |
uv run pip install \
--extra-index-url https://test.pypi.org/simple/ \
"$PKG_NAME==$VERSION"
uv run pip install dist/*.whl
- name: Run unit tests
run: make test
working-directory: ${{ inputs.working-directory }}
test-pypi-publish:
needs:
- build
- release-notes
- pre-release-checks
permissions:
contents: read
id-token: write
uses: ./.github/workflows/_test_release.yml
with:
working-directory: ${{ inputs.working-directory }}
secrets: inherit
publish:
needs:
- build
+41 -41
View File
@@ -809,27 +809,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.16.5"
version = "0.16.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f3/85/c8e12473c93018f92d19dd988a294202e1c27426c47ec4de53ffb847b8d8/ruff-0.16.5.tar.gz", hash = "sha256:1b88500f9ffbcab3dedb0082c9f9492e91ec3d618aac1236a3e0189938f7040b", size = 4912003, upload-time = "2026-08-27T16:34:18.258Z" }
sdist = { url = "https://files.pythonhosted.org/packages/96/bf/c935ca98e73fe8ce65b87ef08a280c0c1e85295d569228c15e87d8fdfaf1/ruff-0.16.9.tar.gz", hash = "sha256:12b625c6cfba78d285d9f48eda5f053374f1e53cb10ef17342a383750db99161", size = 4948764, upload-time = "2026-09-24T20:37:49.416Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c6/b6/77c90a970fe2dae17a723acbd011043ea97c98d7deacccefdc4ba74ec512/ruff-0.16.5-py3-none-linux_armv6l.whl", hash = "sha256:12e5f673e774c35fbb62f288809c7653b73445f8ecec6b6063fd6ea3521aa14b", size = 10011941, upload-time = "2026-08-27T16:33:41.287Z" },
{ url = "https://files.pythonhosted.org/packages/4b/46/6cf67cf6411885a1d6f7f6d801682f155536a85176d10b605e2ceffed8bd/ruff-0.16.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:eda58a5802de40e7ed5b32b64e0b32539338cc6fcd2c78f61e3ad6a0d79f51c3", size = 10204049, upload-time = "2026-08-27T16:33:44.056Z" },
{ url = "https://files.pythonhosted.org/packages/46/fd/c8720ca7a090abf0c2fef4abe8a5ef6e5127ed15196d8886ff75a2b370e2/ruff-0.16.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5ae9a7b9a8875131f40f8fe967cc86abf899779efd663cb7ce3d572d01da7eb", size = 9809037, upload-time = "2026-08-27T16:33:46.257Z" },
{ url = "https://files.pythonhosted.org/packages/43/45/a684caacdedaca180f52bacccc40bf0789d2c5a7c75f25324853e9eaedb5/ruff-0.16.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b719b0a1f4d59710d283ab2965f621684a108a9e41da622e3b23f0326cd0025", size = 9964129, upload-time = "2026-08-27T16:33:48.352Z" },
{ url = "https://files.pythonhosted.org/packages/9e/f2/5d2bcdaca6b5b93d1b4dfc166cd2aebf7680143a1b38a28759df13a94d31/ruff-0.16.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2298f2780ed1be0c5cb1361e32ab7b1467f3cce7dabe101d2210a314f2fe42e9", size = 9821518, upload-time = "2026-08-27T16:33:50.57Z" },
{ url = "https://files.pythonhosted.org/packages/aa/ff/011cce29accf9257d5974145b733fc653a37985ed6825413a3987cefbfe0/ruff-0.16.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:258f29035a2dd021e7861e631b227a5b3f14e50c1184c9a6a122c5f4576154d7", size = 10534835, upload-time = "2026-08-27T16:33:52.522Z" },
{ url = "https://files.pythonhosted.org/packages/d7/5a/f0cf109bada9bba0e96c90c21c9f9251803f57225c32d293327a03c710d6/ruff-0.16.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9a4f0432966834019c74d1b7e5c51224305d7713f3d7faf3e7451f1a3be3cde", size = 11252550, upload-time = "2026-08-27T16:33:54.521Z" },
{ url = "https://files.pythonhosted.org/packages/63/4d/1d481aaea2046c6a7ed7c291f9004c669cce3c087b6b376ed5b08271e3fe/ruff-0.16.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5eb3a8c3d0ade9cea42b591fd530368e8798380e30e0a308b85a5cf718f09ea", size = 10777949, upload-time = "2026-08-27T16:33:56.88Z" },
{ url = "https://files.pythonhosted.org/packages/ee/34/ee245ca55f64443233034b3d02b03236b19242004281247c079390b7facd/ruff-0.16.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef0f69e191a13a3c9816f63163c88790cb12cd157bbbb384e9c44745702ab105", size = 10311656, upload-time = "2026-08-27T16:33:59.12Z" },
{ url = "https://files.pythonhosted.org/packages/a7/4d/c33a333e341c0a2b96c715b52d89a606f5a34cd4ac493cd9b8d0187186b8/ruff-0.16.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0eeab41fbea2c42f98dfb9822cdccda9d24ba38d49f6dc945b5c236d48f0ef29", size = 10532125, upload-time = "2026-08-27T16:34:01.166Z" },
{ url = "https://files.pythonhosted.org/packages/30/e1/a64cef78b40192497bb98a27a8aa8f2c98ee9ee15bc97f7712d94ef32937/ruff-0.16.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f0768e9df4300713fff30733c87575f68b6f1d8de41184e505b7fdd9c0c95eaf", size = 10097648, upload-time = "2026-08-27T16:34:03.16Z" },
{ url = "https://files.pythonhosted.org/packages/cc/4e/4cdc9ed3c3e109d2f71e62572a37457298d7bc7501ec3138babb7ed32bbd/ruff-0.16.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:95cc70cdc7aa80c338de356279d2adbeb2de0f520b9ecd8aba75b94e95e02f91", size = 9829344, upload-time = "2026-08-27T16:34:05.134Z" },
{ url = "https://files.pythonhosted.org/packages/39/4a/31ed35ce31729955fc583ee0d176d6e784c1290cb0b0a75cb2134c1ab72a/ruff-0.16.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d185c8398ded1bfd91c0c2cb258346307571eccc473a8490af8c3977399c384a", size = 10277117, upload-time = "2026-08-27T16:34:07.425Z" },
{ url = "https://files.pythonhosted.org/packages/a8/a0/60356d86687b4b666d593df213f4dc3041750d024cb7bf2cfa81cfd65c2e/ruff-0.16.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:fb8e3a3c4c6a784150a7ced53b015f4b253fc2bf97a610886419ead64b4756ef", size = 10711653, upload-time = "2026-08-27T16:34:09.712Z" },
{ url = "https://files.pythonhosted.org/packages/ed/20/656d67f5b25ca9bda4e02b1de25867b2954e1d19e03648060f167ad0f4cc/ruff-0.16.5-py3-none-win32.whl", hash = "sha256:288b0a5f080492fe5635db849f9e2e84aa3cce7b7f0e955997d416c507c76a26", size = 10034250, upload-time = "2026-08-27T16:34:11.8Z" },
{ url = "https://files.pythonhosted.org/packages/5b/42/ee8e68a207b9127fcde6c3d7e197def432f346cb1af159e1fa14ca0d1cdc/ruff-0.16.5-py3-none-win_amd64.whl", hash = "sha256:ddc6385fb2137f616357ca03d6c74f4be987f80fed4008566b754f6032b8546f", size = 10516714, upload-time = "2026-08-27T16:34:13.963Z" },
{ url = "https://files.pythonhosted.org/packages/73/e3/7df5a396e445b9ba49ce9a9437439a4d80042c61c0ade199abf8d16de1ac/ruff-0.16.5-py3-none-win_arm64.whl", hash = "sha256:a64abe90968719b851bb7cedffaa8753fbdbdadab483089682db623f3edc587e", size = 10391564, upload-time = "2026-08-27T16:34:16.064Z" },
{ url = "https://files.pythonhosted.org/packages/0d/26/df51322b52ee1ada7eff2d071ea09d11d5c2d1dcc9f02594f5785c4d1635/ruff-0.16.9-py3-none-linux_armv6l.whl", hash = "sha256:95e6f022090368ab3b824c36276839c53b2adf1a3f4c09fefc33dfc400f6da96", size = 10082922, upload-time = "2026-09-24T20:37:13.045Z" },
{ url = "https://files.pythonhosted.org/packages/a5/27/7bf51f5a7aa375e9f339280a303aab44ca75dc1525f1cdc5991761685b0f/ruff-0.16.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a5f27be168556594a86d2f415db0cf43f5291917849318f873c7e2791f7a8c67", size = 10236360, upload-time = "2026-09-24T20:37:16.049Z" },
{ url = "https://files.pythonhosted.org/packages/b6/63/09659283f92f02dff45809da194a70da2f688d87c55d8875c4fae3536072/ruff-0.16.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1632eb1d6197f33bd00b1acbc5b71009e89a8895c158e2d2b03a834fac964ab6", size = 9892940, upload-time = "2026-09-24T20:37:17.957Z" },
{ url = "https://files.pythonhosted.org/packages/24/58/98de1b72ec172f5f8f1731236fe21585b3998bf7dfe9fcc44ae9ba626012/ruff-0.16.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3f951b14d865d5952c89d40a5ca07e87abe24fa5453299878411e127748fb1c", size = 10032114, upload-time = "2026-09-24T20:37:19.942Z" },
{ url = "https://files.pythonhosted.org/packages/c8/7d/f1e17c54ab59d4bad1dce8ee3e22a7a1d0ef4745240decacdcf3832b5bb2/ruff-0.16.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:447fc07e1573afff7cb02803462b12b6c8ece7cf10e2cd78565fa6d7a1c0bf8d", size = 9910227, upload-time = "2026-09-24T20:37:21.872Z" },
{ url = "https://files.pythonhosted.org/packages/34/19/436f647a65075bbd3bab2668b3bdaa5120559b294694018cdcefabbbf30b/ruff-0.16.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a3e039a6a40ed976c491722b60e0ae4a4aa1a86057f540ee7a37a5d19ae9120", size = 10547484, upload-time = "2026-09-24T20:37:24.229Z" },
{ url = "https://files.pythonhosted.org/packages/03/59/38430a6bc2f6d8095447ac39625cf8b6e9344a47e6c26225c8ba1bff3ffb/ruff-0.16.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4684dded7db60aa57cb118fa158630f5feade4af5782903b6053484bdf9bd129", size = 11412367, upload-time = "2026-09-24T20:37:26.307Z" },
{ url = "https://files.pythonhosted.org/packages/c8/bd/bbb6d7fc7f208c8b8c50dd5dc8206e4cfdb1e7a8fb852606a3adf370c880/ruff-0.16.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d29c934357e45642fda2f34c0b1f4025b4a6c01e15e4bf0016879d60078a142c", size = 10869787, upload-time = "2026-09-24T20:37:28.35Z" },
{ url = "https://files.pythonhosted.org/packages/bc/b8/9c543074918061abbefc3bd139bee22de35abedb00dde0f2d27288838962/ruff-0.16.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a21713e629d3e5bdb2f5c2def1cc7f04f47fa8e1a7eb0571b4a28e1da64bc728", size = 10406494, upload-time = "2026-09-24T20:37:30.624Z" },
{ url = "https://files.pythonhosted.org/packages/35/7a/5a8851bd146e7ccf8fd4b003f6c75c11f8fbdb0e60673b45097986b6bf41/ruff-0.16.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7baa24ef5fc8e77aa93879e1d3f43754a01ae488e869f1ae30cf431afd4d2452", size = 10590083, upload-time = "2026-09-24T20:37:32.439Z" },
{ url = "https://files.pythonhosted.org/packages/87/f0/4c3467188f23f806960b46fa76575a7cd0514c9ba90562650b71efc96980/ruff-0.16.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a41aac6230aadfaa133bdfa1614488531ffa3e0837567ae04c0da2058a9c0f9e", size = 10119151, upload-time = "2026-09-24T20:37:34.581Z" },
{ url = "https://files.pythonhosted.org/packages/15/34/5a4def5adea572ce6aea0bb64f21f928ee317b80e0db747d7979b01d7261/ruff-0.16.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c2529fb5896d49115b0e9aa8f887490b34bbe76baf879ec2264ac59406869ce7", size = 9911544, upload-time = "2026-09-24T20:37:36.796Z" },
{ url = "https://files.pythonhosted.org/packages/62/5d/d15ebea7499eef9373318c0ee6ca127832927c6529731f6d48e18dce7ca9/ruff-0.16.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:41e3870277694177429b56406d65dfbdb2c2802c52b715edaf6a0b829c69d4ee", size = 10269884, upload-time = "2026-09-24T20:37:38.857Z" },
{ url = "https://files.pythonhosted.org/packages/d1/56/c5d3cd119ded7a3c7aba0e961b69cb3df701c91662c98ad694467d060ce1/ruff-0.16.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8adbe4e58af167f767d7b2ba5e83c42e878350796cf78c2f5e14ab9903a92588", size = 10749366, upload-time = "2026-09-24T20:37:41.042Z" },
{ url = "https://files.pythonhosted.org/packages/ac/fe/734ec7527029ac757ecf821f143c9f3fcf69149c21f53a044a899b430f5a/ruff-0.16.9-py3-none-win32.whl", hash = "sha256:0e1dbc2073624dee6618d41d0098690a7244654af746704b64759e12b6b6b385", size = 10152355, upload-time = "2026-09-24T20:37:43.025Z" },
{ url = "https://files.pythonhosted.org/packages/14/21/26e4643629b3ebb44f0a06f9c9a53058d63d989415f63a9a3c28e2ee7f22/ruff-0.16.9-py3-none-win_amd64.whl", hash = "sha256:6bd40fec8cd4c8a3d4dd589bd8ad4e6320c13c29234159bfd959a40d529d597b", size = 10592965, upload-time = "2026-09-24T20:37:44.944Z" },
{ url = "https://files.pythonhosted.org/packages/51/60/5fb1a39dbb5ae314d5f59bc7348a63c1d5c20f3cd83914c4b5cb0be31d2d/ruff-0.16.9-py3-none-win_arm64.whl", hash = "sha256:ed1a252039200f57a59eebc063b54beabea67bfbaaca0eeaa7f54b5fbcda2284", size = 10458649, upload-time = "2026-09-24T20:37:46.882Z" },
]
[[package]]
@@ -897,27 +897,27 @@ wheels = [
[[package]]
name = "ty"
version = "0.0.75"
version = "0.0.84"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/81/d0/d0c96f898d6974a4a3569ab3efdf9512c04ad99f9203effb55f72497fe97/ty-0.0.75.tar.gz", hash = "sha256:4c5eead33dfbf6e2ebb4f400f74b51ffc9bab702a6f23ddb648a1cbb740387e3", size = 6868326, upload-time = "2026-08-26T20:23:40.399Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e1/f6/34f8869c45ea87fe6a931ffa824b1fe4428167173543d92988d631add355/ty-0.0.84.tar.gz", hash = "sha256:0cefdb0cd5d399418dbe83c349ba605047b7dff815ae6f460c80e8522b40be67", size = 7409537, upload-time = "2026-09-24T13:16:24.367Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/6c/b12d03505f17581f0cfa3c12273fe34c1d67b36dfda1bc561a6bdc16512b/ty-0.0.75-py3-none-linux_armv6l.whl", hash = "sha256:e5409f50db2246fd4bd039d93d261e0cfa1daa554a4fb77256f91072c570349a", size = 12972606, upload-time = "2026-08-26T20:22:59.716Z" },
{ url = "https://files.pythonhosted.org/packages/d1/aa/30f11eecd9215a9f87e8fe8baaf48f3ce905f5d75b8e4aac70f0091f130c/ty-0.0.75-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5e7b8b3472fb9bb2eeab314984b265df08a7a9d518867a9e6020eebc06570be2", size = 12527158, upload-time = "2026-08-26T20:23:02.767Z" },
{ url = "https://files.pythonhosted.org/packages/f2/11/7fd7001b0b5c6610bfbad7357e47d5fe6f82d4e84e94c53776a478f5e9f8/ty-0.0.75-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c6ccf34169821fe0d23e3360deeef981d217963412f1d087b9bdd32ec57f7a57", size = 12400533, upload-time = "2026-08-26T20:23:04.965Z" },
{ url = "https://files.pythonhosted.org/packages/fd/7f/1e284ea3d348d7be02f12d83bc22ed9ef193033f863f05b64db99027f141/ty-0.0.75-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842ebb41e9c6c334b40768704e20b1a69d5c6b08805b289d5e0e2565f49f2de1", size = 12420592, upload-time = "2026-08-26T20:23:07.427Z" },
{ url = "https://files.pythonhosted.org/packages/2d/ab/d813271543370c47fd74b5118f2066ab32b0983e907b1821f3f9a6d0fa7f/ty-0.0.75-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf7a5a723c5f1e0fab4ffbfe9bd95123a526ed48f206e5f25cb2161ca294007a", size = 12739219, upload-time = "2026-08-26T20:23:09.809Z" },
{ url = "https://files.pythonhosted.org/packages/31/5b/95b49cc5570fd92a7bf63732f649b31906158721e03c7fcb1b5be74ee3bf/ty-0.0.75-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54382f98e5da292fcd7104391afef5105c35bb2f312e29bea6f5fa419935255c", size = 13494046, upload-time = "2026-08-26T20:23:12.191Z" },
{ url = "https://files.pythonhosted.org/packages/2c/0d/502d2dd68173cf020e1ad2bdbab9544c86776de0b0e2ed15f8c2fe006e3d/ty-0.0.75-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac13b180dc2aade2cd243f56b01650e78bf091a2e522ad3bc947245d7837c613", size = 13938899, upload-time = "2026-08-26T20:23:14.764Z" },
{ url = "https://files.pythonhosted.org/packages/20/5b/f3b12a25c07224456219fc2bd20db0ad7e40b304be0ff6aad728da0135f9/ty-0.0.75-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:752df7951a443219d7f1ff817e3723c85d428565ff449e08a7a93ba821661526", size = 13656711, upload-time = "2026-08-26T20:23:17.145Z" },
{ url = "https://files.pythonhosted.org/packages/51/7b/f090ad306e2b15a07b332d647138c5264b89d9758855ecce8b8a10bcb153/ty-0.0.75-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fd399feedf7cee816563c1baec45fc1c0b3c89f1ea42364920b688004b5b7da", size = 13093499, upload-time = "2026-08-26T20:23:19.489Z" },
{ url = "https://files.pythonhosted.org/packages/f1/4b/f69b99aaaca0c7c65d5f114b186b26b21666f767b0c69eec99a2bdccc061/ty-0.0.75-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:d7625f6f56c7dc1e873579fdc9e432a0e21e302afe847ab60704d2303442a92e", size = 13520580, upload-time = "2026-08-26T20:23:21.789Z" },
{ url = "https://files.pythonhosted.org/packages/b6/e7/692c5f905c0345a15d2255fc74066d660f030254ae8dcdaf33f5a5c2f279/ty-0.0.75-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:89e7d527e95a2534b70cae29e94c104b84082760ea05927d23bb87280969c104", size = 12524095, upload-time = "2026-08-26T20:23:24.026Z" },
{ url = "https://files.pythonhosted.org/packages/ba/9a/f42b12cf265ea95344bf554764c4791cfb273bdd628aadd7c209af7cadc3/ty-0.0.75-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0843f134440740706e01bee5f88f4cfc10e9b018bddb9e4ef4c12dc9fc0c9aef", size = 12756591, upload-time = "2026-08-26T20:23:26.126Z" },
{ url = "https://files.pythonhosted.org/packages/7c/5e/9b180c133cb9cce48179a7d2bf9e1802d992aa8176a918e0e05205760b42/ty-0.0.75-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1bd0ec0e50ee1376875c88891efe6f549c3560fa5b2ddad79a425cd5a6218b9c", size = 12998754, upload-time = "2026-08-26T20:23:28.353Z" },
{ url = "https://files.pythonhosted.org/packages/39/f6/3c6ef5dd550103e29905121c67fb96a374564f31a2f44c6faa1af98c2d61/ty-0.0.75-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1f9eafd561f90110d5e29f589ec3e956c4686e2f6631348d99276436f5cbe4d1", size = 13316474, upload-time = "2026-08-26T20:23:30.857Z" },
{ url = "https://files.pythonhosted.org/packages/bb/52/12776337874c821076bd5368e352ccd9e67174790abe3b856f749cb3524b/ty-0.0.75-py3-none-win32.whl", hash = "sha256:05063a6fafe2154b794a7f964515d148e51acd186d72d4a3acd347ee9fa19336", size = 12316315, upload-time = "2026-08-26T20:23:33.528Z" },
{ url = "https://files.pythonhosted.org/packages/53/e6/bb51e16af5c7138c9f52f8f3d0a401a371c6798d092e3b74926f186a9814/ty-0.0.75-py3-none-win_amd64.whl", hash = "sha256:81cf1ba5f6b7536ad56747865214255d9bc8e80533a689dbb9ddeaad464b09f1", size = 12917267, upload-time = "2026-08-26T20:23:35.978Z" },
{ url = "https://files.pythonhosted.org/packages/39/73/4542f829107468b5de4231af67f29927c093bfad11f3c1e5b2c08fb1206b/ty-0.0.75-py3-none-win_arm64.whl", hash = "sha256:541c9af5b7a0ad23d15ec315a7da81150833c359f48124ed3789ff25eacd6f42", size = 12711024, upload-time = "2026-08-26T20:23:38.159Z" },
{ url = "https://files.pythonhosted.org/packages/aa/0c/600648778e1c79133ce6b6a5c4c2531ae16b90c9b30f5041b38b574f61b8/ty-0.0.84-py3-none-linux_armv6l.whl", hash = "sha256:868438e2b9abfc835dd5b5b07ed693db95d8348ac40e3228252511d63ae87695", size = 13935333, upload-time = "2026-09-24T13:15:31.167Z" },
{ url = "https://files.pythonhosted.org/packages/c5/3b/27f06f49945c36170765fad82076898039ae3873338e9865f876dd62f12c/ty-0.0.84-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b00f39b521f0b559cde0f6abf8dd47213b513b04f33d58efeb9b98486a16bb17", size = 13511328, upload-time = "2026-09-24T13:15:34.446Z" },
{ url = "https://files.pythonhosted.org/packages/fc/b6/b12dd130e7f30141f0645614f454c925991cd389b1cc6c8284fd6bf32326/ty-0.0.84-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8f78c2915567f2ee62ce0c24d86091bc76f81577677755e242d09951db588b9a", size = 13445445, upload-time = "2026-09-24T13:15:37.476Z" },
{ url = "https://files.pythonhosted.org/packages/44/96/f012de4b3c1d9a4773326621380d768b4d48c47e620dc012775c5e01c7d7/ty-0.0.84-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61155cad0921e890d86d1d911a40b3a0e924ef4bdc3b4f3865a6c89c7e3012dc", size = 13471235, upload-time = "2026-09-24T13:15:40.64Z" },
{ url = "https://files.pythonhosted.org/packages/05/32/dca630f5f5353fa7bf67eebccf1549df99b16656d21071d0df6677c826a5/ty-0.0.84-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:417c3bf14947ed16b0b92976ab333c27915590354e96d4f581709068d3811355", size = 13680704, upload-time = "2026-09-24T13:15:43.817Z" },
{ url = "https://files.pythonhosted.org/packages/44/8d/33702c8f62f05ad45b33644fb914d483de6a0a7bc8e51884e9b8773e6d69/ty-0.0.84-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e06ef117759f654f5379efe9ae79bda8a186016c016f1023d05c34f8e15c1546", size = 14518923, upload-time = "2026-09-24T13:15:46.802Z" },
{ url = "https://files.pythonhosted.org/packages/c8/a1/da3246e6ef2ae0e842bca4058b25c54bee55ab058ffff4ee54e72517ec01/ty-0.0.84-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a05d1d53db8b64410ab38c6e32c5898510584869d1d5dd9c0605db81c9aef7df", size = 15027731, upload-time = "2026-09-24T13:15:49.755Z" },
{ url = "https://files.pythonhosted.org/packages/20/17/b0099098a560aeb4f9fde6c912f9a81622c3e44e6555e1fbe322b368ec31/ty-0.0.84-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b92400494ab855cfb1204ac1101e3f53b2d09a8e21d171758b2cf9acdab1809e", size = 14748260, upload-time = "2026-09-24T13:15:52.713Z" },
{ url = "https://files.pythonhosted.org/packages/60/d5/32cd67aedb271f006e716ad093806c96c5d7e2af86be8255469dbd3d76c8/ty-0.0.84-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af17eb391ae3027fed9be1780bea555c2b8a25ba68e184c627b4981b2c9eaab7", size = 14205858, upload-time = "2026-09-24T13:15:55.677Z" },
{ url = "https://files.pythonhosted.org/packages/43/c4/638ac62ca2e8eca1b92e3e16273085744fada728b993500819b5c258ca15/ty-0.0.84-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:44cf06af0e7ec78ea6d8ff33a3450fc19627756a4fba681f7410d4e3ef63047a", size = 14573196, upload-time = "2026-09-24T13:15:59.165Z" },
{ url = "https://files.pythonhosted.org/packages/a6/f6/9ee81c5d8921e5fd5f10889ae563c95cd3272b31df2ada528919ca1cef6b/ty-0.0.84-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c6e56b443ff9ba462e34bfbc1e582004c2719ed35f8f93a433744b0ba0afb2d9", size = 13480760, upload-time = "2026-09-24T13:16:02.313Z" },
{ url = "https://files.pythonhosted.org/packages/f6/83/fbe5d1177667ae16d84c3242846b143809c9cc09568b333e5a9b4d5908f6/ty-0.0.84-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b6562fcc48820c1030e2a4509ef2c14ef93043ca4860280074314ac3a825b95", size = 13696346, upload-time = "2026-09-24T13:16:05.391Z" },
{ url = "https://files.pythonhosted.org/packages/86/9a/1b4ac9ddc34cc0ab4624bc219825d66af52f1ad87f4778ad08ad03fa06d5/ty-0.0.84-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dee7421451efcbd70f03e95a8f2c8d9e5ec3d35edcd27b4095ee00ee062abfc4", size = 13959410, upload-time = "2026-09-24T13:16:08.661Z" },
{ url = "https://files.pythonhosted.org/packages/c9/04/70e289437a67dfd686056ab4fd91880261a8233033a6a95d29393741fb97/ty-0.0.84-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:31e96307cf621babe969307dd657783d672e2d8bdbd06493710da635bf63fa07", size = 14350294, upload-time = "2026-09-24T13:16:11.865Z" },
{ url = "https://files.pythonhosted.org/packages/9c/f4/ae7dbd118425c850981d23efb850f0d9d7f6b8d2b852bde2767434f668b4/ty-0.0.84-py3-none-win32.whl", hash = "sha256:4bdc85f91cbaae35825f2b17bb4ac5de0563367875cb0f42b2bf07a1bf7ff2ba", size = 13176439, upload-time = "2026-09-24T13:16:15.049Z" },
{ url = "https://files.pythonhosted.org/packages/29/ec/994d87252f065dda5a500bc8afc726d18f6582d81d6f4ff1feb8a267c800/ty-0.0.84-py3-none-win_amd64.whl", hash = "sha256:71cc9aa7a7c89d4e12c6a814e9c0c3310ad5bee44efedbd6f5a42d91e9ac0f0d", size = 13962879, upload-time = "2026-09-24T13:16:18.191Z" },
{ url = "https://files.pythonhosted.org/packages/6d/1c/e6e91852b72566b1ab9aca504712857dfb89324c12092a5bd61d42d34427/ty-0.0.84-py3-none-win_arm64.whl", hash = "sha256:6c9d3718c4a0d318bc9c92af9b2aa85c3294e7dff54cf1d69ad79568f56516da", size = 13656453, upload-time = "2026-09-24T13:16:21.51Z" },
]
[[package]]
@@ -943,11 +943,11 @@ wheels = [
[[package]]
name = "urllib3"
version = "2.7.0"
version = "2.8.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
{ url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" },
]
[[package]]
@@ -448,11 +448,12 @@ class PostgresSaver(BasePostgresSaver):
Two-stage query, both stages cover ALL requested channels:
* Stage 1 (paged): dynamic SELECT over `checkpoints` with K parallel
JSONB key lookups (one column pair per channel) — no subquery, no
aggregation. Pages newest-first by `checkpoint_id` with a cursor;
page size is `_DELTA_PAGE_SIZE`. Stops paging when every channel
has found its seed or the chain is exhausted.
* Stage 1 (paged): dynamic SELECT over `checkpoints` with three
columns per channel: its version, an `EXISTS` probe for a stored
blob at that version, and its inline value. Pages newest-first by
`checkpoint_id` with a cursor; page size is `_DELTA_PAGE_SIZE`.
Stops paging when every channel has found its seed or a page comes
back short.
* Stage 2 (per-channel UNION ALL): one branch per channel reading
`checkpoint_writes` filtered to that channel's specific
@@ -172,30 +172,8 @@ class _DeltaStage2Row(TypedDict, total=False):
version: str | None # "b" rows only
# Multi-channel two-stage DeltaChannel reconstruction.
#
# Stage 1 scans checkpoint metadata (no blob bytes) and emits one row per
# checkpoint with K parallel JSONB key lookups (one column pair per
# requested delta channel: ver_i / hs_i). No subqueries, no aggregation.
# Python walks the parent chain once across all channels.
#
# Stage 2 fetches all writes and the seed blobs for ALL channels in a
# single roundtrip via `channel = ANY(%s)` and chain/seed-version
# filtering.
#
# Empirical comparison vs an alternative "ship full channel_versions /
# channel_values JSONB and let Python pick" form (1000 checkpoints,
# 8 total channels in graph, 3 delta channels requested):
#
# Postgres execution: A=0.24ms vs B=0.38ms (both negligible)
# End-to-end latency: A=6.83ms vs B=2.28ms (B is 3.0x faster)
# Wire payload: A=836KB vs B=330KB (61% smaller)
# Buffer hits: identical (167 blocks)
#
# B (this dynamic-columns design) wins because it avoids JSONB
# serialization on the wire and JSONB-to-dict deserialization in
# psycopg. Even at K=8 (8 delta channels = 16 dynamic columns), B
# still beats A end-to-end (4.2ms vs 6.8ms).
# Delta history is rebuilt in two queries; `_build_delta_stage1_sql` and
# `_build_delta_stage2_sql` document their shapes.
def _build_delta_stage1_sql(channels: Sequence[str], *, paged: bool) -> str:
@@ -335,10 +313,8 @@ def _build_delta_stage2_sql(
return " UNION ALL ".join(branches)
# Stage 1 rows are dynamic-shape dicts: {checkpoint_id, parent_checkpoint_id,
# ver_0, hs_0, ver_1, hs_1, ...}. Walking is parameterized by the channel
# list to map indices back to channel names — no static TypedDict here.
# `dict[str, Any]` is the practical signature.
# Stage 1 rows are dicts keyed by the per-channel aliases
# `_build_delta_stage1_sql` emits, so there is no static TypedDict.
class BasePostgresSaver(BaseCheckpointSaver[str]):
@@ -431,9 +407,11 @@ class BasePostgresSaver(BaseCheckpointSaver[str]):
(a) it found a stored value for its channel — a blob or an inline
primitive (channel becomes seeded),
(b) it reached a real root (parent_of[cid] is None — fully
materialized at this point), or
materialized at this point),
(c) the next ancestor cid isn't in `parent_of` yet (waiting for
a later page; the cursor stays put).
a later page; the cursor stays put), or
(d) the target's own row isn't in `parent_of` yet (the walk has
not started; no cursor is set, so a later page retries).
Mutates `chain_by_ch`, `seed_ver_by_ch`, `seed_inline_by_ch`,
`walk_cursor_by_ch`, and `seeded` in place.
@@ -441,9 +419,12 @@ class BasePostgresSaver(BaseCheckpointSaver[str]):
for i, ch in enumerate(channels):
if ch in seeded:
continue
# First-time entry: cursor starts at the target's parent.
# Pages start at the thread head, so the target may not have
# loaded yet; a `None` cursor would read as "target is a root".
if ch not in walk_cursor_by_ch:
walk_cursor_by_ch[ch] = parent_of.get(target_id)
if target_id not in parent_of:
continue
walk_cursor_by_ch[ch] = parent_of[target_id]
cur_cid = walk_cursor_by_ch[ch]
ch_chain = chain_by_ch[ch]
hb_i = hb_by_i_by_cid[i]
@@ -0,0 +1,132 @@
from __future__ import annotations
from typing import Any
from uuid import uuid4
import pytest
from langgraph.checkpoint.base import (
Checkpoint,
DeltaChannelHistory,
empty_checkpoint,
)
from langgraph.checkpoint.base.id import uuid6
from langgraph.checkpoint.serde.types import _DeltaSnapshot
from langgraph.checkpoint.postgres import PostgresSaver
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
from langgraph.checkpoint.postgres.base import _DELTA_PAGE_SIZE
from tests.conftest import DEFAULT_URI
CHANNEL = "items"
STEPS = 8
SEED_STEP = 1
SEED_VALUE = [10, 20]
TARGET_STEP = 4
# The real page size is the control; the rest leave the target off the first
# page (three checkpoints are newer than it).
PAGE_SIZES = [_DELTA_PAGE_SIZE, 3, 2, 1]
def _step_args(
thread_id: str, step: int, parent: dict | None
) -> tuple[dict, Checkpoint, dict[str, Any]]:
config: dict = {"configurable": {"thread_id": thread_id, "checkpoint_ns": ""}}
if parent is not None:
config["configurable"]["checkpoint_id"] = parent["configurable"][
"checkpoint_id"
]
checkpoint: Checkpoint = empty_checkpoint()
checkpoint["id"] = str(uuid6(clock_seq=step))
checkpoint["channel_versions"][CHANNEL] = f"v{step}"
if step == SEED_STEP:
checkpoint["channel_values"][CHANNEL] = _DeltaSnapshot(list(SEED_VALUE))
return config, checkpoint, {CHANNEL: f"v{step}"}
return config, checkpoint, {}
async def _abuild_chain(saver: AsyncPostgresSaver) -> list[dict]:
thread_id = str(uuid4())
parent: dict | None = None
configs: list[dict] = []
for step in range(STEPS):
config, checkpoint, new_versions = _step_args(thread_id, step, parent)
parent = await saver.aput(
config,
checkpoint,
{"source": "loop", "step": step, "parents": {}},
new_versions,
)
await saver.aput_writes(parent, [(CHANNEL, f"w{step}")], str(uuid4()))
configs.append(parent)
return configs
def _build_chain(saver: PostgresSaver) -> list[dict]:
thread_id = str(uuid4())
parent: dict | None = None
configs: list[dict] = []
for step in range(STEPS):
config, checkpoint, new_versions = _step_args(thread_id, step, parent)
parent = saver.put(
config,
checkpoint,
{"source": "loop", "step": step, "parents": {}},
new_versions,
)
saver.put_writes(parent, [(CHANNEL, f"w{step}")], str(uuid4()))
configs.append(parent)
return configs
def _assert_history(entry: DeltaChannelHistory, page_size: int) -> None:
seed = entry.get("seed")
assert isinstance(seed, _DeltaSnapshot), (
f"page_size={page_size}: expected a snapshot seed, "
f"got {entry.get('seed', '<missing>')!r}"
)
assert seed.value == SEED_VALUE
assert [w[2] for w in entry["writes"]] == ["w1", "w2", "w3"], (
f"page_size={page_size}: got {[w[2] for w in entry['writes']]}"
)
@pytest.mark.parametrize("page_size", PAGE_SIZES)
async def test_async_target_older_than_the_first_page(
page_size: int, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr("langgraph.checkpoint.postgres.aio._DELTA_PAGE_SIZE", page_size)
async with AsyncPostgresSaver.from_conn_string(DEFAULT_URI) as saver:
await saver.setup()
configs = await _abuild_chain(saver)
result = await saver.aget_delta_channel_history(
config=configs[TARGET_STEP], channels=[CHANNEL]
)
_assert_history(result[CHANNEL], page_size)
@pytest.mark.parametrize("page_size", PAGE_SIZES)
def test_sync_target_older_than_the_first_page(
page_size: int, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr("langgraph.checkpoint.postgres._DELTA_PAGE_SIZE", page_size)
with PostgresSaver.from_conn_string(DEFAULT_URI) as saver:
saver.setup()
configs = _build_chain(saver)
result = saver.get_delta_channel_history(
config=configs[TARGET_STEP], channels=[CHANNEL]
)
_assert_history(result[CHANNEL], page_size)
async def test_root_target_has_no_history_and_still_terminates(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr("langgraph.checkpoint.postgres.aio._DELTA_PAGE_SIZE", 1)
async with AsyncPostgresSaver.from_conn_string(DEFAULT_URI) as saver:
await saver.setup()
configs = await _abuild_chain(saver)
result = await saver.aget_delta_channel_history(
config=configs[0], channels=[CHANNEL]
)
assert result[CHANNEL] == {"writes": []}
+151 -119
View File
@@ -17,16 +17,16 @@ wheels = [
[[package]]
name = "anyio"
version = "4.14.2"
version = "4.15.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
{ name = "idna" },
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
{ name = "typing-extensions", version = "4.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.15'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/61/cc/a381afa6efea9f496eff839d4a6a1aed3bfafc7b3ab4b0d1b243a12573dd/anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f", size = 260176, upload-time = "2026-07-12T20:29:07.082Z" }
sdist = { url = "https://files.pythonhosted.org/packages/a9/d2/f4d173e22df740bc37b1db102b386ba719b66e95b0f0d751f556b387e6d2/anyio-4.15.1.tar.gz", hash = "sha256:9f28306018cbd6d329e64a36d58256edff76dd996fe423bc957326e578b82a94", size = 276966, upload-time = "2026-09-05T10:42:39.44Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/da/35/f2287558c17e29fafc8ef3daf819bb9834061cfa43bff8014f7df7f63bdc/anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", size = 125813, upload-time = "2026-07-12T20:29:05.763Z" },
{ url = "https://files.pythonhosted.org/packages/12/b8/4bd346e22b28902df4d651910f5242c28d84e4a5c2435ca5c3f797ed7e2e/anyio-4.15.1-py3-none-any.whl", hash = "sha256:6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101", size = 132079, upload-time = "2026-09-05T10:42:37.923Z" },
]
[[package]]
@@ -159,7 +159,7 @@ name = "exceptiongroup"
version = "1.3.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
{ name = "typing-extensions", version = "4.16.0", source = { registry = "https://pypi.org/simple" } },
]
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
wheels = [
@@ -254,7 +254,8 @@ dependencies = [
{ name = "pydantic" },
{ name = "pyyaml" },
{ name = "tenacity" },
{ name = "typing-extensions" },
{ name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.15'" },
{ name = "typing-extensions", version = "4.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.15'" },
{ name = "uuid-utils" },
]
sdist = { url = "https://files.pythonhosted.org/packages/6e/58/3ad53096eee1e07728e8219ded30ae308b0f2b8b7b26b8ebb6371917c0f5/langchain_core-1.5.2.tar.gz", hash = "sha256:2d13ab35b42eec63d4669a483776b8cdd778ee764107149369fb369d84c08c41", size = 972322, upload-time = "2026-07-28T16:38:37.977Z" }
@@ -267,7 +268,8 @@ name = "langchain-protocol"
version = "0.0.18"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
{ name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.15'" },
{ name = "typing-extensions", version = "4.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.15'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d2/59/b5959aea96faa9146e2e49a7a22882b3528c62efafe9a6a95beab30c2305/langchain_protocol-0.0.18.tar.gz", hash = "sha256:ec3e11782f1ed0c9db38e5a9ed01b0e7a0d3fba406faa8aef6594b73c56a63e6", size = 6150, upload-time = "2026-06-18T17:08:26.959Z" }
wheels = [
@@ -597,15 +599,15 @@ wheels = [
[[package]]
name = "psycopg"
version = "3.3.4"
version = "3.3.6"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
{ name = "typing-extensions", version = "4.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" },
{ name = "tzdata", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/db/2f/cb91e5502ec9de1de6f1b76cfbf69531932725361168bb06963620c77e2e/psycopg-3.3.4.tar.gz", hash = "sha256:e21207764952cff81b6b8bdacad9a3939f2793367fdac2987b3aac36a651b5bc", size = 165799, upload-time = "2026-05-01T23:31:55.179Z" }
sdist = { url = "https://files.pythonhosted.org/packages/76/26/3ea4ca5eaea1c0debcdf7ee7c1613fbe721dc27a03c461c0817ffd8a0601/psycopg-3.3.6.tar.gz", hash = "sha256:c081f2250df751a943036e42db6df4571c66cd0aabe8291a7a506512b12007d2", size = 168171, upload-time = "2026-09-18T13:22:55.152Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5c/e0/7b3dee031daae7743609ce3c746565d4a3ed7c2c186479eb48e34e838c64/psycopg-3.3.4-py3-none-any.whl", hash = "sha256:b6bbc25ccf05c8fad3b061d9db2ef0909a555171b84b07f29458a447253d679a", size = 213001, upload-time = "2026-05-01T23:20:50.816Z" },
{ url = "https://files.pythonhosted.org/packages/4e/de/748bd7609c71cae5d737f0ba9192f19329f70180ecda8fff3cac02c5abe3/psycopg-3.3.6-py3-none-any.whl", hash = "sha256:a1db9f7148b06a28606767efaca51fa6f9398c5c0a3810519be69d7000bdb631", size = 215490, upload-time = "2026-09-18T13:15:29.374Z" },
]
[package.optional-dependencies]
@@ -615,76 +617,88 @@ binary = [
[[package]]
name = "psycopg-binary"
version = "3.3.4"
version = "3.3.6"
source = { registry = "https://pypi.org/simple" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/bf/70d8a60488f9955cbbcd538beae44d56bb2f1d19e673b72788f2d343ff55/psycopg_binary-3.3.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b7bfff1ca23732b488cbca3076fc11bc98d520ee122514fdb17a8e20d3338f5a", size = 4609750, upload-time = "2026-05-01T23:24:20.06Z" },
{ url = "https://files.pythonhosted.org/packages/db/b0/29e98ba210c9dbc75a6dc91e3f99b9e06ea901a62ca95804e02a1ae13e6b/psycopg_binary-3.3.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:32a6fbf8481e3a370d0d72b860d35948a693cb01281da217f7b2f307636e591a", size = 4676700, upload-time = "2026-05-01T23:25:21.727Z" },
{ url = "https://files.pythonhosted.org/packages/8e/ab/3df087b3c12bf74e47c08204172b2fabb5a144679110d5c7ad12d9201323/psycopg_binary-3.3.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bdef84570ebbce1d42b4e7ea952d21c414c5f118ad02fee00c5625f35e134429", size = 5496319, upload-time = "2026-05-01T23:25:28.271Z" },
{ url = "https://files.pythonhosted.org/packages/87/9a/f088207b4cd6772f9e0d8a91807e79fa2458d4eb9eb1ae406c68415f2bec/psycopg_binary-3.3.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fa1cbc10768a796c96d3243656016bf4e337c81c71097270bb7b0ad6210d9765", size = 5171906, upload-time = "2026-05-01T23:25:34.004Z" },
{ url = "https://files.pythonhosted.org/packages/48/45/4523a857f253871d75c22e1c2e79fd47e599e736bcba1bad58d83e24be02/psycopg_binary-3.3.4-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cf7f73a4a792bc5db58a4b385d8a1467e8d468f7548702fb0ed1e9b7501b1c13", size = 6762621, upload-time = "2026-05-01T23:25:41.392Z" },
{ url = "https://files.pythonhosted.org/packages/7c/d1/925bf776503345bef428e6c45fb017d0139ddbe0e211814b585c4253dca8/psycopg_binary-3.3.4-cp310-cp310-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d7b4d40c153fa352ab3cca530f3a0baedf7621b2ebcbd7f084009522c21788fc", size = 5006319, upload-time = "2026-05-01T23:25:51.419Z" },
{ url = "https://files.pythonhosted.org/packages/6f/aa/99727337206fbba357ca084bf4ea8b29dc986f61842a2685859af61416db/psycopg_binary-3.3.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f9b1c2533af01cd7648378599f82b0b8ae32f293296e6eec5753a625bc97ef28", size = 4535388, upload-time = "2026-05-01T23:25:57.957Z" },
{ url = "https://files.pythonhosted.org/packages/0b/a4/567ba2c37d19d8c2f63d836385dfd2495aa5897bbee6cfab104d9ee58624/psycopg_binary-3.3.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ad3bc94054876155549fdaedf4a46d1ec69d39a5bcee377148afe498e84c4b8e", size = 4224544, upload-time = "2026-05-01T23:26:03.832Z" },
{ url = "https://files.pythonhosted.org/packages/b7/23/86457f5a82731685d7701de7bfaa5eb783dd1fecbf875321897d9d9ce33a/psycopg_binary-3.3.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:eb4eed2079c01a4850bf467deacfab56d356d4225040170af03dc9958321242d", size = 3956282, upload-time = "2026-05-01T23:26:09.983Z" },
{ url = "https://files.pythonhosted.org/packages/a7/d8/249456df16d47de082abd9b73bce8ccdeb0293eb12e590f9150c7cbdb788/psycopg_binary-3.3.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f80e3f2b5331dbbf0901bcb658056c03eeb2c1ef31d774afb0d61598b242e744", size = 4261736, upload-time = "2026-05-01T23:26:16.798Z" },
{ url = "https://files.pythonhosted.org/packages/15/6b/c4abe228acafd8a385c1fb615d4f1e3c9b8ad7a4e4f0e84118ba3ffeed9c/psycopg_binary-3.3.4-cp310-cp310-win_amd64.whl", hash = "sha256:574ea21a9651958f1535c5a1c649c7409e9168bcbffa29a3f2f961f58b322949", size = 3570620, upload-time = "2026-05-01T23:26:22.655Z" },
{ url = "https://files.pythonhosted.org/packages/b6/82/df3312c0ca083d5b43b352f27d4dd8b1e614bd334473074715d9e0000da4/psycopg_binary-3.3.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:612a627d733f695b1de1f9b4bd511c15f999a5d8b915d444bbd7dd71cf3370da", size = 4609813, upload-time = "2026-05-01T23:26:30.612Z" },
{ url = "https://files.pythonhosted.org/packages/1f/b5/d74d542458d3e8ac0571d8a88f57ca369999b9a82f4fa528052d0d7d3e4c/psycopg_binary-3.3.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:13a7f380824c35896dcac7fe0f61440f7ca49d6dc73f3c13a9a4471e6a3b302e", size = 4676799, upload-time = "2026-05-01T23:26:38.475Z" },
{ url = "https://files.pythonhosted.org/packages/09/67/06bab9c60671999f4c6ceff1b334f3ac1f9fc5789eb467c714623ea21de9/psycopg_binary-3.3.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:276904e3452d6a23d474ef9a21eee19f20eed3d53ddd2576af033827e0ba0992", size = 5497050, upload-time = "2026-05-01T23:26:47.061Z" },
{ url = "https://files.pythonhosted.org/packages/72/9b/023433e2b20f970de1e22d29132a95281277646da0b2e2879dd4ee94b8c1/psycopg_binary-3.3.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ab8cca8ef8fb1ccf5b048ae5bd78ba55b9e4b5d472e3ce5ca39ff4d2a9c249e4", size = 5172428, upload-time = "2026-05-01T23:26:56.708Z" },
{ url = "https://files.pythonhosted.org/packages/08/cd/ae16da8fde228a38b2fe9269bbc13cf89e0186173f2265600f02d6a71e64/psycopg_binary-3.3.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7465bfe6087d2d5b42d4c53b9b11ca9f218e477317a4a162a10e3c19e984ba8e", size = 6762746, upload-time = "2026-05-01T23:27:07.023Z" },
{ url = "https://files.pythonhosted.org/packages/4f/81/0ba09fa5f5f88779093a2541a8e02489825721f258ab88058b11d68b3eb5/psycopg_binary-3.3.4-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:22cdbf5f91ef7bb91fe0c5757e1962d3127a8010256eefd9c61fcaf441802097", size = 5006033, upload-time = "2026-05-01T23:27:12.221Z" },
{ url = "https://files.pythonhosted.org/packages/73/6a/629136040cc3497adb442a305710b5913f2a754d4630fc3d3717c4c0df65/psycopg_binary-3.3.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e2631da29253a98bd496e6c4813b24e09a4fe3fb2a9e88513305d6f8747cce95", size = 4534175, upload-time = "2026-05-01T23:27:18.248Z" },
{ url = "https://files.pythonhosted.org/packages/7c/32/1027f843c6dc2d5d51960ee62cc0c2cf755a4c39455aff1371173edbef7d/psycopg_binary-3.3.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7f7668f30b9dd5163197e5cbf4e0efd54e00f0a859cc566ce56cfc31f4054839", size = 4224203, upload-time = "2026-05-01T23:27:24.3Z" },
{ url = "https://files.pythonhosted.org/packages/0b/e1/380a724d9093c74adb14d4fce920ea8327838abb61f760b1448586b14a8e/psycopg_binary-3.3.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:cffc3408d77a27973f33e5d909b624cce683db5fc25964b02fe0aae7886c1007", size = 3954509, upload-time = "2026-05-01T23:27:30.815Z" },
{ url = "https://files.pythonhosted.org/packages/db/cd/895893ae575a09c97ccfd5def070d88993d955ef34df45a881fd5ff506d6/psycopg_binary-3.3.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0579252a1202cd73e4da137a1426e2dae993ae44e757605344282af3a082848c", size = 4259551, upload-time = "2026-05-01T23:27:38.828Z" },
{ url = "https://files.pythonhosted.org/packages/dd/c6/2330a20794e37a3ec609ef2fd8522919ec7a4395a1abf979a8e2d1775cd5/psycopg_binary-3.3.4-cp311-cp311-win_amd64.whl", hash = "sha256:41f2ec0fea529832982bcb6c9415de3c86264ebe562b77a467c0fbcd7efbba8d", size = 3572054, upload-time = "2026-05-01T23:27:45.455Z" },
{ url = "https://files.pythonhosted.org/packages/95/7d/03818e13ba7f36de93573c93ee3482006d3dfa8b0f8d28df511bad0a1a92/psycopg_binary-3.3.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5ab28a2a7649df3b72e6b674b4c190e448e8e77cf496a65bd846472048de2089", size = 4591122, upload-time = "2026-05-01T23:27:56.162Z" },
{ url = "https://files.pythonhosted.org/packages/a5/b9/11b341edf8d54e2694726b273fe9652b254d989f4f63e3ac6816ad6b55f4/psycopg_binary-3.3.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6402a9d8146cf4b3974ded3fd28a971e83dc6a0333eb7822524a3aa20b546578", size = 4669943, upload-time = "2026-05-01T23:28:04.522Z" },
{ url = "https://files.pythonhosted.org/packages/8b/18/4665bacd65e7865b4372fcd8abb8b9186ada4b0025f8c2ca691b364a556c/psycopg_binary-3.3.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:580ae30a5f95ccd90008ec697d3ed6a4a2047a516407ad904283fa42086936e9", size = 5469697, upload-time = "2026-05-01T23:28:11.337Z" },
{ url = "https://files.pythonhosted.org/packages/7c/b1/b83136c6e510593d9b0c759ba5384337bc4ad82d19fda675adc4b2703c84/psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7510c37550f91a187e3660a8cc50d4b760f8c3b8b2f89ebc5698cd2c7f2c85d", size = 5152995, upload-time = "2026-05-01T23:28:20.529Z" },
{ url = "https://files.pythonhosted.org/packages/67/8d/a9821e2a648afe6091989929982a3b0f00b2631a859cb81379728f08fb75/psycopg_binary-3.3.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77df19583501ea288eaf15ac0fe7ad01e6d8091a91d5c41df5c718f307d8e31b", size = 6738180, upload-time = "2026-05-01T23:28:30.654Z" },
{ url = "https://files.pythonhosted.org/packages/7e/58/2e349e8d23905dc2317b80ac65f48fb6f821a4777a4e994a60da91c4850f/psycopg_binary-3.3.4-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:018fbed325936da502feb546642c982dcc4b9ffdea32dfef78dbf3b7f7ad4070", size = 4978828, upload-time = "2026-05-01T23:28:37.277Z" },
{ url = "https://files.pythonhosted.org/packages/45/48/57b00d03b4721878326122a1f1e6b0a90b85bcaec56b5b2f8ea6cfa45235/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:17a21953a9e5ff3a16dab692625a3676e2f101db5e40072f39dbee2250194d68", size = 4509757, upload-time = "2026-05-01T23:28:43.078Z" },
{ url = "https://files.pythonhosted.org/packages/25/37/33b47d8c007df69aec500df5889767c4d313748e8e9e27a2fef8a6dabcee/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:eb05ee1c2b817d27c537333224c9e83c7afb86fe7296ba970990068baf819b16", size = 4190546, upload-time = "2026-05-01T23:28:50.016Z" },
{ url = "https://files.pythonhosted.org/packages/ca/c6/32b0835dbc2122617902b649d76a91c1e75406e76bf3d595b0c3bb5ffad6/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:773d573e11f437ce0bdb95b7c18dc58390494f96d43f8b45b9760436114f7652", size = 3926197, upload-time = "2026-05-01T23:28:55.55Z" },
{ url = "https://files.pythonhosted.org/packages/cd/68/d190ef0c0c5b16ded07831dabc8ddd412f4cdab07ec6e30ed38d9bda0e1f/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:71e55ccbdfae79a2ed9c6369c3008a3025817ff9d7e27b32a2d84e2a4267e66e", size = 4236627, upload-time = "2026-05-01T23:29:05.336Z" },
{ url = "https://files.pythonhosted.org/packages/25/8f/81dcbc2e8454b74d14881275ea45f00791052dac531a9fa8be1730d1685b/psycopg_binary-3.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:494ca54901be8cf9eb7e02c25b731f2317c378efa44f43e8f9bd0e1184ae7be4", size = 3560782, upload-time = "2026-05-01T23:29:11.967Z" },
{ url = "https://files.pythonhosted.org/packages/09/43/13e9c406fbbf354580476e248a16b64802a376873ebe6339e30bb655572d/psycopg_binary-3.3.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fbd1d4ed566895ad2d3bf4ddfd8bae90026930ddf29df3b9d91d32c8c47866a7", size = 4590377, upload-time = "2026-05-01T23:29:18.782Z" },
{ url = "https://files.pythonhosted.org/packages/22/be/2923cd7c3683e7afdecf4f10796a18de02f5c5ddc0969aa2ad0a8cdd3bbd/psycopg_binary-3.3.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:75a9067e236f9b9ae3535b66fe99bddb33d39c0de10112e49b9ab11eee53dc31", size = 4669023, upload-time = "2026-05-01T23:29:25.884Z" },
{ url = "https://files.pythonhosted.org/packages/96/a0/2c913d6fe13d6a8bd13597d36739bf47af063ad9399e402cfecab16f3c1e/psycopg_binary-3.3.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:b56b603ebcea8aa10b46228b8410ba7f13e7c2ee54389d4d9be0927fd8ce2a70", size = 5467423, upload-time = "2026-05-01T23:29:33.416Z" },
{ url = "https://files.pythonhosted.org/packages/e7/38/205d10bc1ad0df4a21c5c51659126bd3ea0ef98fcad1e852f78c249bb9c3/psycopg_binary-3.3.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c677c4ad433cb7150c8cd304a0769ae3bcfbe5ea0676eb53faa7b1443b16d0d3", size = 5151137, upload-time = "2026-05-01T23:29:42.013Z" },
{ url = "https://files.pythonhosted.org/packages/36/fc/f0381ddcd45eff3bb70dbca6823a996048d7f507b2ec3fc92c6fabc0fe87/psycopg_binary-3.3.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:26df2717e59c0473e4465a97dfb1b7afebaa479277870fd5784d1436470db47c", size = 6736671, upload-time = "2026-05-01T23:29:51.626Z" },
{ url = "https://files.pythonhosted.org/packages/95/40/fa545ae152c24327651e5624e4902121e808270be36c10b12e9939be09bc/psycopg_binary-3.3.4-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1dc1f79fd16bb1f3f4421417a514607539f17804d95c7ed617265369d1981cae", size = 4979601, upload-time = "2026-05-01T23:29:56.961Z" },
{ url = "https://files.pythonhosted.org/packages/86/e4/2f8a47ee97f90cd2b933d0463081d35631ff419de2b8c984a5f369857de0/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:136f199a407b5348b9b857c504aff60c77622a28482e7195839ce1b51238c4cc", size = 4510513, upload-time = "2026-05-01T23:30:07.243Z" },
{ url = "https://files.pythonhosted.org/packages/0e/0e/94e842ff4a7f98ed162580ca2e8b8864b28c1e0350f2443f8ee47f821167/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b6f5a29e9c775b9f12a1a717aa7a2c80f9e1db6f27ba44a5b59c80ac61d2ffcf", size = 4187243, upload-time = "2026-05-01T23:30:15.352Z" },
{ url = "https://files.pythonhosted.org/packages/d0/83/fc6c174b672e29b7de996ea77b6cbddf46c891751c3355f6974292baa6b4/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ee17a2cf4943cde261adfad1bbc5bf38d6b3776d7afff74c7cabcbeaeb08c260", size = 3927347, upload-time = "2026-05-01T23:30:21.186Z" },
{ url = "https://files.pythonhosted.org/packages/e9/65/768364d4a97a15b1a7f47ba52688c1686f22941d8332a8398cefc468e25f/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c4ab71be17bdca30cb34c34c4e1496e2f5d6f20c199c12bad226070b22ef9bf", size = 4236393, upload-time = "2026-05-01T23:30:26.211Z" },
{ url = "https://files.pythonhosted.org/packages/bd/3b/218efbc9e645becd80cdf651acda05f85cfe546b7a9c0458c7cbc8fe1f74/psycopg_binary-3.3.4-cp313-cp313-win_amd64.whl", hash = "sha256:dbfdb9b6cc79f31104a7b162a2b921b765fcc62af6c00540a167a8de47e4ed38", size = 3564592, upload-time = "2026-05-01T23:30:31.764Z" },
{ url = "https://files.pythonhosted.org/packages/48/a6/828c9185701dab71b234c2a76c38a08b098ebfec5020716b4e93807492b5/psycopg_binary-3.3.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:28b7398fdd19db3232c884fb24550bdfe951221f510e195e233299e4c9b78f97", size = 4607292, upload-time = "2026-05-01T23:30:38.962Z" },
{ url = "https://files.pythonhosted.org/packages/92/58/5b40dbc9d839045c9dae956960e4fb6d20bcabe6c59a2aa34fc3a371913f/psycopg_binary-3.3.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1fbaa292a3c8bb61b45df1ad3da1908ccee7cb889db9425e3557d9e34e2a4829", size = 4687023, upload-time = "2026-05-01T23:30:47.227Z" },
{ url = "https://files.pythonhosted.org/packages/85/a9/793f0ac107a9003b48441d0d1f9f616d96e0f37458dd8dc12528ceff55fb/psycopg_binary-3.3.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94596f9e7633ee3f6440711d43bb70aa31cc0a46a900ab8b4201a366ace5c9e7", size = 5486985, upload-time = "2026-05-01T23:30:55.517Z" },
{ url = "https://files.pythonhosted.org/packages/8f/26/42e8533497e2592334f68ec529cf5f840f7fa4e99575a4bb61aa184dbfbf/psycopg_binary-3.3.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8c0056529e68dbe9184cd4019a1f3d8f3a4ead2f6fc7a5afcf27d3314edd1277", size = 5168745, upload-time = "2026-05-01T23:31:01.904Z" },
{ url = "https://files.pythonhosted.org/packages/15/af/b7151776cc08d5935d45c833ec818a9beb417cf7c08239af1aafbdae78ee/psycopg_binary-3.3.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c09aad7051326e7603c14e50636db9c01f78272dc54b3accff03d46370461e6", size = 6761486, upload-time = "2026-05-01T23:31:14.511Z" },
{ url = "https://files.pythonhosted.org/packages/d0/ed/c92533b9124712d592cbf1cd6c76da933a2e0acea81dfe1fbe7e735f0cff/psycopg_binary-3.3.4-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:514404ed543efd620c85602b747df2a23cf1241b4067199e1a66f2d2757aaa41", size = 4997427, upload-time = "2026-05-01T23:31:20.901Z" },
{ url = "https://files.pythonhosted.org/packages/a2/23/ccadfd0de416aa188356daa199453af24087b042e296088706d190ae0295/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:46893c26858be12cc49ca4226ed6a60b4bfccadd946b3bebb783a60b38788228", size = 4533549, upload-time = "2026-05-01T23:31:26.204Z" },
{ url = "https://files.pythonhosted.org/packages/fd/a0/c8f43cee36386f7bc891ab41a9d31ea07cf9826038e732da79f26b1e5f34/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:df1d567fc430f6df15c9fcf67d87685fc49bdb325adc0db5af1adfb2f44eb5c9", size = 4210256, upload-time = "2026-05-01T23:31:33.884Z" },
{ url = "https://files.pythonhosted.org/packages/4e/2c/c1547871be3790676e8868b38655496422f94f0978dfb66b74bdba2f1676/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:6b9016b1714da4dd5ecaaa75b82098aa5a0b87854ce9b092e21c27c4ae23e014", size = 3946204, upload-time = "2026-05-01T23:31:39.626Z" },
{ url = "https://files.pythonhosted.org/packages/c4/b1/f6670f00fa7ea601584623f6c11602ab92117d83eaff885e0210f6de7418/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:47c656a8a7ba6eb0cff1801a4caaa9c8bdc12d03080e273aff1c8ac39971a77e", size = 4255811, upload-time = "2026-05-01T23:31:44.986Z" },
{ url = "https://files.pythonhosted.org/packages/eb/e6/5fff07a70d1f945ed90ae131c3bd76cab32beff7c58c6db15ad5820b6d1f/psycopg_binary-3.3.4-cp314-cp314-win_amd64.whl", hash = "sha256:c37e024c07308cd06cf3ec51bfd0e7f6157585a4d84d1bce4a7f5f7913719bf8", size = 3666849, upload-time = "2026-05-01T23:31:51.165Z" },
{ url = "https://files.pythonhosted.org/packages/52/92/00350a66de0af05e41d01aa3134e3970045e816afed3f99d58ec1abe15b2/psycopg_binary-3.3.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7beb3e41c9a1e509f3ed85263386588cbe3e975aa67be21f79f44fd35ffaeefc", size = 4728682, upload-time = "2026-09-18T13:15:36.605Z" },
{ url = "https://files.pythonhosted.org/packages/91/fc/afa9c7fd316a469af7ede6ebb020eac482f5d827fae57d5310c9bc0c41ae/psycopg_binary-3.3.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:aa73160077345ec21b3f51e8e24b3de2e99586217e497629326eb9b2ea88c52e", size = 4777111, upload-time = "2026-09-18T13:15:46.566Z" },
{ url = "https://files.pythonhosted.org/packages/f2/44/7c1e015f1bc56b36ff1369f09e852b2d83ccefd5a669a42633a916cdedc4/psycopg_binary-3.3.6-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f87dbdc42e78ee0f7ea180c03f8c78e80a949e373066629bd90fefff10552dff", size = 5592755, upload-time = "2026-09-18T13:15:52.886Z" },
{ url = "https://files.pythonhosted.org/packages/3b/ae/314a251ca918cdac380bce1b87839ade9355382ea749e6ef3ba75ba0c09f/psycopg_binary-3.3.6-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a9348c5b43a3bb5ef8c2e89d5237c9c87eeafb01d338c84a7aebbc5cd0313299", size = 5267949, upload-time = "2026-09-18T13:16:00.53Z" },
{ url = "https://files.pythonhosted.org/packages/b6/9f/3bb0cfe9bb0f31ca57cf486ddc8c9ac51251aed8181bf88ff870b2623105/psycopg_binary-3.3.6-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a52991594ac4db888c7d39bccef331797e30cb31a95cae02cf2607f83a42dc2", size = 6862403, upload-time = "2026-09-18T13:16:10.385Z" },
{ url = "https://files.pythonhosted.org/packages/c4/d6/7032c10309c3155e9b24300fdcc9a1afa539cfd20ce52fdef74a46f10161/psycopg_binary-3.3.6-cp310-cp310-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5ea8beeb5541780b4b50b462eeacbc4f594ce3b911dc20c81c75f267876f71d2", size = 5107271, upload-time = "2026-09-18T13:16:16.843Z" },
{ url = "https://files.pythonhosted.org/packages/61/cc/79add2cf92684cf1a81da134b32caa662c25c72d0cc905d181ef4455f834/psycopg_binary-3.3.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:198a48e68cc99ccac03ba95ac857e73aa66f3bf6be77019fafb0832a05f7ad03", size = 4627984, upload-time = "2026-09-18T13:16:23.889Z" },
{ url = "https://files.pythonhosted.org/packages/c9/48/6dfb14f9350c14af6a2edb3c31262051b8cd94e2186e4b831e46dbbe8cd9/psycopg_binary-3.3.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fa34eb47969297471db7b7f193622c7e3ee839ec05abd05f1fe104d5b1b1dcf4", size = 4322054, upload-time = "2026-09-18T13:16:29.33Z" },
{ url = "https://files.pythonhosted.org/packages/29/35/2982338716a91cbb4dfc866be015be4457ee8106a445aabf3d1fb6a270e0/psycopg_binary-3.3.6-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:b979a42815410432420275412633960807178b1ce26591a16ce06e78a5bd4bb2", size = 4048471, upload-time = "2026-09-18T13:16:34.119Z" },
{ url = "https://files.pythonhosted.org/packages/24/e1/171b1db1542c5f76a678b7ee0a7800bebc9735a0a03417c76cf948bfd63c/psycopg_binary-3.3.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:889e42acec10450185e0cdfb396f375e2c1a8d7737c114830a7fde4654f59e30", size = 4353931, upload-time = "2026-09-18T13:16:38.692Z" },
{ url = "https://files.pythonhosted.org/packages/08/89/4424e62a944eef40bd9326ada4ae23802b28eab6502af91e84ef7bba74fb/psycopg_binary-3.3.6-cp310-cp310-win_amd64.whl", hash = "sha256:cbd5f73073ed19c378d4c35499db1e3e703a5b1a324e521204065967bfaa7a18", size = 3674362, upload-time = "2026-09-18T13:16:44.454Z" },
{ url = "https://files.pythonhosted.org/packages/70/86/b71166048974d49c6d136b2ed1c0e5bec0b974d8c4de5cbce7e86a9e412a/psycopg_binary-3.3.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:be4f9b3c9338ac5dd217c5847e21521b396c8117f78dc420d495a5c49bbef874", size = 4728002, upload-time = "2026-09-18T13:16:53.393Z" },
{ url = "https://files.pythonhosted.org/packages/12/1d/1e06c0de7ed5aed898acb87544eac6ef0bc7d752a67ec6e5d6b835e9b40c/psycopg_binary-3.3.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f0535693ce476a722b718b002d5d2c27d47e71ca945276ac194409c98e74c492", size = 4775403, upload-time = "2026-09-18T13:16:58.939Z" },
{ url = "https://files.pythonhosted.org/packages/84/02/2ffcbc43f8e4bbc38e5286a22013bcac01898d13cd38325f60dd5428a8af/psycopg_binary-3.3.6-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3c9e663b2e800e3218994cf948c11bcc2844e6491b34aa80d089baf6531827bf", size = 5594145, upload-time = "2026-09-18T13:17:08.515Z" },
{ url = "https://files.pythonhosted.org/packages/e1/25/031dae2c7d2e7e77dcf5b1962c1e0684fa548d7af0ff6707b6b5e6054ca7/psycopg_binary-3.3.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a2e44a342d2aee40508e28a563d8961c39d9bbd8cae36d8578f0a3c6658aab0f", size = 5267985, upload-time = "2026-09-18T13:17:16.24Z" },
{ url = "https://files.pythonhosted.org/packages/8c/e5/94c89ada3c003a4d858178f3bba49a35e0297ef2aad659b80eb5e380e690/psycopg_binary-3.3.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f598f19fa9a91540b5cee17932ffd227b7b53a481605bcc4573c0eafa647300", size = 6860986, upload-time = "2026-09-18T13:17:23.348Z" },
{ url = "https://files.pythonhosted.org/packages/9d/a0/81bf499d095adee8413bd19822a6872fbfa21663ec78014a68d83a8db83c/psycopg_binary-3.3.6-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6ff05561e4a067d35507dc5c90f1deb2ec1c9703ac5cccc1bc26e08a197f9c5a", size = 5106702, upload-time = "2026-09-18T13:17:28.847Z" },
{ url = "https://files.pythonhosted.org/packages/00/75/99d56da64c27bd985fd82c6ecbf7976b724ac638fdd1654ef995323a1a26/psycopg_binary-3.3.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:566dd827f17728efdf7d88a5b066f815170f6fdad13967ae952842d90e6aaa9f", size = 4627090, upload-time = "2026-09-18T13:17:36.668Z" },
{ url = "https://files.pythonhosted.org/packages/3e/0c/0222171d11233332c6a24b1cef1578215f0ffddf3642eb8dd8c4448ad69f/psycopg_binary-3.3.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:9b2f11794e017ce340934e35de46181c46ef71ec75ea3d85dd75cd836761c01e", size = 4320353, upload-time = "2026-09-18T13:17:42.526Z" },
{ url = "https://files.pythonhosted.org/packages/62/6f/e1cc2a28dd1228c67c969ba6fd37cd8726b312e2ff51380f847ddb38ccde/psycopg_binary-3.3.6-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:910ace140e3e7b7596898d083f37a8fe90c5c40684252ad4e682364b2cd3deba", size = 4047253, upload-time = "2026-09-18T13:17:47.068Z" },
{ url = "https://files.pythonhosted.org/packages/d8/fd/38b64790ce7a515b1dbd2bab3d119637a858aeb22c380cf4859bc4ce0e42/psycopg_binary-3.3.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37e517c146b185f9c0c6e8d0a0ebbdeeeb67896af28466e032bc810d0c7dc7a7", size = 4353208, upload-time = "2026-09-18T13:17:52.41Z" },
{ url = "https://files.pythonhosted.org/packages/f7/dc/45386530ceb2a8c789a226de9b9b34eca8fccf1feba2e4ef68a6aca50c56/psycopg_binary-3.3.6-cp311-cp311-win_amd64.whl", hash = "sha256:c7f92daa0d2a1c76f07264abddf8cbabd30152a2f09c3270e50f0c7efdf5dcac", size = 3675638, upload-time = "2026-09-18T13:17:58.112Z" },
{ url = "https://files.pythonhosted.org/packages/e6/01/2cdd1824e58b4467ee0b9498664cd28c42d8794db6b1e35b6bcb834f0044/psycopg_binary-3.3.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3f84dab25e0385692ee13274c68678377e0b1a70ab9d14e56264cbf61f60c62d", size = 4707086, upload-time = "2026-09-18T13:18:05.138Z" },
{ url = "https://files.pythonhosted.org/packages/f6/76/de9948ac06895261c84d5b9fbe283d8f3c5bc9f070691b8d9eaa1b51e322/psycopg_binary-3.3.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:612382ac3ed13651c7fa44b5fee9fbf7baaa2ddbc6f500391672682c5f1df9e0", size = 4769607, upload-time = "2026-09-18T13:18:12.83Z" },
{ url = "https://files.pythonhosted.org/packages/76/a9/72436c9915ee4905964689e7f0e182ce7767cc0a0390b3ce703be8177625/psycopg_binary-3.3.6-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:366db6e97e66b37211475f20c4c1324a2dc0dd825e46d4e87f9d599304d276f9", size = 5554134, upload-time = "2026-09-18T13:18:21.175Z" },
{ url = "https://files.pythonhosted.org/packages/0a/42/948bb3d2617795093512613fd96ba380e922992c7908fbc073858147d196/psycopg_binary-3.3.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1679a1cb93fbe5a6d1fd58d82cbddcc6fcb8c61446ba7cae6eb2a7b19bc585de", size = 5235723, upload-time = "2026-09-18T13:18:27.071Z" },
{ url = "https://files.pythonhosted.org/packages/99/47/93e823ff1b0088400703410939c9bda3e63ed9c850b3ee088e8769f4c10b/psycopg_binary-3.3.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:37d40450659401600e6d043ff586c89a71a69f33cbb8bcdba6cdb2569beecdbe", size = 6833587, upload-time = "2026-09-18T13:18:33.794Z" },
{ url = "https://files.pythonhosted.org/packages/5e/2d/ecc69c847795aa704041a9f5667a6b0938a088cf1853636d762a6938e493/psycopg_binary-3.3.6-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a5165300324efd5a772c48a88ab3a928513ab3979fca76553e62ee815f7b2b9c", size = 5070013, upload-time = "2026-09-18T13:18:39.628Z" },
{ url = "https://files.pythonhosted.org/packages/92/36/6126f0dac21713dcae91404f2a76da18598a6252339a8c669c46370d43b2/psycopg_binary-3.3.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d636338c8f21b0df2f84657b00bc34f9313f826ef93f1155bc743607e4a0c5eb", size = 4597367, upload-time = "2026-09-18T13:18:45.023Z" },
{ url = "https://files.pythonhosted.org/packages/4d/29/7ecfc04243b46c89ffd49924e9c5634ea904ef96c7d0f37e4073623584c1/psycopg_binary-3.3.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a4ee3bdd5468a725f2a4d9aab8a74b6d0279f768c8b5d3aeb102c5307ff3d59c", size = 4275419, upload-time = "2026-09-18T13:18:49.299Z" },
{ url = "https://files.pythonhosted.org/packages/6e/90/2f46d2e0de79706ac170df0a3637fe63c4498fc04f131f6049520b78b806/psycopg_binary-3.3.6-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:289aadd6a00e151203c081f708348ec89f1e483c9b510ef4ac3981f847f01f79", size = 4007358, upload-time = "2026-09-18T13:18:53.944Z" },
{ url = "https://files.pythonhosted.org/packages/03/48/6744e91291b751a8cf12d63d719977974bb94c84ceba913e7ddb2e478e51/psycopg_binary-3.3.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f21d057f3e5f5491067e5b292498073b73847d48799b099803fef100775fcc52", size = 4320156, upload-time = "2026-09-18T13:18:59.258Z" },
{ url = "https://files.pythonhosted.org/packages/1a/9b/94ff7fce53a64d5b286e2ec454e0a025cf3d6e6b4a9189bef16aa5de98b2/psycopg_binary-3.3.6-cp312-cp312-win_amd64.whl", hash = "sha256:e23a66a763fbe83fcc210bc77c27e5a5ea380ebf091c06f34d8561b695e5a40f", size = 3658864, upload-time = "2026-09-18T13:19:06.503Z" },
{ url = "https://files.pythonhosted.org/packages/b4/c3/c072584b69ad44a747b448cfc9766fecb8aae56e372a017e2ef668790057/psycopg_binary-3.3.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ad8f35e67cc16d1fad1fa8c88972dc9b3a3141ea67897399904edab96a301b6", size = 4712284, upload-time = "2026-09-18T13:19:13.451Z" },
{ url = "https://files.pythonhosted.org/packages/0a/b9/4283b785339e8e2318d03048994b093d650ea6289fabaa806b765dc0d449/psycopg_binary-3.3.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:373704aea331d3f3e3402c125a1543f5875e2986ebb54f97d1647942161f803f", size = 4772031, upload-time = "2026-09-18T13:19:18.524Z" },
{ url = "https://files.pythonhosted.org/packages/6f/72/7a1321d359246769fff1affffbd0132785a28f7f63c18524c15a502398f4/psycopg_binary-3.3.6-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:b82491019b884d62318b5f30706c3d7e6d4e5a6cb7eabcb3edc0c1b0fdaceae9", size = 5556392, upload-time = "2026-09-18T13:19:24.418Z" },
{ url = "https://files.pythonhosted.org/packages/de/b0/c6f8a0585a5dacbea74e130bcfc66629390e8f5bbc79d2a8e806e8952150/psycopg_binary-3.3.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cec5ea900390897d0b46130f60bc2883bf19c314f9044235217c8be88b0ef269", size = 5237855, upload-time = "2026-09-18T13:19:31.257Z" },
{ url = "https://files.pythonhosted.org/packages/e2/fc/c3a7a8bbef7e945ec584ac61d460a612363ea398511cd0e220242b1d69f1/psycopg_binary-3.3.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98c02090d88f2ebc0ec1e8da538f77d225ce0fffecf372aa39262e62a1b054ef", size = 6833856, upload-time = "2026-09-18T13:19:43.622Z" },
{ url = "https://files.pythonhosted.org/packages/a9/f2/8e80b921db728ebb68fc105bd7c4277f908210ad755bd6481d5ea7add740/psycopg_binary-3.3.6-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ee2c4728c691245e24501fcd7a97b5b381236b9985bc445bba88cdce7d1b5784", size = 5070730, upload-time = "2026-09-18T13:19:49.968Z" },
{ url = "https://files.pythonhosted.org/packages/54/6a/5b313e0c5348244f0e973aff3258bf86766656256d5ece8d541a53e35b4a/psycopg_binary-3.3.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f19cc87343eaa55255e76b31259a570072ac95d6ae82c92dd34b97691f5e49dc", size = 4598089, upload-time = "2026-09-18T13:19:56.426Z" },
{ url = "https://files.pythonhosted.org/packages/32/e9/db7f76ec24bf6699e92bf604e5c4bae10664a681a8999ef42aa0faf0f2c6/psycopg_binary-3.3.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdccb3a0e184b03e9baa673b15a809cf36c339c85dbda0ebc25a698846dfbee8", size = 4278481, upload-time = "2026-09-18T13:20:04.681Z" },
{ url = "https://files.pythonhosted.org/packages/61/83/72c67013656f4d6b547caabffb193e91d57e63f90eefdcc6d045c400e97d/psycopg_binary-3.3.6-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:9892188bb15e5803beb51afe8a25add6b56be391a53058e8bca03b74e1e6bf22", size = 4009229, upload-time = "2026-09-18T13:20:11.905Z" },
{ url = "https://files.pythonhosted.org/packages/82/35/5e4500df2c999eb0faed8b184e6958b834172128274f06167a5deef4c19c/psycopg_binary-3.3.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3af90f92769d8cc10f94515ee7a0aef36ea85ca733a0ce22858f6e0953f41138", size = 4321467, upload-time = "2026-09-18T13:20:17.949Z" },
{ url = "https://files.pythonhosted.org/packages/55/7f/e350e1cf498ba2565c3f87b12f429d2012eb86b76c2b3845a19ee5fbb4d6/psycopg_binary-3.3.6-cp313-cp313-win_amd64.whl", hash = "sha256:0ebfad5d131de9f892ae9e70cc7616207768b6714b66a52d4612b8ceaf78b372", size = 3658179, upload-time = "2026-09-18T13:20:22.691Z" },
{ url = "https://files.pythonhosted.org/packages/6d/b9/60711317c284a442511644ea7185b56ebe627606d6741e732cd16108c47b/psycopg_binary-3.3.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:b3f75dee0f9afafabe4edc52c4842f1e1878ed2069bd05b22d6fe961e97e4dba", size = 4720512, upload-time = "2026-09-18T13:20:29.278Z" },
{ url = "https://files.pythonhosted.org/packages/63/da/28befc84454cbc6374550de7746f591f8fe1b6165c1fce249652cc8291c4/psycopg_binary-3.3.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5927b7ba63153cd8e9862987290a2b783a5c590daf2a4ef981700cc3569166d4", size = 4782318, upload-time = "2026-09-18T13:20:35.401Z" },
{ url = "https://files.pythonhosted.org/packages/a4/8a/0d21c2c833cdc0d4244c77e858e0ed37fa2abec2623be4fd686f617109ce/psycopg_binary-3.3.6-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:0bf08b749cc144f33b44a91b78e3f71c60eb07963746a0df5a100b36ce3d7475", size = 5567460, upload-time = "2026-09-18T13:20:41.902Z" },
{ url = "https://files.pythonhosted.org/packages/49/6d/7692d0d4e656b6cc9868d8acc2e3b42f17a0db4a625400a6d093cb0533a1/psycopg_binary-3.3.6-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:31cd942c23f613276b81a6e6598cefa12960058b0f46e1e874b540c793f6aca5", size = 5246902, upload-time = "2026-09-18T13:20:47.661Z" },
{ url = "https://files.pythonhosted.org/packages/d4/c1/b8a1f18fb1b7558a17f57f7cb3fc8bc93189feea2958925950b3acb15743/psycopg_binary-3.3.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4690cf67738f0e0e49a32aeec99bf0e4595cc2b4f1af984a4345394b1dcff91a", size = 6847192, upload-time = "2026-09-18T13:20:56.874Z" },
{ url = "https://files.pythonhosted.org/packages/a5/76/404f33519167c65cca88ec4998776f1dbebccc301ee977f0e62c47fb0826/psycopg_binary-3.3.6-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ad1c785e784cfd87e8436c6b7702f2d321fc39601bbaf29bc63a41a867091638", size = 5079573, upload-time = "2026-09-18T13:21:04.155Z" },
{ url = "https://files.pythonhosted.org/packages/f0/d9/79e8fbc8f37262a415f3550f0bcc5f98037442bf3d12ef6cbae2056655ae/psycopg_binary-3.3.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:79a2a1c3449f6c3409427078ed1cec10de79f3023cb5f2504f0597d350ad46c7", size = 4613633, upload-time = "2026-09-18T13:21:10.664Z" },
{ url = "https://files.pythonhosted.org/packages/d4/47/96225db74be7d2ce04b3a58678b53cda610225055edf5faa775c9f501d8b/psycopg_binary-3.3.6-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:86147cb5d140341c3363fb5bacce31f8d5543902a46699d3c536b101bbceaf9e", size = 4293375, upload-time = "2026-09-18T13:21:16.027Z" },
{ url = "https://files.pythonhosted.org/packages/2a/d2/18e9c779a5efd565250329adaf529ecc2b8b2ed5be5cb0f6ccee208cbfd9/psycopg_binary-3.3.6-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:7308c93cf0b19bbaf8e6ff0a6ad50d3c442385739245fe15a8d593bf841734a6", size = 4019883, upload-time = "2026-09-18T13:21:21.587Z" },
{ url = "https://files.pythonhosted.org/packages/ef/28/0cc654afc6c2cda982767f5679d3646b30b1ec86545bdaa9402202d6776c/psycopg_binary-3.3.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:05a83ac9fd52b9bca7cb5ab04b3691163170bd16f53defa27216ea3aa07ee781", size = 4332607, upload-time = "2026-09-18T13:21:27.63Z" },
{ url = "https://files.pythonhosted.org/packages/f1/3e/0a753a74fbd7aef120f286c016e09d3cc3f1daf7688f4a145d27281260b2/psycopg_binary-3.3.6-cp314-cp314-win_amd64.whl", hash = "sha256:1fbd30e537dab22cafdf080608f10148fe2a5f3a61294ddb5113caac8a623840", size = 3755671, upload-time = "2026-09-18T13:21:33.855Z" },
{ url = "https://files.pythonhosted.org/packages/0e/b1/a372b9c02aea50148e71c9853e19efca8fa5ae2010a8e27243b9b8f790c0/psycopg_binary-3.3.6-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:bf8c8481d026b85dd70c5fa7dde85b2333aed0b32a2602bcd38a900cbd78a49c", size = 4719571, upload-time = "2026-09-18T13:21:41.437Z" },
{ url = "https://files.pythonhosted.org/packages/65/7c/811e3828c6b82e2f10c6c9cdd963cfc66f3e024026e5a69ac18530bad984/psycopg_binary-3.3.6-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:b599defe9190b17e9907c8b4d114c181e702c87efcd1b8a0ad40971cdcc4634a", size = 4781230, upload-time = "2026-09-18T13:21:49.516Z" },
{ url = "https://files.pythonhosted.org/packages/3e/15/9a784eed813ea9e97c294af3ead63d02b7b203502c66380336c50065e441/psycopg_binary-3.3.6-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:b8ece331509f7a975b90501f41e83ad905e4141753fedf3f2711b2bc70a8efbc", size = 5566111, upload-time = "2026-09-18T13:21:58.089Z" },
{ url = "https://files.pythonhosted.org/packages/68/16/47194e002007c27337b11e49bf459c4b19727463f9aff2e1a90917bcc806/psycopg_binary-3.3.6-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c61617eaae0112ca154da87ffb99b73af2c74067acac28dfb9a4455b019dff2e", size = 5249963, upload-time = "2026-09-18T13:22:06.695Z" },
{ url = "https://files.pythonhosted.org/packages/53/84/5dcf9f310b11f0675cd860c6b2c70f58ce61798a3ee3f6f962b53fa358ca/psycopg_binary-3.3.6-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6d19cb4999d03231e8730a5f66c8f5068bc3b532677eb39dab0f600bff3e312", size = 6847925, upload-time = "2026-09-18T13:22:13.088Z" },
{ url = "https://files.pythonhosted.org/packages/f3/06/1957a06dc22963c418c27b284929579de84f29c37ad1abe6dc6ee9e8cf25/psycopg_binary-3.3.6-cp315-cp315-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8cbb54454dbf1bbf2ff08dd7693e8d94ac94b1a20f70f4b3b813d52ecb5cbc1", size = 5087720, upload-time = "2026-09-18T13:22:17.959Z" },
{ url = "https://files.pythonhosted.org/packages/21/43/ac07d042bae99b57bf123bb473632f29af544008094da0ffd285ab8011e2/psycopg_binary-3.3.6-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:dc75da5a20951049f7b773145f998f69d181adad9c58a0ff36e0cf1d73c10e10", size = 4613412, upload-time = "2026-09-18T13:22:26.719Z" },
{ url = "https://files.pythonhosted.org/packages/aa/b1/019156fbeafcefb4cccc9d109de4699493bceb8313c7545c8349e089dfbc/psycopg_binary-3.3.6-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:955e3dd94da361e052d2e49acf591017158dc8f8ed2c8a42c2e3943403c39dc2", size = 4292618, upload-time = "2026-09-18T13:22:33.042Z" },
{ url = "https://files.pythonhosted.org/packages/5d/0f/62113dc6b1df65983a1f2fc816c04b1edfa22f2ae9d4abee74ed267f4a96/psycopg_binary-3.3.6-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:c7753871eb57e6a5f4646f6168590c6653073dea5e9e720b201c8875332df4c8", size = 4027121, upload-time = "2026-09-18T13:22:38.334Z" },
{ url = "https://files.pythonhosted.org/packages/5d/d5/cf0cbd1ea5a7d8167fe2c6953efde19101f7b193bd61a23e6d622ad6854c/psycopg_binary-3.3.6-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:303732e798fe6729f8e12021b9c96107df8e95ecec4dd487c67b98ec2a59435e", size = 4336388, upload-time = "2026-09-18T13:22:45.576Z" },
{ url = "https://files.pythonhosted.org/packages/98/33/e2a5b36edf8aa422f6fa4b894756eb33dc93b36df5f65121280bb8b929c4/psycopg_binary-3.3.6-cp315-cp315-win_amd64.whl", hash = "sha256:2f122603f36050937982abf9668d8bc4769a79f7c93a65013b1c49f1cab7b56b", size = 3756154, upload-time = "2026-09-18T13:22:51.283Z" },
]
[[package]]
name = "psycopg-pool"
version = "3.3.1"
version = "3.3.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
{ name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.15'" },
{ name = "typing-extensions", version = "4.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.15'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/90/82/7a23d26039827ecd4ebe93905651029ddd307c5182ad59296dfb6f67b528/psycopg_pool-3.3.1.tar.gz", hash = "sha256:b10b10b7a175d5cc1592147dc5b7eec8a9e0834eb3ed2c4a92c858e2f51eb63c", size = 31661, upload-time = "2026-05-01T23:31:59.809Z" }
sdist = { url = "https://files.pythonhosted.org/packages/74/5e/c0664b968b102ff68b811d999c728546c48d5c1eec03e3bbaf88c0cb4472/psycopg_pool-3.3.3.tar.gz", hash = "sha256:df87b5d9d0ad7db37f6cdad4fa8ce113d250f5997f6db38e9a99192fb67f9e1d", size = 32006, upload-time = "2026-09-22T15:53:24.947Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/37/ed/89c2c620af0e1660354cd8aabf9f5b21f911597ce22acb37c805d6c86bc8/psycopg_pool-3.3.1-py3-none-any.whl", hash = "sha256:2af5b432941c4c9ad5c87b3fa410aec910ec8f7c122855897983a06c45f2e4b5", size = 40023, upload-time = "2026-05-01T23:31:53.136Z" },
{ url = "https://files.pythonhosted.org/packages/5d/b4/452c6607a0f479465cd8a9b0d9956919fcb150050c1f83f9f11e6b8ee8dc/psycopg_pool-3.3.3-py3-none-any.whl", hash = "sha256:9b9cd6a4fcec47a410f7e82d408540e7f77b478509e91b44c1a5457a13e5ff37", size = 40304, upload-time = "2026-09-22T15:53:23.712Z" },
]
[[package]]
@@ -694,7 +708,8 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "annotated-types" },
{ name = "pydantic-core" },
{ name = "typing-extensions" },
{ name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.15'" },
{ name = "typing-extensions", version = "4.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.15'" },
{ name = "typing-inspection" },
]
sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" }
@@ -707,7 +722,8 @@ name = "pydantic-core"
version = "2.41.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
{ name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.15'" },
{ name = "typing-extensions", version = "4.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.15'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" }
wheels = [
@@ -854,7 +870,7 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "backports-asyncio-runner", marker = "python_full_version < '3.11'" },
{ name = "pytest" },
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
{ name = "typing-extensions", version = "4.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/43/7c/d36d04db312ecf4298932ef77e6e4a9e8ad017906e24e34f0b0c361a2473/pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42", size = 58514, upload-time = "2026-05-26T09:56:04.083Z" }
wheels = [
@@ -863,14 +879,14 @@ wheels = [
[[package]]
name = "pytest-mock"
version = "3.15.1"
version = "3.16.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/68/14/eb014d26be205d38ad5ad20d9a80f7d201472e08167f0bb4361e251084a9/pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f", size = 34036, upload-time = "2025-09-16T16:37:27.081Z" }
sdist = { url = "https://files.pythonhosted.org/packages/7a/7f/6ed29931d5c8cd396e7c0a55412e6cc88020373365c8685985dea53d26d7/pytest_mock-3.16.0.tar.gz", hash = "sha256:5a8395528b8f498205f3718f575228d0edaed7425fff638f87d1a6c3e0383636", size = 35362, upload-time = "2026-09-27T14:57:55.46Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095, upload-time = "2025-09-16T16:37:25.734Z" },
{ url = "https://files.pythonhosted.org/packages/db/5b/b83a9bf1a3b4ec222f9fa083147ff6816245223da0ab92370e7e056f113f/pytest_mock-3.16.0-py3-none-any.whl", hash = "sha256:007cfeb257801d88d9c0b2a7b5a15a15e73b71968dfd72e7bf8c4a2f8393aec8", size = 10016, upload-time = "2026-09-27T14:57:54.283Z" },
]
[[package]]
@@ -979,27 +995,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.16.5"
version = "0.16.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f3/85/c8e12473c93018f92d19dd988a294202e1c27426c47ec4de53ffb847b8d8/ruff-0.16.5.tar.gz", hash = "sha256:1b88500f9ffbcab3dedb0082c9f9492e91ec3d618aac1236a3e0189938f7040b", size = 4912003, upload-time = "2026-08-27T16:34:18.258Z" }
sdist = { url = "https://files.pythonhosted.org/packages/96/bf/c935ca98e73fe8ce65b87ef08a280c0c1e85295d569228c15e87d8fdfaf1/ruff-0.16.9.tar.gz", hash = "sha256:12b625c6cfba78d285d9f48eda5f053374f1e53cb10ef17342a383750db99161", size = 4948764, upload-time = "2026-09-24T20:37:49.416Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c6/b6/77c90a970fe2dae17a723acbd011043ea97c98d7deacccefdc4ba74ec512/ruff-0.16.5-py3-none-linux_armv6l.whl", hash = "sha256:12e5f673e774c35fbb62f288809c7653b73445f8ecec6b6063fd6ea3521aa14b", size = 10011941, upload-time = "2026-08-27T16:33:41.287Z" },
{ url = "https://files.pythonhosted.org/packages/4b/46/6cf67cf6411885a1d6f7f6d801682f155536a85176d10b605e2ceffed8bd/ruff-0.16.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:eda58a5802de40e7ed5b32b64e0b32539338cc6fcd2c78f61e3ad6a0d79f51c3", size = 10204049, upload-time = "2026-08-27T16:33:44.056Z" },
{ url = "https://files.pythonhosted.org/packages/46/fd/c8720ca7a090abf0c2fef4abe8a5ef6e5127ed15196d8886ff75a2b370e2/ruff-0.16.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5ae9a7b9a8875131f40f8fe967cc86abf899779efd663cb7ce3d572d01da7eb", size = 9809037, upload-time = "2026-08-27T16:33:46.257Z" },
{ url = "https://files.pythonhosted.org/packages/43/45/a684caacdedaca180f52bacccc40bf0789d2c5a7c75f25324853e9eaedb5/ruff-0.16.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b719b0a1f4d59710d283ab2965f621684a108a9e41da622e3b23f0326cd0025", size = 9964129, upload-time = "2026-08-27T16:33:48.352Z" },
{ url = "https://files.pythonhosted.org/packages/9e/f2/5d2bcdaca6b5b93d1b4dfc166cd2aebf7680143a1b38a28759df13a94d31/ruff-0.16.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2298f2780ed1be0c5cb1361e32ab7b1467f3cce7dabe101d2210a314f2fe42e9", size = 9821518, upload-time = "2026-08-27T16:33:50.57Z" },
{ url = "https://files.pythonhosted.org/packages/aa/ff/011cce29accf9257d5974145b733fc653a37985ed6825413a3987cefbfe0/ruff-0.16.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:258f29035a2dd021e7861e631b227a5b3f14e50c1184c9a6a122c5f4576154d7", size = 10534835, upload-time = "2026-08-27T16:33:52.522Z" },
{ url = "https://files.pythonhosted.org/packages/d7/5a/f0cf109bada9bba0e96c90c21c9f9251803f57225c32d293327a03c710d6/ruff-0.16.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9a4f0432966834019c74d1b7e5c51224305d7713f3d7faf3e7451f1a3be3cde", size = 11252550, upload-time = "2026-08-27T16:33:54.521Z" },
{ url = "https://files.pythonhosted.org/packages/63/4d/1d481aaea2046c6a7ed7c291f9004c669cce3c087b6b376ed5b08271e3fe/ruff-0.16.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5eb3a8c3d0ade9cea42b591fd530368e8798380e30e0a308b85a5cf718f09ea", size = 10777949, upload-time = "2026-08-27T16:33:56.88Z" },
{ url = "https://files.pythonhosted.org/packages/ee/34/ee245ca55f64443233034b3d02b03236b19242004281247c079390b7facd/ruff-0.16.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef0f69e191a13a3c9816f63163c88790cb12cd157bbbb384e9c44745702ab105", size = 10311656, upload-time = "2026-08-27T16:33:59.12Z" },
{ url = "https://files.pythonhosted.org/packages/a7/4d/c33a333e341c0a2b96c715b52d89a606f5a34cd4ac493cd9b8d0187186b8/ruff-0.16.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0eeab41fbea2c42f98dfb9822cdccda9d24ba38d49f6dc945b5c236d48f0ef29", size = 10532125, upload-time = "2026-08-27T16:34:01.166Z" },
{ url = "https://files.pythonhosted.org/packages/30/e1/a64cef78b40192497bb98a27a8aa8f2c98ee9ee15bc97f7712d94ef32937/ruff-0.16.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f0768e9df4300713fff30733c87575f68b6f1d8de41184e505b7fdd9c0c95eaf", size = 10097648, upload-time = "2026-08-27T16:34:03.16Z" },
{ url = "https://files.pythonhosted.org/packages/cc/4e/4cdc9ed3c3e109d2f71e62572a37457298d7bc7501ec3138babb7ed32bbd/ruff-0.16.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:95cc70cdc7aa80c338de356279d2adbeb2de0f520b9ecd8aba75b94e95e02f91", size = 9829344, upload-time = "2026-08-27T16:34:05.134Z" },
{ url = "https://files.pythonhosted.org/packages/39/4a/31ed35ce31729955fc583ee0d176d6e784c1290cb0b0a75cb2134c1ab72a/ruff-0.16.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d185c8398ded1bfd91c0c2cb258346307571eccc473a8490af8c3977399c384a", size = 10277117, upload-time = "2026-08-27T16:34:07.425Z" },
{ url = "https://files.pythonhosted.org/packages/a8/a0/60356d86687b4b666d593df213f4dc3041750d024cb7bf2cfa81cfd65c2e/ruff-0.16.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:fb8e3a3c4c6a784150a7ced53b015f4b253fc2bf97a610886419ead64b4756ef", size = 10711653, upload-time = "2026-08-27T16:34:09.712Z" },
{ url = "https://files.pythonhosted.org/packages/ed/20/656d67f5b25ca9bda4e02b1de25867b2954e1d19e03648060f167ad0f4cc/ruff-0.16.5-py3-none-win32.whl", hash = "sha256:288b0a5f080492fe5635db849f9e2e84aa3cce7b7f0e955997d416c507c76a26", size = 10034250, upload-time = "2026-08-27T16:34:11.8Z" },
{ url = "https://files.pythonhosted.org/packages/5b/42/ee8e68a207b9127fcde6c3d7e197def432f346cb1af159e1fa14ca0d1cdc/ruff-0.16.5-py3-none-win_amd64.whl", hash = "sha256:ddc6385fb2137f616357ca03d6c74f4be987f80fed4008566b754f6032b8546f", size = 10516714, upload-time = "2026-08-27T16:34:13.963Z" },
{ url = "https://files.pythonhosted.org/packages/73/e3/7df5a396e445b9ba49ce9a9437439a4d80042c61c0ade199abf8d16de1ac/ruff-0.16.5-py3-none-win_arm64.whl", hash = "sha256:a64abe90968719b851bb7cedffaa8753fbdbdadab483089682db623f3edc587e", size = 10391564, upload-time = "2026-08-27T16:34:16.064Z" },
{ url = "https://files.pythonhosted.org/packages/0d/26/df51322b52ee1ada7eff2d071ea09d11d5c2d1dcc9f02594f5785c4d1635/ruff-0.16.9-py3-none-linux_armv6l.whl", hash = "sha256:95e6f022090368ab3b824c36276839c53b2adf1a3f4c09fefc33dfc400f6da96", size = 10082922, upload-time = "2026-09-24T20:37:13.045Z" },
{ url = "https://files.pythonhosted.org/packages/a5/27/7bf51f5a7aa375e9f339280a303aab44ca75dc1525f1cdc5991761685b0f/ruff-0.16.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a5f27be168556594a86d2f415db0cf43f5291917849318f873c7e2791f7a8c67", size = 10236360, upload-time = "2026-09-24T20:37:16.049Z" },
{ url = "https://files.pythonhosted.org/packages/b6/63/09659283f92f02dff45809da194a70da2f688d87c55d8875c4fae3536072/ruff-0.16.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1632eb1d6197f33bd00b1acbc5b71009e89a8895c158e2d2b03a834fac964ab6", size = 9892940, upload-time = "2026-09-24T20:37:17.957Z" },
{ url = "https://files.pythonhosted.org/packages/24/58/98de1b72ec172f5f8f1731236fe21585b3998bf7dfe9fcc44ae9ba626012/ruff-0.16.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3f951b14d865d5952c89d40a5ca07e87abe24fa5453299878411e127748fb1c", size = 10032114, upload-time = "2026-09-24T20:37:19.942Z" },
{ url = "https://files.pythonhosted.org/packages/c8/7d/f1e17c54ab59d4bad1dce8ee3e22a7a1d0ef4745240decacdcf3832b5bb2/ruff-0.16.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:447fc07e1573afff7cb02803462b12b6c8ece7cf10e2cd78565fa6d7a1c0bf8d", size = 9910227, upload-time = "2026-09-24T20:37:21.872Z" },
{ url = "https://files.pythonhosted.org/packages/34/19/436f647a65075bbd3bab2668b3bdaa5120559b294694018cdcefabbbf30b/ruff-0.16.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a3e039a6a40ed976c491722b60e0ae4a4aa1a86057f540ee7a37a5d19ae9120", size = 10547484, upload-time = "2026-09-24T20:37:24.229Z" },
{ url = "https://files.pythonhosted.org/packages/03/59/38430a6bc2f6d8095447ac39625cf8b6e9344a47e6c26225c8ba1bff3ffb/ruff-0.16.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4684dded7db60aa57cb118fa158630f5feade4af5782903b6053484bdf9bd129", size = 11412367, upload-time = "2026-09-24T20:37:26.307Z" },
{ url = "https://files.pythonhosted.org/packages/c8/bd/bbb6d7fc7f208c8b8c50dd5dc8206e4cfdb1e7a8fb852606a3adf370c880/ruff-0.16.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d29c934357e45642fda2f34c0b1f4025b4a6c01e15e4bf0016879d60078a142c", size = 10869787, upload-time = "2026-09-24T20:37:28.35Z" },
{ url = "https://files.pythonhosted.org/packages/bc/b8/9c543074918061abbefc3bd139bee22de35abedb00dde0f2d27288838962/ruff-0.16.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a21713e629d3e5bdb2f5c2def1cc7f04f47fa8e1a7eb0571b4a28e1da64bc728", size = 10406494, upload-time = "2026-09-24T20:37:30.624Z" },
{ url = "https://files.pythonhosted.org/packages/35/7a/5a8851bd146e7ccf8fd4b003f6c75c11f8fbdb0e60673b45097986b6bf41/ruff-0.16.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7baa24ef5fc8e77aa93879e1d3f43754a01ae488e869f1ae30cf431afd4d2452", size = 10590083, upload-time = "2026-09-24T20:37:32.439Z" },
{ url = "https://files.pythonhosted.org/packages/87/f0/4c3467188f23f806960b46fa76575a7cd0514c9ba90562650b71efc96980/ruff-0.16.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a41aac6230aadfaa133bdfa1614488531ffa3e0837567ae04c0da2058a9c0f9e", size = 10119151, upload-time = "2026-09-24T20:37:34.581Z" },
{ url = "https://files.pythonhosted.org/packages/15/34/5a4def5adea572ce6aea0bb64f21f928ee317b80e0db747d7979b01d7261/ruff-0.16.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c2529fb5896d49115b0e9aa8f887490b34bbe76baf879ec2264ac59406869ce7", size = 9911544, upload-time = "2026-09-24T20:37:36.796Z" },
{ url = "https://files.pythonhosted.org/packages/62/5d/d15ebea7499eef9373318c0ee6ca127832927c6529731f6d48e18dce7ca9/ruff-0.16.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:41e3870277694177429b56406d65dfbdb2c2802c52b715edaf6a0b829c69d4ee", size = 10269884, upload-time = "2026-09-24T20:37:38.857Z" },
{ url = "https://files.pythonhosted.org/packages/d1/56/c5d3cd119ded7a3c7aba0e961b69cb3df701c91662c98ad694467d060ce1/ruff-0.16.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8adbe4e58af167f767d7b2ba5e83c42e878350796cf78c2f5e14ab9903a92588", size = 10749366, upload-time = "2026-09-24T20:37:41.042Z" },
{ url = "https://files.pythonhosted.org/packages/ac/fe/734ec7527029ac757ecf821f143c9f3fcf69149c21f53a044a899b430f5a/ruff-0.16.9-py3-none-win32.whl", hash = "sha256:0e1dbc2073624dee6618d41d0098690a7244654af746704b64759e12b6b6b385", size = 10152355, upload-time = "2026-09-24T20:37:43.025Z" },
{ url = "https://files.pythonhosted.org/packages/14/21/26e4643629b3ebb44f0a06f9c9a53058d63d989415f63a9a3c28e2ee7f22/ruff-0.16.9-py3-none-win_amd64.whl", hash = "sha256:6bd40fec8cd4c8a3d4dd589bd8ad4e6320c13c29234159bfd959a40d529d597b", size = 10592965, upload-time = "2026-09-24T20:37:44.944Z" },
{ url = "https://files.pythonhosted.org/packages/51/60/5fb1a39dbb5ae314d5f59bc7348a63c1d5c20f3cd83914c4b5cb0be31d2d/ruff-0.16.9-py3-none-win_arm64.whl", hash = "sha256:ed1a252039200f57a59eebc063b54beabea67bfbaaca0eeaa7f54b5fbcda2284", size = 10458649, upload-time = "2026-09-24T20:37:46.882Z" },
]
[[package]]
@@ -1067,44 +1083,60 @@ wheels = [
[[package]]
name = "ty"
version = "0.0.75"
version = "0.0.84"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/81/d0/d0c96f898d6974a4a3569ab3efdf9512c04ad99f9203effb55f72497fe97/ty-0.0.75.tar.gz", hash = "sha256:4c5eead33dfbf6e2ebb4f400f74b51ffc9bab702a6f23ddb648a1cbb740387e3", size = 6868326, upload-time = "2026-08-26T20:23:40.399Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e1/f6/34f8869c45ea87fe6a931ffa824b1fe4428167173543d92988d631add355/ty-0.0.84.tar.gz", hash = "sha256:0cefdb0cd5d399418dbe83c349ba605047b7dff815ae6f460c80e8522b40be67", size = 7409537, upload-time = "2026-09-24T13:16:24.367Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/6c/b12d03505f17581f0cfa3c12273fe34c1d67b36dfda1bc561a6bdc16512b/ty-0.0.75-py3-none-linux_armv6l.whl", hash = "sha256:e5409f50db2246fd4bd039d93d261e0cfa1daa554a4fb77256f91072c570349a", size = 12972606, upload-time = "2026-08-26T20:22:59.716Z" },
{ url = "https://files.pythonhosted.org/packages/d1/aa/30f11eecd9215a9f87e8fe8baaf48f3ce905f5d75b8e4aac70f0091f130c/ty-0.0.75-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5e7b8b3472fb9bb2eeab314984b265df08a7a9d518867a9e6020eebc06570be2", size = 12527158, upload-time = "2026-08-26T20:23:02.767Z" },
{ url = "https://files.pythonhosted.org/packages/f2/11/7fd7001b0b5c6610bfbad7357e47d5fe6f82d4e84e94c53776a478f5e9f8/ty-0.0.75-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c6ccf34169821fe0d23e3360deeef981d217963412f1d087b9bdd32ec57f7a57", size = 12400533, upload-time = "2026-08-26T20:23:04.965Z" },
{ url = "https://files.pythonhosted.org/packages/fd/7f/1e284ea3d348d7be02f12d83bc22ed9ef193033f863f05b64db99027f141/ty-0.0.75-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842ebb41e9c6c334b40768704e20b1a69d5c6b08805b289d5e0e2565f49f2de1", size = 12420592, upload-time = "2026-08-26T20:23:07.427Z" },
{ url = "https://files.pythonhosted.org/packages/2d/ab/d813271543370c47fd74b5118f2066ab32b0983e907b1821f3f9a6d0fa7f/ty-0.0.75-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf7a5a723c5f1e0fab4ffbfe9bd95123a526ed48f206e5f25cb2161ca294007a", size = 12739219, upload-time = "2026-08-26T20:23:09.809Z" },
{ url = "https://files.pythonhosted.org/packages/31/5b/95b49cc5570fd92a7bf63732f649b31906158721e03c7fcb1b5be74ee3bf/ty-0.0.75-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54382f98e5da292fcd7104391afef5105c35bb2f312e29bea6f5fa419935255c", size = 13494046, upload-time = "2026-08-26T20:23:12.191Z" },
{ url = "https://files.pythonhosted.org/packages/2c/0d/502d2dd68173cf020e1ad2bdbab9544c86776de0b0e2ed15f8c2fe006e3d/ty-0.0.75-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac13b180dc2aade2cd243f56b01650e78bf091a2e522ad3bc947245d7837c613", size = 13938899, upload-time = "2026-08-26T20:23:14.764Z" },
{ url = "https://files.pythonhosted.org/packages/20/5b/f3b12a25c07224456219fc2bd20db0ad7e40b304be0ff6aad728da0135f9/ty-0.0.75-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:752df7951a443219d7f1ff817e3723c85d428565ff449e08a7a93ba821661526", size = 13656711, upload-time = "2026-08-26T20:23:17.145Z" },
{ url = "https://files.pythonhosted.org/packages/51/7b/f090ad306e2b15a07b332d647138c5264b89d9758855ecce8b8a10bcb153/ty-0.0.75-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fd399feedf7cee816563c1baec45fc1c0b3c89f1ea42364920b688004b5b7da", size = 13093499, upload-time = "2026-08-26T20:23:19.489Z" },
{ url = "https://files.pythonhosted.org/packages/f1/4b/f69b99aaaca0c7c65d5f114b186b26b21666f767b0c69eec99a2bdccc061/ty-0.0.75-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:d7625f6f56c7dc1e873579fdc9e432a0e21e302afe847ab60704d2303442a92e", size = 13520580, upload-time = "2026-08-26T20:23:21.789Z" },
{ url = "https://files.pythonhosted.org/packages/b6/e7/692c5f905c0345a15d2255fc74066d660f030254ae8dcdaf33f5a5c2f279/ty-0.0.75-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:89e7d527e95a2534b70cae29e94c104b84082760ea05927d23bb87280969c104", size = 12524095, upload-time = "2026-08-26T20:23:24.026Z" },
{ url = "https://files.pythonhosted.org/packages/ba/9a/f42b12cf265ea95344bf554764c4791cfb273bdd628aadd7c209af7cadc3/ty-0.0.75-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0843f134440740706e01bee5f88f4cfc10e9b018bddb9e4ef4c12dc9fc0c9aef", size = 12756591, upload-time = "2026-08-26T20:23:26.126Z" },
{ url = "https://files.pythonhosted.org/packages/7c/5e/9b180c133cb9cce48179a7d2bf9e1802d992aa8176a918e0e05205760b42/ty-0.0.75-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1bd0ec0e50ee1376875c88891efe6f549c3560fa5b2ddad79a425cd5a6218b9c", size = 12998754, upload-time = "2026-08-26T20:23:28.353Z" },
{ url = "https://files.pythonhosted.org/packages/39/f6/3c6ef5dd550103e29905121c67fb96a374564f31a2f44c6faa1af98c2d61/ty-0.0.75-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1f9eafd561f90110d5e29f589ec3e956c4686e2f6631348d99276436f5cbe4d1", size = 13316474, upload-time = "2026-08-26T20:23:30.857Z" },
{ url = "https://files.pythonhosted.org/packages/bb/52/12776337874c821076bd5368e352ccd9e67174790abe3b856f749cb3524b/ty-0.0.75-py3-none-win32.whl", hash = "sha256:05063a6fafe2154b794a7f964515d148e51acd186d72d4a3acd347ee9fa19336", size = 12316315, upload-time = "2026-08-26T20:23:33.528Z" },
{ url = "https://files.pythonhosted.org/packages/53/e6/bb51e16af5c7138c9f52f8f3d0a401a371c6798d092e3b74926f186a9814/ty-0.0.75-py3-none-win_amd64.whl", hash = "sha256:81cf1ba5f6b7536ad56747865214255d9bc8e80533a689dbb9ddeaad464b09f1", size = 12917267, upload-time = "2026-08-26T20:23:35.978Z" },
{ url = "https://files.pythonhosted.org/packages/39/73/4542f829107468b5de4231af67f29927c093bfad11f3c1e5b2c08fb1206b/ty-0.0.75-py3-none-win_arm64.whl", hash = "sha256:541c9af5b7a0ad23d15ec315a7da81150833c359f48124ed3789ff25eacd6f42", size = 12711024, upload-time = "2026-08-26T20:23:38.159Z" },
{ url = "https://files.pythonhosted.org/packages/aa/0c/600648778e1c79133ce6b6a5c4c2531ae16b90c9b30f5041b38b574f61b8/ty-0.0.84-py3-none-linux_armv6l.whl", hash = "sha256:868438e2b9abfc835dd5b5b07ed693db95d8348ac40e3228252511d63ae87695", size = 13935333, upload-time = "2026-09-24T13:15:31.167Z" },
{ url = "https://files.pythonhosted.org/packages/c5/3b/27f06f49945c36170765fad82076898039ae3873338e9865f876dd62f12c/ty-0.0.84-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b00f39b521f0b559cde0f6abf8dd47213b513b04f33d58efeb9b98486a16bb17", size = 13511328, upload-time = "2026-09-24T13:15:34.446Z" },
{ url = "https://files.pythonhosted.org/packages/fc/b6/b12dd130e7f30141f0645614f454c925991cd389b1cc6c8284fd6bf32326/ty-0.0.84-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8f78c2915567f2ee62ce0c24d86091bc76f81577677755e242d09951db588b9a", size = 13445445, upload-time = "2026-09-24T13:15:37.476Z" },
{ url = "https://files.pythonhosted.org/packages/44/96/f012de4b3c1d9a4773326621380d768b4d48c47e620dc012775c5e01c7d7/ty-0.0.84-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61155cad0921e890d86d1d911a40b3a0e924ef4bdc3b4f3865a6c89c7e3012dc", size = 13471235, upload-time = "2026-09-24T13:15:40.64Z" },
{ url = "https://files.pythonhosted.org/packages/05/32/dca630f5f5353fa7bf67eebccf1549df99b16656d21071d0df6677c826a5/ty-0.0.84-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:417c3bf14947ed16b0b92976ab333c27915590354e96d4f581709068d3811355", size = 13680704, upload-time = "2026-09-24T13:15:43.817Z" },
{ url = "https://files.pythonhosted.org/packages/44/8d/33702c8f62f05ad45b33644fb914d483de6a0a7bc8e51884e9b8773e6d69/ty-0.0.84-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e06ef117759f654f5379efe9ae79bda8a186016c016f1023d05c34f8e15c1546", size = 14518923, upload-time = "2026-09-24T13:15:46.802Z" },
{ url = "https://files.pythonhosted.org/packages/c8/a1/da3246e6ef2ae0e842bca4058b25c54bee55ab058ffff4ee54e72517ec01/ty-0.0.84-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a05d1d53db8b64410ab38c6e32c5898510584869d1d5dd9c0605db81c9aef7df", size = 15027731, upload-time = "2026-09-24T13:15:49.755Z" },
{ url = "https://files.pythonhosted.org/packages/20/17/b0099098a560aeb4f9fde6c912f9a81622c3e44e6555e1fbe322b368ec31/ty-0.0.84-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b92400494ab855cfb1204ac1101e3f53b2d09a8e21d171758b2cf9acdab1809e", size = 14748260, upload-time = "2026-09-24T13:15:52.713Z" },
{ url = "https://files.pythonhosted.org/packages/60/d5/32cd67aedb271f006e716ad093806c96c5d7e2af86be8255469dbd3d76c8/ty-0.0.84-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af17eb391ae3027fed9be1780bea555c2b8a25ba68e184c627b4981b2c9eaab7", size = 14205858, upload-time = "2026-09-24T13:15:55.677Z" },
{ url = "https://files.pythonhosted.org/packages/43/c4/638ac62ca2e8eca1b92e3e16273085744fada728b993500819b5c258ca15/ty-0.0.84-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:44cf06af0e7ec78ea6d8ff33a3450fc19627756a4fba681f7410d4e3ef63047a", size = 14573196, upload-time = "2026-09-24T13:15:59.165Z" },
{ url = "https://files.pythonhosted.org/packages/a6/f6/9ee81c5d8921e5fd5f10889ae563c95cd3272b31df2ada528919ca1cef6b/ty-0.0.84-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c6e56b443ff9ba462e34bfbc1e582004c2719ed35f8f93a433744b0ba0afb2d9", size = 13480760, upload-time = "2026-09-24T13:16:02.313Z" },
{ url = "https://files.pythonhosted.org/packages/f6/83/fbe5d1177667ae16d84c3242846b143809c9cc09568b333e5a9b4d5908f6/ty-0.0.84-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b6562fcc48820c1030e2a4509ef2c14ef93043ca4860280074314ac3a825b95", size = 13696346, upload-time = "2026-09-24T13:16:05.391Z" },
{ url = "https://files.pythonhosted.org/packages/86/9a/1b4ac9ddc34cc0ab4624bc219825d66af52f1ad87f4778ad08ad03fa06d5/ty-0.0.84-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dee7421451efcbd70f03e95a8f2c8d9e5ec3d35edcd27b4095ee00ee062abfc4", size = 13959410, upload-time = "2026-09-24T13:16:08.661Z" },
{ url = "https://files.pythonhosted.org/packages/c9/04/70e289437a67dfd686056ab4fd91880261a8233033a6a95d29393741fb97/ty-0.0.84-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:31e96307cf621babe969307dd657783d672e2d8bdbd06493710da635bf63fa07", size = 14350294, upload-time = "2026-09-24T13:16:11.865Z" },
{ url = "https://files.pythonhosted.org/packages/9c/f4/ae7dbd118425c850981d23efb850f0d9d7f6b8d2b852bde2767434f668b4/ty-0.0.84-py3-none-win32.whl", hash = "sha256:4bdc85f91cbaae35825f2b17bb4ac5de0563367875cb0f42b2bf07a1bf7ff2ba", size = 13176439, upload-time = "2026-09-24T13:16:15.049Z" },
{ url = "https://files.pythonhosted.org/packages/29/ec/994d87252f065dda5a500bc8afc726d18f6582d81d6f4ff1feb8a267c800/ty-0.0.84-py3-none-win_amd64.whl", hash = "sha256:71cc9aa7a7c89d4e12c6a814e9c0c3310ad5bee44efedbd6f5a42d91e9ac0f0d", size = 13962879, upload-time = "2026-09-24T13:16:18.191Z" },
{ url = "https://files.pythonhosted.org/packages/6d/1c/e6e91852b72566b1ab9aca504712857dfb89324c12092a5bd61d42d34427/ty-0.0.84-py3-none-win_arm64.whl", hash = "sha256:6c9d3718c4a0d318bc9c92af9b2aa85c3294e7dff54cf1d69ad79568f56516da", size = 13656453, upload-time = "2026-09-24T13:16:21.51Z" },
]
[[package]]
name = "typing-extensions"
version = "4.15.0"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version >= '3.15'",
]
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
]
[[package]]
name = "typing-extensions"
version = "4.16.0"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
"python_full_version < '3.15'",
]
sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
]
[[package]]
name = "typing-inspection"
version = "0.4.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
{ name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.15'" },
{ name = "typing-extensions", version = "4.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.15'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
wheels = [
@@ -1122,11 +1154,11 @@ wheels = [
[[package]]
name = "urllib3"
version = "2.7.0"
version = "2.8.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
{ url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" },
]
[[package]]
+8 -32
View File
@@ -40,24 +40,12 @@ with SqliteSaver.from_conn_string(":memory:") as checkpointer:
"v": 4,
"ts": "2024-07-31T20:14:19.804150+00:00",
"id": "1ef4f797-8335-6428-8001-8a1503f9b875",
"channel_values": {
"my_key": "meow",
"node": "node"
},
"channel_versions": {
"__start__": 2,
"my_key": 3,
"start:node": 3,
"node": 3
},
"channel_values": {"my_key": "meow", "node": "node"},
"channel_versions": {"__start__": 2, "my_key": 3, "start:node": 3, "node": 3},
"versions_seen": {
"__input__": {},
"__start__": {
"__start__": 1
},
"node": {
"start:node": 2
}
"__start__": {"__start__": 1},
"node": {"start:node": 2},
},
}
@@ -81,24 +69,12 @@ async with AsyncSqliteSaver.from_conn_string(":memory:") as checkpointer:
"v": 4,
"ts": "2024-07-31T20:14:19.804150+00:00",
"id": "1ef4f797-8335-6428-8001-8a1503f9b875",
"channel_values": {
"my_key": "meow",
"node": "node"
},
"channel_versions": {
"__start__": 2,
"my_key": 3,
"start:node": 3,
"node": 3
},
"channel_values": {"my_key": "meow", "node": "node"},
"channel_versions": {"__start__": 2, "my_key": 3, "start:node": 3, "node": 3},
"versions_seen": {
"__input__": {},
"__start__": {
"__start__": 1
},
"node": {
"start:node": 2
}
"__start__": {"__start__": 1},
"node": {"start:node": 2},
},
}
@@ -507,13 +507,12 @@ class SqliteSaver(BaseCheckpointSaver[str]):
Two-stage query:
* Stage 1 (paged): newest-first slice of `checkpoints` returning
`(checkpoint_id, parent_checkpoint_id, type, checkpoint)` per
ancestor. Sqlite has no JSONB, so we ship the full serialized
checkpoint blob and inspect `channel_values` in Python. Pages
newest-first by `checkpoint_id` with a `< cursor` predicate;
page size is `DELTA_PAGE_SIZE`. Stops paging when every channel
has found its seed or the chain is exhausted.
* Stage 1 (streamed): recursive CTE over `checkpoints` following
`parent_checkpoint_id` from the target, returning
`(checkpoint_id, type, checkpoint)` per ancestor. Sqlite has no
JSONB, so we ship the full serialized checkpoint blob and inspect
`channel_values` in Python. Stops reading when every channel has
found its seed or the chain is exhausted.
* Stage 2 (per-channel UNION ALL): one branch per channel reading
`writes` filtered to that channel's specific `chain_cids`. No
@@ -538,12 +537,14 @@ class SqliteSaver(BaseCheckpointSaver[str]):
seeded: set[str] = set()
with self.cursor(transaction=False) as cur:
cur.execute(DELTA_STAGE1_SQL, (thread_id, checkpoint_ns, checkpoint_id))
cur.execute(
DELTA_STAGE1_SQL,
(thread_id, checkpoint_ns, checkpoint_id, thread_id, checkpoint_ns),
)
for row in cur:
cid, parent_cid, type_tag, blob = row
cid, type_tag, blob = row
if step_walk_with_row(
cid=cid,
parent_cid=parent_cid,
type_tag=type_tag,
blob=blob,
target_id=checkpoint_id,
@@ -26,16 +26,33 @@ from typing import Any
from langgraph.checkpoint.base import DeltaChannelHistory, PendingWrite
# Stage 1 streams ancestors of `target_cid` newest-first. The `<=`
# predicate keeps target itself in the stream so we can read its
# `parent_checkpoint_id` from the first row without a separate lookup;
# the caller skips target's own writes/seed (matches the
# `BaseCheckpointSaver` contract).
# Stage 1 streams target, then its ancestors nearest-first, by following
# `parent_checkpoint_id` rather than id order: ids are only monotonic within
# one process, so a range scan by id can miss a parent whose id sorts above
# its child's. Target is the anchor row; its own writes/seed are skipped
# (matches the `BaseCheckpointSaver` contract).
#
# `put` is `INSERT OR REPLACE`, so re-putting an existing id under a
# descendant's config makes the chain a loop. `step_walk_with_row` stops on a
# repeated id; sqlite yields recursive rows lazily, so abandoning the cursor
# ends the recursion.
#
# `CROSS JOIN` pins `ancestors` as the outer loop, so each step is one primary
# key lookup. With a plain `JOIN` and no `ANALYZE` stats, sqlite can put
# `checkpoints` outside and scan the whole thread per step.
DELTA_STAGE1_SQL = (
"WITH RECURSIVE ancestors(checkpoint_id, parent_checkpoint_id, type, "
"checkpoint) AS ("
"SELECT checkpoint_id, parent_checkpoint_id, type, checkpoint "
"FROM checkpoints "
"WHERE thread_id = ? AND checkpoint_ns = ? AND checkpoint_id <= ? "
"ORDER BY checkpoint_id DESC"
"WHERE thread_id = ? AND checkpoint_ns = ? AND checkpoint_id = ? "
"UNION ALL "
"SELECT c.checkpoint_id, c.parent_checkpoint_id, c.type, c.checkpoint "
"FROM ancestors a CROSS JOIN checkpoints c "
"ON c.checkpoint_id = a.parent_checkpoint_id "
"WHERE c.thread_id = ? AND c.checkpoint_ns = ?"
") "
"SELECT checkpoint_id, type, checkpoint FROM ancestors"
)
@@ -68,7 +85,6 @@ def build_delta_stage2_sql(*, chain_lens: Sequence[int]) -> str:
def step_walk_with_row(
*,
cid: str,
parent_cid: str | None,
type_tag: str,
blob: bytes,
target_id: str,
@@ -81,36 +97,32 @@ def step_walk_with_row(
) -> bool:
"""Process one streamed stage-1 row in the merged ancestor walk.
The cursor returns (cid, parent_cid, type, blob) rows in
`checkpoint_id` DESC order starting at target. The first row is
target itself; we read its parent_cid to seed the walk and otherwise
skip it (target's own writes/seed are not part of the contract).
The cursor returns (cid, type, blob) rows in walk order starting at
target. The first row is target itself and is skipped (target's own
writes/seed are not part of the contract).
For each subsequent row, if `cid` matches the walk's current
position, we deserialize the blob, append the cid to every
not-yet-seeded channel's chain, and check `channel_values` for
For each subsequent row we deserialize the blob, append the cid to
every not-yet-seeded channel's chain, and check `channel_values` for
seeds. The deserialized checkpoint is dropped before advancing — no
cross-row cache, so peak in-flight is one deserialized checkpoint.
Off-path rows (different branch on the same thread) advance the
cursor without doing any work.
Returns True when every requested channel is seeded — the caller
can stop iterating and close the cursor.
Returns True when the caller can stop iterating and close the cursor:
every requested channel is seeded, or the chain revisited a checkpoint.
"""
if "started" not in walk_state:
if cid == target_id:
walk_state["started"] = True
walk_state["cur_cid"] = parent_cid
walk_state["active"] = {ch for ch in channels if ch not in seeded}
walk_state["walked"] = {cid}
# Not target yet (or target not present): keep streaming.
return False
active: set[str] = walk_state["active"]
if not active:
return True
if cid != walk_state["cur_cid"]:
# Off-path row from a sibling branch — skip without deserializing.
return False
walked: set[str] = walk_state["walked"]
if cid in walked:
return True
walked.add(cid)
for ch in active:
chain_by_ch[ch].append(cid)
ckpt = serde.loads_typed((type_tag, blob))
@@ -120,7 +132,6 @@ def step_walk_with_row(
seeded.add(ch)
active.discard(ch)
del ckpt, channel_values
walk_state["cur_cid"] = parent_cid
return not active
@@ -625,8 +625,8 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
"""Fast-path override of `BaseCheckpointSaver.aget_delta_channel_history`.
See `SqliteSaver.get_delta_channel_history` for design notes; this
is the async equivalent using `aiosqlite` cursors. Stage 1 pages
the parent chain newest-first and Python-deserializes each
is the async equivalent using `aiosqlite` cursors. Stage 1 streams
the parent chain from the target and Python-deserializes each
checkpoint blob to find per-channel snapshots; stage 2 fetches
only the relevant writes via per-channel UNION ALL.
"""
@@ -650,13 +650,13 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
async with self.lock, self.conn.cursor() as cur:
await cur.execute(
DELTA_STAGE1_SQL, (thread_id, checkpoint_ns, checkpoint_id)
DELTA_STAGE1_SQL,
(thread_id, checkpoint_ns, checkpoint_id, thread_id, checkpoint_ns),
)
async for row in cur:
cid, parent_cid, type_tag, blob = row
cid, type_tag, blob = row
if step_walk_with_row(
cid=cid,
parent_cid=parent_cid,
type_tag=type_tag,
blob=blob,
target_id=checkpoint_id,
@@ -547,7 +547,7 @@ class AsyncSqliteStore(AsyncBatchedBaseStore, BaseSqliteStore):
await cur.execute(query, params)
rows = await cur.fetchall()
if needs_refresh and rows and self.ttl_config:
if needs_refresh and self.ttl_config:
keys_to_refresh = []
for row_data in rows:
# Assuming row_data[0] is prefix (text), row_data[1] is key (text)
@@ -0,0 +1,104 @@
from __future__ import annotations
from typing import Any
import pytest
from langgraph.checkpoint.base import (
BaseCheckpointSaver,
Checkpoint,
DeltaChannelHistory,
empty_checkpoint,
)
from langgraph.checkpoint.sqlite import SqliteSaver
from langgraph.checkpoint.sqlite._delta import DELTA_STAGE1_SQL
from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
CHANNEL = "ch"
CONFIG: dict[str, Any] = {"configurable": {"thread_id": "t", "checkpoint_ns": ""}}
EXPECTED: DeltaChannelHistory = {
"writes": [("task", CHANNEL, "write-root")],
"seed": "seed",
}
def _checkpoint(checkpoint_id: str, values: dict[str, Any]) -> Checkpoint:
value = empty_checkpoint()
value["id"] = checkpoint_id
value["channel_values"] = values
return value
PARENT_ID_ORDERS = [
pytest.param("z-older", "a-newer", id="parent_id_sorts_above_child"),
pytest.param("a-older", "z-newer", id="parent_id_sorts_below_child"),
]
@pytest.mark.parametrize(("root_id", "child_id"), PARENT_ID_ORDERS)
def test_sync_walk_reaches_parent_whatever_the_id_order(
root_id: str, child_id: str
) -> None:
with SqliteSaver.from_conn_string(":memory:") as saver:
root = saver.put(CONFIG, _checkpoint(root_id, {CHANNEL: "seed"}), {}, {})
saver.put_writes(root, [(CHANNEL, "write-root")], "task")
child = saver.put(root, _checkpoint(child_id, {}), {}, {})
got = saver.get_delta_channel_history(config=child, channels=[CHANNEL])
reference = BaseCheckpointSaver.get_delta_channel_history(
saver, config=child, channels=[CHANNEL]
)
assert got[CHANNEL] == EXPECTED
assert got[CHANNEL] == reference[CHANNEL], "fast path disagrees with base"
@pytest.mark.parametrize(("root_id", "child_id"), PARENT_ID_ORDERS)
async def test_async_walk_reaches_parent_whatever_the_id_order(
root_id: str, child_id: str
) -> None:
async with AsyncSqliteSaver.from_conn_string(":memory:") as saver:
root = await saver.aput(CONFIG, _checkpoint(root_id, {CHANNEL: "seed"}), {}, {})
await saver.aput_writes(root, [(CHANNEL, "write-root")], "task")
child = await saver.aput(root, _checkpoint(child_id, {}), {}, {})
got = await saver.aget_delta_channel_history(config=child, channels=[CHANNEL])
assert got[CHANNEL] == EXPECTED
def test_walk_reaches_root_of_long_chain_with_descending_ids() -> None:
steps = 40
with SqliteSaver.from_conn_string(":memory:") as saver:
parent = saver.put(
CONFIG, _checkpoint(f"id-{steps:03d}", {CHANNEL: "seed"}), {}, {}
)
saver.put_writes(parent, [(CHANNEL, "write-root")], "task")
for step in range(steps - 1, 0, -1):
parent = saver.put(parent, _checkpoint(f"id-{step:03d}", {}), {}, {})
got = saver.get_delta_channel_history(config=parent, channels=[CHANNEL])
assert got[CHANNEL] == EXPECTED
def test_walk_terminates_when_put_makes_the_parent_chain_cycle() -> None:
with SqliteSaver.from_conn_string(":memory:") as saver:
a = saver.put(CONFIG, _checkpoint("cid-a", {}), {}, {})
b = saver.put(a, _checkpoint("cid-b", {}), {}, {})
repoint_a_under_b = _checkpoint("cid-a", {})
saver.put(b, repoint_a_under_b, {}, {})
got = saver.get_delta_channel_history(config=b, channels=[CHANNEL])
assert got[CHANNEL] == {"writes": []}
def test_walk_step_looks_up_the_parent_by_primary_key() -> None:
with SqliteSaver.from_conn_string(":memory:") as saver:
saver.setup()
plan = [
row[3]
for row in saver.conn.execute(
f"EXPLAIN QUERY PLAN {DELTA_STAGE1_SQL}", ("t", "", "id", "t", "")
)
]
assert any(
step.startswith("SEARCH c ") and "checkpoint_id=?" in step for step in plan
), f"recursive step should look up the parent by key, got {plan}"
+44 -44
View File
@@ -783,14 +783,14 @@ wheels = [
[[package]]
name = "pytest-mock"
version = "3.15.1"
version = "3.16.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/68/14/eb014d26be205d38ad5ad20d9a80f7d201472e08167f0bb4361e251084a9/pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f", size = 34036, upload-time = "2025-09-16T16:37:27.081Z" }
sdist = { url = "https://files.pythonhosted.org/packages/7a/7f/6ed29931d5c8cd396e7c0a55412e6cc88020373365c8685985dea53d26d7/pytest_mock-3.16.0.tar.gz", hash = "sha256:5a8395528b8f498205f3718f575228d0edaed7425fff638f87d1a6c3e0383636", size = 35362, upload-time = "2026-09-27T14:57:55.46Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095, upload-time = "2025-09-16T16:37:25.734Z" },
{ url = "https://files.pythonhosted.org/packages/db/5b/b83a9bf1a3b4ec222f9fa083147ff6816245223da0ab92370e7e056f113f/pytest_mock-3.16.0-py3-none-any.whl", hash = "sha256:007cfeb257801d88d9c0b2a7b5a15a15e73b71968dfd72e7bf8c4a2f8393aec8", size = 10016, upload-time = "2026-09-27T14:57:54.283Z" },
]
[[package]]
@@ -911,27 +911,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.16.5"
version = "0.16.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f3/85/c8e12473c93018f92d19dd988a294202e1c27426c47ec4de53ffb847b8d8/ruff-0.16.5.tar.gz", hash = "sha256:1b88500f9ffbcab3dedb0082c9f9492e91ec3d618aac1236a3e0189938f7040b", size = 4912003, upload-time = "2026-08-27T16:34:18.258Z" }
sdist = { url = "https://files.pythonhosted.org/packages/96/bf/c935ca98e73fe8ce65b87ef08a280c0c1e85295d569228c15e87d8fdfaf1/ruff-0.16.9.tar.gz", hash = "sha256:12b625c6cfba78d285d9f48eda5f053374f1e53cb10ef17342a383750db99161", size = 4948764, upload-time = "2026-09-24T20:37:49.416Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c6/b6/77c90a970fe2dae17a723acbd011043ea97c98d7deacccefdc4ba74ec512/ruff-0.16.5-py3-none-linux_armv6l.whl", hash = "sha256:12e5f673e774c35fbb62f288809c7653b73445f8ecec6b6063fd6ea3521aa14b", size = 10011941, upload-time = "2026-08-27T16:33:41.287Z" },
{ url = "https://files.pythonhosted.org/packages/4b/46/6cf67cf6411885a1d6f7f6d801682f155536a85176d10b605e2ceffed8bd/ruff-0.16.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:eda58a5802de40e7ed5b32b64e0b32539338cc6fcd2c78f61e3ad6a0d79f51c3", size = 10204049, upload-time = "2026-08-27T16:33:44.056Z" },
{ url = "https://files.pythonhosted.org/packages/46/fd/c8720ca7a090abf0c2fef4abe8a5ef6e5127ed15196d8886ff75a2b370e2/ruff-0.16.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5ae9a7b9a8875131f40f8fe967cc86abf899779efd663cb7ce3d572d01da7eb", size = 9809037, upload-time = "2026-08-27T16:33:46.257Z" },
{ url = "https://files.pythonhosted.org/packages/43/45/a684caacdedaca180f52bacccc40bf0789d2c5a7c75f25324853e9eaedb5/ruff-0.16.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b719b0a1f4d59710d283ab2965f621684a108a9e41da622e3b23f0326cd0025", size = 9964129, upload-time = "2026-08-27T16:33:48.352Z" },
{ url = "https://files.pythonhosted.org/packages/9e/f2/5d2bcdaca6b5b93d1b4dfc166cd2aebf7680143a1b38a28759df13a94d31/ruff-0.16.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2298f2780ed1be0c5cb1361e32ab7b1467f3cce7dabe101d2210a314f2fe42e9", size = 9821518, upload-time = "2026-08-27T16:33:50.57Z" },
{ url = "https://files.pythonhosted.org/packages/aa/ff/011cce29accf9257d5974145b733fc653a37985ed6825413a3987cefbfe0/ruff-0.16.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:258f29035a2dd021e7861e631b227a5b3f14e50c1184c9a6a122c5f4576154d7", size = 10534835, upload-time = "2026-08-27T16:33:52.522Z" },
{ url = "https://files.pythonhosted.org/packages/d7/5a/f0cf109bada9bba0e96c90c21c9f9251803f57225c32d293327a03c710d6/ruff-0.16.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9a4f0432966834019c74d1b7e5c51224305d7713f3d7faf3e7451f1a3be3cde", size = 11252550, upload-time = "2026-08-27T16:33:54.521Z" },
{ url = "https://files.pythonhosted.org/packages/63/4d/1d481aaea2046c6a7ed7c291f9004c669cce3c087b6b376ed5b08271e3fe/ruff-0.16.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5eb3a8c3d0ade9cea42b591fd530368e8798380e30e0a308b85a5cf718f09ea", size = 10777949, upload-time = "2026-08-27T16:33:56.88Z" },
{ url = "https://files.pythonhosted.org/packages/ee/34/ee245ca55f64443233034b3d02b03236b19242004281247c079390b7facd/ruff-0.16.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef0f69e191a13a3c9816f63163c88790cb12cd157bbbb384e9c44745702ab105", size = 10311656, upload-time = "2026-08-27T16:33:59.12Z" },
{ url = "https://files.pythonhosted.org/packages/a7/4d/c33a333e341c0a2b96c715b52d89a606f5a34cd4ac493cd9b8d0187186b8/ruff-0.16.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0eeab41fbea2c42f98dfb9822cdccda9d24ba38d49f6dc945b5c236d48f0ef29", size = 10532125, upload-time = "2026-08-27T16:34:01.166Z" },
{ url = "https://files.pythonhosted.org/packages/30/e1/a64cef78b40192497bb98a27a8aa8f2c98ee9ee15bc97f7712d94ef32937/ruff-0.16.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f0768e9df4300713fff30733c87575f68b6f1d8de41184e505b7fdd9c0c95eaf", size = 10097648, upload-time = "2026-08-27T16:34:03.16Z" },
{ url = "https://files.pythonhosted.org/packages/cc/4e/4cdc9ed3c3e109d2f71e62572a37457298d7bc7501ec3138babb7ed32bbd/ruff-0.16.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:95cc70cdc7aa80c338de356279d2adbeb2de0f520b9ecd8aba75b94e95e02f91", size = 9829344, upload-time = "2026-08-27T16:34:05.134Z" },
{ url = "https://files.pythonhosted.org/packages/39/4a/31ed35ce31729955fc583ee0d176d6e784c1290cb0b0a75cb2134c1ab72a/ruff-0.16.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d185c8398ded1bfd91c0c2cb258346307571eccc473a8490af8c3977399c384a", size = 10277117, upload-time = "2026-08-27T16:34:07.425Z" },
{ url = "https://files.pythonhosted.org/packages/a8/a0/60356d86687b4b666d593df213f4dc3041750d024cb7bf2cfa81cfd65c2e/ruff-0.16.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:fb8e3a3c4c6a784150a7ced53b015f4b253fc2bf97a610886419ead64b4756ef", size = 10711653, upload-time = "2026-08-27T16:34:09.712Z" },
{ url = "https://files.pythonhosted.org/packages/ed/20/656d67f5b25ca9bda4e02b1de25867b2954e1d19e03648060f167ad0f4cc/ruff-0.16.5-py3-none-win32.whl", hash = "sha256:288b0a5f080492fe5635db849f9e2e84aa3cce7b7f0e955997d416c507c76a26", size = 10034250, upload-time = "2026-08-27T16:34:11.8Z" },
{ url = "https://files.pythonhosted.org/packages/5b/42/ee8e68a207b9127fcde6c3d7e197def432f346cb1af159e1fa14ca0d1cdc/ruff-0.16.5-py3-none-win_amd64.whl", hash = "sha256:ddc6385fb2137f616357ca03d6c74f4be987f80fed4008566b754f6032b8546f", size = 10516714, upload-time = "2026-08-27T16:34:13.963Z" },
{ url = "https://files.pythonhosted.org/packages/73/e3/7df5a396e445b9ba49ce9a9437439a4d80042c61c0ade199abf8d16de1ac/ruff-0.16.5-py3-none-win_arm64.whl", hash = "sha256:a64abe90968719b851bb7cedffaa8753fbdbdadab483089682db623f3edc587e", size = 10391564, upload-time = "2026-08-27T16:34:16.064Z" },
{ url = "https://files.pythonhosted.org/packages/0d/26/df51322b52ee1ada7eff2d071ea09d11d5c2d1dcc9f02594f5785c4d1635/ruff-0.16.9-py3-none-linux_armv6l.whl", hash = "sha256:95e6f022090368ab3b824c36276839c53b2adf1a3f4c09fefc33dfc400f6da96", size = 10082922, upload-time = "2026-09-24T20:37:13.045Z" },
{ url = "https://files.pythonhosted.org/packages/a5/27/7bf51f5a7aa375e9f339280a303aab44ca75dc1525f1cdc5991761685b0f/ruff-0.16.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a5f27be168556594a86d2f415db0cf43f5291917849318f873c7e2791f7a8c67", size = 10236360, upload-time = "2026-09-24T20:37:16.049Z" },
{ url = "https://files.pythonhosted.org/packages/b6/63/09659283f92f02dff45809da194a70da2f688d87c55d8875c4fae3536072/ruff-0.16.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1632eb1d6197f33bd00b1acbc5b71009e89a8895c158e2d2b03a834fac964ab6", size = 9892940, upload-time = "2026-09-24T20:37:17.957Z" },
{ url = "https://files.pythonhosted.org/packages/24/58/98de1b72ec172f5f8f1731236fe21585b3998bf7dfe9fcc44ae9ba626012/ruff-0.16.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3f951b14d865d5952c89d40a5ca07e87abe24fa5453299878411e127748fb1c", size = 10032114, upload-time = "2026-09-24T20:37:19.942Z" },
{ url = "https://files.pythonhosted.org/packages/c8/7d/f1e17c54ab59d4bad1dce8ee3e22a7a1d0ef4745240decacdcf3832b5bb2/ruff-0.16.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:447fc07e1573afff7cb02803462b12b6c8ece7cf10e2cd78565fa6d7a1c0bf8d", size = 9910227, upload-time = "2026-09-24T20:37:21.872Z" },
{ url = "https://files.pythonhosted.org/packages/34/19/436f647a65075bbd3bab2668b3bdaa5120559b294694018cdcefabbbf30b/ruff-0.16.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a3e039a6a40ed976c491722b60e0ae4a4aa1a86057f540ee7a37a5d19ae9120", size = 10547484, upload-time = "2026-09-24T20:37:24.229Z" },
{ url = "https://files.pythonhosted.org/packages/03/59/38430a6bc2f6d8095447ac39625cf8b6e9344a47e6c26225c8ba1bff3ffb/ruff-0.16.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4684dded7db60aa57cb118fa158630f5feade4af5782903b6053484bdf9bd129", size = 11412367, upload-time = "2026-09-24T20:37:26.307Z" },
{ url = "https://files.pythonhosted.org/packages/c8/bd/bbb6d7fc7f208c8b8c50dd5dc8206e4cfdb1e7a8fb852606a3adf370c880/ruff-0.16.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d29c934357e45642fda2f34c0b1f4025b4a6c01e15e4bf0016879d60078a142c", size = 10869787, upload-time = "2026-09-24T20:37:28.35Z" },
{ url = "https://files.pythonhosted.org/packages/bc/b8/9c543074918061abbefc3bd139bee22de35abedb00dde0f2d27288838962/ruff-0.16.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a21713e629d3e5bdb2f5c2def1cc7f04f47fa8e1a7eb0571b4a28e1da64bc728", size = 10406494, upload-time = "2026-09-24T20:37:30.624Z" },
{ url = "https://files.pythonhosted.org/packages/35/7a/5a8851bd146e7ccf8fd4b003f6c75c11f8fbdb0e60673b45097986b6bf41/ruff-0.16.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7baa24ef5fc8e77aa93879e1d3f43754a01ae488e869f1ae30cf431afd4d2452", size = 10590083, upload-time = "2026-09-24T20:37:32.439Z" },
{ url = "https://files.pythonhosted.org/packages/87/f0/4c3467188f23f806960b46fa76575a7cd0514c9ba90562650b71efc96980/ruff-0.16.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a41aac6230aadfaa133bdfa1614488531ffa3e0837567ae04c0da2058a9c0f9e", size = 10119151, upload-time = "2026-09-24T20:37:34.581Z" },
{ url = "https://files.pythonhosted.org/packages/15/34/5a4def5adea572ce6aea0bb64f21f928ee317b80e0db747d7979b01d7261/ruff-0.16.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c2529fb5896d49115b0e9aa8f887490b34bbe76baf879ec2264ac59406869ce7", size = 9911544, upload-time = "2026-09-24T20:37:36.796Z" },
{ url = "https://files.pythonhosted.org/packages/62/5d/d15ebea7499eef9373318c0ee6ca127832927c6529731f6d48e18dce7ca9/ruff-0.16.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:41e3870277694177429b56406d65dfbdb2c2802c52b715edaf6a0b829c69d4ee", size = 10269884, upload-time = "2026-09-24T20:37:38.857Z" },
{ url = "https://files.pythonhosted.org/packages/d1/56/c5d3cd119ded7a3c7aba0e961b69cb3df701c91662c98ad694467d060ce1/ruff-0.16.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8adbe4e58af167f767d7b2ba5e83c42e878350796cf78c2f5e14ab9903a92588", size = 10749366, upload-time = "2026-09-24T20:37:41.042Z" },
{ url = "https://files.pythonhosted.org/packages/ac/fe/734ec7527029ac757ecf821f143c9f3fcf69149c21f53a044a899b430f5a/ruff-0.16.9-py3-none-win32.whl", hash = "sha256:0e1dbc2073624dee6618d41d0098690a7244654af746704b64759e12b6b6b385", size = 10152355, upload-time = "2026-09-24T20:37:43.025Z" },
{ url = "https://files.pythonhosted.org/packages/14/21/26e4643629b3ebb44f0a06f9c9a53058d63d989415f63a9a3c28e2ee7f22/ruff-0.16.9-py3-none-win_amd64.whl", hash = "sha256:6bd40fec8cd4c8a3d4dd589bd8ad4e6320c13c29234159bfd959a40d529d597b", size = 10592965, upload-time = "2026-09-24T20:37:44.944Z" },
{ url = "https://files.pythonhosted.org/packages/51/60/5fb1a39dbb5ae314d5f59bc7348a63c1d5c20f3cd83914c4b5cb0be31d2d/ruff-0.16.9-py3-none-win_arm64.whl", hash = "sha256:ed1a252039200f57a59eebc063b54beabea67bfbaaca0eeaa7f54b5fbcda2284", size = 10458649, upload-time = "2026-09-24T20:37:46.882Z" },
]
[[package]]
@@ -1011,27 +1011,27 @@ wheels = [
[[package]]
name = "ty"
version = "0.0.75"
version = "0.0.84"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/81/d0/d0c96f898d6974a4a3569ab3efdf9512c04ad99f9203effb55f72497fe97/ty-0.0.75.tar.gz", hash = "sha256:4c5eead33dfbf6e2ebb4f400f74b51ffc9bab702a6f23ddb648a1cbb740387e3", size = 6868326, upload-time = "2026-08-26T20:23:40.399Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e1/f6/34f8869c45ea87fe6a931ffa824b1fe4428167173543d92988d631add355/ty-0.0.84.tar.gz", hash = "sha256:0cefdb0cd5d399418dbe83c349ba605047b7dff815ae6f460c80e8522b40be67", size = 7409537, upload-time = "2026-09-24T13:16:24.367Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/6c/b12d03505f17581f0cfa3c12273fe34c1d67b36dfda1bc561a6bdc16512b/ty-0.0.75-py3-none-linux_armv6l.whl", hash = "sha256:e5409f50db2246fd4bd039d93d261e0cfa1daa554a4fb77256f91072c570349a", size = 12972606, upload-time = "2026-08-26T20:22:59.716Z" },
{ url = "https://files.pythonhosted.org/packages/d1/aa/30f11eecd9215a9f87e8fe8baaf48f3ce905f5d75b8e4aac70f0091f130c/ty-0.0.75-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5e7b8b3472fb9bb2eeab314984b265df08a7a9d518867a9e6020eebc06570be2", size = 12527158, upload-time = "2026-08-26T20:23:02.767Z" },
{ url = "https://files.pythonhosted.org/packages/f2/11/7fd7001b0b5c6610bfbad7357e47d5fe6f82d4e84e94c53776a478f5e9f8/ty-0.0.75-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c6ccf34169821fe0d23e3360deeef981d217963412f1d087b9bdd32ec57f7a57", size = 12400533, upload-time = "2026-08-26T20:23:04.965Z" },
{ url = "https://files.pythonhosted.org/packages/fd/7f/1e284ea3d348d7be02f12d83bc22ed9ef193033f863f05b64db99027f141/ty-0.0.75-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842ebb41e9c6c334b40768704e20b1a69d5c6b08805b289d5e0e2565f49f2de1", size = 12420592, upload-time = "2026-08-26T20:23:07.427Z" },
{ url = "https://files.pythonhosted.org/packages/2d/ab/d813271543370c47fd74b5118f2066ab32b0983e907b1821f3f9a6d0fa7f/ty-0.0.75-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf7a5a723c5f1e0fab4ffbfe9bd95123a526ed48f206e5f25cb2161ca294007a", size = 12739219, upload-time = "2026-08-26T20:23:09.809Z" },
{ url = "https://files.pythonhosted.org/packages/31/5b/95b49cc5570fd92a7bf63732f649b31906158721e03c7fcb1b5be74ee3bf/ty-0.0.75-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54382f98e5da292fcd7104391afef5105c35bb2f312e29bea6f5fa419935255c", size = 13494046, upload-time = "2026-08-26T20:23:12.191Z" },
{ url = "https://files.pythonhosted.org/packages/2c/0d/502d2dd68173cf020e1ad2bdbab9544c86776de0b0e2ed15f8c2fe006e3d/ty-0.0.75-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac13b180dc2aade2cd243f56b01650e78bf091a2e522ad3bc947245d7837c613", size = 13938899, upload-time = "2026-08-26T20:23:14.764Z" },
{ url = "https://files.pythonhosted.org/packages/20/5b/f3b12a25c07224456219fc2bd20db0ad7e40b304be0ff6aad728da0135f9/ty-0.0.75-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:752df7951a443219d7f1ff817e3723c85d428565ff449e08a7a93ba821661526", size = 13656711, upload-time = "2026-08-26T20:23:17.145Z" },
{ url = "https://files.pythonhosted.org/packages/51/7b/f090ad306e2b15a07b332d647138c5264b89d9758855ecce8b8a10bcb153/ty-0.0.75-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fd399feedf7cee816563c1baec45fc1c0b3c89f1ea42364920b688004b5b7da", size = 13093499, upload-time = "2026-08-26T20:23:19.489Z" },
{ url = "https://files.pythonhosted.org/packages/f1/4b/f69b99aaaca0c7c65d5f114b186b26b21666f767b0c69eec99a2bdccc061/ty-0.0.75-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:d7625f6f56c7dc1e873579fdc9e432a0e21e302afe847ab60704d2303442a92e", size = 13520580, upload-time = "2026-08-26T20:23:21.789Z" },
{ url = "https://files.pythonhosted.org/packages/b6/e7/692c5f905c0345a15d2255fc74066d660f030254ae8dcdaf33f5a5c2f279/ty-0.0.75-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:89e7d527e95a2534b70cae29e94c104b84082760ea05927d23bb87280969c104", size = 12524095, upload-time = "2026-08-26T20:23:24.026Z" },
{ url = "https://files.pythonhosted.org/packages/ba/9a/f42b12cf265ea95344bf554764c4791cfb273bdd628aadd7c209af7cadc3/ty-0.0.75-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0843f134440740706e01bee5f88f4cfc10e9b018bddb9e4ef4c12dc9fc0c9aef", size = 12756591, upload-time = "2026-08-26T20:23:26.126Z" },
{ url = "https://files.pythonhosted.org/packages/7c/5e/9b180c133cb9cce48179a7d2bf9e1802d992aa8176a918e0e05205760b42/ty-0.0.75-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1bd0ec0e50ee1376875c88891efe6f549c3560fa5b2ddad79a425cd5a6218b9c", size = 12998754, upload-time = "2026-08-26T20:23:28.353Z" },
{ url = "https://files.pythonhosted.org/packages/39/f6/3c6ef5dd550103e29905121c67fb96a374564f31a2f44c6faa1af98c2d61/ty-0.0.75-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1f9eafd561f90110d5e29f589ec3e956c4686e2f6631348d99276436f5cbe4d1", size = 13316474, upload-time = "2026-08-26T20:23:30.857Z" },
{ url = "https://files.pythonhosted.org/packages/bb/52/12776337874c821076bd5368e352ccd9e67174790abe3b856f749cb3524b/ty-0.0.75-py3-none-win32.whl", hash = "sha256:05063a6fafe2154b794a7f964515d148e51acd186d72d4a3acd347ee9fa19336", size = 12316315, upload-time = "2026-08-26T20:23:33.528Z" },
{ url = "https://files.pythonhosted.org/packages/53/e6/bb51e16af5c7138c9f52f8f3d0a401a371c6798d092e3b74926f186a9814/ty-0.0.75-py3-none-win_amd64.whl", hash = "sha256:81cf1ba5f6b7536ad56747865214255d9bc8e80533a689dbb9ddeaad464b09f1", size = 12917267, upload-time = "2026-08-26T20:23:35.978Z" },
{ url = "https://files.pythonhosted.org/packages/39/73/4542f829107468b5de4231af67f29927c093bfad11f3c1e5b2c08fb1206b/ty-0.0.75-py3-none-win_arm64.whl", hash = "sha256:541c9af5b7a0ad23d15ec315a7da81150833c359f48124ed3789ff25eacd6f42", size = 12711024, upload-time = "2026-08-26T20:23:38.159Z" },
{ url = "https://files.pythonhosted.org/packages/aa/0c/600648778e1c79133ce6b6a5c4c2531ae16b90c9b30f5041b38b574f61b8/ty-0.0.84-py3-none-linux_armv6l.whl", hash = "sha256:868438e2b9abfc835dd5b5b07ed693db95d8348ac40e3228252511d63ae87695", size = 13935333, upload-time = "2026-09-24T13:15:31.167Z" },
{ url = "https://files.pythonhosted.org/packages/c5/3b/27f06f49945c36170765fad82076898039ae3873338e9865f876dd62f12c/ty-0.0.84-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b00f39b521f0b559cde0f6abf8dd47213b513b04f33d58efeb9b98486a16bb17", size = 13511328, upload-time = "2026-09-24T13:15:34.446Z" },
{ url = "https://files.pythonhosted.org/packages/fc/b6/b12dd130e7f30141f0645614f454c925991cd389b1cc6c8284fd6bf32326/ty-0.0.84-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8f78c2915567f2ee62ce0c24d86091bc76f81577677755e242d09951db588b9a", size = 13445445, upload-time = "2026-09-24T13:15:37.476Z" },
{ url = "https://files.pythonhosted.org/packages/44/96/f012de4b3c1d9a4773326621380d768b4d48c47e620dc012775c5e01c7d7/ty-0.0.84-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61155cad0921e890d86d1d911a40b3a0e924ef4bdc3b4f3865a6c89c7e3012dc", size = 13471235, upload-time = "2026-09-24T13:15:40.64Z" },
{ url = "https://files.pythonhosted.org/packages/05/32/dca630f5f5353fa7bf67eebccf1549df99b16656d21071d0df6677c826a5/ty-0.0.84-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:417c3bf14947ed16b0b92976ab333c27915590354e96d4f581709068d3811355", size = 13680704, upload-time = "2026-09-24T13:15:43.817Z" },
{ url = "https://files.pythonhosted.org/packages/44/8d/33702c8f62f05ad45b33644fb914d483de6a0a7bc8e51884e9b8773e6d69/ty-0.0.84-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e06ef117759f654f5379efe9ae79bda8a186016c016f1023d05c34f8e15c1546", size = 14518923, upload-time = "2026-09-24T13:15:46.802Z" },
{ url = "https://files.pythonhosted.org/packages/c8/a1/da3246e6ef2ae0e842bca4058b25c54bee55ab058ffff4ee54e72517ec01/ty-0.0.84-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a05d1d53db8b64410ab38c6e32c5898510584869d1d5dd9c0605db81c9aef7df", size = 15027731, upload-time = "2026-09-24T13:15:49.755Z" },
{ url = "https://files.pythonhosted.org/packages/20/17/b0099098a560aeb4f9fde6c912f9a81622c3e44e6555e1fbe322b368ec31/ty-0.0.84-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b92400494ab855cfb1204ac1101e3f53b2d09a8e21d171758b2cf9acdab1809e", size = 14748260, upload-time = "2026-09-24T13:15:52.713Z" },
{ url = "https://files.pythonhosted.org/packages/60/d5/32cd67aedb271f006e716ad093806c96c5d7e2af86be8255469dbd3d76c8/ty-0.0.84-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af17eb391ae3027fed9be1780bea555c2b8a25ba68e184c627b4981b2c9eaab7", size = 14205858, upload-time = "2026-09-24T13:15:55.677Z" },
{ url = "https://files.pythonhosted.org/packages/43/c4/638ac62ca2e8eca1b92e3e16273085744fada728b993500819b5c258ca15/ty-0.0.84-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:44cf06af0e7ec78ea6d8ff33a3450fc19627756a4fba681f7410d4e3ef63047a", size = 14573196, upload-time = "2026-09-24T13:15:59.165Z" },
{ url = "https://files.pythonhosted.org/packages/a6/f6/9ee81c5d8921e5fd5f10889ae563c95cd3272b31df2ada528919ca1cef6b/ty-0.0.84-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c6e56b443ff9ba462e34bfbc1e582004c2719ed35f8f93a433744b0ba0afb2d9", size = 13480760, upload-time = "2026-09-24T13:16:02.313Z" },
{ url = "https://files.pythonhosted.org/packages/f6/83/fbe5d1177667ae16d84c3242846b143809c9cc09568b333e5a9b4d5908f6/ty-0.0.84-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b6562fcc48820c1030e2a4509ef2c14ef93043ca4860280074314ac3a825b95", size = 13696346, upload-time = "2026-09-24T13:16:05.391Z" },
{ url = "https://files.pythonhosted.org/packages/86/9a/1b4ac9ddc34cc0ab4624bc219825d66af52f1ad87f4778ad08ad03fa06d5/ty-0.0.84-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dee7421451efcbd70f03e95a8f2c8d9e5ec3d35edcd27b4095ee00ee062abfc4", size = 13959410, upload-time = "2026-09-24T13:16:08.661Z" },
{ url = "https://files.pythonhosted.org/packages/c9/04/70e289437a67dfd686056ab4fd91880261a8233033a6a95d29393741fb97/ty-0.0.84-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:31e96307cf621babe969307dd657783d672e2d8bdbd06493710da635bf63fa07", size = 14350294, upload-time = "2026-09-24T13:16:11.865Z" },
{ url = "https://files.pythonhosted.org/packages/9c/f4/ae7dbd118425c850981d23efb850f0d9d7f6b8d2b852bde2767434f668b4/ty-0.0.84-py3-none-win32.whl", hash = "sha256:4bdc85f91cbaae35825f2b17bb4ac5de0563367875cb0f42b2bf07a1bf7ff2ba", size = 13176439, upload-time = "2026-09-24T13:16:15.049Z" },
{ url = "https://files.pythonhosted.org/packages/29/ec/994d87252f065dda5a500bc8afc726d18f6582d81d6f4ff1feb8a267c800/ty-0.0.84-py3-none-win_amd64.whl", hash = "sha256:71cc9aa7a7c89d4e12c6a814e9c0c3310ad5bee44efedbd6f5a42d91e9ac0f0d", size = 13962879, upload-time = "2026-09-24T13:16:18.191Z" },
{ url = "https://files.pythonhosted.org/packages/6d/1c/e6e91852b72566b1ab9aca504712857dfb89324c12092a5bd61d42d34427/ty-0.0.84-py3-none-win_arm64.whl", hash = "sha256:6c9d3718c4a0d318bc9c92af9b2aa85c3294e7dff54cf1d69ad79568f56516da", size = 13656453, upload-time = "2026-09-24T13:16:21.51Z" },
]
[[package]]
@@ -1057,11 +1057,11 @@ wheels = [
[[package]]
name = "urllib3"
version = "2.7.0"
version = "2.8.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
{ url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" },
]
[[package]]
+47 -47
View File
@@ -268,7 +268,7 @@ wheels = [
[[package]]
name = "langchain-core"
version = "1.6.1"
version = "1.6.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "httpx" },
@@ -282,9 +282,9 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "uuid-utils" },
]
sdist = { url = "https://files.pythonhosted.org/packages/90/12/aff76ca89c219ebe6f9dd3c5dbc4e3b1cf5450e9fc7037dccad23d45cd7a/langchain_core-1.6.1.tar.gz", hash = "sha256:1b156cb395aac4f009a8a1b38a574c7d948fe2d5f74c96e0d8a5017b4149e04f", size = 1003359, upload-time = "2026-08-27T19:31:14.956Z" }
sdist = { url = "https://files.pythonhosted.org/packages/ed/ed/ceecd3bfcfc77a94cf30a9f1506e907fdea447458825e01914a72d2d1a6f/langchain_core-1.6.5.tar.gz", hash = "sha256:bdb059fef65473fd444558dbb18f50901657402c43ceed9dc0fdc7b76a393c6b", size = 1007041, upload-time = "2026-09-24T18:11:06.487Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8e/25/f50dd65673c819aa33d3c34df58c115dbb6ec627d19f93e6e401dd0fc8d7/langchain_core-1.6.1-py3-none-any.whl", hash = "sha256:954a84132a5cb0435d27b910e336347b6744ecc18fbeef1e2de7029a0959841a", size = 571478, upload-time = "2026-08-27T19:31:13.34Z" },
{ url = "https://files.pythonhosted.org/packages/59/68/447ac7e734990b7ed9dcfc3b6dee9a4cd4d4169e296429fa71a9a47c1c7b/langchain_core-1.6.5-py3-none-any.whl", hash = "sha256:54c7b0e9314b9084fb04405bb33dc5d32986d512d92b7b8863899cd5f6267556", size = 572136, upload-time = "2026-09-24T18:11:04.837Z" },
]
[[package]]
@@ -1015,14 +1015,14 @@ wheels = [
[[package]]
name = "pytest-mock"
version = "3.15.1"
version = "3.16.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/68/14/eb014d26be205d38ad5ad20d9a80f7d201472e08167f0bb4361e251084a9/pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f", size = 34036, upload-time = "2025-09-16T16:37:27.081Z" }
sdist = { url = "https://files.pythonhosted.org/packages/7a/7f/6ed29931d5c8cd396e7c0a55412e6cc88020373365c8685985dea53d26d7/pytest_mock-3.16.0.tar.gz", hash = "sha256:5a8395528b8f498205f3718f575228d0edaed7425fff638f87d1a6c3e0383636", size = 35362, upload-time = "2026-09-27T14:57:55.46Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095, upload-time = "2025-09-16T16:37:25.734Z" },
{ url = "https://files.pythonhosted.org/packages/db/5b/b83a9bf1a3b4ec222f9fa083147ff6816245223da0ab92370e7e056f113f/pytest_mock-3.16.0-py3-none-any.whl", hash = "sha256:007cfeb257801d88d9c0b2a7b5a15a15e73b71968dfd72e7bf8c4a2f8393aec8", size = 10016, upload-time = "2026-09-27T14:57:54.283Z" },
]
[[package]]
@@ -1164,27 +1164,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.16.5"
version = "0.16.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f3/85/c8e12473c93018f92d19dd988a294202e1c27426c47ec4de53ffb847b8d8/ruff-0.16.5.tar.gz", hash = "sha256:1b88500f9ffbcab3dedb0082c9f9492e91ec3d618aac1236a3e0189938f7040b", size = 4912003, upload-time = "2026-08-27T16:34:18.258Z" }
sdist = { url = "https://files.pythonhosted.org/packages/96/bf/c935ca98e73fe8ce65b87ef08a280c0c1e85295d569228c15e87d8fdfaf1/ruff-0.16.9.tar.gz", hash = "sha256:12b625c6cfba78d285d9f48eda5f053374f1e53cb10ef17342a383750db99161", size = 4948764, upload-time = "2026-09-24T20:37:49.416Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c6/b6/77c90a970fe2dae17a723acbd011043ea97c98d7deacccefdc4ba74ec512/ruff-0.16.5-py3-none-linux_armv6l.whl", hash = "sha256:12e5f673e774c35fbb62f288809c7653b73445f8ecec6b6063fd6ea3521aa14b", size = 10011941, upload-time = "2026-08-27T16:33:41.287Z" },
{ url = "https://files.pythonhosted.org/packages/4b/46/6cf67cf6411885a1d6f7f6d801682f155536a85176d10b605e2ceffed8bd/ruff-0.16.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:eda58a5802de40e7ed5b32b64e0b32539338cc6fcd2c78f61e3ad6a0d79f51c3", size = 10204049, upload-time = "2026-08-27T16:33:44.056Z" },
{ url = "https://files.pythonhosted.org/packages/46/fd/c8720ca7a090abf0c2fef4abe8a5ef6e5127ed15196d8886ff75a2b370e2/ruff-0.16.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5ae9a7b9a8875131f40f8fe967cc86abf899779efd663cb7ce3d572d01da7eb", size = 9809037, upload-time = "2026-08-27T16:33:46.257Z" },
{ url = "https://files.pythonhosted.org/packages/43/45/a684caacdedaca180f52bacccc40bf0789d2c5a7c75f25324853e9eaedb5/ruff-0.16.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b719b0a1f4d59710d283ab2965f621684a108a9e41da622e3b23f0326cd0025", size = 9964129, upload-time = "2026-08-27T16:33:48.352Z" },
{ url = "https://files.pythonhosted.org/packages/9e/f2/5d2bcdaca6b5b93d1b4dfc166cd2aebf7680143a1b38a28759df13a94d31/ruff-0.16.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2298f2780ed1be0c5cb1361e32ab7b1467f3cce7dabe101d2210a314f2fe42e9", size = 9821518, upload-time = "2026-08-27T16:33:50.57Z" },
{ url = "https://files.pythonhosted.org/packages/aa/ff/011cce29accf9257d5974145b733fc653a37985ed6825413a3987cefbfe0/ruff-0.16.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:258f29035a2dd021e7861e631b227a5b3f14e50c1184c9a6a122c5f4576154d7", size = 10534835, upload-time = "2026-08-27T16:33:52.522Z" },
{ url = "https://files.pythonhosted.org/packages/d7/5a/f0cf109bada9bba0e96c90c21c9f9251803f57225c32d293327a03c710d6/ruff-0.16.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9a4f0432966834019c74d1b7e5c51224305d7713f3d7faf3e7451f1a3be3cde", size = 11252550, upload-time = "2026-08-27T16:33:54.521Z" },
{ url = "https://files.pythonhosted.org/packages/63/4d/1d481aaea2046c6a7ed7c291f9004c669cce3c087b6b376ed5b08271e3fe/ruff-0.16.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5eb3a8c3d0ade9cea42b591fd530368e8798380e30e0a308b85a5cf718f09ea", size = 10777949, upload-time = "2026-08-27T16:33:56.88Z" },
{ url = "https://files.pythonhosted.org/packages/ee/34/ee245ca55f64443233034b3d02b03236b19242004281247c079390b7facd/ruff-0.16.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef0f69e191a13a3c9816f63163c88790cb12cd157bbbb384e9c44745702ab105", size = 10311656, upload-time = "2026-08-27T16:33:59.12Z" },
{ url = "https://files.pythonhosted.org/packages/a7/4d/c33a333e341c0a2b96c715b52d89a606f5a34cd4ac493cd9b8d0187186b8/ruff-0.16.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0eeab41fbea2c42f98dfb9822cdccda9d24ba38d49f6dc945b5c236d48f0ef29", size = 10532125, upload-time = "2026-08-27T16:34:01.166Z" },
{ url = "https://files.pythonhosted.org/packages/30/e1/a64cef78b40192497bb98a27a8aa8f2c98ee9ee15bc97f7712d94ef32937/ruff-0.16.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f0768e9df4300713fff30733c87575f68b6f1d8de41184e505b7fdd9c0c95eaf", size = 10097648, upload-time = "2026-08-27T16:34:03.16Z" },
{ url = "https://files.pythonhosted.org/packages/cc/4e/4cdc9ed3c3e109d2f71e62572a37457298d7bc7501ec3138babb7ed32bbd/ruff-0.16.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:95cc70cdc7aa80c338de356279d2adbeb2de0f520b9ecd8aba75b94e95e02f91", size = 9829344, upload-time = "2026-08-27T16:34:05.134Z" },
{ url = "https://files.pythonhosted.org/packages/39/4a/31ed35ce31729955fc583ee0d176d6e784c1290cb0b0a75cb2134c1ab72a/ruff-0.16.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d185c8398ded1bfd91c0c2cb258346307571eccc473a8490af8c3977399c384a", size = 10277117, upload-time = "2026-08-27T16:34:07.425Z" },
{ url = "https://files.pythonhosted.org/packages/a8/a0/60356d86687b4b666d593df213f4dc3041750d024cb7bf2cfa81cfd65c2e/ruff-0.16.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:fb8e3a3c4c6a784150a7ced53b015f4b253fc2bf97a610886419ead64b4756ef", size = 10711653, upload-time = "2026-08-27T16:34:09.712Z" },
{ url = "https://files.pythonhosted.org/packages/ed/20/656d67f5b25ca9bda4e02b1de25867b2954e1d19e03648060f167ad0f4cc/ruff-0.16.5-py3-none-win32.whl", hash = "sha256:288b0a5f080492fe5635db849f9e2e84aa3cce7b7f0e955997d416c507c76a26", size = 10034250, upload-time = "2026-08-27T16:34:11.8Z" },
{ url = "https://files.pythonhosted.org/packages/5b/42/ee8e68a207b9127fcde6c3d7e197def432f346cb1af159e1fa14ca0d1cdc/ruff-0.16.5-py3-none-win_amd64.whl", hash = "sha256:ddc6385fb2137f616357ca03d6c74f4be987f80fed4008566b754f6032b8546f", size = 10516714, upload-time = "2026-08-27T16:34:13.963Z" },
{ url = "https://files.pythonhosted.org/packages/73/e3/7df5a396e445b9ba49ce9a9437439a4d80042c61c0ade199abf8d16de1ac/ruff-0.16.5-py3-none-win_arm64.whl", hash = "sha256:a64abe90968719b851bb7cedffaa8753fbdbdadab483089682db623f3edc587e", size = 10391564, upload-time = "2026-08-27T16:34:16.064Z" },
{ url = "https://files.pythonhosted.org/packages/0d/26/df51322b52ee1ada7eff2d071ea09d11d5c2d1dcc9f02594f5785c4d1635/ruff-0.16.9-py3-none-linux_armv6l.whl", hash = "sha256:95e6f022090368ab3b824c36276839c53b2adf1a3f4c09fefc33dfc400f6da96", size = 10082922, upload-time = "2026-09-24T20:37:13.045Z" },
{ url = "https://files.pythonhosted.org/packages/a5/27/7bf51f5a7aa375e9f339280a303aab44ca75dc1525f1cdc5991761685b0f/ruff-0.16.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a5f27be168556594a86d2f415db0cf43f5291917849318f873c7e2791f7a8c67", size = 10236360, upload-time = "2026-09-24T20:37:16.049Z" },
{ url = "https://files.pythonhosted.org/packages/b6/63/09659283f92f02dff45809da194a70da2f688d87c55d8875c4fae3536072/ruff-0.16.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1632eb1d6197f33bd00b1acbc5b71009e89a8895c158e2d2b03a834fac964ab6", size = 9892940, upload-time = "2026-09-24T20:37:17.957Z" },
{ url = "https://files.pythonhosted.org/packages/24/58/98de1b72ec172f5f8f1731236fe21585b3998bf7dfe9fcc44ae9ba626012/ruff-0.16.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3f951b14d865d5952c89d40a5ca07e87abe24fa5453299878411e127748fb1c", size = 10032114, upload-time = "2026-09-24T20:37:19.942Z" },
{ url = "https://files.pythonhosted.org/packages/c8/7d/f1e17c54ab59d4bad1dce8ee3e22a7a1d0ef4745240decacdcf3832b5bb2/ruff-0.16.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:447fc07e1573afff7cb02803462b12b6c8ece7cf10e2cd78565fa6d7a1c0bf8d", size = 9910227, upload-time = "2026-09-24T20:37:21.872Z" },
{ url = "https://files.pythonhosted.org/packages/34/19/436f647a65075bbd3bab2668b3bdaa5120559b294694018cdcefabbbf30b/ruff-0.16.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a3e039a6a40ed976c491722b60e0ae4a4aa1a86057f540ee7a37a5d19ae9120", size = 10547484, upload-time = "2026-09-24T20:37:24.229Z" },
{ url = "https://files.pythonhosted.org/packages/03/59/38430a6bc2f6d8095447ac39625cf8b6e9344a47e6c26225c8ba1bff3ffb/ruff-0.16.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4684dded7db60aa57cb118fa158630f5feade4af5782903b6053484bdf9bd129", size = 11412367, upload-time = "2026-09-24T20:37:26.307Z" },
{ url = "https://files.pythonhosted.org/packages/c8/bd/bbb6d7fc7f208c8b8c50dd5dc8206e4cfdb1e7a8fb852606a3adf370c880/ruff-0.16.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d29c934357e45642fda2f34c0b1f4025b4a6c01e15e4bf0016879d60078a142c", size = 10869787, upload-time = "2026-09-24T20:37:28.35Z" },
{ url = "https://files.pythonhosted.org/packages/bc/b8/9c543074918061abbefc3bd139bee22de35abedb00dde0f2d27288838962/ruff-0.16.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a21713e629d3e5bdb2f5c2def1cc7f04f47fa8e1a7eb0571b4a28e1da64bc728", size = 10406494, upload-time = "2026-09-24T20:37:30.624Z" },
{ url = "https://files.pythonhosted.org/packages/35/7a/5a8851bd146e7ccf8fd4b003f6c75c11f8fbdb0e60673b45097986b6bf41/ruff-0.16.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7baa24ef5fc8e77aa93879e1d3f43754a01ae488e869f1ae30cf431afd4d2452", size = 10590083, upload-time = "2026-09-24T20:37:32.439Z" },
{ url = "https://files.pythonhosted.org/packages/87/f0/4c3467188f23f806960b46fa76575a7cd0514c9ba90562650b71efc96980/ruff-0.16.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a41aac6230aadfaa133bdfa1614488531ffa3e0837567ae04c0da2058a9c0f9e", size = 10119151, upload-time = "2026-09-24T20:37:34.581Z" },
{ url = "https://files.pythonhosted.org/packages/15/34/5a4def5adea572ce6aea0bb64f21f928ee317b80e0db747d7979b01d7261/ruff-0.16.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c2529fb5896d49115b0e9aa8f887490b34bbe76baf879ec2264ac59406869ce7", size = 9911544, upload-time = "2026-09-24T20:37:36.796Z" },
{ url = "https://files.pythonhosted.org/packages/62/5d/d15ebea7499eef9373318c0ee6ca127832927c6529731f6d48e18dce7ca9/ruff-0.16.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:41e3870277694177429b56406d65dfbdb2c2802c52b715edaf6a0b829c69d4ee", size = 10269884, upload-time = "2026-09-24T20:37:38.857Z" },
{ url = "https://files.pythonhosted.org/packages/d1/56/c5d3cd119ded7a3c7aba0e961b69cb3df701c91662c98ad694467d060ce1/ruff-0.16.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8adbe4e58af167f767d7b2ba5e83c42e878350796cf78c2f5e14ab9903a92588", size = 10749366, upload-time = "2026-09-24T20:37:41.042Z" },
{ url = "https://files.pythonhosted.org/packages/ac/fe/734ec7527029ac757ecf821f143c9f3fcf69149c21f53a044a899b430f5a/ruff-0.16.9-py3-none-win32.whl", hash = "sha256:0e1dbc2073624dee6618d41d0098690a7244654af746704b64759e12b6b6b385", size = 10152355, upload-time = "2026-09-24T20:37:43.025Z" },
{ url = "https://files.pythonhosted.org/packages/14/21/26e4643629b3ebb44f0a06f9c9a53058d63d989415f63a9a3c28e2ee7f22/ruff-0.16.9-py3-none-win_amd64.whl", hash = "sha256:6bd40fec8cd4c8a3d4dd589bd8ad4e6320c13c29234159bfd959a40d529d597b", size = 10592965, upload-time = "2026-09-24T20:37:44.944Z" },
{ url = "https://files.pythonhosted.org/packages/51/60/5fb1a39dbb5ae314d5f59bc7348a63c1d5c20f3cd83914c4b5cb0be31d2d/ruff-0.16.9-py3-none-win_arm64.whl", hash = "sha256:ed1a252039200f57a59eebc063b54beabea67bfbaaca0eeaa7f54b5fbcda2284", size = 10458649, upload-time = "2026-09-24T20:37:46.882Z" },
]
[[package]]
@@ -1261,27 +1261,27 @@ wheels = [
[[package]]
name = "ty"
version = "0.0.75"
version = "0.0.84"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/81/d0/d0c96f898d6974a4a3569ab3efdf9512c04ad99f9203effb55f72497fe97/ty-0.0.75.tar.gz", hash = "sha256:4c5eead33dfbf6e2ebb4f400f74b51ffc9bab702a6f23ddb648a1cbb740387e3", size = 6868326, upload-time = "2026-08-26T20:23:40.399Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e1/f6/34f8869c45ea87fe6a931ffa824b1fe4428167173543d92988d631add355/ty-0.0.84.tar.gz", hash = "sha256:0cefdb0cd5d399418dbe83c349ba605047b7dff815ae6f460c80e8522b40be67", size = 7409537, upload-time = "2026-09-24T13:16:24.367Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/6c/b12d03505f17581f0cfa3c12273fe34c1d67b36dfda1bc561a6bdc16512b/ty-0.0.75-py3-none-linux_armv6l.whl", hash = "sha256:e5409f50db2246fd4bd039d93d261e0cfa1daa554a4fb77256f91072c570349a", size = 12972606, upload-time = "2026-08-26T20:22:59.716Z" },
{ url = "https://files.pythonhosted.org/packages/d1/aa/30f11eecd9215a9f87e8fe8baaf48f3ce905f5d75b8e4aac70f0091f130c/ty-0.0.75-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5e7b8b3472fb9bb2eeab314984b265df08a7a9d518867a9e6020eebc06570be2", size = 12527158, upload-time = "2026-08-26T20:23:02.767Z" },
{ url = "https://files.pythonhosted.org/packages/f2/11/7fd7001b0b5c6610bfbad7357e47d5fe6f82d4e84e94c53776a478f5e9f8/ty-0.0.75-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c6ccf34169821fe0d23e3360deeef981d217963412f1d087b9bdd32ec57f7a57", size = 12400533, upload-time = "2026-08-26T20:23:04.965Z" },
{ url = "https://files.pythonhosted.org/packages/fd/7f/1e284ea3d348d7be02f12d83bc22ed9ef193033f863f05b64db99027f141/ty-0.0.75-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842ebb41e9c6c334b40768704e20b1a69d5c6b08805b289d5e0e2565f49f2de1", size = 12420592, upload-time = "2026-08-26T20:23:07.427Z" },
{ url = "https://files.pythonhosted.org/packages/2d/ab/d813271543370c47fd74b5118f2066ab32b0983e907b1821f3f9a6d0fa7f/ty-0.0.75-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf7a5a723c5f1e0fab4ffbfe9bd95123a526ed48f206e5f25cb2161ca294007a", size = 12739219, upload-time = "2026-08-26T20:23:09.809Z" },
{ url = "https://files.pythonhosted.org/packages/31/5b/95b49cc5570fd92a7bf63732f649b31906158721e03c7fcb1b5be74ee3bf/ty-0.0.75-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54382f98e5da292fcd7104391afef5105c35bb2f312e29bea6f5fa419935255c", size = 13494046, upload-time = "2026-08-26T20:23:12.191Z" },
{ url = "https://files.pythonhosted.org/packages/2c/0d/502d2dd68173cf020e1ad2bdbab9544c86776de0b0e2ed15f8c2fe006e3d/ty-0.0.75-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac13b180dc2aade2cd243f56b01650e78bf091a2e522ad3bc947245d7837c613", size = 13938899, upload-time = "2026-08-26T20:23:14.764Z" },
{ url = "https://files.pythonhosted.org/packages/20/5b/f3b12a25c07224456219fc2bd20db0ad7e40b304be0ff6aad728da0135f9/ty-0.0.75-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:752df7951a443219d7f1ff817e3723c85d428565ff449e08a7a93ba821661526", size = 13656711, upload-time = "2026-08-26T20:23:17.145Z" },
{ url = "https://files.pythonhosted.org/packages/51/7b/f090ad306e2b15a07b332d647138c5264b89d9758855ecce8b8a10bcb153/ty-0.0.75-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fd399feedf7cee816563c1baec45fc1c0b3c89f1ea42364920b688004b5b7da", size = 13093499, upload-time = "2026-08-26T20:23:19.489Z" },
{ url = "https://files.pythonhosted.org/packages/f1/4b/f69b99aaaca0c7c65d5f114b186b26b21666f767b0c69eec99a2bdccc061/ty-0.0.75-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:d7625f6f56c7dc1e873579fdc9e432a0e21e302afe847ab60704d2303442a92e", size = 13520580, upload-time = "2026-08-26T20:23:21.789Z" },
{ url = "https://files.pythonhosted.org/packages/b6/e7/692c5f905c0345a15d2255fc74066d660f030254ae8dcdaf33f5a5c2f279/ty-0.0.75-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:89e7d527e95a2534b70cae29e94c104b84082760ea05927d23bb87280969c104", size = 12524095, upload-time = "2026-08-26T20:23:24.026Z" },
{ url = "https://files.pythonhosted.org/packages/ba/9a/f42b12cf265ea95344bf554764c4791cfb273bdd628aadd7c209af7cadc3/ty-0.0.75-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0843f134440740706e01bee5f88f4cfc10e9b018bddb9e4ef4c12dc9fc0c9aef", size = 12756591, upload-time = "2026-08-26T20:23:26.126Z" },
{ url = "https://files.pythonhosted.org/packages/7c/5e/9b180c133cb9cce48179a7d2bf9e1802d992aa8176a918e0e05205760b42/ty-0.0.75-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1bd0ec0e50ee1376875c88891efe6f549c3560fa5b2ddad79a425cd5a6218b9c", size = 12998754, upload-time = "2026-08-26T20:23:28.353Z" },
{ url = "https://files.pythonhosted.org/packages/39/f6/3c6ef5dd550103e29905121c67fb96a374564f31a2f44c6faa1af98c2d61/ty-0.0.75-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1f9eafd561f90110d5e29f589ec3e956c4686e2f6631348d99276436f5cbe4d1", size = 13316474, upload-time = "2026-08-26T20:23:30.857Z" },
{ url = "https://files.pythonhosted.org/packages/bb/52/12776337874c821076bd5368e352ccd9e67174790abe3b856f749cb3524b/ty-0.0.75-py3-none-win32.whl", hash = "sha256:05063a6fafe2154b794a7f964515d148e51acd186d72d4a3acd347ee9fa19336", size = 12316315, upload-time = "2026-08-26T20:23:33.528Z" },
{ url = "https://files.pythonhosted.org/packages/53/e6/bb51e16af5c7138c9f52f8f3d0a401a371c6798d092e3b74926f186a9814/ty-0.0.75-py3-none-win_amd64.whl", hash = "sha256:81cf1ba5f6b7536ad56747865214255d9bc8e80533a689dbb9ddeaad464b09f1", size = 12917267, upload-time = "2026-08-26T20:23:35.978Z" },
{ url = "https://files.pythonhosted.org/packages/39/73/4542f829107468b5de4231af67f29927c093bfad11f3c1e5b2c08fb1206b/ty-0.0.75-py3-none-win_arm64.whl", hash = "sha256:541c9af5b7a0ad23d15ec315a7da81150833c359f48124ed3789ff25eacd6f42", size = 12711024, upload-time = "2026-08-26T20:23:38.159Z" },
{ url = "https://files.pythonhosted.org/packages/aa/0c/600648778e1c79133ce6b6a5c4c2531ae16b90c9b30f5041b38b574f61b8/ty-0.0.84-py3-none-linux_armv6l.whl", hash = "sha256:868438e2b9abfc835dd5b5b07ed693db95d8348ac40e3228252511d63ae87695", size = 13935333, upload-time = "2026-09-24T13:15:31.167Z" },
{ url = "https://files.pythonhosted.org/packages/c5/3b/27f06f49945c36170765fad82076898039ae3873338e9865f876dd62f12c/ty-0.0.84-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b00f39b521f0b559cde0f6abf8dd47213b513b04f33d58efeb9b98486a16bb17", size = 13511328, upload-time = "2026-09-24T13:15:34.446Z" },
{ url = "https://files.pythonhosted.org/packages/fc/b6/b12dd130e7f30141f0645614f454c925991cd389b1cc6c8284fd6bf32326/ty-0.0.84-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8f78c2915567f2ee62ce0c24d86091bc76f81577677755e242d09951db588b9a", size = 13445445, upload-time = "2026-09-24T13:15:37.476Z" },
{ url = "https://files.pythonhosted.org/packages/44/96/f012de4b3c1d9a4773326621380d768b4d48c47e620dc012775c5e01c7d7/ty-0.0.84-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61155cad0921e890d86d1d911a40b3a0e924ef4bdc3b4f3865a6c89c7e3012dc", size = 13471235, upload-time = "2026-09-24T13:15:40.64Z" },
{ url = "https://files.pythonhosted.org/packages/05/32/dca630f5f5353fa7bf67eebccf1549df99b16656d21071d0df6677c826a5/ty-0.0.84-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:417c3bf14947ed16b0b92976ab333c27915590354e96d4f581709068d3811355", size = 13680704, upload-time = "2026-09-24T13:15:43.817Z" },
{ url = "https://files.pythonhosted.org/packages/44/8d/33702c8f62f05ad45b33644fb914d483de6a0a7bc8e51884e9b8773e6d69/ty-0.0.84-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e06ef117759f654f5379efe9ae79bda8a186016c016f1023d05c34f8e15c1546", size = 14518923, upload-time = "2026-09-24T13:15:46.802Z" },
{ url = "https://files.pythonhosted.org/packages/c8/a1/da3246e6ef2ae0e842bca4058b25c54bee55ab058ffff4ee54e72517ec01/ty-0.0.84-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a05d1d53db8b64410ab38c6e32c5898510584869d1d5dd9c0605db81c9aef7df", size = 15027731, upload-time = "2026-09-24T13:15:49.755Z" },
{ url = "https://files.pythonhosted.org/packages/20/17/b0099098a560aeb4f9fde6c912f9a81622c3e44e6555e1fbe322b368ec31/ty-0.0.84-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b92400494ab855cfb1204ac1101e3f53b2d09a8e21d171758b2cf9acdab1809e", size = 14748260, upload-time = "2026-09-24T13:15:52.713Z" },
{ url = "https://files.pythonhosted.org/packages/60/d5/32cd67aedb271f006e716ad093806c96c5d7e2af86be8255469dbd3d76c8/ty-0.0.84-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af17eb391ae3027fed9be1780bea555c2b8a25ba68e184c627b4981b2c9eaab7", size = 14205858, upload-time = "2026-09-24T13:15:55.677Z" },
{ url = "https://files.pythonhosted.org/packages/43/c4/638ac62ca2e8eca1b92e3e16273085744fada728b993500819b5c258ca15/ty-0.0.84-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:44cf06af0e7ec78ea6d8ff33a3450fc19627756a4fba681f7410d4e3ef63047a", size = 14573196, upload-time = "2026-09-24T13:15:59.165Z" },
{ url = "https://files.pythonhosted.org/packages/a6/f6/9ee81c5d8921e5fd5f10889ae563c95cd3272b31df2ada528919ca1cef6b/ty-0.0.84-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c6e56b443ff9ba462e34bfbc1e582004c2719ed35f8f93a433744b0ba0afb2d9", size = 13480760, upload-time = "2026-09-24T13:16:02.313Z" },
{ url = "https://files.pythonhosted.org/packages/f6/83/fbe5d1177667ae16d84c3242846b143809c9cc09568b333e5a9b4d5908f6/ty-0.0.84-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b6562fcc48820c1030e2a4509ef2c14ef93043ca4860280074314ac3a825b95", size = 13696346, upload-time = "2026-09-24T13:16:05.391Z" },
{ url = "https://files.pythonhosted.org/packages/86/9a/1b4ac9ddc34cc0ab4624bc219825d66af52f1ad87f4778ad08ad03fa06d5/ty-0.0.84-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dee7421451efcbd70f03e95a8f2c8d9e5ec3d35edcd27b4095ee00ee062abfc4", size = 13959410, upload-time = "2026-09-24T13:16:08.661Z" },
{ url = "https://files.pythonhosted.org/packages/c9/04/70e289437a67dfd686056ab4fd91880261a8233033a6a95d29393741fb97/ty-0.0.84-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:31e96307cf621babe969307dd657783d672e2d8bdbd06493710da635bf63fa07", size = 14350294, upload-time = "2026-09-24T13:16:11.865Z" },
{ url = "https://files.pythonhosted.org/packages/9c/f4/ae7dbd118425c850981d23efb850f0d9d7f6b8d2b852bde2767434f668b4/ty-0.0.84-py3-none-win32.whl", hash = "sha256:4bdc85f91cbaae35825f2b17bb4ac5de0563367875cb0f42b2bf07a1bf7ff2ba", size = 13176439, upload-time = "2026-09-24T13:16:15.049Z" },
{ url = "https://files.pythonhosted.org/packages/29/ec/994d87252f065dda5a500bc8afc726d18f6582d81d6f4ff1feb8a267c800/ty-0.0.84-py3-none-win_amd64.whl", hash = "sha256:71cc9aa7a7c89d4e12c6a814e9c0c3310ad5bee44efedbd6f5a42d91e9ac0f0d", size = 13962879, upload-time = "2026-09-24T13:16:18.191Z" },
{ url = "https://files.pythonhosted.org/packages/6d/1c/e6e91852b72566b1ab9aca504712857dfb89324c12092a5bd61d42d34427/ty-0.0.84-py3-none-win_arm64.whl", hash = "sha256:6c9d3718c4a0d318bc9c92af9b2aa85c3294e7dff54cf1d69ad79568f56516da", size = 13656453, upload-time = "2026-09-24T13:16:21.51Z" },
]
[[package]]
@@ -1338,11 +1338,11 @@ wheels = [
[[package]]
name = "urllib3"
version = "2.7.0"
version = "2.8.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
{ url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" },
]
[[package]]
+2
View File
@@ -103,6 +103,8 @@ The CLI uses a `langgraph.json` configuration file with these key settings:
}
```
Git dependencies should use credential-free URLs. The CLI conservatively scans direct `langgraph.json` dependencies, common Python package files, uv project and lock files, and common Node.js package and lock files for HTTP Git URLs with userinfo. This check is not exhaustive: generated Docker builds can copy other files, including nested requirement or constraint files, into image layers without scanning them. For private dependencies, provide short-lived credentials through your build environment's secret-backed Git credential helper. Do not store credentials in copied files such as `langgraph.json` or `pip_config_file`.
See the [full documentation](https://reference.langchain.com/python/langgraph-cli) for detailed configuration options.
## Development
@@ -9,8 +9,8 @@
},
"dependencies": {
"@js-monorepo-example/shared": "*",
"@langchain/core": "^1.2.9",
"@langchain/langgraph": "^1.4.13"
"@langchain/core": "^1.2.13",
"@langchain/langgraph": "^1.4.18"
},
"devDependencies": {
"typescript": "^7.0.2"
+6 -6
View File
@@ -17,18 +17,18 @@
"lint": "eslint 'apps/**/*.ts' 'libs/**/*.ts'"
},
"devDependencies": {
"turbo": "^2.10.12",
"turbo": "^2.11.5",
"typescript": "^7.0.2",
"@tsconfig/recommended": "^1.0.13",
"@eslint/eslintrc": "^3.3.6",
"@eslint/eslintrc": "^3.3.7",
"@eslint/js": "^10.0.1",
"eslint": "^10.9.1",
"eslint": "^10.11.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-no-instanceof": "^1.0.1",
"eslint-plugin-prettier": "^5.5.6",
"@typescript-eslint/eslint-plugin": "^8.68.0",
"@typescript-eslint/parser": "^8.68.0",
"prettier": "^3.9.6"
"@typescript-eslint/eslint-plugin": "^8.70.1",
"@typescript-eslint/parser": "^8.70.1",
"prettier": "^3.9.9"
}
}
+226 -169
View File
@@ -2,6 +2,24 @@
# yarn lockfile v1
"@cacheable/memory@^2.2.0":
version "2.2.0"
resolved "https://registry.yarnpkg.com/@cacheable/memory/-/memory-2.2.0.tgz#72aeb8b051f6d597d10ac8595b94ad8302bd2239"
integrity sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==
dependencies:
"@cacheable/utils" "^2.5.0"
"@keyv/bigmap" "^1.3.1"
hookified "^1.15.1"
keyv "^5.6.0"
"@cacheable/utils@^2.5.0":
version "2.5.0"
resolved "https://registry.yarnpkg.com/@cacheable/utils/-/utils-2.5.0.tgz#534c91113aa48fe43baedb169550b6ee070ef303"
integrity sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==
dependencies:
hashery "^1.5.1"
keyv "^5.6.0"
"@cfworker/json-schema@^4.0.2":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@cfworker/json-schema/-/json-schema-4.1.1.tgz#4a2a3947ee9fa7b7c24be981422831b8674c3be6"
@@ -42,10 +60,10 @@
dependencies:
"@types/json-schema" "^7.0.15"
"@eslint/eslintrc@^3.3.6":
version "3.3.6"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.6.tgz#d22bfd6b3a7d8e1f2c0b2f2e6de111b53ec6e13e"
integrity sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==
"@eslint/eslintrc@^3.3.7":
version "3.3.7"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.7.tgz#76d3dedec4a30ea32df797bf8a0085c1311b7316"
integrity sha512-F42g89Qd5oAWtp0k0nnSrjziAKza7w8SVT4mStc18LZMaRb4J1HQAHLCalEtDCxrTuksx7NU9qsmeLwpOfPqWw==
dependencies:
ajv "^6.14.0"
debug "^4.3.2"
@@ -53,7 +71,7 @@
globals "^14.0.0"
ignore "^5.2.0"
import-fresh "^3.2.1"
js-yaml "^4.3.0"
js-yaml "^4.3.2"
minimatch "^3.1.5"
strip-json-comments "^3.1.1"
@@ -67,10 +85,10 @@
resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-3.0.5.tgz#88e9bf4d11d2b19c082e78ebe7ce88724a5eb091"
integrity sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==
"@eslint/plugin-kit@^0.7.2":
version "0.7.2"
resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz#4b0962f3f2c7ce8bc98b3ecfe34525c09d2cb729"
integrity sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==
"@eslint/plugin-kit@^0.7.3":
version "0.7.3"
resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz#cc7268cc36405b331ef92db1bc37971f21d66fe1"
integrity sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==
dependencies:
"@eslint/core" "^1.2.1"
levn "^0.4.1"
@@ -103,10 +121,23 @@
resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-9.0.0.tgz#4d0a3f127058043bf2e7ee169eaf30ed901302f3"
integrity sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==
"@langchain/core@^1.2.9":
version "1.2.9"
resolved "https://registry.yarnpkg.com/@langchain/core/-/core-1.2.9.tgz#4f5fb27ba07c51ce4fb8e1dc32eb36945737afa1"
integrity sha512-conzSEj9Zu1AyXJLXsSbgrtxtxinmI1yGqQ5CIJZSoV5rvv+yvQE/vgBnoySpBQ/bl3YPgj2FL/gbDjWykLSfg==
"@keyv/bigmap@^1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@keyv/bigmap/-/bigmap-1.3.1.tgz#fc82fa83947e7ff68c6798d08907db842771ef2c"
integrity sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==
dependencies:
hashery "^1.4.0"
hookified "^1.15.0"
"@keyv/serialize@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@keyv/serialize/-/serialize-1.1.1.tgz#0c01dd3a3483882af7cf3878d4e71d505c81fc4a"
integrity sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==
"@langchain/core@^1.2.13":
version "1.2.13"
resolved "https://registry.yarnpkg.com/@langchain/core/-/core-1.2.13.tgz#4ea4eb0308a25af350f75de2fbf34aecb819177e"
integrity sha512-ADGTxZ84n3civruUX1LlTOdua/PDGoni2U6TmKTX7hvRU2Jlepu8vLJI4Wnwj45KUKhUCrW94Il12Q2bxE3e8A==
dependencies:
"@cfworker/json-schema" "^4.0.2"
"@standard-schema/spec" "^1.1.0"
@@ -121,31 +152,26 @@
resolved "https://registry.yarnpkg.com/@langchain/langgraph-checkpoint/-/langgraph-checkpoint-1.1.5.tgz#c793177f9afcce31a1e9922f317f88fec1254282"
integrity sha512-BwDwl5VeTOh6CVuiIPgsUgfK51vTJDMSbFcSCUfjJWsl8/DPdK/mbv+ejxJstkSk/BlSPMP4JfXWcN6jD2ea2Q==
"@langchain/langgraph-sdk@~1.10.0":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@langchain/langgraph-sdk/-/langgraph-sdk-1.10.0.tgz#6ec1364a97caf615983161ae1f00b196897b9cd6"
integrity sha512-cPPkh+hMNgeOaGtJRrqs1AjZde45cG2+Ma9Sc10wz2RyvT8SKToCKS+VvkS18SsLajnmq6/FKVmthq6rnUVYOw==
"@langchain/langgraph-sdk@~1.12.0":
version "1.12.0"
resolved "https://registry.yarnpkg.com/@langchain/langgraph-sdk/-/langgraph-sdk-1.12.0.tgz#b063a7eba0a66f51cbc841a824626a47eca1eec9"
integrity sha512-F3AOZjKZRUGmE3FzY+RaVZI6WzXOkwnuF7jqgto6rDPSnO9OdVdYGvwGDi3jjRGf5xLoDtX2dpsR9z5KptU+5A==
dependencies:
"@langchain/protocol" "^0.0.19"
"@types/json-schema" "^7.0.15"
p-queue "^9.0.1"
p-retry "^7.1.1"
"@langchain/langgraph@^1.4.13":
version "1.4.13"
resolved "https://registry.yarnpkg.com/@langchain/langgraph/-/langgraph-1.4.13.tgz#168ab4f05c212fd5ab4b2816bcad2e963b345101"
integrity sha512-LO1ak6jNQ9jR13tm7Ay4Yh2/otrH7LNVUwWTAI7WJigVdW5Fb6LuYSZUzVn4S7sVSiyVFfnrUcDTd8c7eAzPrQ==
"@langchain/langgraph@^1.4.18":
version "1.4.18"
resolved "https://registry.yarnpkg.com/@langchain/langgraph/-/langgraph-1.4.18.tgz#c8cc4ea734834262fdb00ae6a45a0849620e4fd2"
integrity sha512-yrMMJ9hk2NVMD2xU2WoVrgFawAU6s/RzEl/dX9BhlyxZHazo1wHY35z4K2BIBzTUh4z3giCzrUoqRAqW2CWpWg==
dependencies:
"@langchain/langgraph-checkpoint" "^1.1.5"
"@langchain/langgraph-sdk" "~1.10.0"
"@langchain/protocol" "^0.0.18"
"@langchain/langgraph-sdk" "~1.12.0"
"@langchain/protocol" "^0.0.19"
"@standard-schema/spec" "1.1.0"
"@langchain/protocol@^0.0.18":
version "0.0.18"
resolved "https://registry.yarnpkg.com/@langchain/protocol/-/protocol-0.0.18.tgz#6d96155e7263c958fbce6d4b7241b4725b72fbad"
integrity sha512-XW1egQtPfsGI41w2AMZNFZrUIwFSQHTjVMZs0OaTpCAvht/QLoaPN8FQcsysMVypOhupG28J29yOorrc70otBQ==
"@langchain/protocol@^0.0.19":
version "0.0.19"
resolved "https://registry.yarnpkg.com/@langchain/protocol/-/protocol-0.0.19.tgz#7fe43fed115dc34b3b4c246e8d5283fbcbfab7b0"
@@ -171,35 +197,35 @@
resolved "https://registry.yarnpkg.com/@tsconfig/recommended/-/recommended-1.0.13.tgz#269fce3ad04ca70b93269ff44cca81b950f542da"
integrity sha512-sySRuBfMKyKO/j2ZAhR8kSembhjuPEV4Ra3AHtmWLq51+iGaudr45crPSzNC5b7/Ctrh9dfUpBuTlYrH6rM58Q==
"@turbo/darwin-64@2.10.12":
version "2.10.12"
resolved "https://registry.yarnpkg.com/@turbo/darwin-64/-/darwin-64-2.10.12.tgz#719ac12ae47caf7b4be855d672582cdbfde177ea"
integrity sha512-9nKgKoF6ZOUsM+or0OtNf+TTJSfGvDNP7ZFv/ZGWVwOSCkumyctQiTeHwB4UNljHTnC41AqylgbunLDHoccNrA==
"@turbo/darwin-64@2.11.5":
version "2.11.5"
resolved "https://registry.yarnpkg.com/@turbo/darwin-64/-/darwin-64-2.11.5.tgz#6ddc580c2b7d05e578ca1c06b3f61473f4b7b00e"
integrity sha512-KdY4y7BBjIisl+jAkb3FFaRjClGqHyaeHCcVcCT8LBzFFwUu6thgfxyRZAx0uL4KoxLmH+iOan8UhVf/aDDcaA==
"@turbo/darwin-arm64@2.10.12":
version "2.10.12"
resolved "https://registry.yarnpkg.com/@turbo/darwin-arm64/-/darwin-arm64-2.10.12.tgz#ac2d3dde3a2407f8359ca2e3152690280cff2714"
integrity sha512-H4Elb1jqTZVeIC9bbcNwjSzemZ6RegoTOVHeuV5Osirt2Z8UguTyisMEkvZjPVZgMeN9J4ERZBFad40tFnkb7w==
"@turbo/darwin-arm64@2.11.5":
version "2.11.5"
resolved "https://registry.yarnpkg.com/@turbo/darwin-arm64/-/darwin-arm64-2.11.5.tgz#a756c67bb828cd00d03e909769dd39453c1f1e69"
integrity sha512-ToZDGi2u410+TfRtC/O1/LpujGgvNJoRBZnwVXob7oO0+3OSlwIO3zofXKUvwQvlba7a8ZXPyCZwufjAXd7f0w==
"@turbo/linux-64@2.10.12":
version "2.10.12"
resolved "https://registry.yarnpkg.com/@turbo/linux-64/-/linux-64-2.10.12.tgz#264a0ec88a1f69f93cf57dab20be1b4c50bf226c"
integrity sha512-lr7KIotukvjZwEXiFSYAeOH3BWzjFVBbSzTbv0fuGFsNukYyH0+g1hB5ecqnJkgkYU+KHEMG1edOhnjiKON1wQ==
"@turbo/linux-64@2.11.5":
version "2.11.5"
resolved "https://registry.yarnpkg.com/@turbo/linux-64/-/linux-64-2.11.5.tgz#b95c05218aebb06c06e5f991d48c55b78dc5e005"
integrity sha512-Ub2d/nAbdWLaSytcEaPp1wm/YuIvHEIqNrCRMI/UgOGyFdOhgxm8VyWPAJilQWRYxYVrqEUoy2K5S5K8SG50rA==
"@turbo/linux-arm64@2.10.12":
version "2.10.12"
resolved "https://registry.yarnpkg.com/@turbo/linux-arm64/-/linux-arm64-2.10.12.tgz#3ee53d1f930d2bb65708e904971be0e765381e37"
integrity sha512-f0pZDTtvzB5SuNwuXBaKbZHUCMCukgc8nMlHEuvLmj91Fzec+MEbr3cAvGNor5htEDqZnO6Lxt9N/GPI/77oGA==
"@turbo/linux-arm64@2.11.5":
version "2.11.5"
resolved "https://registry.yarnpkg.com/@turbo/linux-arm64/-/linux-arm64-2.11.5.tgz#c7a1d1a44c8c8dcff4b72fbafe9a5059c8fb668a"
integrity sha512-JQjmGxp724Wuft9FAxPMtmBur1CEdUyxJ+FVoIvKkgj63rXHl9PYCWrsU2tMjVi609XTQ3M8vZD9Yc9qVAVYrw==
"@turbo/windows-64@2.10.12":
version "2.10.12"
resolved "https://registry.yarnpkg.com/@turbo/windows-64/-/windows-64-2.10.12.tgz#ac0a0b7794f9a541e68e930383f48747f7e648ab"
integrity sha512-SDOueJRjS/QcykWf2KCRtTLmIl5YMKsLbXkXQGhDwcTXvKXZiS5ih5lBl/gkwZIpYFjqA/rAlfMzlAFcVHNe0g==
"@turbo/windows-64@2.11.5":
version "2.11.5"
resolved "https://registry.yarnpkg.com/@turbo/windows-64/-/windows-64-2.11.5.tgz#60bdaaa7e8ba32f32623b31a1c75f6c3db400a0c"
integrity sha512-AFkbPmXNd8XgCi/66YEHR2bVl3gtusXyDihTIVEPAuSB+7ulLmJePvz1unWPVKLHdbCTTIdKq2mpJ1B1e3lJXw==
"@turbo/windows-arm64@2.10.12":
version "2.10.12"
resolved "https://registry.yarnpkg.com/@turbo/windows-arm64/-/windows-arm64-2.10.12.tgz#50eb6c20a20d0aab216d2b6aa13cc3100ea44106"
integrity sha512-0i0mVUa4kKk+/B3RwEwPMf9CB+T7ul56hn5FFHNA4VUNTOoLBEd6aNf3FaKfCatDNZ6cicCEf6if9QUTVyzzcA==
"@turbo/windows-arm64@2.11.5":
version "2.11.5"
resolved "https://registry.yarnpkg.com/@turbo/windows-arm64/-/windows-arm64-2.11.5.tgz#18bd5a0ad30c4e094995786bd78916b6de6b5c1c"
integrity sha512-52ziXYP3snGOxjv19xA3WL1WDKv9Q6uDAa/7EKIR5j4hocMlYURkrOHbJ2ZZI+VfPU5MwKpcGeRfHxHJu7Y/Pw==
"@types/esrecurse@^4.3.1":
version "4.3.1"
@@ -221,110 +247,110 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
"@typescript-eslint/eslint-plugin@^8.68.0":
version "8.68.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.68.0.tgz#a8fbdb1cf49aafaf16071b646daad890151bd149"
integrity sha512-WASHDpCm6qO5jj9g1a+8NiW5+GCkAyLReR56/4VruYmNgfUmqpxOfZ2Yfb8xGfJPWv5Qi6LSD8sXdces3vbp/Q==
"@typescript-eslint/eslint-plugin@^8.70.1":
version "8.70.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.70.1.tgz#d404bac4cb04e4dcd20086e46e13c952bd0771e0"
integrity sha512-nDNrUQ/4ruSNYbu749TRY7cfrzPtoLHEXSNBI8aaNY32LlZCajixqRf3FqcKC4p5Cam4VOHYx/t+i5+nKXvrqA==
dependencies:
"@eslint-community/regexpp" "^4.12.2"
"@typescript-eslint/scope-manager" "8.68.0"
"@typescript-eslint/type-utils" "8.68.0"
"@typescript-eslint/utils" "8.68.0"
"@typescript-eslint/visitor-keys" "8.68.0"
"@typescript-eslint/scope-manager" "8.70.1"
"@typescript-eslint/type-utils" "8.70.1"
"@typescript-eslint/utils" "8.70.1"
"@typescript-eslint/visitor-keys" "8.70.1"
ignore "^7.0.5"
natural-compare "^1.4.0"
ts-api-utils "^2.5.0"
"@typescript-eslint/parser@^8.68.0":
version "8.68.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.68.0.tgz#61de31481354c50457bc9621a7ed746779f09ee7"
integrity sha512-fHq2VC1kpyYfvEcbiMjOpySY4WS7voEp89yAThrHRX5sm9j2lzYppCb2umFMEed4fWcyeLjHxrz0mpjNBaBxMQ==
"@typescript-eslint/parser@^8.70.1":
version "8.70.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.70.1.tgz#6c99b7b954efc05dae179001c8b477d1a8948dcf"
integrity sha512-nO974WLllwhSFWQXnMLj6nDGa8f0khKEz1JzpPJ1u7Vm/4X1X6ZHajpoknU4bb41vJyMB0HHVyS2GqdhWfIXZw==
dependencies:
"@typescript-eslint/scope-manager" "8.68.0"
"@typescript-eslint/types" "8.68.0"
"@typescript-eslint/typescript-estree" "8.68.0"
"@typescript-eslint/visitor-keys" "8.68.0"
"@typescript-eslint/scope-manager" "8.70.1"
"@typescript-eslint/types" "8.70.1"
"@typescript-eslint/typescript-estree" "8.70.1"
"@typescript-eslint/visitor-keys" "8.70.1"
debug "^4.4.3"
"@typescript-eslint/project-service@8.68.0":
version "8.68.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.68.0.tgz#ea4b2869f59165c420cd7a4bbebc38039794e8cc"
integrity sha512-5GQtWZCXFcFYux955pvoS02WLc49pXNlvIxocKjS0clvwo3in1RdlzVKyiqQH9vE5AKWFLTaUgeQkOrTS+0Qxw==
"@typescript-eslint/project-service@8.70.1":
version "8.70.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.70.1.tgz#d5635594cc8a573f0e15a772b1704e93a00134c1"
integrity sha512-62xOgboPfwc3/IgPSX/W6oQR3ZbF04194FPGUGH8HL8iLFHbt/456/8Ph1wLNUgVF+s94FlHoipBsz+v7+LMnA==
dependencies:
"@typescript-eslint/tsconfig-utils" "^8.68.0"
"@typescript-eslint/types" "^8.68.0"
"@typescript-eslint/tsconfig-utils" "^8.70.1"
"@typescript-eslint/types" "^8.70.1"
debug "^4.4.3"
"@typescript-eslint/scope-manager@8.68.0":
version "8.68.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.68.0.tgz#e5a13a1159497faeab4e48279bf07576045b1499"
integrity sha512-T5eXpcaJNg8bhjHJ8Rjp68Vq/QBteYtTKY8TZqVNPaUbuz0f6jI9t6aDkylwvalpAB9XTTFeFOjrjXAZ3YvmVA==
"@typescript-eslint/scope-manager@8.70.1":
version "8.70.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.70.1.tgz#0feeae4da2d279b960cdbfe5e0a02fbf1195e93f"
integrity sha512-Pa0EeSeAusQc1WbjQMac+YfenewYTBu0KjgYvkUKwhXaHUKbFog23Dm/rp0DX/6tyYOQ3Xl1a+3EcFNZynGHCw==
dependencies:
"@typescript-eslint/types" "8.68.0"
"@typescript-eslint/visitor-keys" "8.68.0"
"@typescript-eslint/types" "8.70.1"
"@typescript-eslint/visitor-keys" "8.70.1"
"@typescript-eslint/tsconfig-utils@8.68.0":
version "8.68.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.68.0.tgz#594d7a3c5952055b3c431fc563ca7fd1defcce18"
integrity sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==
"@typescript-eslint/tsconfig-utils@8.70.1":
version "8.70.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.70.1.tgz#e9353a6e5f3498a29b40946ca3e11f6166fef09e"
integrity sha512-jumze1fPI+sDOaM2TWGQdn39PDxTr7TZGeuyLkAbNyx2vtMT3uRnVKChN0hfht5V2TugphJzF6bYXvBcE09qqg==
"@typescript-eslint/tsconfig-utils@^8.68.0":
version "8.69.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.69.0.tgz#d3b0ccc781ab252a90a0b3989b9d1eb85ab59469"
integrity sha512-xNqK7YTDZsLniQMV/4rpFR8Z5JlqeRvVjuG1YgF/mdPVH84HSD19L8CczMA0qg2RfwEV231GHH3VnToJDo4MfQ==
"@typescript-eslint/tsconfig-utils@^8.70.1":
version "8.71.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.0.tgz#83a69c9a514af8f5ff099cc6c0d609c273e8f039"
integrity sha512-Z1UlWHADEK2Mlb9NpWfDeSjqoZ5EyrOv4R3eQpbkzqn/EwaIdOpXXupEA1+0ZIOSJSZZDBHG0BrQyN8zUG6Pwg==
"@typescript-eslint/type-utils@8.68.0":
version "8.68.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.68.0.tgz#8f3e838dbd740909db27053857468cd037b00220"
integrity sha512-X77zqoY1EjeWGs/0JNxeaMfp5C5lIz4Tw8y66F1Ne8Faq6g424sBNYM6xBAqElfGZPLpWS+CZAp0DXyKDzWiHg==
"@typescript-eslint/type-utils@8.70.1":
version "8.70.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.70.1.tgz#6ea36f2c7dc0776c1c8e1c380b4896f00bc4c27f"
integrity sha512-7zKTnyvaVWqzLZHPFQtX1hVHqgkMC+WebPWakNCSyrQVbIP1AM0L0TlBZtACldIRb6PptI8Odk+jyZ5kP3B1VA==
dependencies:
"@typescript-eslint/types" "8.68.0"
"@typescript-eslint/typescript-estree" "8.68.0"
"@typescript-eslint/utils" "8.68.0"
"@typescript-eslint/types" "8.70.1"
"@typescript-eslint/typescript-estree" "8.70.1"
"@typescript-eslint/utils" "8.70.1"
debug "^4.4.3"
ts-api-utils "^2.5.0"
"@typescript-eslint/types@8.68.0":
version "8.68.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.68.0.tgz#3f9d4e62fbe5728f09403cdc7b4d58af842ac1af"
integrity sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==
"@typescript-eslint/types@8.70.1":
version "8.70.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.70.1.tgz#2022b9d07d057174eba25b9bbd289641d262a196"
integrity sha512-Dm1ypdhhrGCTyyehxElhgJ6kgk8MVCv5qXdoOVqPr1uqk42jX8KjrZqhROvdShczA8qrDoYiOWn1ykWlx2k81Q==
"@typescript-eslint/types@^8.68.0":
version "8.69.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.69.0.tgz#5d9ad3f707c2e4f70a2db540031104df3e63bcf5"
integrity sha512-K3VrubUPhlo9VDBS6QdI8YB5j7ClpqLRdefcz6PFrhnwicehBweqQ9Evhl4l+FYz0HdDmMqIiSX0aldGRYtDCA==
"@typescript-eslint/types@^8.70.1":
version "8.71.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.71.0.tgz#a230a121e71665060afe27d1f1ad110371f9451e"
integrity sha512-cJ4OoxPGWvFnBTnSZyaU+qJzGTqPTGJY+gDchj6cRyLRdmIdt4rcsE4twj+zPfrNiWuVi38wijHzShL++Z9atQ==
"@typescript-eslint/typescript-estree@8.68.0":
version "8.68.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.68.0.tgz#bf4165029825138ac27231a3ff02923ecd977f38"
integrity sha512-OKKsD0tYmoNiU5PW2zehO1yO56jYOm1ShYlxon/Z0SJNidAkdVg86eg9ruRuoXf8xfnuWZGbwDsStkoXbZtIIA==
"@typescript-eslint/typescript-estree@8.70.1":
version "8.70.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.70.1.tgz#ced48fee6f7043835d2edfed9786ae74813a3c99"
integrity sha512-TU8PwyGN0PQJUcE96mw8eCQ44SmxGdQlJmlWakHaHQ15eIuuvye5yNtmh/i6oS88jzXVQB71xdNkbkB/fMwL0g==
dependencies:
"@typescript-eslint/project-service" "8.68.0"
"@typescript-eslint/tsconfig-utils" "8.68.0"
"@typescript-eslint/types" "8.68.0"
"@typescript-eslint/visitor-keys" "8.68.0"
"@typescript-eslint/project-service" "8.70.1"
"@typescript-eslint/tsconfig-utils" "8.70.1"
"@typescript-eslint/types" "8.70.1"
"@typescript-eslint/visitor-keys" "8.70.1"
debug "^4.4.3"
minimatch "^10.2.2"
semver "^7.7.3"
tinyglobby "^0.2.15"
ts-api-utils "^2.5.0"
"@typescript-eslint/utils@8.68.0":
version "8.68.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.68.0.tgz#00547f2c8de8aca2a3c21752a9711f73206fd36d"
integrity sha512-PB5gJMMOg0Q5P1tsgWtEAqQacJXq0qEqRHDX/YJ4FaTMLfZPpHB3gjl2EJuiZyPABxmj4ZQYiY9m1bdAJ5y7tQ==
"@typescript-eslint/utils@8.70.1":
version "8.70.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.70.1.tgz#6a97887cee702df513692f5cdc7f79baeef48e02"
integrity sha512-Esgul8MsnKnRLdYU2Eb2cRV9bS5HJYtKj1ByJnOzzG2M58DGdSUQ1jUuILxipqcpB2h9WLrbD5GijIWUjX/Tqw==
dependencies:
"@eslint-community/eslint-utils" "^4.9.1"
"@typescript-eslint/scope-manager" "8.68.0"
"@typescript-eslint/types" "8.68.0"
"@typescript-eslint/typescript-estree" "8.68.0"
"@typescript-eslint/scope-manager" "8.70.1"
"@typescript-eslint/types" "8.70.1"
"@typescript-eslint/typescript-estree" "8.70.1"
"@typescript-eslint/visitor-keys@8.68.0":
version "8.68.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.68.0.tgz#78db3c9bb258a0309d9e2b1b617127c3a8fb1f54"
integrity sha512-YR65gGdGvTUAWLldC3xLOvOzamdGzB4A5/N8rehEaHs3Zvoe39BhgY+u0SPch1OvrVTfLcc55wsSgK2NcnTS/A==
"@typescript-eslint/visitor-keys@8.70.1":
version "8.70.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.70.1.tgz#b4cde0ed16982bd963a6310fcae554f59fd14124"
integrity sha512-Vwj9lUIW5Xq3wQ9w6gv3R86g1hMK8f2zNOdGTAgeXUMMXFK78G9ruCjjqutHMNJc0+CH7LYRnHeUB9IT8wFmcw==
dependencies:
"@typescript-eslint/types" "8.68.0"
"@typescript-eslint/types" "8.70.1"
eslint-visitor-keys "^5.0.0"
"@typescript/typescript-aix-ppc64@7.0.2":
@@ -569,6 +595,17 @@ brace-expansion@^5.0.8:
dependencies:
balanced-match "^4.0.2"
cacheable@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/cacheable/-/cacheable-2.5.0.tgz#d142d41043e5a865f6053cc70ef4e3ad068bd5ce"
integrity sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==
dependencies:
"@cacheable/memory" "^2.2.0"
"@cacheable/utils" "^2.5.0"
hookified "^1.15.0"
keyv "^5.6.0"
qified "^0.10.1"
call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6"
@@ -886,17 +923,17 @@ eslint-visitor-keys@^5.0.0, eslint-visitor-keys@^5.0.1:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz#9e3c9489697824d2d4ce3a8ad12628f91e9f59be"
integrity sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==
eslint@^10.9.1:
version "10.9.1"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-10.9.1.tgz#409da5c41a5536d5a849f8555a18ca7ef1eb963b"
integrity sha512-9VaAkDURekixUQJy0oJYl2DcN6oKMfxay7XzaGYAWQwsb6qfKf+x76R2k1L8kb1boc+FyCAaTA9GmiKaaiaF+A==
eslint@^10.11.0:
version "10.11.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-10.11.0.tgz#304d1591b7c6a327e3f64b4f550f99fda160ae20"
integrity sha512-P7a6UEEqb9G95MYAtqkmsTbVXIYyzIfl6NGOIJk162PaahFxFyeGcrlXYFSiagECg4sEm8IseJdZBKR3rx6MsQ==
dependencies:
"@eslint-community/eslint-utils" "^4.8.0"
"@eslint-community/regexpp" "^4.12.2"
"@eslint/config-array" "^0.23.5"
"@eslint/config-helpers" "^0.7.0"
"@eslint/core" "^1.2.1"
"@eslint/plugin-kit" "^0.7.2"
"@eslint/plugin-kit" "^0.7.3"
"@humanfs/node" "^0.16.6"
"@humanwhocodes/module-importer" "^1.0.1"
"@humanwhocodes/retry" "^0.4.2"
@@ -911,7 +948,7 @@ eslint@^10.9.1:
esquery "^1.7.0"
esutils "^2.0.2"
fast-deep-equal "^3.1.3"
file-entry-cache "^8.0.0"
file-entry-cache "11.1.5 || >11.1.6 <12"
find-up "^5.0.0"
glob-parent "^6.0.2"
ignore "^5.2.0"
@@ -999,12 +1036,12 @@ fdir@^6.5.0:
resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350"
integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==
file-entry-cache@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f"
integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==
"file-entry-cache@11.1.5 || >11.1.6 <12":
version "11.1.5"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-11.1.5.tgz#c8210eb055de63e68685ccfb6a017e386d4577d0"
integrity sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==
dependencies:
flat-cache "^4.0.0"
flat-cache "^6.1.23"
find-up@^5.0.0:
version "5.0.0"
@@ -1014,18 +1051,19 @@ find-up@^5.0.0:
locate-path "^6.0.0"
path-exists "^4.0.0"
flat-cache@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c"
integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==
flat-cache@^6.1.23:
version "6.1.23"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-6.1.23.tgz#735dc888c271868d7301b3bbb8edba5028afb61d"
integrity sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==
dependencies:
flatted "^3.2.9"
keyv "^4.5.4"
cacheable "^2.5.0"
flatted "^3.4.2"
hookified "^1.15.0"
flatted@^3.2.9:
version "3.4.2"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.4.2.tgz#f5c23c107f0f37de8dbdf24f13722b3b98d52726"
integrity sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==
flatted@^3.4.2:
version "3.4.4"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.4.4.tgz#aeeca2a506303f0cee61c59e6c9f2a88d2f29fc6"
integrity sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==
for-each@^0.3.3, for-each@^0.3.5:
version "0.3.5"
@@ -1145,6 +1183,13 @@ has-tostringtag@^1.0.2:
dependencies:
has-symbols "^1.0.3"
hashery@^1.4.0, hashery@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/hashery/-/hashery-1.5.1.tgz#4ba82ad54911ac617467870845d57a9fe508a400"
integrity sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==
dependencies:
hookified "^1.15.0"
hasown@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
@@ -1152,6 +1197,16 @@ hasown@^2.0.2:
dependencies:
function-bind "^1.1.2"
hookified@^1.15.0, hookified@^1.15.1:
version "1.15.1"
resolved "https://registry.yarnpkg.com/hookified/-/hookified-1.15.1.tgz#b1fafeaa5489cdc29cb85546a8f837ed4ffbbcb6"
integrity sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==
hookified@^2.1.1:
version "2.2.0"
resolved "https://registry.yarnpkg.com/hookified/-/hookified-2.2.0.tgz#1d024ac1668973dd5bcc4a96ab9ccdb7639ef8d4"
integrity sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==
ignore@^5.2.0:
version "5.3.2"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
@@ -1390,18 +1445,13 @@ js-tiktoken@^1.0.12:
dependencies:
base64-js "^1.5.1"
js-yaml@^4.3.0:
js-yaml@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.3.2.tgz#8e44fb14a2643c59726bb15787b5f1512cb3d3fb"
integrity sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==
dependencies:
argparse "^2.0.1"
json-buffer@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
@@ -1419,12 +1469,12 @@ json5@^1.0.2:
dependencies:
minimist "^1.2.0"
keyv@^4.5.4:
version "4.5.4"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
keyv@^5.6.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-5.6.0.tgz#03044074c6b4d072d0a62c7b9fa649537baf0105"
integrity sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==
dependencies:
json-buffer "3.0.1"
"@keyv/serialize" "^1.1.1"
"langsmith@>=0.5.0 <1.0.0":
version "0.7.1"
@@ -1657,16 +1707,23 @@ prettier-linter-helpers@^1.0.1:
dependencies:
fast-diff "^1.1.2"
prettier@^3.9.6:
version "3.9.6"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.9.6.tgz#b3ea5146515d40fc53f18aa63f74dfab1e10dbf6"
integrity sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==
prettier@^3.9.9:
version "3.9.9"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.9.9.tgz#09b826918c91cd4cbc80e0cbd1d2a922ff04f233"
integrity sha512-Z/CJHIkdujO/OtN7nXUii0Rf3VT5SRuhjBA82Xvu2XhBUgX3nhP67T0LHceBdQLex7OOFGTox+Q5Yg8Jk2Qivg==
punycode@^2.1.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
qified@^0.10.1:
version "0.10.1"
resolved "https://registry.yarnpkg.com/qified/-/qified-0.10.1.tgz#0640bf21bbe6ca540db290ad8f5fde4d870b8bda"
integrity sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==
dependencies:
hookified "^2.1.1"
reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9:
version "1.0.10"
resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9"
@@ -1913,17 +1970,17 @@ tsconfig-paths@^3.15.0:
minimist "^1.2.6"
strip-bom "^3.0.0"
turbo@^2.10.12:
version "2.10.12"
resolved "https://registry.yarnpkg.com/turbo/-/turbo-2.10.12.tgz#22f552bd88182d58365960a02e5f45e628fb965b"
integrity sha512-AswgMPnpOoaVZHrrSBejETzEbuIA69OVGwfkHwfrY0A23VjWXBANzgq9+OymWOHAIArB7D1+1z498WY8fGg1Jw==
turbo@^2.11.5:
version "2.11.5"
resolved "https://registry.yarnpkg.com/turbo/-/turbo-2.11.5.tgz#e7223abd0555b978d3efe1b00ea9a98f43afb7ab"
integrity sha512-qLXheqz3TUvJpHIV6MUBwkNkvwKxMVG/QsimyiKT9DfNWPHJ294G/i5nDaH+fbHJt3UH7orubNNxAqYkbUNGAQ==
optionalDependencies:
"@turbo/darwin-64" "2.10.12"
"@turbo/darwin-arm64" "2.10.12"
"@turbo/linux-64" "2.10.12"
"@turbo/linux-arm64" "2.10.12"
"@turbo/windows-64" "2.10.12"
"@turbo/windows-arm64" "2.10.12"
"@turbo/darwin-64" "2.11.5"
"@turbo/darwin-arm64" "2.11.5"
"@turbo/linux-64" "2.11.5"
"@turbo/linux-arm64" "2.11.5"
"@turbo/windows-64" "2.11.5"
"@turbo/windows-arm64" "2.11.5"
type-check@^0.4.0, type-check@~0.4.0:
version "0.4.0"
+87 -3
View File
@@ -6,6 +6,7 @@ import re
import shlex
import textwrap
from collections import Counter
from collections.abc import Iterable
from typing import Literal, NamedTuple
import click
@@ -36,6 +37,10 @@ DISALLOWED_BUILD_COMMAND_CHARS = [
# This blocks background execution (cmd &) while allowing command
# chaining (cmd1 && cmd2) which is common in build commands.
_SINGLE_AMPERSAND_RE = re.compile(r"(?<!&)&(?:&&)*(?!&)")
_GIT_HTTP_AUTHORITY_RES = (
re.compile(r"git\+https?://(?P<authority>[^/\s\"']+)", re.I),
re.compile(r"\bgit\s*=\s*[\"']https?://(?P<authority>[^/\s\"']+)", re.I),
)
_API_VERSION_PATTERN = re.compile(
r"^(?P<major>\d+)"
r"(?:\.(?P<minor>\d+))?"
@@ -78,6 +83,62 @@ def has_disallowed_build_command_content(command: str) -> bool:
return False
def _has_git_http_url_userinfo(dependency: str) -> bool:
"""Check whether a Git HTTP URL contains userinfo."""
return any(
"@" in match.group("authority")
for pattern in _GIT_HTTP_AUTHORITY_RES
for match in pattern.finditer(dependency)
)
def _validate_git_http_url_userinfo(
values: Iterable[str], *, source: pathlib.Path | None = None
) -> None:
"""Reject credential-bearing Git HTTP URLs without echoing their values."""
if not any(_has_git_http_url_userinfo(value) for value in values):
return
message = (
"Git dependency URLs must not contain credentials or other URL "
"userinfo because generated Dockerfiles and image layers can retain "
"them. Use a credential-free Git URL and provide short-lived "
"credentials through your build environment's secret-backed Git "
"credential helper."
)
if source is not None:
message += f" Found in: {source}"
raise click.UsageError(message)
def _validate_git_http_url_userinfo_files(paths: Iterable[pathlib.Path]) -> None:
"""Reject credential-bearing Git HTTP URLs in dependency files."""
for path in paths:
path = path.resolve()
if not path.is_file():
continue
try:
contents = path.read_text(encoding="utf-8", errors="replace")
except OSError:
raise click.UsageError(
f"Could not inspect dependency file for embedded credentials: {path}"
) from None
_validate_git_http_url_userinfo([contents], source=path)
def _validate_local_dependency_files(config_path: pathlib.Path, config: Config) -> None:
"""Validate dependency files copied into a non-uv Python image."""
paths: list[pathlib.Path] = []
for dependency in config["dependencies"]:
if not isinstance(dependency, str) or not dependency.startswith("."):
continue
root = (config_path.parent / dependency).resolve()
paths.extend(
root / name
for name in ("requirements.txt", "pyproject.toml", "setup.py", "setup.cfg")
)
_validate_git_http_url_userinfo_files(paths)
MIN_PYTHON_VERSION = "3.11"
DEFAULT_PYTHON_VERSION = "3.11"
@@ -320,7 +381,9 @@ def _get_source_kind(config: Config) -> str | None:
return kind if isinstance(kind, str) else None
def validate_config(config: Config) -> Config:
def validate_config(
config: Config, *, source_path: pathlib.Path | None = None
) -> Config:
"""Validate a configuration dictionary."""
graphs = config.get("graphs", {})
@@ -415,6 +478,15 @@ def validate_config(config: Config) -> Config:
' "source": {"kind": "uv", "root": ".."}'
)
_validate_git_http_url_userinfo(
(
dependency
for dependency in config["dependencies"]
if isinstance(dependency, str)
),
source=source_path,
)
source = config.get("source")
source_kind = _get_source_kind(config)
if source is not None and not isinstance(source, dict):
@@ -609,7 +681,7 @@ def validate_config_file(config_path: pathlib.Path) -> Config:
"""Load and validate a configuration file."""
with open(config_path) as f:
config = json.load(f)
validated = validate_config(config)
validated = validate_config(config, source_path=config_path.resolve())
# Enforce the package.json doesn't enforce an
# incompatible Node.js version
if validated.get("node_version"):
@@ -1280,6 +1352,7 @@ def python_config_to_docker(
api_version=api_version,
build_tools_to_uninstall=build_tools_to_uninstall,
)
_validate_local_dependency_files(config_path, config)
if pip_installer == "auto":
if _image_supports_uv(base_image):
pip_installer = "uv"
@@ -1490,7 +1563,18 @@ def node_config_to_docker(
) -> tuple[str, dict[str, str]]:
# Calculate paths for monorepo support
install_root = (
pathlib.Path(build_context).resolve() if build_context else config_path.parent
pathlib.Path(build_context).resolve()
if build_context
else config_path.parent.resolve()
)
config_root = config_path.parent.resolve()
dependency_roots = (
(install_root, config_root) if install_root != config_root else (install_root,)
)
_validate_git_http_url_userinfo_files(
root / name
for root in dependency_roots
for name in ("package.json", "package-lock.json", "yarn.lock", "pnpm-lock.yaml")
)
install_cmd = install_command or _get_node_pm_install_cmd(install_root)
if build_context:
+3 -13
View File
@@ -12,7 +12,6 @@ from collections.abc import Callable, Mapping, Sequence
from contextlib import contextmanager
from dataclasses import asdict, dataclass, field
from datetime import datetime, timezone
from functools import partial
from typing import Protocol, TypeVar
import click
@@ -1918,8 +1917,7 @@ OPT_AGENT_ID = click.option(
help="Logical agent ID (requires agent mode enabled for the tenant).",
)
OPT_AGENT_ENVIRONMENT = partial(
click.option,
OPT_AGENT_ENVIRONMENT = click.option(
"--agent-environment",
"environment",
envvar="LANGSMITH_AGENT_ENVIRONMENT",
@@ -2027,9 +2025,7 @@ def _deploy_base_options(
OPT_HOST_API_KEY,
OPT_HOST_DEPLOYMENT_NAME,
OPT_AGENT_ID,
OPT_AGENT_ENVIRONMENT()
if include_docker_args
else OPT_AGENT_ENVIRONMENT(type=str),
OPT_AGENT_ENVIRONMENT,
click.option(
"--deployment-id",
help=(
@@ -2176,12 +2172,6 @@ def deploy(ctx: click.Context, **_: object):
# otherwise, we return None here and click will proceed to actually run the subcommand (list or delete)
if ctx.invoked_subcommand is not None:
return
environment_param = next(
param for param in _deploy_cmd.params if param.name == "environment"
)
ctx.params["environment"] = environment_param.type_cast_value(
ctx, ctx.params["environment"]
)
if (
ctx.params.get("agent_id") is not None
or ctx.params.get("environment") is not None
@@ -2381,7 +2371,7 @@ def _deploy_cmd(
@OPT_HOST_API_KEY
@OPT_HOST_URL
@OPT_AGENT_ID
@OPT_AGENT_ENVIRONMENT()
@OPT_AGENT_ENVIRONMENT
@click.option(
"--name-contains",
default="",
+5 -1
View File
@@ -650,7 +650,8 @@ class Config(TypedDict, total=False):
pip_config_file: str | None
"""Optional. Path to a pip config file (e.g., "/etc/pip.conf" or "pip.ini") for controlling
package installation (custom indices, credentials, etc.).
package installation (custom indices, timeouts, etc.). The file is copied into the
generated image, so it must not contain credentials or other secrets.
Only relevant if Python dependencies are installed via pip. If omitted, default pip settings are used.
"""
@@ -689,6 +690,9 @@ class Config(TypedDict, total=False):
- "." or "./src" if you have a local Python package
- str (aka "anthropic") for a PyPI package
- "git+https://github.com/org/repo.git@main" for a Git-based package
Git HTTP URLs must not contain userinfo such as a username or token. For private
dependencies, provide short-lived credentials through the build environment's
secret-backed Git credential helper.
Defaults to an empty list, meaning no additional packages installed beyond your base environment.
This field is not supported when `source.kind` is `uv`.
+10
View File
@@ -880,6 +880,7 @@ def python_config_to_docker_uv_lock(
_get_node_pm_install_cmd,
_get_pip_cleanup_lines,
_image_supports_uv,
_validate_git_http_url_userinfo_files,
docker_tag,
)
@@ -890,11 +891,20 @@ def python_config_to_docker_uv_lock(
)
config_root = config_path.parent.resolve()
source_root = config["source"].get("root", ".")
project_root = (config_root / source_root).resolve()
_validate_git_http_url_userinfo_files(
[project_root / "pyproject.toml", project_root / "uv.lock"]
)
install_cmd = "uv pip install --system"
_, global_reqs_pip_install, pip_config_file_str = _build_python_install_commands(
config, install_cmd
)
plan = _plan_uv_lock_workspace(config_path, config)
_validate_git_http_url_userinfo_files(
package.pyproject_path for package in plan.install_order
)
_update_uv_lock_graph_paths(config_path, config, plan)
for section, key in [
+2 -2
View File
@@ -28,7 +28,7 @@
"type": "null"
}
],
"description": "Optional. Path to a pip config file (e.g., \"/etc/pip.conf\" or \"pip.ini\") for controlling\npackage installation (custom indices, credentials, etc.).\n\nOnly relevant if Python dependencies are installed via pip. If omitted, default pip settings are used.\n"
"description": "Optional. Path to a pip config file (e.g., \"/etc/pip.conf\" or \"pip.ini\") for controlling\npackage installation (custom indices, timeouts, etc.). The file is copied into the\ngenerated image, so it must not contain credentials or other secrets.\n\nOnly relevant if Python dependencies are installed via pip. If omitted, default pip settings are used.\n"
},
"_INTERNAL_docker_tag": {
"anyOf": [
@@ -270,7 +270,7 @@
"type": "null"
}
],
"description": "Optional. Path to a pip config file (e.g., \"/etc/pip.conf\" or \"pip.ini\") for controlling\npackage installation (custom indices, credentials, etc.).\n\nOnly relevant if Python dependencies are installed via pip. If omitted, default pip settings are used.\n"
"description": "Optional. Path to a pip config file (e.g., \"/etc/pip.conf\" or \"pip.ini\") for controlling\npackage installation (custom indices, timeouts, etc.). The file is copied into the\ngenerated image, so it must not contain credentials or other secrets.\n\nOnly relevant if Python dependencies are installed via pip. If omitted, default pip settings are used.\n"
},
"_INTERNAL_docker_tag": {
"anyOf": [
+2 -2
View File
@@ -28,7 +28,7 @@
"type": "null"
}
],
"description": "Optional. Path to a pip config file (e.g., \"/etc/pip.conf\" or \"pip.ini\") for controlling\npackage installation (custom indices, credentials, etc.).\n\nOnly relevant if Python dependencies are installed via pip. If omitted, default pip settings are used.\n"
"description": "Optional. Path to a pip config file (e.g., \"/etc/pip.conf\" or \"pip.ini\") for controlling\npackage installation (custom indices, timeouts, etc.). The file is copied into the\ngenerated image, so it must not contain credentials or other secrets.\n\nOnly relevant if Python dependencies are installed via pip. If omitted, default pip settings are used.\n"
},
"_INTERNAL_docker_tag": {
"anyOf": [
@@ -270,7 +270,7 @@
"type": "null"
}
],
"description": "Optional. Path to a pip config file (e.g., \"/etc/pip.conf\" or \"pip.ini\") for controlling\npackage installation (custom indices, credentials, etc.).\n\nOnly relevant if Python dependencies are installed via pip. If omitted, default pip settings are used.\n"
"description": "Optional. Path to a pip config file (e.g., \"/etc/pip.conf\" or \"pip.ini\") for controlling\npackage installation (custom indices, timeouts, etc.). The file is copied into the\ngenerated image, so it must not contain credentials or other secrets.\n\nOnly relevant if Python dependencies are installed via pip. If omitted, default pip settings are used.\n"
},
"_INTERNAL_docker_tag": {
"anyOf": [
+237
View File
@@ -255,6 +255,243 @@ def test_validate_config():
)
@pytest.mark.parametrize(
"dependency",
[
"git+https://user:secret-token@github.com/org/private.git@main",
"private-package @ git+http://token@github.com/org/private.git",
"git+HTTPS://user%40example.com:secret%2Ftoken@github.com/org/private.git",
"git+https://${GIT_TOKEN}@github.com/org/private.git",
],
)
def test_validate_config_rejects_git_http_url_userinfo(dependency: str):
with pytest.raises(click.UsageError) as exc_info:
validate_config(
{
"python_version": "3.11",
"dependencies": [dependency],
"graphs": {"agent": "./agent.py:graph"},
}
)
message = str(exc_info.value)
assert "must not contain credentials or other URL userinfo" in message
assert "secret-token" not in message
assert "secret%2Ftoken" not in message
def test_validate_config_file_reports_source_for_git_http_url_userinfo(
tmp_path: pathlib.Path,
):
config_path = tmp_path / "langgraph.json"
config_path.write_text(
json.dumps(
{
"python_version": "3.11",
"dependencies": ["git+https://secret-token@github.com/org/private.git"],
"graphs": {"agent": "./agent.py:graph"},
}
)
)
with pytest.raises(click.UsageError) as exc_info:
validate_config_file(config_path)
message = str(exc_info.value)
assert "secret-token" not in message
assert f"Found in: {config_path.resolve()}" in message
@pytest.mark.parametrize(
"manifest", ["package.json", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"]
)
def test_config_to_docker_rejects_git_http_url_userinfo_in_node_files(
tmp_path: pathlib.Path, manifest: str
):
config_path = tmp_path / "langgraph.json"
config_path.write_text("{}\n")
(tmp_path / "agent.js").write_text("export const graph = {};\n")
(tmp_path / "package.json").write_text('{"name":"agent"}\n')
(tmp_path / manifest).write_text(
'"priv": "git+https://user:secret-token@github.com/org/private.git"\n'
)
config = validate_config(
{
"node_version": "20",
"graphs": {"agent": "./agent.js:graph"},
}
)
with pytest.raises(click.UsageError) as exc_info:
config_to_docker(
config_path,
config,
base_image="langchain/langgraphjs-api",
)
message = str(exc_info.value)
assert "must not contain credentials or other URL userinfo" in message
assert "secret-token" not in message
assert f"Found in: {(tmp_path / manifest).resolve()}" in message
def test_config_to_docker_allows_node_git_urls_without_http_userinfo(
tmp_path: pathlib.Path,
):
config_path = tmp_path / "langgraph.json"
config_path.write_text("{}\n")
(tmp_path / "agent.js").write_text("export const graph = {};\n")
(tmp_path / "package.json").write_text(
'{"dependencies":{"public":"git+https://github.com/org/public.git"}}\n'
)
config = validate_config(
{
"node_version": "20",
"graphs": {"agent": "./agent.js:graph"},
}
)
docker, _ = config_to_docker(
config_path,
config,
base_image="langchain/langgraphjs-api",
)
assert f"ADD . /deps/{tmp_path.name}" in docker
def test_config_to_docker_rejects_git_http_url_userinfo_in_node_workspace(
tmp_path: pathlib.Path,
):
config_root = tmp_path / "apps" / "agent"
config_root.mkdir(parents=True)
config_path = config_root / "langgraph.json"
config_path.write_text("{}\n")
(config_root / "agent.js").write_text("export const graph = {};\n")
(config_root / "package.json").write_text(
'{"dependencies":{"priv":"git+https://secret-token@github.com/org/private.git"}}\n'
)
(tmp_path / "package.json").write_text('{"name":"workspace"}\n')
config = validate_config(
{
"node_version": "20",
"graphs": {"agent": "./agent.js:graph"},
}
)
with pytest.raises(click.UsageError) as exc_info:
config_to_docker(
config_path,
config,
base_image="langchain/langgraphjs-api",
build_context=str(tmp_path),
)
message = str(exc_info.value)
assert "secret-token" not in message
assert f"Found in: {(config_root / 'package.json').resolve()}" in message
@pytest.mark.parametrize(
"dependency",
[
"git+https://github.com/org/public.git@main",
"private-package @ git+https://github.com/org/private.git@main",
"git+ssh://git@github.com/org/private.git@main",
],
)
def test_validate_config_allows_git_urls_without_http_userinfo(dependency: str):
config = validate_config(
{
"python_version": "3.11",
"dependencies": [dependency],
"graphs": {"agent": "./agent.py:graph"},
}
)
assert config["dependencies"] == [dependency]
def test_config_to_docker_rejects_git_http_url_userinfo_in_requirements(
tmp_path: pathlib.Path,
):
config_path = tmp_path / "langgraph.json"
config_path.write_text("{}\n")
(tmp_path / "agent.py").write_text("graph = object()\n")
(tmp_path / "requirements.txt").write_text(
"private @ git+https://secret-token@github.com/org/private.git\n"
)
config = validate_config(
{
"python_version": "3.11",
"dependencies": ["."],
"graphs": {"agent": "./agent.py:graph"},
}
)
with pytest.raises(click.UsageError) as exc_info:
config_to_docker(
config_path,
config,
base_image="langchain/langgraph-api:0.2.47",
)
message = str(exc_info.value)
assert "must not contain credentials or other URL userinfo" in message
assert "secret-token" not in message
assert f"Found in: {(tmp_path / 'requirements.txt').resolve()}" in message
@pytest.mark.parametrize("manifest", ["pyproject.toml", "uv.lock"])
def test_config_to_docker_rejects_git_http_url_userinfo_in_uv_files(
tmp_path: pathlib.Path, manifest: str
):
config_path = tmp_path / "langgraph.json"
config_path.write_text("{}\n")
(tmp_path / "src").mkdir()
(tmp_path / "src" / "agent.py").write_text("graph = object()\n")
pyproject = textwrap.dedent(
"""
[project]
name = "agent"
version = "0.1.0"
dependencies = ["private"]
[tool.uv.sources]
private = { git = "https://github.com/org/private.git" }
"""
).strip()
uv_lock = "# uv lock file\n"
if manifest == "pyproject.toml":
pyproject = pyproject.replace(
"https://github.com", "https://secret-token@github.com"
)
else:
uv_lock += (
'source = { git = "https://secret-token@github.com/org/private.git" }\n'
)
(tmp_path / "pyproject.toml").write_text(pyproject + "\n")
(tmp_path / "uv.lock").write_text(uv_lock)
config = validate_config(
{
"python_version": "3.11",
"graphs": {"agent": "./src/agent.py:graph"},
"source": {"kind": "uv"},
}
)
with pytest.raises(click.UsageError) as exc_info:
config_to_docker(
config_path,
config,
base_image="langchain/langgraph-api:0.2.47",
)
message = str(exc_info.value)
assert "must not contain credentials or other URL userinfo" in message
assert "secret-token" not in message
def test_validate_config_image_distro():
"""Test validation of image_distro field."""
# Valid image_distro values should work
+3 -3
View File
@@ -732,11 +732,11 @@ wheels = [
[[package]]
name = "urllib3"
version = "2.7.0"
version = "2.8.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
{ url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" },
]
[[package]]
+3 -3
View File
@@ -672,11 +672,11 @@ wheels = [
[[package]]
name = "urllib3"
version = "2.7.0"
version = "2.8.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
{ url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" },
]
[[package]]
+59 -60
View File
@@ -678,7 +678,7 @@ wheels = [
[[package]]
name = "hatch"
version = "1.18.0"
version = "1.18.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "backports-zstd", marker = "python_full_version < '3.14'" },
@@ -701,9 +701,9 @@ dependencies = [
{ name = "uv" },
{ name = "virtualenv" },
]
sdist = { url = "https://files.pythonhosted.org/packages/10/fd/634c575b5becad2dfa7135f3ad66d57102cd77d834cf473756d868a808ff/hatch-1.18.0.tar.gz", hash = "sha256:463d214cb068391454be198e58d3cc0846f71e39d68c5568ba650af7781e8ae3", size = 5275084, upload-time = "2026-08-11T05:06:41.513Z" }
sdist = { url = "https://files.pythonhosted.org/packages/91/81/a5a77aaa23df824562d50ad25eeb52ae6446924d0dc68c7c19ed6d8b171f/hatch-1.18.1.tar.gz", hash = "sha256:222fff78e197cf12a39db7efe5318ca403f2614db213416fd106a6c3260ef221", size = 5277846, upload-time = "2026-09-16T16:56:20.886Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/fd/b1/d14265cb26c57af1485c01fd95037a35f13748b718617405cdefc6150429/hatch-1.18.0-py3-none-any.whl", hash = "sha256:75874c0905fe76b44fd39585c49bc9bd2b9fee638abb11f1f3d087042e7f9122", size = 171310, upload-time = "2026-08-11T05:06:39.807Z" },
{ url = "https://files.pythonhosted.org/packages/04/a0/dc90fbe25bca29154d5926e1c96385d1c7a6feb120fa2c1b3e6098ad4d23/hatch-1.18.1-py3-none-any.whl", hash = "sha256:f005959995df45e5f5dd27c862dd77ce07e24e7f06aa8e51cbba2a40bac33a40", size = 172336, upload-time = "2026-09-16T16:56:19.332Z" },
]
[[package]]
@@ -1207,7 +1207,7 @@ wheels = [
[[package]]
name = "langgraph-sdk"
version = "0.4.4"
version = "0.4.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "httpx" },
@@ -1216,9 +1216,9 @@ dependencies = [
{ name = "orjson" },
{ name = "websockets" },
]
sdist = { url = "https://files.pythonhosted.org/packages/3f/ae/91446c1fffa04a2dc1f81afbfb5bfff3590452891a72bd9098a656ab2657/langgraph_sdk-0.4.4.tar.gz", hash = "sha256:4e651ffa09de695681579396375377bdde23bedbc8e35b070e615cbd5af7da8b", size = 345789, upload-time = "2026-08-27T21:25:22.593Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e8/9c/7ff305b366ce986052a27dc5946839bef2823b3567664cbad22e294dff5a/langgraph_sdk-0.4.5.tar.gz", hash = "sha256:d49a98a2ee8e0c494b101a7caf8061c8b4b94d3ee5ada0ea2dbe50903a5487b1", size = 349783, upload-time = "2026-09-21T14:42:55.732Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/43/d5/2ad7f3a835c6fcebf58b6669552536ecd52d2dfe4cf49c6c36648fd83572/langgraph_sdk-0.4.4-py3-none-any.whl", hash = "sha256:39afe416c91742925e6f8a93715f566d499b36e1b636b804a4ffe3190e4f4e64", size = 162270, upload-time = "2026-08-27T21:25:21.072Z" },
{ url = "https://files.pythonhosted.org/packages/49/a9/71a6499f3481bc00bf4f42a17cb81caf19a02fce762db356626d7214e2c2/langgraph_sdk-0.4.5-py3-none-any.whl", hash = "sha256:e03ef033a20d21288af496e9b6c08ae3afcc1b58dc5abcd37575bfd1a93045de", size = 162304, upload-time = "2026-09-21T14:42:54.623Z" },
]
[[package]]
@@ -1777,11 +1777,11 @@ wheels = [
[[package]]
name = "pyjwt"
version = "2.13.0"
version = "2.15.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" }
sdist = { url = "https://files.pythonhosted.org/packages/02/a5/5197bfd06417837ac079921c66fa6393f1dea3557272a263cebfef69e432/pyjwt-2.15.0.tar.gz", hash = "sha256:b11c5f9791d7bf51c2b39a81ed669f6b2dbbd669df2942f6c60167e9e3d1abe4", size = 120513, upload-time = "2026-09-23T16:56:00.689Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" },
{ url = "https://files.pythonhosted.org/packages/e8/55/40e45bf052ee8ee12a4dfd785519660f8effa7b065442b91646ec6828619/pyjwt-2.15.0-py3-none-any.whl", hash = "sha256:7a3742debf6b879e912dbb9819ceec1594be812452b78c5f2e2dfc56564954f8", size = 33680, upload-time = "2026-09-23T16:55:59.241Z" },
]
[[package]]
@@ -1827,14 +1827,14 @@ wheels = [
[[package]]
name = "pytest-mock"
version = "3.15.1"
version = "3.16.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/68/14/eb014d26be205d38ad5ad20d9a80f7d201472e08167f0bb4361e251084a9/pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f", size = 34036, upload-time = "2025-09-16T16:37:27.081Z" }
sdist = { url = "https://files.pythonhosted.org/packages/7a/7f/6ed29931d5c8cd396e7c0a55412e6cc88020373365c8685985dea53d26d7/pytest_mock-3.16.0.tar.gz", hash = "sha256:5a8395528b8f498205f3718f575228d0edaed7425fff638f87d1a6c3e0383636", size = 35362, upload-time = "2026-09-27T14:57:55.46Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095, upload-time = "2025-09-16T16:37:25.734Z" },
{ url = "https://files.pythonhosted.org/packages/db/5b/b83a9bf1a3b4ec222f9fa083147ff6816245223da0ab92370e7e056f113f/pytest_mock-3.16.0-py3-none-any.whl", hash = "sha256:007cfeb257801d88d9c0b2a7b5a15a15e73b71968dfd72e7bf8c4a2f8393aec8", size = 10016, upload-time = "2026-09-27T14:57:54.283Z" },
]
[[package]]
@@ -1863,15 +1863,14 @@ wheels = [
[[package]]
name = "python-discovery"
version = "1.2.2"
version = "1.6.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "filelock" },
{ name = "platformdirs" },
]
sdist = { url = "https://files.pythonhosted.org/packages/de/ef/3bae0e537cfe91e8431efcba4434463d2c5a65f5a89edd47c6cf2f03c55f/python_discovery-1.2.2.tar.gz", hash = "sha256:876e9c57139eb757cb5878cbdd9ae5379e5d96266c99ef731119e04fffe533bb", size = 58872, upload-time = "2026-04-07T17:28:49.249Z" }
sdist = { url = "https://files.pythonhosted.org/packages/0c/57/250bd238b966cece44328235eb85290045d059265fdaf7527a3a958123db/python_discovery-1.6.1.tar.gz", hash = "sha256:cf87d3627dfb4412437fdd5b13eae402607722998d21567993aedbc59b23c15e", size = 84338, upload-time = "2026-09-18T01:31:53.971Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl", hash = "sha256:e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a", size = 31894, upload-time = "2026-04-07T17:28:48.09Z" },
{ url = "https://files.pythonhosted.org/packages/16/7d/e9ffbadfbf89c93848412d04594135c4ae8c1d37d9e053b9c3ed718fabc4/python_discovery-1.6.1-py3-none-any.whl", hash = "sha256:d43fcdef879fe795352bd13ccf8d185ba5a9f86f36cfcd00529f596e737442b3", size = 38664, upload-time = "2026-09-18T01:31:52.448Z" },
]
[[package]]
@@ -1998,27 +1997,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.16.5"
version = "0.16.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f3/85/c8e12473c93018f92d19dd988a294202e1c27426c47ec4de53ffb847b8d8/ruff-0.16.5.tar.gz", hash = "sha256:1b88500f9ffbcab3dedb0082c9f9492e91ec3d618aac1236a3e0189938f7040b", size = 4912003, upload-time = "2026-08-27T16:34:18.258Z" }
sdist = { url = "https://files.pythonhosted.org/packages/96/bf/c935ca98e73fe8ce65b87ef08a280c0c1e85295d569228c15e87d8fdfaf1/ruff-0.16.9.tar.gz", hash = "sha256:12b625c6cfba78d285d9f48eda5f053374f1e53cb10ef17342a383750db99161", size = 4948764, upload-time = "2026-09-24T20:37:49.416Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c6/b6/77c90a970fe2dae17a723acbd011043ea97c98d7deacccefdc4ba74ec512/ruff-0.16.5-py3-none-linux_armv6l.whl", hash = "sha256:12e5f673e774c35fbb62f288809c7653b73445f8ecec6b6063fd6ea3521aa14b", size = 10011941, upload-time = "2026-08-27T16:33:41.287Z" },
{ url = "https://files.pythonhosted.org/packages/4b/46/6cf67cf6411885a1d6f7f6d801682f155536a85176d10b605e2ceffed8bd/ruff-0.16.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:eda58a5802de40e7ed5b32b64e0b32539338cc6fcd2c78f61e3ad6a0d79f51c3", size = 10204049, upload-time = "2026-08-27T16:33:44.056Z" },
{ url = "https://files.pythonhosted.org/packages/46/fd/c8720ca7a090abf0c2fef4abe8a5ef6e5127ed15196d8886ff75a2b370e2/ruff-0.16.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5ae9a7b9a8875131f40f8fe967cc86abf899779efd663cb7ce3d572d01da7eb", size = 9809037, upload-time = "2026-08-27T16:33:46.257Z" },
{ url = "https://files.pythonhosted.org/packages/43/45/a684caacdedaca180f52bacccc40bf0789d2c5a7c75f25324853e9eaedb5/ruff-0.16.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b719b0a1f4d59710d283ab2965f621684a108a9e41da622e3b23f0326cd0025", size = 9964129, upload-time = "2026-08-27T16:33:48.352Z" },
{ url = "https://files.pythonhosted.org/packages/9e/f2/5d2bcdaca6b5b93d1b4dfc166cd2aebf7680143a1b38a28759df13a94d31/ruff-0.16.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2298f2780ed1be0c5cb1361e32ab7b1467f3cce7dabe101d2210a314f2fe42e9", size = 9821518, upload-time = "2026-08-27T16:33:50.57Z" },
{ url = "https://files.pythonhosted.org/packages/aa/ff/011cce29accf9257d5974145b733fc653a37985ed6825413a3987cefbfe0/ruff-0.16.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:258f29035a2dd021e7861e631b227a5b3f14e50c1184c9a6a122c5f4576154d7", size = 10534835, upload-time = "2026-08-27T16:33:52.522Z" },
{ url = "https://files.pythonhosted.org/packages/d7/5a/f0cf109bada9bba0e96c90c21c9f9251803f57225c32d293327a03c710d6/ruff-0.16.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9a4f0432966834019c74d1b7e5c51224305d7713f3d7faf3e7451f1a3be3cde", size = 11252550, upload-time = "2026-08-27T16:33:54.521Z" },
{ url = "https://files.pythonhosted.org/packages/63/4d/1d481aaea2046c6a7ed7c291f9004c669cce3c087b6b376ed5b08271e3fe/ruff-0.16.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5eb3a8c3d0ade9cea42b591fd530368e8798380e30e0a308b85a5cf718f09ea", size = 10777949, upload-time = "2026-08-27T16:33:56.88Z" },
{ url = "https://files.pythonhosted.org/packages/ee/34/ee245ca55f64443233034b3d02b03236b19242004281247c079390b7facd/ruff-0.16.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef0f69e191a13a3c9816f63163c88790cb12cd157bbbb384e9c44745702ab105", size = 10311656, upload-time = "2026-08-27T16:33:59.12Z" },
{ url = "https://files.pythonhosted.org/packages/a7/4d/c33a333e341c0a2b96c715b52d89a606f5a34cd4ac493cd9b8d0187186b8/ruff-0.16.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0eeab41fbea2c42f98dfb9822cdccda9d24ba38d49f6dc945b5c236d48f0ef29", size = 10532125, upload-time = "2026-08-27T16:34:01.166Z" },
{ url = "https://files.pythonhosted.org/packages/30/e1/a64cef78b40192497bb98a27a8aa8f2c98ee9ee15bc97f7712d94ef32937/ruff-0.16.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f0768e9df4300713fff30733c87575f68b6f1d8de41184e505b7fdd9c0c95eaf", size = 10097648, upload-time = "2026-08-27T16:34:03.16Z" },
{ url = "https://files.pythonhosted.org/packages/cc/4e/4cdc9ed3c3e109d2f71e62572a37457298d7bc7501ec3138babb7ed32bbd/ruff-0.16.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:95cc70cdc7aa80c338de356279d2adbeb2de0f520b9ecd8aba75b94e95e02f91", size = 9829344, upload-time = "2026-08-27T16:34:05.134Z" },
{ url = "https://files.pythonhosted.org/packages/39/4a/31ed35ce31729955fc583ee0d176d6e784c1290cb0b0a75cb2134c1ab72a/ruff-0.16.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d185c8398ded1bfd91c0c2cb258346307571eccc473a8490af8c3977399c384a", size = 10277117, upload-time = "2026-08-27T16:34:07.425Z" },
{ url = "https://files.pythonhosted.org/packages/a8/a0/60356d86687b4b666d593df213f4dc3041750d024cb7bf2cfa81cfd65c2e/ruff-0.16.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:fb8e3a3c4c6a784150a7ced53b015f4b253fc2bf97a610886419ead64b4756ef", size = 10711653, upload-time = "2026-08-27T16:34:09.712Z" },
{ url = "https://files.pythonhosted.org/packages/ed/20/656d67f5b25ca9bda4e02b1de25867b2954e1d19e03648060f167ad0f4cc/ruff-0.16.5-py3-none-win32.whl", hash = "sha256:288b0a5f080492fe5635db849f9e2e84aa3cce7b7f0e955997d416c507c76a26", size = 10034250, upload-time = "2026-08-27T16:34:11.8Z" },
{ url = "https://files.pythonhosted.org/packages/5b/42/ee8e68a207b9127fcde6c3d7e197def432f346cb1af159e1fa14ca0d1cdc/ruff-0.16.5-py3-none-win_amd64.whl", hash = "sha256:ddc6385fb2137f616357ca03d6c74f4be987f80fed4008566b754f6032b8546f", size = 10516714, upload-time = "2026-08-27T16:34:13.963Z" },
{ url = "https://files.pythonhosted.org/packages/73/e3/7df5a396e445b9ba49ce9a9437439a4d80042c61c0ade199abf8d16de1ac/ruff-0.16.5-py3-none-win_arm64.whl", hash = "sha256:a64abe90968719b851bb7cedffaa8753fbdbdadab483089682db623f3edc587e", size = 10391564, upload-time = "2026-08-27T16:34:16.064Z" },
{ url = "https://files.pythonhosted.org/packages/0d/26/df51322b52ee1ada7eff2d071ea09d11d5c2d1dcc9f02594f5785c4d1635/ruff-0.16.9-py3-none-linux_armv6l.whl", hash = "sha256:95e6f022090368ab3b824c36276839c53b2adf1a3f4c09fefc33dfc400f6da96", size = 10082922, upload-time = "2026-09-24T20:37:13.045Z" },
{ url = "https://files.pythonhosted.org/packages/a5/27/7bf51f5a7aa375e9f339280a303aab44ca75dc1525f1cdc5991761685b0f/ruff-0.16.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a5f27be168556594a86d2f415db0cf43f5291917849318f873c7e2791f7a8c67", size = 10236360, upload-time = "2026-09-24T20:37:16.049Z" },
{ url = "https://files.pythonhosted.org/packages/b6/63/09659283f92f02dff45809da194a70da2f688d87c55d8875c4fae3536072/ruff-0.16.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1632eb1d6197f33bd00b1acbc5b71009e89a8895c158e2d2b03a834fac964ab6", size = 9892940, upload-time = "2026-09-24T20:37:17.957Z" },
{ url = "https://files.pythonhosted.org/packages/24/58/98de1b72ec172f5f8f1731236fe21585b3998bf7dfe9fcc44ae9ba626012/ruff-0.16.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3f951b14d865d5952c89d40a5ca07e87abe24fa5453299878411e127748fb1c", size = 10032114, upload-time = "2026-09-24T20:37:19.942Z" },
{ url = "https://files.pythonhosted.org/packages/c8/7d/f1e17c54ab59d4bad1dce8ee3e22a7a1d0ef4745240decacdcf3832b5bb2/ruff-0.16.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:447fc07e1573afff7cb02803462b12b6c8ece7cf10e2cd78565fa6d7a1c0bf8d", size = 9910227, upload-time = "2026-09-24T20:37:21.872Z" },
{ url = "https://files.pythonhosted.org/packages/34/19/436f647a65075bbd3bab2668b3bdaa5120559b294694018cdcefabbbf30b/ruff-0.16.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a3e039a6a40ed976c491722b60e0ae4a4aa1a86057f540ee7a37a5d19ae9120", size = 10547484, upload-time = "2026-09-24T20:37:24.229Z" },
{ url = "https://files.pythonhosted.org/packages/03/59/38430a6bc2f6d8095447ac39625cf8b6e9344a47e6c26225c8ba1bff3ffb/ruff-0.16.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4684dded7db60aa57cb118fa158630f5feade4af5782903b6053484bdf9bd129", size = 11412367, upload-time = "2026-09-24T20:37:26.307Z" },
{ url = "https://files.pythonhosted.org/packages/c8/bd/bbb6d7fc7f208c8b8c50dd5dc8206e4cfdb1e7a8fb852606a3adf370c880/ruff-0.16.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d29c934357e45642fda2f34c0b1f4025b4a6c01e15e4bf0016879d60078a142c", size = 10869787, upload-time = "2026-09-24T20:37:28.35Z" },
{ url = "https://files.pythonhosted.org/packages/bc/b8/9c543074918061abbefc3bd139bee22de35abedb00dde0f2d27288838962/ruff-0.16.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a21713e629d3e5bdb2f5c2def1cc7f04f47fa8e1a7eb0571b4a28e1da64bc728", size = 10406494, upload-time = "2026-09-24T20:37:30.624Z" },
{ url = "https://files.pythonhosted.org/packages/35/7a/5a8851bd146e7ccf8fd4b003f6c75c11f8fbdb0e60673b45097986b6bf41/ruff-0.16.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7baa24ef5fc8e77aa93879e1d3f43754a01ae488e869f1ae30cf431afd4d2452", size = 10590083, upload-time = "2026-09-24T20:37:32.439Z" },
{ url = "https://files.pythonhosted.org/packages/87/f0/4c3467188f23f806960b46fa76575a7cd0514c9ba90562650b71efc96980/ruff-0.16.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a41aac6230aadfaa133bdfa1614488531ffa3e0837567ae04c0da2058a9c0f9e", size = 10119151, upload-time = "2026-09-24T20:37:34.581Z" },
{ url = "https://files.pythonhosted.org/packages/15/34/5a4def5adea572ce6aea0bb64f21f928ee317b80e0db747d7979b01d7261/ruff-0.16.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c2529fb5896d49115b0e9aa8f887490b34bbe76baf879ec2264ac59406869ce7", size = 9911544, upload-time = "2026-09-24T20:37:36.796Z" },
{ url = "https://files.pythonhosted.org/packages/62/5d/d15ebea7499eef9373318c0ee6ca127832927c6529731f6d48e18dce7ca9/ruff-0.16.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:41e3870277694177429b56406d65dfbdb2c2802c52b715edaf6a0b829c69d4ee", size = 10269884, upload-time = "2026-09-24T20:37:38.857Z" },
{ url = "https://files.pythonhosted.org/packages/d1/56/c5d3cd119ded7a3c7aba0e961b69cb3df701c91662c98ad694467d060ce1/ruff-0.16.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8adbe4e58af167f767d7b2ba5e83c42e878350796cf78c2f5e14ab9903a92588", size = 10749366, upload-time = "2026-09-24T20:37:41.042Z" },
{ url = "https://files.pythonhosted.org/packages/ac/fe/734ec7527029ac757ecf821f143c9f3fcf69149c21f53a044a899b430f5a/ruff-0.16.9-py3-none-win32.whl", hash = "sha256:0e1dbc2073624dee6618d41d0098690a7244654af746704b64759e12b6b6b385", size = 10152355, upload-time = "2026-09-24T20:37:43.025Z" },
{ url = "https://files.pythonhosted.org/packages/14/21/26e4643629b3ebb44f0a06f9c9a53058d63d989415f63a9a3c28e2ee7f22/ruff-0.16.9-py3-none-win_amd64.whl", hash = "sha256:6bd40fec8cd4c8a3d4dd589bd8ad4e6320c13c29234159bfd959a40d529d597b", size = 10592965, upload-time = "2026-09-24T20:37:44.944Z" },
{ url = "https://files.pythonhosted.org/packages/51/60/5fb1a39dbb5ae314d5f59bc7348a63c1d5c20f3cd83914c4b5cb0be31d2d/ruff-0.16.9-py3-none-win_arm64.whl", hash = "sha256:ed1a252039200f57a59eebc063b54beabea67bfbaaca0eeaa7f54b5fbcda2284", size = 10458649, upload-time = "2026-09-24T20:37:46.882Z" },
]
[[package]]
@@ -2197,27 +2196,27 @@ wheels = [
[[package]]
name = "ty"
version = "0.0.75"
version = "0.0.84"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/81/d0/d0c96f898d6974a4a3569ab3efdf9512c04ad99f9203effb55f72497fe97/ty-0.0.75.tar.gz", hash = "sha256:4c5eead33dfbf6e2ebb4f400f74b51ffc9bab702a6f23ddb648a1cbb740387e3", size = 6868326, upload-time = "2026-08-26T20:23:40.399Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e1/f6/34f8869c45ea87fe6a931ffa824b1fe4428167173543d92988d631add355/ty-0.0.84.tar.gz", hash = "sha256:0cefdb0cd5d399418dbe83c349ba605047b7dff815ae6f460c80e8522b40be67", size = 7409537, upload-time = "2026-09-24T13:16:24.367Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/6c/b12d03505f17581f0cfa3c12273fe34c1d67b36dfda1bc561a6bdc16512b/ty-0.0.75-py3-none-linux_armv6l.whl", hash = "sha256:e5409f50db2246fd4bd039d93d261e0cfa1daa554a4fb77256f91072c570349a", size = 12972606, upload-time = "2026-08-26T20:22:59.716Z" },
{ url = "https://files.pythonhosted.org/packages/d1/aa/30f11eecd9215a9f87e8fe8baaf48f3ce905f5d75b8e4aac70f0091f130c/ty-0.0.75-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5e7b8b3472fb9bb2eeab314984b265df08a7a9d518867a9e6020eebc06570be2", size = 12527158, upload-time = "2026-08-26T20:23:02.767Z" },
{ url = "https://files.pythonhosted.org/packages/f2/11/7fd7001b0b5c6610bfbad7357e47d5fe6f82d4e84e94c53776a478f5e9f8/ty-0.0.75-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c6ccf34169821fe0d23e3360deeef981d217963412f1d087b9bdd32ec57f7a57", size = 12400533, upload-time = "2026-08-26T20:23:04.965Z" },
{ url = "https://files.pythonhosted.org/packages/fd/7f/1e284ea3d348d7be02f12d83bc22ed9ef193033f863f05b64db99027f141/ty-0.0.75-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842ebb41e9c6c334b40768704e20b1a69d5c6b08805b289d5e0e2565f49f2de1", size = 12420592, upload-time = "2026-08-26T20:23:07.427Z" },
{ url = "https://files.pythonhosted.org/packages/2d/ab/d813271543370c47fd74b5118f2066ab32b0983e907b1821f3f9a6d0fa7f/ty-0.0.75-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf7a5a723c5f1e0fab4ffbfe9bd95123a526ed48f206e5f25cb2161ca294007a", size = 12739219, upload-time = "2026-08-26T20:23:09.809Z" },
{ url = "https://files.pythonhosted.org/packages/31/5b/95b49cc5570fd92a7bf63732f649b31906158721e03c7fcb1b5be74ee3bf/ty-0.0.75-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54382f98e5da292fcd7104391afef5105c35bb2f312e29bea6f5fa419935255c", size = 13494046, upload-time = "2026-08-26T20:23:12.191Z" },
{ url = "https://files.pythonhosted.org/packages/2c/0d/502d2dd68173cf020e1ad2bdbab9544c86776de0b0e2ed15f8c2fe006e3d/ty-0.0.75-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac13b180dc2aade2cd243f56b01650e78bf091a2e522ad3bc947245d7837c613", size = 13938899, upload-time = "2026-08-26T20:23:14.764Z" },
{ url = "https://files.pythonhosted.org/packages/20/5b/f3b12a25c07224456219fc2bd20db0ad7e40b304be0ff6aad728da0135f9/ty-0.0.75-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:752df7951a443219d7f1ff817e3723c85d428565ff449e08a7a93ba821661526", size = 13656711, upload-time = "2026-08-26T20:23:17.145Z" },
{ url = "https://files.pythonhosted.org/packages/51/7b/f090ad306e2b15a07b332d647138c5264b89d9758855ecce8b8a10bcb153/ty-0.0.75-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fd399feedf7cee816563c1baec45fc1c0b3c89f1ea42364920b688004b5b7da", size = 13093499, upload-time = "2026-08-26T20:23:19.489Z" },
{ url = "https://files.pythonhosted.org/packages/f1/4b/f69b99aaaca0c7c65d5f114b186b26b21666f767b0c69eec99a2bdccc061/ty-0.0.75-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:d7625f6f56c7dc1e873579fdc9e432a0e21e302afe847ab60704d2303442a92e", size = 13520580, upload-time = "2026-08-26T20:23:21.789Z" },
{ url = "https://files.pythonhosted.org/packages/b6/e7/692c5f905c0345a15d2255fc74066d660f030254ae8dcdaf33f5a5c2f279/ty-0.0.75-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:89e7d527e95a2534b70cae29e94c104b84082760ea05927d23bb87280969c104", size = 12524095, upload-time = "2026-08-26T20:23:24.026Z" },
{ url = "https://files.pythonhosted.org/packages/ba/9a/f42b12cf265ea95344bf554764c4791cfb273bdd628aadd7c209af7cadc3/ty-0.0.75-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0843f134440740706e01bee5f88f4cfc10e9b018bddb9e4ef4c12dc9fc0c9aef", size = 12756591, upload-time = "2026-08-26T20:23:26.126Z" },
{ url = "https://files.pythonhosted.org/packages/7c/5e/9b180c133cb9cce48179a7d2bf9e1802d992aa8176a918e0e05205760b42/ty-0.0.75-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1bd0ec0e50ee1376875c88891efe6f549c3560fa5b2ddad79a425cd5a6218b9c", size = 12998754, upload-time = "2026-08-26T20:23:28.353Z" },
{ url = "https://files.pythonhosted.org/packages/39/f6/3c6ef5dd550103e29905121c67fb96a374564f31a2f44c6faa1af98c2d61/ty-0.0.75-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1f9eafd561f90110d5e29f589ec3e956c4686e2f6631348d99276436f5cbe4d1", size = 13316474, upload-time = "2026-08-26T20:23:30.857Z" },
{ url = "https://files.pythonhosted.org/packages/bb/52/12776337874c821076bd5368e352ccd9e67174790abe3b856f749cb3524b/ty-0.0.75-py3-none-win32.whl", hash = "sha256:05063a6fafe2154b794a7f964515d148e51acd186d72d4a3acd347ee9fa19336", size = 12316315, upload-time = "2026-08-26T20:23:33.528Z" },
{ url = "https://files.pythonhosted.org/packages/53/e6/bb51e16af5c7138c9f52f8f3d0a401a371c6798d092e3b74926f186a9814/ty-0.0.75-py3-none-win_amd64.whl", hash = "sha256:81cf1ba5f6b7536ad56747865214255d9bc8e80533a689dbb9ddeaad464b09f1", size = 12917267, upload-time = "2026-08-26T20:23:35.978Z" },
{ url = "https://files.pythonhosted.org/packages/39/73/4542f829107468b5de4231af67f29927c093bfad11f3c1e5b2c08fb1206b/ty-0.0.75-py3-none-win_arm64.whl", hash = "sha256:541c9af5b7a0ad23d15ec315a7da81150833c359f48124ed3789ff25eacd6f42", size = 12711024, upload-time = "2026-08-26T20:23:38.159Z" },
{ url = "https://files.pythonhosted.org/packages/aa/0c/600648778e1c79133ce6b6a5c4c2531ae16b90c9b30f5041b38b574f61b8/ty-0.0.84-py3-none-linux_armv6l.whl", hash = "sha256:868438e2b9abfc835dd5b5b07ed693db95d8348ac40e3228252511d63ae87695", size = 13935333, upload-time = "2026-09-24T13:15:31.167Z" },
{ url = "https://files.pythonhosted.org/packages/c5/3b/27f06f49945c36170765fad82076898039ae3873338e9865f876dd62f12c/ty-0.0.84-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b00f39b521f0b559cde0f6abf8dd47213b513b04f33d58efeb9b98486a16bb17", size = 13511328, upload-time = "2026-09-24T13:15:34.446Z" },
{ url = "https://files.pythonhosted.org/packages/fc/b6/b12dd130e7f30141f0645614f454c925991cd389b1cc6c8284fd6bf32326/ty-0.0.84-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8f78c2915567f2ee62ce0c24d86091bc76f81577677755e242d09951db588b9a", size = 13445445, upload-time = "2026-09-24T13:15:37.476Z" },
{ url = "https://files.pythonhosted.org/packages/44/96/f012de4b3c1d9a4773326621380d768b4d48c47e620dc012775c5e01c7d7/ty-0.0.84-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61155cad0921e890d86d1d911a40b3a0e924ef4bdc3b4f3865a6c89c7e3012dc", size = 13471235, upload-time = "2026-09-24T13:15:40.64Z" },
{ url = "https://files.pythonhosted.org/packages/05/32/dca630f5f5353fa7bf67eebccf1549df99b16656d21071d0df6677c826a5/ty-0.0.84-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:417c3bf14947ed16b0b92976ab333c27915590354e96d4f581709068d3811355", size = 13680704, upload-time = "2026-09-24T13:15:43.817Z" },
{ url = "https://files.pythonhosted.org/packages/44/8d/33702c8f62f05ad45b33644fb914d483de6a0a7bc8e51884e9b8773e6d69/ty-0.0.84-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e06ef117759f654f5379efe9ae79bda8a186016c016f1023d05c34f8e15c1546", size = 14518923, upload-time = "2026-09-24T13:15:46.802Z" },
{ url = "https://files.pythonhosted.org/packages/c8/a1/da3246e6ef2ae0e842bca4058b25c54bee55ab058ffff4ee54e72517ec01/ty-0.0.84-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a05d1d53db8b64410ab38c6e32c5898510584869d1d5dd9c0605db81c9aef7df", size = 15027731, upload-time = "2026-09-24T13:15:49.755Z" },
{ url = "https://files.pythonhosted.org/packages/20/17/b0099098a560aeb4f9fde6c912f9a81622c3e44e6555e1fbe322b368ec31/ty-0.0.84-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b92400494ab855cfb1204ac1101e3f53b2d09a8e21d171758b2cf9acdab1809e", size = 14748260, upload-time = "2026-09-24T13:15:52.713Z" },
{ url = "https://files.pythonhosted.org/packages/60/d5/32cd67aedb271f006e716ad093806c96c5d7e2af86be8255469dbd3d76c8/ty-0.0.84-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af17eb391ae3027fed9be1780bea555c2b8a25ba68e184c627b4981b2c9eaab7", size = 14205858, upload-time = "2026-09-24T13:15:55.677Z" },
{ url = "https://files.pythonhosted.org/packages/43/c4/638ac62ca2e8eca1b92e3e16273085744fada728b993500819b5c258ca15/ty-0.0.84-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:44cf06af0e7ec78ea6d8ff33a3450fc19627756a4fba681f7410d4e3ef63047a", size = 14573196, upload-time = "2026-09-24T13:15:59.165Z" },
{ url = "https://files.pythonhosted.org/packages/a6/f6/9ee81c5d8921e5fd5f10889ae563c95cd3272b31df2ada528919ca1cef6b/ty-0.0.84-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c6e56b443ff9ba462e34bfbc1e582004c2719ed35f8f93a433744b0ba0afb2d9", size = 13480760, upload-time = "2026-09-24T13:16:02.313Z" },
{ url = "https://files.pythonhosted.org/packages/f6/83/fbe5d1177667ae16d84c3242846b143809c9cc09568b333e5a9b4d5908f6/ty-0.0.84-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b6562fcc48820c1030e2a4509ef2c14ef93043ca4860280074314ac3a825b95", size = 13696346, upload-time = "2026-09-24T13:16:05.391Z" },
{ url = "https://files.pythonhosted.org/packages/86/9a/1b4ac9ddc34cc0ab4624bc219825d66af52f1ad87f4778ad08ad03fa06d5/ty-0.0.84-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dee7421451efcbd70f03e95a8f2c8d9e5ec3d35edcd27b4095ee00ee062abfc4", size = 13959410, upload-time = "2026-09-24T13:16:08.661Z" },
{ url = "https://files.pythonhosted.org/packages/c9/04/70e289437a67dfd686056ab4fd91880261a8233033a6a95d29393741fb97/ty-0.0.84-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:31e96307cf621babe969307dd657783d672e2d8bdbd06493710da635bf63fa07", size = 14350294, upload-time = "2026-09-24T13:16:11.865Z" },
{ url = "https://files.pythonhosted.org/packages/9c/f4/ae7dbd118425c850981d23efb850f0d9d7f6b8d2b852bde2767434f668b4/ty-0.0.84-py3-none-win32.whl", hash = "sha256:4bdc85f91cbaae35825f2b17bb4ac5de0563367875cb0f42b2bf07a1bf7ff2ba", size = 13176439, upload-time = "2026-09-24T13:16:15.049Z" },
{ url = "https://files.pythonhosted.org/packages/29/ec/994d87252f065dda5a500bc8afc726d18f6582d81d6f4ff1feb8a267c800/ty-0.0.84-py3-none-win_amd64.whl", hash = "sha256:71cc9aa7a7c89d4e12c6a814e9c0c3310ad5bee44efedbd6f5a42d91e9ac0f0d", size = 13962879, upload-time = "2026-09-24T13:16:18.191Z" },
{ url = "https://files.pythonhosted.org/packages/6d/1c/e6e91852b72566b1ab9aca504712857dfb89324c12092a5bd61d42d34427/ty-0.0.84-py3-none-win_arm64.whl", hash = "sha256:6c9d3718c4a0d318bc9c92af9b2aa85c3294e7dff54cf1d69ad79568f56516da", size = 13656453, upload-time = "2026-09-24T13:16:21.51Z" },
]
[[package]]
@@ -2243,11 +2242,11 @@ wheels = [
[[package]]
name = "urllib3"
version = "2.7.0"
version = "2.8.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
{ url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" },
]
[[package]]
@@ -2376,7 +2375,7 @@ wheels = [
[[package]]
name = "virtualenv"
version = "21.2.4"
version = "21.7.13"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "distlib" },
@@ -2385,9 +2384,9 @@ dependencies = [
{ name = "python-discovery" },
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0c/98/3a7e644e19cb26133488caff231be390579860bbbb3da35913c49a1d0a46/virtualenv-21.2.4.tar.gz", hash = "sha256:b294ef68192638004d72524ce7ef303e9d0cf5a44c95ce2e54a7500a6381cada", size = 5850742, upload-time = "2026-04-14T22:15:31.438Z" }
sdist = { url = "https://files.pythonhosted.org/packages/13/50/c9b84eb106d0db420b9878dac0a386c5791726f127ce20b06897f6e3a1e9/virtualenv-21.7.13.tar.gz", hash = "sha256:0355558b6f33619aab31347e43643b0ebc97f61ea3acf617b2b69e1f8a843d11", size = 5360306, upload-time = "2026-09-18T04:35:49.354Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/27/8d/edd0bd910ff803c308ee9a6b7778621af0d10252219ad9f19ef4d4982a61/virtualenv-21.2.4-py3-none-any.whl", hash = "sha256:29d21e941795206138d0f22f4e45ff7050e5da6c6472299fb7103318763861ac", size = 5831232, upload-time = "2026-04-14T22:15:29.342Z" },
{ url = "https://files.pythonhosted.org/packages/9a/ce/e74453531b0c49a58d0e8a4f9bab4495705859fee4a4f7de27d58f4a791a/virtualenv-21.7.13-py3-none-any.whl", hash = "sha256:1bea5af7463f59c4719db48fe739579a2a4f569c96f26c086edda85c96da9f59", size = 5328680, upload-time = "2026-09-18T04:35:47.194Z" },
]
[[package]]
@@ -23,6 +23,9 @@ RETURN = sys.intern("__return__")
# for writes of a task where we simply record the return value
PREVIOUS = sys.intern("__previous__")
# the implicit branch that handles each node's Control values
SNAPSHOT_BUMPS = sys.intern("__snapshot_bumps__")
# `versions_seen` key recording which entries a snapshot-only version bump
# advanced, and the versions those nodes really read
# --- Reserved cache namespaces ---
@@ -116,6 +119,7 @@ RESERVED = {
ERROR,
ERROR_SOURCE_NODE,
NO_WRITES,
SNAPSHOT_BUMPS,
# reserved config.configurable keys
CONFIG_KEY_SEND,
CONFIG_KEY_READ,
+1 -1
View File
@@ -235,7 +235,7 @@ def add_messages(
if format == "langchain-openai":
merged = _format_messages(merged)
elif format:
elif cast(str | None, format):
msg = f"Unrecognized {format=}. Expected one of 'langchain-openai', None."
raise ValueError(msg)
else:
+203 -51
View File
@@ -3,18 +3,31 @@ from __future__ import annotations
import uuid
from collections.abc import Callable, Iterable, Mapping
from datetime import datetime, timezone
from typing import Any, cast
from typing import Any, Literal, cast
from langchain_core.runnables import RunnableConfig
from langgraph.checkpoint.base import (
BaseCheckpointSaver,
ChannelVersions,
Checkpoint,
CheckpointTuple,
PendingWrite,
)
from langgraph.checkpoint.base.id import uuid6
from langgraph.checkpoint.serde.types import _DeltaSnapshot
from langgraph._internal._config import DELTA_MAX_SUPERSTEPS_SINCE_SNAPSHOT
from langgraph._internal._constants import PUSH
from langgraph._internal._config import (
DELTA_MAX_SUPERSTEPS_SINCE_SNAPSHOT,
patch_configurable,
)
from langgraph._internal._constants import (
CONF,
CONFIG_KEY_CHECKPOINT_ID,
NS_END,
NS_SEP,
PUSH,
SNAPSHOT_BUMPS,
)
from langgraph._internal._typing import MISSING
from langgraph.channels.base import BaseChannel
from langgraph.channels.delta import DeltaChannel
@@ -50,17 +63,23 @@ def exit_delta_task_id(step: int, task_id: str) -> str:
def delta_channels_to_snapshot(
channels: Mapping[str, BaseChannel],
counters_since_delta_snapshot: Mapping[str, tuple[int, int]],
channel_versions: ChannelVersions,
) -> set[str]:
"""Return the set of DeltaChannel names that should snapshot now.
A channel snapshots when EITHER its accumulated update count reaches
`snapshot_frequency` OR the total supersteps since its last snapshot
reaches `DELTA_MAX_SUPERSTEPS_SINCE_SNAPSHOT`. This is a pure
predicate — no mutation.
reaches `DELTA_MAX_SUPERSTEPS_SINCE_SNAPSHOT`. A channel without a version
was never written on this branch, so it has nothing to snapshot. This is a
pure predicate — no mutation.
"""
result: set[str] = set()
for name, ch in channels.items():
if not isinstance(ch, DeltaChannel) or not ch.is_available():
if (
not isinstance(ch, DeltaChannel)
or not ch.is_available()
or name not in channel_versions
):
continue
updates, supersteps = counters_since_delta_snapshot.get(name, (0, 0))
if (
@@ -80,15 +99,63 @@ def get_updated_channels_from_tasks(
def get_delta_channels_from_all_channels(
channels: Mapping[str, BaseChannel],
channel_versions: ChannelVersions,
) -> set[str]:
"""DeltaChannels to snapshot on the first update_state of a fresh thread."""
"""DeltaChannels to snapshot on the first update_state of a fresh thread:
the ones it wrote, as the rest have no version and nothing to store."""
return {
k
for k, ch in channels.items()
if isinstance(ch, DeltaChannel) and ch.is_available()
if isinstance(ch, DeltaChannel) and ch.is_available() and k in channel_versions
}
def delta_channels_with_pending_writes(
specs: Mapping[str, Any],
pending_writes: Iterable[PendingWrite] | None,
) -> set[str]:
"""DeltaChannels a branch starting from this checkpoint must snapshot.
A checkpoint's pending writes belong to the child that consumed them, and
nothing records which child that was. A new branch snapshots every delta
channel they touch, so its ancestor walk never replays them.
"""
return {
ch
for _, ch, _ in pending_writes or ()
if isinstance(specs.get(ch), DeltaChannel)
}
def checkpoint_superseded(
saver: BaseCheckpointSaver, config: RunnableConfig, saved: CheckpointTuple
) -> bool:
"""Whether the thread has moved past `saved`, the checkpoint `config` addressed.
A checkpoint with a child is never the latest put, so this misses none. A
leaf of an abandoned branch counts as well; telling it apart would mean
listing the thread to look for children, which the saver can't do cheaply.
"""
if not config[CONF].get(CONFIG_KEY_CHECKPOINT_ID):
return False
latest = saver.get_tuple(
patch_configurable(config, {CONFIG_KEY_CHECKPOINT_ID: None})
)
return latest is not None and latest.checkpoint["id"] != saved.checkpoint["id"]
async def acheckpoint_superseded(
saver: BaseCheckpointSaver, config: RunnableConfig, saved: CheckpointTuple
) -> bool:
"""Async `checkpoint_superseded`."""
if not config[CONF].get(CONFIG_KEY_CHECKPOINT_ID):
return False
latest = await saver.aget_tuple(
patch_configurable(config, {CONFIG_KEY_CHECKPOINT_ID: None})
)
return latest is not None and latest.checkpoint["id"] != saved.checkpoint["id"]
def create_metadata_for_update_state_api(
channels: Mapping[str, BaseChannel],
updated_channels: set[str],
@@ -118,26 +185,34 @@ def create_checkpoint_plan_for_update_state_api(
channels: Mapping[str, BaseChannel],
updated_channels: set[str],
*,
source: Literal["update", "input"],
step: int,
parents: dict[str, Any],
saved_metadata: Mapping[str, Any] | None,
is_fresh_thread: bool,
fork_channels: set[str],
channel_versions: ChannelVersions,
) -> tuple[set[str], dict[str, Any]]:
"""Return ``(channels_to_snapshot, metadata)`` for an update_state head."""
metadata: dict[str, Any] = {
"source": "update",
"source": source,
"step": step,
"parents": parents,
}
if is_fresh_thread:
return get_delta_channels_from_all_channels(channels), metadata
return get_delta_channels_from_all_channels(
channels, channel_versions
), metadata
new_counters = create_metadata_for_update_state_api(
channels,
updated_channels,
prev_metadata=saved_metadata,
)
channels_to_snapshot = delta_channels_to_snapshot(channels, new_counters)
channels_to_snapshot = (
delta_channels_to_snapshot(channels, new_counters, channel_versions)
| fork_channels
)
for k in channels_to_snapshot:
new_counters[k] = (0, 0)
non_zero = {k: v for k, v in new_counters.items() if v != (0, 0)}
@@ -155,6 +230,7 @@ def create_checkpoint(
updated_channels: set[str] | None = None,
get_next_version: GetNextVersion | None = None,
channels_to_snapshot: set[str] | None = None,
stored_versions: ChannelVersions | None = None,
) -> Checkpoint:
"""Build a new Checkpoint from the previous one and live channel state.
@@ -164,9 +240,14 @@ def create_checkpoint(
from `checkpoint_writes`. Callers compute the set via
`delta_channels_to_snapshot(channels, counters)`; defaults to empty
(no snapshots) when not provided.
`stored_versions` are the channel versions of the last checkpoint the
saver stored. A snapshotted channel whose version has not moved since
then is bumped.
"""
ts = datetime.now(timezone.utc).isoformat()
channels_to_snapshot = channels_to_snapshot or set()
bumped: dict[str, tuple[Any, Any]] = {}
if channels is None:
values = checkpoint["channel_values"]
channel_versions = checkpoint["channel_versions"]
@@ -174,30 +255,29 @@ def create_checkpoint(
values = {}
channel_versions = dict(checkpoint["channel_versions"])
for k in channels:
if k not in channel_versions:
continue
ch = channels[k]
if k not in channel_versions:
# A forced snapshot of a never-written channel still has to
# land to stop the ancestor walk, and `put` only stores blobs
# for versioned channels.
if k in channels_to_snapshot and get_next_version is not None:
channel_versions[k] = get_next_version(None, None)
bumped[k] = (None, channel_versions[k])
values[k] = _DeltaSnapshot(ch.get())
continue
if k in channels_to_snapshot:
# Callers force a full snapshot blob here: exit mode when a
# delta channel reaches its snapshot cadence, and update_state
# on a fresh thread (no ancestor to replay writes from). The
# manual version-bump below only applies to the exit-mode case.
#
# In exit mode, the snapshot decision is deferred to exit
# time (intermediate steps have do_checkpoint=False). The
# channel's count may have reached snapshot_frequency over
# several supersteps, but the LAST superstep may not have
# written to this channel. In that case apply_writes()
# (in _algo.py) didn't bump this channel's version, so
# saver.put() wouldn't include it in new_versions and
# the snapshot blob would be silently dropped. The manual
# bump below closes the gap. In sync/async durability this
# branch is effectively dead code (the step that pushes
# the count to freq always writes the channel).
if get_next_version is not None and (
updated_channels is None or k not in updated_channels
# `put` only stores a blob for a channel whose version moved,
# so snapshotting a channel this step did not write needs a
# bump: exit mode reaching the cadence on a superstep that
# skipped the channel, and a fork's first checkpoint.
if (
get_next_version is not None
and stored_versions is not None
and channel_versions[k] == stored_versions.get(k)
):
channel_versions[k] = get_next_version(channel_versions[k], None)
old = channel_versions[k]
channel_versions[k] = get_next_version(old, None)
bumped[k] = (old, channel_versions[k])
values[k] = _DeltaSnapshot(ch.get())
else:
v = ch.checkpoint()
@@ -209,21 +289,99 @@ def create_checkpoint(
id=id or str(uuid6(clock_seq=step)),
channel_values=values,
channel_versions=channel_versions,
versions_seen=checkpoint["versions_seen"],
versions_seen=_mark_bumps_seen(checkpoint["versions_seen"], bumped),
updated_channels=None if updated_channels is None else sorted(updated_channels),
)
def _needs_replay(spec: BaseChannel, stored: object) -> bool:
"""True if `spec` is a `DeltaChannel` and no value is stored at this
checkpoint, requiring an ancestor walk to reconstruct.
def _mark_bumps_seen(
versions_seen: dict[str, ChannelVersions],
bumped: Mapping[str, tuple[Any, Any]],
) -> dict[str, ChannelVersions]:
"""Advance whoever had seen a bumped channel's old version to the new one.
`_DeltaSnapshot` blobs and plain values (migration) resolve directly via
`from_checkpoint` — only absence (`MISSING`) triggers replay.
A bump that only stores a snapshot is not a write. Left unseen, it would
re-fire `interrupt_before` and rerun the channel's subscribers. For each
entry it advances, `SNAPSHOT_BUMPS` keeps the new version and the one the
node really read, so `versions_seen_without_bumps` can put the read back.
"""
if not isinstance(spec, DeltaChannel):
return False
return stored is MISSING
if not bumped:
return versions_seen
out = dict(versions_seen)
marks = dict(versions_seen.get(SNAPSHOT_BUMPS, {}))
for node, seen in versions_seen.items():
if node == SNAPSHOT_BUMPS:
continue
for k, (old, new) in bumped.items():
if seen.get(k) != old:
continue
advanced, read = _bump_keys(node, k)
# If an earlier bump set `old`, the real read is already recorded.
if old is not None and marks.get(advanced) != old:
marks[read] = old
marks[advanced] = new
out[node] = {**out[node], k: new}
if marks:
out[SNAPSHOT_BUMPS] = marks
return out
def _bump_keys(node: str, channel: str) -> tuple[str, str]:
# Node names can't contain either separator, so the keys can't collide.
return f"{node}{NS_SEP}{channel}", f"{node}{NS_END}{channel}"
def versions_seen_without_bumps(
versions_seen: dict[str, ChannelVersions],
) -> dict[str, ChannelVersions]:
"""`versions_seen` as the nodes read it: an entry a bump advanced goes back
to the version the node really read, or away if it never read one."""
if not (marks := versions_seen.get(SNAPSHOT_BUMPS)):
return versions_seen
out: dict[str, ChannelVersions] = {}
for node, seen in versions_seen.items():
if node == SNAPSHOT_BUMPS:
continue
out[node] = {}
for k, v in seen.items():
advanced, read = _bump_keys(node, k)
if marks.get(advanced) != v:
out[node][k] = v
elif read in marks:
out[node][k] = marks[read]
return out
def _delta_channels_to_replay(
specs: Mapping[str, BaseChannel], checkpoint: Checkpoint
) -> list[str]:
"""DeltaChannels whose value at `checkpoint` the ancestor walk rebuilds.
A `_DeltaSnapshot` blob or a plain value (migration) resolves directly via
`from_checkpoint`, so only a channel with nothing stored here needs the
walk. A channel with no version was never written, so it is empty without
one; a walk for it would find no snapshot to stop at and read every
ancestor, every time the thread is loaded.
"""
return [
k
for k, spec in specs.items()
if isinstance(spec, DeltaChannel)
and k in checkpoint["channel_versions"]
and checkpoint["channel_values"].get(k, MISSING) is MISSING
]
def _require_saver_for_history(
delta_channels: list[str],
saver: BaseCheckpointSaver | None,
config: RunnableConfig | None,
) -> None:
if delta_channels and (saver is None or config is None):
raise ValueError(
f"DeltaChannel {delta_channels} has history to replay but no "
"checkpointer or config was passed to read it"
)
def channels_from_checkpoint(
@@ -251,11 +409,8 @@ def channels_from_checkpoint(
else:
managed_specs[k] = v
delta_channels: list[str] = [
k
for k, spec in channel_specs.items()
if _needs_replay(spec, checkpoint["channel_values"].get(k, MISSING))
]
delta_channels = _delta_channels_to_replay(channel_specs, checkpoint)
_require_saver_for_history(delta_channels, saver, config)
histories: Mapping[str, Any] = {}
if delta_channels and saver is not None and config is not None:
histories = saver.get_delta_channel_history(
@@ -293,11 +448,8 @@ async def achannels_from_checkpoint(
else:
managed_specs[k] = v
delta_channels: list[str] = [
k
for k, spec in channel_specs.items()
if _needs_replay(spec, checkpoint["channel_values"].get(k, MISSING))
]
delta_channels = _delta_channels_to_replay(channel_specs, checkpoint)
_require_saver_for_history(delta_channels, saver, config)
histories: Mapping[str, Any] = {}
if delta_channels and saver is not None and config is not None:
histories = await saver.aget_delta_channel_history(
+132 -60
View File
@@ -98,10 +98,13 @@ from langgraph.pregel._algo import (
)
from langgraph.pregel._checkpoint import (
achannels_from_checkpoint,
acheckpoint_superseded,
channels_from_checkpoint,
checkpoint_superseded,
copy_checkpoint,
create_checkpoint,
delta_channels_to_snapshot,
delta_channels_with_pending_writes,
empty_checkpoint,
exit_delta_task_id,
)
@@ -119,6 +122,7 @@ from langgraph.pregel._io import (
)
from langgraph.pregel._messages import ensure_message_ids
from langgraph.pregel._read import PregelNode
from langgraph.pregel._task_status import read_task_statuses
from langgraph.pregel._utils import get_new_channel_versions, is_xxh3_128_hexdigest
from langgraph.pregel.debug import (
map_debug_checkpoint,
@@ -222,10 +226,21 @@ class PregelLoop:
# under the saver's `ORDER BY task_id, idx` sorting.
_exit_delta_writes: list[tuple[int, str, str, Any]] | None = None
# Delta channels that saw an Overwrite since the last checkpoint. These
# channels must snapshot after live update applies overwrite semantics so
# sparse replay starts from the same post-overwrite value.
_delta_channels_with_overwrite: set[str]
# Delta channels that must snapshot at the next checkpoint, whatever their
# cadence counters say:
# * an Overwrite arrived since the last checkpoint, so sparse replay has to
# start from the post-overwrite value;
# * the checkpoint this run starts from has pending writes to them; see
# `delta_channels_with_pending_writes`.
_delta_channels_forced_snapshot: set[str]
# Set by `_first` for a resume: the writes it loaded with the checkpoint,
# which `after_tick` checks against the ones reapply handed back.
_resume_loaded_writes: Sequence[PendingWrite] = ()
# Tasks `_reapply_writes_to_succeeded_nodes` handed loaded writes back to.
_reapplied_task_ids: set[str]
# An update or fork checkpoint addressed by `checkpoint_id` that the thread
# has moved past, so it may already have children.
_addressed_checkpoint_superseded: bool = False
# The checkpoint_config that points at the parent loaded at `__enter__`
# (or the synthetic-empty checkpoint, on first run). We capture it
@@ -581,7 +596,7 @@ class PregelLoop:
# save the new task
self.tasks[pushed.id] = pushed
# match any pending writes to the new task
if not self.is_replaying:
if self._reapplies_pending_writes:
self._reapply_writes_to_succeeded_nodes({pushed.id: pushed})
# return the new task, to be started if not run before
return pushed
@@ -659,7 +674,7 @@ class PregelLoop:
return False
# if there are pending writes from a previous loop, apply them
if not self.is_replaying and self.checkpoint_pending_writes:
if self._reapplies_pending_writes and self.checkpoint_pending_writes:
self._reapply_writes_to_succeeded_nodes(self.tasks)
self._resume_error_handlers_if_applicable()
@@ -683,11 +698,26 @@ class PregelLoop:
def after_tick(self) -> None:
# finish superstep
writes = [w for t in self.tasks.values() for w in t.writes]
self._delta_channels_with_overwrite.update(
self._delta_channels_forced_snapshot.update(
ch
for ch, v in writes
if isinstance(self.specs.get(ch), DeltaChannel) and _get_overwrite(v)[0]
)
if self._resume_loaded_writes:
# A loaded write reapply didn't hand back belongs to a task this run
# drops or reruns: a `Send` that `Command(goto=...)` replaced, or an
# error handler that runs again.
self._delta_channels_forced_snapshot.update(
delta_channels_with_pending_writes(
self.specs,
[
w
for w in self._resume_loaded_writes
if w[0] not in self._reapplied_task_ids
],
)
)
self._resume_loaded_writes = ()
# all tasks have finished
self.updated_channels = apply_writes(
self.checkpoint,
@@ -733,20 +763,24 @@ class PregelLoop:
# private
@property
def _reapplies_pending_writes(self) -> bool:
"""Whether the writes loaded with the checkpoint go back to the tasks
that made them, instead of those tasks rerunning."""
return not self.is_replaying
def _reapply_writes_to_succeeded_nodes(
self, tasks: Mapping[str, PregelExecutableTask]
) -> None:
"""Restore successful channel writes from checkpoint to in-memory tasks.
"""Restore the output of finished tasks from checkpoint to in-memory tasks.
Skips control signals (ERROR, ERROR_SOURCE_NODE, INTERRUPT, RESUME)
so that failed/interrupted tasks remain with empty writes and will be
re-executed (or routed to error handlers) by the runner.
Unfinished (failed or interrupted) tasks keep empty writes, so the
runner re-executes them or routes them to error handlers.
"""
for tid, k, v in self.checkpoint_pending_writes:
if k in (ERROR, ERROR_SOURCE_NODE, INTERRUPT, RESUME):
continue
for tid, status in read_task_statuses(self.checkpoint_pending_writes).items():
if task := tasks.get(tid):
task.writes.append((k, v))
task.writes.extend(status.output)
self._reapplied_task_ids.add(tid)
def _resume_error_handlers_if_applicable(self) -> None:
"""On resume, schedule error handlers for tasks that failed in a prior run.
@@ -816,35 +850,13 @@ class PregelLoop:
self.tasks[handler_task.id] = handler_task
def _pending_interrupts(self) -> set[str]:
"""Return the set of interrupt ids that are pending without corresponding resume values."""
# mapping of task ids to interrupt ids
pending_interrupts: dict[str, str] = {}
# set of resume task ids
pending_resumes: set[str] = set()
for task_id, write_type, value in self.checkpoint_pending_writes:
if write_type == INTERRUPT:
# interrupts is always a list, but there should only be one element
pending_interrupts[task_id] = value[0].id
elif write_type == RESUME:
pending_resumes.add(task_id)
resumed_interrupt_ids = {
pending_interrupts[task_id]
for task_id in pending_resumes
if task_id in pending_interrupts
"""Return the ids of interrupts that are still waiting for an answer."""
return {
interrupt.id
for status in read_task_statuses(self.checkpoint_pending_writes).values()
for interrupt in status.pending_interrupts
}
# Keep only interrupts whose interrupt_id is not resumed
hanging_interrupts: set[str] = {
interrupt_id
for interrupt_id in pending_interrupts.values()
if interrupt_id not in resumed_interrupt_ids
}
return hanging_interrupts
def _first(
self, *, input_keys: str | Sequence[str], updated_channels: set[str] | None
) -> set[str] | None:
@@ -898,6 +910,39 @@ class PregelLoop:
self.checkpoint_pending_writes = [
w for w in self.checkpoint_pending_writes if w[1] != RESUME
]
# The parent checkpoint subgraphs replay from, when a fork below would
# otherwise move it
replay_bound: RunnableConfig | None = None
# Whether this run saves a fork checkpoint (below) to start its branch.
# The fork carries a `Command`'s writes itself, so nothing this run
# writes is stored on the checkpoint it addressed, which may have
# children that replay it.
forks = (
is_resuming
and is_time_traveling
and (
self.checkpoint_metadata.get("source") not in ("update", "fork")
or self._addressed_checkpoint_superseded
)
)
carried: list[PendingWrite] = []
# A resume that reapplies the head's pending writes only learns which
# of them go back to their tasks once those are scheduled, so
# `after_tick` seals the rest. Kept apart from the writes this run adds.
reapplies = is_resuming and self._reapplies_pending_writes
self._resume_loaded_writes = (
[w for w in self.checkpoint_pending_writes if w[0] != NULL_TASK_ID]
if reapplies
else ()
)
self._reapplied_task_ids = set()
self._delta_channels_forced_snapshot = (
set()
if reapplies
else delta_channels_with_pending_writes(
self.specs, self.checkpoint_pending_writes
)
)
# map command to writes
if input_is_command:
@@ -928,10 +973,18 @@ class PregelLoop:
raise EmptyInputError("Received empty Command input")
# save writes
for tid, ws in writes.items():
self.put_writes(tid, ws)
if forks:
carried.extend((tid, c, v) for c, v in ws)
else:
self.put_writes(tid, ws)
self._delta_channels_forced_snapshot.update(
delta_channels_with_pending_writes(self.specs, carried)
)
# apply NULL writes
if null_writes := [
w[1:] for w in self.checkpoint_pending_writes if w[0] == NULL_TASK_ID
w[1:]
for w in (*self.checkpoint_pending_writes, *carried)
if w[0] == NULL_TASK_ID
]:
null_updated_channels = apply_writes(
self.checkpoint,
@@ -956,11 +1009,15 @@ class PregelLoop:
# the parent's latest checkpoint remains the old one and
# subsequent resumes load the wrong state.
# Skip for update_state forks (source=update/fork) since they
# already have their own fork checkpoint.
if is_time_traveling and self.checkpoint_metadata.get("source") not in (
"update",
"fork",
):
# already have their own fork checkpoint, unless the thread moved
# past it: its other children would replay whatever this run
# stores on it.
if forks:
if (
self.checkpoint_metadata.get("source") in ("update", "fork")
and self.prev_checkpoint_config
):
replay_bound = self.prev_checkpoint_config
# Clear old INTERRUPT writes from the loaded checkpoint.
# The fork will have a new checkpoint_id which changes
# task IDs — stale interrupt writes would accumulate and
@@ -991,7 +1048,7 @@ class PregelLoop:
manager=None,
updated_channels=updated_channels,
)
self._delta_channels_with_overwrite.update(
self._delta_channels_forced_snapshot.update(
c
for c, v in input_writes
if isinstance(self.specs.get(c), DeltaChannel) and _get_overwrite(v)[0]
@@ -1053,7 +1110,11 @@ class PregelLoop:
replay_state: ReplayState | None = None
if is_time_traveling:
replay_checkpoint_id = self.checkpoint["id"]
if (
if replay_bound is not None:
replay_checkpoint_id = replay_bound[CONF].get(
CONFIG_KEY_CHECKPOINT_ID, replay_checkpoint_id
)
elif (
self.checkpoint_metadata.get("source")
in (
"update",
@@ -1135,8 +1196,10 @@ class PregelLoop:
)
# create new checkpoint
channels_to_snapshot = (
delta_channels_to_snapshot(self.channels, new_counters)
| self._delta_channels_with_overwrite
delta_channels_to_snapshot(
self.channels, new_counters, self.checkpoint["channel_versions"]
)
| self._delta_channels_forced_snapshot
if do_checkpoint
else set()
)
@@ -1150,11 +1213,12 @@ class PregelLoop:
if do_checkpoint
else None,
channels_to_snapshot=channels_to_snapshot,
stored_versions=self.checkpoint_previous_versions,
)
for k in channels_to_snapshot:
new_counters[k] = (0, 0)
if do_checkpoint:
self._delta_channels_with_overwrite.difference_update(channels_to_snapshot)
self._delta_channels_forced_snapshot.difference_update(channels_to_snapshot)
non_zero = {k: v for k, v in new_counters.items() if v != (0, 0)}
if non_zero:
self.checkpoint_metadata["counters_since_delta_snapshot"] = non_zero
@@ -1238,8 +1302,10 @@ class PregelLoop:
self.checkpoint_metadata.get("counters_since_delta_snapshot") or {}
)
channels_to_snapshot = (
delta_channels_to_snapshot(self.channels, counters)
| self._delta_channels_with_overwrite
delta_channels_to_snapshot(
self.channels, counters, self.checkpoint["channel_versions"]
)
| self._delta_channels_forced_snapshot
)
pending = [
@@ -1600,7 +1666,7 @@ class SyncPregelLoop(PregelLoop, AbstractContextManager):
if handler_task is None:
return None
self.tasks[handler_task.id] = handler_task
if not self.is_replaying:
if self._reapplies_pending_writes:
self._reapply_writes_to_succeeded_nodes({handler_task.id: handler_task})
for task in self.match_cached_writes():
self.output_writes(task.id, task.writes, cached=True)
@@ -1635,6 +1701,10 @@ class SyncPregelLoop(PregelLoop, AbstractContextManager):
# This covers both normal replay and subgraphs resolved via
# checkpoint_map during time-travel.
saved = self.checkpointer.get_tuple(self.checkpoint_config)
if saved is not None and saved.metadata.get("source") in ("update", "fork"):
self._addressed_checkpoint_superseded = checkpoint_superseded(
self.checkpointer, self.checkpoint_config, saved
)
elif replay_state := self.config[CONF].get(CONFIG_KEY_REPLAY_STATE):
# Subgraph replay: the parent is replaying and passed us a
# replay_state with its checkpoint_id. Look up our checkpoint
@@ -1684,7 +1754,6 @@ class SyncPregelLoop(PregelLoop, AbstractContextManager):
)
self._delta_write_futs = []
self._error_handler_write_futs = []
self._delta_channels_with_overwrite = set()
self._exit_delta_writes = (
[] if self.durability == "exit" and self.checkpointer is not None else None
)
@@ -1855,7 +1924,7 @@ class AsyncPregelLoop(PregelLoop, AbstractAsyncContextManager):
if handler_task is None:
return None
self.tasks[handler_task.id] = handler_task
if not self.is_replaying:
if self._reapplies_pending_writes:
self._reapply_writes_to_succeeded_nodes({handler_task.id: handler_task})
for task in await self.amatch_cached_writes():
self.output_writes(task.id, task.writes, cached=True)
@@ -1893,6 +1962,10 @@ class AsyncPregelLoop(PregelLoop, AbstractAsyncContextManager):
# This covers both normal replay and subgraphs resolved via
# checkpoint_map during time-travel.
saved = await self.checkpointer.aget_tuple(self.checkpoint_config)
if saved is not None and saved.metadata.get("source") in ("update", "fork"):
self._addressed_checkpoint_superseded = await acheckpoint_superseded(
self.checkpointer, self.checkpoint_config, saved
)
elif replay_state := self.config[CONF].get(CONFIG_KEY_REPLAY_STATE):
# Subgraph replay: the parent is replaying and passed us a
# replay_state with its checkpoint_id. Look up our checkpoint
@@ -1942,7 +2015,6 @@ class AsyncPregelLoop(PregelLoop, AbstractAsyncContextManager):
)
self._delta_write_futs = []
self._error_handler_write_futs = []
self._delta_channels_with_overwrite = set()
self._exit_delta_writes = (
[] if self.durability == "exit" and self.checkpointer is not None else None
)
+4 -2
View File
@@ -45,6 +45,7 @@ from langgraph.errors import GraphBubbleUp, GraphInterrupt
from langgraph.pregel._algo import Call
from langgraph.pregel._executor import Submit
from langgraph.pregel._retry import arun_with_retry, run_with_retry
from langgraph.pregel._task_status import CONTROL_WRITES
from langgraph.types import (
CachePolicy,
PregelExecutableTask,
@@ -606,8 +607,9 @@ class PregelRunner:
task.config is None or TAG_HIDDEN not in task.config.get("tags", [])
):
self.node_finished(task.name)
if not task.writes:
# add no writes marker
if all(chan in CONTROL_WRITES for chan, _ in task.writes):
# record that the task finished, even if it produced no output
# (see `langgraph.pregel._task_status`)
task.writes.append((NO_WRITES, None))
# save task writes to checkpointer
self.put_writes()(task.id, task.writes) # type: ignore[misc]
@@ -0,0 +1,129 @@
"""Read the status of each task from the writes recorded for a superstep.
While a superstep is open, the checkpointer keeps a log of writes for each
task in that step. Entries are added as tasks run and are only discarded when
the whole superstep finishes and a new checkpoint is saved. When a task runs
again, for example after being resumed, its earlier entries stay in the log.
This module is the single place that turns that log into task status. Code that
needs to know whether a task finished, which interrupts it raised, which of them
are still waiting for an answer, or which output it produced must use
`read_task_statuses` instead of inspecting the writes directly.
The log uses two kinds of writes:
- Control writes describe what happened to a task: `INTERRUPT` (the task asked
a question), `RESUME` (answers the task has received), `ERROR`, and
`ERROR_SOURCE_NODE`. `INTERRUPT`, `RESUME` and `ERROR` each have a fixed slot
per task (`WRITES_IDX_MAP`), so a newer write of the same kind can replace an
older one.
- Every other write is output: channel writes, `RETURN` for functional tasks,
and the `NO_WRITES` marker.
The rules are:
1. When a task that ran finishes successfully, `PregelRunner.commit` records at
least one output write, adding `NO_WRITES` if the task produced no other
output.
2. A task that pauses at an interrupt records only control writes.
3. A task is therefore treated as finished if and only if it has an output
write.
4. Because `INTERRUPT` is stored in a fixed slot, its recorded value is the most
recent question the task asked. That question is waiting for an answer only
while the task is unfinished.
A `RESUME` write never means a task is finished: it can hold the answer to an
earlier question while the task waits on a later one.
What these rules cannot see:
- A task whose result came from the cache does not go through
`PregelRunner.commit`, so nothing is recorded for it. It reads as not
finished.
- A task that fails can record partial output writes along with its error. It
reads as finished, which is how the executor has always treated it.
- Writes recorded before rule 1 existed may describe a finished task with no
output using only control writes. Those tasks read as unfinished. The
executor treated them the same way before and runs them again. Their last
interrupt now counts as pending, so they appear in `next` and a resume
without an interrupt id raises if another interrupt is also pending.
"""
from __future__ import annotations
from collections.abc import Iterable, Sequence
from dataclasses import dataclass
from typing import Any
from langgraph.checkpoint.base import PendingWrite
from langgraph._internal._constants import (
ERROR,
ERROR_SOURCE_NODE,
INTERRUPT,
NULL_TASK_ID,
RESUME,
)
from langgraph.types import Interrupt
__all__ = ("CONTROL_WRITES", "TaskStatus", "read_task_statuses")
CONTROL_WRITES = frozenset((ERROR, ERROR_SOURCE_NODE, INTERRUPT, RESUME))
"""Channels that describe what happened to a task rather than what it produced."""
@dataclass(frozen=True, slots=True)
class TaskStatus:
"""The status of one task, read from the writes recorded for its superstep."""
output: tuple[tuple[str, Any], ...] = ()
"""Output writes in recorded order. Empty if the task has not finished."""
interrupts: tuple[Interrupt, ...] = ()
"""The most recent interrupts the task raised, whether or not they were answered."""
error: BaseException | None = None
"""The recorded error, if any."""
@property
def finished(self) -> bool:
"""Whether the task ran to completion."""
return bool(self.output)
@property
def pending_interrupts(self) -> tuple[Interrupt, ...]:
"""Interrupts waiting for an answer. Always empty for a finished task."""
return () if self.finished else self.interrupts
def read_task_statuses(
pending_writes: Iterable[PendingWrite],
) -> dict[str, TaskStatus]:
"""Return the status of every task that has recorded writes, keyed by task id.
Writes from `NULL_TASK_ID` are input to the superstep, not task activity, so
they are not included.
"""
output: dict[str, list[tuple[str, Any]]] = {}
interrupts: dict[str, list[Interrupt]] = {}
errors: dict[str, BaseException] = {}
for task_id, channel, value in pending_writes:
if task_id == NULL_TASK_ID:
continue
output.setdefault(task_id, [])
if channel == INTERRUPT:
interrupts.setdefault(task_id, []).extend(
value if isinstance(value, Sequence) else [value]
)
elif channel == ERROR:
errors.setdefault(task_id, value)
elif channel not in CONTROL_WRITES:
output[task_id].append((channel, value))
return {
task_id: TaskStatus(
output=tuple(task_output),
interrupts=tuple(interrupts.get(task_id, ())),
error=errors.get(task_id),
)
for task_id, task_output in output.items()
}
+18 -33
View File
@@ -26,6 +26,7 @@ from langgraph._internal._typing import MISSING
from langgraph.channels.base import BaseChannel
from langgraph.constants import TAG_HIDDEN
from langgraph.pregel._io import read_channels
from langgraph.pregel._task_status import TaskStatus, read_task_statuses
from langgraph.types import (
CheckpointPayload,
PregelExecutableTask,
@@ -37,6 +38,8 @@ from langgraph.types import (
TASK_NAMESPACE = UUID("6ba7b831-9dad-11d1-80b4-00c04fd430c8")
_NOT_STARTED = TaskStatus()
def map_debug_tasks(tasks: Iterable[PregelExecutableTask]) -> Iterator[TaskPayload]:
"""Produce "task" events for stream_mode=debug."""
@@ -211,35 +214,21 @@ def tasks_w_writes(
pending_writes: list[PendingWrite] | None,
states: dict[str, RunnableConfig | StateSnapshot] | None,
output_keys: str | Sequence[str],
*,
live: bool = False,
) -> tuple[PregelTask, ...]:
"""Apply writes / subgraph states to tasks to be returned in a StateSnapshot."""
pending_writes = pending_writes or []
"""Apply writes / subgraph states to tasks to be returned in a StateSnapshot.
With `live=True`, tasks report only the interrupts still waiting for an
answer, as of the most recent writes. Otherwise tasks report the interrupts
they raised in the step, including answered ones, as a record of the step.
"""
statuses = read_task_statuses(pending_writes or [])
out: list[PregelTask] = []
for task in tasks:
rtn = next(
(
val
for tid, chan, val in pending_writes
if tid == task.id and chan == RETURN
),
MISSING,
)
task_error = next(
(exc for tid, n, exc in pending_writes if tid == task.id and n == ERROR),
None,
)
task_interrupts = tuple(
v
for tid, n, vv in pending_writes
if tid == task.id and n == INTERRUPT
for v in (vv if isinstance(vv, Sequence) else [vv])
)
task_writes = [
(chan, val)
for tid, chan, val in pending_writes
if tid == task.id and chan not in (ERROR, INTERRUPT, RETURN)
]
status = statuses.get(task.id, _NOT_STARTED)
rtn = next((val for chan, val in status.output if chan == RETURN), MISSING)
task_writes = [(chan, val) for chan, val in status.output if chan != RETURN]
if rtn is not MISSING:
task_result = rtn
@@ -261,19 +250,15 @@ def tasks_w_writes(
mapped_writes = map_task_result_writes(filtered_writes)
task_result = mapped_writes if filtered_writes else {}
has_writes = rtn is not MISSING or any(
w[0] == task.id and w[1] not in (ERROR, INTERRUPT) for w in pending_writes
)
out.append(
PregelTask(
task.id,
task.name,
task.path,
task_error,
task_interrupts,
status.error,
status.pending_interrupts if live else status.interrupts,
states.get(task.id) if states else None,
task_result if has_writes else None,
task_result if status.finished else None,
)
)
return tuple(out)
File diff suppressed because it is too large Load Diff
+7 -1
View File
@@ -726,7 +726,13 @@ class StateSnapshot(NamedTuple):
tasks: tuple[PregelTask, ...]
"""Tasks to execute in this step. If already attempted, may contain an error."""
interrupts: tuple[Interrupt, ...]
"""Interrupts that occurred in this step that are pending resolution."""
"""Interrupts that occurred in this step.
When reading the latest state (`get_state` without a `checkpoint_id`), this
contains only interrupts still waiting for an answer. When reading a specific
checkpoint or state history, it contains the most recent interrupt each task
raised in that step, including ones answered later in the same step.
"""
class Send:
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "langgraph"
version = "1.2.12"
version = "1.2.13"
description = "Building stateful, multi-actor applications with LLMs"
authors = []
requires-python = ">=3.10"
+5 -3
View File
@@ -85,11 +85,13 @@ class MemorySaverAssertImmutable(InMemorySaver):
)
== saved
), config["configurable"]["checkpoint_ns"]
next_config = super().put(config, checkpoint, metadata, new_versions)
# Read back, not the object handed in: a DeltaChannel a step did not
# write is refilled on read from the blob its inherited version points at.
self.storage_for_copies[thread_id][checkpoint_ns][checkpoint["id"]] = (
self.serde.dumps_typed(checkpoint)
self.serde.dumps_typed(super().get(next_config))
)
# call super to write checkpoint
return super().put(config, checkpoint, metadata, new_versions)
return next_config
class MemorySaverNoPending(InMemorySaver):
@@ -0,0 +1,996 @@
"""Forking a thread must not replay the abandoned branch into the fork.
Every graph carries a `DeltaChannel` and a plain reducer channel fed the same
values; the plain channel needs no replay, so it is the oracle.
"""
import sys
import threading
from collections.abc import Sequence
from operator import add
from typing import Annotated, Any
import pytest
from langchain_core.runnables import RunnableConfig
from langgraph.checkpoint.base import BaseCheckpointSaver
from langgraph.checkpoint.serde.types import _DeltaSnapshot
from typing_extensions import TypedDict
from langgraph._internal._constants import INPUT
from langgraph.channels.delta import DeltaChannel
from langgraph.errors import NodeError
from langgraph.graph import END, START, StateGraph
from langgraph.types import (
Command,
Durability,
Send,
StateSnapshot,
StateUpdate,
interrupt,
)
pytestmark = pytest.mark.anyio
NEEDS_CONTEXTVARS = pytest.mark.skipif(
sys.version_info < (3, 11),
reason="Python 3.11+ is required for async contextvars support",
)
def _append(current: list | None, writes: Sequence[Any]) -> list:
out = list(current or [])
for write in writes:
out.extend(write if isinstance(write, list) else [write])
return out
class _State(TypedDict):
log: Annotated[list, DeltaChannel(_append, snapshot_frequency=1000)]
plain: Annotated[list, add]
other: Annotated[list, add]
def _build(checkpointer: BaseCheckpointSaver, tag: str) -> Any:
def node(state: _State) -> dict:
return {"log": [f"{tag}-out"], "plain": [f"{tag}-out"]}
builder = StateGraph(_State)
builder.add_node("n", node)
builder.set_entry_point("n")
builder.set_finish_point("n")
return builder.compile(checkpointer=checkpointer)
def _build_without_delta_writes(checkpointer: BaseCheckpointSaver, tag: str) -> Any:
def node(state: _State) -> dict:
return {"other": [f"{tag}-other"]}
builder = StateGraph(_State)
builder.add_node("n", node)
builder.set_entry_point("n")
builder.set_finish_point("n")
return builder.compile(checkpointer=checkpointer)
def _thread(thread_id: str) -> RunnableConfig:
return {"configurable": {"thread_id": thread_id}}
def _at(config: RunnableConfig, snapshot: StateSnapshot) -> RunnableConfig:
return {
"configurable": {
**config["configurable"],
"checkpoint_ns": "",
"checkpoint_id": snapshot.config["configurable"]["checkpoint_id"],
}
}
def _both(marker: str) -> dict:
return {"log": [marker], "plain": [marker]}
def _snapshotted_checkpoints(
checkpointer: BaseCheckpointSaver, config: RunnableConfig
) -> list[str]:
return [
tuple_.config["configurable"]["checkpoint_id"]
for tuple_ in checkpointer.list(config)
if isinstance(tuple_.checkpoint["channel_values"].get("log"), _DeltaSnapshot)
]
def _assert_fork_is_clean(state: StateSnapshot, abandoned: str) -> None:
assert state.values["log"] == state.values["plain"], (
f"delta channel diverged from the plain channel: "
f"{state.values['log']} != {state.values['plain']}"
)
assert abandoned not in state.values["log"], (
f"{abandoned!r} belongs to the branch the fork replaced, "
f"but was replayed into {state.values['log']}"
)
def test_fork_by_invoke(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
config = _thread("t")
_build(sync_checkpointer, "first").invoke(
_both("in-1"), config, durability=durability
)
graph = _build(sync_checkpointer, "second")
graph.invoke(_both("in-2"), config, durability=durability)
abandoned_head = graph.get_state(config)
base = next(
snapshot
for snapshot in graph.get_state_history(config)
if "in-2" not in snapshot.values["log"]
)
_build(sync_checkpointer, "third").invoke(
_both("in-3"), _at(config, base), durability=durability
)
state = graph.get_state(config)
_assert_fork_is_clean(state, "in-2")
assert state.values["log"] == [*base.values["log"], "in-3", "third-out"]
abandoned = graph.get_state(abandoned_head.config).values
assert abandoned["log"] == abandoned["plain"] == abandoned_head.values["log"]
async def test_afork_by_invoke(
async_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
config = _thread("t")
await _build(async_checkpointer, "first").ainvoke(
_both("in-1"), config, durability=durability
)
graph = _build(async_checkpointer, "second")
await graph.ainvoke(_both("in-2"), config, durability=durability)
abandoned_head = await graph.aget_state(config)
base = await anext(
snapshot
async for snapshot in graph.aget_state_history(config)
if "in-2" not in snapshot.values["log"]
)
await _build(async_checkpointer, "third").ainvoke(
_both("in-3"), _at(config, base), durability=durability
)
state = await graph.aget_state(config)
_assert_fork_is_clean(state, "in-2")
assert state.values["log"] == [*base.values["log"], "in-3", "third-out"]
abandoned = (await graph.aget_state(abandoned_head.config)).values
assert abandoned["log"] == abandoned["plain"] == abandoned_head.values["log"]
def test_fork_off_checkpoint_before_first_input(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
config = _thread("t")
graph = _build(sync_checkpointer, "first")
graph.invoke(_both("in-1"), config, durability=durability)
root = list(graph.get_state_history(config))[-1]
assert root.values["log"] == []
_build(sync_checkpointer, "third").invoke(
_both("in-9"), _at(config, root), durability=durability
)
state = graph.get_state(config)
_assert_fork_is_clean(state, "in-1")
assert state.values["log"] == ["in-9", "third-out"]
async def test_afork_off_checkpoint_before_first_input(
async_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
config = _thread("t")
graph = _build(async_checkpointer, "first")
await graph.ainvoke(_both("in-1"), config, durability=durability)
root = [snapshot async for snapshot in graph.aget_state_history(config)][-1]
assert root.values["log"] == []
await _build(async_checkpointer, "third").ainvoke(
_both("in-9"), _at(config, root), durability=durability
)
state = await graph.aget_state(config)
_assert_fork_is_clean(state, "in-1")
assert state.values["log"] == ["in-9", "third-out"]
def test_fork_by_update_state(sync_checkpointer: BaseCheckpointSaver) -> None:
config = _thread("t")
_build(sync_checkpointer, "first").invoke(_both("in-1"), config)
graph = _build(sync_checkpointer, "second")
graph.invoke(_both("in-2"), config)
base = next(
snapshot
for snapshot in graph.get_state_history(config)
if "in-2" not in snapshot.values["log"]
)
forked = graph.update_state(_at(config, base), _both("patched"))
state = graph.get_state(forked)
_assert_fork_is_clean(state, "in-2")
assert state.values["log"] == [*base.values["log"], "patched"]
async def test_afork_by_update_state(
async_checkpointer: BaseCheckpointSaver,
) -> None:
config = _thread("t")
await _build(async_checkpointer, "first").ainvoke(_both("in-1"), config)
graph = _build(async_checkpointer, "second")
await graph.ainvoke(_both("in-2"), config)
base = await anext(
snapshot
async for snapshot in graph.aget_state_history(config)
if "in-2" not in snapshot.values["log"]
)
forked = await graph.aupdate_state(_at(config, base), _both("patched"))
state = await graph.aget_state(forked)
_assert_fork_is_clean(state, "in-2")
assert state.values["log"] == [*base.values["log"], "patched"]
def _assert_branch_unchanged(state: StateSnapshot, expected: list, edit: str) -> None:
assert state.values["log"] == state.values["plain"] == expected, (
f"{edit!r} was written by an update_state on this branch's base, "
f"but this branch now reads {state.values['log']}"
)
# The old checkpoint is either a finished turn, which saved no writes, or one
# whose next node already ran there, so the edit reuses that task's id.
@pytest.mark.parametrize("next_node_ran", [False, True])
def test_update_state_on_an_old_checkpoint_leaves_its_other_branch_alone(
sync_checkpointer: BaseCheckpointSaver, next_node_ran: bool
) -> None:
config = _thread("t")
graph = _build(sync_checkpointer, "first")
graph.invoke(_both("in-1"), config)
_build(sync_checkpointer, "second").invoke(_both("in-2"), config)
branch = graph.get_state(config)
base = next(
snapshot
for snapshot in graph.get_state_history(config)
if "in-2" not in snapshot.values["log"]
and snapshot.next == (("n",) if next_node_ran else ())
)
edited = graph.update_state(_at(config, base), _both("edit"), as_node="n")
_assert_branch_unchanged(
graph.get_state(branch.config), branch.values["log"], "edit"
)
assert graph.get_state(edited).values["log"] == [*base.values["log"], "edit"]
_build(sync_checkpointer, "third").invoke(_both("in-3"), branch.config)
_assert_branch_unchanged(
graph.get_state(config),
[*branch.values["log"], "in-3", "third-out"],
"edit",
)
@pytest.mark.parametrize("next_node_ran", [False, True])
async def test_aupdate_state_on_an_old_checkpoint_leaves_its_other_branch_alone(
async_checkpointer: BaseCheckpointSaver, next_node_ran: bool
) -> None:
config = _thread("t")
graph = _build(async_checkpointer, "first")
await graph.ainvoke(_both("in-1"), config)
await _build(async_checkpointer, "second").ainvoke(_both("in-2"), config)
branch = await graph.aget_state(config)
base = await anext(
snapshot
async for snapshot in graph.aget_state_history(config)
if "in-2" not in snapshot.values["log"]
and snapshot.next == (("n",) if next_node_ran else ())
)
edited = await graph.aupdate_state(_at(config, base), _both("edit"), as_node="n")
_assert_branch_unchanged(
await graph.aget_state(branch.config), branch.values["log"], "edit"
)
assert (await graph.aget_state(edited)).values["log"] == [
*base.values["log"],
"edit",
]
await _build(async_checkpointer, "third").ainvoke(_both("in-3"), branch.config)
_assert_branch_unchanged(
await graph.aget_state(config),
[*branch.values["log"], "in-3", "third-out"],
"edit",
)
def test_bulk_update_on_an_old_checkpoint_leaves_its_other_branch_alone(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
config = _thread("t")
graph = _build(sync_checkpointer, "first")
graph.invoke(_both("in-1"), config)
base = graph.get_state(config)
_build(sync_checkpointer, "second").invoke(_both("in-2"), config)
branch = graph.get_state(config)
edited = graph.bulk_update_state(
_at(config, base),
[[StateUpdate(_both("s1"), "n")], [StateUpdate(_both("s2"), "n")]],
)
_assert_branch_unchanged(graph.get_state(branch.config), branch.values["log"], "s1")
assert graph.get_state(edited).values["log"] == [*base.values["log"], "s1", "s2"]
@pytest.mark.parametrize(
"edit", [_both("edit"), {"other": ["edit"]}], ids=["delta_and_plain", "plain_only"]
)
def test_clearing_an_old_checkpoint_does_not_pick_up_an_edit_of_it(
sync_checkpointer: BaseCheckpointSaver, edit: dict
) -> None:
graph = (
StateGraph(_State)
.add_node("a", lambda state: _both("a"))
.add_node("b", lambda state: _both("b"))
.add_edge(START, "a")
.add_edge("a", "b")
.compile(checkpointer=sync_checkpointer)
)
config = _thread("t")
graph.invoke(_both("in"), config, interrupt_before=["b"])
base = graph.get_state(config)
graph.update_state(config, _both("later"), as_node="a")
graph.update_state(base.config, edit, as_node="b")
cleared = graph.update_state(base.config, None, as_node=END)
values = graph.get_state(cleared).values
assert values["log"] == values["plain"] == ["in", "a"]
assert values["other"] == []
def test_clearing_a_checkpoint_after_editing_it_keeps_the_edit_in_both_channels(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
def q(state: _State) -> dict:
interrupt("continue?")
return _both("q")
graph = (
StateGraph(_State)
.add_node("p", lambda state: _both("p"))
.add_node("q", q)
.add_edge(START, "p")
.add_edge(START, "q")
.compile(checkpointer=sync_checkpointer)
)
config = _thread("t")
graph.invoke(_both("in"), config)
head = graph.get_state(config)
graph.update_state(head.config, _both("edit"), as_node="q")
cleared = graph.update_state(head.config, None, as_node=END)
state = graph.get_state(cleared)
assert state.values["log"] == state.values["plain"] == ["in", "p", "edit"]
def test_update_state_with_the_head_checkpoint_id_stores_no_snapshot(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
config = _thread("t")
graph = _build(sync_checkpointer, "first")
graph.invoke(_both("in-1"), config)
for i in range(3):
graph.update_state(graph.get_state(config).config, _both(f"u{i}"))
assert not _snapshotted_checkpoints(sync_checkpointer, config)
assert graph.get_state(config).values["log"] == [
"in-1",
"first-out",
"u0",
"u1",
"u2",
]
def test_unaddressed_run_keeps_snapshot_cadence(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
config = _thread("t")
graph = _build(sync_checkpointer, "first")
graph.invoke(_both("in-1"), config, durability=durability)
graph.invoke(_both("in-2"), config, durability=durability)
assert not _snapshotted_checkpoints(sync_checkpointer, config)
def test_fork_before_first_value_when_fork_never_writes_the_channel(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
config = _thread("t")
graph = _build(sync_checkpointer, "first")
graph.invoke(_both("in-1"), config, durability=durability)
root = list(graph.get_state_history(config))[-1]
assert root.values["log"] == []
_build_without_delta_writes(sync_checkpointer, "third").invoke(
{"other": ["in-9"]}, _at(config, root), durability=durability
)
state = graph.get_state(config)
_assert_fork_is_clean(state, "in-1")
assert state.values["log"] == []
async def test_afork_before_first_value_when_fork_never_writes_the_channel(
async_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
config = _thread("t")
graph = _build(async_checkpointer, "first")
await graph.ainvoke(_both("in-1"), config, durability=durability)
root = [snapshot async for snapshot in graph.aget_state_history(config)][-1]
assert root.values["log"] == []
await _build_without_delta_writes(async_checkpointer, "third").ainvoke(
{"other": ["in-9"]}, _at(config, root), durability=durability
)
state = await graph.aget_state(config)
_assert_fork_is_clean(state, "in-1")
assert state.values["log"] == []
def test_fork_before_first_value_by_bulk_update(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
config = _thread("t")
graph = _build(sync_checkpointer, "first")
graph.invoke(_both("in-1"), config)
root = list(graph.get_state_history(config))[-1]
assert root.values["log"] == []
forked = graph.bulk_update_state(
_at(config, root),
[
[StateUpdate({"other": ["s1"]}, "n")],
[StateUpdate(_both("s2"), "n")],
],
)
state = graph.get_state(forked)
_assert_fork_is_clean(state, "in-1")
assert state.values["log"] == ["s2"]
@pytest.mark.parametrize("first_as_node", [INPUT, END, "__copy__"])
def test_fork_by_bulk_update_whose_first_superstep_is_not_a_node(
sync_checkpointer: BaseCheckpointSaver, first_as_node: str
) -> None:
config = _thread("t")
_build(sync_checkpointer, "first").invoke(_both("in-1"), config)
graph = _build(sync_checkpointer, "second")
graph.invoke(_both("in-2"), config)
base = next(
snapshot
for snapshot in graph.get_state_history(config)
if "in-2" not in snapshot.values["log"]
)
first = (
StateUpdate(_both("first-step"), first_as_node)
if first_as_node == INPUT
else StateUpdate(None, first_as_node)
)
forked = graph.bulk_update_state(
_at(config, base),
[[first], [StateUpdate(_both("second-step"), "n")]],
)
state = graph.get_state(forked)
assert state.values["log"] == state.values["plain"], (
f"delta channel diverged from the plain channel: "
f"{state.values['log']} != {state.values['plain']}"
)
def test_bulk_update_after_a_copy_stores_no_snapshot(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
config = _thread("t")
_build(sync_checkpointer, "first").invoke(_both("in-1"), config)
graph = _build(sync_checkpointer, "second")
graph.invoke(_both("in-2"), config)
base = next(
s for s in graph.get_state_history(config) if "in-2" not in s.values["log"]
)
forked = graph.bulk_update_state(
_at(config, base),
[[StateUpdate(None, "__copy__")], [StateUpdate(_both("s2"), "n")]],
)
assert graph.get_state(forked).values["log"] == ["in-1", "first-out", "s2"]
assert not _snapshotted_checkpoints(sync_checkpointer, config)
def test_unaddressed_bulk_update_keeps_snapshot_cadence(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
config = _thread("t")
graph = _build(sync_checkpointer, "first")
graph.invoke(_both("in-1"), config)
graph.bulk_update_state(
config,
[[StateUpdate(_both(f"u{i}"), "n")] for i in range(4)],
)
assert not _snapshotted_checkpoints(sync_checkpointer, config)
def _build_two_steps(checkpointer: BaseCheckpointSaver, subgraph: bool) -> Any:
if subgraph:
inner = StateGraph(_State)
inner.add_node("b1", lambda state: _both("b1"))
inner.add_node("b2", lambda state: _both("b2"))
inner.add_edge(START, "b1")
inner.add_edge("b1", "b2")
second: Any = inner.compile()
else:
second = lambda state: _both("b") # noqa: E731
builder = StateGraph(_State)
builder.add_node("a", lambda state: _both("a"))
builder.add_node("b", second)
builder.add_edge(START, "a")
builder.add_edge("a", "b")
return builder.compile(checkpointer=checkpointer)
@pytest.mark.parametrize(
"replay_input", [None, Command(update=_both("cmd"))], ids=["none", "command"]
)
@pytest.mark.parametrize("subgraph", [False, True])
def test_replay_from_an_edit_the_thread_moved_past_leaves_its_branch_alone(
sync_checkpointer: BaseCheckpointSaver,
durability: Durability,
subgraph: bool,
replay_input: Command | None,
) -> None:
graph = _build_two_steps(sync_checkpointer, subgraph)
config = _thread("t")
graph.invoke(_both("in-1"), config, durability=durability)
edit = graph.update_state(config, _both("edit"), as_node="a")
graph.invoke(_both("in-2"), config, durability=durability)
branch = graph.get_state(config)
graph.invoke(replay_input, edit, durability=durability)
after = graph.get_state(branch.config).values
assert after["log"] == after["plain"] == branch.values["log"], (
f"a replay from the edit wrote into the branch that already grew from it: "
f"{after['log']}"
)
replay = graph.get_state(config).values
assert replay["log"] == replay["plain"]
@pytest.mark.parametrize(
"replay_input", [None, Command(update=_both("cmd"))], ids=["none", "command"]
)
@pytest.mark.parametrize("subgraph", [False, True])
async def test_areplay_from_an_edit_the_thread_moved_past_leaves_its_branch_alone(
async_checkpointer: BaseCheckpointSaver,
durability: Durability,
subgraph: bool,
replay_input: Command | None,
) -> None:
graph = _build_two_steps(async_checkpointer, subgraph)
config = _thread("t")
await graph.ainvoke(_both("in-1"), config, durability=durability)
edit = await graph.aupdate_state(config, _both("edit"), as_node="a")
await graph.ainvoke(_both("in-2"), config, durability=durability)
branch = await graph.aget_state(config)
await graph.ainvoke(replay_input, edit, durability=durability)
after = (await graph.aget_state(branch.config)).values
assert after["log"] == after["plain"] == branch.values["log"], (
f"a replay from the edit wrote into the branch that already grew from it: "
f"{after['log']}"
)
replay = (await graph.aget_state(config)).values
assert replay["log"] == replay["plain"]
@pytest.mark.parametrize(
"command",
[Command(update=_both("cmd")), Command(goto="a")],
ids=["update", "goto"],
)
def test_command_replay_of_an_old_checkpoint_stores_nothing_on_it(
sync_checkpointer: BaseCheckpointSaver, durability: Durability, command: Command
) -> None:
graph = _build_two_steps(sync_checkpointer, subgraph=False)
config = _thread("t")
graph.invoke(_both("in"), config, interrupt_before=["b"], durability=durability)
old = graph.get_state(config)
graph.invoke(None, config, durability=durability)
branch = graph.get_state(config)
graph.invoke(command, old.config, durability=durability)
after = graph.get_state(branch.config).values
assert after["log"] == after["plain"] == branch.values["log"]
graph.invoke(None, old.config, durability=durability)
replay = graph.get_state(config).values
assert replay["log"] == replay["plain"] == ["in", "a", "b"], (
f"a later replay of the checkpoint repeated the earlier Command: {replay}"
)
def _build_paused_before_b(checkpointer: BaseCheckpointSaver) -> Any:
builder = StateGraph(_State)
builder.add_node("a", lambda state: _both("a"))
builder.add_node("b", lambda state: _both("b"))
builder.add_edge(START, "a")
builder.add_edge("a", "b")
builder.add_edge("b", END)
return builder.compile(checkpointer=checkpointer, interrupt_before=["b"])
def _build_parallel_interrupt(checkpointer: BaseCheckpointSaver) -> Any:
def ask(state: _State) -> dict:
interrupt("approve?")
return {"other": ["q"]}
builder = StateGraph(_State)
builder.add_node("p", lambda state: _both("p"))
builder.add_node("q", ask)
builder.add_edge(START, "p")
builder.add_edge(START, "q")
return builder.compile(checkpointer=checkpointer)
def test_resume_at_interrupt_before_with_the_head_checkpoint_id_runs_the_node(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
config = _thread("t")
graph = _build_paused_before_b(sync_checkpointer)
graph.invoke(_both("in"), config, durability=durability)
graph.invoke(None, graph.get_state(config).config, durability=durability)
state = graph.get_state(config)
assert state.next == (), f"resume paused again before {state.next}"
assert state.values["log"] == state.values["plain"] == ["in", "a", "b"]
async def test_aresume_at_interrupt_before_with_the_head_checkpoint_id_runs_the_node(
async_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
config = _thread("t")
graph = _build_paused_before_b(async_checkpointer)
await graph.ainvoke(_both("in"), config, durability=durability)
await graph.ainvoke(
None, (await graph.aget_state(config)).config, durability=durability
)
state = await graph.aget_state(config)
assert state.next == (), f"resume paused again before {state.next}"
assert state.values["log"] == state.values["plain"] == ["in", "a", "b"]
def test_replay_from_a_paused_checkpoint_runs_the_node_once(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
config = _thread("t")
graph = _build_paused_before_b(sync_checkpointer)
graph.invoke(_both("in"), config)
paused = graph.get_state(config).config
graph.invoke(None, config)
graph.invoke(None, paused)
state = graph.get_state(config)
assert state.next == (), f"replay paused again before {state.next}"
assert state.values["log"] == state.values["plain"] == ["in", "a", "b"]
@pytest.mark.parametrize("addressed", [False, True])
def test_new_input_on_an_interrupted_head_does_not_replay_its_pending_writes(
sync_checkpointer: BaseCheckpointSaver, durability: Durability, addressed: bool
) -> None:
config = _thread("t")
graph = _build_parallel_interrupt(sync_checkpointer)
graph.invoke(_both("in-1"), config, durability=durability)
head = graph.get_state(config).config
graph.invoke(_both("in-2"), head if addressed else config, durability=durability)
state = graph.get_state(config)
assert state.values["log"] == state.values["plain"] == ["in-1", "in-2", "p"]
def _build_deferred_after_interrupt(checkpointer: BaseCheckpointSaver) -> Any:
builder = StateGraph(_State)
builder.add_node("a", lambda state: _both("a"))
builder.add_node("b", lambda state: _both("b"), defer=True)
builder.add_node("c", lambda state: {})
builder.add_edge(START, "a")
builder.add_edge("a", "b")
builder.add_edge("a", "c")
return builder.compile(checkpointer=checkpointer, interrupt_after=["a"])
@pytest.mark.parametrize(
"durability",
[
"sync",
"async",
pytest.param(
"exit",
marks=pytest.mark.xfail(
reason="exit durability stores a resumed run's loaded writes twice",
strict=True,
),
),
],
)
def test_resume_on_an_interrupted_head_consumes_its_writes_without_a_snapshot(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
config = _thread("t")
graph = _build_parallel_interrupt(sync_checkpointer)
graph.invoke(_both("in-1"), config, durability=durability)
graph.invoke(Command(resume="yes"), config, durability=durability)
state = graph.get_state(config)
assert state.next == ()
assert state.values["log"] == state.values["plain"] == ["in-1", "p"]
assert not _snapshotted_checkpoints(sync_checkpointer, config)
def test_resume_whose_node_writes_the_delta_channel_stores_no_snapshot(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
def ask(state: _State) -> dict:
return _both(interrupt("continue?"))
graph = (
StateGraph(_State)
.add_node("ask", ask)
.add_edge(START, "ask")
.compile(checkpointer=sync_checkpointer)
)
config = _thread("t")
graph.invoke(_both("in"), config, durability=durability)
graph.invoke(Command(resume="yes"), config, durability=durability)
state = graph.get_state(config)
assert state.values["log"] == state.values["plain"] == ["in", "yes"]
assert not _snapshotted_checkpoints(sync_checkpointer, config)
def test_resume_after_interrupt_before_stores_no_snapshot(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
config = _thread("t")
graph = _build(sync_checkpointer, "n")
graph.invoke(_both("in"), config, interrupt_before=["n"], durability=durability)
graph.invoke(None, config, durability=durability)
state = graph.get_state(config)
assert state.values["log"] == state.values["plain"] == ["in", "n-out"]
assert not _snapshotted_checkpoints(sync_checkpointer, config)
def _build_send_fan_out(checkpointer: BaseCheckpointSaver) -> Any:
def q(state: _State) -> dict:
interrupt("continue?")
return _both("q")
builder = StateGraph(_State)
builder.add_node("p", lambda state: _both("p"))
builder.add_node("q", q)
builder.add_conditional_edges(
START, lambda state: [Send("p", state), Send("q", state)], ["p", "q"]
)
return builder.compile(checkpointer=checkpointer)
def test_resume_that_replaces_the_pending_sends_drops_the_finished_task(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
graph = _build_send_fan_out(sync_checkpointer)
config = _thread("t")
graph.invoke(_both("in"), config, durability=durability)
live = graph.invoke(
Command(resume="yes", goto=[Send("q", _both("unused"))]),
config,
durability=durability,
)
state = graph.get_state(config)
assert state.values["log"] == state.values["plain"] == live["log"], (
f"'p' ran in the fan-out the resume replaced, but the reload reads "
f"{state.values['log']} against the live {live['log']}"
)
@NEEDS_CONTEXTVARS
async def test_aresume_that_replaces_the_pending_sends_drops_the_finished_task(
async_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
graph = _build_send_fan_out(async_checkpointer)
config = _thread("t")
await graph.ainvoke(_both("in"), config, durability=durability)
live = await graph.ainvoke(
Command(resume="yes", goto=[Send("q", _both("unused"))]),
config,
durability=durability,
)
state = await graph.aget_state(config)
assert state.values["log"] == state.values["plain"] == live["log"], (
f"'p' ran in the fan-out the resume replaced, but the reload reads "
f"{state.values['log']} against the live {live['log']}"
)
def test_replay_interrupted_in_its_first_step_still_seals_the_fork(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
graph = _build_send_fan_out(sync_checkpointer)
config = _thread("t")
graph.invoke(_both("in"), config, durability=durability)
graph.invoke(None, graph.get_state(config).config, durability=durability)
state = graph.get_state(config)
assert state.values["log"] == state.values["plain"] == ["in", "p"], (
f"the replay reran p, so the fork must not also replay the first p, "
f"but it reads {state.values['log']}"
)
@NEEDS_CONTEXTVARS
async def test_areplay_interrupted_in_its_first_step_still_seals_the_fork(
async_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
graph = _build_send_fan_out(async_checkpointer)
config = _thread("t")
await graph.ainvoke(_both("in"), config, durability=durability)
await graph.ainvoke(
None, (await graph.aget_state(config)).config, durability=durability
)
state = await graph.aget_state(config)
assert state.values["log"] == state.values["plain"] == ["in", "p"], (
f"the replay reran p, so the fork must not also replay the first p, "
f"but it reads {state.values['log']}"
)
def test_resume_addressed_at_an_interrupted_head_reruns_its_tasks_once(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
config = _thread("t")
graph = _build_parallel_interrupt(sync_checkpointer)
graph.invoke(_both("in-1"), config, durability=durability)
graph.invoke(
Command(resume="yes"), graph.get_state(config).config, durability=durability
)
state = graph.get_state(config)
assert state.next == ()
assert state.values["log"] == state.values["plain"] == ["in-1", "p"]
def test_update_state_with_the_head_checkpoint_id_keeps_a_deferred_node(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
graph = _build_deferred_after_interrupt(sync_checkpointer)
config = _thread("t")
graph.invoke(_both("in"), config)
graph.update_state(graph.get_state(config).config, _both("u"), as_node="c")
graph.invoke(None, config)
state = graph.get_state(config)
assert state.next == (), f"deferred node never ran, still pending: {state.next}"
assert state.values["log"] == state.values["plain"] == ["in", "a", "u", "b"]
async def test_aupdate_state_with_the_head_checkpoint_id_keeps_a_deferred_node(
async_checkpointer: BaseCheckpointSaver,
) -> None:
graph = _build_deferred_after_interrupt(async_checkpointer)
config = _thread("t")
await graph.ainvoke(_both("in"), config)
await graph.aupdate_state(
(await graph.aget_state(config)).config, _both("u"), as_node="c"
)
await graph.ainvoke(None, config)
state = await graph.aget_state(config)
assert state.next == (), f"deferred node never ran, still pending: {state.next}"
assert state.values["log"] == state.values["plain"] == ["in", "a", "u", "b"]
def test_turns_addressed_at_the_head_store_no_snapshot(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
config = _thread("t")
graph = _build(sync_checkpointer, "turn")
graph.invoke(_both("in-1"), config)
for turn in range(2, 5):
graph.invoke(_both(f"in-{turn}"), graph.get_state(config).config)
assert not _snapshotted_checkpoints(sync_checkpointer, config)
assert (
graph.get_state(config).values["log"] == graph.get_state(config).values["plain"]
)
def test_resume_that_reruns_an_error_handler_drops_its_stored_writes(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
handled = threading.Event()
attempts = {"c": 0}
def fails(state: _State) -> dict:
raise RuntimeError("f always fails")
def handler(state: _State, error: NodeError) -> dict:
handled.set()
return _both("h")
def flaky(state: _State) -> dict:
attempts["c"] += 1
if attempts["c"] == 1:
assert handled.wait(5)
raise ValueError("c fails once")
return _both("c")
graph = (
StateGraph(_State)
.add_node("f", fails, error_handler=handler)
.add_node("c", flaky)
.add_edge(START, "f")
.add_edge(START, "c")
.compile(checkpointer=sync_checkpointer)
)
config = _thread("t")
with pytest.raises(ValueError):
graph.invoke(_both("in"), config, durability=durability)
live = graph.invoke(None, config, durability=durability)
state = graph.get_state(config)
assert state.values["log"] == state.values["plain"] == live["log"]
@@ -0,0 +1,496 @@
import operator
from typing import Annotated, Any, Literal
import pytest
from langchain_core.runnables import RunnableConfig
from langgraph.checkpoint.base import BaseCheckpointSaver
from langgraph.checkpoint.memory import InMemorySaver
from typing_extensions import TypedDict
from langgraph._internal._constants import CONFIG_KEY_CHECKPOINTER
from langgraph.channels.delta import DeltaChannel
from langgraph.graph import END, START, StateGraph
from langgraph.pregel._checkpoint import (
achannels_from_checkpoint,
channels_from_checkpoint,
empty_checkpoint,
)
pytestmark = pytest.mark.anyio
def _extend(state: list | None, writes: list[Any]) -> list:
out = list(state or [])
for write in writes:
out.extend(write if isinstance(write, list) else [write])
return out
def _state_schema(snapshot_frequency: int = 1000) -> type:
class State(TypedDict, total=False):
delta: Annotated[
list, DeltaChannel(_extend, snapshot_frequency=snapshot_frequency)
]
plain: Annotated[list, operator.add]
return State
def _both(*items: str) -> dict:
return {"delta": list(items), "plain": list(items)}
def _child_builder(*, snapshot_frequency: int = 1000) -> StateGraph:
builder = StateGraph(_state_schema(snapshot_frequency))
builder.add_node("a", lambda state: _both("a1"))
builder.add_node("b", lambda state: _both("b1", "b2"))
builder.add_edge(START, "a")
builder.add_edge("a", "b")
builder.add_edge("b", END)
return builder
def _wrap(
inner: StateGraph,
*,
checkpointer: bool | None = None,
interrupt_before: list[str] | None = None,
) -> StateGraph:
builder = StateGraph(inner.state_schema)
builder.add_node(
"child",
inner.compile(checkpointer=checkpointer, interrupt_before=interrupt_before),
)
builder.add_edge(START, "child")
builder.add_edge("child", END)
return builder
def _nested_app(
checkpointer: BaseCheckpointSaver,
*,
depth: int = 1,
snapshot_frequency: int = 1000,
pause_before_b: bool = False,
subgraph_checkpointer: bool | None = None,
) -> Any:
graph = _child_builder(snapshot_frequency=snapshot_frequency)
for _ in range(depth):
graph = _wrap(
graph,
checkpointer=subgraph_checkpointer,
interrupt_before=["b"] if pause_before_b else None,
)
return graph.compile(checkpointer=checkpointer)
def _scoped(config: dict, namespace: str) -> dict:
return {"configurable": {**config["configurable"], "checkpoint_ns": namespace}}
def _child_namespace(app: Any, config: dict, *, depth: int = 1) -> str:
namespace = ""
for level in range(depth):
scoped = _scoped(config, namespace) if namespace else config
namespace = next(
(
task.state["configurable"]["checkpoint_ns"]
for snapshot in app.get_state_history(scoped)
for task in snapshot.tasks
if task.name == "child" and isinstance(task.state, dict)
),
"",
)
assert namespace, f"no `child` subgraph task at nesting level {level}"
return namespace
async def _achild_namespace(app: Any, config: dict) -> str:
async for snapshot in app.aget_state_history(config):
for task in snapshot.tasks:
if task.name == "child" and isinstance(task.state, dict):
return task.state["configurable"]["checkpoint_ns"]
raise AssertionError("no `child` subgraph task")
HISTORY = [_both("a1", "b1", "b2"), _both("a1"), _both(), _both()]
def test_subgraph_get_state(sync_checkpointer: BaseCheckpointSaver) -> None:
app = _nested_app(sync_checkpointer)
config = {"configurable": {"thread_id": "1"}}
app.invoke({}, config)
child = _scoped(config, _child_namespace(app, config))
assert app.get_state(config).values == _both("a1", "b1", "b2")
assert app.get_state(child).values == _both("a1", "b1", "b2")
async def test_subgraph_aget_state(async_checkpointer: BaseCheckpointSaver) -> None:
app = _nested_app(async_checkpointer)
config = {"configurable": {"thread_id": "1"}}
await app.ainvoke({}, config)
child = _scoped(config, await _achild_namespace(app, config))
assert (await app.aget_state(child)).values == _both("a1", "b1", "b2")
def test_subgraph_get_state_history(sync_checkpointer: BaseCheckpointSaver) -> None:
app = _nested_app(sync_checkpointer)
config = {"configurable": {"thread_id": "1"}}
app.invoke({}, config)
child = _scoped(config, _child_namespace(app, config))
assert [s.values for s in app.get_state_history(child)] == HISTORY
async def test_subgraph_aget_state_history(
async_checkpointer: BaseCheckpointSaver,
) -> None:
app = _nested_app(async_checkpointer)
config = {"configurable": {"thread_id": "1"}}
await app.ainvoke({}, config)
child = _scoped(config, await _achild_namespace(app, config))
assert [s.values async for s in app.aget_state_history(child)] == HISTORY
def test_doubly_nested_subgraph_get_state(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
app = _nested_app(sync_checkpointer, depth=2)
config = {"configurable": {"thread_id": "1"}}
app.invoke({}, config)
child = _scoped(config, _child_namespace(app, config, depth=2))
assert app.get_state(child).values == _both("a1", "b1", "b2")
@pytest.mark.parametrize("persistence", ["per-invocation", "per-thread"])
def test_interrupted_subgraph_task_state(
sync_checkpointer: BaseCheckpointSaver,
persistence: Literal["per-invocation", "per-thread"],
) -> None:
app = _nested_app(
sync_checkpointer,
pause_before_b=True,
subgraph_checkpointer=True if persistence == "per-thread" else None,
)
config = {"configurable": {"thread_id": "1"}}
app.invoke({}, config)
(task,) = app.get_state(config, subgraphs=True).tasks
assert task.state.values == _both("a1")
@pytest.mark.parametrize("persistence", ["per-invocation", "per-thread"])
async def test_interrupted_subgraph_task_state_async(
async_checkpointer: BaseCheckpointSaver,
persistence: Literal["per-invocation", "per-thread"],
) -> None:
app = _nested_app(
async_checkpointer,
pause_before_b=True,
subgraph_checkpointer=True if persistence == "per-thread" else None,
)
config = {"configurable": {"thread_id": "1"}}
await app.ainvoke({}, config)
(task,) = (await app.aget_state(config, subgraphs=True)).tasks
assert task.state.values == _both("a1")
@pytest.mark.parametrize("persistence", ["per-invocation", "per-thread"])
def test_interrupted_subgraph_history_from_its_task_config(
sync_checkpointer: BaseCheckpointSaver,
persistence: Literal["per-invocation", "per-thread"],
) -> None:
app = _nested_app(
sync_checkpointer,
pause_before_b=True,
subgraph_checkpointer=True if persistence == "per-thread" else None,
)
config = {"configurable": {"thread_id": "1"}}
app.invoke({}, config)
(task,) = app.get_state(config).tasks
history = list(app.get_state_history(task.state))
assert [snapshot.values for snapshot in history][:1] == [_both("a1")]
@pytest.mark.parametrize("persistence", ["per-invocation", "per-thread"])
async def test_interrupted_subgraph_ahistory_from_its_task_config(
async_checkpointer: BaseCheckpointSaver,
persistence: Literal["per-invocation", "per-thread"],
) -> None:
app = _nested_app(
async_checkpointer,
pause_before_b=True,
subgraph_checkpointer=True if persistence == "per-thread" else None,
)
config = {"configurable": {"thread_id": "1"}}
await app.ainvoke({}, config)
(task,) = (await app.aget_state(config)).tasks
history = [snapshot async for snapshot in app.aget_state_history(task.state)]
assert [snapshot.values for snapshot in history][:1] == [_both("a1")]
@pytest.mark.parametrize("persistence", ["per-invocation", "per-thread"])
def test_interrupted_subgraph_update_state_from_its_task_config(
sync_checkpointer: BaseCheckpointSaver,
persistence: Literal["per-invocation", "per-thread"],
) -> None:
app = _nested_app(
sync_checkpointer,
pause_before_b=True,
subgraph_checkpointer=True if persistence == "per-thread" else None,
)
config = {"configurable": {"thread_id": "1"}}
app.invoke({}, config)
(task,) = app.get_state(config).tasks
app.update_state(task.state, _both("edit"), as_node="a")
(task,) = app.get_state(config, subgraphs=True).tasks
assert task.state.values == _both("a1", "edit")
@pytest.mark.parametrize("persistence", ["per-invocation", "per-thread"])
async def test_interrupted_subgraph_aupdate_state_from_its_task_config(
async_checkpointer: BaseCheckpointSaver,
persistence: Literal["per-invocation", "per-thread"],
) -> None:
app = _nested_app(
async_checkpointer,
pause_before_b=True,
subgraph_checkpointer=True if persistence == "per-thread" else None,
)
config = {"configurable": {"thread_id": "1"}}
await app.ainvoke({}, config)
(task,) = (await app.aget_state(config)).tasks
await app.aupdate_state(task.state, _both("edit"), as_node="a")
(task,) = (await app.aget_state(config, subgraphs=True)).tasks
assert task.state.values == _both("a1", "edit")
def test_subgraph_update_state_keeps_history(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
app = _nested_app(sync_checkpointer, snapshot_frequency=2)
config = {"configurable": {"thread_id": "1"}}
app.invoke({}, config)
child = _scoped(config, _child_namespace(app, config))
app.update_state(child, _both("manual"))
assert app.get_state(child).values == _both("a1", "b1", "b2", "manual")
async def test_subgraph_aupdate_state_keeps_history(
async_checkpointer: BaseCheckpointSaver,
) -> None:
app = _nested_app(async_checkpointer, snapshot_frequency=2)
config = {"configurable": {"thread_id": "1"}}
await app.ainvoke({}, config)
child = _scoped(config, await _achild_namespace(app, config))
await app.aupdate_state(child, _both("manual"))
assert (await app.aget_state(child)).values == _both("a1", "b1", "b2", "manual")
def test_stateless_subgraph_persists_nothing(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
app = _nested_app(sync_checkpointer, subgraph_checkpointer=False)
config = {"configurable": {"thread_id": "1"}}
app.invoke({}, config)
child_tasks = [
task
for snapshot in app.get_state_history(config)
for task in snapshot.tasks
if task.name == "child" and isinstance(task.state, dict)
]
assert child_tasks == []
assert app.get_state(config).values == _both("a1", "b1", "b2")
def test_completed_subgraph_exposes_no_task_state(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
app = _nested_app(sync_checkpointer)
config = {"configurable": {"thread_id": "1"}}
app.invoke({}, config)
assert app.get_state(config, subgraphs=True).tasks == ()
def _written_delta_checkpoint() -> Any:
checkpoint = empty_checkpoint()
checkpoint["channel_versions"]["delta"] = 1
return checkpoint
def test_hydrating_written_delta_channel_without_saver_raises() -> None:
with pytest.raises(ValueError, match="no checkpointer"):
channels_from_checkpoint(
{"delta": DeltaChannel(_extend)}, _written_delta_checkpoint()
)
async def test_ahydrating_written_delta_channel_without_saver_raises() -> None:
with pytest.raises(ValueError, match="no checkpointer"):
await achannels_from_checkpoint(
{"delta": DeltaChannel(_extend)}, _written_delta_checkpoint()
)
def test_hydrating_written_delta_channel_without_config_raises() -> None:
with pytest.raises(ValueError, match="no checkpointer"):
channels_from_checkpoint(
{"delta": DeltaChannel(_extend)},
_written_delta_checkpoint(),
saver=InMemorySaver(),
)
def test_hydrating_unwritten_delta_channel_without_saver_is_empty() -> None:
channels, _ = channels_from_checkpoint(
{"delta": DeltaChannel(_extend)}, empty_checkpoint()
)
assert channels["delta"].get() == []
def test_root_checkpointer_true_graph_state_read_raises() -> None:
app = _child_builder().compile(checkpointer=True)
with pytest.raises(RuntimeError, match="checkpointer=True cannot be used"):
app.get_state({"configurable": {"thread_id": "1"}})
def test_stateless_graph_update_state_ignores_lent_saver() -> None:
saver = InMemorySaver()
app = _child_builder().compile(checkpointer=False)
config = {
"configurable": {
"thread_id": "1",
"checkpoint_ns": "child:1",
CONFIG_KEY_CHECKPOINTER: saver,
}
}
with pytest.raises(ValueError, match="No checkpointer set"):
app.update_state(config, _both("x"), as_node="a")
assert list(saver.list(None)) == []
def test_graph_without_a_checkpointer_reads_through_a_lent_saver(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
app = _child_builder().compile()
config = {
"configurable": {"thread_id": "1", CONFIG_KEY_CHECKPOINTER: sync_checkpointer}
}
app.invoke(_both("in"), config)
assert app.get_state(config).values == _both("in", "a1", "b1", "b2")
app.update_state(config, _both("edit"), as_node="b")
assert app.get_state(config).values == _both("in", "a1", "b1", "b2", "edit")
assert next(iter(app.get_state_history(config))).values == _both(
"in", "a1", "b1", "b2", "edit"
)
async def test_graph_without_a_checkpointer_areads_through_a_lent_saver(
async_checkpointer: BaseCheckpointSaver,
) -> None:
app = _child_builder().compile()
config = {
"configurable": {"thread_id": "1", CONFIG_KEY_CHECKPOINTER: async_checkpointer}
}
await app.ainvoke(_both("in"), config)
assert (await app.aget_state(config)).values == _both("in", "a1", "b1", "b2")
await app.aupdate_state(config, _both("edit"), as_node="b")
assert (await app.aget_state(config)).values == _both(
"in", "a1", "b1", "b2", "edit"
)
history = [s async for s in app.aget_state_history(config)]
assert history[0].values == _both("in", "a1", "b1", "b2", "edit")
def test_second_call_of_a_checkpointer_true_subgraph_reads_its_own_history(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
child = _child_builder().compile(checkpointer=True)
def node(state: dict) -> dict:
child.invoke(_both("first"))
child.invoke(_both("second"))
return {}
builder = StateGraph(_state_schema())
builder.add_node("node", node)
builder.add_edge(START, "node")
builder.compile(checkpointer=sync_checkpointer).invoke(
_both(), {"configurable": {"thread_id": "1"}}
)
def read(namespace: str) -> dict:
return child.get_state(
{
"configurable": {
"thread_id": "1",
"checkpoint_ns": namespace,
CONFIG_KEY_CHECKPOINTER: sync_checkpointer,
}
}
).values
assert read("node") == _both("first", "a1", "b1", "b2")
assert read("node|1") == _both("second", "a1", "b1", "b2")
async def test_second_call_of_a_checkpointer_true_subgraph_areads_its_own_history(
async_checkpointer: BaseCheckpointSaver,
) -> None:
child = _child_builder().compile(checkpointer=True)
async def node(state: dict, config: RunnableConfig) -> dict:
await child.ainvoke(_both("first"), config)
await child.ainvoke(_both("second"), config)
return {}
builder = StateGraph(_state_schema())
builder.add_node("node", node)
builder.add_edge(START, "node")
await builder.compile(checkpointer=async_checkpointer).ainvoke(
_both(), {"configurable": {"thread_id": "1"}}
)
async def read(namespace: str) -> dict:
snapshot = await child.aget_state(
{
"configurable": {
"thread_id": "1",
"checkpoint_ns": namespace,
CONFIG_KEY_CHECKPOINTER: async_checkpointer,
}
}
)
return snapshot.values
assert await read("node") == _both("first", "a1", "b1", "b2")
assert await read("node|1") == _both("second", "a1", "b1", "b2")
@@ -16,6 +16,7 @@ from typing_extensions import TypedDict
from langgraph.channels.delta import DeltaChannel
from langgraph.graph import END, START, StateGraph
from langgraph.pregel._checkpoint import delta_channels_to_snapshot
from langgraph.types import Command, interrupt
pytestmark = pytest.mark.anyio
@@ -94,6 +95,28 @@ async def test_forced_snapshot_single_run() -> None:
assert "seed-a" in state.values["a"]
async def test_supersteps_bound_skips_a_channel_never_written() -> None:
with patch(
"langgraph.pregel._checkpoint.DELTA_MAX_SUPERSTEPS_SINCE_SNAPSHOT",
3,
):
saver = InMemorySaver()
graph = _build_two_channel_graph(saver, n_loops=4)
config = {"configurable": {"thread_id": "never-written"}}
graph.invoke({"a": ["seed-a"]}, config)
minted = [
t.config["configurable"]["checkpoint_id"]
for t in saver.list(config)
if "b" in t.checkpoint["channel_versions"]
]
assert not minted, (
f"b was never written, but {len(minted)} checkpoints minted it a version"
)
assert graph.get_state(config).values["b"] == []
async def test_forced_snapshot_accumulates_across_runs() -> None:
"""Supersteps counter for an unwritten channel persists across separate
invoke() calls. After enough runs, the channel is force-snapshotted."""
@@ -139,13 +162,126 @@ async def test_predicate_fires_on_supersteps_overflow() -> None:
channels = {"x": ch_instance}
counters: dict[str, tuple[int, int]] = {"x": (0, 5000)}
result = delta_channels_to_snapshot(channels, counters)
result = delta_channels_to_snapshot(channels, counters, {"x": 1})
assert "x" in result
counters_below: dict[str, tuple[int, int]] = {"x": (0, 4999)}
result2 = delta_channels_to_snapshot(channels, counters_below)
result2 = delta_channels_to_snapshot(channels, counters_below, {"x": 1})
assert "x" not in result2
assert not delta_channels_to_snapshot(channels, counters, {}), (
"a channel with no version was never written, so it has nothing to snapshot"
)
def _delta_counters(saver: InMemorySaver, config: Any) -> dict[str, list[int]]:
tup = saver.get_tuple(config)
assert tup is not None
counters = tup.metadata.get("counters_since_delta_snapshot") or {}
return {ch: list(c) for ch, c in counters.items()}
_CLEAR_COPY_AND_INPUT_UPDATES = pytest.mark.parametrize(
("values", "as_node", "supersteps"),
[
(None, END, 1),
(None, "__copy__", 0),
({"a": []}, "__input__", 1),
],
ids=["clear as END", "copy", "update as input"],
)
@_CLEAR_COPY_AND_INPUT_UPDATES
def test_update_state_path_keeps_delta_counters(
values: Any, as_node: str, supersteps: int
) -> None:
saver = InMemorySaver()
graph = _build_two_channel_graph(saver)
config = {"configurable": {"thread_id": "counters"}}
graph.invoke({"a": ["seed-a"], "b": ["seed-b"]}, config)
before = _delta_counters(saver, config)
assert set(before) == {"a", "b"}, f"both channels need live counters: {before}"
updated = graph.update_state(config, values, as_node=as_node)
assert _delta_counters(saver, updated) == {
ch: [u, s + supersteps] for ch, (u, s) in before.items()
}
@_CLEAR_COPY_AND_INPUT_UPDATES
async def test_aupdate_state_path_keeps_delta_counters(
values: Any, as_node: str, supersteps: int
) -> None:
saver = InMemorySaver()
graph = _build_two_channel_graph(saver)
config = {"configurable": {"thread_id": "counters"}}
await graph.ainvoke({"a": ["seed-a"], "b": ["seed-b"]}, config)
before = _delta_counters(saver, config)
assert set(before) == {"a", "b"}, f"both channels need live counters: {before}"
updated = await graph.aupdate_state(config, values, as_node=as_node)
assert _delta_counters(saver, updated) == {
ch: [u, s + supersteps] for ch, (u, s) in before.items()
}
_UPDATES_THAT_ADD_A_SUPERSTEP = pytest.mark.parametrize(
("values", "as_node"),
[(None, END), ({"a": []}, "__input__")],
ids=["clear as END", "update as input"],
)
@_UPDATES_THAT_ADD_A_SUPERSTEP
def test_update_state_path_snapshots_at_the_supersteps_bound(
values: Any, as_node: str
) -> None:
saver = InMemorySaver()
graph = _build_two_channel_graph(saver)
config = {"configurable": {"thread_id": "bound"}}
graph.invoke({"a": ["seed-a"], "b": ["seed-b"]}, config)
expected = graph.get_state(config).values
supersteps = _delta_counters(saver, config)["b"][1]
with patch(
"langgraph.pregel._checkpoint.DELTA_MAX_SUPERSTEPS_SINCE_SNAPSHOT",
supersteps + 1,
):
updated = graph.update_state(config, values, as_node=as_node)
head = saver.get_tuple(updated)
assert head is not None
assert isinstance(head.checkpoint["channel_values"].get("b"), _DeltaSnapshot)
assert "b" not in _delta_counters(saver, updated)
assert graph.get_state(updated).values == expected
@_UPDATES_THAT_ADD_A_SUPERSTEP
async def test_aupdate_state_path_snapshots_at_the_supersteps_bound(
values: Any, as_node: str
) -> None:
saver = InMemorySaver()
graph = _build_two_channel_graph(saver)
config = {"configurable": {"thread_id": "bound"}}
await graph.ainvoke({"a": ["seed-a"], "b": ["seed-b"]}, config)
expected = (await graph.aget_state(config)).values
supersteps = _delta_counters(saver, config)["b"][1]
with patch(
"langgraph.pregel._checkpoint.DELTA_MAX_SUPERSTEPS_SINCE_SNAPSHOT",
supersteps + 1,
):
updated = await graph.aupdate_state(config, values, as_node=as_node)
head = saver.get_tuple(updated)
assert head is not None
assert isinstance(head.checkpoint["channel_values"].get("b"), _DeltaSnapshot)
assert "b" not in _delta_counters(saver, updated)
assert (await graph.aget_state(updated)).values == expected
async def test_counter_reset_after_supersteps_snapshot() -> None:
"""After the supersteps bound triggers a snapshot, the counters for
@@ -193,3 +329,78 @@ async def test_counter_reset_after_supersteps_snapshot() -> None:
state = graph.get_state(config)
assert state.values["b"] == ["seed-b"]
class _HistoryRequestSaver(InMemorySaver):
def __init__(self) -> None:
super().__init__()
self.requested: list[list[str]] = []
def get_delta_channel_history(self, *, config: Any, channels: Any) -> Any:
self.requested.append(sorted(channels))
return super().get_delta_channel_history(config=config, channels=channels)
def test_never_written_channel_is_not_walked() -> None:
saver = _HistoryRequestSaver()
graph = _build_two_channel_graph(saver, n_loops=3)
config = {"configurable": {"thread_id": "never-written"}}
graph.invoke({"a": ["seed-a"]}, config)
saver.requested.clear()
graph.invoke({"a": ["more-a"]}, config)
state = graph.get_state(config)
assert state.values["b"] == []
assert saver.requested and all(r == ["a"] for r in saver.requested), (
f"only the written channel needs a walk; asked for {saver.requested}"
)
async def test_anever_written_channel_is_not_walked() -> None:
saver = _HistoryRequestSaver()
graph = _build_two_channel_graph(saver, n_loops=3)
config = {"configurable": {"thread_id": "never-written"}}
await graph.ainvoke({"a": ["seed-a"]}, config)
saver.requested.clear()
await graph.ainvoke({"a": ["more-a"]}, config)
state = await graph.aget_state(config)
assert state.values["b"] == []
assert saver.requested and all(r == ["a"] for r in saver.requested), (
f"only the written channel needs a walk; asked for {saver.requested}"
)
@pytest.mark.parametrize("durability", ["sync", "async"])
def test_first_write_pending_at_an_interrupt_is_applied_once_on_resume(
durability: Any,
) -> None:
class State(TypedDict):
x: list
first: Annotated[list, DeltaChannel(_simple_reducer)]
def ask(state: State) -> dict:
interrupt("ok?")
return {"x": ["asked"]}
saver = InMemorySaver()
graph = (
StateGraph(State)
.add_node("p", lambda state: {"first": ["p"]})
.add_node("ask", ask)
.add_edge(START, "p")
.add_edge(START, "ask")
.compile(checkpointer=saver)
)
config = {"configurable": {"thread_id": "pending-first-write"}}
graph.invoke({"x": ["in"]}, config, durability=durability)
head = saver.get_tuple(config)
assert head is not None
assert "first" not in head.checkpoint["channel_versions"]
assert ("first", ["p"]) in [w[1:] for w in head.pending_writes or []]
graph.invoke(Command(resume="yes"), config, durability=durability)
assert graph.get_state(config).values["first"] == ["p"]
@@ -113,6 +113,37 @@ def test_fresh_update_state_head_snapshots_delta_channel() -> None:
assert "counters_since_delta_snapshot" not in head.metadata
def test_fresh_update_state_stores_nothing_for_a_delta_channel_it_did_not_write() -> (
None
):
saver = InMemorySaver()
State = TypedDict( # type: ignore[call-overload] # noqa: UP013
"State",
{
"messages": Annotated[list, DeltaChannel(_messages_delta_reducer)],
"notes": Annotated[list, DeltaChannel(_messages_delta_reducer)],
},
)
graph = (
StateGraph(State)
.add_node("model", lambda state: {})
.add_edge(START, "model")
.compile(checkpointer=saver)
)
config = {"configurable": {"thread_id": "fresh-unwritten"}}
graph.update_state(
config,
{"messages": [HumanMessage(content="hello", id="m1")]},
as_node="model",
)
head = saver.get_tuple(config)
assert head is not None
assert "notes" not in head.checkpoint["channel_versions"]
assert graph.get_state(config).values["notes"] == []
# ---------------------------------------------------------------------------
# Non-fresh thread: update_state after invoke
# ---------------------------------------------------------------------------
@@ -338,3 +369,29 @@ def test_state_history_chain_after_fresh_update_state_delta_channel() -> None:
assert update_snapshot.metadata["step"] == 0
assert update_snapshot.parent_config is None
assert [m.content for m in update_snapshot.values["messages"]] == ["hello"]
def test_update_state_that_snapshots_keeps_a_deferred_node_pending() -> None:
channel = DeltaChannel(_messages_delta_reducer, snapshot_frequency=1)
class State(TypedDict):
messages: Annotated[list, channel]
builder = StateGraph(State)
builder.add_node("a", lambda state: {"messages": [HumanMessage("a", id="a")]})
builder.add_node(
"b", lambda state: {"messages": [HumanMessage("b", id="b")]}, defer=True
)
builder.add_node("c", lambda state: {})
builder.add_edge(START, "a")
builder.add_edge("a", "b")
builder.add_edge("a", "c")
graph = builder.compile(checkpointer=InMemorySaver(), interrupt_after=["a"])
config = {"configurable": {"thread_id": "t"}}
graph.invoke({"messages": [HumanMessage("s", id="s")]}, config)
graph.update_state(config, {"messages": [HumanMessage("u", id="u")]}, as_node="c")
final = graph.invoke(None, config)
assert [m.content for m in final["messages"]] == ["s", "a", "u", "b"]
assert graph.get_state(config).next == ()
@@ -0,0 +1,534 @@
"""State reads while some tasks of a superstep are finished and others are paused.
When parallel tasks each call `interrupt()` and only some of them are resumed,
the superstep stays open. Its recorded writes then contain the old interrupt of
each finished task next to that task's output. These tests check that state
reads, which are rebuilt from the checkpointer, report only the interrupts that
still need an answer.
"""
import operator
import sys
import uuid
from collections import Counter
from typing import Annotated, Any
import pytest
from langgraph.checkpoint.base import BaseCheckpointSaver
from typing_extensions import TypedDict
from langgraph._internal._constants import (
ERROR,
INTERRUPT,
NO_WRITES,
NULL_TASK_ID,
RESUME,
RETURN,
)
from langgraph.func import entrypoint, task
from langgraph.graph import END, START, StateGraph
from langgraph.pregel._task_status import read_task_statuses
from langgraph.types import Command, Durability, Interrupt, Send, interrupt
pytestmark = pytest.mark.anyio
NEEDS_CONTEXTVARS = pytest.mark.skipif(
sys.version_info < (3, 11),
reason="Python 3.11+ is required for async contextvars support",
)
class State(TypedDict, total=False):
log: Annotated[list[str], operator.add]
count: int
def _config() -> dict[str, Any]:
return {"configurable": {"thread_id": str(uuid.uuid4())}}
def _build_parallel(
checkpointer: BaseCheckpointSaver,
calls: Counter[str],
*,
a_questions: int = 1,
a_returns: Any = "log",
):
"""Build a graph where nodes `a` and `b` start in parallel and both ask questions.
`a` asks `a_questions` questions in a row. `a_returns` controls what `a`
returns after its last answer. The default `"log"` returns the answers in
`log`. Any other value is returned as-is.
"""
def a(state: State) -> Any:
calls["a"] += 1
answers = [interrupt(f"A{i + 1}") for i in range(a_questions)]
if a_returns == "log":
return {"log": [f"a:{answer}" for answer in answers]}
return a_returns
def b(state: State) -> State:
calls["b"] += 1
return {"log": [f"b:{interrupt('B')}"]}
builder = StateGraph(State)
builder.add_node("a", a)
builder.add_node("b", b)
builder.add_edge(START, "a")
builder.add_edge(START, "b")
builder.add_edge("a", END)
builder.add_edge("b", END)
return builder.compile(checkpointer=checkpointer)
def _interrupt_by_value(snapshot: Any, value: str) -> Interrupt:
return next(i for i in snapshot.interrupts if i.value == value)
def _task(snapshot: Any, name: str) -> Any:
return next(t for t in snapshot.tasks if t.name == name)
def _interrupt_values(interrupts: Any) -> list[str]:
return sorted(i.value for i in interrupts)
# --- Task A answered and finished, task B still paused ---
def test_finished_task_does_not_report_answered_interrupt(
sync_checkpointer: BaseCheckpointSaver, durability: Durability
) -> None:
calls: Counter[str] = Counter()
graph = _build_parallel(sync_checkpointer, calls)
config = _config()
graph.invoke({"log": []}, config, durability=durability)
snapshot = graph.get_state(config)
assert _interrupt_values(snapshot.interrupts) == ["A1", "B"]
graph.invoke(
Command(resume={_interrupt_by_value(snapshot, "A1").id: "yes"}),
config,
durability=durability,
)
snapshot = graph.get_state(config)
assert _interrupt_values(snapshot.interrupts) == ["B"]
assert snapshot.next == ("b",)
assert _task(snapshot, "a").interrupts == ()
assert _task(snapshot, "a").result == {"log": ["a:yes"]}
assert _interrupt_values(_task(snapshot, "b").interrupts) == ["B"]
assert _task(snapshot, "b").result is None
# Reading the same checkpoint by id gives the record of the step: every task
# in it, and every question asked, including the one A already answered.
record = graph.get_state(snapshot.config)
assert sorted(record.next) == ["a", "b"]
assert _interrupt_values(record.interrupts) == ["A1", "B"]
assert _interrupt_values(_task(record, "a").interrupts) == ["A1"]
assert _task(record, "a").result == {"log": ["a:yes"]}
# B can still be answered, and the graph finishes normally.
result = graph.invoke(
Command(resume={_interrupt_by_value(snapshot, "B").id: "ok"}),
config,
durability=durability,
)
assert sorted(result["log"]) == ["a:yes", "b:ok"]
assert calls == {"a": 2, "b": 3}
snapshot = graph.get_state(config)
assert snapshot.next == ()
assert snapshot.interrupts == ()
# History still shows where each question was asked.
asked = [
_interrupt_values(s.interrupts)
for s in graph.get_state_history(config)
if s.interrupts
]
if durability != "exit":
assert asked == [["A1", "B"]]
@NEEDS_CONTEXTVARS
async def test_finished_task_does_not_report_answered_interrupt_async(
async_checkpointer: BaseCheckpointSaver,
) -> None:
calls: Counter[str] = Counter()
graph = _build_parallel(async_checkpointer, calls)
config = _config()
await graph.ainvoke({"log": []}, config)
snapshot = await graph.aget_state(config)
await graph.ainvoke(
Command(resume={_interrupt_by_value(snapshot, "A1").id: "yes"}), config
)
snapshot = await graph.aget_state(config)
assert _interrupt_values(snapshot.interrupts) == ["B"]
assert snapshot.next == ("b",)
assert _task(snapshot, "a").interrupts == ()
assert _task(snapshot, "a").result == {"log": ["a:yes"]}
assert _interrupt_values(_task(snapshot, "b").interrupts) == ["B"]
record = await graph.aget_state(snapshot.config)
assert _interrupt_values(record.interrupts) == ["A1", "B"]
assert _interrupt_values(_task(record, "a").interrupts) == ["A1"]
result = await graph.ainvoke(
Command(resume={_interrupt_by_value(snapshot, "B").id: "ok"}), config
)
assert sorted(result["log"]) == ["a:yes", "b:ok"]
assert calls == {"a": 2, "b": 3}
# --- Task A answered its first question and asked a second one ---
def test_task_paused_at_second_question_stays_pending(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
calls: Counter[str] = Counter()
graph = _build_parallel(sync_checkpointer, calls, a_questions=2)
config = _config()
graph.invoke({"log": []}, config)
snapshot = graph.get_state(config)
graph.invoke(
Command(resume={_interrupt_by_value(snapshot, "A1").id: "one"}), config
)
snapshot = graph.get_state(config)
assert _interrupt_values(snapshot.interrupts) == ["A2", "B"]
# A is not finished: it has a saved answer, but no output.
assert sorted(snapshot.next) == ["a", "b"]
assert _interrupt_values(_task(snapshot, "a").interrupts) == ["A2"]
assert _task(snapshot, "a").result is None
assert _interrupt_values(_task(snapshot, "b").interrupts) == ["B"]
# Both remaining questions can be answered together.
result = graph.invoke(
Command(
resume={
_interrupt_by_value(snapshot, "A2").id: "two",
_interrupt_by_value(snapshot, "B").id: "ok",
}
),
config,
)
assert sorted(result["log"]) == ["a:one", "a:two", "b:ok"]
snapshot = graph.get_state(config)
assert snapshot.next == ()
assert snapshot.interrupts == ()
@NEEDS_CONTEXTVARS
async def test_task_paused_at_second_question_stays_pending_async(
async_checkpointer: BaseCheckpointSaver,
) -> None:
calls: Counter[str] = Counter()
graph = _build_parallel(async_checkpointer, calls, a_questions=2)
config = _config()
await graph.ainvoke({"log": []}, config)
snapshot = await graph.aget_state(config)
await graph.ainvoke(
Command(resume={_interrupt_by_value(snapshot, "A1").id: "one"}), config
)
snapshot = await graph.aget_state(config)
assert _interrupt_values(snapshot.interrupts) == ["A2", "B"]
assert sorted(snapshot.next) == ["a", "b"]
assert _interrupt_values(_task(snapshot, "a").interrupts) == ["A2"]
assert _task(snapshot, "a").result is None
def test_task_paused_at_second_question_then_other_task_finishes(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
calls: Counter[str] = Counter()
graph = _build_parallel(sync_checkpointer, calls, a_questions=2)
config = _config()
graph.invoke({"log": []}, config)
snapshot = graph.get_state(config)
graph.invoke(
Command(resume={_interrupt_by_value(snapshot, "A1").id: "one"}), config
)
snapshot = graph.get_state(config)
graph.invoke(Command(resume={_interrupt_by_value(snapshot, "B").id: "ok"}), config)
snapshot = graph.get_state(config)
assert _interrupt_values(snapshot.interrupts) == ["A2"]
assert snapshot.next == ("a",)
assert _task(snapshot, "b").interrupts == ()
assert _task(snapshot, "b").result == {"log": ["b:ok"]}
result = graph.invoke(
Command(resume={_interrupt_by_value(snapshot, "A2").id: "two"}), config
)
assert sorted(result["log"]) == ["a:one", "a:two", "b:ok"]
def test_resume_without_id_rejected_when_second_question_and_other_task_pending(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
calls: Counter[str] = Counter()
graph = _build_parallel(sync_checkpointer, calls, a_questions=2)
config = _config()
graph.invoke({"log": []}, config)
snapshot = graph.get_state(config)
graph.invoke(
Command(resume={_interrupt_by_value(snapshot, "A1").id: "one"}), config
)
# A2 and B are both waiting, so a resume value without an id is ambiguous.
with pytest.raises(RuntimeError, match="multiple pending interrupts"):
graph.invoke(Command(resume="ambiguous"), config)
def test_resume_without_id_rejected_when_subgraph_has_parallel_interrupts(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
# A subgraph node whose child graph pauses in two parallel nodes records
# both interrupts under one parent task. Both count as pending, so a resume
# value without an id is ambiguous. (Before, only the first was counted and
# the value went to whichever interrupt consumed it first.)
child_builder = StateGraph(State)
child_builder.add_node("a", lambda s: {"log": [f"a:{interrupt('A')}"]})
child_builder.add_node("b", lambda s: {"log": [f"b:{interrupt('B')}"]})
child_builder.add_edge(START, "a")
child_builder.add_edge(START, "b")
builder = StateGraph(State)
builder.add_node("child", child_builder.compile())
builder.add_edge(START, "child")
graph = builder.compile(checkpointer=sync_checkpointer)
config = _config()
graph.invoke({"log": []}, config)
snapshot = graph.get_state(config)
assert _interrupt_values(snapshot.interrupts) == ["A", "B"]
with pytest.raises(RuntimeError, match="multiple pending interrupts"):
graph.invoke(Command(resume="ambiguous"), config)
result = graph.invoke(
Command(
resume={
_interrupt_by_value(snapshot, "A").id: "x",
_interrupt_by_value(snapshot, "B").id: "y",
}
),
config,
)
assert sorted(result["log"]) == ["a:x", "b:y"]
# --- Task A finished with an empty or falsy result ---
@pytest.mark.parametrize(
"a_returns",
[None, {}, {"count": 0}, {"log": []}],
ids=["none", "empty_dict", "zero", "empty_list"],
)
def test_task_finished_with_falsy_result(
sync_checkpointer: BaseCheckpointSaver, a_returns: Any
) -> None:
calls: Counter[str] = Counter()
graph = _build_parallel(sync_checkpointer, calls, a_returns=a_returns)
config = _config()
graph.invoke({"log": []}, config)
snapshot = graph.get_state(config)
graph.invoke(
Command(resume={_interrupt_by_value(snapshot, "A1").id: "yes"}), config
)
snapshot = graph.get_state(config)
assert _interrupt_values(snapshot.interrupts) == ["B"]
assert snapshot.next == ("b",)
assert _task(snapshot, "a").interrupts == ()
graph.invoke(Command(resume={_interrupt_by_value(snapshot, "B").id: "ok"}), config)
# A already finished, so resuming B must not run A again.
assert calls == {"a": 2, "b": 3}
snapshot = graph.get_state(config)
assert snapshot.next == ()
assert snapshot.interrupts == ()
@pytest.mark.parametrize("a_returns", [None, {"count": 0}], ids=["none", "zero"])
@NEEDS_CONTEXTVARS
async def test_task_finished_with_falsy_result_async(
async_checkpointer: BaseCheckpointSaver, a_returns: Any
) -> None:
calls: Counter[str] = Counter()
graph = _build_parallel(async_checkpointer, calls, a_returns=a_returns)
config = _config()
await graph.ainvoke({"log": []}, config)
snapshot = await graph.aget_state(config)
await graph.ainvoke(
Command(resume={_interrupt_by_value(snapshot, "A1").id: "yes"}), config
)
snapshot = await graph.aget_state(config)
assert _interrupt_values(snapshot.interrupts) == ["B"]
assert snapshot.next == ("b",)
assert _task(snapshot, "a").interrupts == ()
await graph.ainvoke(
Command(resume={_interrupt_by_value(snapshot, "B").id: "ok"}), config
)
assert calls == {"a": 2, "b": 3}
# --- Subgraphs and the functional API ---
def test_parallel_subgraphs_report_only_pending_interrupts(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
class ChildState(TypedDict):
prompt: str
answers: Annotated[list[str], operator.add]
def ask(state: ChildState) -> dict[str, Any]:
return {"answers": [interrupt(state["prompt"])]}
child_builder = StateGraph(ChildState)
child_builder.add_node("ask", ask)
child_builder.add_edge(START, "ask")
child = child_builder.compile()
class ParentState(TypedDict):
answers: Annotated[list[str], operator.add]
builder = StateGraph(ParentState)
builder.add_node("child", child)
builder.add_conditional_edges(
START,
lambda _: [Send("child", {"prompt": p, "answers": []}) for p in ("a", "b")],
["child"],
)
graph = builder.compile(checkpointer=sync_checkpointer)
config = _config()
graph.invoke({"answers": []}, config)
snapshot = graph.get_state(config)
assert _interrupt_values(snapshot.interrupts) == ["a", "b"]
graph.invoke(Command(resume={_interrupt_by_value(snapshot, "a").id: "x"}), config)
snapshot = graph.get_state(config)
assert _interrupt_values(snapshot.interrupts) == ["b"]
assert snapshot.next == ("child",)
finished = next(t for t in snapshot.tasks if t.result is not None)
assert finished.interrupts == ()
assert finished.result == {"answers": ["x"]}
result = graph.invoke(
Command(resume={_interrupt_by_value(snapshot, "b").id: "y"}), config
)
assert sorted(result["answers"]) == ["x", "y"]
def test_functional_task_finished_with_none_is_not_rerun(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
calls: Counter[str] = Counter()
@task
def ask_a() -> None:
calls["a"] += 1
interrupt("A")
@task
def ask_b() -> str:
calls["b"] += 1
return interrupt("B")
@entrypoint(checkpointer=sync_checkpointer)
def workflow(_: Any) -> list[Any]:
a, b = ask_a(), ask_b()
return [a.result(), b.result()]
config = _config()
workflow.invoke(1, config)
snapshot = workflow.get_state(config)
workflow.invoke(
Command(resume={_interrupt_by_value(snapshot, "A").id: "x"}), config
)
snapshot = workflow.get_state(config)
assert _interrupt_values(snapshot.interrupts) == ["B"]
result = workflow.invoke(
Command(resume={_interrupt_by_value(snapshot, "B").id: "y"}), config
)
assert result == [None, "y"]
assert calls == {"a": 2, "b": 3}
# --- Reading task status from recorded writes ---
def test_read_task_statuses() -> None:
a1 = Interrupt(value="A1", id="a")
a2 = Interrupt(value="A2", id="a")
b = Interrupt(value="B", id="b")
error = ValueError("boom")
statuses = read_task_statuses(
[
# answered and finished: old interrupt stays recorded
("finished", INTERRUPT, (a1,)),
("finished", RESUME, ["yes"]),
("finished", "log", ["a:yes"]),
# answered once, then paused at a second question
("paused", INTERRUPT, (a2,)),
("paused", RESUME, ["one"]),
# finished with no output
("no_output", INTERRUPT, (b,)),
("no_output", RESUME, ["ok"]),
("no_output", NO_WRITES, None),
# functional task that returned None
("returned_none", RETURN, None),
# failed
("failed", ERROR, error),
# not a task
(NULL_TASK_ID, RESUME, "global"),
]
)
assert set(statuses) == {
"finished",
"paused",
"no_output",
"returned_none",
"failed",
}
assert statuses["finished"].finished
assert statuses["finished"].interrupts == (a1,)
assert statuses["finished"].pending_interrupts == ()
assert statuses["finished"].output == (("log", ["a:yes"]),)
assert not statuses["paused"].finished
assert statuses["paused"].interrupts == (a2,)
assert statuses["paused"].pending_interrupts == (a2,)
assert statuses["paused"].output == ()
assert statuses["no_output"].finished
assert statuses["no_output"].interrupts == (b,)
assert statuses["no_output"].pending_interrupts == ()
assert statuses["returned_none"].finished
assert statuses["returned_none"].output == ((RETURN, None),)
assert not statuses["failed"].finished
assert statuses["failed"].error is error
@@ -152,6 +152,11 @@ def test_empty_inputs():
]
def test_invalid_format():
with pytest.raises(ValueError, match="Unrecognized format="):
add_messages([], [], format="invalid")
def test_non_list_inputs():
left = HumanMessage(content="Hello", id="1")
right = AIMessage(content="Hi there!", id="2")
+186
View File
@@ -9410,6 +9410,192 @@ def test_fork_does_not_apply_pending_writes(
assert result == {"value": 121}
def _extend(state: list, writes: list[list]) -> list:
return [*state, *(v for write in writes for v in write)]
class _IntVersionSaver(InMemorySaver):
"""Integer versions tie exactly where `InMemorySaver`'s break at random."""
get_next_version = BaseCheckpointSaver.get_next_version
def _build_chain_after_a_delta_channel() -> Pregel:
return Pregel(
nodes={
"a": NodeBuilder().subscribe_only("inp").do(lambda _: ["a"]).write_to("d"),
"b": NodeBuilder().subscribe_only("d").do(lambda _: "b").write_to("x"),
"c": NodeBuilder().subscribe_only("x").do(lambda _: "c").write_to("out"),
},
channels={
"inp": LastValue(str),
"d": DeltaChannel(_extend, snapshot_frequency=1),
"x": LastValue(str),
"out": LastValue(str),
},
input_channels=["inp"],
output_channels=["out"],
checkpointer=_IntVersionSaver(),
)
def test_update_state_after_an_exit_snapshot_infers_the_last_writer() -> None:
graph = _build_chain_after_a_delta_channel()
config = {"configurable": {"thread_id": "t"}}
graph.invoke({"inp": "go"}, config, durability="exit")
graph.update_state(config, "u")
values = graph.get_state(config).values
assert values["out"] == "u", (
f"the update should apply as c, the last node to write, but state is {values}"
)
async def test_aupdate_state_after_an_exit_snapshot_infers_the_last_writer() -> None:
graph = _build_chain_after_a_delta_channel()
config = {"configurable": {"thread_id": "t"}}
await graph.ainvoke({"inp": "go"}, config, durability="exit")
await graph.aupdate_state(config, "u")
values = (await graph.aget_state(config)).values
assert values["out"] == "u", (
f"the update should apply as c, the last node to write, but state is {values}"
)
def test_update_state_after_a_fork_seal_infers_the_subscriber_that_ran() -> None:
graph = Pregel(
nodes={
"a": NodeBuilder()
.subscribe_only("inp")
.do(lambda _: ["a"])
.write_to("d", go="go"),
"c": NodeBuilder().subscribe_only("go").do(lambda _: ["c"]).write_to("d"),
"b": NodeBuilder().subscribe_only("d").do(lambda _: "b").write_to("out"),
},
channels={
"inp": LastValue(str),
"go": EphemeralValue(str),
"d": DeltaChannel(_extend),
"out": LastValue(str),
},
input_channels=["inp"],
output_channels=["out"],
checkpointer=_IntVersionSaver(),
)
config = {"configurable": {"thread_id": "t"}}
graph.invoke({"inp": "go"}, config)
base = next(s for s in graph.get_state_history(config) if s.metadata["step"] == 0)
graph.invoke(None, graph.update_state(base.config, "u", as_node="b"))
graph.update_state(config, "w")
values = graph.get_state(config).values
assert values["out"] == "w", (
f"the update should apply as b, the last node to run, but state is {values}"
)
def test_update_state_after_a_fork_seal_infers_the_node_whose_read_it_advanced() -> (
None
):
graph = Pregel(
nodes={
"a": NodeBuilder().subscribe_only("inp").do(lambda _: ["a"]).write_to("d"),
"b": NodeBuilder().subscribe_only("d").do(lambda _: "b").write_to("out"),
},
channels={
"inp": LastValue(str),
"d": DeltaChannel(_extend),
"out": LastValue(str),
},
input_channels=["inp"],
output_channels=["out"],
checkpointer=_IntVersionSaver(),
)
config = {"configurable": {"thread_id": "t"}}
graph.invoke({"inp": "1"}, config)
graph.invoke({"inp": "2"}, config)
base = next(s for s in graph.get_state_history(config) if s.next == ("a",))
fork = graph.update_state(base.config, "u", as_node="b")
graph.update_state(fork, "w")
values = graph.get_state(config).values
assert values["out"] == "w", (
f"the update should apply as b, the last node to read, but state is {values}"
)
def test_update_state_after_a_snapshotting_update_infers_the_last_writer() -> None:
graph = _build_chain_after_a_delta_channel()
config = {"configurable": {"thread_id": "t"}}
graph.update_state(config, ["u"], as_node="a")
graph.invoke(None, config, interrupt_after=["b"])
graph.update_state(config, "u")
values = graph.get_state(config).values
assert values.get("x") == "u", (
f"the update should apply as b, the last node to write, but state is {values}"
)
async def test_aupdate_state_after_a_snapshotting_update_infers_the_last_writer() -> (
None
):
graph = _build_chain_after_a_delta_channel()
config = {"configurable": {"thread_id": "t"}}
await graph.aupdate_state(config, ["u"], as_node="a")
await graph.ainvoke(None, config, interrupt_after=["b"])
await graph.aupdate_state(config, "u")
values = (await graph.aget_state(config)).values
assert values.get("x") == "u", (
f"the update should apply as b, the last node to write, but state is {values}"
)
class _UpdatesOnlyState(TypedDict):
x: Annotated[list[str], operator.add]
def _graph_never_run() -> Any:
return (
StateGraph(_UpdatesOnlyState)
.add_node("a", lambda _: {"x": ["a"]})
.add_node("b", lambda _: {"x": ["b"]})
.add_edge(START, "a")
.add_edge("a", "b")
.compile(checkpointer=InMemorySaver())
)
def test_update_state_on_a_thread_seeded_by_updates_applies_as_input() -> None:
graph = _graph_never_run()
config = {"configurable": {"thread_id": "t"}}
graph.update_state(config, {"x": ["u1"]})
graph.update_state(config, {"x": ["u2"]})
state = graph.get_state(config)
assert (state.values["x"], state.next) == (["u1", "u2"], ("a",))
async def test_aupdate_state_on_a_thread_seeded_by_updates_applies_as_input() -> None:
graph = _graph_never_run()
config = {"configurable": {"thread_id": "t"}}
await graph.aupdate_state(config, {"x": ["u1"]})
await graph.aupdate_state(config, {"x": ["u2"]})
state = await graph.aget_state(config)
assert (state.values["x"], state.next) == (["u1", "u2"], ("a",))
async def test_delta_channel_end_to_end_inmemory() -> None:
"""Full graph run: DeltaChannel accumulates correctly across multiple turns."""
+3
View File
@@ -2755,6 +2755,7 @@ def test_error_handler_resumes_after_crash_multiple_nodes():
call_count = {"a": 0, "b": 0, "handler_a": 0, "handler_b": 0}
handler_a_started = threading.Event()
handler_b_started = threading.Event()
def node_a(state: State) -> State:
call_count["a"] += 1
@@ -2775,6 +2776,7 @@ def test_error_handler_resumes_after_crash_multiple_nodes():
assert "a failed" in str(error.error)
handler_a_started.set()
if handler_should_fail[0]:
assert handler_b_started.wait(timeout=5), "handler_b never started"
raise RuntimeError("handler_a crash")
return {"results": [f"recovered_a:{error.node}"]}
@@ -2782,6 +2784,7 @@ def test_error_handler_resumes_after_crash_multiple_nodes():
call_count["handler_b"] += 1
assert error.node == "b"
assert "b failed" in str(error.error)
handler_b_started.set()
if handler_should_fail[0]:
raise RuntimeError("handler_b crash")
return {"results": [f"recovered_b:{error.node}"]}
+73 -73
View File
@@ -1404,7 +1404,7 @@ wheels = [
[[package]]
name = "langchain-core"
version = "1.6.1"
version = "1.6.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "httpx" },
@@ -1418,9 +1418,9 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "uuid-utils" },
]
sdist = { url = "https://files.pythonhosted.org/packages/90/12/aff76ca89c219ebe6f9dd3c5dbc4e3b1cf5450e9fc7037dccad23d45cd7a/langchain_core-1.6.1.tar.gz", hash = "sha256:1b156cb395aac4f009a8a1b38a574c7d948fe2d5f74c96e0d8a5017b4149e04f", size = 1003359, upload-time = "2026-08-27T19:31:14.956Z" }
sdist = { url = "https://files.pythonhosted.org/packages/ed/ed/ceecd3bfcfc77a94cf30a9f1506e907fdea447458825e01914a72d2d1a6f/langchain_core-1.6.5.tar.gz", hash = "sha256:bdb059fef65473fd444558dbb18f50901657402c43ceed9dc0fdc7b76a393c6b", size = 1007041, upload-time = "2026-09-24T18:11:06.487Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8e/25/f50dd65673c819aa33d3c34df58c115dbb6ec627d19f93e6e401dd0fc8d7/langchain_core-1.6.1-py3-none-any.whl", hash = "sha256:954a84132a5cb0435d27b910e336347b6744ecc18fbeef1e2de7029a0959841a", size = 571478, upload-time = "2026-08-27T19:31:13.34Z" },
{ url = "https://files.pythonhosted.org/packages/59/68/447ac7e734990b7ed9dcfc3b6dee9a4cd4d4169e296429fa71a9a47c1c7b/langchain_core-1.6.5-py3-none-any.whl", hash = "sha256:54c7b0e9314b9084fb04405bb33dc5d32986d512d92b7b8863899cd5f6267556", size = 572136, upload-time = "2026-09-24T18:11:04.837Z" },
]
[[package]]
@@ -1437,7 +1437,7 @@ wheels = [
[[package]]
name = "langgraph"
version = "1.2.12"
version = "1.2.13"
source = { editable = "." }
dependencies = [
{ name = "langchain-core" },
@@ -1917,13 +1917,13 @@ dev = [
{ name = "pytest-asyncio" },
{ name = "pytest-mock" },
{ name = "pytest-watch" },
{ name = "ruff", specifier = "==0.16.5" },
{ name = "ruff", specifier = "==0.16.9" },
{ name = "starlette" },
{ name = "ty" },
]
lint = [
{ name = "codespell" },
{ name = "ruff", specifier = "==0.16.5" },
{ name = "ruff", specifier = "==0.16.9" },
{ name = "starlette" },
{ name = "ty" },
]
@@ -2146,7 +2146,7 @@ wheels = [
[[package]]
name = "notebook"
version = "7.5.6"
version = "7.5.7"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jupyter-server" },
@@ -2155,9 +2155,9 @@ dependencies = [
{ name = "notebook-shim" },
{ name = "tornado" },
]
sdist = { url = "https://files.pythonhosted.org/packages/2a/c2/cf59bd2e6f2c8b976b52477e3e53bf6f97bc714ed046a51821afb428eaee/notebook-7.5.6.tar.gz", hash = "sha256:621174aade80108f0020b0f00738000b215f75fa3cd90771ad7aa0f24536a4e1", size = 14170814, upload-time = "2026-04-30T11:46:26.613Z" }
sdist = { url = "https://files.pythonhosted.org/packages/3e/c4/f71f8716f2903e9e817a47f534b9fd84831e155e2acb32c26691c8e06243/notebook-7.5.7.tar.gz", hash = "sha256:d6d59288a25303b25e1dcb71e9b017ec3a785f7d92f38b9bc288ca1970d5b0a8", size = 14171612, upload-time = "2026-06-04T18:33:45.224Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e9/d6/1fd0646b9bbd9efbb0b8ae21b2325fbef515769a5621c03e31d8eb8da587/notebook-7.5.6-py3-none-any.whl", hash = "sha256:4dde3f8fb55fa8fb7946d58c6e869ce9baf46d00fc070664f62604569d0faca0", size = 14581730, upload-time = "2026-04-30T11:46:22.342Z" },
{ url = "https://files.pythonhosted.org/packages/e1/4d/b3347f7073a377273531efe4ffc738fc910e93718fd2838c7ebf6736c6af/notebook-7.5.7-py3-none-any.whl", hash = "sha256:1f95f79d117e47d20b5555b5c85a397d2cfecf136978aaab767cf0314b09165b", size = 14583767, upload-time = "2026-06-04T18:33:40.987Z" },
]
[[package]]
@@ -2841,11 +2841,11 @@ wheels = [
[[package]]
name = "pyjwt"
version = "2.13.0"
version = "2.15.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" }
sdist = { url = "https://files.pythonhosted.org/packages/43/ea/5194e52748b0da83d71e082d75496eaec6e58f419f5e184786ded517e6a9/pyjwt-2.15.1.tar.gz", hash = "sha256:4f259e80cdfb6b3fc18a7de51fd1ef9ec79652f25019bae68975ca2468a34df8", size = 121252, upload-time = "2026-09-28T18:40:42.598Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" },
{ url = "https://files.pythonhosted.org/packages/50/ca/44de4e75f8aadc457f0634be3b542815078ded46dca30efb960edeecad6e/pyjwt-2.15.1-py3-none-any.whl", hash = "sha256:42d59d631f7768a1028a64c7ff581a9bf7519804daf91fc5b6c56e30eec5e193", size = 33860, upload-time = "2026-09-28T18:40:41.429Z" },
]
[[package]]
@@ -2907,14 +2907,14 @@ wheels = [
[[package]]
name = "pytest-mock"
version = "3.15.1"
version = "3.16.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/68/14/eb014d26be205d38ad5ad20d9a80f7d201472e08167f0bb4361e251084a9/pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f", size = 34036, upload-time = "2025-09-16T16:37:27.081Z" }
sdist = { url = "https://files.pythonhosted.org/packages/7a/7f/6ed29931d5c8cd396e7c0a55412e6cc88020373365c8685985dea53d26d7/pytest_mock-3.16.0.tar.gz", hash = "sha256:5a8395528b8f498205f3718f575228d0edaed7425fff638f87d1a6c3e0383636", size = 35362, upload-time = "2026-09-27T14:57:55.46Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095, upload-time = "2025-09-16T16:37:25.734Z" },
{ url = "https://files.pythonhosted.org/packages/db/5b/b83a9bf1a3b4ec222f9fa083147ff6816245223da0ab92370e7e056f113f/pytest_mock-3.16.0-py3-none-any.whl", hash = "sha256:007cfeb257801d88d9c0b2a7b5a15a15e73b71968dfd72e7bf8c4a2f8393aec8", size = 10016, upload-time = "2026-09-27T14:57:54.283Z" },
]
[[package]]
@@ -3352,27 +3352,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.16.5"
version = "0.16.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f3/85/c8e12473c93018f92d19dd988a294202e1c27426c47ec4de53ffb847b8d8/ruff-0.16.5.tar.gz", hash = "sha256:1b88500f9ffbcab3dedb0082c9f9492e91ec3d618aac1236a3e0189938f7040b", size = 4912003, upload-time = "2026-08-27T16:34:18.258Z" }
sdist = { url = "https://files.pythonhosted.org/packages/96/bf/c935ca98e73fe8ce65b87ef08a280c0c1e85295d569228c15e87d8fdfaf1/ruff-0.16.9.tar.gz", hash = "sha256:12b625c6cfba78d285d9f48eda5f053374f1e53cb10ef17342a383750db99161", size = 4948764, upload-time = "2026-09-24T20:37:49.416Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c6/b6/77c90a970fe2dae17a723acbd011043ea97c98d7deacccefdc4ba74ec512/ruff-0.16.5-py3-none-linux_armv6l.whl", hash = "sha256:12e5f673e774c35fbb62f288809c7653b73445f8ecec6b6063fd6ea3521aa14b", size = 10011941, upload-time = "2026-08-27T16:33:41.287Z" },
{ url = "https://files.pythonhosted.org/packages/4b/46/6cf67cf6411885a1d6f7f6d801682f155536a85176d10b605e2ceffed8bd/ruff-0.16.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:eda58a5802de40e7ed5b32b64e0b32539338cc6fcd2c78f61e3ad6a0d79f51c3", size = 10204049, upload-time = "2026-08-27T16:33:44.056Z" },
{ url = "https://files.pythonhosted.org/packages/46/fd/c8720ca7a090abf0c2fef4abe8a5ef6e5127ed15196d8886ff75a2b370e2/ruff-0.16.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5ae9a7b9a8875131f40f8fe967cc86abf899779efd663cb7ce3d572d01da7eb", size = 9809037, upload-time = "2026-08-27T16:33:46.257Z" },
{ url = "https://files.pythonhosted.org/packages/43/45/a684caacdedaca180f52bacccc40bf0789d2c5a7c75f25324853e9eaedb5/ruff-0.16.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b719b0a1f4d59710d283ab2965f621684a108a9e41da622e3b23f0326cd0025", size = 9964129, upload-time = "2026-08-27T16:33:48.352Z" },
{ url = "https://files.pythonhosted.org/packages/9e/f2/5d2bcdaca6b5b93d1b4dfc166cd2aebf7680143a1b38a28759df13a94d31/ruff-0.16.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2298f2780ed1be0c5cb1361e32ab7b1467f3cce7dabe101d2210a314f2fe42e9", size = 9821518, upload-time = "2026-08-27T16:33:50.57Z" },
{ url = "https://files.pythonhosted.org/packages/aa/ff/011cce29accf9257d5974145b733fc653a37985ed6825413a3987cefbfe0/ruff-0.16.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:258f29035a2dd021e7861e631b227a5b3f14e50c1184c9a6a122c5f4576154d7", size = 10534835, upload-time = "2026-08-27T16:33:52.522Z" },
{ url = "https://files.pythonhosted.org/packages/d7/5a/f0cf109bada9bba0e96c90c21c9f9251803f57225c32d293327a03c710d6/ruff-0.16.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9a4f0432966834019c74d1b7e5c51224305d7713f3d7faf3e7451f1a3be3cde", size = 11252550, upload-time = "2026-08-27T16:33:54.521Z" },
{ url = "https://files.pythonhosted.org/packages/63/4d/1d481aaea2046c6a7ed7c291f9004c669cce3c087b6b376ed5b08271e3fe/ruff-0.16.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5eb3a8c3d0ade9cea42b591fd530368e8798380e30e0a308b85a5cf718f09ea", size = 10777949, upload-time = "2026-08-27T16:33:56.88Z" },
{ url = "https://files.pythonhosted.org/packages/ee/34/ee245ca55f64443233034b3d02b03236b19242004281247c079390b7facd/ruff-0.16.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef0f69e191a13a3c9816f63163c88790cb12cd157bbbb384e9c44745702ab105", size = 10311656, upload-time = "2026-08-27T16:33:59.12Z" },
{ url = "https://files.pythonhosted.org/packages/a7/4d/c33a333e341c0a2b96c715b52d89a606f5a34cd4ac493cd9b8d0187186b8/ruff-0.16.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0eeab41fbea2c42f98dfb9822cdccda9d24ba38d49f6dc945b5c236d48f0ef29", size = 10532125, upload-time = "2026-08-27T16:34:01.166Z" },
{ url = "https://files.pythonhosted.org/packages/30/e1/a64cef78b40192497bb98a27a8aa8f2c98ee9ee15bc97f7712d94ef32937/ruff-0.16.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f0768e9df4300713fff30733c87575f68b6f1d8de41184e505b7fdd9c0c95eaf", size = 10097648, upload-time = "2026-08-27T16:34:03.16Z" },
{ url = "https://files.pythonhosted.org/packages/cc/4e/4cdc9ed3c3e109d2f71e62572a37457298d7bc7501ec3138babb7ed32bbd/ruff-0.16.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:95cc70cdc7aa80c338de356279d2adbeb2de0f520b9ecd8aba75b94e95e02f91", size = 9829344, upload-time = "2026-08-27T16:34:05.134Z" },
{ url = "https://files.pythonhosted.org/packages/39/4a/31ed35ce31729955fc583ee0d176d6e784c1290cb0b0a75cb2134c1ab72a/ruff-0.16.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d185c8398ded1bfd91c0c2cb258346307571eccc473a8490af8c3977399c384a", size = 10277117, upload-time = "2026-08-27T16:34:07.425Z" },
{ url = "https://files.pythonhosted.org/packages/a8/a0/60356d86687b4b666d593df213f4dc3041750d024cb7bf2cfa81cfd65c2e/ruff-0.16.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:fb8e3a3c4c6a784150a7ced53b015f4b253fc2bf97a610886419ead64b4756ef", size = 10711653, upload-time = "2026-08-27T16:34:09.712Z" },
{ url = "https://files.pythonhosted.org/packages/ed/20/656d67f5b25ca9bda4e02b1de25867b2954e1d19e03648060f167ad0f4cc/ruff-0.16.5-py3-none-win32.whl", hash = "sha256:288b0a5f080492fe5635db849f9e2e84aa3cce7b7f0e955997d416c507c76a26", size = 10034250, upload-time = "2026-08-27T16:34:11.8Z" },
{ url = "https://files.pythonhosted.org/packages/5b/42/ee8e68a207b9127fcde6c3d7e197def432f346cb1af159e1fa14ca0d1cdc/ruff-0.16.5-py3-none-win_amd64.whl", hash = "sha256:ddc6385fb2137f616357ca03d6c74f4be987f80fed4008566b754f6032b8546f", size = 10516714, upload-time = "2026-08-27T16:34:13.963Z" },
{ url = "https://files.pythonhosted.org/packages/73/e3/7df5a396e445b9ba49ce9a9437439a4d80042c61c0ade199abf8d16de1ac/ruff-0.16.5-py3-none-win_arm64.whl", hash = "sha256:a64abe90968719b851bb7cedffaa8753fbdbdadab483089682db623f3edc587e", size = 10391564, upload-time = "2026-08-27T16:34:16.064Z" },
{ url = "https://files.pythonhosted.org/packages/0d/26/df51322b52ee1ada7eff2d071ea09d11d5c2d1dcc9f02594f5785c4d1635/ruff-0.16.9-py3-none-linux_armv6l.whl", hash = "sha256:95e6f022090368ab3b824c36276839c53b2adf1a3f4c09fefc33dfc400f6da96", size = 10082922, upload-time = "2026-09-24T20:37:13.045Z" },
{ url = "https://files.pythonhosted.org/packages/a5/27/7bf51f5a7aa375e9f339280a303aab44ca75dc1525f1cdc5991761685b0f/ruff-0.16.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a5f27be168556594a86d2f415db0cf43f5291917849318f873c7e2791f7a8c67", size = 10236360, upload-time = "2026-09-24T20:37:16.049Z" },
{ url = "https://files.pythonhosted.org/packages/b6/63/09659283f92f02dff45809da194a70da2f688d87c55d8875c4fae3536072/ruff-0.16.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1632eb1d6197f33bd00b1acbc5b71009e89a8895c158e2d2b03a834fac964ab6", size = 9892940, upload-time = "2026-09-24T20:37:17.957Z" },
{ url = "https://files.pythonhosted.org/packages/24/58/98de1b72ec172f5f8f1731236fe21585b3998bf7dfe9fcc44ae9ba626012/ruff-0.16.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3f951b14d865d5952c89d40a5ca07e87abe24fa5453299878411e127748fb1c", size = 10032114, upload-time = "2026-09-24T20:37:19.942Z" },
{ url = "https://files.pythonhosted.org/packages/c8/7d/f1e17c54ab59d4bad1dce8ee3e22a7a1d0ef4745240decacdcf3832b5bb2/ruff-0.16.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:447fc07e1573afff7cb02803462b12b6c8ece7cf10e2cd78565fa6d7a1c0bf8d", size = 9910227, upload-time = "2026-09-24T20:37:21.872Z" },
{ url = "https://files.pythonhosted.org/packages/34/19/436f647a65075bbd3bab2668b3bdaa5120559b294694018cdcefabbbf30b/ruff-0.16.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a3e039a6a40ed976c491722b60e0ae4a4aa1a86057f540ee7a37a5d19ae9120", size = 10547484, upload-time = "2026-09-24T20:37:24.229Z" },
{ url = "https://files.pythonhosted.org/packages/03/59/38430a6bc2f6d8095447ac39625cf8b6e9344a47e6c26225c8ba1bff3ffb/ruff-0.16.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4684dded7db60aa57cb118fa158630f5feade4af5782903b6053484bdf9bd129", size = 11412367, upload-time = "2026-09-24T20:37:26.307Z" },
{ url = "https://files.pythonhosted.org/packages/c8/bd/bbb6d7fc7f208c8b8c50dd5dc8206e4cfdb1e7a8fb852606a3adf370c880/ruff-0.16.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d29c934357e45642fda2f34c0b1f4025b4a6c01e15e4bf0016879d60078a142c", size = 10869787, upload-time = "2026-09-24T20:37:28.35Z" },
{ url = "https://files.pythonhosted.org/packages/bc/b8/9c543074918061abbefc3bd139bee22de35abedb00dde0f2d27288838962/ruff-0.16.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a21713e629d3e5bdb2f5c2def1cc7f04f47fa8e1a7eb0571b4a28e1da64bc728", size = 10406494, upload-time = "2026-09-24T20:37:30.624Z" },
{ url = "https://files.pythonhosted.org/packages/35/7a/5a8851bd146e7ccf8fd4b003f6c75c11f8fbdb0e60673b45097986b6bf41/ruff-0.16.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7baa24ef5fc8e77aa93879e1d3f43754a01ae488e869f1ae30cf431afd4d2452", size = 10590083, upload-time = "2026-09-24T20:37:32.439Z" },
{ url = "https://files.pythonhosted.org/packages/87/f0/4c3467188f23f806960b46fa76575a7cd0514c9ba90562650b71efc96980/ruff-0.16.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a41aac6230aadfaa133bdfa1614488531ffa3e0837567ae04c0da2058a9c0f9e", size = 10119151, upload-time = "2026-09-24T20:37:34.581Z" },
{ url = "https://files.pythonhosted.org/packages/15/34/5a4def5adea572ce6aea0bb64f21f928ee317b80e0db747d7979b01d7261/ruff-0.16.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c2529fb5896d49115b0e9aa8f887490b34bbe76baf879ec2264ac59406869ce7", size = 9911544, upload-time = "2026-09-24T20:37:36.796Z" },
{ url = "https://files.pythonhosted.org/packages/62/5d/d15ebea7499eef9373318c0ee6ca127832927c6529731f6d48e18dce7ca9/ruff-0.16.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:41e3870277694177429b56406d65dfbdb2c2802c52b715edaf6a0b829c69d4ee", size = 10269884, upload-time = "2026-09-24T20:37:38.857Z" },
{ url = "https://files.pythonhosted.org/packages/d1/56/c5d3cd119ded7a3c7aba0e961b69cb3df701c91662c98ad694467d060ce1/ruff-0.16.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8adbe4e58af167f767d7b2ba5e83c42e878350796cf78c2f5e14ab9903a92588", size = 10749366, upload-time = "2026-09-24T20:37:41.042Z" },
{ url = "https://files.pythonhosted.org/packages/ac/fe/734ec7527029ac757ecf821f143c9f3fcf69149c21f53a044a899b430f5a/ruff-0.16.9-py3-none-win32.whl", hash = "sha256:0e1dbc2073624dee6618d41d0098690a7244654af746704b64759e12b6b6b385", size = 10152355, upload-time = "2026-09-24T20:37:43.025Z" },
{ url = "https://files.pythonhosted.org/packages/14/21/26e4643629b3ebb44f0a06f9c9a53058d63d989415f63a9a3c28e2ee7f22/ruff-0.16.9-py3-none-win_amd64.whl", hash = "sha256:6bd40fec8cd4c8a3d4dd589bd8ad4e6320c13c29234159bfd959a40d529d597b", size = 10592965, upload-time = "2026-09-24T20:37:44.944Z" },
{ url = "https://files.pythonhosted.org/packages/51/60/5fb1a39dbb5ae314d5f59bc7348a63c1d5c20f3cd83914c4b5cb0be31d2d/ruff-0.16.9-py3-none-win_arm64.whl", hash = "sha256:ed1a252039200f57a59eebc063b54beabea67bfbaaca0eeaa7f54b5fbcda2284", size = 10458649, upload-time = "2026-09-24T20:37:46.882Z" },
]
[[package]]
@@ -3475,14 +3475,14 @@ wheels = [
[[package]]
name = "syrupy"
version = "6.0.0"
version = "6.1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d2/a7/3c797c76994dc817582abdda90ee31867a9883567b0add47dbc0ccb12ce4/syrupy-6.0.0.tar.gz", hash = "sha256:bf4f5f662a7b23a9e5711bd5597e301cd09c00f31be5fa4095f79da7b0585f3d", size = 99435, upload-time = "2026-08-22T20:48:39.493Z" }
sdist = { url = "https://files.pythonhosted.org/packages/74/2c/8ffc1414d1951895d0d5b7dc83c0b079ebc48c3bf27ffbb0064646367500/syrupy-6.1.1.tar.gz", hash = "sha256:7e584a8df4ede6dd3c1c44a77f9edc46186b6767a73dea6f0083044946839a59", size = 109705, upload-time = "2026-09-13T20:25:21.599Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7c/ff/4d8ae6d6070ea73ee9d466701584a75db9586ce09de98f8f1b3276efad5f/syrupy-6.0.0-py3-none-any.whl", hash = "sha256:3efa16d767bd8614413cc20057552e4aec14428c6e5ea788c1f7e03047e8a5e4", size = 58047, upload-time = "2026-08-22T20:48:38.213Z" },
{ url = "https://files.pythonhosted.org/packages/2c/b5/bf2a8a335a6a813869dd482cedbcde252f582b5afbfe50eb78ec09962800/syrupy-6.1.1-py3-none-any.whl", hash = "sha256:6ac9ac6a42d70ae44156f5f157a9563b9bb8cc96dcf9364327f330463bff889a", size = 63436, upload-time = "2026-09-13T20:25:20.294Z" },
]
[[package]]
@@ -3576,19 +3576,19 @@ wheels = [
[[package]]
name = "tornado"
version = "6.5.8"
version = "6.5.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/10/d3/343e5bb989d6515b1646cf3d40135d73f3d5e45339bded401b56cdac24dd/tornado-6.5.8.tar.gz", hash = "sha256:9452e1b208a8bd771e2cb1f2ff564985b9b214bdebbe622793e1799e0a6bd23f", size = 520493, upload-time = "2026-08-07T02:12:42.971Z" }
sdist = { url = "https://files.pythonhosted.org/packages/22/15/ca7aaebb77f850493cba71ace508aeffb896d1ad8976417b48b79823dbd2/tornado-6.5.9.tar.gz", hash = "sha256:4d868544ebdf2fc155239a74397f65ebfea9b4d3635296c96b5dfb0701c354f5", size = 536145, upload-time = "2026-09-14T18:08:37.434Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f2/d5/007086fd8df5489338e204f65adce33fd4f21a4999dbb2b9cff2f897b5f4/tornado-6.5.8-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:cc6aa787d7cfab7c3d35189dc7a56fbd2399a569624c730c6b55b3d6531d0403", size = 449487, upload-time = "2026-08-07T02:12:28.682Z" },
{ url = "https://files.pythonhosted.org/packages/70/c8/5a24a99495903f594f6a199dd7beead1cbc0a13e2cb9102727bcaaf2a997/tornado-6.5.8-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9715b5eb79735b2bcd454ce216a9275b7c0470e64ea1bf5742f78b2f72b26eeb", size = 447649, upload-time = "2026-08-07T02:12:30.306Z" },
{ url = "https://files.pythonhosted.org/packages/6e/de/f2e733f386b85962d1b1dc82cd63d169b5b4580062b35397eac9244a41fe/tornado-6.5.8-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:547d63f450d570c14fe0e8db2cfb14c9bbd1c2503b4a6612586267955aa47b58", size = 450707, upload-time = "2026-08-07T02:12:31.95Z" },
{ url = "https://files.pythonhosted.org/packages/0b/94/20efeee9a01c141e9ac47c397f81679dfda24b32768fc4fff24e76d36c2c/tornado-6.5.8-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e2360a0ffbe145eca8af0b19cb7203d79b1a98dd4cccdd6b368f6f49c2e3808", size = 451677, upload-time = "2026-08-07T02:12:33.512Z" },
{ url = "https://files.pythonhosted.org/packages/42/ec/a96ccb8ccf0de2b7bc2c5fa1608a4803735018242e90c4882365a9fd418f/tornado-6.5.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5d242290bdf7ab3151bc1065fdd75c0dcc21cbc7b49f22a4c56329c2d6566d22", size = 451510, upload-time = "2026-08-07T02:12:35.346Z" },
{ url = "https://files.pythonhosted.org/packages/29/b5/93185859245ad3f00e62175f29607346788b696369347f0146e0421286bb/tornado-6.5.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7b94ff0e128fe0542f3bd331fb44d06260fc4ac16881545159f34ef08aad4195", size = 450917, upload-time = "2026-08-07T02:12:36.963Z" },
{ url = "https://files.pythonhosted.org/packages/97/cf/fe33cf062834487d34d1559746a4a12521033c22645b6d74d4bca702e018/tornado-6.5.8-cp39-abi3-win32.whl", hash = "sha256:67832909c4779c64942380cb5f044a5c6163d00831472d80e25e115de9917836", size = 451952, upload-time = "2026-08-07T02:12:38.512Z" },
{ url = "https://files.pythonhosted.org/packages/cb/e1/468ad54333e92ccb62627e62cb88e5fc14a2171daa67ed47b1b8542d5b86/tornado-6.5.8-cp39-abi3-win_amd64.whl", hash = "sha256:11881db6b7c168494be2c2d12e65931451bdf7ee718535418ae1d8855dd5a0ee", size = 452391, upload-time = "2026-08-07T02:12:39.971Z" },
{ url = "https://files.pythonhosted.org/packages/ad/3e/cd5e4f06e34cde33b8ef66cf36aa2b5ad46354cc1af7d2136bbe365fee1d/tornado-6.5.8-cp39-abi3-win_arm64.whl", hash = "sha256:68a7468c7e289f8514d7d664101753903217eff1bb6822c6b5994a0b5f5bcb26", size = 451411, upload-time = "2026-08-07T02:12:41.469Z" },
{ url = "https://files.pythonhosted.org/packages/a0/4a/4d3459fd2f360dd99233f69f22b36012a42856ace526da2c6da3cb0e6df2/tornado-6.5.9-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:dea3bee433b73d6312d993ce89ad5f2b8d3ed9fde56e79ba5342b9edb78d342a", size = 464279, upload-time = "2026-09-14T18:08:20.909Z" },
{ url = "https://files.pythonhosted.org/packages/26/4b/5af2f7dcd674e2f1cacef763456f79823404f50954789d6e1ec7a70cd58a/tornado-6.5.9-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:22bed49cdb55292d1d58f46008ba2cc3020e5b84995ef6ae749676c8b5309514", size = 462440, upload-time = "2026-09-14T18:08:22.711Z" },
{ url = "https://files.pythonhosted.org/packages/9e/0f/38f8d16011de3b1ce2babb4c3bcefb126d2dc47d04878ae3ad5c39a00caa/tornado-6.5.9-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0cc0876a58eee9143476f24901b1b8eb4d52443283ade2b6bca650dd1da04f84", size = 465496, upload-time = "2026-09-14T18:08:24.407Z" },
{ url = "https://files.pythonhosted.org/packages/8c/e9/3888f265d1e287fc63cd61a6696f96a650024e32f9e89c0b1817ac5c40f4/tornado-6.5.9-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc0d703cc7ec92b47ebfe236c97cd765c1f2e45744a2e156e6677e54c948274d", size = 466468, upload-time = "2026-09-14T18:08:25.928Z" },
{ url = "https://files.pythonhosted.org/packages/d6/8b/d2bcf417981fa6f7698ab84a52394a76cf608e6704d266e2e0e29f1fd9d0/tornado-6.5.9-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:93f9ab0226ef625b94cacb7981a5af104f1735ea02f92282abe5c389109fb31d", size = 466303, upload-time = "2026-09-14T18:08:27.566Z" },
{ url = "https://files.pythonhosted.org/packages/7e/a5/c5cfab11420c3f908238a6c861b8f3864fdbd2b2b87e30c9c16f36a11512/tornado-6.5.9-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5801bbf94dfde8d21087b6aa0b17f3a5dab6110dfe44e7e4492df5de393ac15b", size = 465706, upload-time = "2026-09-14T18:08:29.182Z" },
{ url = "https://files.pythonhosted.org/packages/ab/36/5a5da0aa15b7afdd46ece09c004a75af7d00f6a96b692bf696ff94bc2a55/tornado-6.5.9-cp39-abi3-win32.whl", hash = "sha256:dca9f377e80efe5dd4d52a2776b67492a81a39b2d931de169b6b36d0c1da444c", size = 466750, upload-time = "2026-09-14T18:08:30.836Z" },
{ url = "https://files.pythonhosted.org/packages/34/d7/2446cf3125372e2b4be6483b4b93f360dc50ce2493864755484b23bb50f2/tornado-6.5.9-cp39-abi3-win_amd64.whl", hash = "sha256:f810730ac71eadf009e6e5cb6d534d096887310f5649cff19d7e0d19c0bf4ee7", size = 467191, upload-time = "2026-09-14T18:08:32.521Z" },
{ url = "https://files.pythonhosted.org/packages/39/70/f1024364bf78fa921c63ef2883d36a3b3b705750c98ae174593afaab7a65/tornado-6.5.9-cp39-abi3-win_arm64.whl", hash = "sha256:b5f4d92798337260c6d9f9f0e400c7539dd5e55cf93479a3f8508c9aa09c2b3b", size = 466211, upload-time = "2026-09-14T18:08:35.18Z" },
]
[[package]]
@@ -3611,39 +3611,39 @@ wheels = [
[[package]]
name = "ty"
version = "0.0.75"
version = "0.0.84"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/81/d0/d0c96f898d6974a4a3569ab3efdf9512c04ad99f9203effb55f72497fe97/ty-0.0.75.tar.gz", hash = "sha256:4c5eead33dfbf6e2ebb4f400f74b51ffc9bab702a6f23ddb648a1cbb740387e3", size = 6868326, upload-time = "2026-08-26T20:23:40.399Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e1/f6/34f8869c45ea87fe6a931ffa824b1fe4428167173543d92988d631add355/ty-0.0.84.tar.gz", hash = "sha256:0cefdb0cd5d399418dbe83c349ba605047b7dff815ae6f460c80e8522b40be67", size = 7409537, upload-time = "2026-09-24T13:16:24.367Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/6c/b12d03505f17581f0cfa3c12273fe34c1d67b36dfda1bc561a6bdc16512b/ty-0.0.75-py3-none-linux_armv6l.whl", hash = "sha256:e5409f50db2246fd4bd039d93d261e0cfa1daa554a4fb77256f91072c570349a", size = 12972606, upload-time = "2026-08-26T20:22:59.716Z" },
{ url = "https://files.pythonhosted.org/packages/d1/aa/30f11eecd9215a9f87e8fe8baaf48f3ce905f5d75b8e4aac70f0091f130c/ty-0.0.75-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5e7b8b3472fb9bb2eeab314984b265df08a7a9d518867a9e6020eebc06570be2", size = 12527158, upload-time = "2026-08-26T20:23:02.767Z" },
{ url = "https://files.pythonhosted.org/packages/f2/11/7fd7001b0b5c6610bfbad7357e47d5fe6f82d4e84e94c53776a478f5e9f8/ty-0.0.75-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c6ccf34169821fe0d23e3360deeef981d217963412f1d087b9bdd32ec57f7a57", size = 12400533, upload-time = "2026-08-26T20:23:04.965Z" },
{ url = "https://files.pythonhosted.org/packages/fd/7f/1e284ea3d348d7be02f12d83bc22ed9ef193033f863f05b64db99027f141/ty-0.0.75-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842ebb41e9c6c334b40768704e20b1a69d5c6b08805b289d5e0e2565f49f2de1", size = 12420592, upload-time = "2026-08-26T20:23:07.427Z" },
{ url = "https://files.pythonhosted.org/packages/2d/ab/d813271543370c47fd74b5118f2066ab32b0983e907b1821f3f9a6d0fa7f/ty-0.0.75-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf7a5a723c5f1e0fab4ffbfe9bd95123a526ed48f206e5f25cb2161ca294007a", size = 12739219, upload-time = "2026-08-26T20:23:09.809Z" },
{ url = "https://files.pythonhosted.org/packages/31/5b/95b49cc5570fd92a7bf63732f649b31906158721e03c7fcb1b5be74ee3bf/ty-0.0.75-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54382f98e5da292fcd7104391afef5105c35bb2f312e29bea6f5fa419935255c", size = 13494046, upload-time = "2026-08-26T20:23:12.191Z" },
{ url = "https://files.pythonhosted.org/packages/2c/0d/502d2dd68173cf020e1ad2bdbab9544c86776de0b0e2ed15f8c2fe006e3d/ty-0.0.75-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac13b180dc2aade2cd243f56b01650e78bf091a2e522ad3bc947245d7837c613", size = 13938899, upload-time = "2026-08-26T20:23:14.764Z" },
{ url = "https://files.pythonhosted.org/packages/20/5b/f3b12a25c07224456219fc2bd20db0ad7e40b304be0ff6aad728da0135f9/ty-0.0.75-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:752df7951a443219d7f1ff817e3723c85d428565ff449e08a7a93ba821661526", size = 13656711, upload-time = "2026-08-26T20:23:17.145Z" },
{ url = "https://files.pythonhosted.org/packages/51/7b/f090ad306e2b15a07b332d647138c5264b89d9758855ecce8b8a10bcb153/ty-0.0.75-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fd399feedf7cee816563c1baec45fc1c0b3c89f1ea42364920b688004b5b7da", size = 13093499, upload-time = "2026-08-26T20:23:19.489Z" },
{ url = "https://files.pythonhosted.org/packages/f1/4b/f69b99aaaca0c7c65d5f114b186b26b21666f767b0c69eec99a2bdccc061/ty-0.0.75-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:d7625f6f56c7dc1e873579fdc9e432a0e21e302afe847ab60704d2303442a92e", size = 13520580, upload-time = "2026-08-26T20:23:21.789Z" },
{ url = "https://files.pythonhosted.org/packages/b6/e7/692c5f905c0345a15d2255fc74066d660f030254ae8dcdaf33f5a5c2f279/ty-0.0.75-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:89e7d527e95a2534b70cae29e94c104b84082760ea05927d23bb87280969c104", size = 12524095, upload-time = "2026-08-26T20:23:24.026Z" },
{ url = "https://files.pythonhosted.org/packages/ba/9a/f42b12cf265ea95344bf554764c4791cfb273bdd628aadd7c209af7cadc3/ty-0.0.75-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0843f134440740706e01bee5f88f4cfc10e9b018bddb9e4ef4c12dc9fc0c9aef", size = 12756591, upload-time = "2026-08-26T20:23:26.126Z" },
{ url = "https://files.pythonhosted.org/packages/7c/5e/9b180c133cb9cce48179a7d2bf9e1802d992aa8176a918e0e05205760b42/ty-0.0.75-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1bd0ec0e50ee1376875c88891efe6f549c3560fa5b2ddad79a425cd5a6218b9c", size = 12998754, upload-time = "2026-08-26T20:23:28.353Z" },
{ url = "https://files.pythonhosted.org/packages/39/f6/3c6ef5dd550103e29905121c67fb96a374564f31a2f44c6faa1af98c2d61/ty-0.0.75-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1f9eafd561f90110d5e29f589ec3e956c4686e2f6631348d99276436f5cbe4d1", size = 13316474, upload-time = "2026-08-26T20:23:30.857Z" },
{ url = "https://files.pythonhosted.org/packages/bb/52/12776337874c821076bd5368e352ccd9e67174790abe3b856f749cb3524b/ty-0.0.75-py3-none-win32.whl", hash = "sha256:05063a6fafe2154b794a7f964515d148e51acd186d72d4a3acd347ee9fa19336", size = 12316315, upload-time = "2026-08-26T20:23:33.528Z" },
{ url = "https://files.pythonhosted.org/packages/53/e6/bb51e16af5c7138c9f52f8f3d0a401a371c6798d092e3b74926f186a9814/ty-0.0.75-py3-none-win_amd64.whl", hash = "sha256:81cf1ba5f6b7536ad56747865214255d9bc8e80533a689dbb9ddeaad464b09f1", size = 12917267, upload-time = "2026-08-26T20:23:35.978Z" },
{ url = "https://files.pythonhosted.org/packages/39/73/4542f829107468b5de4231af67f29927c093bfad11f3c1e5b2c08fb1206b/ty-0.0.75-py3-none-win_arm64.whl", hash = "sha256:541c9af5b7a0ad23d15ec315a7da81150833c359f48124ed3789ff25eacd6f42", size = 12711024, upload-time = "2026-08-26T20:23:38.159Z" },
{ url = "https://files.pythonhosted.org/packages/aa/0c/600648778e1c79133ce6b6a5c4c2531ae16b90c9b30f5041b38b574f61b8/ty-0.0.84-py3-none-linux_armv6l.whl", hash = "sha256:868438e2b9abfc835dd5b5b07ed693db95d8348ac40e3228252511d63ae87695", size = 13935333, upload-time = "2026-09-24T13:15:31.167Z" },
{ url = "https://files.pythonhosted.org/packages/c5/3b/27f06f49945c36170765fad82076898039ae3873338e9865f876dd62f12c/ty-0.0.84-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b00f39b521f0b559cde0f6abf8dd47213b513b04f33d58efeb9b98486a16bb17", size = 13511328, upload-time = "2026-09-24T13:15:34.446Z" },
{ url = "https://files.pythonhosted.org/packages/fc/b6/b12dd130e7f30141f0645614f454c925991cd389b1cc6c8284fd6bf32326/ty-0.0.84-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8f78c2915567f2ee62ce0c24d86091bc76f81577677755e242d09951db588b9a", size = 13445445, upload-time = "2026-09-24T13:15:37.476Z" },
{ url = "https://files.pythonhosted.org/packages/44/96/f012de4b3c1d9a4773326621380d768b4d48c47e620dc012775c5e01c7d7/ty-0.0.84-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61155cad0921e890d86d1d911a40b3a0e924ef4bdc3b4f3865a6c89c7e3012dc", size = 13471235, upload-time = "2026-09-24T13:15:40.64Z" },
{ url = "https://files.pythonhosted.org/packages/05/32/dca630f5f5353fa7bf67eebccf1549df99b16656d21071d0df6677c826a5/ty-0.0.84-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:417c3bf14947ed16b0b92976ab333c27915590354e96d4f581709068d3811355", size = 13680704, upload-time = "2026-09-24T13:15:43.817Z" },
{ url = "https://files.pythonhosted.org/packages/44/8d/33702c8f62f05ad45b33644fb914d483de6a0a7bc8e51884e9b8773e6d69/ty-0.0.84-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e06ef117759f654f5379efe9ae79bda8a186016c016f1023d05c34f8e15c1546", size = 14518923, upload-time = "2026-09-24T13:15:46.802Z" },
{ url = "https://files.pythonhosted.org/packages/c8/a1/da3246e6ef2ae0e842bca4058b25c54bee55ab058ffff4ee54e72517ec01/ty-0.0.84-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a05d1d53db8b64410ab38c6e32c5898510584869d1d5dd9c0605db81c9aef7df", size = 15027731, upload-time = "2026-09-24T13:15:49.755Z" },
{ url = "https://files.pythonhosted.org/packages/20/17/b0099098a560aeb4f9fde6c912f9a81622c3e44e6555e1fbe322b368ec31/ty-0.0.84-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b92400494ab855cfb1204ac1101e3f53b2d09a8e21d171758b2cf9acdab1809e", size = 14748260, upload-time = "2026-09-24T13:15:52.713Z" },
{ url = "https://files.pythonhosted.org/packages/60/d5/32cd67aedb271f006e716ad093806c96c5d7e2af86be8255469dbd3d76c8/ty-0.0.84-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af17eb391ae3027fed9be1780bea555c2b8a25ba68e184c627b4981b2c9eaab7", size = 14205858, upload-time = "2026-09-24T13:15:55.677Z" },
{ url = "https://files.pythonhosted.org/packages/43/c4/638ac62ca2e8eca1b92e3e16273085744fada728b993500819b5c258ca15/ty-0.0.84-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:44cf06af0e7ec78ea6d8ff33a3450fc19627756a4fba681f7410d4e3ef63047a", size = 14573196, upload-time = "2026-09-24T13:15:59.165Z" },
{ url = "https://files.pythonhosted.org/packages/a6/f6/9ee81c5d8921e5fd5f10889ae563c95cd3272b31df2ada528919ca1cef6b/ty-0.0.84-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c6e56b443ff9ba462e34bfbc1e582004c2719ed35f8f93a433744b0ba0afb2d9", size = 13480760, upload-time = "2026-09-24T13:16:02.313Z" },
{ url = "https://files.pythonhosted.org/packages/f6/83/fbe5d1177667ae16d84c3242846b143809c9cc09568b333e5a9b4d5908f6/ty-0.0.84-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b6562fcc48820c1030e2a4509ef2c14ef93043ca4860280074314ac3a825b95", size = 13696346, upload-time = "2026-09-24T13:16:05.391Z" },
{ url = "https://files.pythonhosted.org/packages/86/9a/1b4ac9ddc34cc0ab4624bc219825d66af52f1ad87f4778ad08ad03fa06d5/ty-0.0.84-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dee7421451efcbd70f03e95a8f2c8d9e5ec3d35edcd27b4095ee00ee062abfc4", size = 13959410, upload-time = "2026-09-24T13:16:08.661Z" },
{ url = "https://files.pythonhosted.org/packages/c9/04/70e289437a67dfd686056ab4fd91880261a8233033a6a95d29393741fb97/ty-0.0.84-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:31e96307cf621babe969307dd657783d672e2d8bdbd06493710da635bf63fa07", size = 14350294, upload-time = "2026-09-24T13:16:11.865Z" },
{ url = "https://files.pythonhosted.org/packages/9c/f4/ae7dbd118425c850981d23efb850f0d9d7f6b8d2b852bde2767434f668b4/ty-0.0.84-py3-none-win32.whl", hash = "sha256:4bdc85f91cbaae35825f2b17bb4ac5de0563367875cb0f42b2bf07a1bf7ff2ba", size = 13176439, upload-time = "2026-09-24T13:16:15.049Z" },
{ url = "https://files.pythonhosted.org/packages/29/ec/994d87252f065dda5a500bc8afc726d18f6582d81d6f4ff1feb8a267c800/ty-0.0.84-py3-none-win_amd64.whl", hash = "sha256:71cc9aa7a7c89d4e12c6a814e9c0c3310ad5bee44efedbd6f5a42d91e9ac0f0d", size = 13962879, upload-time = "2026-09-24T13:16:18.191Z" },
{ url = "https://files.pythonhosted.org/packages/6d/1c/e6e91852b72566b1ab9aca504712857dfb89324c12092a5bd61d42d34427/ty-0.0.84-py3-none-win_arm64.whl", hash = "sha256:6c9d3718c4a0d318bc9c92af9b2aa85c3294e7dff54cf1d69ad79568f56516da", size = 13656453, upload-time = "2026-09-24T13:16:21.51Z" },
]
[[package]]
name = "types-requests"
version = "2.33.0.20260712"
version = "2.33.0.20260906"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/db/51/703318f7b7be8bee126ec13bf615050f932d0179b8784420f3a0199cc769/types_requests-2.33.0.20260712.tar.gz", hash = "sha256:2141b67ab534a5c5cd2dac5034f2a35f42e699c5bf185eee608c5246a069d7fb", size = 25084, upload-time = "2026-07-12T05:14:20.455Z" }
sdist = { url = "https://files.pythonhosted.org/packages/c0/18/4c2c0290953f8b3b9612adfcb07b57f144ade3ad32a76764fca42b77c5f3/types_requests-2.33.0.20260906.tar.gz", hash = "sha256:76ab8a0fb736744a0c3deee7aa57b2927e301f078d9e61f5391b3e92002416b9", size = 25263, upload-time = "2026-09-06T06:35:47.707Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/62/e7/010c87f559e216d83f9dc51e939633fd0d0ead3377340181ab0e223cd3b5/types_requests-2.33.0.20260712-py3-none-any.whl", hash = "sha256:de027e28c171d3da529689cbfa023b0b4eab188c8dfa22fd834eebd2cee6e7bb", size = 21392, upload-time = "2026-07-12T05:14:19.616Z" },
{ url = "https://files.pythonhosted.org/packages/60/4c/51ec821d22a45b4162fa3f3e9e94ea4c0f8c49e82363b10955baa5438391/types_requests-2.33.0.20260906-py3-none-any.whl", hash = "sha256:9f53622652bd921ead7a54d665be1b8d518165c8b51cc9d68d944cd6b6bfa8fb", size = 21461, upload-time = "2026-09-06T06:35:45.856Z" },
]
[[package]]
@@ -3687,11 +3687,11 @@ wheels = [
[[package]]
name = "urllib3"
version = "2.7.0"
version = "2.8.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
{ url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" },
]
[[package]]
+6 -6
View File
@@ -286,7 +286,7 @@ wheels = [
[[package]]
name = "langgraph"
version = "1.2.12"
version = "1.2.13"
source = { editable = "../langgraph" }
dependencies = [
{ name = "langchain-core" },
@@ -626,13 +626,13 @@ dev = [
{ name = "pytest-asyncio" },
{ name = "pytest-mock" },
{ name = "pytest-watch" },
{ name = "ruff", specifier = "==0.16.5" },
{ name = "ruff", specifier = "==0.16.9" },
{ name = "starlette" },
{ name = "ty" },
]
lint = [
{ name = "codespell" },
{ name = "ruff", specifier = "==0.16.5" },
{ name = "ruff", specifier = "==0.16.9" },
{ name = "starlette" },
{ name = "ty" },
]
@@ -1363,11 +1363,11 @@ wheels = [
[[package]]
name = "urllib3"
version = "2.7.0"
version = "2.8.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
{ url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" },
]
[[package]]
+1 -1
View File
@@ -312,7 +312,7 @@ class _ActionHandler(typing.Protocol[V]):
) -> types.HandlerResult: ...
T = typing.TypeVar("T", covariant=True)
T = typing.TypeVar("T")
class _ResourceActionOn(typing.Generic[T]):
+1 -1
View File
@@ -36,7 +36,7 @@ test = [
"pytest-watch",
]
lint = [
"ruff==0.16.5",
"ruff==0.16.9",
"codespell",
"ty",
"starlette",
+53 -53
View File
@@ -266,7 +266,7 @@ wheels = [
[[package]]
name = "langchain-core"
version = "1.6.1"
version = "1.6.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "httpx" },
@@ -281,9 +281,9 @@ dependencies = [
{ name = "typing-extensions", version = "4.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.15'" },
{ name = "uuid-utils" },
]
sdist = { url = "https://files.pythonhosted.org/packages/90/12/aff76ca89c219ebe6f9dd3c5dbc4e3b1cf5450e9fc7037dccad23d45cd7a/langchain_core-1.6.1.tar.gz", hash = "sha256:1b156cb395aac4f009a8a1b38a574c7d948fe2d5f74c96e0d8a5017b4149e04f", size = 1003359, upload-time = "2026-08-27T19:31:14.956Z" }
sdist = { url = "https://files.pythonhosted.org/packages/ed/ed/ceecd3bfcfc77a94cf30a9f1506e907fdea447458825e01914a72d2d1a6f/langchain_core-1.6.5.tar.gz", hash = "sha256:bdb059fef65473fd444558dbb18f50901657402c43ceed9dc0fdc7b76a393c6b", size = 1007041, upload-time = "2026-09-24T18:11:06.487Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8e/25/f50dd65673c819aa33d3c34df58c115dbb6ec627d19f93e6e401dd0fc8d7/langchain_core-1.6.1-py3-none-any.whl", hash = "sha256:954a84132a5cb0435d27b910e336347b6744ecc18fbeef1e2de7029a0959841a", size = 571478, upload-time = "2026-08-27T19:31:13.34Z" },
{ url = "https://files.pythonhosted.org/packages/59/68/447ac7e734990b7ed9dcfc3b6dee9a4cd4d4169e296429fa71a9a47c1c7b/langchain_core-1.6.5-py3-none-any.whl", hash = "sha256:54c7b0e9314b9084fb04405bb33dc5d32986d512d92b7b8863899cd5f6267556", size = 572136, upload-time = "2026-09-24T18:11:04.837Z" },
]
[[package]]
@@ -301,7 +301,7 @@ wheels = [
[[package]]
name = "langgraph"
version = "1.2.12"
version = "1.2.13"
source = { editable = "../langgraph" }
dependencies = [
{ name = "langchain-core" },
@@ -537,13 +537,13 @@ dev = [
{ name = "pytest-asyncio" },
{ name = "pytest-mock" },
{ name = "pytest-watch" },
{ name = "ruff", specifier = "==0.16.5" },
{ name = "ruff", specifier = "==0.16.9" },
{ name = "starlette" },
{ name = "ty" },
]
lint = [
{ name = "codespell" },
{ name = "ruff", specifier = "==0.16.5" },
{ name = "ruff", specifier = "==0.16.9" },
{ name = "starlette" },
{ name = "ty" },
]
@@ -897,14 +897,14 @@ wheels = [
[[package]]
name = "pytest-mock"
version = "3.15.1"
version = "3.16.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/68/14/eb014d26be205d38ad5ad20d9a80f7d201472e08167f0bb4361e251084a9/pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f", size = 34036, upload-time = "2025-09-16T16:37:27.081Z" }
sdist = { url = "https://files.pythonhosted.org/packages/7a/7f/6ed29931d5c8cd396e7c0a55412e6cc88020373365c8685985dea53d26d7/pytest_mock-3.16.0.tar.gz", hash = "sha256:5a8395528b8f498205f3718f575228d0edaed7425fff638f87d1a6c3e0383636", size = 35362, upload-time = "2026-09-27T14:57:55.46Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095, upload-time = "2025-09-16T16:37:25.734Z" },
{ url = "https://files.pythonhosted.org/packages/db/5b/b83a9bf1a3b4ec222f9fa083147ff6816245223da0ab92370e7e056f113f/pytest_mock-3.16.0-py3-none-any.whl", hash = "sha256:007cfeb257801d88d9c0b2a7b5a15a15e73b71968dfd72e7bf8c4a2f8393aec8", size = 10016, upload-time = "2026-09-27T14:57:54.283Z" },
]
[[package]]
@@ -1012,40 +1012,40 @@ wheels = [
[[package]]
name = "ruff"
version = "0.16.5"
version = "0.16.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f3/85/c8e12473c93018f92d19dd988a294202e1c27426c47ec4de53ffb847b8d8/ruff-0.16.5.tar.gz", hash = "sha256:1b88500f9ffbcab3dedb0082c9f9492e91ec3d618aac1236a3e0189938f7040b", size = 4912003, upload-time = "2026-08-27T16:34:18.258Z" }
sdist = { url = "https://files.pythonhosted.org/packages/96/bf/c935ca98e73fe8ce65b87ef08a280c0c1e85295d569228c15e87d8fdfaf1/ruff-0.16.9.tar.gz", hash = "sha256:12b625c6cfba78d285d9f48eda5f053374f1e53cb10ef17342a383750db99161", size = 4948764, upload-time = "2026-09-24T20:37:49.416Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c6/b6/77c90a970fe2dae17a723acbd011043ea97c98d7deacccefdc4ba74ec512/ruff-0.16.5-py3-none-linux_armv6l.whl", hash = "sha256:12e5f673e774c35fbb62f288809c7653b73445f8ecec6b6063fd6ea3521aa14b", size = 10011941, upload-time = "2026-08-27T16:33:41.287Z" },
{ url = "https://files.pythonhosted.org/packages/4b/46/6cf67cf6411885a1d6f7f6d801682f155536a85176d10b605e2ceffed8bd/ruff-0.16.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:eda58a5802de40e7ed5b32b64e0b32539338cc6fcd2c78f61e3ad6a0d79f51c3", size = 10204049, upload-time = "2026-08-27T16:33:44.056Z" },
{ url = "https://files.pythonhosted.org/packages/46/fd/c8720ca7a090abf0c2fef4abe8a5ef6e5127ed15196d8886ff75a2b370e2/ruff-0.16.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5ae9a7b9a8875131f40f8fe967cc86abf899779efd663cb7ce3d572d01da7eb", size = 9809037, upload-time = "2026-08-27T16:33:46.257Z" },
{ url = "https://files.pythonhosted.org/packages/43/45/a684caacdedaca180f52bacccc40bf0789d2c5a7c75f25324853e9eaedb5/ruff-0.16.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b719b0a1f4d59710d283ab2965f621684a108a9e41da622e3b23f0326cd0025", size = 9964129, upload-time = "2026-08-27T16:33:48.352Z" },
{ url = "https://files.pythonhosted.org/packages/9e/f2/5d2bcdaca6b5b93d1b4dfc166cd2aebf7680143a1b38a28759df13a94d31/ruff-0.16.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2298f2780ed1be0c5cb1361e32ab7b1467f3cce7dabe101d2210a314f2fe42e9", size = 9821518, upload-time = "2026-08-27T16:33:50.57Z" },
{ url = "https://files.pythonhosted.org/packages/aa/ff/011cce29accf9257d5974145b733fc653a37985ed6825413a3987cefbfe0/ruff-0.16.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:258f29035a2dd021e7861e631b227a5b3f14e50c1184c9a6a122c5f4576154d7", size = 10534835, upload-time = "2026-08-27T16:33:52.522Z" },
{ url = "https://files.pythonhosted.org/packages/d7/5a/f0cf109bada9bba0e96c90c21c9f9251803f57225c32d293327a03c710d6/ruff-0.16.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9a4f0432966834019c74d1b7e5c51224305d7713f3d7faf3e7451f1a3be3cde", size = 11252550, upload-time = "2026-08-27T16:33:54.521Z" },
{ url = "https://files.pythonhosted.org/packages/63/4d/1d481aaea2046c6a7ed7c291f9004c669cce3c087b6b376ed5b08271e3fe/ruff-0.16.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5eb3a8c3d0ade9cea42b591fd530368e8798380e30e0a308b85a5cf718f09ea", size = 10777949, upload-time = "2026-08-27T16:33:56.88Z" },
{ url = "https://files.pythonhosted.org/packages/ee/34/ee245ca55f64443233034b3d02b03236b19242004281247c079390b7facd/ruff-0.16.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef0f69e191a13a3c9816f63163c88790cb12cd157bbbb384e9c44745702ab105", size = 10311656, upload-time = "2026-08-27T16:33:59.12Z" },
{ url = "https://files.pythonhosted.org/packages/a7/4d/c33a333e341c0a2b96c715b52d89a606f5a34cd4ac493cd9b8d0187186b8/ruff-0.16.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0eeab41fbea2c42f98dfb9822cdccda9d24ba38d49f6dc945b5c236d48f0ef29", size = 10532125, upload-time = "2026-08-27T16:34:01.166Z" },
{ url = "https://files.pythonhosted.org/packages/30/e1/a64cef78b40192497bb98a27a8aa8f2c98ee9ee15bc97f7712d94ef32937/ruff-0.16.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f0768e9df4300713fff30733c87575f68b6f1d8de41184e505b7fdd9c0c95eaf", size = 10097648, upload-time = "2026-08-27T16:34:03.16Z" },
{ url = "https://files.pythonhosted.org/packages/cc/4e/4cdc9ed3c3e109d2f71e62572a37457298d7bc7501ec3138babb7ed32bbd/ruff-0.16.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:95cc70cdc7aa80c338de356279d2adbeb2de0f520b9ecd8aba75b94e95e02f91", size = 9829344, upload-time = "2026-08-27T16:34:05.134Z" },
{ url = "https://files.pythonhosted.org/packages/39/4a/31ed35ce31729955fc583ee0d176d6e784c1290cb0b0a75cb2134c1ab72a/ruff-0.16.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d185c8398ded1bfd91c0c2cb258346307571eccc473a8490af8c3977399c384a", size = 10277117, upload-time = "2026-08-27T16:34:07.425Z" },
{ url = "https://files.pythonhosted.org/packages/a8/a0/60356d86687b4b666d593df213f4dc3041750d024cb7bf2cfa81cfd65c2e/ruff-0.16.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:fb8e3a3c4c6a784150a7ced53b015f4b253fc2bf97a610886419ead64b4756ef", size = 10711653, upload-time = "2026-08-27T16:34:09.712Z" },
{ url = "https://files.pythonhosted.org/packages/ed/20/656d67f5b25ca9bda4e02b1de25867b2954e1d19e03648060f167ad0f4cc/ruff-0.16.5-py3-none-win32.whl", hash = "sha256:288b0a5f080492fe5635db849f9e2e84aa3cce7b7f0e955997d416c507c76a26", size = 10034250, upload-time = "2026-08-27T16:34:11.8Z" },
{ url = "https://files.pythonhosted.org/packages/5b/42/ee8e68a207b9127fcde6c3d7e197def432f346cb1af159e1fa14ca0d1cdc/ruff-0.16.5-py3-none-win_amd64.whl", hash = "sha256:ddc6385fb2137f616357ca03d6c74f4be987f80fed4008566b754f6032b8546f", size = 10516714, upload-time = "2026-08-27T16:34:13.963Z" },
{ url = "https://files.pythonhosted.org/packages/73/e3/7df5a396e445b9ba49ce9a9437439a4d80042c61c0ade199abf8d16de1ac/ruff-0.16.5-py3-none-win_arm64.whl", hash = "sha256:a64abe90968719b851bb7cedffaa8753fbdbdadab483089682db623f3edc587e", size = 10391564, upload-time = "2026-08-27T16:34:16.064Z" },
{ url = "https://files.pythonhosted.org/packages/0d/26/df51322b52ee1ada7eff2d071ea09d11d5c2d1dcc9f02594f5785c4d1635/ruff-0.16.9-py3-none-linux_armv6l.whl", hash = "sha256:95e6f022090368ab3b824c36276839c53b2adf1a3f4c09fefc33dfc400f6da96", size = 10082922, upload-time = "2026-09-24T20:37:13.045Z" },
{ url = "https://files.pythonhosted.org/packages/a5/27/7bf51f5a7aa375e9f339280a303aab44ca75dc1525f1cdc5991761685b0f/ruff-0.16.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a5f27be168556594a86d2f415db0cf43f5291917849318f873c7e2791f7a8c67", size = 10236360, upload-time = "2026-09-24T20:37:16.049Z" },
{ url = "https://files.pythonhosted.org/packages/b6/63/09659283f92f02dff45809da194a70da2f688d87c55d8875c4fae3536072/ruff-0.16.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1632eb1d6197f33bd00b1acbc5b71009e89a8895c158e2d2b03a834fac964ab6", size = 9892940, upload-time = "2026-09-24T20:37:17.957Z" },
{ url = "https://files.pythonhosted.org/packages/24/58/98de1b72ec172f5f8f1731236fe21585b3998bf7dfe9fcc44ae9ba626012/ruff-0.16.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3f951b14d865d5952c89d40a5ca07e87abe24fa5453299878411e127748fb1c", size = 10032114, upload-time = "2026-09-24T20:37:19.942Z" },
{ url = "https://files.pythonhosted.org/packages/c8/7d/f1e17c54ab59d4bad1dce8ee3e22a7a1d0ef4745240decacdcf3832b5bb2/ruff-0.16.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:447fc07e1573afff7cb02803462b12b6c8ece7cf10e2cd78565fa6d7a1c0bf8d", size = 9910227, upload-time = "2026-09-24T20:37:21.872Z" },
{ url = "https://files.pythonhosted.org/packages/34/19/436f647a65075bbd3bab2668b3bdaa5120559b294694018cdcefabbbf30b/ruff-0.16.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a3e039a6a40ed976c491722b60e0ae4a4aa1a86057f540ee7a37a5d19ae9120", size = 10547484, upload-time = "2026-09-24T20:37:24.229Z" },
{ url = "https://files.pythonhosted.org/packages/03/59/38430a6bc2f6d8095447ac39625cf8b6e9344a47e6c26225c8ba1bff3ffb/ruff-0.16.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4684dded7db60aa57cb118fa158630f5feade4af5782903b6053484bdf9bd129", size = 11412367, upload-time = "2026-09-24T20:37:26.307Z" },
{ url = "https://files.pythonhosted.org/packages/c8/bd/bbb6d7fc7f208c8b8c50dd5dc8206e4cfdb1e7a8fb852606a3adf370c880/ruff-0.16.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d29c934357e45642fda2f34c0b1f4025b4a6c01e15e4bf0016879d60078a142c", size = 10869787, upload-time = "2026-09-24T20:37:28.35Z" },
{ url = "https://files.pythonhosted.org/packages/bc/b8/9c543074918061abbefc3bd139bee22de35abedb00dde0f2d27288838962/ruff-0.16.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a21713e629d3e5bdb2f5c2def1cc7f04f47fa8e1a7eb0571b4a28e1da64bc728", size = 10406494, upload-time = "2026-09-24T20:37:30.624Z" },
{ url = "https://files.pythonhosted.org/packages/35/7a/5a8851bd146e7ccf8fd4b003f6c75c11f8fbdb0e60673b45097986b6bf41/ruff-0.16.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7baa24ef5fc8e77aa93879e1d3f43754a01ae488e869f1ae30cf431afd4d2452", size = 10590083, upload-time = "2026-09-24T20:37:32.439Z" },
{ url = "https://files.pythonhosted.org/packages/87/f0/4c3467188f23f806960b46fa76575a7cd0514c9ba90562650b71efc96980/ruff-0.16.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a41aac6230aadfaa133bdfa1614488531ffa3e0837567ae04c0da2058a9c0f9e", size = 10119151, upload-time = "2026-09-24T20:37:34.581Z" },
{ url = "https://files.pythonhosted.org/packages/15/34/5a4def5adea572ce6aea0bb64f21f928ee317b80e0db747d7979b01d7261/ruff-0.16.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c2529fb5896d49115b0e9aa8f887490b34bbe76baf879ec2264ac59406869ce7", size = 9911544, upload-time = "2026-09-24T20:37:36.796Z" },
{ url = "https://files.pythonhosted.org/packages/62/5d/d15ebea7499eef9373318c0ee6ca127832927c6529731f6d48e18dce7ca9/ruff-0.16.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:41e3870277694177429b56406d65dfbdb2c2802c52b715edaf6a0b829c69d4ee", size = 10269884, upload-time = "2026-09-24T20:37:38.857Z" },
{ url = "https://files.pythonhosted.org/packages/d1/56/c5d3cd119ded7a3c7aba0e961b69cb3df701c91662c98ad694467d060ce1/ruff-0.16.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8adbe4e58af167f767d7b2ba5e83c42e878350796cf78c2f5e14ab9903a92588", size = 10749366, upload-time = "2026-09-24T20:37:41.042Z" },
{ url = "https://files.pythonhosted.org/packages/ac/fe/734ec7527029ac757ecf821f143c9f3fcf69149c21f53a044a899b430f5a/ruff-0.16.9-py3-none-win32.whl", hash = "sha256:0e1dbc2073624dee6618d41d0098690a7244654af746704b64759e12b6b6b385", size = 10152355, upload-time = "2026-09-24T20:37:43.025Z" },
{ url = "https://files.pythonhosted.org/packages/14/21/26e4643629b3ebb44f0a06f9c9a53058d63d989415f63a9a3c28e2ee7f22/ruff-0.16.9-py3-none-win_amd64.whl", hash = "sha256:6bd40fec8cd4c8a3d4dd589bd8ad4e6320c13c29234159bfd959a40d529d597b", size = 10592965, upload-time = "2026-09-24T20:37:44.944Z" },
{ url = "https://files.pythonhosted.org/packages/51/60/5fb1a39dbb5ae314d5f59bc7348a63c1d5c20f3cd83914c4b5cb0be31d2d/ruff-0.16.9-py3-none-win_arm64.whl", hash = "sha256:ed1a252039200f57a59eebc063b54beabea67bfbaaca0eeaa7f54b5fbcda2284", size = 10458649, upload-time = "2026-09-24T20:37:46.882Z" },
]
[[package]]
name = "starlette"
version = "1.6.0"
version = "1.7.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
{ name = "typing-extensions", version = "4.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b5/b4/205b0d5241d934e8add0c38aa924c4f9fb7330834ff11e5444db964ec3f9/starlette-1.6.0.tar.gz", hash = "sha256:d4e3ac5e546444960c710297a3c9fc3f7ebae1b7e963f3d36173b49da535be9b", size = 2716969, upload-time = "2026-08-08T18:27:57.512Z" }
sdist = { url = "https://files.pythonhosted.org/packages/7b/2b/3850dc6bf7ef71b088962eba31dafc6cffd2f96e577ebb0bb316df96da3e/starlette-1.7.0.tar.gz", hash = "sha256:c79f74ea63cff761804fbbfb182f1e0b440c2d07b164d24700c5a1bab5d6ff5d", size = 2736246, upload-time = "2026-09-23T07:30:26.35Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c8/cb/6a6a47d5b464bd08695d254f3da6e7986cc70c9fa5d778eda57538edfe56/starlette-1.6.0-py3-none-any.whl", hash = "sha256:a86dd39d14bb45f85a3d18525215a9ef0cfd1f192ac793220e72598c90335f0c", size = 75969, upload-time = "2026-08-08T18:27:56.196Z" },
{ url = "https://files.pythonhosted.org/packages/4e/d6/1ec1b290f9e0fb067899b61e1d37a30c923068bad260b216dbe37a7d2967/starlette-1.7.0-py3-none-any.whl", hash = "sha256:67f8e99895493dd2911a03f11314af6ceebeae4e704bb9f43dfc6a9db151c93e", size = 78980, upload-time = "2026-09-23T07:30:24.567Z" },
]
[[package]]
@@ -1113,27 +1113,27 @@ wheels = [
[[package]]
name = "ty"
version = "0.0.75"
version = "0.0.84"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/81/d0/d0c96f898d6974a4a3569ab3efdf9512c04ad99f9203effb55f72497fe97/ty-0.0.75.tar.gz", hash = "sha256:4c5eead33dfbf6e2ebb4f400f74b51ffc9bab702a6f23ddb648a1cbb740387e3", size = 6868326, upload-time = "2026-08-26T20:23:40.399Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e1/f6/34f8869c45ea87fe6a931ffa824b1fe4428167173543d92988d631add355/ty-0.0.84.tar.gz", hash = "sha256:0cefdb0cd5d399418dbe83c349ba605047b7dff815ae6f460c80e8522b40be67", size = 7409537, upload-time = "2026-09-24T13:16:24.367Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/6c/b12d03505f17581f0cfa3c12273fe34c1d67b36dfda1bc561a6bdc16512b/ty-0.0.75-py3-none-linux_armv6l.whl", hash = "sha256:e5409f50db2246fd4bd039d93d261e0cfa1daa554a4fb77256f91072c570349a", size = 12972606, upload-time = "2026-08-26T20:22:59.716Z" },
{ url = "https://files.pythonhosted.org/packages/d1/aa/30f11eecd9215a9f87e8fe8baaf48f3ce905f5d75b8e4aac70f0091f130c/ty-0.0.75-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5e7b8b3472fb9bb2eeab314984b265df08a7a9d518867a9e6020eebc06570be2", size = 12527158, upload-time = "2026-08-26T20:23:02.767Z" },
{ url = "https://files.pythonhosted.org/packages/f2/11/7fd7001b0b5c6610bfbad7357e47d5fe6f82d4e84e94c53776a478f5e9f8/ty-0.0.75-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c6ccf34169821fe0d23e3360deeef981d217963412f1d087b9bdd32ec57f7a57", size = 12400533, upload-time = "2026-08-26T20:23:04.965Z" },
{ url = "https://files.pythonhosted.org/packages/fd/7f/1e284ea3d348d7be02f12d83bc22ed9ef193033f863f05b64db99027f141/ty-0.0.75-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:842ebb41e9c6c334b40768704e20b1a69d5c6b08805b289d5e0e2565f49f2de1", size = 12420592, upload-time = "2026-08-26T20:23:07.427Z" },
{ url = "https://files.pythonhosted.org/packages/2d/ab/d813271543370c47fd74b5118f2066ab32b0983e907b1821f3f9a6d0fa7f/ty-0.0.75-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf7a5a723c5f1e0fab4ffbfe9bd95123a526ed48f206e5f25cb2161ca294007a", size = 12739219, upload-time = "2026-08-26T20:23:09.809Z" },
{ url = "https://files.pythonhosted.org/packages/31/5b/95b49cc5570fd92a7bf63732f649b31906158721e03c7fcb1b5be74ee3bf/ty-0.0.75-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54382f98e5da292fcd7104391afef5105c35bb2f312e29bea6f5fa419935255c", size = 13494046, upload-time = "2026-08-26T20:23:12.191Z" },
{ url = "https://files.pythonhosted.org/packages/2c/0d/502d2dd68173cf020e1ad2bdbab9544c86776de0b0e2ed15f8c2fe006e3d/ty-0.0.75-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac13b180dc2aade2cd243f56b01650e78bf091a2e522ad3bc947245d7837c613", size = 13938899, upload-time = "2026-08-26T20:23:14.764Z" },
{ url = "https://files.pythonhosted.org/packages/20/5b/f3b12a25c07224456219fc2bd20db0ad7e40b304be0ff6aad728da0135f9/ty-0.0.75-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:752df7951a443219d7f1ff817e3723c85d428565ff449e08a7a93ba821661526", size = 13656711, upload-time = "2026-08-26T20:23:17.145Z" },
{ url = "https://files.pythonhosted.org/packages/51/7b/f090ad306e2b15a07b332d647138c5264b89d9758855ecce8b8a10bcb153/ty-0.0.75-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fd399feedf7cee816563c1baec45fc1c0b3c89f1ea42364920b688004b5b7da", size = 13093499, upload-time = "2026-08-26T20:23:19.489Z" },
{ url = "https://files.pythonhosted.org/packages/f1/4b/f69b99aaaca0c7c65d5f114b186b26b21666f767b0c69eec99a2bdccc061/ty-0.0.75-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:d7625f6f56c7dc1e873579fdc9e432a0e21e302afe847ab60704d2303442a92e", size = 13520580, upload-time = "2026-08-26T20:23:21.789Z" },
{ url = "https://files.pythonhosted.org/packages/b6/e7/692c5f905c0345a15d2255fc74066d660f030254ae8dcdaf33f5a5c2f279/ty-0.0.75-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:89e7d527e95a2534b70cae29e94c104b84082760ea05927d23bb87280969c104", size = 12524095, upload-time = "2026-08-26T20:23:24.026Z" },
{ url = "https://files.pythonhosted.org/packages/ba/9a/f42b12cf265ea95344bf554764c4791cfb273bdd628aadd7c209af7cadc3/ty-0.0.75-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0843f134440740706e01bee5f88f4cfc10e9b018bddb9e4ef4c12dc9fc0c9aef", size = 12756591, upload-time = "2026-08-26T20:23:26.126Z" },
{ url = "https://files.pythonhosted.org/packages/7c/5e/9b180c133cb9cce48179a7d2bf9e1802d992aa8176a918e0e05205760b42/ty-0.0.75-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1bd0ec0e50ee1376875c88891efe6f549c3560fa5b2ddad79a425cd5a6218b9c", size = 12998754, upload-time = "2026-08-26T20:23:28.353Z" },
{ url = "https://files.pythonhosted.org/packages/39/f6/3c6ef5dd550103e29905121c67fb96a374564f31a2f44c6faa1af98c2d61/ty-0.0.75-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1f9eafd561f90110d5e29f589ec3e956c4686e2f6631348d99276436f5cbe4d1", size = 13316474, upload-time = "2026-08-26T20:23:30.857Z" },
{ url = "https://files.pythonhosted.org/packages/bb/52/12776337874c821076bd5368e352ccd9e67174790abe3b856f749cb3524b/ty-0.0.75-py3-none-win32.whl", hash = "sha256:05063a6fafe2154b794a7f964515d148e51acd186d72d4a3acd347ee9fa19336", size = 12316315, upload-time = "2026-08-26T20:23:33.528Z" },
{ url = "https://files.pythonhosted.org/packages/53/e6/bb51e16af5c7138c9f52f8f3d0a401a371c6798d092e3b74926f186a9814/ty-0.0.75-py3-none-win_amd64.whl", hash = "sha256:81cf1ba5f6b7536ad56747865214255d9bc8e80533a689dbb9ddeaad464b09f1", size = 12917267, upload-time = "2026-08-26T20:23:35.978Z" },
{ url = "https://files.pythonhosted.org/packages/39/73/4542f829107468b5de4231af67f29927c093bfad11f3c1e5b2c08fb1206b/ty-0.0.75-py3-none-win_arm64.whl", hash = "sha256:541c9af5b7a0ad23d15ec315a7da81150833c359f48124ed3789ff25eacd6f42", size = 12711024, upload-time = "2026-08-26T20:23:38.159Z" },
{ url = "https://files.pythonhosted.org/packages/aa/0c/600648778e1c79133ce6b6a5c4c2531ae16b90c9b30f5041b38b574f61b8/ty-0.0.84-py3-none-linux_armv6l.whl", hash = "sha256:868438e2b9abfc835dd5b5b07ed693db95d8348ac40e3228252511d63ae87695", size = 13935333, upload-time = "2026-09-24T13:15:31.167Z" },
{ url = "https://files.pythonhosted.org/packages/c5/3b/27f06f49945c36170765fad82076898039ae3873338e9865f876dd62f12c/ty-0.0.84-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b00f39b521f0b559cde0f6abf8dd47213b513b04f33d58efeb9b98486a16bb17", size = 13511328, upload-time = "2026-09-24T13:15:34.446Z" },
{ url = "https://files.pythonhosted.org/packages/fc/b6/b12dd130e7f30141f0645614f454c925991cd389b1cc6c8284fd6bf32326/ty-0.0.84-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8f78c2915567f2ee62ce0c24d86091bc76f81577677755e242d09951db588b9a", size = 13445445, upload-time = "2026-09-24T13:15:37.476Z" },
{ url = "https://files.pythonhosted.org/packages/44/96/f012de4b3c1d9a4773326621380d768b4d48c47e620dc012775c5e01c7d7/ty-0.0.84-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61155cad0921e890d86d1d911a40b3a0e924ef4bdc3b4f3865a6c89c7e3012dc", size = 13471235, upload-time = "2026-09-24T13:15:40.64Z" },
{ url = "https://files.pythonhosted.org/packages/05/32/dca630f5f5353fa7bf67eebccf1549df99b16656d21071d0df6677c826a5/ty-0.0.84-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:417c3bf14947ed16b0b92976ab333c27915590354e96d4f581709068d3811355", size = 13680704, upload-time = "2026-09-24T13:15:43.817Z" },
{ url = "https://files.pythonhosted.org/packages/44/8d/33702c8f62f05ad45b33644fb914d483de6a0a7bc8e51884e9b8773e6d69/ty-0.0.84-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e06ef117759f654f5379efe9ae79bda8a186016c016f1023d05c34f8e15c1546", size = 14518923, upload-time = "2026-09-24T13:15:46.802Z" },
{ url = "https://files.pythonhosted.org/packages/c8/a1/da3246e6ef2ae0e842bca4058b25c54bee55ab058ffff4ee54e72517ec01/ty-0.0.84-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a05d1d53db8b64410ab38c6e32c5898510584869d1d5dd9c0605db81c9aef7df", size = 15027731, upload-time = "2026-09-24T13:15:49.755Z" },
{ url = "https://files.pythonhosted.org/packages/20/17/b0099098a560aeb4f9fde6c912f9a81622c3e44e6555e1fbe322b368ec31/ty-0.0.84-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b92400494ab855cfb1204ac1101e3f53b2d09a8e21d171758b2cf9acdab1809e", size = 14748260, upload-time = "2026-09-24T13:15:52.713Z" },
{ url = "https://files.pythonhosted.org/packages/60/d5/32cd67aedb271f006e716ad093806c96c5d7e2af86be8255469dbd3d76c8/ty-0.0.84-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af17eb391ae3027fed9be1780bea555c2b8a25ba68e184c627b4981b2c9eaab7", size = 14205858, upload-time = "2026-09-24T13:15:55.677Z" },
{ url = "https://files.pythonhosted.org/packages/43/c4/638ac62ca2e8eca1b92e3e16273085744fada728b993500819b5c258ca15/ty-0.0.84-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:44cf06af0e7ec78ea6d8ff33a3450fc19627756a4fba681f7410d4e3ef63047a", size = 14573196, upload-time = "2026-09-24T13:15:59.165Z" },
{ url = "https://files.pythonhosted.org/packages/a6/f6/9ee81c5d8921e5fd5f10889ae563c95cd3272b31df2ada528919ca1cef6b/ty-0.0.84-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c6e56b443ff9ba462e34bfbc1e582004c2719ed35f8f93a433744b0ba0afb2d9", size = 13480760, upload-time = "2026-09-24T13:16:02.313Z" },
{ url = "https://files.pythonhosted.org/packages/f6/83/fbe5d1177667ae16d84c3242846b143809c9cc09568b333e5a9b4d5908f6/ty-0.0.84-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b6562fcc48820c1030e2a4509ef2c14ef93043ca4860280074314ac3a825b95", size = 13696346, upload-time = "2026-09-24T13:16:05.391Z" },
{ url = "https://files.pythonhosted.org/packages/86/9a/1b4ac9ddc34cc0ab4624bc219825d66af52f1ad87f4778ad08ad03fa06d5/ty-0.0.84-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dee7421451efcbd70f03e95a8f2c8d9e5ec3d35edcd27b4095ee00ee062abfc4", size = 13959410, upload-time = "2026-09-24T13:16:08.661Z" },
{ url = "https://files.pythonhosted.org/packages/c9/04/70e289437a67dfd686056ab4fd91880261a8233033a6a95d29393741fb97/ty-0.0.84-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:31e96307cf621babe969307dd657783d672e2d8bdbd06493710da635bf63fa07", size = 14350294, upload-time = "2026-09-24T13:16:11.865Z" },
{ url = "https://files.pythonhosted.org/packages/9c/f4/ae7dbd118425c850981d23efb850f0d9d7f6b8d2b852bde2767434f668b4/ty-0.0.84-py3-none-win32.whl", hash = "sha256:4bdc85f91cbaae35825f2b17bb4ac5de0563367875cb0f42b2bf07a1bf7ff2ba", size = 13176439, upload-time = "2026-09-24T13:16:15.049Z" },
{ url = "https://files.pythonhosted.org/packages/29/ec/994d87252f065dda5a500bc8afc726d18f6582d81d6f4ff1feb8a267c800/ty-0.0.84-py3-none-win_amd64.whl", hash = "sha256:71cc9aa7a7c89d4e12c6a814e9c0c3310ad5bee44efedbd6f5a42d91e9ac0f0d", size = 13962879, upload-time = "2026-09-24T13:16:18.191Z" },
{ url = "https://files.pythonhosted.org/packages/6d/1c/e6e91852b72566b1ab9aca504712857dfb89324c12092a5bd61d42d34427/ty-0.0.84-py3-none-win_arm64.whl", hash = "sha256:6c9d3718c4a0d318bc9c92af9b2aa85c3294e7dff54cf1d69ad79568f56516da", size = 13656453, upload-time = "2026-09-24T13:16:21.51Z" },
]
[[package]]
@@ -1175,11 +1175,11 @@ wheels = [
[[package]]
name = "urllib3"
version = "2.7.0"
version = "2.8.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" },
{ url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" },
]
[[package]]