From ba50e00c4d6944f789665e76c6064ed4a4617a89 Mon Sep 17 00:00:00 2001 From: shadeMe Date: Mon, 23 Oct 2023 11:37:31 +0200 Subject: [PATCH 1/9] Update the "Missing factory" error message This accounts for model installations that took place during the current Python session. --- spacy/errors.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spacy/errors.py b/spacy/errors.py index db1a886aa8f..68d3b32991a 100644 --- a/spacy/errors.py +++ b/spacy/errors.py @@ -229,8 +229,9 @@ class Errors(metaclass=ErrorsWithCodes): "If you're using a Transformer, make sure to install 'spacy-transformers'. " "If you're using a custom component, make sure you've added the " "decorator `@Language.component` (for function components) or " - "`@Language.factory` (for class components).\n\nAvailable " - "factories: {opts}") + "`@Language.factory` (for class components). If you installed the model " + "during the current Python session, you'll need to restart Python to " + "correctly load the dependencies.\n\nAvailable factories: {opts}") E003 = ("Not a valid pipeline component. Expected callable, but " "got {component} (name: '{name}'). If you're using a custom " "component factory, double-check that it correctly returns your " From b99d2236edefc486a3a917084d8c4aa78ee418e1 Mon Sep 17 00:00:00 2001 From: shadeMe Date: Mon, 23 Oct 2023 11:57:16 +0200 Subject: [PATCH 2/9] Add a note about Jupyter notebooks --- spacy/errors.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spacy/errors.py b/spacy/errors.py index 68d3b32991a..29694532f66 100644 --- a/spacy/errors.py +++ b/spacy/errors.py @@ -230,8 +230,9 @@ class Errors(metaclass=ErrorsWithCodes): "If you're using a custom component, make sure you've added the " "decorator `@Language.component` (for function components) or " "`@Language.factory` (for class components). If you installed the model " - "during the current Python session, you'll need to restart Python to " - "correctly load the dependencies.\n\nAvailable factories: {opts}") + "during the current Python/Jupyter session, you'll need to restart Python (or " + "reload your Jupyter notebook) to correctly load the dependencies.\n\n" + "Available factories: {opts}") E003 = ("Not a valid pipeline component. Expected callable, but " "got {component} (name: '{name}'). If you're using a custom " "component factory, double-check that it correctly returns your " From 92ebb931bfac23cc21627a99d55245ce410992a4 Mon Sep 17 00:00:00 2001 From: shadeMe Date: Mon, 23 Oct 2023 14:25:11 +0200 Subject: [PATCH 3/9] Move error to `spacy.cli.download` Add extra message for Jupyter sessions --- spacy/cli/download.py | 24 +++++++++++++++++++++++- spacy/errors.py | 6 ++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/spacy/cli/download.py b/spacy/cli/download.py index de731b0fdde..35afef609fb 100644 --- a/spacy/cli/download.py +++ b/spacy/cli/download.py @@ -7,7 +7,13 @@ from .. import about from ..errors import OLD_MODEL_SHORTCUTS -from ..util import get_minor_version, is_package, is_prerelease_version, run_command +from ..util import ( + get_minor_version, + is_in_jupyter, + is_package, + is_prerelease_version, + run_command, +) from ._util import SDIST_SUFFIX, WHEEL_SUFFIX, Arg, Opt, app @@ -78,6 +84,22 @@ def download( f"You can now load the package via spacy.load('{model_name}')", ) + reload_deps_msg = ( + "If you have one or more instances of the Python runtime executing " + "in the background, you'll need to restart them to correctly load " + "the dependencies of the newly downloaded model. " + ) + if is_in_jupyter(): + reload_deps_msg = ( + f"{reload_deps_msg}This includes the current Jupyter session: " + "You can do this clicking on the 'Restart Kernel' button (or " + "'Restart Runtime' button in the case of Google Colab)" + ) + msg.info( + "Reloading dependencies", + reload_deps_msg, + ) + def get_model_filename(model_name: str, version: str, sdist: bool = False) -> str: dl_tpl = "{m}-{v}/{m}-{v}{s}" diff --git a/spacy/errors.py b/spacy/errors.py index 29694532f66..db1a886aa8f 100644 --- a/spacy/errors.py +++ b/spacy/errors.py @@ -229,10 +229,8 @@ class Errors(metaclass=ErrorsWithCodes): "If you're using a Transformer, make sure to install 'spacy-transformers'. " "If you're using a custom component, make sure you've added the " "decorator `@Language.component` (for function components) or " - "`@Language.factory` (for class components). If you installed the model " - "during the current Python/Jupyter session, you'll need to restart Python (or " - "reload your Jupyter notebook) to correctly load the dependencies.\n\n" - "Available factories: {opts}") + "`@Language.factory` (for class components).\n\nAvailable " + "factories: {opts}") E003 = ("Not a valid pipeline component. Expected callable, but " "got {component} (name: '{name}'). If you're using a custom " "component factory, double-check that it correctly returns your " From be4a7aab8675b751b999c5a150e192224542c662 Mon Sep 17 00:00:00 2001 From: shadeMe Date: Tue, 24 Oct 2023 10:46:18 +0200 Subject: [PATCH 4/9] Add additional note for interactive sessions --- spacy/cli/download.py | 6 ++++++ spacy/util.py | 12 +++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/spacy/cli/download.py b/spacy/cli/download.py index 35afef609fb..7196b7fcadd 100644 --- a/spacy/cli/download.py +++ b/spacy/cli/download.py @@ -9,6 +9,7 @@ from ..errors import OLD_MODEL_SHORTCUTS from ..util import ( get_minor_version, + is_in_interactive, is_in_jupyter, is_package, is_prerelease_version, @@ -95,6 +96,11 @@ def download( "You can do this clicking on the 'Restart Kernel' button (or " "'Restart Runtime' button in the case of Google Colab)" ) + elif is_in_interactive(): + reload_deps_msg = ( + f"{reload_deps_msg}This includes the current interactive Python session: " + "You can do this by pressing 'Ctrl+D' (or 'Ctrl+Z' and 'Enter' on Windows)." + ) msg.info( "Reloading dependencies", reload_deps_msg, diff --git a/spacy/util.py b/spacy/util.py index 79fcb8b8d04..79c911491fc 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -43,11 +43,12 @@ import langcodes import numpy import srsly -import thinc from catalogue import Registry, RegistryError from packaging.requirements import Requirement from packaging.specifiers import InvalidSpecifier, SpecifierSet from packaging.version import InvalidVersion, Version + +import thinc from thinc.api import ( Adam, Config, @@ -1111,6 +1112,15 @@ def is_in_jupyter() -> bool: return False +def is_in_interactive() -> bool: + """Check if user is running spaCy from an interactive Python + shell. Will return True in Jupyter notebooks too. + RETURNS (bool): True if in interactive mode, False if not. + """ + # https://stackoverflow.com/questions/2356399/tell-if-python-is-in-interactive-mode + return hasattr(sys, "ps1") or hasattr(sys, "ps2") + + def get_object_name(obj: Any) -> str: """Get a human-readable name of a Python object, e.g. a pipeline component. From 03cd5c941f685a2f12e96bf3cfff4a219f4b778d Mon Sep 17 00:00:00 2001 From: shadeMe Date: Tue, 24 Oct 2023 10:46:56 +0200 Subject: [PATCH 5/9] Remove note about `spacy-transformers` from error message --- spacy/errors.py | 1 - 1 file changed, 1 deletion(-) diff --git a/spacy/errors.py b/spacy/errors.py index db1a886aa8f..2f0135551fd 100644 --- a/spacy/errors.py +++ b/spacy/errors.py @@ -226,7 +226,6 @@ class Errors(metaclass=ErrorsWithCodes): E002 = ("Can't find factory for '{name}' for language {lang} ({lang_code}). " "This usually happens when spaCy calls `nlp.{method}` with a custom " "component name that's not registered on the current language class. " - "If you're using a Transformer, make sure to install 'spacy-transformers'. " "If you're using a custom component, make sure you've added the " "decorator `@Language.component` (for function components) or " "`@Language.factory` (for class components).\n\nAvailable " From 614dbec34ef477a5980a680fc03792e1e03e9166 Mon Sep 17 00:00:00 2001 From: shadeMe Date: Tue, 24 Oct 2023 10:48:56 +0200 Subject: [PATCH 6/9] `isort` --- spacy/util.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spacy/util.py b/spacy/util.py index 79c911491fc..f02b998ca25 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -43,12 +43,11 @@ import langcodes import numpy import srsly +import thinc from catalogue import Registry, RegistryError from packaging.requirements import Requirement from packaging.specifiers import InvalidSpecifier, SpecifierSet from packaging.version import InvalidVersion, Version - -import thinc from thinc.api import ( Adam, Config, From e8b715807b59d057f0616ab0392dd3cac4c49de0 Mon Sep 17 00:00:00 2001 From: Adriane Boyd Date: Sun, 5 Nov 2023 15:40:40 +0100 Subject: [PATCH 7/9] Improve checks for colab (also helps displacy) --- spacy/util.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/spacy/util.py b/spacy/util.py index f02b998ca25..63d7ea466f3 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -1097,17 +1097,26 @@ def is_cwd(path: Union[Path, str]) -> bool: def is_in_jupyter() -> bool: - """Check if user is running spaCy from a Jupyter notebook by detecting the - IPython kernel. Mainly used for the displaCy visualizer. - RETURNS (bool): True if in Jupyter, False if not. + """Check if user is running spaCy from a Jupyter or Colab notebook by + detecting the IPython kernel. Mainly used for the displaCy visualizer. + RETURNS (bool): True if in Jupyter/Colab, False if not. """ # https://stackoverflow.com/a/39662359/6400719 + # https://stackoverflow.com/questions/15411967 try: - shell = get_ipython().__class__.__name__ # type: ignore[name-defined] - if shell == "ZMQInteractiveShell": + if get_ipython().__class__.__name__ == "ZMQInteractiveShell": # type: ignore[name-defined] return True # Jupyter notebook or qtconsole + if get_ipython().__class__.__module__ == "google.colab._shell": # type: ignore[name-defined] + return True # Colab notebook except NameError: return False # Probably standard Python interpreter + # additional check for Colab + try: + import google.colab + + return True # Colab notebook + except ImportError: + return False return False From ea7a4e07054477d477fa5190b100ec0b6e49d275 Mon Sep 17 00:00:00 2001 From: Adriane Boyd Date: Sun, 5 Nov 2023 15:41:03 +0100 Subject: [PATCH 8/9] Update warning messages --- spacy/cli/download.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/spacy/cli/download.py b/spacy/cli/download.py index 7196b7fcadd..21c777f81fb 100644 --- a/spacy/cli/download.py +++ b/spacy/cli/download.py @@ -84,27 +84,27 @@ def download( "Download and installation successful", f"You can now load the package via spacy.load('{model_name}')", ) - - reload_deps_msg = ( - "If you have one or more instances of the Python runtime executing " - "in the background, you'll need to restart them to correctly load " - "the dependencies of the newly downloaded model. " - ) if is_in_jupyter(): reload_deps_msg = ( - f"{reload_deps_msg}This includes the current Jupyter session: " - "You can do this clicking on the 'Restart Kernel' button (or " - "'Restart Runtime' button in the case of Google Colab)" + "If you are in a Jupyter or Colab notebook, you may need to " + "restart Python in order to load all the package's dependencies. " + "You can do this by selecting the 'Restart kernel' or 'Restart " + "runtime' option." + ) + msg.warn( + "Restart to reload dependencies", + reload_deps_msg, ) elif is_in_interactive(): reload_deps_msg = ( - f"{reload_deps_msg}This includes the current interactive Python session: " - "You can do this by pressing 'Ctrl+D' (or 'Ctrl+Z' and 'Enter' on Windows)." + "If you are in an interactive Python session, you may need to " + "exit and restart Python to load all the package's dependencies. " + "You can exit with Ctrl-D (or Ctrl-Z and Enter on Windows)." + ) + msg.warn( + "Restart to reload dependencies", + reload_deps_msg, ) - msg.info( - "Reloading dependencies", - reload_deps_msg, - ) def get_model_filename(model_name: str, version: str, sdist: bool = False) -> str: From 0070daf3c8d203fb4bd0bf2b5f205891407ab73e Mon Sep 17 00:00:00 2001 From: Adriane Boyd Date: Wed, 8 Nov 2023 21:36:52 +0100 Subject: [PATCH 9/9] Improve flow for multiple checks --- spacy/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spacy/util.py b/spacy/util.py index d7a1c49bb0c..c127be03c37 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -1089,14 +1089,14 @@ def is_in_jupyter() -> bool: if get_ipython().__class__.__module__ == "google.colab._shell": # type: ignore[name-defined] return True # Colab notebook except NameError: - return False # Probably standard Python interpreter + pass # Probably standard Python interpreter # additional check for Colab try: import google.colab return True # Colab notebook except ImportError: - return False + pass return False