Repository: piskvorky/gensim

Issue:
Provide Python3.9 Wheels 
<!--
**IMPORTANT**:

- Use the [Gensim mailing list](https://groups.google.com/forum/#!forum/gensim) to ask general or usage questions. Github issues are only for bug reports.
- Check [Recipes&FAQ](https://github.com/RaRe-Technologies/gensim/wiki/Recipes-&-FAQ) first for common answers.

Github bug reports that do not include relevant information and context will be closed without an answer. Thanks!
-->

#### Problem description

I'm attempting to install this on Windows as it is a dependency for a program I wish to run however, to install from source Microsoft Visual C++ 14.0 is required. 

Would it be possible to provide wheels for this version? 

#### Steps/code/corpus to reproduce

do `pip install gensim` on Python3.9 Windows 10

```
Microsoft Visual C++ 14.0 is required. Get it with "Build Tools for Visual Studio": https://visualstudio.microsoft.com/downloads/   
```

#### Versions


Windows-10-10.0.19041-SP0
Python 3.9.2 (tags/v3.9.2:1a79785, Feb 19 2021, 13:44:55) [MSC v.1928 64 bit (AMD64)]
Bits 64
NumPy 1.20.1
SciPy 1.6.1
gensim N/A (attempting to install 3.8.3)



Thanks 


Discussion:
Related PR: https://github.com/RaRe-Technologies/gensim/pull/2966

Resolving patch:
diff --git a/gensim/similarities/__init__.py b/gensim/similarities/__init__.py
--- a/gensim/similarities/__init__.py
+++ b/gensim/similarities/__init__.py
@@ -3,7 +3,18 @@
 """
 
 # bring classes directly into package namespace, to save some typing
-
+import warnings
+try:
+    import Levenshtein  # noqa:F401
+except ImportError:
+    warnings.warn(
+        "The gensim.similarities.levenshtein submodule is disabled, because the optional "
+        "Levenshtein package <https://pypi.org/project/python-Levenshtein/> is unavailable. "
+        "Install Levenhstein (e.g. `pip install python-Levenshtein`) to suppress this warning."
+    )
+    LevenshteinSimilarityIndex = None
+else:
+    from .levenshtein import LevenshteinSimilarityIndex  # noqa:F401
 from .docsim import (  # noqa:F401
     Similarity,
     MatrixSimilarity,
@@ -15,4 +26,3 @@
     UniformTermSimilarityIndex,
     WordEmbeddingSimilarityIndex,
     SparseTermSimilarityMatrix)
-from .levenshtein import LevenshteinSimilarityIndex  # noqa:F401
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -17,9 +17,9 @@
 import platform
 import shutil
 import sys
-from setuptools import setup, find_packages, Extension
-from setuptools.command.build_ext import build_ext
 
+from setuptools import Extension, find_packages, setup
+from setuptools.command.build_ext import build_ext
 
 c_extensions = {
     'gensim.models.word2vec_inner': 'gensim/models/word2vec_inner.c',
@@ -270,15 +270,19 @@ def run(self):
 #    'pytest-rerunfailures',  # disabled 2020-08-28 for <https://github.com/pytest-dev/pytest-rerunfailures/issues/128>
     'mock',
     'cython',
-    'nmslib',
-    'pyemd',
     'testfixtures',
     'Morfessor==2.0.2a4',
-    'python-Levenshtein >= 0.10.2',
 ]
 
+if not (sys.platform.lower().startswith("win") and sys.version_info[:2] >= (3, 9)):
+    core_testenv.extend([
+        'pyemd',
+        'nmslib',
+        'python-Levenshtein >= 0.10.2',
+    ])
+
 # Add additional requirements for testing on Linux that are skipped on Windows.
-linux_testenv = core_testenv[:] + visdom_req + ['pyemd', ]
+linux_testenv = core_testenv[:] + visdom_req
 
 # Skip problematic/uninstallable  packages (& thus related conditional tests) in Windows builds.
 # We still test them in Linux via Travis, see linux_testenv above.
@@ -308,7 +312,6 @@ def run(self):
     'nltk',
     'testfixtures',
     'statsmodels',
-    'pyemd',
     'pandas',
 ]
 


Test patch:
diff --git a/gensim/test/test_similarities.py b/gensim/test/test_similarities.py
--- a/gensim/test/test_similarities.py
+++ b/gensim/test/test_similarities.py
@@ -1545,6 +1545,7 @@ def test_inner_product_corpus_corpus_true_true(self):
 
 
 class TestLevenshteinDistance(unittest.TestCase):
+    @unittest.skipIf(LevenshteinSimilarityIndex is None, "gensim.similarities.levenshtein is disabled")
     def test_max_distance(self):
         t1 = "holiday"
         t2 = "day"
@@ -1557,12 +1558,14 @@ def test_max_distance(self):
 
 
 class TestLevenshteinSimilarity(unittest.TestCase):
+    @unittest.skipIf(LevenshteinSimilarityIndex is None, "gensim.similarities.levenshtein is disabled")
     def test_empty_strings(self):
         t1 = ""
         t2 = ""
 
         self.assertEqual(1.0, levsim(t1, t2))
 
+    @unittest.skipIf(LevenshteinSimilarityIndex is None, "gensim.similarities.levenshtein is disabled")
     def test_negative_hyperparameters(self):
         t1 = "holiday"
         t2 = "day"
@@ -1578,6 +1581,7 @@ def test_negative_hyperparameters(self):
         with self.assertRaises(AssertionError):
             levsim(t1, t2, -alpha, -beta)
 
+    @unittest.skipIf(LevenshteinSimilarityIndex is None, "gensim.similarities.levenshtein is disabled")
     def test_min_similarity(self):
         t1 = "holiday"
         t2 = "day"
@@ -1607,9 +1611,9 @@ def setUp(self):
         self.documents = [[u"government", u"denied", u"holiday"], [u"holiday", u"slowing", u"hollingworth"]]
         self.dictionary = Dictionary(self.documents)
 
+    @unittest.skipIf(LevenshteinSimilarityIndex is None, "gensim.similarities.levenshtein is disabled")
     def test_most_similar(self):
         """Test most_similar returns expected results."""
-
         index = LevenshteinSimilarityIndex(self.dictionary)
         results = list(index.most_similar(u"holiday", topn=1))
         self.assertLess(0, len(results))