16323 Commits

Author SHA1 Message Date
Matthew Honnibal f69c32f7a0 Install click with previous spaCy in upgrade test
spacy <=3.8.14 imports click without declaring it (#13971), and modern
typer no longer depends on click, so the pre-upgrade install fails on
import without it.
release-v3.8.15
2026-08-07 13:44:28 +02:00
Matthew Honnibal 29bc4f2a5a Fix release smoke/upgrade tests
- Download wheels from the run's own artifacts: the release created by
  build_wheels is a draft, and drafts can't be looked up by tag, so the
  release-downloader step always 404'd
- Drop the checkout: the source tree shadowed the installed wheel when
  running python from the workspace root (No module named spacy.symbols)
- Strip the release-v prefix from the tag before using it as a pip
  version specifier
2026-08-07 12:12:52 +02:00
Matthew Honnibal 86edb26d60 Build linux wheels in manylinux_2_28 containers
numpy >=2.3 only publishes manylinux_2_28 wheels, so pip inside the
manylinux2014 build container falls back to compiling numpy from
source, which fails (container GCC is too old for numpy's meson
build). Bump the x86_64 and aarch64 build images to manylinux_2_28,
matching numpy's own baseline.
2026-08-07 10:17:55 +02:00
Matthew Honnibal 7a64151619 Cap hypothesis below 6.156 to keep win_arm64 wheel builds working 2026-08-07 09:58:05 +02:00
Matthew Honnibal 768e8d572c Fix CI: bump mypy pin for numpy 2.5 stubs, sync confection pin
mypy 1.5.x crashes with an internal error on numpy>=2.3 type stubs,
which killed the mypy step on Python 3.12+. Bump to mypy 1.20.x and
fix the type errors the newer mypy reports.

Also sync the confection pin in requirements.txt with setup.cfg
(>=1.3.2), which was the single test failure on Python 3.10/3.11.
2026-08-07 09:34:11 +02:00
Matthew Honnibal edd3d0fcca Format tests README code blocks for ruff 0.16 markdown formatting 2026-08-07 09:13:50 +02:00
Matthew Honnibal 82d98b2d96 Update version 2026-08-06 23:03:15 +02:00
Matthew Honnibal 47ce793778 Merge branch 'master' of https://github.com/explosion/spaCy 2026-08-06 23:02:36 +02:00
Mart Ratas dbe520e702 Fix click dependency issue (#13971) (#13973)
* Add click dependency in requirements.txt

* Add click dependency in setup.cfg
2026-08-06 22:59:47 +02:00
Ines Montani e67199550e Update README.md [ci skip] 2026-05-19 08:48:33 +02:00
Ines Montani 9af7b84777 Add note about Ellf [ci skip] 2026-05-19 08:48:27 +02:00
Matthew Honnibal 0f7e41d148 Add release notes for v3.8.14 2026-03-29 09:22:47 +02:00
Matthew Honnibal 0069cf99b6 Set version to 3.8.14 2026-03-28 21:59:08 +01:00
Taylor Satula 56032260f2 fix: check pip module availability instead of PATH binary in download (#13947)
_get_pip_install_cmd() uses shutil.which("pip") to check for pip, then
returns [sys.executable, "-m", "pip", "install"] which invokes pip as a
module. The binary check fails in venvs where ensurepip creates pip3 but
not pip (common on Debian/Ubuntu), even though python -m pip works.

Replace shutil.which("pip") with importlib.util.find_spec("pip"), which
tests the actual precondition: whether pip is importable in the current
interpreter. The uv branch is unchanged since uv is a standalone binary.

Fixes #13946
2026-03-28 21:56:56 +01:00
Matthew Honnibal d4bb796b5e Add least-privilege permissions to CI workflow 2026-03-27 08:49:43 +01:00
Matthew Honnibal 9d29209d04 Pass github context via stdin instead of CLI arg 2026-03-27 08:49:41 +01:00
Matthew Honnibal 4216738cf8 Pin GitHub Actions to commit SHAs for supply chain security 2026-03-26 15:48:47 +01:00
Matthew Honnibal 297938e704 Add smoke test and upgrade test to release build workflow
After wheels are built:
- smoke_test: install from wheel, download en_core_web_sm, verify entities
- upgrade_test: install previous spacy, download model, upgrade from wheel,
  verify model still loads and produces entities
2026-03-23 18:46:43 +01:00
Matthew Honnibal fdca647b1b Set version to 3.8.13 2026-03-23 16:52:52 +01:00
Matthew Honnibal 0d94a9d66d Pin confection>=1.3.2 — older versions crash with pydantic v2 2026-03-23 16:50:20 +01:00
Matthew Honnibal f175a51e2d Fully migrate to Pydantic v2 (#13940)
Use confection v1.3 and Thinc v8.3.13, which implement custom validation logic in place of Pydantic, allowing us to properly adopt Pydantic v2 and provide full Python 3.14 support.

Our dependency tree used Pydantic v1 in unusual ways, and relied on behaviours that Pydantic v2 reformed. In the time since Pydantic v2 was released there were a few attempts to migrate over to it, but the task has been complicated by the fact that the confection library has a fairly tangled implementation and I had reduced availability for open-source work in 2024 and 2025.

Specifically, our library confection provides the extensible configuration system we use in spaCy and Thinc. The config system allows you to refer to values that will be supplied by arbitrary functions, that e.g. define some neural network model or its sublayers. The functionality in confection is complicated because we aggressively prioritised user experience in the specification, even if it required increased implementation complexity.

Confection's original implementation built a dynamic Pydantic v1 schema for function-supplied values ("promises"). We validate the schema before calling any promises, and then validate the schema again after calling all the promises and substituting in their values. The variable-interpolation system adds further difficulties to the implementation, and we have to do it all subclassing the Python built-in configparser, which ties us to implementation choices I'd do differently if I had a clean slate.

Here's one summary of Pydantic v1-specific behaviours that the migration to v2 particularly difficult for us. This particular summary was produced during a session with Claude Code Opus 4.6, so nuances of it might be wrong. The full history of attempts at doing this spans over different refactors separated by a few months at a time, so I don't have a full record of all the things that I struggled with. It's possible some details of this summary are incorrect though.

The core problem we kept hitting: Pydantic v2 compiles validation schemas upfront and has much stricter immutability. The whole session has been a series of workarounds for this:

```
 1. Schema mutation — v1 let you mutate __fields__ in place; v2 needs model_rebuild() which loses forward ref namespaces, or create_model subclasses which don't propagate to parent schemas.
 2. model_dump vs dict — v2 converts dataclasses to dicts, breaking resolved objects. Needed a custom _model_to_dict helper.
 3. model_construct drops extras — v2 silently drops fields with extra="forbid", needed manual workarounds.
 4. Strict coercion — v2 coerces ndarray to List[Floats1d] via iteration, needed strict=True.
 5. Forward refs — Every schema with TYPE_CHECKING imports needs model_rebuild() with the right namespace, and that breaks when confection re-rebuilds later.
In order to adjust for behavioural differences like this, I'd refactored confection to build the different versions of the schema in multiple passes, instead of building all the representations together as we'd been doing. However this refactor itself had problems, further complicating the migration.
```

~I've now bitten the bullet and rolled back the refactor I'd been attempting of confection, and instead replaced the Pydantic validation with custom logic. This allows Confection to remove Pydantic as a dependency entirely.~ Update: Actually I went back and got the refactor working. All much nicer now.

I've taken some lengths to explain this because migrating off a dependency after breaking changes can be a sensitive topic. I want to stress that the changes Pydantic made from v1 to v2 are very good, and I greatly appreciate them as a user of FastAPI in our services. It would be very bad for the ecosystem if Pydantic pinned themselves to exactly matching the behaviours they had in v1 just to avoid breaking support for the sort of thing we'd been doing. Instead users who were relying on those behaviours like us should just find some way to adapt --- either vendor the v1 version we need, or change our behaviours, or implement an alternative. I would have liked to do this sooner but we've ultimately gone with the third option.
2026-03-23 13:45:02 +01:00
Matthew Honnibal 24255bd1e2 Fix import sorting for ruff isort compliance 2026-03-21 08:44:43 +01:00
Matthew Honnibal 8e6bd6d1c5 Apply ruff formatting to 8 files 2026-03-21 08:43:52 +01:00
Matthew Honnibal 47b5504e90 Autofix autofixable things from ruff 2026-03-21 08:43:16 +01:00
Matthew Honnibal 86f7ce303a Limit CI ruff lint to isort-only checks for now 2026-03-21 08:41:25 +01:00
Matthew Honnibal 79b5f811bf Update CI validation workflow: replace black, isort, flake8 with ruff 2026-03-21 08:39:43 +01:00
Matthew Honnibal 32c4b638ae Format with ruff 2026-03-21 08:38:53 +01:00
Matthew Honnibal a7f629bb91 Fix ruff isort config: replace unsupported profile with equivalent settings 2026-03-21 08:38:28 +01:00
Matthew Honnibal adeb1620ec Remove W503 from ruff ignore list (not a valid ruff rule) 2026-03-21 08:38:28 +01:00
Matthew Honnibal fd99ed312b Replace black, isort, and flake8 with ruff for linting and formatting
- requirements.txt: remove black, isort, flake8; add ruff
- pyproject.toml: replace [tool.isort] with [tool.ruff] config
- setup.cfg: remove [flake8] section (rules moved to pyproject.toml)
- .pre-commit-config.yaml: replace black/flake8 hooks with ruff/ruff-format
2026-03-21 08:38:28 +01:00
Matthew Honnibal 501ccfd5fb Fix pydantic v2 pattern validation error counts and attributeruler type annotation
- Update expected error counts in test_pattern_validation.py for pydantic v2
  (v2 reports errors for all union members, increasing counts for OP and
  nested pattern validation)
- Fix AttributeRulerPatternType to include List[MatcherPatternType] in
  the union (v2 is strict about nested list-of-list-of-dict types that
  v1 accepted laxly)
2026-03-20 20:50:56 +01:00
Matthew Honnibal b8bade1a57 Update spaCy to pydantic v2 native API
- Replace pydantic.v1 compat imports with direct v2 imports
- Replace class Config with model_config = ConfigDict(...)
- Replace @validator with @field_validator
- Replace ConstrainedStr with constr()
- Replace min_items with min_length, allow_population_by_field_name
  with populate_by_name
- Add model_rebuild() calls in __init__.py for forward ref resolution
- Update test error type assertions for v2
2026-03-20 15:03:41 +01:00
Matthew Honnibal f835985f3f Increment version 2026-03-20 14:38:21 +01:00
Matthew Honnibal d5f67dc92d Update spaCy pydantic imports from v1 compat to v2 native API 2026-03-20 14:31:59 +01:00
Matthew Honnibal 3154ede82a Revert pydantic v2 migration, restore v1 compat imports 2026-03-20 14:09:37 +01:00
Matthew Honnibal 4f19800b4e Revert to weasel <0.5 2026-03-20 14:04:12 +01:00
Matthew Honnibal 60a19cb800 Revert to confection <1 and allow pydantic v1 2026-03-20 14:02:03 +01:00
Matthew Honnibal 2afc3fd41c Escape braces in TokenPatternOperatorMinMax regex for Rust regex engine 2026-03-20 11:34:12 +01:00
Matthew Honnibal d41afc2966 isort 2026-03-20 11:13:21 +01:00
Matthew Honnibal 21439ec09d Migrate from pydantic v1 to v2, require pydantic>=2.0.0
Replace all pydantic.v1 compat imports with direct pydantic v2 imports.
Migrate schemas to v2 API: ConfigDict instead of inner Config class,
field_validator instead of validator, RootModel instead of __root__,
model_dump() instead of dict(), model_validate() instead of parse_obj(),
Annotated[str, StringConstraints()] instead of ConstrainedStr,
min_length instead of min_items, populate_by_name instead of
allow_population_by_field_name.
2026-03-20 11:10:26 +01:00
Matthew Honnibal f22ff91476 Fix vuln scan by not calling test file requirements requirements.txt 2026-03-20 09:55:49 +01:00
Matthew Honnibal ed20f79abe Require confection 2026-03-20 09:43:20 +01:00
Matthew Honnibal c6c78d6c33 Allow use of uv as a fallback to pip in spacy download 2026-03-20 09:20:38 +01:00
Matthew Honnibal 2f6142b43e Require weasel 1.0 2026-03-20 09:17:28 +01:00
Sofie Van Landeghem 37b4a74fa7 Switch dependency back from typer-slim to typer (#13922)
* change typer-slim dependency to typer

* set rich_markup_mode to None to preserve behaviour
2026-03-20 09:14:19 +01:00
Kaushik Rajan cfa1d3a59a fix: ensure memory_zone cleanup runs on exception (#13924) (#13932)
Wrap yield in try/finally in StringStore.memory_zone and
Vocab.memory_zone so transient state is always cleaned up,
even when an exception propagates through the context manager.
2026-03-15 11:29:09 +01:00
Matthew Honnibal 453732d32d Format (#13929) 2026-03-03 09:56:06 +01:00
Nathan Goldbaum c1e7cb2ebf Merge pull request #13865 from reonokiy/fix-ipython-display-import 2025-11-27 11:55:45 -07:00
reonokiy b85cf89b0b chore(ipython): import from IPython.display instead of IPython.core.display 2025-11-27 12:20:20 +08:00
Matthew Honnibal e7a662acf8 Skip Python 3.10 on Windows ARM 2025-11-17 18:21:33 +01:00