Repository: netsiphd/netrd (language: python)

Issue:
LGTM results/integration
I ran the repo through LGTM a while back, and the results are [here](https://lgtm.com/projects/g/netsiphd/netrd/?mode=list). Most of these are pretty easy fixes. 

I think it might also make sense to add the integration to avoid having these things pile up.


Discussion / hints:
@leotrs I think you had mentioned some other automated code review integration.
https://www.codefactor.io/
[Here](https://www.codefactor.io/repository/github/netsiphd/netrd/issues) are the Codefactor results. Less about unused imports, a bit more substantive.

Maybe instead of adding another integration, we just add a check in the existing test suite to use flake8 to catch unused imports, then add to that as needed?
Yes, sounds good. Also, Codefactor can become very fussy, especially when taking contributions from many people who are not all on the same page about code standards/quality/practices/etc.
Conveniently, I missed an unused import for us to try out the flake8 integration on...

Fix patch:
diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml
index edfe3af9..223781ad 100644
--- a/.github/workflows/python-ci.yml
+++ b/.github/workflows/python-ci.yml
@@ -24,13 +24,17 @@ jobs:
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip
-        pip install black pytest
+        pip install black pytest flake8
         if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
         pip install -e .
     - name: Lint with black
       run: |
         black --skip-string-normalization --check netrd
         black --skip-string-normalization --check tests
+    - name: Check for unused imports with flake8
+      run: |
+        flake8 --select=F401,F403 netrd
+        flake8 --select=F401,F403 tests
     - name: Test with pytest
       run: |
         cd tests/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index fd93e5d4..f2ca01c5 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -208,7 +208,23 @@ Once you have completed the above steps, you are ready to choose an algorithm to
    If you do not do this, our tests will likely fail and your code will not be
    merged without further changes.
 
-2. After updating your local code, the first thing to do is tell git which files
+2. We also want to make sure there are no unused imports; for that we'll use
+   [flake8](https://flake8.pycqa.org/en/latest/). This is a general-purpose
+   linter that we're using to catch unused imports and wildcard imports. You
+   can probably check these manually, but our test suite will run this command:
+
+   ```
+   # if you don't have flake8 installed on your system, just pip install:
+   # pip install flake8
+
+   flake8 --select F401,F403 netrd/
+   flake8 --select F401,F403 tests/
+   ```
+
+   And if there are any import warnings, it cause the tests to fail and will
+   have to be fixed before merging.
+
+3. After updating your local code, the first thing to do is tell git which files
    you have been working on. (This is called staging.) If you worked on a
    distance algorithm, for example, do
 
@@ -216,7 +232,7 @@ Once you have completed the above steps, you are ready to choose an algorithm to
    git add netrd/distance/<your_file> netrd/distance/__init__.py
    ```
 
-3. Next tell git to commit (or save) your changes:
+4. Next tell git to commit (or save) your changes:
 
 	```
 	git commit -m 'Write a commit message here. This will be public and
@@ -226,7 +242,7 @@ Once you have completed the above steps, you are ready to choose an algorithm to
 	implementation of SomeMethod, based on SomeAuthor and/or SomeCode.'
 	```
 
-4. Now you have to tell git to do two things. First, `pull` the latest changes from
+5. Now you have to tell git to do two things. First, `pull` the latest changes from
    the upstream repository (in case someone made changes while you were coding), 
    then `push` your changes and the updated code from your machine to your fork:
 
@@ -239,7 +255,7 @@ Once you have completed the above steps, you are ready to choose an algorithm to
 	conflicts that must be merged. If you run in to trouble here, ask
 	for help!
 
-5. Finally, you need to tell this (the upstream) repository to include your
+6. Finally, you need to tell this (the upstream) repository to include your
    contributions. For this, we use the GitHub web interface. At the top of
    this page, there is a 'New Pull Request' button. Click on it, and it
    will take you to a page titled 'Compare Changes'. Right below the title,
diff --git a/netrd/__init__.py b/netrd/__init__.py
index 08df8648..5b14c0f5 100644
--- a/netrd/__init__.py
+++ b/netrd/__init__.py
@@ -9,7 +9,7 @@
 
 """
 
-from . import distance
-from . import reconstruction
-from . import dynamics
-from . import utilities
+from . import distance  # noqa
+from . import reconstruction  # noqa
+from . import dynamics  # noqa
+from . import utilities  # noqa
diff --git a/netrd/distance/__init__.py b/netrd/distance/__init__.py
index bbd5c63c..f2f9dc3f 100644
--- a/netrd/distance/__init__.py
+++ b/netrd/distance/__init__.py
@@ -22,6 +22,7 @@
 from .graph_diffusion import GraphDiffusion
 
 __all__ = [
+    'BaseDistance',
     'Hamming',
     'Frobenius',
     'PortraitDivergence',
diff --git a/netrd/dynamics/__init__.py b/netrd/dynamics/__init__.py
index c064e078..b9bbba73 100644
--- a/netrd/dynamics/__init__.py
+++ b/netrd/dynamics/__init__.py
@@ -9,6 +9,7 @@
 from .SIS import SISModel
 
 __all__ = [
+    'BaseDynamics',
     'SherringtonKirkpatrickIsing',
     'SingleUnbiasedRandomWalker',
     'Kuramoto',
diff --git a/netrd/reconstruction/__init__.py b/netrd/reconstruction/__init__.py
index 3ce579a9..227d23ae 100644
--- a/netrd/reconstruction/__init__.py
+++ b/netrd/reconstruction/__init__.py
@@ -18,6 +18,7 @@
 from .correlation_spanning_tree import CorrelationSpanningTree
 
 __all__ = [
+    'BaseReconstructor',
     'RandomReconstructor',
     'CorrelationMatrix',
     'PartialCorrelationMatrix',
diff --git a/netrd/reconstruction/random.py b/netrd/reconstruction/random.py
index 14417938..b1ce7414 100644
--- a/netrd/reconstruction/random.py
+++ b/netrd/reconstruction/random.py
@@ -12,7 +12,6 @@
 """
 
 from .base import BaseReconstructor
-import networkx as nx
 import numpy as np
 from ..utilities import create_graph, threshold
 
diff --git a/netrd/utilities/__init__.py b/netrd/utilities/__init__.py
index 0b40a40b..bf25dc21 100644
--- a/netrd/utilities/__init__.py
+++ b/netrd/utilities/__init__.py
@@ -6,9 +6,39 @@
 
 """
 from .threshold import threshold
-from .graph import *
-from .read import *
-from .cluster import *
-from .standardize import *
+from .graph import (
+    create_graph,
+    ensure_undirected,
+    undirected,
+    ensure_unweighted,
+    unweighted,
+)
+from .read import read_time_series
+from .cluster import clusterGraph
+from .standardize import mean_GNP_distance
+from .entropy import (
+    js_divergence,
+    entropy_from_seq,
+    joint_entropy,
+    conditional_entropy,
+    categorized_data,
+    linear_bins,
+)
 
-__all__ = []
+__all__ = [
+    'threshold',
+    'clusterGraph',
+    'js_divergence',
+    'entropy_from_seq',
+    'joint_entropy',
+    'conditional_entropy',
+    'categorized_data',
+    'linear_bins',
+    'create_graph',
+    'undirected',
+    'ensure_undirected',
+    'unweighted',
+    'ensure_unweighted',
+    'read_time_series',
+    'mean_GNP_distance',
+]


Test patch:
diff --git a/tests/test_dynamics.py b/tests/test_dynamics.py
index 08436ee4..027b6f09 100644
--- a/tests/test_dynamics.py
+++ b/tests/test_dynamics.py
@@ -7,7 +7,6 @@
 """
 
 import networkx as nx
-import numpy as np
 from netrd import dynamics
 from netrd.dynamics import BaseDynamics