mirror of
https://github.com/explosion/spaCy.git
synced 2024-11-10 19:57:17 +03:00
Use more sophisticated version parsing logic
This commit is contained in:
parent
bed62991ad
commit
e47e5a4b10
|
@ -5,7 +5,7 @@ import sys
|
|||
from wasabi import msg
|
||||
|
||||
from .. import about
|
||||
from ..util import is_package
|
||||
from ..util import is_package, get_base_version
|
||||
|
||||
|
||||
def download(
|
||||
|
@ -63,8 +63,7 @@ def get_json(url, desc):
|
|||
|
||||
|
||||
def get_compatibility():
|
||||
version = about.__version__
|
||||
version = version.rsplit(".dev", 1)[0]
|
||||
version = get_base_version(about.__version__)
|
||||
comp_table = get_json(about.__compatibility__, "compatibility table")
|
||||
comp = comp_table["spacy"]
|
||||
if version not in comp:
|
||||
|
@ -73,7 +72,7 @@ def get_compatibility():
|
|||
|
||||
|
||||
def get_version(model, comp):
|
||||
model = model.rsplit(".dev", 1)[0]
|
||||
model = get_base_version(model)
|
||||
if model not in comp:
|
||||
msg.fail(
|
||||
f"No compatible model found for '{model}' (spaCy v{about.__version__})",
|
||||
|
|
|
@ -90,7 +90,7 @@ def generate_meta(model_path, existing_meta, msg):
|
|||
("license", "License", meta.get("license", "MIT")),
|
||||
]
|
||||
nlp = util.load_model_from_path(Path(model_path))
|
||||
meta["spacy_version"] = about.__version__
|
||||
meta["spacy_version"] = util.get_model_version_range(about.__version__)
|
||||
meta["pipeline"] = nlp.pipe_names
|
||||
meta["vectors"] = {
|
||||
"width": nlp.vocab.vectors_length,
|
||||
|
@ -138,7 +138,7 @@ def list_files(data_dir):
|
|||
|
||||
def list_requirements(meta):
|
||||
parent_package = meta.get('parent_package', 'spacy')
|
||||
requirements = [parent_package + '>=' + meta['spacy_version']]
|
||||
requirements = [parent_package + meta['spacy_version']]
|
||||
if 'setup_requires' in meta:
|
||||
requirements += meta['setup_requires']
|
||||
if 'requirements' in meta:
|
||||
|
|
|
@ -4,7 +4,7 @@ import requests
|
|||
from wasabi import msg
|
||||
|
||||
from .. import about
|
||||
from ..util import get_package_version, get_installed_models, split_version
|
||||
from ..util import get_package_version, get_installed_models, get_base_version
|
||||
from ..util import get_package_path, get_model_meta, is_compatible_model
|
||||
|
||||
|
||||
|
@ -14,7 +14,7 @@ def validate():
|
|||
with the installed models. Should be run after `pip install -U spacy`.
|
||||
"""
|
||||
model_pkgs, compat = get_model_pkgs()
|
||||
spacy_version = about.__version__.rsplit(".dev", 1)[0]
|
||||
spacy_version = get_base_version(about.__version__)
|
||||
current_compat = compat.get(spacy_version, {})
|
||||
if not current_compat:
|
||||
msg.warn(f"No compatible models found for v{spacy_version} of spaCy")
|
||||
|
@ -78,13 +78,12 @@ def get_model_pkgs():
|
|||
version = get_package_version(pkg_name)
|
||||
if package in compat:
|
||||
is_compat = version in compat[package]
|
||||
v_maj, v_min = split_version(about.__version__)
|
||||
spacy_version = f"{v_maj}.{v_min}"
|
||||
spacy_version = about.__version__
|
||||
else:
|
||||
model_path = get_package_path(package)
|
||||
model_meta = get_model_meta(model_path)
|
||||
is_compat = is_compatible_model(model_meta)
|
||||
spacy_version = model_meta.get("spacy_version", "n/a")
|
||||
is_compat = is_compatible_model(spacy_version)
|
||||
pkgs[pkg_name] = {
|
||||
"name": package,
|
||||
"version": version,
|
||||
|
|
|
@ -191,13 +191,14 @@ class Language(object):
|
|||
|
||||
@property
|
||||
def meta(self):
|
||||
spacy_version = util.get_model_version_range(about.__version__)
|
||||
if self.vocab.lang:
|
||||
self._meta.setdefault("lang", self.vocab.lang)
|
||||
else:
|
||||
self._meta.setdefault("lang", self.lang)
|
||||
self._meta.setdefault("name", "model")
|
||||
self._meta.setdefault("version", "0.0.0")
|
||||
self._meta.setdefault("spacy_version", about.__version__)
|
||||
self._meta.setdefault("spacy_version", spacy_version)
|
||||
self._meta.setdefault("description", "")
|
||||
self._meta.setdefault("author", "")
|
||||
self._meta.setdefault("email", "")
|
||||
|
|
|
@ -95,7 +95,15 @@ def test_ascii_filenames():
|
|||
|
||||
@pytest.mark.parametrize(
|
||||
"version,compatible",
|
||||
[(spacy_version, True), ("2.0.0", False), (">=1.2.3,<4.5.6", False)],
|
||||
[
|
||||
(spacy_version, True),
|
||||
(f">={spacy_version}", True),
|
||||
("2.0.0", False),
|
||||
(">=2.0.0", True),
|
||||
(">=1.0.0,<2.1.1", False),
|
||||
(">=1.2.3,<4.5.6", True),
|
||||
("n/a", None),
|
||||
],
|
||||
)
|
||||
def test_is_compatible_model(version, compatible):
|
||||
assert util.is_compatible_model({"spacy_version": version}) is compatible
|
||||
assert util.is_compatible_model(version) is compatible
|
||||
|
|
|
@ -14,6 +14,8 @@ import srsly
|
|||
import catalogue
|
||||
import sys
|
||||
import warnings
|
||||
from packaging.specifiers import SpecifierSet, InvalidSpecifier
|
||||
from packaging.version import Version, InvalidVersion
|
||||
|
||||
|
||||
try:
|
||||
|
@ -236,42 +238,31 @@ def get_package_version(name):
|
|||
return None
|
||||
|
||||
|
||||
def split_version(version):
|
||||
"""RETURNS (tuple): Two integers, the major and minor spaCy version."""
|
||||
pieces = version.split(".", 3)
|
||||
return int(pieces[0]), int(pieces[1])
|
||||
|
||||
|
||||
def is_compatible_model(meta):
|
||||
"""Check if a model is compatible with the current version of spaCy, based
|
||||
on its meta.json. We compare the version of spaCy the model was created with
|
||||
with the current version. If the minor version is different, it's considered
|
||||
incompatible.
|
||||
|
||||
meta (dict): The model's meta.
|
||||
RETURNS (bool / None): Whether the model is compatible with the current
|
||||
spaCy or None if we don't have enough info.
|
||||
"""
|
||||
cur_v = about.__version__
|
||||
pkg_v = meta.get("spacy_version")
|
||||
if not pkg_v or not isinstance(pkg_v, str):
|
||||
def is_compatible_model(constraint):
|
||||
version = Version(about.__version__)
|
||||
if constraint[0].isdigit():
|
||||
# Handle cases where exact version is provided as constraint
|
||||
constraint = f"=={constraint}"
|
||||
try:
|
||||
spec = SpecifierSet(constraint)
|
||||
except InvalidSpecifier:
|
||||
return None
|
||||
# Handle spacy_version values like >=x,<y, just in case
|
||||
pkg_v = re.sub(r"[^0-9.]", "", pkg_v.split(",")[0])
|
||||
cur_major, cur_minor = split_version(cur_v)
|
||||
pkg_major, pkg_minor = split_version(pkg_v)
|
||||
if cur_major != pkg_major or cur_minor != pkg_minor:
|
||||
return False
|
||||
return True
|
||||
# Allow prereleases and dev versions
|
||||
spec.prereleases = True
|
||||
return version in spec
|
||||
|
||||
|
||||
def get_model_version_range(version):
|
||||
def get_model_version_range(spacy_version):
|
||||
"""Generate a version range like >=1.2.3,<1.3.0 based on a given spaCy
|
||||
version. Models are always compatible across patch versions but not
|
||||
across minor or major versions.
|
||||
"""
|
||||
major, minor = split_version(version)
|
||||
return f">={version},<{major}.{minor + 1}.0"
|
||||
release = Version(spacy_version).release
|
||||
return f">={spacy_version},<{release[0]}.{release[1] + 1}.0"
|
||||
|
||||
|
||||
def get_base_version(version):
|
||||
return Version(version).base_version
|
||||
|
||||
|
||||
def load_config(path, create_objects=False):
|
||||
|
|
Loading…
Reference in New Issue
Block a user