Commits

Andreas Stührk committed 0477d51

Add tests for issues #108 and #133.

  • Participants
  • Parent commits 523f633

Comments (0)

Files changed (4)

bpython/inspection.py

     kwparsed = parsekeywordpairs(signature)
 
     for i, (key, value) in enumerate(zip(keys, values)):
-        if len(str(value)) != len(kwparsed[key]):
+        if len(repr(value)) != len(kwparsed[key]):
             values[i] = kwparsed[key]
 
     argspec[3] = values

bpython/test/test.config

+[general]
+hist_file = /dev/null
+paste_time = 0

bpython/test/test_crashers.py

+import fcntl
+import os
+import pty
+import struct
+import sys
+import termios
+import textwrap
+import unittest
+
+try:
+    from twisted.internet import reactor
+    from twisted.internet.defer import Deferred
+    from twisted.internet.protocol import ProcessProtocol
+    from twisted.trial.unittest import TestCase as TrialTestCase
+except ImportError:
+    reactor = None
+
+TEST_CONFIG = os.path.join(os.path.dirname(__file__), "test.config")
+
+def set_win_size(fd, rows, columns):
+    s = struct.pack('HHHH', rows, columns, 0, 0)
+    fcntl.ioctl(fd, termios.TIOCSWINSZ, s)
+
+class CrashersTest(object):
+    backend = "cli"
+
+    def run_bpython(self, input):
+        """
+        Run bpython (with `backend` as backend) in a subprocess and
+        enter the given input. Uses a test config that disables the
+        paste detection.
+
+        Retuns bpython's output.
+        """
+        result = Deferred()
+
+        class Protocol(ProcessProtocol):
+            STATES = (SEND_INPUT, COLLECT) = xrange(2)
+
+            def __init__(self):
+                self.data = ""
+                self.delayed_call = None
+                self.states = iter(self.STATES)
+                self.state = self.states.next()
+
+            def outReceived(self, data):
+                self.data += data
+                if self.delayed_call is not None:
+                    self.delayed_call.cancel()
+                self.delayed_call = reactor.callLater(0.5, self.next)
+
+            def next(self):
+                self.delayed_call = None
+                if self.state == self.SEND_INPUT:
+                    index = self.data.find(">>> ")
+                    if index >= 0:
+                        self.data = self.data[index + 4:]
+                        self.transport.write(input)
+                        self.state = self.states.next()
+                else:
+                    self.transport.closeStdin()
+                    if self.transport.pid is not None:
+                        self.delayed_call = None
+                        self.transport.signalProcess("TERM")
+
+            def processExited(self, reason):
+                if self.delayed_call is not None:
+                    self.delayed_call.cancel()
+                result.callback(self.data)
+
+        (master, slave) = pty.openpty()
+        set_win_size(slave, 25, 80)
+        reactor.spawnProcess(Protocol(), sys.executable,
+            (sys.executable, "-m", "bpython." + self.backend,
+             "-c",  TEST_CONFIG),
+            env=dict(TERM="vt100"),
+            usePTY=(master, slave, os.ttyname(slave)))
+        return result
+
+    def test_issue108(self):
+        input = textwrap.dedent(
+            """\
+            def spam():
+            u"y\\xe4y"
+            \b
+            spam(""")
+        deferred = self.run_bpython(input)
+        return deferred.addCallback(self.check_no_traceback)
+
+    def test_issue133(self):
+        input = textwrap.dedent(
+            """\
+            def spam(a, (b, c)):
+            pass
+            \b
+            spam(1""")
+        return self.run_bpython(input).addCallback(self.check_no_traceback)
+
+    def check_no_traceback(self, data):
+        tb = data[data.find("Traceback"):]
+        self.assertTrue("Traceback" not in data, tb)
+
+if reactor is not None:
+    class CursesCrashersTest(TrialTestCase, CrashersTest):
+        backend = "cli"
+
+    class UrwidCrashersTest(TrialTestCase, CrashersTest):
+        backend = "urwid"
+
+if __name__ == "__main__":
+    unittest.main()

bpython/test/test_inspection.py

+import inspect
 import unittest
 
 from bpython import inspection
         defaults = argspec[1][3]
         self.assertEqual(str(defaults[0]), default_arg_repr)
 
+    def test_fixlongargs(self):
+        def spam(a, b=1, c="y\xc3\xa4y"):
+            pass
+
+        argspec = list(inspect.getargspec(spam))
+        print argspec[3],
+        inspection.fixlongargs(spam, argspec)
+        print argspec[3], [type(a) for a in argspec[3]]
+        self.assertFalse(argspec)
+
 if __name__ == '__main__':
     unittest.main()