From 8ed788660b1103077d8a90eb4664772a040058d5 Mon Sep 17 00:00:00 2001 From: Koichi Yasuoka Date: Tue, 9 Feb 2021 14:43:02 +0900 Subject: [PATCH 1/2] Several callable objects do not have __qualname__ --- spacy/util.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spacy/util.py b/spacy/util.py index f55b03db8..013c87acc 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -930,6 +930,8 @@ def is_same_func(func1: Callable, func2: Callable) -> bool: """ if not callable(func1) or not callable(func2): return False + if not hasattr(func1,"__qualname__") or not hasattr(func2,"__qualname__"): + return False same_name = func1.__qualname__ == func2.__qualname__ same_file = inspect.getfile(func1) == inspect.getfile(func2) same_code = inspect.getsourcelines(func1) == inspect.getsourcelines(func2) From 21176c69b0c9743c5e107fed6637208f97f48fd0 Mon Sep 17 00:00:00 2001 From: Ines Montani Date: Wed, 10 Feb 2021 14:12:00 +1100 Subject: [PATCH 2/2] Update and add test --- spacy/tests/pipeline/test_pipe_factories.py | 21 +++++++++++++++++---- spacy/util.py | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/spacy/tests/pipeline/test_pipe_factories.py b/spacy/tests/pipeline/test_pipe_factories.py index 2af4b1efb..e1706ffb1 100644 --- a/spacy/tests/pipeline/test_pipe_factories.py +++ b/spacy/tests/pipeline/test_pipe_factories.py @@ -451,13 +451,27 @@ def test_pipe_factories_from_source_config(): assert config["arg"] == "world" -def test_pipe_factories_decorator_idempotent(): +class PipeFactoriesIdempotent: + def __init__(self, nlp, name): + ... + + def __call__(self, doc): + ... + + +@pytest.mark.parametrize( + "i,func,func2", + [ + (0, lambda nlp, name: lambda doc: doc, lambda doc: doc), + (1, PipeFactoriesIdempotent, PipeFactoriesIdempotent(None, None)), + ], +) +def test_pipe_factories_decorator_idempotent(i, func, func2): """Check that decorator can be run multiple times if the function is the same. This is especially relevant for live reloading because we don't want spaCy to raise an error if a module registering components is reloaded. """ - name = "test_pipe_factories_decorator_idempotent" - func = lambda nlp, name: lambda doc: doc + name = f"test_pipe_factories_decorator_idempotent_{i}" for i in range(5): Language.factory(name, func=func) nlp = Language() @@ -466,7 +480,6 @@ def test_pipe_factories_decorator_idempotent(): # Make sure it also works for component decorator, which creates the # factory function name2 = f"{name}2" - func2 = lambda doc: doc for i in range(5): Language.component(name2, func=func2) nlp = Language() diff --git a/spacy/util.py b/spacy/util.py index 013c87acc..aa9bf301e 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -930,7 +930,7 @@ def is_same_func(func1: Callable, func2: Callable) -> bool: """ if not callable(func1) or not callable(func2): return False - if not hasattr(func1,"__qualname__") or not hasattr(func2,"__qualname__"): + if not hasattr(func1, "__qualname__") or not hasattr(func2, "__qualname__"): return False same_name = func1.__qualname__ == func2.__qualname__ same_file = inspect.getfile(func1) == inspect.getfile(func2)