plotter: constraint: don't expose the constraints inside the ConstraintManager

Instead of exposing the "constraints" property of the ConstraintManager,
let other classes deal with the ConstraintManager as an entity which is
a collection of Constraints and can be iterated over or asked for its
length.

Change-Id: I77d859999a3d6962872a07843c92e3189658d4e7
diff --git a/cr2/plotter/Constraint.py b/cr2/plotter/Constraint.py
index 1f2af09..b3d06ba 100644
--- a/cr2/plotter/Constraint.py
+++ b/cr2/plotter/Constraint.py
@@ -199,11 +199,11 @@
         self._max_len = max(self._lens)
         self._pivot = pivot
         self._filters = filters
-        self.constraints = []
+        self._constraints = []
 
         self._run_expanded = False
         self._expand()
-        self._constraints()
+        self._populate_constraints()
 
     def _expand(self):
         """This is really important. We need to
@@ -250,7 +250,7 @@
                 self._ip_vec[val] = normalize_list(self._max_len,
                                                    self._ip_vec[val])
 
-    def _constraints(self):
+    def _populate_constraints(self):
         """Popluate the expanded constraints"""
 
         for idx in range(self._max_len):
@@ -262,7 +262,7 @@
             run = self._ip_vec[0][idx]
             col = self._ip_vec[1][idx]
             template = self._ip_vec[2][idx]
-            self.constraints.append(
+            self._constraints.append(
                 Constraint(
                     run,
                     self._pivot,
@@ -274,7 +274,7 @@
     def get_all_pivots(self):
         """Return a union of the pivot values"""
         pivot_vals = []
-        for constraint in self.constraints:
+        for constraint in self._constraints:
             pivot_vals += constraint.result.keys()
 
         p_list = list(set(pivot_vals))
@@ -291,4 +291,10 @@
 
     def constraint_labels(self):
         """Get the Str representation of the constraints"""
-        return map(str, self.constraints)
+        return map(str, self._constraints)
+
+    def __len__(self):
+        return len(self._constraints)
+
+    def __iter__(self):
+        return iter(self._constraints)
diff --git a/cr2/plotter/ILinePlot.py b/cr2/plotter/ILinePlot.py
index 683cb17..0c1eb0d 100644
--- a/cr2/plotter/ILinePlot.py
+++ b/cr2/plotter/ILinePlot.py
@@ -54,7 +54,6 @@
         self.templates = templates
         self.set_defaults()
         self._layout = None
-        self._constraints = []
 
         self._check_data()
         for key in kwargs:
@@ -72,7 +71,6 @@
             templates,
             self._attr["pivot"],
             self._attr["filters"])
-        self._constraints = self.c_mgr.constraints
         super(ILinePlot, self).__init__()
 
     def savefig(self, *args, **kwargs):
@@ -108,7 +106,7 @@
         for pivot in pivot_vals:
             data_frame = pd.Series()
 
-            for constraint in self._constraints:
+            for constraint in self.c_mgr:
                 result = constraint.result
                 constraint_str = str(constraint)
 
@@ -131,11 +129,10 @@
         pivot_vals = self.c_mgr.get_all_pivots()
         plot_index = 0
 
-        self._layout = ILinePlotGen(self._attr["per_line"],
-                                    len(self._constraints),
+        self._layout = ILinePlotGen(self._attr["per_line"], len(self.c_mgr),
                                     **self._attr)
 
-        for constraint in self._constraints:
+        for constraint in self.c_mgr:
             result = constraint.result
             title = str(constraint)
             data_frame = pd.Series()
diff --git a/cr2/plotter/LinePlot.py b/cr2/plotter/LinePlot.py
index 782fc2d..e855971 100644
--- a/cr2/plotter/LinePlot.py
+++ b/cr2/plotter/LinePlot.py
@@ -52,7 +52,6 @@
         self.set_defaults()
         self._fig = None
         self._layout = None
-        self._constraints = []
 
         self._check_data()
 
@@ -71,7 +70,6 @@
             templates,
             self._attr["pivot"],
             self._attr["filters"])
-        self._constraints = self.c_mgr.constraints
         super(LinePlot, self).__init__()
 
     def savefig(self, *args, **kwargs):
@@ -126,12 +124,12 @@
 
         self._fig = self._layout.get_fig()
 
-        legend = [None] * len(self._constraints)
+        legend = [None] * len(self.c_mgr)
         legend_str = self.c_mgr.constraint_labels()
         constraint_index = 0
-        cmap = ColorMap(len(self._constraints))
+        cmap = ColorMap(len(self.c_mgr))
 
-        for constraint in self._constraints:
+        for constraint in self.c_mgr:
             result = constraint.result
             plot_index = 0
             for pivot in pivot_vals:
@@ -197,11 +195,9 @@
 
         cmap = ColorMap(num_lines)
 
-        self._layout = PlotLayout(
-            self._attr["per_line"],
-            len(self._constraints),
-            width=self._attr["width"],
-            length=self._attr["length"])
+        self._layout = PlotLayout(self._attr["per_line"], len(self.c_mgr),
+                                  width=self._attr["width"],
+                                  length=self._attr["length"])
 
         self._fig = self._layout.get_fig()
 
@@ -210,7 +206,7 @@
         legend_str = []
         for pivot in pivot_vals:
             plot_index = 0
-            for constraint in self._constraints:
+            for constraint in self.c_mgr:
                 result = constraint.result
                 if pivot in result:
                     axis = self._layout.get_axis(plot_index)
@@ -255,8 +251,8 @@
 
         self._fig.legend(legend, legend_str)
         plot_index = 0
-        for constraint in self._constraints:
+        for constraint in self.c_mgr:
             self._layout.get_axis(plot_index).set_title(str(constraint))
             plot_index += 1
 
-        self._layout.finish(len(self._constraints))
+        self._layout.finish(len(self.c_mgr))
diff --git a/tests/test_constraint.py b/tests/test_constraint.py
index f18a4b7..228b7d8 100644
--- a/tests/test_constraint.py
+++ b/tests/test_constraint.py
@@ -40,9 +40,10 @@
 
         c_mgr = ConstraintManager(dfr, "load", None, AttrConf.PIVOT, {})
 
-        self.assertEquals(len(c_mgr.constraints), 1)
+        self.assertEquals(len(c_mgr), 1)
 
-        series = c_mgr.constraints[0].result[AttrConf.PIVOT_VAL]
+        constraint = iter(c_mgr).next()
+        series = constraint.result[AttrConf.PIVOT_VAL]
         self.assertEquals(series.to_dict().values(),
                           dfr["load"].to_dict().values())
 
@@ -51,9 +52,9 @@
 
         c_mgr = ConstraintManager(self.dfrs, "load", None, AttrConf.PIVOT, {})
 
-        self.assertEquals(len(c_mgr.constraints), 2)
+        self.assertEquals(len(c_mgr), 2)
 
-        for constraint, orig_dfr in zip(c_mgr.constraints, self.dfrs):
+        for constraint, orig_dfr in zip(c_mgr, self.dfrs):
             series = constraint.result[AttrConf.PIVOT_VAL]
             self.assertEquals(series.to_dict().values(),
                               orig_dfr["load"].to_dict().values())
@@ -64,9 +65,9 @@
         cols = ["load", "freq"]
         c_mgr = ConstraintManager(self.dfrs, cols, None, AttrConf.PIVOT, {})
 
-        self.assertEquals(len(c_mgr.constraints), 2)
+        self.assertEquals(len(c_mgr), 2)
 
-        for constraint, orig_dfr, col in zip(c_mgr.constraints, self.dfrs, cols):
+        for constraint, orig_dfr, col in zip(c_mgr, self.dfrs, cols):
             series = constraint.result[AttrConf.PIVOT_VAL]
             self.assertEquals(series.to_dict().values(),
                               orig_dfr[col].to_dict().values())
@@ -79,12 +80,15 @@
         c_mgr = ConstraintManager(self.dfrs, "load", None, AttrConf.PIVOT,
                                   simple_filter)
 
-        num_constraints = len(c_mgr.constraints)
+        num_constraints = len(c_mgr)
         self.assertEquals(num_constraints, 2)
 
-        self.assertEquals(len(c_mgr.constraints[0].result), 1)
+        constraint_iter = iter(c_mgr)
+        constraint = constraint_iter.next()
+        self.assertEquals(len(constraint.result), 1)
 
-        series_second_frame = c_mgr.constraints[1].result[AttrConf.PIVOT_VAL]
+        constraint = constraint_iter.next()
+        series_second_frame = constraint.result[AttrConf.PIVOT_VAL]
         self.assertEquals(series_second_frame.to_dict().values(), [3, 2])
 
     def test_pivoted_data(self):
@@ -92,9 +96,9 @@
 
         c_mgr = ConstraintManager(self.dfrs[0], "load", None, "cpu", {})
 
-        self.assertEquals(len(c_mgr.constraints), 1)
+        self.assertEquals(len(c_mgr), 1)
 
-        constraint = c_mgr.constraints[0]
+        constraint = iter(c_mgr).next()
         results = dict([(k, v.to_dict().values()) for k, v in constraint.result.items()])
         expected_results = {0: [1, 2], 1: [2, 3]}
 
@@ -105,24 +109,26 @@
 
         c_mgr = ConstraintManager(self.dfrs, "load", None, "cpu", {})
 
-        self.assertEquals(len(c_mgr.constraints), 2)
+        self.assertEquals(len(c_mgr), 2)
 
-        constraint = c_mgr.constraints[0]
+        constraint_iter = iter(c_mgr)
+        constraint = constraint_iter.next()
         self.assertEquals(constraint.result[0].to_dict().values(), [1, 2])
 
-        constraint = c_mgr.constraints[1]
+        constraint = constraint_iter.next()
         self.assertEquals(constraint.result[1].to_dict().values(), [2, 2])
 
     def test_pivoted_multiruns_multicolumns(self):
         """Test the constraint manager with multiple runs and columns"""
 
         c_mgr = ConstraintManager(self.dfrs, ["load", "freq"], None, "cpu", {})
-        self.assertEquals(len(c_mgr.constraints), 2)
+        self.assertEquals(len(c_mgr), 2)
 
-        constraint = c_mgr.constraints[0]
+        constraint_iter = iter(c_mgr)
+        constraint = constraint_iter.next()
         self.assertEquals(constraint.result[1].to_dict().values(), [2, 3])
 
-        constraint = c_mgr.constraints[1]
+        constraint = constraint_iter.next()
         self.assertEquals(constraint.result[0].to_dict().values(), [2, 1])
 
     def test_pivoted_with_filters(self):
@@ -132,9 +138,9 @@
         c_mgr = ConstraintManager(self.dfrs[0], "freq", None, "cpu",
                                   simple_filter)
 
-        self.assertEquals(len(c_mgr.constraints), 1)
+        self.assertEquals(len(c_mgr), 1)
 
-        constraint = c_mgr.constraints[0]
+        constraint = iter(c_mgr).next()
         result = constraint.result
 
         self.assertEquals(result[0].iloc[0], 3)