SIGN IN SIGN UP

INTPYTHON-1067 Range langchain-tests instead of pinning; raise pytest-asyncio floor (#434)

[INTPYTHON-1067](https://jira.mongodb.org/browse/INTPYTHON-1067)

> [!NOTE]
> **Draft — this is a proposal for discussion, not a merge request.**
Opened so @blink1073 and Casey can see the change and its verification.
INTPYTHON-1067 is deliberately left in Triage.

## Summary

Implements @blink1073's suggested route from INTPYTHON-1067: replace the
exact `langchain-tests` pin with a range that is **open at the bottom**.

An exact pin propagates the pinned package's own requirements as hard
floors across the whole project, and `langchain-tests` lives in the
`dev` group, which uv installs by default. `langchain-tests==1.1.9`
requires `langchain-core>=1.4.0` **and** `pytest-asyncio>=1.3.0` — both
above our declared floors, so neither declared floor was reachable in
any dev or CI environment, and neither had ever been tested.

Steve's verification, checking PyPI metadata for every 1.1.x release —
the `langchain-core` floor climbs over time:

| langchain-tests | requires langchain-core |
|---|---|
| 1.1.0 | `>=1.1.0` |
| 1.1.1–1.1.2 | `>=1.2.2` |
| 1.1.3–1.1.5 | `>=1.2.7` |
| 1.1.6 | `>=1.2.27` |
| 1.1.7 | `>=1.3.2` |
| 1.1.8–1.1.9 | `>=1.4.0` |

Opening the bottom lets `lowest-direct` select 1.1.0, whose floor no
longer exceeds ours. This is why a range open only at the top (e.g.
`>=1.1.9,<1.2`) would **not** have worked — it keeps the clamp.

The upper bound preserves what the pin was presumably protecting
against: `langchain-tests` ships the standard test suites we inherit
from (11 subclasses across `test_tools.py`,
`test_vectorstore_standard.py`, `test_retrievers_standard.py`), so a
minor release can add new required test methods and redden CI with no
change on our side.

## One addition to the proposal: `pytest-asyncio`

Steve's dry-run showed `langchain-core==1.2.5`. That was our runtime
floor at the time; #432 (INTPYTHON-1065) merged since and raised it to
`>=1.4.2`. The mechanism is unaffected — arguably it now reads better,
because the resolved version *equals* the declared floor, which is the
whole point of the change.

But removing the pin also unclamps `pytest-asyncio`, which falls to its
declared floor of `0.21.1`. That version does not recognise
`asyncio_default_fixture_loop_scope` (set in
`[tool.pytest.ini_options]`), and `--strict-config` in `addopts` makes
it fatal:

```
ERROR: Unknown config option: asyncio_default_fixture_loop_scope
collected 75 items
============================ no tests ran in 0.98s =============================
```

Bisected against the rest of the graph at floors: `0.21.1` ✗, `0.23.8`
✗, **`0.24.0` ✓**. So this PR raises that floor too.

Worth stating plainly: this failure is **an argument for the change, not
against it**. The range surfaced a real, previously-masked floor error —
exactly what it is supposed to do.

## Changes in this PR

```toml
"langchain-tests>=1.1.0,<1.2",   # was ==1.1.9
"pytest-asyncio>=0.24.0",        # was >=0.21.1
```

Both lines carry a comment explaining the reasoning, since the failure
mode is non-obvious. `uv.lock` regenerated — the diff is exactly those
two specifiers, no package pins changed.

## Test Plan

Python 3.11, against current `main` (`006027e`):

| | Result |
|---|---|
| `lowest-direct` unit suite | **75 passed** |
| Normal resolution unit suite | **75 passed** |
| Integration tests (collection, against 1.1.0 base classes) | **153
collected** |

Resolution under `lowest-direct` after the change:

```
langchain-tests: 1.1.0
langchain-core:  1.4.2   ← our declared runtime floor, no longer clamped
pytest-asyncio:  0.24.0
pytest:          8.2.0
```

Minimum-version results were obtained with `uv run --no-sync`, since the
CI step that would do this is currently a no-op (#433 / INTPYTHON-1066).

## Open question for review

`pytest` still resolves to **8.2.0** despite a declared floor of
`>=7.3.0`, and `langchain-tests` 1.1.0 permits `>=7.0.0` — so something
else clamps it. Same untested-floor pattern, not breaking anything
today. Worth chasing here, or leaving for a follow-up?

## Checklist

### Checklist for Author

- [ ] Did you update the changelog (if necessary)?
- [ ] Is the intention of the code captured in relevant tests?
- [ ] If there are new TODOs, has a related JIRA ticket been created?
- [ ] Has a MongoDB Employee run [the patch build of this
PR](https://github.com/mongodb-labs/ai-ml-pipeline-testing?tab=readme-ov-file#running-a-patch-build-of-a-given-pr)?

### Checklist for Reviewer

- [x] Does the title of the PR reference a JIRA Ticket?
- [x] Do you fully understand the implementation? (Would you be
comfortable explaining how this code works to someone else?)
- [ ] Is all relevant documentation (README or docstring) updated?

---------

Signed-off-by: Casey Clements <casey.clements@mongodb.com>
Co-authored-by: Steven Silvester <steve.silvester@mongodb.com>
C
Casey Clements committed
03156246c666da6ebaacc1c38b0ebd8b4b9800f4
Parent: 50df93a
Committed by GitHub <noreply@github.com> on 8/25/2026, 2:24:58 PM
No diff available for this commit.