Exemple #1
0
def test_output_optimization(undo, do, expected_instructions):
    output = CaptureOutput()
    formatter = formatting.Formatter()
    formatter.set_output(output)
    formatter.format([], undo, None)
    formatter.format(undo, do, None)
    assert output.instructions == expected_instructions
Exemple #2
0
    def test_output_optimisation(self):
        for undo, do, expected_instructions in (
            # No change.
            ([
                translation(english='noop'),
            ], [
                translation(english='noop'),

            ], [('s', ' noop')]),
            # Append only.
            ([
                translation(english='test'),
            ], [
                translation(english='testing'),

            ], [('s', ' test'), ('s', 'ing')]),
            # Chained meta-commands.
            ([
                translation(english='{#a}'),
            ], [
                translation(english='{#a}{#b}'),

            ], [('c', 'a'), ('c', 'b')]),
        ):
            output = CaptureOutput()
            formatter = formatting.Formatter()
            formatter.set_output(output)
            formatter.format([], undo, None)
            formatter.format(undo, do, None)
            self.assertEqual(output.instructions, expected_instructions)
Exemple #3
0
    def test_replace(self):
        for translations, expected_instructions in (
            # Check that 'replace' does not unconditionally erase
            # the previous character if it does not match.
            ([
                translation(english='{MODE:SET_SPACE:}'),
                translation(english='foobar'),
                translation(english='{^}{#Return}{^}{-|}'),

            ], [('s', 'foobar'), ('c', 'Return')]),
            # Check 'replace' correctly takes into account
            # the previous translation.
            ([
                translation(english='test '),
                translation(english='{^,}'),

            ], [('s', 'test '), ('b', 1), ('s', ', ')]),
            # While the previous translation must be taken into account,
            # any meta-command must not be fired again.
            ([
                translation(english='{#Return}'),
                translation(english='test'),

            ], [('c', 'Return'), ('s', 'test ')]),
        ):
            output = CaptureOutput()
            formatter = formatting.Formatter()
            formatter.set_output(output)
            formatter.set_space_placement('After Output')
            prev = None
            for t in translations:
                formatter.format([], [t], prev)
                prev = t
            self.assertEqual(output.instructions, expected_instructions)
    def test_starting_stroke(self):
        # Args: (Capitalized, Attached, Undo, Current, Prev Formatter)
        cases = (
            ((True, True, [], [translation(rtfcre=('S'), english='hello')],
              None), ([action(text='Hello',
                              word='Hello')], ), [('s', 'Hello')]),
            ((False, False, [], [translation(rtfcre=('S'), english='hello')],
              None), ([action(text=' hello',
                              word='hello')], ), [('s', ' hello')]),
            ((True, False, [], [translation(rtfcre=('S'), english='hello')],
              None), ([action(text=' Hello',
                              word='Hello')], ), [('s', ' Hello')]),
            ((False, True, [], [translation(rtfcre=('S'), english='hello')],
              None), ([action(text='hello',
                              word='hello')], ), [('s', 'hello')]),
        )

        for args, formats, outputs in cases:
            output = CaptureOutput()
            formatter = formatting.Formatter()
            formatter.set_output(output)
            formatter.set_space_placement('Before Output')

            capitalized, attached, undo, do, prev = args
            formatter.start_capitalized = capitalized
            formatter.start_attached = attached
            formatter.format(undo, do, prev)
            for i, t in enumerate(do):
                self.assertEqual(t.formatting, formats[i])
            self.assertEqual(output.instructions, outputs)
Exemple #5
0
def test_replace(translations, expected_instructions):
    output = CaptureOutput()
    formatter = formatting.Formatter()
    formatter.set_output(output)
    formatter.set_space_placement('After Output')
    prev = []
    for t in translations:
        formatter.format([], [t], prev)
        prev.append(t)
    assert output.instructions == expected_instructions
Exemple #6
0
 def test_get_last_action(self):
     formatter = formatting.Formatter()
     self.assertEqual(formatter._get_last_action(None), action())
     self.assertEqual(formatter._get_last_action([]), action())
     actions = [action(text='hello'), action(text='world')]
     self.assertEqual(formatter._get_last_action(actions), actions[-1])
     formatter.start_attached = True
     formatter.start_capitalized = True
     self.assertEqual(formatter._get_last_action(None), action(capitalize=True,
                                                               attach=True))
Exemple #7
0
def test_get_last_action():
    formatter = formatting.Formatter()
    assert formatter._get_last_action(None) == action()
    assert formatter._get_last_action([]) == action()
    actions = [action(text='hello'), action(text='world')]
    assert formatter._get_last_action(actions) == actions[-1]
    formatter.start_attached = True
    formatter.start_capitalized = True
    assert formatter._get_last_action(None) == action(capitalize=True,
                                                      attach=True)
Exemple #8
0
def test_starting_stroke(capitalized, attached, undo, do, prev,
                         expected_formats, expected_outputs):
    output = CaptureOutput()
    formatter = formatting.Formatter()
    formatter.set_output(output)
    formatter.start_capitalized = capitalized
    formatter.start_attached = attached
    formatter.format(undo, do, prev)
    for i, t in enumerate(do):
        assert t.formatting == expected_formats[i]
    assert output.instructions == expected_outputs
Exemple #9
0
def test_formatter(undo, do, prev, expected_formats, expected_outputs):
    output = CaptureOutput()
    # Add some initial blank text so
    # undoing with no previous state
    # does not assert.
    output.text = ' ' * 128
    formatter = formatting.Formatter()
    formatter.set_output(output)
    formatter.format(undo, do, prev)
    for i, t in enumerate(do):
        assert t.formatting == expected_formats[i]
    assert output.instructions == expected_outputs
Exemple #10
0
 def test_undo_replace(self):
         # Undoing a replace....
         output = CaptureOutput()
         formatter = formatting.Formatter()
         formatter.set_output(output)
         formatter.set_space_placement('After Output')
         prev = translation(english='test')
         formatter.format([], [prev], None)
         undo = translation(english='{^,}')
         formatter.format([], [undo], prev)
         # Undo.
         formatter.format([undo], [], prev)
         self.assertEqual(output.instructions, [
             ('s', 'test '), ('b', 1), ('s', ', '), ('b', 2), ('s', ' '),
         ])
Exemple #11
0
    def __init__(self, thread_hook=same_thread_hook):
        """Creates and configures a single steno pipeline."""
        self.subscribers = []
        self.stroke_listeners = []
        self.is_running = False
        self.machine = None
        self.thread_hook = thread_hook

        self.translator = translation.Translator()
        self.formatter = formatting.Formatter()
        self.translator.add_listener(log.translation)
        self.translator.add_listener(self.formatter.format)
        # This seems like a reasonable number. If this becomes a problem it can
        # be parameterized.
        self.translator.set_min_undo_length(10)

        self.full_output = SimpleNamespace()
        self.command_only_output = SimpleNamespace()
        self.running_state = self.translator.get_state()
        self.set_is_running(False)
Exemple #12
0
    def __init__(self, thread_hook=same_thread_hook):
        """Creates and configures a single steno pipeline."""
        self.subscribers = []
        self.stroke_listeners = []
        self.is_running = False
        self.machine = None
        self.machine_class = None
        self.machine_options = None
        self.machine_mappings = None
        self.thread_hook = thread_hook

        self.translator = translation.Translator()
        self.formatter = formatting.Formatter()
        self.translator.add_listener(log.translation)
        self.translator.add_listener(self.formatter.format)

        self.full_output = SimpleNamespace()
        self.command_only_output = SimpleNamespace()
        self.running_state = self.translator.get_state()
        self.set_is_running(False)
Exemple #13
0
    def __init__(self, engine_command_callback):
        """Creates and configures a single steno pipeline."""
        self.subscribers = []
        self.is_running = False
        self.machine = None
        self.machine_init = {}
        self.translator = None
        self.formatter = None
        self.output = None

        # Check and use configuration
        self.config = conf.get_config()
        config_errors, config_values = check_steno_config(self.config)
        for error in config_errors:
            # This will raise one of the configuration errors.
            raise error

        machine_type, user_dictionary = config_values

        # Set the machine module and any initialization variables.
        self.machine_module = conf.import_named_module(
            machine_type, SUPPORTED_MACHINES_DICT)
        if self.machine_module is None:
            raise InvalidConfigurationError(
                'Invalid configuration value for %s: %s' %
                (conf.MACHINE_TYPE_OPTION, machine_type))

        if issubclass(self.machine_module.Stenotype,
                      plover.machine.base.SerialStenotypeBase):
            serial_params = conf.get_serial_params(machine_type, self.config)
            self.machine_init.update(serial_params.__dict__)

        # Initialize the logger.
        log_file = join(
            conf.CONFIG_DIR,
            self.config.get(conf.LOGGING_CONFIG_SECTION, conf.LOG_FILE_OPTION))
        self.logger = logging.getLogger(conf.LOGGER_NAME)
        self.logger.setLevel(logging.DEBUG)
        handler = RotatingFileHandler(
            log_file,
            maxBytes=conf.LOG_MAX_BYTES,
            backupCount=conf.LOG_COUNT,
        )
        handler.setFormatter(logging.Formatter(conf.LOG_FORMAT))
        self.logger.addHandler(handler)

        # Construct the stenography capture-translate-format-display pipeline.
        self.machine = self.machine_module.Stenotype(**self.machine_init)
        self.translator = translation.Translator()
        self.translator.set_dictionary(user_dictionary)
        self.formatter = formatting.Formatter()

        # Add hooks for logging. Do this first so logs appear in order.
        if self.config.getboolean(conf.LOGGING_CONFIG_SECTION,
                                  conf.ENABLE_STROKE_LOGGING_OPTION):
            self.machine.add_callback(self._log_stroke)
        if self.config.getboolean(conf.LOGGING_CONFIG_SECTION,
                                  conf.ENABLE_TRANSLATION_LOGGING_OPTION):
            self.translator.add_listener(self._log_translation)

        self.machine.add_callback(
            lambda x: self.translator.translate(steno.Stroke(x)))
        self.translator.add_listener(self.formatter.format)
        # This seems like a reasonable number. If this becomes a problem it can
        # be parameterized.
        self.translator.set_min_undo_length(10)
        keyboard_control = keyboardcontrol.KeyboardEmulation()
        bag = SimpleNamespace()
        bag.send_backspaces = keyboard_control.send_backspaces
        bag.send_string = keyboard_control.send_string
        bag.send_key_combination = keyboard_control.send_key_combination
        bag.send_engine_command = engine_command_callback
        self.full_output = bag
        bag = SimpleNamespace()
        bag.send_engine_command = engine_command_callback
        self.command_only_output = bag
        self.running_state = self.translator.get_state()

        auto_start = self.config.getboolean(conf.MACHINE_CONFIG_SECTION,
                                            conf.MACHINE_AUTO_START_OPTION)
        self.set_is_running(auto_start)

        # Start the machine monitoring for steno strokes.
        self.machine.start_capture()
Exemple #14
0
    def test_formatter(self):
        cases = (

        (
         ([translation(formatting=[action(text='hello')])], [], None),
         (),
         [('b', 5)]
        ),
        
        (
         ([], 
          [translation(rtfcre=('S'), english='hello')], 
          translation(rtfcre=('T'), english='a', formatting=[action(text='f')])
         ),
         ([action(text=' hello', word='hello')],),
         [('s', ' hello')]
        ),
        
        (
         ([], [translation(rtfcre=('S'), english='hello')], None),
         ([action(text=' hello', word='hello')],),
         [('s', ' hello')]
        ),
        
        (
         ([], [translation(rtfcre=('ST-T',))], None),
         ([action(text=' ST-T', word='ST-T')],),
         [('s', ' ST-T')]
        ),
        
        (
         ([], 
          [translation(rtfcre=('ST-T',))], 
          translation(formatting=[action(text='hi')])),
         ([action(text=' ST-T', word='ST-T')],),
         [('s', ' ST-T')]
        ),
        
        (
         ([translation(formatting=[action(text=' test')])],
          [translation(english='rest')],
          translation(formatting=[action(capitalize=True)])),
         ([action(text=' Rest', word='Rest')],),
         [('b', 4), ('s', 'Rest')]
        ),
        
        (
         ([translation(formatting=[action(text='dare'), 
                                   action(text='ing', replace='e')])],
         [translation(english='rest')],
         translation(formatting=[action(capitalize=True)])),
         ([action(text=' Rest', word='Rest')],),
         [('b', 6), ('s', ' Rest')]
        ),
        
        (
         ([translation(formatting=[action(text=' drive')])],
         [translation(english='driving')],
         None),
         ([action(text=' driving', word='driving')],),
         [('b', 1), ('s', 'ing')]
        ),
        
        (
         ([translation(formatting=[action(text=' drive')])],
         [translation(english='{#c}driving')],
         None),
         ([action(combo='c'), action(text=' driving', word='driving')],),
         [('b', 6), ('c', 'c'), ('s', ' driving')]
        ),
        
        (
         ([translation(formatting=[action(text=' drive')])],
         [translation(english='{PLOVER:c}driving')],
         None),
         ([action(command='c'), action(text=' driving', word='driving')],),
         [('b', 6), ('e', 'c'), ('s', ' driving')]
        ),
        
        (
         ([],
          [translation(rtfcre=('1',))],
          None),
         ([action(text=' 1', word='1', glue=True)],),
         [('s', ' 1')]
        ),
        
        (
         ([],
          [translation(rtfcre=('1',))],
          translation(formatting=[action(text='hi', word='hi')])),
         ([action(text=' 1', word='1', glue=True)],),
         [('s', ' 1')]
        ),

        (
         ([],
          [translation(rtfcre=('1',))],
          translation(formatting=[action(text='hi', word='hi', glue=True)])),
         ([action(text='1', word='hi1', glue=True)],),
         [('s', '1')]
        ),

        (
         ([],
          [translation(rtfcre=('1-9',))],
          translation(formatting=[action(text='hi', word='hi', glue=True)])),
         ([action(text='19', word='hi19', glue=True)],),
         [('s', '19')]
        ),

        (
         ([],
          [translation(rtfcre=('ST-PL',))],
          translation(formatting=[action(text='hi', word='hi')])),
         ([action(text=' ST-PL', word='ST-PL')],),
         [('s', ' ST-PL')]
        ),

        (
         ([],
          [translation(rtfcre=('ST-PL',))],
          None),
         ([action(text=' ST-PL', word='ST-PL')],),
         [('s', ' ST-PL')]
        ),

        )

        for args, formats, outputs in cases:
            output = CaptureOutput()
            formatter = formatting.Formatter()
            formatter.set_output(output)
            formatter.set_space_placement('Before Output')
            undo, do, prev = args
            formatter.format(undo, do, prev)
            for i in xrange(len(do)):
                self.assertEqual(do[i].formatting, formats[i])
            self.assertEqual(output.instructions, outputs)
Exemple #15
0
 def setup_method(self):
     self.formatter = formatting.Formatter()
     self.translations = []
     self.retro_formatter = formatting.RetroFormatter(self.translations)
Exemple #16
0
    def __init__(self):
        """Creates and configures a single steno pipeline."""
        self.subscribers = []
        self.is_running = False
        self.machine = None
        self.machine_init = {}
        self.translator = None
        self.formatter = None
        self.output = None
        self.config = conf.get_config()

        # Set the machine module and any initialization variables.
        machine_type = self.config.get(conf.MACHINE_CONFIG_SECTION,
                                       conf.MACHINE_TYPE_OPTION)
        self.machine_module = conf.import_named_module(machine_type,
                                                       machine.supported)
        if self.machine_module is None:
            raise ValueError('Invalid configuration value for %s: %s' %
                             (conf.MACHINE_TYPE_OPTION, machine_type))
        if issubclass(self.machine_module.Stenotype,
                      plover.machine.base.SerialStenotypeBase):
            serial_params = conf.get_serial_params(machine_type, self.config)
            self.machine_init.update(serial_params.__dict__)

        # Set the steno dictionary format module.
        dictionary_format = self.config.get(conf.DICTIONARY_CONFIG_SECTION,
                                            conf.DICTIONARY_FORMAT_OPTION)
        self.dictionary_module = conf.import_named_module(
            dictionary_format, dictionary.supported)
        if self.dictionary_module is None:
            raise ValueError(
                'Invalid configuration value for %s: %s' %
                (conf.DICTIONARY_FORMAT_OPTION, dictionary_format))

        # Load the dictionary. The dictionary path can be either
        # absolute or relative to the configuration directory.
        dictionary_filename = self.config.get(conf.DICTIONARY_CONFIG_SECTION,
                                              conf.DICTIONARY_FILE_OPTION)
        dictionary_path = os.path.join(conf.CONFIG_DIR, dictionary_filename)
        if not os.path.isfile(dictionary_path):
            raise ValueError('Invalid configuration value for %s: %s' %
                             (conf.DICTIONARY_FILE_OPTION, dictionary_path))
        dictionary_extension = os.path.splitext(dictionary_path)[1]
        if dictionary_extension == conf.JSON_EXTENSION:
            try:
                with open(dictionary_path, 'r') as f:
                    self.dictionary = json.load(f)
            except UnicodeDecodeError:
                with open(dictionary_path, 'r') as f:
                    self.dictionary = json.load(f, conf.ALTERNATIVE_ENCODING)
        else:
            raise ValueError(
                'The value of %s must end with %s.' %
                (conf.DICTIONARY_FILE_OPTION, conf.JSON_EXTENSION))

        # Initialize the logger.
        log_file = os.path.join(
            conf.CONFIG_DIR,
            self.config.get(conf.LOGGING_CONFIG_SECTION, conf.LOG_FILE_OPTION))
        self.logger = logging.getLogger(conf.LOGGER_NAME)
        self.logger.setLevel(logging.DEBUG)
        handler = logging.handlers.RotatingFileHandler(
            log_file, maxBytes=conf.LOG_MAX_BYTES, backupCount=conf.LOG_COUNT)
        handler.setFormatter(logging.Formatter(conf.LOG_FORMAT))
        self.logger.addHandler(handler)

        # Construct the stenography capture-translate-format-display pipeline.
        self.machine = self.machine_module.Stenotype(**self.machine_init)
        self.output = keyboardcontrol.KeyboardEmulation()
        self.translator = steno.Translator(self.machine, self.dictionary,
                                           self.dictionary_module)
        self.formatter = formatting.Formatter(self.translator)
        auto_start = self.config.getboolean(conf.MACHINE_CONFIG_SECTION,
                                            conf.MACHINE_AUTO_START_OPTION)
        self.set_is_running(auto_start)

        # Add hooks for logging.
        if self.config.getboolean(conf.LOGGING_CONFIG_SECTION,
                                  conf.ENABLE_STROKE_LOGGING_OPTION):
            self.machine.add_callback(self._log_stroke)
        if self.config.getboolean(conf.LOGGING_CONFIG_SECTION,
                                  conf.ENABLE_TRANSLATION_LOGGING_OPTION):
            self.translator.add_callback(self._log_translation)

        # Start the machine monitoring for steno strokes.
        self.machine.start_capture()