From 5661bca92f3d5aecc6af0131bfadf8b3dbe74067 Mon Sep 17 00:00:00 2001
From: Brandon Rodriguez <brodriguez8774@gmail.com>
Date: Tue, 3 Dec 2019 23:35:38 -0500
Subject: [PATCH] Create initial "network flow" graph classes

---
 __init__.py                                   |  1 +
 resources/__init__.py                         |  1 +
 resources/graphs/__init__.py                  |  2 +
 .../graphs/network_flow_graph/__init__.py     | 13 +++
 .../graphs/network_flow_graph/components.py   | 57 ++++++++++++
 resources/graphs/network_flow_graph/graph.py  | 89 +++++++++++++++++++
 .../graphs/network_flow_graph/__init__.py     |  0
 .../graphs/network_flow_graph/edge.py         | 24 +++++
 .../graphs/network_flow_graph/graph.py        | 56 ++++++++++++
 .../graphs/network_flow_graph/node.py         | 24 +++++
 10 files changed, 267 insertions(+)
 create mode 100644 resources/graphs/network_flow_graph/__init__.py
 create mode 100644 resources/graphs/network_flow_graph/components.py
 create mode 100644 resources/graphs/network_flow_graph/graph.py
 create mode 100644 tests/resources/graphs/network_flow_graph/__init__.py
 create mode 100644 tests/resources/graphs/network_flow_graph/edge.py
 create mode 100644 tests/resources/graphs/network_flow_graph/graph.py
 create mode 100644 tests/resources/graphs/network_flow_graph/node.py

diff --git a/__init__.py b/__init__.py
index 9257653..b902ffb 100644
--- a/__init__.py
+++ b/__init__.py
@@ -15,4 +15,5 @@ __all__ = [
     'WeightedGraph', 'WeightedEdge', 'WeightedNode',
 
     'DirectedWeightedEdge', 'DirectedWeightedNode', 'DirectedWeightedGraph',
+    'NetworkFlowEdge', 'NetworkFlowNode', 'NetworkFlowGraph',
 ]
diff --git a/resources/__init__.py b/resources/__init__.py
index a56c5a6..3785cc4 100644
--- a/resources/__init__.py
+++ b/resources/__init__.py
@@ -15,4 +15,5 @@ __all__ = [
     'WeightedEdge', 'WeightedNode', 'WeightedGraph',
 
     'DirectedWeightedEdge', 'DirectedWeightedNode', 'DirectedWeightedGraph',
+    'NetworkFlowEdge', 'NetworkFlowNode', 'NetworkFlowGraph',
 ]
diff --git a/resources/graphs/__init__.py b/resources/graphs/__init__.py
index c15d535..d757fe4 100644
--- a/resources/graphs/__init__.py
+++ b/resources/graphs/__init__.py
@@ -6,6 +6,7 @@
 from .basic_graph import *
 from .directed_graph import *
 from .directed_weighted_graph import *
+from .network_flow_graph import *
 from .state_machine import *
 from .weighted_graph import *
 
@@ -19,4 +20,5 @@ __all__ = [
     'WeightedEdge', 'WeightedNode', 'WeightedGraph',
 
     'DirectedWeightedEdge', 'DirectedWeightedNode', 'DirectedWeightedGraph',
+    'NetworkFlowEdge', 'NetworkFlowNode', 'NetworkFlowGraph',
 ]
diff --git a/resources/graphs/network_flow_graph/__init__.py b/resources/graphs/network_flow_graph/__init__.py
new file mode 100644
index 0000000..f0b274f
--- /dev/null
+++ b/resources/graphs/network_flow_graph/__init__.py
@@ -0,0 +1,13 @@
+"""
+"Network Flow Graph" folder importing definitions.
+"""
+
+# Import files/values we want to be available to other folders.
+from .components import NetworkFlowEdge, NetworkFlowNode
+from .graph import NetworkFlowGraph
+
+
+# Define imports when using the * flag on this folder.
+__all__ = [
+    'NetworkFlowEdge', 'NetworkFlowNode', 'NetworkFlowGraph',
+]
diff --git a/resources/graphs/network_flow_graph/components.py b/resources/graphs/network_flow_graph/components.py
new file mode 100644
index 0000000..e171dbd
--- /dev/null
+++ b/resources/graphs/network_flow_graph/components.py
@@ -0,0 +1,57 @@
+"""
+Date: 12-03-19
+Class: CS5310
+Assignment: Graph Library
+Author: Brandon Rodriguez
+
+
+Edge and Node classes for a "network flow graph" (Has edge weights and edge directions).
+Essentially the "vertex" and "vertex connection" classes in a Graph data structure.
+
+These classes are combined into one single file to avoid circular import dependencies.
+"""
+
+# System Imports.
+
+# User Class Imports.
+from ..directed_weighted_graph.components import DirectedWeightedEdge, DirectedWeightedNode
+
+
+#region Logging Initialization
+
+# Since this is a library, we specifically only modify logging if the library is being run alone.
+try:
+    # First, try to import the variable specific to our library logging.
+    from resources.logging import graph_library_logger
+
+    # It worked, so we know the project is being run stand alone, probably as a unittest.
+    # Proceed to configure logging.
+    from resources.logging import get_logger as init_logging
+    logger = init_logging(__name__)
+except (ImportError, ModuleNotFoundError):
+    # Above import failed. Project is being run as a library.
+    # Just import existing logger and do not modify.
+    import logging as init_logging
+    logger = init_logging.getLogger('graph_library')
+
+#endregion Logging Initialization
+
+
+class NetworkFlowEdge(DirectedWeightedEdge):
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+        # Define expected class types (should all be of "Network Flow" type).
+        # This is necessary for inheritance, or else child classes will only have access to parent functions.
+        self._edge_type = NetworkFlowEdge
+        self._node_type = NetworkFlowNode
+
+
+class NetworkFlowNode(DirectedWeightedNode):
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+        # Define expected class types (should all be of "Network Flow" type).
+        # This is necessary for inheritance, or else child classes will only have access to parent functions.
+        self._edge_type = NetworkFlowEdge
+        self._node_type = NetworkFlowNode
diff --git a/resources/graphs/network_flow_graph/graph.py b/resources/graphs/network_flow_graph/graph.py
new file mode 100644
index 0000000..19797ea
--- /dev/null
+++ b/resources/graphs/network_flow_graph/graph.py
@@ -0,0 +1,89 @@
+"""
+Date: 12-03-19
+Class: CS5310
+Assignment: Graph Library
+Author: Brandon Rodriguez
+
+
+Graph class for a "network flow graph" (Has edge weights and edge directions).
+Parent structure containing various Nodes and Edges.
+"""
+
+# System Imports.
+
+# User Class Imports.
+from .components import NetworkFlowEdge, NetworkFlowNode
+from ..directed_weighted_graph.graph import (
+    DirectedWeightedGraph,
+    DirectedWeightedGraphDisplay,
+    DirectedWeightedGraphEdges,
+    DirectedWeightedGraphNodes,
+)
+
+#region Logging Initialization
+
+# Since this is a library, we specifically only modify logging if the library is being run alone.
+try:
+    # First, try to import the variable specific to our library logging.
+    from resources.logging import graph_library_logger
+
+    # It worked, so we know the project is being run stand alone, probably as a unittest.
+    # Proceed to configure logging.
+    from resources.logging import get_logger as init_logging
+    logger = init_logging(__name__)
+except (ImportError, ModuleNotFoundError):
+    # Above import failed. Project is being run as a library.
+    # Just import existing logger and do not modify.
+    import logging as init_logging
+    logger = init_logging.getLogger('graph_library')
+
+#endregion Logging Initialization
+
+
+class NetworkFlowGraph(DirectedWeightedGraph):
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+        # Define expected class types (should all be of "Directed, Weighted" type).
+        # This is necessary for inheritance, or else child classes will only have access to parent functions.
+        self._edge_type = NetworkFlowEdge
+        self._graph_type = NetworkFlowGraph
+        self._node_type = NetworkFlowNode
+
+        # Get associated child classes.
+        self.display = NetworkFlowGraphDisplay(self)
+        self.edges = NetworkFlowGraphEdges(self)
+        self.nodes = NetworkFlowGraphNodes(self)
+
+
+class NetworkFlowGraphDisplay(DirectedWeightedGraphDisplay):
+    def __init__(self, parent, *args, **kwargs):
+        super().__init__(parent, *args, *kwargs)
+
+        if not isinstance(parent, NetworkFlowGraph):
+            raise TypeError('Expected parent of type NetworkFlowGraph.')
+
+        # Get calling parent.
+        self._parent = parent
+
+
+class NetworkFlowGraphEdges(DirectedWeightedGraphEdges):
+    def __init__(self, parent, *args, **kwargs):
+        super().__init__(parent, *args, *kwargs)
+
+        if not isinstance(parent, NetworkFlowGraph):
+            raise TypeError('Expected parent of type NetworkFlowGraph.')
+
+        # Get calling parent.
+        self._parent = parent
+
+
+class NetworkFlowGraphNodes(DirectedWeightedGraphNodes):
+    def __init__(self, parent, *args, **kwargs):
+        super().__init__(parent, *args, *kwargs)
+
+        if not isinstance(parent, NetworkFlowGraph):
+            raise TypeError('Expected parent of type NetworkFlowGraph.')
+
+        # Get calling parent.
+        self._parent = parent
diff --git a/tests/resources/graphs/network_flow_graph/__init__.py b/tests/resources/graphs/network_flow_graph/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/resources/graphs/network_flow_graph/edge.py b/tests/resources/graphs/network_flow_graph/edge.py
new file mode 100644
index 0000000..132fb6f
--- /dev/null
+++ b/tests/resources/graphs/network_flow_graph/edge.py
@@ -0,0 +1,24 @@
+"""
+Date: 12-03-19
+Class: CS5310
+Assignment: Graph Library
+Author: Brandon Rodriguez
+
+
+Tests for "Network Flow Edge" class.
+"""
+
+# System Imports.
+import unittest
+
+# User Class Imports.
+from resources import NetworkFlowEdge, NetworkFlowNode
+
+
+class TestNetworkFlowEdge(unittest.TestCase):
+    def setUp(self):
+        self.test_edge = NetworkFlowEdge('Test Edge')
+
+    def test__node_initialization(self):
+        self.assertEqual(self.test_edge._edge_type, NetworkFlowEdge)
+        self.assertEqual(self.test_edge._node_type, NetworkFlowNode)
diff --git a/tests/resources/graphs/network_flow_graph/graph.py b/tests/resources/graphs/network_flow_graph/graph.py
new file mode 100644
index 0000000..9ff035c
--- /dev/null
+++ b/tests/resources/graphs/network_flow_graph/graph.py
@@ -0,0 +1,56 @@
+"""
+Date: 12-03-19
+Class: CS5310
+Assignment: Graph Library
+Author: Brandon Rodriguez
+
+
+Tests for "Network Flow Graph" class.
+"""
+
+# System Imports.
+import unittest
+
+# User Class Imports.
+from resources import NetworkFlowEdge, NetworkFlowNode
+from resources import NetworkFlowGraph
+
+
+class TestNetworkFlowGraph(unittest.TestCase):
+    def setUp(self):
+        self.test_graph = NetworkFlowGraph()
+
+    def test__node_initialization(self):
+        self.assertEqual(self.test_graph._edge_type, NetworkFlowEdge)
+        self.assertEqual(self.test_graph._graph_type, NetworkFlowGraph)
+        self.assertEqual(self.test_graph._node_type, NetworkFlowNode)
+
+    def test__create(self):
+        # We have pretty thorough testing of the parent function.
+        # Thus, just test returned node is of "Network Flow" type.
+        node_1 = self.test_graph.nodes.create()
+        self.assertTrue(isinstance(node_1, NetworkFlowNode))
+
+    def test__remove(self):
+        # We have pretty thorough testing of the parent function.
+        # Thus, just test returned node is of "Network Flow" type.
+        node_1 = self.test_graph.nodes.create()
+        node_1 = self.test_graph.nodes.remove(node_1)
+        self.assertTrue(isinstance(node_1, NetworkFlowNode))
+
+    def test__connect(self):
+        # We have pretty thorough testing of the parent function.
+        # Thus, just test returned edge is of "Network Flow" type.
+        node_1 = self.test_graph.nodes.create()
+        node_2 = self.test_graph.nodes.create()
+        edge_1 = self.test_graph.nodes.connect(node_1, node_2)
+        self.assertTrue(isinstance(edge_1, NetworkFlowEdge))
+
+    def test__disconnect(self):
+        # We have pretty thorough testing of the parent function.
+        # Thus, just test returned edge is of "Network Flow" type.
+        node_1 = self.test_graph.nodes.create()
+        node_2 = self.test_graph.nodes.create()
+        self.test_graph.nodes.connect(node_1, node_2)
+        edge_1 = self.test_graph.nodes.disconnect(node_1_identifier=node_1, node_2_identifier=node_2)
+        self.assertTrue(isinstance(edge_1, NetworkFlowEdge))
diff --git a/tests/resources/graphs/network_flow_graph/node.py b/tests/resources/graphs/network_flow_graph/node.py
new file mode 100644
index 0000000..4c743d6
--- /dev/null
+++ b/tests/resources/graphs/network_flow_graph/node.py
@@ -0,0 +1,24 @@
+"""
+Date: 12-03-19
+Class: CS5310
+Assignment: Graph Library
+Author: Brandon Rodriguez
+
+
+Tests for "Network Flow Node" class.
+"""
+
+# System Imports.
+import unittest
+
+# User Class Imports.
+from resources import NetworkFlowEdge, NetworkFlowNode
+
+
+class TestNetworkFlowNode(unittest.TestCase):
+    def setUp(self):
+        self.test_node = NetworkFlowNode('Test Node')
+
+    def test__node_initialization(self):
+        self.assertEqual(self.test_node._edge_type, NetworkFlowEdge)
+        self.assertEqual(self.test_node._node_type, NetworkFlowNode)
-- 
GitLab