From eee3ba5550dae1bcf2d4aa50af9f83c544ac9f74 Mon Sep 17 00:00:00 2001 From: Yuri Ulianov <68346643+yukeeul@users.noreply.github.com> Date: Sun, 21 May 2023 19:31:06 +0300 Subject: [PATCH] Removed nmslib installation on Win Python3.9 (#36) * removed nmslib installation on Win Python3.9 * fixes for int32 problem * nmslib moved to extras, reversed type specifications * added message for nmslib ImportError * changed ImportError description * refactored nmslib ImportError handling --- poetry.lock | 5 +++-- pyproject.toml | 5 +++-- rectools/compat.py | 20 ++++++++++++++++++++ rectools/tools/__init__.py | 5 ++++- tests/test_compat.py | 4 ++-- 5 files changed, 32 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index 573c13fc..fa065722 100644 --- a/poetry.lock +++ b/poetry.lock @@ -549,7 +549,7 @@ name = "nmslib" version = "2.1.1" description = "Non-Metric Space Library (NMSLIB)" category = "main" -optional = false +optional = true python-versions = "*" [package.dependencies] @@ -1221,8 +1221,9 @@ docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tideli testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] [extras] -all = ["torch", "pytorch-lightning"] +nmslib = ["nmslib"] nn = ["torch", "pytorch-lightning"] +all = ["nmslib", "torch", "pytorch-lightning"] [metadata] lock-version = "1.1" diff --git a/pyproject.toml b/pyproject.toml index 51c3884d..b7e50f86 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,6 @@ pandas = ">=0.25.3, <2.0.0" scipy = "^1.5.4" tqdm = "^4.27.0" implicit = "0.4.4" -nmslib = "^2.0.4" attrs = ">=19.1.0,<22.0.0" typeguard = "^2.0.1" lightfm = "^1.16" @@ -63,12 +62,14 @@ lightfm = "^1.16" # To avoid problems with resolving dependencies Markdown = "~3.2" +nmslib = {version = "^2.0.4", optional = true} torch = {version = "^1.6", optional = true} pytorch-lightning = {version = "^1.6", optional = true} [tool.poetry.extras] +nmslib = ["nmslib"] nn = ["torch", "pytorch-lightning"] -all = ["torch", "pytorch-lightning"] +all = ["nmslib", "torch", "pytorch-lightning"] [tool.poetry.dev-dependencies] black = "22.3.0" diff --git a/rectools/compat.py b/rectools/compat.py index ae3b4504..6933ad1e 100644 --- a/rectools/compat.py +++ b/rectools/compat.py @@ -27,5 +27,25 @@ def __new__(cls, *args: tp.Any, **kwargs: tp.Any) -> tp.Any: ) +class NmslibModelUnavailable: + """Dummy class the instance of which is returned in case a model provided lacks any libraries required""" + + def __new__(cls, *args: tp.Any, **kwargs: tp.Any) -> tp.Any: + """Raise ImportError when an attempt to instantiate an unavailable model is made""" + raise ImportError( + f"Cannot initialize {cls.__name__}: " + f"run `pip install rectools[nmslib]` to install extra requirements before accessing {cls.__name__} " + f"(see `extras/requirements-nn.txt)" + ) + + class DSSMModel(NNModelUnavailable): """Dummy class the instance of which is returned in case DSSMModel lacks any libraries required""" + + +class ItemToItemAnnRecommender(NmslibModelUnavailable): + """Dummy class the instance of which is returned in case ItemToItemAnnRecommender lacks any libraries required""" + + +class UserToItemAnnRecommender(NmslibModelUnavailable): + """Dummy class the instance of which is returned in case UserToItemAnnRecommender lacks any libraries required""" diff --git a/rectools/tools/__init__.py b/rectools/tools/__init__.py index a65fe1df..ff9d6550 100644 --- a/rectools/tools/__init__.py +++ b/rectools/tools/__init__.py @@ -25,7 +25,10 @@ `tools.UserToItemAnnRecommender` """ -from .ann import ItemToItemAnnRecommender, UserToItemAnnRecommender +try: + from .ann import ItemToItemAnnRecommender, UserToItemAnnRecommender +except ImportError: # pragma: no cover + from ..compat import ItemToItemAnnRecommender, UserToItemAnnRecommender # type: ignore __all__ = ( "ItemToItemAnnRecommender", diff --git a/tests/test_compat.py b/tests/test_compat.py index 614e7c0e..da21e151 100644 --- a/tests/test_compat.py +++ b/tests/test_compat.py @@ -16,12 +16,12 @@ import pytest -from rectools.compat import DSSMModel +from rectools.compat import DSSMModel, ItemToItemAnnRecommender, UserToItemAnnRecommender @pytest.mark.parametrize( "model", - (DSSMModel,), + (DSSMModel, ItemToItemAnnRecommender, UserToItemAnnRecommender), ) def test_raise_when_model_not_available( model: tp.Any,