Repository: aplbrain/dotmotif (language: python)

Issue:
Move special imports to `extras_require` 
You should be able to use DotMotif without installing neo4j- and docker-flavored dependencies.

## Proposal:

```shell
# Only install core dotmotif for networkx and grandiso:
pip install dotmotif

# Install cypher extensions for neuPrint, and docker 
# extensions for creating a local neo4j database:
pip install 'dotmotif[neo4j]'
```


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml
index 048515b..1b0993c 100644
--- a/.github/workflows/python-package.yml
+++ b/.github/workflows/python-package.yml
@@ -15,7 +15,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        python-version: [3.7, 3.8]
+        python-version: [3.7, 3.8, 3.9, '3.10']
 
     steps:
           
diff --git a/dotmotif/__init__.py b/dotmotif/__init__.py
index a6bd687..26c349d 100644
--- a/dotmotif/__init__.py
+++ b/dotmotif/__init__.py
@@ -28,7 +28,12 @@
 
 from .executors.NetworkXExecutor import NetworkXExecutor
 from .executors.GrandIsoExecutor import GrandIsoExecutor
-from .executors.Neo4jExecutor import Neo4jExecutor
+
+try:
+    # For backwards compatibility:
+    from .executors.Neo4jExecutor import Neo4jExecutor
+except ImportError:
+    pass
 
 __version__ = "0.11.0"
 
diff --git a/dotmotif/executors/__init__.py b/dotmotif/executors/__init__.py
index 0bfc820..f70ec1d 100644
--- a/dotmotif/executors/__init__.py
+++ b/dotmotif/executors/__init__.py
@@ -1,5 +1,5 @@
 """
-Copyright 2020 The Johns Hopkins University Applied Physics Laboratory.
+Copyright 2022 The Johns Hopkins University Applied Physics Laboratory.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -15,6 +15,5 @@
 """
 
 from .Executor import Executor
-from .Neo4jExecutor import Neo4jExecutor
 from .NetworkXExecutor import NetworkXExecutor
 from .GrandIsoExecutor import GrandIsoExecutor
diff --git a/dotmotif/ingest/__init__.py b/dotmotif/ingest/__init__.py
index 68c6946..e803887 100644
--- a/dotmotif/ingest/__init__.py
+++ b/dotmotif/ingest/__init__.py
@@ -1,19 +1,14 @@
 # Standard installs:
 import abc
-import json
 import os
-import numbers
 
 # Non-standard installs:
-import dask.dataframe as dd
 import pandas as pd
 
 # Types only:
 from typing import List
 import networkx as nx
 
-from .. import utils
-
 
 class NetworkXConverter(abc.ABC):
     """
diff --git a/requirements.txt b/requirements.txt
index 754f643..be2243b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,7 +4,6 @@ lark-parser
 docker
 pandas
 py2neo
-dask[dataframe]
 tamarind>=0.2.0
 neuprint-python
 grandiso>=2.1.0
diff --git a/setup.py b/setup.py
index 77679b4..7319304 100644
--- a/setup.py
+++ b/setup.py
@@ -31,16 +31,21 @@
     packages=find_packages(exclude=["tests", "*.tests", "*.tests.*", "tests.*"]),
     classifiers=[],
     install_requires=[
-        "networkx",
+        "networkx>2.4",
         "numpy",
         "lark-parser",
-        "docker",
         "pandas",
-        "py2neo",
-        "dask[dataframe]",
-        "tamarind>=0.1.5",
-        "neuprint-python",
         "grandiso>=2.0.0",
     ],
+    extras_require={
+        "neo4j": [
+            "docker",
+            "tamarind>=0.1.5",
+            "py2neo",
+        ],
+        "neuprint": [
+            "neuprint-python",
+        ],
+    },
     include_package_data=True,
 )


Test patch:
diff --git a/dotmotif/executors/test_dm_cypher.py b/dotmotif/executors/test_dm_cypher.py
index 78eddd7..db86c40 100644
--- a/dotmotif/executors/test_dm_cypher.py
+++ b/dotmotif/executors/test_dm_cypher.py
@@ -6,7 +6,7 @@
 
 import unittest
 import dotmotif
-from dotmotif.executors import Neo4jExecutor
+from dotmotif.executors.Neo4jExecutor import Neo4jExecutor
 
 
 _DEMO_G_MIN = """
diff --git a/dotmotif/executors/test_grandisoexecutor.py b/dotmotif/executors/test_grandisoexecutor.py
index 95cd88b..7c7bdd1 100644
--- a/dotmotif/executors/test_grandisoexecutor.py
+++ b/dotmotif/executors/test_grandisoexecutor.py
@@ -2,10 +2,6 @@
 import dotmotif
 from dotmotif import Motif
 from dotmotif.executors import GrandIsoExecutor
-from dotmotif.executors.NetworkXExecutor import (
-    _edge_satisfies_constraints,
-    _node_satisfies_constraints,
-)
 from dotmotif.parsers.v2 import ParserV2
 import networkx as nx
 
diff --git a/dotmotif/executors/test_neuprintexecutor.py b/dotmotif/executors/test_neuprintexecutor.py
index a6b27ea..fde4f62 100644
--- a/dotmotif/executors/test_neuprintexecutor.py
+++ b/dotmotif/executors/test_neuprintexecutor.py
@@ -3,13 +3,12 @@
 HOST = "neuprint.janelia.org"
 DATASET = "hemibrain:v1.1"
 TOKEN = os.getenv("NEUPRINT_TOKEN")
+if TOKEN:
 
-import unittest
-
-from .. import Motif
-from .NeuPrintExecutor import NeuPrintExecutor
+    import unittest
 
-if TOKEN:
+    from .. import Motif
+    from .NeuPrintExecutor import NeuPrintExecutor
 
     class TestNeuPrintConnection(unittest.TestCase):
         def test_can_get_version(self):
diff --git a/dotmotif/tests/test_dm_flags.py b/dotmotif/tests/test_dm_flags.py
index 891a97f..ebe8a3f 100644
--- a/dotmotif/tests/test_dm_flags.py
+++ b/dotmotif/tests/test_dm_flags.py
@@ -1,7 +1,8 @@
 import unittest
 import dotmotif
 import networkx as nx
-from dotmotif.executors import Neo4jExecutor, NetworkXExecutor
+from dotmotif.executors.Neo4jExecutor import Neo4jExecutor
+from dotmotif.executors.GrandIsoExecutor import GrandIsoExecutor
 
 
 _DEMO_G_MIN = """
@@ -78,7 +79,7 @@ def test_from_nx_import(self):
         g.add_edge("A", "B")
         dm = dotmotif.Motif().from_nx(g)
 
-        E = NetworkXExecutor(graph=G)
+        E = GrandIsoExecutor(graph=G)
         self.assertEqual(len(E.find(dm)), 4)
 
     def test_from_nx_import(self):
@@ -90,5 +91,5 @@ def test_from_nx_import(self):
         g.add_edge("A", "B")
         dm = dotmotif.Motif(ignore_direction=True).from_nx(g)
 
-        E = NetworkXExecutor(graph=G)
+        E = GrandIsoExecutor(graph=G)
         self.assertEqual(len(E.find(dm)), 4)