Repository: GiulioRossetti/cdlib (language: python)

Issue:
`infomap` ImportError not catched by `cdlib` in [crisp_partition.py, bipartite_clustering.py] in light version
Hi cdlib team,

Thanks for fixing the import issue mentioned in #201 . There is probably one more little code issue to be fixed.

**Describe the bug**
```
try:
    import infomap as imp
except ModuleNotFoundError:
    missing_packages.add("infomap")
    imp = None
```
This does not catch `ImportError`, which is the case in my environment. After capturing Exception (all exception) in `crisp_partition.py, bipartite_clustering.py` (two files), I can import cdlib.algorithms without other issues.


**To Reproduce**
Steps to reproduce the behavior:
- CDlib version
0.2.6 light version

**Screenshots**
![image](https://user-images.githubusercontent.com/12120524/160213574-5b2d6f19-d101-4854-b219-f5dbb2da4c0d.png)

Import issue on Mac M1
**Describe the bug**
`import cdlib.algorithms`
Apple M1 chip

```
(dynamo-dev) Ks-MacBook-Pro:dynamo-tutorials random$ python
Python 3.9.7 (default, Sep 16 2021, 08:50:36) 
[Clang 10.0.0 ] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import cdlib
>>> import cdlib.algorithms
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/random/opt/anaconda3/envs/dynamo-dev/lib/python3.9/site-packages/cdlib/algorithms/__init__.py", line 2, in <module>
    from .crisp_partition import *
  File "/Users/random/opt/anaconda3/envs/dynamo-dev/lib/python3.9/site-packages/cdlib/algorithms/crisp_partition.py", line 2, in <module>
    import infomap as imp
  File "/Users/random/opt/anaconda3/envs/dynamo-dev/lib/python3.9/site-packages/infomap.py", line 35, in <module>
    import _infomap
ImportError: dlopen(/Users/random/opt/anaconda3/envs/dynamo-dev/lib/python3.9/site-packages/_infomap.cpython-39-darwin.so, 0x0002): Library not loaded: /usr/local/opt/libomp/lib/libomp.dylib
  Referenced from: /Users/random/opt/anaconda3/envs/dynamo-dev/lib/python3.9/site-packages/_infomap.cpython-39-darwin.so
  Reason: tried: '/usr/local/opt/libomp/lib/libomp.dylib' (no such file), '/usr/local/lib/libomp.dylib' (no such file), '/usr/lib/libomp.dylib' (no such file)
```

```
(cdlib-test) Ks-MacBook-Pro:16725-medical-imaging random$ python
Python 3.8.12 | packaged by conda-forge | (default, Jan 30 2022, 23:36:06) 
[Clang 11.1.0 ] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import cdlib
>>> import cdlib.algorithms
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/random/opt/anaconda3/envs/cdlib-test/lib/python3.8/site-packages/cdlib/algorithms/__init__.py", line 2, in <module>
    from .crisp_partition import *
  File "/Users/random/opt/anaconda3/envs/cdlib-test/lib/python3.8/site-packages/cdlib/algorithms/crisp_partition.py", line 2, in <module>
    import infomap as imp
  File "/Users/random/opt/anaconda3/envs/cdlib-test/lib/python3.8/site-packages/infomap.py", line 35, in <module>
    import _infomap
ImportError: dlopen(/Users/random/opt/anaconda3/envs/cdlib-test/lib/python3.8/site-packages/_infomap.cpython-38-darwin.so, 0x0002): Library not loaded: /usr/local/opt/libomp/lib/libomp.dylib
  Referenced from: /Users/random/opt/anaconda3/envs/cdlib-test/lib/python3.8/site-packages/_infomap.cpython-38-darwin.so
  Reason: tried: '/usr/local/opt/libomp/lib/libomp.dylib' (no such file), '/usr/local/lib/libomp.dylib' (no such file), '/usr/lib/libomp.dylib' (no such file)

```
**To Reproduce**
installed via pip
```
Name: cdlib
Version: 0.2.5
Summary: Community Discovery Library
Home-page: https://github.com/GiulioRossetti/cdlib
Author: Giulio Rossetti
Author-email: giulio.rossetti@gmail.com
License: BSD-Clause-2
Location: /Users/random/opt/anaconda3/envs/cdlib-test/lib/python3.8/site-packages
Requires: angel-cd, bimlpa, chinese-whispers, cython, demon, dynetx, eva-lcd, future, infomap, karateclub, leidenalg, markov-clustering, matplotlib, networkx, nf1, numpy, pandas, pooch, pulp, pyclustering, python-igraph, python-Levenshtein, python-louvain, scikit-learn, scipy, seaborn, thresholdclustering, tqdm, wurlitzer
```
- Operating System
  - macOS Monterey
- Python version
 - tried in conda env 3.7, 3.8, 3.9

**Expected behavior**
Import successfully (cdlib worked and tested in 2021)

I treid `brew install libomp` but it does not work. The laptop is relatively new (released last year) and there are almost no messy system level customizations on this laptop.

Thanks for providing the community with the package! It is convenient, powerful and with good documentation. 



Discussion / hints:

Thanks for submitting your first issue!
Thanks for raising this issue: unfortunately, I don't have a recent M1 MacOS to reproduce it... 

@Yquetzal can you look into this?
I'll look into it, Wednesday at the latest.
So I confirm that I have the same problem, and I could not find a simple solution to solve the problem. It comes from infomap itself. I'll inform the creators of infomap of this problem just now, but in the meantime I have no solution... @GiulioRossetti , I was thinking even before this that we should have as default version a very basic, python-only cdlib (no infomap, no Leiden, no karate). 1)Many people come for Louvain and quality functions, 2) it would be lighter to install for teaching, 3)When such a crash happen, people will understand that it comes from the imported package. What do you think ? I can participate to clean the error messages when people try to run a method nor already installed.
@Yquetzal I think that having a "light" version of CDlib should be easy to achieve (we already have something similar with the pip package). If you can spot all the "troubling" dependencies I'll take care of revising the packaging pipeline and updating the installation instructions.
@dummyindex Following your problem, we modified the library structure so that you are not blocked by external packages that cannot install on your architecture. So now cdlib should work, you just cannot use infomap. I reported the problem to infomap managers, if you need it you can go to their GitHub and see that current workaround they propose, hopefully there is a simpler solution soon.
Feel free to report any additional issue.

Fix patch:
diff --git a/cdlib/algorithms/bipartite_clustering.py b/cdlib/algorithms/bipartite_clustering.py
index f608f8ed..e9d16af0 100644
--- a/cdlib/algorithms/bipartite_clustering.py
+++ b/cdlib/algorithms/bipartite_clustering.py
@@ -3,6 +3,7 @@
 from cdlib.utils import convert_graph_formats
 from collections import defaultdict
 from cdlib.algorithms.internal.pycondor import condor_object, initial_community, brim
+from cdlib.prompt_utils import report_missing_packages, prompt_import_failure
 
 missing_packages = set()
 
@@ -11,6 +12,8 @@
 except ModuleNotFoundError:
     missing_packages.add("infomap")
     imp = None
+except Exception as exception:
+    prompt_import_failure("infomap", exception)
 
 try:
     from wurlitzer import pipes
@@ -29,11 +32,7 @@
     missing_packages.add("leidenalg")
     leidenalg = None
 
-if len(missing_packages) > 0:
-    print(
-        "Note: to be able to use all bipartite methods, you need to install some additional packages: ",
-        missing_packages,
-    )
+report_missing_packages(missing_packages)
 
 __all__ = ["bimlpa", "CPM_Bipartite", "infomap_bipartite", "condor"]
 
diff --git a/cdlib/algorithms/crisp_partition.py b/cdlib/algorithms/crisp_partition.py
index 0be2dcba..5d95d3c4 100644
--- a/cdlib/algorithms/crisp_partition.py
+++ b/cdlib/algorithms/crisp_partition.py
@@ -33,6 +33,8 @@
 from cdlib.algorithms.internal.principled import principled
 from cdlib.algorithms.internal.MCODE import m_code
 from cdlib.algorithms.internal.RSC import rsc_evaluate_graph
+from cdlib.prompt_utils import report_missing_packages, prompt_import_failure
+
 import warnings
 
 import markov_clustering as mc
@@ -55,6 +57,8 @@
 except ModuleNotFoundError:
     missing_packages.add("infomap")
     imp = None
+except Exception as exception:
+    prompt_import_failure("infomap", exception)
 
 try:
     from wurlitzer import pipes
@@ -85,11 +89,8 @@
     missing_packages.add("karateclub")
 
 
-if len(missing_packages) > 0:
-    print(
-        "Note: to be able to use all crisp methods, you need to install some additional packages: ",
-        missing_packages,
-    )
+report_missing_packages(missing_packages)
+
 
 try:
     from GraphRicciCurvature.OllivierRicci import OllivierRicci
diff --git a/cdlib/algorithms/overlapping_partition.py b/cdlib/algorithms/overlapping_partition.py
index 16db1cea..30ae9ffe 100644
--- a/cdlib/algorithms/overlapping_partition.py
+++ b/cdlib/algorithms/overlapping_partition.py
@@ -32,6 +32,8 @@
     endntm_find_overlap_cluster,
     endntm_evalFuction,
 )
+from cdlib.prompt_utils import report_missing_packages
+
 import warnings
 
 missing_packages = set()
@@ -71,11 +73,7 @@ def __try_load_karate(init=False):
     ASLPAw = None
     missing_packages.add("ASLPAw")
 
-if len(missing_packages) > 0:
-    print(
-        "Note: to be able to use all overlapping methods, you need to install some additional packages: ",
-        missing_packages,
-    )
+report_missing_packages(missing_packages)
 
 __all__ = [
     "ego_networks",
diff --git a/cdlib/prompt_utils.py b/cdlib/prompt_utils.py
new file mode 100644
index 00000000..9e71c085
--- /dev/null
+++ b/cdlib/prompt_utils.py
@@ -0,0 +1,12 @@
+def report_missing_packages(package_list: list):
+    if len(package_list) > 0:
+        print(
+            "Note: to be able to use all crisp methods, you need to install some additional packages: ",
+            package_list,
+        )
+
+def prompt_import_failure(package: str, exception: Exception, show_details=False):
+    print("Note: cannot import package: %s" % str(package))
+    if show_details:
+        print("------> Detailed exception:")
+        print(exception)


Test patch:
diff --git a/cdlib/test/test_community_discovery_models.py b/cdlib/test/test_community_discovery_models.py
index 232b87e4..05d1c303 100644
--- a/cdlib/test/test_community_discovery_models.py
+++ b/cdlib/test/test_community_discovery_models.py
@@ -29,6 +29,8 @@
     import infomap
 except ModuleNotFoundError:
     infomap = None
+except Exception as exception:
+    prompt_import_failure("infomap", exception)
 
 try:
     import graph_tool.all as gt