Skip to content

Commit 80120d7

Browse files
committed
refacto: we now require python>=3.10, pydantic>=2 and spacy>=3.8.7
1 parent 175976f commit 80120d7

File tree

23 files changed

+145
-244
lines changed

23 files changed

+145
-244
lines changed

.github/workflows/documentation.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ env:
1313

1414
jobs:
1515
Documentation:
16-
runs-on: ubuntu-22.04
16+
runs-on: ubuntu-latest
1717
steps:
1818
- uses: actions/checkout@v2
1919

2020
- uses: actions/setup-python@v4
2121
with:
22-
python-version: "3.9"
22+
python-version: "3.11"
2323
cache: 'pip'
2424

2525
- run: echo WEEK=$(date +%V) >>$GITHUB_ENV

.github/workflows/release.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
runs-on: ${{ matrix.os }}
2525
strategy:
2626
matrix:
27-
os: [ubuntu-22.04, windows-latest, macos-latest]
27+
os: [ubuntu-latest, windows-latest, macos-latest]
2828

2929
steps:
3030
- uses: actions/checkout@v4
@@ -42,7 +42,7 @@ jobs:
4242

4343
build_sdist:
4444
name: Build source distribution
45-
runs-on: ubuntu-22.04
45+
runs-on: ubuntu-latest
4646
steps:
4747
- uses: actions/checkout@v2
4848

@@ -58,7 +58,7 @@ jobs:
5858
name: Upload to PyPI
5959

6060
needs: [build_wheels, build_sdist]
61-
runs-on: ubuntu-22.04
61+
runs-on: ubuntu-latest
6262

6363
steps:
6464
- uses: actions/download-artifact@v4
@@ -76,13 +76,13 @@ jobs:
7676
# repository_url: https://test.pypi.org/legacy/
7777

7878
Documentation:
79-
runs-on: ubuntu-22.04
79+
runs-on: ubuntu-latest
8080
steps:
8181
- uses: actions/checkout@v3
8282

8383
- uses: actions/setup-python@v4
8484
with:
85-
python-version: "3.9"
85+
python-version: "3.11"
8686
cache: 'pip'
8787

8888
- name: Install dependencies

.github/workflows/test-build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
runs-on: ${{ matrix.os }}
1919
strategy:
2020
matrix:
21-
os: [ubuntu-22.04, windows-latest, macos-latest]
21+
os: [ubuntu-latest, windows-latest, macos-latest]
2222

2323
steps:
2424
- uses: actions/checkout@v2
@@ -33,7 +33,7 @@ jobs:
3333

3434
build_sdist:
3535
name: Build source distribution
36-
runs-on: ubuntu-22.04
36+
runs-on: ubuntu-latest
3737
steps:
3838
- uses: actions/checkout@v2
3939

.github/workflows/tests.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
linting:
1818
name: Linting
1919
if: github.event_name == 'pull_request'
20-
runs-on: ubuntu-22.04
20+
runs-on: ubuntu-latest
2121
steps:
2222
- uses: actions/checkout@v3
2323
with:
@@ -34,11 +34,11 @@ jobs:
3434

3535
pytest:
3636
name: Pytest
37-
runs-on: ubuntu-22.04
37+
runs-on: ubuntu-latest
3838
strategy:
3939
fail-fast: true
4040
matrix:
41-
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
41+
python-version: ["3.10", "3.11", "3.12", "3.13"]
4242
steps:
4343
- uses: actions/checkout@v2
4444

@@ -62,28 +62,28 @@ jobs:
6262

6363
- name: Install dependencies
6464
run: pip install -e . --group dev
65-
if: matrix.python-version != '3.9' && matrix.python-version != '3.10' && matrix.python-version != '3.11' && matrix.python-version != '3.12'
65+
if: matrix.python-version != '3.10' && matrix.python-version != '3.12' && matrix.python-version != '3.13' && matrix.python-version != '3.14'
6666

6767
- name: Install dependencies
6868
run: pip install -e . --group dev --group setup
69-
if: matrix.python-version == '3.9'
69+
if: matrix.python-version == '3.10'
7070

7171
- name: Install dependencies
72-
# skip ML tests for 3.10 and 3.11
72+
# skip ML tests for 3.12 and 3.13
7373
run: pip install -e . --group dev-no-ml
74-
if: matrix.python-version == '3.10' || matrix.python-version == '3.11' || matrix.python-version == '3.12'
74+
if: matrix.python-version == '3.12' || matrix.python-version == '3.13' || matrix.python-version == '3.14'
7575

7676
- name: Test with Pytest on Python ${{ matrix.python-version }}
7777
env:
7878
UMLS_API_KEY: ${{ secrets.UMLS_API_KEY }}
7979
run: coverage run -m pytest --ignore tests/test_docs.py
80-
if: matrix.python-version != '3.9'
80+
if: matrix.python-version != '3.10'
8181

8282
- name: Test with Pytest on Python ${{ matrix.python-version }}
8383
env:
8484
UMLS_API_KEY: ${{ secrets.UMLS_API_KEY }}
8585
run: coverage run -m pytest
86-
if: matrix.python-version == '3.9'
86+
if: matrix.python-version == '3.10'
8787

8888
- name: Upload coverage data
8989
uses: actions/upload-artifact@v4
@@ -114,7 +114,7 @@ jobs:
114114

115115
- uses: actions/setup-python@v5
116116
with:
117-
python-version: 3.9
117+
python-version: "3.11"
118118
cache: 'pip'
119119

120120
- name: Install dependencies
@@ -181,11 +181,11 @@ jobs:
181181
182182
simple-installation:
183183
name: Simple installation
184-
runs-on: ubuntu-22.04
184+
runs-on: ubuntu-latest
185185
strategy:
186186
fail-fast: true
187187
matrix:
188-
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
188+
python-version: ["3.10", "3.11", "3.12", "3.13"]
189189
steps:
190190
- uses: actions/checkout@v2
191191

Makefile

Lines changed: 0 additions & 29 deletions
This file was deleted.

changelog.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
### Changed
66

7-
- Dependencies (dev, docs and setup) are now listed in dependency groups and installable via `pip install -e . --group the_group`
7+
- :explosion: EDS-NLP now requires Python 3.10 or later.
88

99
## v0.19.0 (2025-10-04)
1010

docs/tutorials/training-span-classifier.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ dependencies = [
4040
"sentencepiece>=0.1.96"
4141
]
4242

43-
[project.optional-dependencies]
43+
[dependency-groups]
4444
dev = [
4545
"dvc>=2.37.0; python_version >= '3.8'",
4646
"pandas>=1.4.0,<2.0.0; python_version >= '3.8'",

edsnlp/core/pipeline.py

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import contextlib
22
import functools
33
import importlib
4+
import importlib.metadata as importlib_metadata
45
import os
56
import re
67
import shutil
@@ -30,20 +31,25 @@
3031
Union,
3132
)
3233

33-
import pkg_resources
3434
import requests
3535
import spacy
3636
import srsly
3737
from confit import Config
3838
from confit.errors import ConfitValidationError, patch_errors
3939
from confit.utils.xjson import Reference
40+
from packaging.requirements import Requirement
41+
from packaging.version import Version
42+
from pydantic_core import core_schema
4043
from spacy.language import BaseDefaults
4144
from spacy.tokenizer import Tokenizer
4245
from spacy.tokens import Doc
4346
from spacy.util import get_lang_class
4447
from spacy.vocab import Vocab, create_vocab
4548
from typing_extensions import Literal, Self
4649

50+
import edsnlp
51+
from edsnlp.utils.collections import flatten
52+
4753
from ..core.registries import PIPE_META, DraftPipe, FactoryMeta, registry
4854
from ..utils.collections import (
4955
FrozenDict,
@@ -58,14 +64,6 @@
5864
if TYPE_CHECKING:
5965
import torch
6066

61-
try:
62-
import importlib.metadata as importlib_metadata
63-
except ModuleNotFoundError:
64-
import importlib_metadata
65-
66-
import edsnlp
67-
from edsnlp.utils.collections import flatten
68-
6967
EMPTY_LIST = FrozenList()
7068
FORBIDDEN_AUTO_HF_OWNERS = {
7169
"models",
@@ -626,11 +624,8 @@ def disabled(self):
626624
return FrozenList(self._disabled)
627625

628626
@classmethod
629-
def __get_validators__(cls):
630-
"""
631-
Pydantic validators generator
632-
"""
633-
yield cls.validate
627+
def __get_pydantic_core_schema__(cls, source, handler):
628+
return core_schema.no_info_plain_validator_function(cls.validate)
634629

635630
@classmethod
636631
def validate(cls, v, config=None):
@@ -1336,10 +1331,13 @@ def load_from_huggingface(
13361331
missing_deps = []
13371332
# Check if the dependencies are installed, with the correct version
13381333
for req in reqs:
1339-
req_without_extra = re.sub(r"\[.*\]", "", req)
1334+
r = Requirement(re.sub(r"\[.*\]", "", req))
13401335
try:
1341-
pkg_resources.require(req_without_extra)
1342-
except (pkg_resources.VersionConflict, pkg_resources.DistributionNotFound):
1336+
installed = Version(importlib_metadata.version(r.name))
1337+
except importlib_metadata.PackageNotFoundError:
1338+
installed = None
1339+
1340+
if installed is None or r.specifier and installed not in r.specifier:
13431341
missing_deps.append(req)
13441342

13451343
if missing_deps:

edsnlp/core/registries.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import importlib.metadata as importlib_metadata
12
import inspect
23
import types
34
from contextlib import contextmanager
@@ -17,20 +18,18 @@
1718
from weakref import WeakKeyDictionary
1819

1920
import catalogue
21+
import confit
2022
import spacy
21-
from confit import Config, Registry, RegistryCollection, set_default_registry
23+
import spacy.registrations
24+
from confit import Config, RegistryCollection, set_default_registry
2225
from confit.errors import ConfitValidationError, patch_errors
2326
from confit.registry import Draft
2427
from spacy.pipe_analysis import validate_attrs
28+
from spacy.pipeline.factories import register_factories
2529

2630
import edsnlp
2731
from edsnlp.utils.collections import FrozenDict, FrozenList
2832

29-
try:
30-
import importlib.metadata as importlib_metadata
31-
except ImportError:
32-
import importlib_metadata
33-
3433
PIPE_META = WeakKeyDictionary()
3534

3635

@@ -75,6 +74,13 @@ class FactoryMeta:
7574
_AUTO_INSTANTIATE_COMPLETE_PIPE_DRAFT = True
7675

7776

77+
class Registry(confit.Registry):
78+
def get(self, name: str) -> Any:
79+
if name.startswith("spacy."):
80+
spacy.registrations.populate_registry()
81+
return super().get(name)
82+
83+
7884
class DraftPipe(Draft[T]):
7985
def __init__(self, func, kwargs):
8086
super().__init__(func, kwargs)
@@ -277,10 +283,15 @@ def get(self, name: str) -> Any:
277283
registry_path = list(self.namespace) + [name]
278284
registry_spacy_path = ["spacy", "factories", name]
279285
registry_internal_spacy_path = ["spacy", "internal_factories", name]
286+
registry_legacy_spacy_path = ["spacy-legacy", "factories", name]
280287

281288
def check_and_return():
282289
if not catalogue.check_exists(*registry_path):
283-
for path in (registry_spacy_path, registry_internal_spacy_path):
290+
for path in (
291+
registry_spacy_path,
292+
registry_internal_spacy_path,
293+
registry_legacy_spacy_path,
294+
):
284295
if catalogue.check_exists(*path):
285296
func = catalogue._get(path)
286297
meta = spacy.Language.get_factory_meta(name)
@@ -301,14 +312,14 @@ def check_and_return():
301312
# Steps 1 & 2
302313
func = check_and_return()
303314
if func is None and self.entry_points:
315+
register_factories()
304316
# Update entry points in case packages lookup paths have changed
305317
catalogue.AVAILABLE_ENTRY_POINTS = importlib_metadata.entry_points()
306318
# Otherwise, step 3
307319
self.get_entry_point(name)
308320
# Then redo steps 1 & 2
309321
func = check_and_return()
310322
if func is None:
311-
# Otherwise, step 4
312323
if hasattr(spacy.registry, "_entry_point_factories"):
313324
spacy.registry._entry_point_factories.get_entry_point(name)
314325
# Then redo steps 1 & 2

edsnlp/data/converters.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
Union,
2020
)
2121

22-
import pydantic
2322
import spacy
2423
from confit.registry import ValidatedFunction
2524
from spacy.tokenizer import Tokenizer
@@ -90,9 +89,7 @@ def validate_kwargs(func, kwargs):
9089
model = vd.init_model_instance(
9190
**{k: v for k, v in kwargs.items() if k in spec.args}
9291
)
93-
fields = (
94-
model.__fields__ if pydantic.__version__ < "2" else vd.model.model_fields
95-
)
92+
fields = vd.model.model_fields
9693
d = {
9794
k: v
9895
for k, v in model.__dict__.items()

0 commit comments

Comments
 (0)