def test_load_dict(self): """Test the load_dict function. This test just tests load_dict so it mocks out the converters and just verifies that they are called. """ expected_styles = { 0: 'Normal', 1: 'Question', 2: 'Answer', 3: 'Colloquy', 4: 'Continuation Q', 5: 'Continuation A', 6: 'Continuation Col', 7: 'Paren', 8: 'Centered', } header = '\r\n'.join( [r'{\rtf1\ansi\cxdict{\*\cxrev100}{\*\cxsystem Fake Software}'] + [r'{\s%d %s;}' % (k, v) for k, v in expected_styles.items()] + ['}']) footer = '\r\n}' @contextmanager def make_dict(contents): tf = tempfile.NamedTemporaryFile(delete=False) writer = codecs.getwriter('cp1252')(tf) try: writer.write(header) writer.write(contents) writer.write(footer) tf.close() yield tf.name finally: os.unlink(tf.name) def assertEqual(a, b): self.assertEqual(a._dict, b) this = self class Converter(object): def __init__(self, styles): this.assertEqual(styles, expected_styles) def __call__(self, s): if s == 'return_none': return None return 'converted(%s)' % s convert = Converter(expected_styles) normalize = lambda x: 'normalized(%s)' % x cases = ( # Empty dictionary. ('', {}), # Only one translation. ('{\\*\\cxs SP}translation', { 'SP': 'translation' }), # Multiple translations no newlines. ('{\\*\\cxs SP}translation{\\*\\cxs S}translation2', { 'SP': 'translation', 'S': 'translation2' }), # Multiple translations on separate lines. ('{\\*\\cxs SP}translation\r\n{\\*\\cxs S}translation2', { 'SP': 'translation', 'S': 'translation2' }), ('{\\*\\cxs SP}translation\n{\\*\\cxs S}translation2', { 'SP': 'translation', 'S': 'translation2' }), # Escaped \r and \n handled ('{\\*\\cxs SP}trans\\\r\\\n', { 'SP': 'trans\\\r\\\n' }), # Escaped \r\n handled in mid translation ('{\\*\\cxs SP}trans\\\r\\\nlation', { 'SP': 'trans\\\r\\\nlation' }), # Whitespace is preserved in various situations. ('{\\*\\cxs S}t ', { 'S': 't ' }), ('{\\*\\cxs S}t {\\*\\cxs T}t ', { 'S': 't ', 'T': 't ' }), ('{\\*\\cxs S}t \r\n{\\*\\cxs T}t ', { 'S': 't ', 'T': 't ' }), ('{\\*\\cxs S}t \r\n{\\*\\cxs T} t \r\n', { 'S': 't ', 'T': ' t ' }), # Translations are ignored if converter returns None ('{\\*\\cxs S}return_none', {}), ('{\\*\\cxs T}t t t ', { 'T': 't t t ' }), # Conflicts result on only the last one kept. ('{\\*\\cxs T}t{\\*\\cxs T}g', { 'T': 'g' }), ('{\\*\\cxs T}t{\\*\\cxs T}return_none', { 'T': 't' }), ) patch_path = 'plover.dictionary.rtfcre_dict' with mock.patch.multiple(patch_path, normalize_steno=normalize, TranslationConverter=Converter): for contents, expected in cases: expected = dict( (normalize(k), convert(v)) for k, v in expected.items()) with make_dict(contents) as filename: assertEqual(load_dictionary(filename), expected)
def test_load_dict(self): """Test the load_dict function. This test just tests load_dict so it mocks out the converters and just verifies that they are called. """ expected_styles = { 0: 'Normal', 1: 'Question', 2: 'Answer', 3: 'Colloquy', 4: 'Continuation Q', 5: 'Continuation A', 6: 'Continuation Col', 7: 'Paren', 8: 'Centered', } header = '\r\n'.join( [r'{\rtf1\ansi\cxdict{\*\cxrev100}{\*\cxsystem Fake Software}'] + [r'{\s%d %s;}' % (k, v) for k, v in expected_styles.items()] + ['}']) footer = '\r\n}' @contextmanager def make_dict(contents): tf = tempfile.NamedTemporaryFile(delete=False) try: tf.write(header) tf.write(contents) tf.write(footer) tf.close() yield tf.name finally: os.unlink(tf.name) def assertEqual(a, b): self.assertEqual(a._dict, b) this = self class Converter(object): def __init__(self, styles): this.assertEqual(styles, expected_styles) def __call__(self, s): if s == 'return_none': return None return 'converted(%s)' % s convert = Converter(expected_styles) normalize = lambda x: 'normalized(%s)' % x cases = ( # Empty dictionary. ('', {}), # Only one translation. ('{\\*\\cxs SP}translation', {'SP': 'translation'}), # Multiple translations no newlines. ('{\\*\\cxs SP}translation{\\*\\cxs S}translation2', {'SP': 'translation', 'S': 'translation2'}), # Multiple translations on separate lines. ('{\\*\\cxs SP}translation\r\n{\\*\\cxs S}translation2', {'SP': 'translation', 'S': 'translation2'}), ('{\\*\\cxs SP}translation\n{\\*\\cxs S}translation2', {'SP': 'translation', 'S': 'translation2'}), # Escaped \r and \n handled ('{\\*\\cxs SP}trans\\\r\\\n', {'SP': 'trans\\\r\\\n'}), # Escaped \r\n handled in mid translation ('{\\*\\cxs SP}trans\\\r\\\nlation', {'SP': 'trans\\\r\\\nlation'}), # Whitespace is preserved in various situations. ('{\\*\\cxs S}t ', {'S': 't '}), ('{\\*\\cxs S}t {\\*\\cxs T}t ', {'S': 't ', 'T': 't '}), ('{\\*\\cxs S}t \r\n{\\*\\cxs T}t ', {'S': 't ', 'T': 't '}), ('{\\*\\cxs S}t \r\n{\\*\\cxs T} t \r\n', {'S': 't ', 'T': ' t '}), # Translations are ignored if converter returns None ('{\\*\\cxs S}return_none', {}), ('{\\*\\cxs T}t t t ', {'T': 't t t '}), # Conflicts result on only the last one kept. ('{\\*\\cxs T}t{\\*\\cxs T}g', {'T': 'g'}), ('{\\*\\cxs T}t{\\*\\cxs T}return_none', {'T': 't'}), ) patch_path = 'plover.dictionary.rtfcre_dict' with mock.patch.multiple(patch_path, normalize_steno=normalize, TranslationConverter=Converter): for contents, expected in cases: expected = dict((normalize(k), convert(v)) for k, v in expected.iteritems()) with make_dict(contents) as filename: assertEqual(load_dictionary(filename), expected)