Skip to content

Support Cython 3 (and also Python 3.13). #951

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

J08nY
Copy link

@J08nY J08nY commented Jan 16, 2025

Description

Fixes the build on Python 3.13 (with Cython 3). Fixes #926 and fixes #947.

Types of change

Removal of Cython version restriction and a small fix.

Checklist

  • I confirm that I have the right to submit this contribution under the project's MIT license.
  • I ran the tests, and all new and existing tests passed.
  • My changes don't require a change to the documentation, or if they do, I've added all required information.

@ngoldbaum
Copy link

It would also be neat to check the Cython 3.1 alpha release or Cython's master branch against free-threaded 3.13.

See https://py-free-threading.github.io for more info about supporting free-threaded Python in native code.

@J08nY
Copy link
Author

J08nY commented Feb 2, 2025

Any progress on getting this in and cutting a new release? Python 3.13 is now 4 months old.

@h-vetinari
Copy link

h-vetinari commented Feb 6, 2025

I would be willing to test this in conda-forge (where we run the test suite anyway), but thinc depends on srsly, confection & wasabi, so those need to be solved first.

image

Xref conda-forge/srsly-feedstock#53

@J08nY
Copy link
Author

J08nY commented Feb 7, 2025

I would be willing to test this in conda-forge (where we run the test suite anyway), but thinc depends on srsly, confection & wasabi, so those need to be solved first.

It seems that all of srsly, confection & wasabi now install under Python 3.13. Atleast in my environment.

@J08nY
Copy link
Author

J08nY commented Feb 7, 2025

I am getting lots of warnings while running tests under 3.13:

thinc/tests/layers/test_layers_api.py: 1594 warnings
thinc/tests/layers/test_lstm.py: 238 warnings
thinc/tests/layers/test_transforms.py: 296 warnings
thinc/tests/layers/test_with_transforms.py: 2508 warnings
thinc/tests/model/test_validation.py: 145 warnings
thinc/tests/test_config.py: 66 warnings
  /tmp/virt/lib/python3.13/site-packages/pydantic/v1/typing.py:68: DeprecationWarning: Failing to pass a value to the 'type_params' parameter of 'typing.ForwardRef._evaluate' is deprecated, as it leads to incorrect behaviour when calling typing.ForwardRef._evaluate on a stringified annotation that references a PEP 695 type parameter. It will be disallowed in Python 3.15.
    return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set())

Also some errors:

============================================================================================= short test summary info =============================================================================================
FAILED thinc/tests/backends/test_ops.py::test_ops_consistency[NumpyOps] - AssertionError: alloc
FAILED thinc/tests/layers/test_layers_api.py::test_layers_from_config[SparseLinear.v1-kwargs55-in_data55-out_data55] - NameError: name 'InT' is not defined
FAILED thinc/tests/layers/test_layers_api.py::test_layers_from_config[SparseLinear.v2-kwargs56-in_data56-out_data56] - NameError: name 'InT' is not defined
FAILED thinc/tests/layers/test_layers_api.py::test_layers_from_config[premap_ids.v1-kwargs59-in_data59-out_data59] - NameError: name 'InT' is not defined
FAILED thinc/tests/layers/test_layers_api.py::test_dropout[data2] - thinc.util.DataValidationError: 
FAILED thinc/tests/layers/test_layers_api.py::test_layers_batching_all[premap_ids.v1-kwargs59-in_data59-out_data59] - NameError: name 'InT' is not defined

which expand out to this, and are clearly connected to the warning:

thinc/tests/layers/test_layers_api.py:211: in util_batch_unbatch_array
    model.initialize(in_data, out_data)
thinc/model.py:316: in initialize
    validate_fwd_input_output(self.name, self._func, X, Y)
thinc/util.py:588: in validate_fwd_input_output
    ArgModel.update_forward_refs(**types.__dict__)
../virt/lib/python3.13/site-packages/pydantic/v1/main.py:814: in update_forward_refs
    update_model_forward_refs(cls, cls.__fields__.values(), cls.__config__.json_encoders, localns)
../virt/lib/python3.13/site-packages/pydantic/v1/typing.py:559: in update_model_forward_refs
    update_field_forward_refs(f, globalns=globalns, localns=localns)
../virt/lib/python3.13/site-packages/pydantic/v1/typing.py:525: in update_field_forward_refs
    field.type_ = evaluate_forwardref(field.type_, globalns, localns or None)
../virt/lib/python3.13/site-packages/pydantic/v1/typing.py:68: in evaluate_forwardref
    return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set())
/usr/lib/python3.13/typing.py:1081: in _evaluate
    eval(self.__forward_code__, globalns, localns),

Seems to be an upstream pydantic issue: pydantic/pydantic#9613

@J08nY
Copy link
Author

J08nY commented Feb 10, 2025

Pinging this. Could anyone have a look, fix the failing test and merge? It is blocking a lot of people depending on spacy.

@salty-horse
Copy link

requirements.txt should also be updated, since it's referenced in the README.

If no-one responds in a few more weeks, maybe email Explosion.

@h-vetinari
Copy link

I tried this in conda-forge/thinc-feedstock#126. On python <3.13, the test suite fails with:

=============================== warnings summary ===============================
$PREFIX/lib/python3.12/site-packages/thinc/tests/layers/test_mnist.py:81
  $PREFIX/lib/python3.12/site-packages/thinc/tests/layers/test_mnist.py:81: PytestUnknownMarkWarning: Unknown pytest.mark.slow - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/how-to/mark.html
    @pytest.mark.slow

$PREFIX/lib/python3.12/site-packages/thinc/tests/regression/issue519/test_issue519.py:13
  $PREFIX/lib/python3.12/site-packages/thinc/tests/regression/issue519/test_issue519.py:13: PytestUnknownMarkWarning: Unknown pytest.mark.slow - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/how-to/mark.html
    @pytest.mark.slow

tests/layers/test_shim.py::test_shim_can_roundtrip_with_path_subclass
tests/model/test_model.py::test_model_can_roundtrip_with_path_subclass
  $PREFIX/lib/python3.12/site-packages/thinc/tests/conftest.py:54: PytestDeprecationWarning: 
  Module 'pathy' was found, but when imported by pytest it raised:
      ImportError("cannot import name '_PosixFlavour' from 'pathlib' ($PREFIX/lib/python3.12/pathlib.py)")
  In pytest 9.1 this warning will become an error by default.
  You can fix the underlying problem, or alternatively overwrite this behavior and silence this warning by passing exc_type=ImportError explicitly.
  See https://docs.pytest.org/en/stable/deprecations.html#pytest-importorskip-default-behavior-regarding-importerror
    pytest.importorskip("pathy")

Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED tests/backends/test_ops.py::test_ops_consistency[NumpyOps] - AssertionError: alloc
assert 'Shape' == 'typing.Tuple[int, ...]'
  
  - typing.Tuple[int, ...]
  + Shape
FAILED tests/layers/test_layers_api.py::test_layers_from_config[SparseLinear.v1-kwargs55-in_data55-out_data55] - NameError: name 'InT' is not defined
FAILED tests/layers/test_layers_api.py::test_layers_from_config[SparseLinear.v2-kwargs56-in_data56-out_data56] - NameError: name 'InT' is not defined
FAILED tests/layers/test_layers_api.py::test_layers_from_config[premap_ids.v1-kwargs59-in_data59-out_data59] - NameError: name 'InT' is not defined
FAILED tests/layers/test_layers_api.py::test_dropout[data2] - thinc.util.DataValidationError: 

Data validation error in 'dropout'
X: <class 'thinc.types.Padded'> Y: <class 'thinc.types.Padded'>

X                     not a valid numpy or cupy array
X                     not a valid numpy or cupy array
X                     not a valid numpy or cupy array
X                     not a valid numpy or cupy array
X                     not a valid numpy or cupy array
X                     not a valid numpy or cupy array
X                     not a valid numpy or cupy array
X                     not a valid numpy or cupy array
X                     value is not a valid sequence 
X                     instance of Ragged, tuple or dict expected
X -> size_at_t        wrong array data type (expected int32/int64/uint32/uint64, got float32)
Y -> 0                not a valid numpy or cupy array
Y -> 0                not a valid numpy or cupy array
Y -> 0                not a valid numpy or cupy array
Y -> 0                not a valid numpy or cupy array
Y -> 0                not a valid numpy or cupy array
Y -> 0                not a valid numpy or cupy array
Y -> 0                not a valid numpy or cupy array
Y -> 0                not a valid numpy or cupy array
Y -> 0                value is not a valid sequence 
Y -> 0                instance of Ragged, tuple or dict expected
Y -> 0 -> size_at_t   wrong array data type (expected int32/int64/uint32/uint64, got float32)
FAILED tests/layers/test_layers_api.py::test_layers_batching_all[premap_ids.v1-kwargs59-in_data59-out_data59] - NameError: name 'InT' is not defined
=========== 6 failed, 1219 passed, 119 skipped, 4 warnings in 11.81s ===========

For 3.13, we'd also need to lift the cap here

blis>=1.0.0,<1.1.0

because we only have 3.13 builds for blis>=1.1 (though it's technically possible to backport this to 1.0, that makes no sense IMO in terms of policy).

@davispuh
Copy link
Contributor

davispuh commented Mar 6, 2025

I can confirm that this PR allows to build thinc on Arch Linux with Python 3.13

But for tests also need this change

diff --git i/thinc/tests/layers/test_linear.py w/thinc/tests/layers/test_linear.py
index 345669d8..d91061a4 100644
--- i/thinc/tests/layers/test_linear.py
+++ w/thinc/tests/layers/test_linear.py
@@ -1,7 +1,7 @@
 import numpy
 import pytest
 from hypothesis import given, settings
-from mock import MagicMock
+from unittest.mock import MagicMock
 from numpy.testing import assert_allclose

 from thinc.api import SGD, Dropout, Linear, chain
diff --git i/thinc/tests/layers/test_with_debug.py w/thinc/tests/layers/test_with_debug.py
index 3f65a3ac..3e31c71f 100644
--- i/thinc/tests/layers/test_with_debug.py
+++ w/thinc/tests/layers/test_with_debug.py
@@ -1,4 +1,4 @@
-from mock import MagicMock
+from unittest.mock import MagicMock

 from thinc.api import Linear, with_debug

@J08nY
Copy link
Author

J08nY commented Mar 7, 2025

I can confirm that this PR allows to build thinc on Arch Linux with Python 3.13

But for tests also need this change

diff --git i/thinc/tests/layers/test_linear.py w/thinc/tests/layers/test_linear.py
index 345669d8..d91061a4 100644
--- i/thinc/tests/layers/test_linear.py
+++ w/thinc/tests/layers/test_linear.py
@@ -1,7 +1,7 @@
 import numpy
 import pytest
 from hypothesis import given, settings
-from mock import MagicMock
+from unittest.mock import MagicMock
 from numpy.testing import assert_allclose

 from thinc.api import SGD, Dropout, Linear, chain
diff --git i/thinc/tests/layers/test_with_debug.py w/thinc/tests/layers/test_with_debug.py
index 3f65a3ac..3e31c71f 100644
--- i/thinc/tests/layers/test_with_debug.py
+++ w/thinc/tests/layers/test_with_debug.py
@@ -1,4 +1,4 @@
-from mock import MagicMock
+from unittest.mock import MagicMock

 from thinc.api import Linear, with_debug

Does this fix all of the test failures? I haven't had a chance to try.

@davispuh
Copy link
Contributor

davispuh commented Mar 7, 2025

It only fixes so that tests itself run.

There are some test failures but I'm not sure if they're due Python 3.13 as they might be because of some other reason.

==================================================================== FAILURES =====================================================================
_________________________________________________________ test_ops_consistency[NumpyOps] __________________________________________________________

op = <class 'thinc.backends.numpy_ops.NumpyOps'>

    @pytest.mark.parametrize("op", [NumpyOps, CupyOps])
    def test_ops_consistency(op):
        """Test that specific ops don't define any methods that are not on the
        Ops base class and that all ops methods define the exact same arguments."""
        attrs = [m for m in dir(op) if not m.startswith("_")]
        for attr in attrs:
            assert hasattr(Ops, attr)
            method = getattr(op, attr)
            if hasattr(method, "__call__"):
                sig = inspect.signature(method)
                params = [p for p in sig.parameters][1:]
                base_sig = inspect.signature(getattr(Ops, attr))
                base_params = [p for p in base_sig.parameters][1:]
                assert params == base_params, attr
                defaults = [p.default for p in sig.parameters.values()][1:]
                base_defaults = [p.default for p in base_sig.parameters.values()][1:]
                assert defaults == base_defaults, attr
                # If args are type annotated, their types should be the same
                annots = [p.annotation for p in sig.parameters.values()][1:]
                base_annots = [p.annotation for p in base_sig.parameters.values()][1:]
                for i, (p1, p2) in enumerate(zip(annots, base_annots)):
                    if p1 != inspect.Parameter.empty and p2 != inspect.Parameter.empty:
                        # Need to check string value to handle TypeVars etc.
>                       assert str(p1) == str(p2), attr
E                       AssertionError: alloc
E                       assert 'Shape' == 'typing.Tuple[int, ...]'
E
E                         - typing.Tuple[int, ...]
E                         + Shape

thinc/tests/backends/test_ops.py:155: AssertionError
_____________________________________ test_layers_from_config[SparseLinear.v1-kwargs55-in_data55-out_data55] ______________________________________

name = 'SparseLinear.v1', kwargs = {}, in_data = (array([1, 2, 3], dtype=uint64), array([1., 2., 3.], dtype=float32), array([1, 1], dtype=int32))
out_data = array([[4., 2., 3., 4.],
       [1., 5., 3., 1.],
       [9., 8., 5., 7.]], dtype=float32)

    @pytest.mark.parametrize("name,kwargs,in_data,out_data", TEST_CASES)
    def test_layers_from_config(name, kwargs, in_data, out_data):
        cfg = {"@layers": name, **kwargs}
        filled_cfg = registry.fill({"config": cfg})
        assert srsly.is_json_serializable(filled_cfg)
        model = registry.resolve({"config": cfg})["config"]
        if "LSTM" in name:
            model = with_padded(model)
        valid = True
        with data_validation(valid):
>           model.initialize(in_data, out_data)

thinc/tests/layers/test_layers_api.py:153:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
thinc/model.py:316: in initialize
    validate_fwd_input_output(self.name, self._func, X, Y)
thinc/util.py:588: in validate_fwd_input_output
    ArgModel.update_forward_refs(**types.__dict__)
pydantic/v1/main.py:814: in update_forward_refs
    update_model_forward_refs(cls, cls.__fields__.values(), cls.__config__.json_encoders, localns)
pydantic/v1/typing.py:559: in update_model_forward_refs
    update_field_forward_refs(f, globalns=globalns, localns=localns)
pydantic/v1/typing.py:525: in update_field_forward_refs
    field.type_ = evaluate_forwardref(field.type_, globalns, localns or None)
pydantic/v1/typing.py:68: in evaluate_forwardref
    return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set())
typing.py:1081: in _evaluate
    eval(self.__forward_code__, globalns, localns),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

>   ???
E   NameError: name 'InT' is not defined

<string>:1: NameError
_____________________________________ test_layers_from_config[SparseLinear.v2-kwargs56-in_data56-out_data56] ______________________________________

name = 'SparseLinear.v2', kwargs = {}, in_data = (array([1, 2, 3], dtype=uint64), array([1., 2., 3.], dtype=float32), array([1, 1], dtype=int32))
out_data = array([[4., 2., 3., 4.],
       [1., 5., 3., 1.],
       [9., 8., 5., 7.]], dtype=float32)

    @pytest.mark.parametrize("name,kwargs,in_data,out_data", TEST_CASES)
    def test_layers_from_config(name, kwargs, in_data, out_data):
        cfg = {"@layers": name, **kwargs}
        filled_cfg = registry.fill({"config": cfg})
        assert srsly.is_json_serializable(filled_cfg)
        model = registry.resolve({"config": cfg})["config"]
        if "LSTM" in name:
            model = with_padded(model)
        valid = True
        with data_validation(valid):
>           model.initialize(in_data, out_data)

thinc/tests/layers/test_layers_api.py:153:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
thinc/model.py:316: in initialize
    validate_fwd_input_output(self.name, self._func, X, Y)
thinc/util.py:588: in validate_fwd_input_output
    ArgModel.update_forward_refs(**types.__dict__)
pydantic/v1/main.py:814: in update_forward_refs
    update_model_forward_refs(cls, cls.__fields__.values(), cls.__config__.json_encoders, localns)
pydantic/v1/typing.py:559: in update_model_forward_refs
    update_field_forward_refs(f, globalns=globalns, localns=localns)
pydantic/v1/typing.py:525: in update_field_forward_refs
    field.type_ = evaluate_forwardref(field.type_, globalns, localns or None)
pydantic/v1/typing.py:68: in evaluate_forwardref
    return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set())
typing.py:1081: in _evaluate
    eval(self.__forward_code__, globalns, localns),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

>   ???
E   NameError: name 'InT' is not defined

<string>:1: NameError
______________________________________ test_layers_from_config[premap_ids.v1-kwargs59-in_data59-out_data59] _______________________________________

name = 'premap_ids.v1', kwargs = {'column': 1, 'mapping_table': {}}, in_data = array([[1, 4],
       [2, 5],
       [3, 6]])
out_data = array([[1, 2, 3],
       [4, 5, 6]], dtype=int32)

    @pytest.mark.parametrize("name,kwargs,in_data,out_data", TEST_CASES)
    def test_layers_from_config(name, kwargs, in_data, out_data):
        cfg = {"@layers": name, **kwargs}
        filled_cfg = registry.fill({"config": cfg})
        assert srsly.is_json_serializable(filled_cfg)
        model = registry.resolve({"config": cfg})["config"]
        if "LSTM" in name:
            model = with_padded(model)
        valid = True
        with data_validation(valid):
>           model.initialize(in_data, out_data)

thinc/tests/layers/test_layers_api.py:153:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
thinc/model.py:316: in initialize
    validate_fwd_input_output(self.name, self._func, X, Y)
thinc/util.py:588: in validate_fwd_input_output
    ArgModel.update_forward_refs(**types.__dict__)
pydantic/v1/main.py:814: in update_forward_refs
    update_model_forward_refs(cls, cls.__fields__.values(), cls.__config__.json_encoders, localns)
pydantic/v1/typing.py:559: in update_model_forward_refs
    update_field_forward_refs(f, globalns=globalns, localns=localns)
pydantic/v1/typing.py:525: in update_field_forward_refs
    field.type_ = evaluate_forwardref(field.type_, globalns, localns or None)
pydantic/v1/typing.py:68: in evaluate_forwardref
    return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set())
typing.py:1081: in _evaluate
    eval(self.__forward_code__, globalns, localns),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

>   ???
E   NameError: name 'InT' is not defined

<string>:1: NameError
_______________________________________________________________ test_dropout[data2] _______________________________________________________________

data = Padded(data=array([[[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]],

       [[0., 0., 0.],
        [0., 0.,...array([1., 2., 3.], dtype=float32), lengths=array([1, 2, 3, 4], dtype=int32), indices=array([1, 2, 3, 4], dtype=int32))

    @pytest.mark.parametrize("data", [array2d, ragged, padded, [array2d, array2d]])
    def test_dropout(data):
        model = Dropout(0.2)
>       model.initialize(data, data)

thinc/tests/layers/test_layers_api.py:181:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
thinc/model.py:316: in initialize
    validate_fwd_input_output(self.name, self._func, X, Y)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

name = 'dropout', func = <function forward at 0x7bd4ac549d00>
X = Padded(data=array([[[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]],

       [[0., 0., 0.],
        [0., 0.,...array([1., 2., 3.], dtype=float32), lengths=array([1, 2, 3, 4], dtype=int32), indices=array([1, 2, 3, 4], dtype=int32))
Y = Padded(data=array([[[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]],

       [[0., 0., 0.],
        [0., 0.,...array([1., 2., 3.], dtype=float32), lengths=array([1, 2, 3, 4], dtype=int32), indices=array([1, 2, 3, 4], dtype=int32))

    def validate_fwd_input_output(
        name: str, func: Callable[[Any, Any, bool], Any], X: Any, Y: Any
    ) -> None:
        """Validate the input and output of a forward function against the type
        annotations, if available. Used in Model.initialize with the input and
        output samples as they pass through the network.
        """
        sig = inspect.signature(func)
        empty = inspect.Signature.empty
        params = list(sig.parameters.values())
        if len(params) != 3:
            bad_params = f"{len(params)} ({', '.join([p.name for p in params])})"
            err = f"Invalid forward function. Expected 3 arguments (model, X , is_train), got {bad_params}"
            raise DataValidationError(name, X, Y, [{"msg": err}])
        annot_x = params[1].annotation
        annot_y = sig.return_annotation
        sig_args: Dict[str, Any] = {"__config__": _ArgModelConfig}
        args = {}
        if X is not None and annot_x != empty:
            if isinstance(X, list) and len(X) > 5:
                X = X[:5]
            sig_args["X"] = (annot_x, ...)
            args["X"] = X
        if Y is not None and annot_y != empty:
            if isinstance(Y, list) and len(Y) > 5:
                Y = Y[:5]
            sig_args["Y"] = (annot_y, ...)
            args["Y"] = (Y, lambda x: x)
        ArgModel = create_model("ArgModel", **sig_args)
        # Make sure the forward refs are resolved and the types used by them are
        # available in the correct scope. See #494 for details.
        ArgModel.update_forward_refs(**types.__dict__)
        try:
            ArgModel.parse_obj(args)
        except ValidationError as e:
>           raise DataValidationError(name, X, Y, e.errors()) from None
E           thinc.util.DataValidationError:
E
E           Data validation error in 'dropout'
E           X: <class 'thinc.types.Padded'> Y: <class 'thinc.types.Padded'>
E
E           X                     not a valid numpy or cupy array
E           X                     not a valid numpy or cupy array
E           X                     not a valid numpy or cupy array
E           X                     not a valid numpy or cupy array
E           X                     not a valid numpy or cupy array
E           X                     not a valid numpy or cupy array
E           X                     not a valid numpy or cupy array
E           X                     not a valid numpy or cupy array
E           X                     value is not a valid sequence
E           X                     instance of Ragged, tuple or dict expected
E           X -> size_at_t        wrong array data type (expected int32/int64/uint32/uint64, got float32)
E           Y -> 0                not a valid numpy or cupy array
E           Y -> 0                not a valid numpy or cupy array
E           Y -> 0                not a valid numpy or cupy array
E           Y -> 0                not a valid numpy or cupy array
E           Y -> 0                not a valid numpy or cupy array
E           Y -> 0                not a valid numpy or cupy array
E           Y -> 0                not a valid numpy or cupy array
E           Y -> 0                not a valid numpy or cupy array
E           Y -> 0                value is not a valid sequence
E           Y -> 0                instance of Ragged, tuple or dict expected
E           Y -> 0 -> size_at_t   wrong array data type (expected int32/int64/uint32/uint64, got float32)

thinc/util.py:592: DataValidationError
______________________________________ test_layers_batching_all[premap_ids.v1-kwargs59-in_data59-out_data59] ______________________________________

name = 'premap_ids.v1', kwargs = {'column': 1, 'mapping_table': {}}, in_data = array([[1, 4],
       [2, 5],
       [3, 6]])
out_data = array([[1, 2, 3],
       [4, 5, 6]], dtype=int32)

    @pytest.mark.parametrize("name,kwargs,in_data,out_data", TEST_CASES)
    def test_layers_batching_all(name, kwargs, in_data, out_data):
        cfg = {"@layers": name, **kwargs}
        model = registry.resolve({"config": cfg})["config"]
        if "expand_window" in name:
            return
        if "LSTM" in name:
            model = with_padded(model)
            util_batch_unbatch_list(model, in_data, out_data)
        else:
            if isinstance(in_data, OPS.xp.ndarray) and in_data.ndim == 2:
                if isinstance(out_data, OPS.xp.ndarray) and out_data.ndim == 2:
>                   util_batch_unbatch_array(model, in_data, out_data)

thinc/tests/layers/test_layers_api.py:200:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
thinc/tests/layers/test_layers_api.py:211: in util_batch_unbatch_array
    model.initialize(in_data, out_data)
thinc/model.py:316: in initialize
    validate_fwd_input_output(self.name, self._func, X, Y)
thinc/util.py:588: in validate_fwd_input_output
    ArgModel.update_forward_refs(**types.__dict__)
pydantic/v1/main.py:814: in update_forward_refs
    update_model_forward_refs(cls, cls.__fields__.values(), cls.__config__.json_encoders, localns)
pydantic/v1/typing.py:559: in update_model_forward_refs
    update_field_forward_refs(f, globalns=globalns, localns=localns)
pydantic/v1/typing.py:525: in update_field_forward_refs
    field.type_ = evaluate_forwardref(field.type_, globalns, localns or None)
pydantic/v1/typing.py:68: in evaluate_forwardref
    return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set())
typing.py:1081: in _evaluate
    eval(self.__forward_code__, globalns, localns),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

>   ???
E   NameError: name 'InT' is not defined

<string>:1: NameError
================================================================ warnings summary =================================================================
../..thinc/tests/layers/test_mnist.py:81
  thinc/tests/layers/test_mnist.py:81: PytestUnknownMarkWarning: Unknown pytest.mark.slow - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/how-to/mark.html
    @pytest.mark.slow

../..thinc/tests/regression/issue519/test_issue519.py:13
  thinc/tests/regression/issue519/test_issue519.py:13: PytestUnknownMarkWarning: Unknown pytest.mark.slow - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/how-to/mark.html
    @pytest.mark.slow

tests/backends/test_ops.py: 80 warnings
  thinc/tests/backends/test_ops.py:1541: DeprecationWarning: Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)
    assert ops.xp.isclose(x_torch.grad.item() * dY, float(dx_thinc), atol=1e-06)

tests/backends/test_ops.py: 360 warnings
  thinc/tests/backends/test_ops.py:1549: DeprecationWarning: Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)
    x_torch.grad.item() * dY, float(backward(dY_thinc, X=x_thinc)), atol=1e-06

tests/backends/test_ops.py: 40 warnings
  thinc/tests/backends/test_ops.py:1533: DeprecationWarning: Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)
    assert ops.xp.isclose(x_torch.grad.item() * dY, float(dx_thinc), atol=1e-06)

tests/layers/test_layers_api.py: 1746 warnings
tests/layers/test_lstm.py: 238 warnings
tests/layers/test_transforms.py: 296 warnings
tests/layers/test_with_transforms.py: 2508 warnings
tests/model/test_validation.py: 145 warnings
tests/test_config.py: 66 warnings
  pydantic/v1/typing.py:68: DeprecationWarning: Failing to pass a value to the 'type_params' parameter of 'typing.ForwardRef._evaluate' is deprecated, as it leads to incorrect behaviour when calling typing.ForwardRef._evaluate on a stringified annotation that references a PEP 695 type parameter. It will be disallowed in Python 3.15.
    return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set())

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
============================================================= short test summary info =============================================================
FAILED tests/backends/test_ops.py::test_ops_consistency[NumpyOps] - AssertionError: alloc
FAILED tests/layers/test_layers_api.py::test_layers_from_config[SparseLinear.v1-kwargs55-in_data55-out_data55] - NameError: name 'InT' is not defined
FAILED tests/layers/test_layers_api.py::test_layers_from_config[SparseLinear.v2-kwargs56-in_data56-out_data56] - NameError: name 'InT' is not defined
FAILED tests/layers/test_layers_api.py::test_layers_from_config[premap_ids.v1-kwargs59-in_data59-out_data59] - NameError: name 'InT' is not defined
FAILED tests/layers/test_layers_api.py::test_dropout[data2] - thinc.util.DataValidationError:
FAILED tests/layers/test_layers_api.py::test_layers_batching_all[premap_ids.v1-kwargs59-in_data59-out_data59] - NameError: name 'InT' is not defined
=========================================== 6 failed, 1298 passed, 88 skipped, 5481 warnings in 22.47s ============================================

@honnibal
Copy link
Member

honnibal commented Apr 3, 2025

Thanks for attention on this. We've had a size restriction on PyPi that prevented releases on spaCy, and there's issues associated with Python 3.13 to do with the Pydantic usage for validation. I'm working on the update now.

We need to target the 8.3.x branch. That's the one spaCy uses.

I've been streaming some spaCy and ecosystem development to increase transparency, so you can see some of the issues around Pydantic in this stream: https://www.youtube.com/watch?v=TTEWWJ2PmZQ&list=PLBmcuObd5An5_iAxNYLJa_xWmNzsYce8c&index=1&t=2882s . I've had to work on a consulting project the last couple of weeks so I had to pause work on this, but I'm back on it now.

@Unknownuserfrommars
Copy link

Guys any news on this? Lots of packages are depending on spaCy and it can't update to support for Py 3.13.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

pipenv install failed with spacy 3.8.2 and thinc 8.3.2. Support for cython 3.x
7 participants