]> hydra-www.ietfng.org Git - dyna2/commitdiff
Big improvements to code coverage!
authorTim Vieira <tim.f.vieira@gmail.com>
Mon, 5 Aug 2013 19:31:48 +0000 (15:31 -0400)
committerTim Vieira <tim.f.vieira@gmail.com>
Mon, 5 Aug 2013 19:31:48 +0000 (15:31 -0400)
12 files changed:
.coveragerc [new file with mode: 0644]
src/Dyna/Backend/Python/aggregator.py
src/Dyna/Backend/Python/chart.py
src/Dyna/Backend/Python/interpreter.py
src/Dyna/Backend/Python/prioritydict.py
src/Dyna/Backend/Python/repl.py
src/Dyna/Backend/Python/term.py
test/repl/aggregators.dynadoc [new file with mode: 0644]
test/repl/boolean-aggregators.dynadoc
test/repl/list.dynadoc
test/repl/repl-misc.dynadoc [new file with mode: 0644]
test/repl/retract-aggregator.dynadoc [moved from test/repl/retract-aggregator.dyna with 100% similarity]

diff --git a/.coveragerc b/.coveragerc
new file mode 100644 (file)
index 0000000..6cf9822
--- /dev/null
@@ -0,0 +1,26 @@
+# .coveragerc to control coverage.py
+[run]
+branch = True
+
+[report]
+# Regexes for lines to exclude from consideration
+exclude_lines =
+    # Have to re-enable the standard pragma
+    pragma: no cover
+
+    # Don't complain about missing debug-only code:
+    #def __repr__
+    #if self\.debug
+
+    # Don't complain if tests don't hit defensive assertion code:
+    raise AssertionError
+    raise NotImplementedError
+
+    # Don't complain if non-runnable code isn't run:
+    if 0:
+    if __name__ == .__main__.:
+
+ignore_errors = True
+
+[html]
+directory = coverage_html_report
index 9794891d771d16c23dd1c1cefd8b13acec32cd0b..685080d41578b6e4620ffdab04b2ad0f94770bb9 100644 (file)
@@ -23,13 +23,13 @@ class NoAggregatorError(Exception):
 
 class Aggregator(object):
     def fold(self):
-        raise AggregatorError("item doesn't have an aggregator.")
+        raise NotImplementedError('')
     def inc(self, _val, _ruleix, _variables):
-        pass
+        raise NotImplementedError('')
     def dec(self, _val, _ruleix, _variables):
-        pass
+        raise NotImplementedError('')
     def clear(self):
-        pass
+        raise NotImplementedError('')
 
 
 NoAggregator = Aggregator()
@@ -43,7 +43,7 @@ class BAggregator(Counter, Aggregator):
     def dec(self, val, _ruleix, _variables):
         self[val] -= 1
     def fromkeys(self, *_):
-        assert False, "This method should never be called."
+        raise NotImplementedError("This method should never be called.")
     def empty(self):
         return not any(m > 0 for m in self.itervalues())
 
@@ -100,7 +100,7 @@ class DictEquals(BAggregator):
 
 class majority_equals(BAggregator):
     def fold(self):
-        [(k,c)] = self.most_common(1)
+        [(k,c)] = self.most_common(1)   # how are ties handled?
         if c > 0:
             return k
 
index 505ff2df263ad16bd9d25d516cd87f29bccd0095..16047471a9bbfbe301daf4127a7288e5edfdfe77 100644 (file)
@@ -29,13 +29,13 @@ class Chart(object):
 
         heading = [self.name, '='*len(self.name)]
 
-        # special handing or-equals aggregators -- only list true facts (and errors)
+        # special handing `:-` aggregator -- only list true facts (and errors)
         if self.agg_name == ':-':
             lines = []
             for term in sorted(rows):
                 if term.value is true:
                     lines.append('%s.' % _repr(term))
-                elif term.value:  # e.g. $error
+                else:                                           # e.g. $error
                     lines.append('%s = %s.' % (_repr(term), _repr(term.value)))
             if self.arity != 0:
                 lines = heading + lines # heading
index 73ef0318b635ac54b17a98af02b50af452ba5d00..4f5c50d284003bfd347668cc0a03119791b16f1b 100644 (file)
@@ -377,6 +377,7 @@ class Interpreter(object):
     def run_uninitialized(self):
         q = set(self.uninitialized_rules)
         failed = []
+        # run to fixed point
         while q:
             rule = q.pop()
             try:
@@ -533,7 +534,7 @@ class Interpreter(object):
             if isinstance(item, Rule):
                 continue
             (v, es) = x
-            self.error[item] = (v, [(e, h) for e, h in es if h is None or h.rule.index == rule.index])
+            self.error[item] = (v, [(e, h) for e, h in es if h is None or h.rule == rule])
 
         self.recompute_coarse()
 
@@ -577,10 +578,7 @@ class Interpreter(object):
     # Communication with Dyna compiler
 
     def dynac(self, filename):
-        """
-        Compile a file full of dyna code. Note: this routine does not pass along
-        parser_state.
-        """
+        "Compile a string of dyna code."
         return self.compiler.dynac(filename)
 
     def dynac_code(self, code):
@@ -660,7 +658,7 @@ class Interpreter(object):
                 print >> out
 
         # errors pertaining to rules
-        for r in sorted(E, key=lambda r: r.index):
+        for r in sorted(E):
             print >> out, 'Error(s) in rule %s:' % r.index, r.span
             print >> out
             for line in r.src.split('\n'):
@@ -692,7 +690,7 @@ class Interpreter(object):
         if self.uninitialized_rules:
             print >> out, red % 'Uninitialized rules'
             print >> out, red % '==================='
-            for rule in sorted(self.uninitialized_rules, key=lambda r: r.index):
+            for rule in sorted(self.uninitialized_rules):
                 e = self.error[rule]
                 print >> out, 'Failed to initialize rule:'
                 print >> out, '   ', rule.src
@@ -704,7 +702,7 @@ class Interpreter(object):
         if self.recompile:
             print >> out, red % 'Failed to recompile'
             print >> out, red % '==================='
-            for rule in sorted(self.recompile, key=lambda r: r.index):
+            for rule in sorted(self.recompile):
                 e = self.error[rule]
                 print >> out, 'Failed to recompile rule:'
                 print >> out, '   ', rule.src
index fe1424a727510e14a979a7bca20f8e0ba3cc25ee..454dfb0df12211e5b4db0d05a500f96c7c7ffdc8 100644 (file)
@@ -33,28 +33,20 @@ class prioritydict(dict):
         self._heap = [(v, k) for k, v in self.iteritems()]
         heapify(self._heap)
 
-    def smallest(self):
-        """
-        Return the item with the lowest priority.
-
-        Raises IndexError if the object is empty.
-        """
-        heap = self._heap
-        v, k = heap[0]
-        while k not in self or self[k] != v:
-            heappop(heap)
-            v, k = heap[0]
-        return k
-
     def pop_smallest(self):
         """
         Return the item with the lowest priority and remove it.
 
         Raises IndexError if the object is empty.
         """
+
+        # Implementation note: Since we don't eagerly remove an element when
+        # it's priority changes, we need to filter our pops to make sure the
+        # priority isn't stale.
+
         heap = self._heap
         v, k = heappop(heap)
-        while k not in self or self[k] != v:
+        while k not in self or self[k] != v:   # while `k` is stale
             v, k = heappop(heap)
         del self[k]
         return k
index 8c2304bd9af4c849317b8d29998f1d4d2d05b6aa..cb5800dc81927180b28d7353ea84a44b7cb5b10c 100644 (file)
@@ -531,7 +531,7 @@ class REPL(cmd.Cmd, object):
         """
 
         if not q.strip():
-            print 'No query specified. Type `help trace` for usage information.'
+            print 'No query specified. Type `help trace` for usage.'
             return
 
         if q.endswith('.'):
index f46f6253b950f23907b0950265dfa63e4514fb57..f2b238758ac85f66d2282039a6c2afbe4a296812 100644 (file)
@@ -12,8 +12,8 @@ class Term(object):
         self.value = None
         self.aggregator = None
 
-    def __eq__(self, other):
-        return self is other
+#    def __eq__(self, other):
+#        return self is other
 
     def __cmp__(self, other):
         if self is other:
@@ -75,8 +75,8 @@ class Cons(NoIntern, Term):
             else:
                 yield a, (None,), a
 
-    def __iter__(self):
-        return iter(self.aslist)
+#    def __iter__(self):
+#        return iter(self.aslist)
 
 
 class Error(NoIntern, Term):
@@ -97,8 +97,8 @@ class _Nil(Term):
     def like_chart(self):
         return iter([])
 
-    def __iter__(self):
-        return iter([])
+#    def __iter__(self):
+#        return iter([])
 
 
 Nil = _Nil()
diff --git a/test/repl/aggregators.dynadoc b/test/repl/aggregators.dynadoc
new file mode 100644 (file)
index 0000000..312922c
--- /dev/null
@@ -0,0 +1,94 @@
+> a majority= 1.
+| a majority= 1.
+| a majority= 1.
+| a majority= 2.
+| a majority= 2.
+
+Changes
+=======
+a = 1.
+
+%> rules
+%Rules
+%=====
+%  0: a majority= 1.
+%  1: a majority= 1.
+%  2: a majority= 1.
+%  3: a majority= 2.
+%  4: a majority= 2.
+
+
+% ties are broken arbitrarily
+> retract_rule 0
+> retract_rule 1
+
+Changes
+=======
+a = 2.
+
+% retract remaining rules to make sure the aggregator goes null
+> retract_rule 2
+> retract_rule 3
+> retract_rule 4
+
+Changes
+=======
+a = null.
+
+
+> a mean= 1.
+| a mean= 2.
+| a mean= 3.
+
+Changes
+=======
+a = 2.0.
+
+%> rules
+%
+%Rules
+%=====
+%  5: a mean= 1.
+%  6: a mean= 2.
+%  7: a mean= 3.
+
+> retract_rule 5
+
+Changes
+=======
+a = 2.5.
+
+> retract_rule 6
+
+Changes
+=======
+a = 3.0.
+
+> retract_rule 7
+
+Changes
+=======
+a = null.
+
+
+
+% A few simple tests for `*=`
+
+> a *= 3.
+| a *= 3.
+
+Changes
+=======
+a = 9.
+
+> retract_rule 8
+
+Changes
+=======
+a = 3.
+
+> retract_rule 9
+
+Changes
+=======
+a = null.
index 4ad4c4393af849729d09161a35e131ec81da2523..105cea1ef274492330f4eb713f949f54b043d0fb 100644 (file)
@@ -36,6 +36,18 @@ e = $error.
 
 >>> 1 new errors. Type `sol` for details.
 
+> sol
+
+Solution
+========
+e = $error.
+
+Errors
+======
+Error(s) aggregating e/0:
+  TypeError:
+    `e`: false is not true.
+
 
 > e :- true.
 
@@ -135,4 +147,35 @@ c = true.
 f/2
 ===
 f(1,2).
-f(2,2).
\ No newline at end of file
+f(2,2).
+
+
+% type checking for `|=`
+
+> foo |= 10.
+
+Changes
+=======
+foo = $error.
+>>> 1 new errors. Type `sol` for details.
+
+
+> goo &= true.
+
+Changes
+=======
+goo = true.
+
+> goo &= false.
+
+Changes
+=======
+goo = false.
+
+
+> goo &= 10.
+
+Changes
+=======
+goo = $error.
+>>> 1 new errors. Type `sol` for details.
index fa91a0201cca7becc8a917bacfd8243bb2db22b8..a742f34e26a8d49b2964f986f5273f1358ffaf36 100644 (file)
@@ -150,3 +150,21 @@ Changes
 =======
 thingsbag = [true, 1, 1, 2, "three"].
 thingset = [true, 1, 2, "three"].
+
+
+% comparison operator
+> foobar([]).
+| foobar([1,2]).
+| foobar([1,3]).
+| foobar("a").
+| foobar(&a, &b).
+| foobar(&a, &c).
+
+Changes
+=======
+foobar("a") = true.
+foobar([1, 2]) = true.
+foobar([1, 3]) = true.
+foobar([]) = true.
+foobar(a,b) = true.
+foobar(a,c) = true.
diff --git a/test/repl/repl-misc.dynadoc b/test/repl/repl-misc.dynadoc
new file mode 100644 (file)
index 0000000..82af397
--- /dev/null
@@ -0,0 +1,121 @@
+> rules
+
+No rules found.
+
+> a += 1.
+
+Changes
+=======
+a = 1.
+
+> rules
+
+Rules
+=====
+  0: a += 1.
+
+> a += 1
+
+ERROR: Line doesn't end with period.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Retract rule
+
+> retract_rule asdf
+
+Please specify an integer. Type `help retract_rule` to read more.
+
+> retract_rule 1000
+
+Rule 1000 not found.
+List available by typing `rules`
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Query
+
+> query
+
+No query specified. Type `help query` for usage.
+
+> query a.
+
+Queries don't end with a dot.
+
+> query a
+
+a = 1.
+
+%%% TODO: a query with an error > query a/0
+
+> query xxxx
+
+No results.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% vquery
+
+> vquery
+
+No query specified. Type `help query` for usage.
+
+> vquery a.
+
+Queries don't end with a dot.
+
+> vquery a
+
+1 where {}
+
+> vquery xxxx
+
+No results.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% trace
+
+> trace
+
+No query specified. Type `help trace` for usage.
+
+> trace a.
+
+Queries don't end with a dot.
+
+> trace xxxx
+
+no items matching `xxxx`.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Help
+
+> help query
+
+      Query solution.
+
+        Consider the following example;
+          > f(1) := 1.
+          > f(2) := 4.
+
+        There a few versions of query:
+
+         - `vquery` shows variable bindings
+            > vquery f(X)
+            1 where {X=1}
+            4 where {X=1}
+
+         - `query` shows variable bindings applied to query
+            > query f(X)
+            f(1) = 1.
+            f(2) = 4.
+
+         - `trace` is an introspection tool for visualizing the derivation of an
+           item and its value. Type `help trace` for more information.
+
+> help vquery
+
+See query.