def testEmptyStack(self): "Calling on an empty stack must return None, None" c = Calculator() error = r"^Cannot run 'cmd' \(stack has only 0 items\)$" self.assertRaisesRegex(StackError, error, c.findCallableAndArgs, 'cmd', Modifiers(), None)
def testStackLengthOne(self): "Calling on a stack with only one item must return None, None" c = Calculator() c.execute('4') error = r"^Cannot run 'cmd' \(stack has only 1 item\)$" self.assertRaisesRegex(StackError, error, c.findStringAndArgs, 'cmd', Modifiers(), None)
def testStackLengthOne(self): "Calling on a stack with only one item must raise a StackError." errfp = StringIO() c = Calculator(errfp=errfp) c.execute('4') error = r"^Cannot run 'cmd' \(stack has only 1 item\)$" self.assertRaisesRegex(StackError, error, c.findCallableAndArgs, 'cmd', Modifiers(), None)
def testStackLengthTwoWithCount(self): """Calling on a stack with two items and a count must return correctly.""" c = Calculator() c.execute("'string'") c.execute('4') string, args = c.findStringAndArgs('cmd', Modifiers(), 1) self.assertEqual('string', string) self.assertEqual([4], args)
def testStackLengthThree(self): "Calling on a stack with three items (count=2) must return correctly" c = Calculator() c.execute('log10 :!') c.execute('4') c.execute('5') func, args = c.findCallableAndArgs('cmd', Modifiers(), 2) self.assertIs(math.log10, func) self.assertEqual([4, 5], args)
def testStackLengthTwoWithCount(self): """Calling on a stack with two items and a count must return correctly.""" c = Calculator() c.execute('log10 :!') c.execute('4') func, args = c.findCallableAndArgs('cmd', Modifiers(), 1) self.assertIs(math.log10, func) self.assertEqual([4], args)
def testStackLengthThree(self): "Calling on a stack with three items (count=2) must return correctly" c = Calculator() c.execute("'string'") c.execute('4') c.execute('5') string, args = c.findStringAndArgs('cmd', Modifiers(), 2) self.assertEqual('string', string) self.assertEqual([4, 5], args)
def testStackLengthTwoNoCount(self): """Calling on a stack with two items and no count must return correctly. The number of stack items is obtained from the function signature""" c = Calculator() c.execute("'string'") c.execute('4') string, args = c.findStringAndArgs('cmd', Modifiers(), None) self.assertEqual('string', string) self.assertEqual([4], args)
def testStackLengthTwoNoCount(self): """Calling on a stack with two items and no count must return correctly. The number of stack items is obtained from the function signature""" c = Calculator() c.execute('log10 :!') c.execute('4') func, args = c.findCallableAndArgs('cmd', Modifiers(), None) self.assertIs(math.log10, func) self.assertEqual([4], args)
def testStackLengthThreeWithCountError(self): """Calling on a stack with three items and a count that points to a non-string must result in an error""" c = Calculator() c.execute("'string'") c.execute('4') c.execute('5') error = (r"^Cannot run 'cmd' with 1 argument. Stack item \(4\) is " r"not a string$") self.assertRaisesRegex(StackError, error, c.findStringAndArgs, 'cmd', Modifiers(), 1)
def findModifiers(line): """Find the modifiers (if any) in an input line. @param line: A C{str} input line. @return: A 3-C{tuple} with the C{int} offset of the modifier separator in C{line} or -1 if no modifier is found, a C{Modifiers} instance, and an C{int} count (or C{None} if no count is found). """ index = line.rfind(_MODIFIERS_SEPARATOR) if index == -1: return -1, Modifiers(), None line = line[index + 1:] # Look for a number and extract it if present. match = _NUMBER_RE.search(line) if match: count = int(match.group(1)) line = line[:match.start(1)] + line[match.end(1):] else: count = None # Examine all the other characters. # # We only consider this to be a valid set of modifiers if the letters # are all in MODIFIERS. Be slightly lenient and allow repeated letters. seen = set() for letter in line: if letter in MODIFIERS: seen.add(letter) elif not letter.isspace(): break else: return index, strToModifiers(''.join(seen)), count # Even though we found the modifier separator, there are unknown # characters that follow it, so we conclude that this is not actually # an attempt to give modifier. E.g., in {'a': 27, 'b': 77} there is # a colon but it's followed by a '}' so we reject. return -1, Modifiers(), None
def testStackLengthThreeWithCountError(self): """Calling on a stack with three items and a count that points to a non-callable must result in an error""" errfp = StringIO() c = Calculator(errfp=errfp) c.execute('log10 :!') c.execute('4') c.execute('5') error = (r"^Cannot run 'cmd' with 1 argument. Stack item \(4\) is " r"not callable$") self.assertRaisesRegex(StackError, error, c.findCallableAndArgs, 'cmd', Modifiers(), 1)
def testTwoCommandsSecondWithModifiersAfterSpace(self): "Test two commands on one line, the 2nd with modifiers after a space" self.assertEqual( (('hey', Modifiers(), None), ('you', strToModifiers('='), None)), tuple(findCommands('hey you :=')))
def testTwoCommandsFirstWithModifiers(self): "Test two commands on one line, the 1st with modifiers (and no space)" self.assertEqual( (('hey', strToModifiers('='), None), ('you', Modifiers(), None)), tuple(findCommands('hey:= you')))
def testTwoCommands(self): "Test two commands on one line" self.assertEqual( (('hey', Modifiers(), None), ('you', Modifiers(), None)), tuple(findCommands('hey you')))
def testCommandWithNoModifiers(self): "Test a command with no modifiers" self.assertEqual((('hey', Modifiers(), None),), tuple(findCommands('hey')))
def testCommentPrecededByWhitespace(self): "Test a comment preceeded by whitespace." self.assertEqual((('', Modifiers(), None),), tuple(findCommands(' # comment')))
def testCommandWithNoModifiersCaseUnchanged(self): "Test that command case is unmodified" self.assertEqual((('HeY', Modifiers(), None),), tuple(findCommands('HeY')))
def testDefaultsFalse(self): "Test all attributes default to False." modifiers = Modifiers() for name in MODIFIERS.values(): self.assertEqual(False, getattr(modifiers, name))
def testUnknownLetter(self): "Test a string with a non-modifier letter." # Before testing, make sure '?' is not actually a valid modifier. self.assertFalse('?' in MODIFIERS) self.assertEqual((-1, Modifiers(), None), findModifiers('4 :?'))
def testDictWithModifiers(self): "A dict with a count must be processed correctly." self.assertEqual((("{'a':6,'b':10,'c':15}", Modifiers(), 7),), tuple(findCommands("{'a':6,'b':10,'c':15}:7")))
def testStringWithNoModifierSeparator(self): "Test a string with no modifier separator." self.assertEqual((-1, Modifiers(), None), findModifiers('hello'))
def testCommandWithCount(self): "Test a command with a count" self.assertEqual((('hey', Modifiers(), 101),), tuple(findCommands('hey :101')))
def testSeparatorIsLastLetter(self): "Test a string that ends with the separator." self.assertEqual((0, Modifiers(), None), findModifiers(':'))
def testEmpty(self): "Test an empty string." self.assertEqual((-1, Modifiers(), None), findModifiers(''))
def testDict(self): "A dict must not be confused for a string with modifiers." self.assertEqual((-1, Modifiers(), None), findModifiers("{'a':6, 'b':10, 'c':15}"))
def testThreeCommandsSecondWithModifiers(self): "Test three commands on one line, the 2nd with modifiers" self.assertEqual( (('hey', Modifiers(), None), ('you', strToModifiers('='), None), ('there', Modifiers(), None)), tuple(findCommands('hey you:= there')))
def testComment(self): "Test a comment." self.assertEqual((('', Modifiers(), None),), tuple(findCommands('# comment')))
def testDict(self): "A dict must not be confused for a string with modifiers." self.assertEqual((("{'a':6,'b':10,'c':15}", Modifiers(), None),), tuple(findCommands("{'a':6,'b':10,'c':15}")))
def testCommandWithSurroundingSpaceAndNoModifiers(self): "Test a command with surrounding space and no modifiers" self.assertEqual((('hey', Modifiers(), None),), tuple(findCommands(' hey ')))