def _get_dictionary_save_name(self,
                               title,
                               default_name=None,
                               default_extensions=(),
                               initial_filename=None):
     if default_name is not None:
         # Default to a writable dictionary format.
         writable_extensions = set(
             _dictionary_formats(include_readonly=False))
         default_name += '.' + next(
             (e for e in default_extensions if e in writable_extensions),
             'json')
         default_name = os.path.join(self._file_dialogs_directory,
                                     default_name)
     else:
         default_name = self._file_dialogs_directory
     new_filename = QFileDialog.getSaveFileName(
         parent=self,
         caption=title,
         directory=default_name,
         filter=_dictionary_filters(include_readonly=False),
     )[0]
     if not new_filename:
         return None
     new_filename = normalize_path(new_filename)
     self._file_dialogs_directory = os.path.dirname(new_filename)
     if new_filename == initial_filename:
         return None
     return new_filename
Beispiel #2
0
 def test_dictionaries_option(self):
     section = config.SYSTEM_CONFIG_SECTION % config.DEFAULT_SYSTEM_NAME
     option = config.SYSTEM_DICTIONARIES_OPTION
     legacy_section = config.LEGACY_DICTIONARY_CONFIG_SECTION
     legacy_option = config.LEGACY_DICTIONARY_FILE_OPTION
     c = config.Config()
     config_dir = os.path.normcase(os.path.realpath(config.CONFIG_DIR))
     # Check the default value.
     self.assertEqual(c.get_dictionaries(),
                      [DictionaryConfig(path)
                       for path in system.DEFAULT_DICTIONARIES])
     # Load from a file encoded the ancient way...
     filename = normalize_path('/some_file')
     f = make_config('[%s]\n%s: %s' % (legacy_section, legacy_option, filename))
     c.load(f)
     # ..and make sure the right value is set.
     self.assertEqual(c.get_dictionaries(), [DictionaryConfig(filename)])
     # Load from a file encoded the old way...
     filenames = [os.path.join(ABS_PATH, f) for f in ('b', 'a', 'd', 'c')]
     dictionaries = [DictionaryConfig(path) for path in filenames]
     value = '\n'.join('%s%d: %s' % (legacy_option, d, v)
                           for d, v in enumerate(reversed(filenames), start=1))
     f = make_config('[%s]\n%s' % (legacy_section, value))
     c.load(f)
     # ...and make sure the right value is set.
     self.assertEqual(c.get_dictionaries(), dictionaries)
     # Check the config is saved back converted to the new way.
     f = make_config()
     c.save(f)
     new_config_contents = '[%s]\n%s = %s\n\n' % (
         section, option, json.dumps([
             {'path': path, 'enabled': True}
             for path in filenames
         ], sort_keys=True))
     self.assertEqual(f.getvalue().decode('utf-8'), new_config_contents)
     # Load from a file encoded the new way...
     f = make_config(new_config_contents)
     c.load(f)
     # ...and make sure the right value is set.
     self.assertEqual(c.get_dictionaries(), dictionaries)
     # Set a value...
     dictionaries.reverse()
     filenames.reverse()
     c.set_dictionaries(dictionaries)
     f = make_config()
     # ...save it...
     c.save(f)
     # ...and make sure it's right.
     new_config_contents = '[%s]\n%s = %s\n\n' % (
         section, option, json.dumps([
             {'path': path, 'enabled': True}
             for path in filenames
         ], sort_keys=True))
     self.assertEqual(f.getvalue().decode('utf-8'), new_config_contents)
     # The new way must take precedence over the old way.
     legacy_value = '\n'.join('%s%d = %s' % (legacy_option, d, v)
                           for d, v in enumerate(['/foo', '/bar'], start=1))
     f = make_config(new_config_contents + '\n[%s]\n%s\n' % ( legacy_section, legacy_value))
     c.load(f)
     self.assertEqual(c.get_dictionaries(), dictionaries)
Beispiel #3
0
 def _create_new_dictionary(self):
     new_filename = QFileDialog.getSaveFileName(
         self,
         _('New dictionary'),
         None,
         _dictionary_filters(include_readonly=False),
     )[0]
     if not new_filename:
         return
     new_filename = normalize_path(new_filename)
     try:
         d = create_dictionary(new_filename, threaded_save=False)
         d.save()
     except:
         log.error('creating dictionary %s failed',
                   new_filename,
                   exc_info=True)
         return
     dictionaries = self._config_dictionaries[:]
     for d in dictionaries:
         if d.path == new_filename:
             break
     else:
         dictionaries.insert(0, DictionaryConfig(new_filename))
     # Note: pass in `loaded_dictionaries` to force update (use case:
     # the user decided to overwrite an already loaded dictionary).
     self._update_dictionaries(
         dictionaries,
         keep_selection=False,
         loaded_dictionaries=self._loaded_dictionaries)
 def handle(self, words=None):
     if not words:
         self.output("Filename must be provided")
         return True
     else:
         filename = normalize_path(' '.join(words))
         with open(filename, 'a') as f:
             f.write(self.tape_buffer.text)
         self.output(f"Saved tape to {filename}")
         return True
Beispiel #5
0
    def test_simple_fields(self):
        Case = namedtuple('Case', ['field', 'section', 'option', 'default', 
                                   'value1', 'value2', 'value3'])

        cases = (
        ('machine_type', config.MACHINE_CONFIG_SECTION, 
         config.MACHINE_TYPE_OPTION, config.DEFAULT_MACHINE_TYPE, 'Gemini PR', 'TX Bolt',
         'Passport'),
        ('log_file_name', config.LOGGING_CONFIG_SECTION, config.LOG_FILE_OPTION, 
         normalize_path(os.path.join(CONFIG_DIR, config.DEFAULT_LOG_FILE)),
         os.path.join(ABS_PATH, 'l1'), os.path.join(ABS_PATH, 'log'), os.path.join(ABS_PATH, 'sawzall')),
        ('enable_stroke_logging', config.LOGGING_CONFIG_SECTION, 
         config.ENABLE_STROKE_LOGGING_OPTION, 
         config.DEFAULT_ENABLE_STROKE_LOGGING, False, True, False),
        ('enable_translation_logging', config.LOGGING_CONFIG_SECTION, 
         config.ENABLE_TRANSLATION_LOGGING_OPTION, 
         config.DEFAULT_ENABLE_TRANSLATION_LOGGING, False, True, False),
        ('auto_start', config.MACHINE_CONFIG_SECTION, 
         config.MACHINE_AUTO_START_OPTION, config.DEFAULT_MACHINE_AUTO_START, 
         True, False, True),
        ('show_stroke_display', config.STROKE_DISPLAY_SECTION, 
         config.STROKE_DISPLAY_SHOW_OPTION, config.DEFAULT_STROKE_DISPLAY_SHOW, 
         True, False, True),
        ('space_placement', config.OUTPUT_CONFIG_SECTION, 
         config.OUTPUT_CONFIG_SPACE_PLACEMENT_OPTION, config.DEFAULT_OUTPUT_CONFIG_SPACE_PLACEMENT, 
         'Before Output', 'After Output', 'None'),
        )

        for case in cases:
            case = Case(*case)
            c = config.Config()
            getter = getattr(c, 'get_' + case.field)
            setter = getattr(c, 'set_' + case.field)
            # Check the default value.
            self.assertEqual(getter(), case.default)
            # Set a value...
            setter(case.value1)
            # ...and make sure it is really set.
            self.assertEqual(getter(), case.value1)
            # Load from a file...
            f = make_config('[%s]\n%s: %s' % (case.section, case.option,
                                              case.value2))
            c.load(f)
            # ..and make sure the right value is set.
            self.assertEqual(getter(), case.value2)
            # Set a value...
            setter(case.value3)
            f = make_config()
            # ...save it...
            c.save(f)
            # ...and make sure it's right.
            self.assertEqual(f.getvalue().decode('utf-8'),
                             '[%s]\n%s = %s\n\n' % (case.section, case.option,
                                                    case.value3))
 def handle(self, words=[]):
     path = normalize_path(" ".join(words))
     if not isfile(path):
         self.output(f"{path} is not a file")
         return True
     with self.engine:
         self.output(f"Adding {path} as a dictionary")
         dicts = self.engine.config["dictionaries"].copy()
         dicts.insert(0, DictionaryConfig(path))
         self.engine.config = {"dictionaries": dicts}
         return True
Beispiel #7
0
def make_dict(contents, extension=None, name=None):
    kwargs = {'delete': False}
    if name is not None:
        kwargs['prefix'] = name + '_'
    if extension is not None:
        kwargs['suffix'] = '.' + extension
    tf = tempfile.NamedTemporaryFile(**kwargs)
    try:
        tf.write(contents)
        tf.close()
        yield normalize_path(tf.name)
    finally:
        os.unlink(tf.name)
Beispiel #8
0
 def _add_existing_dictionaries(self):
     new_filenames = QFileDialog.getOpenFileNames(
         self, _('Add dictionaries'), None, _dictionary_filters(),
     )[0]
     dictionaries = self._config_dictionaries[:]
     for filename in new_filenames:
         filename = normalize_path(filename)
         for d in dictionaries:
             if d.path == filename:
                 break
         else:
             dictionaries.insert(0, DictionaryConfig(filename))
     self._update_dictionaries(dictionaries, keep_selection=False)
Beispiel #9
0
def make_dict(contents, extension=None, name=None):
    kwargs = { 'delete': False }
    if name is not None:
        kwargs['prefix'] = name + '_'
    if extension is not None:
        kwargs['suffix'] = '.' + extension
    tf = tempfile.NamedTemporaryFile(**kwargs)
    try:
        tf.write(contents)
        tf.close()
        yield normalize_path(tf.name)
    finally:
        os.unlink(tf.name)
Beispiel #10
0
 def _add_existing_dictionaries(self):
     new_filenames = QFileDialog.getOpenFileNames(
         self,
         _('Add dictionaries'),
         None,
         _dictionary_filters(),
     )[0]
     dictionaries = self._config_dictionaries[:]
     for filename in new_filenames:
         filename = normalize_path(filename)
         for d in dictionaries:
             if d.path == filename:
                 break
         else:
             dictionaries.insert(0, DictionaryConfig(filename))
     self._update_dictionaries(dictionaries, keep_selection=False)
 def _add_existing_dictionaries(self):
     new_filenames = QFileDialog.getOpenFileNames(
         # i18n: Widget: “DictionariesWidget”, “add” file picker.
         parent=self,
         caption=_('Add dictionaries'),
         directory=self._file_dialogs_directory,
         filter=_dictionary_filters(),
     )[0]
     dictionaries = self._config_dictionaries[:]
     for filename in new_filenames:
         filename = normalize_path(filename)
         self._file_dialogs_directory = os.path.dirname(filename)
         for d in dictionaries:
             if d.path == filename:
                 break
         else:
             dictionaries.insert(0, DictionaryConfig(filename))
     self._update_dictionaries(dictionaries, keep_selection=False)
Beispiel #12
0
 def _create_new_dictionary(self):
     new_filename = QFileDialog.getSaveFileName(
         self, _('New dictionary'), None,
         _dictionary_filters(include_readonly=False),
     )[0]
     if not new_filename:
         return
     new_filename = normalize_path(new_filename)
     try:
         d = create_dictionary(new_filename, threaded_save=False)
         d.save()
     except:
         log.error('creating dictionary %s failed', new_filename, exc_info=True)
         return
     dictionaries = self._config_dictionaries[:]
     for d in dictionaries:
         if d.path == new_filename:
             break
     else:
         dictionaries.insert(0, DictionaryConfig(new_filename))
     # Note: pass in `loaded_dictionaries` to force update (use case:
     # the user decided to overwrite an already loaded dictionary).
     self._update_dictionaries(dictionaries, keep_selection=False,
                               loaded_dictionaries=self._loaded_dictionaries)
Beispiel #13
0
def test_loading_dictionaries(tmp_path, engine):
    def check_loaded_events(actual_events, expected_events):
        assert len(actual_events) == len(expected_events)
        for n, event in enumerate(actual_events):
            event_type, event_args, event_kwargs = event
            msg = 'event %u: %r' % (n, event)
            assert event_type == 'dictionaries_loaded', msg
            assert event_kwargs == {}, msg
            assert len(event_args) == 1, msg
            assert isinstance(event_args[0], StenoDictionaryCollection), msg
            assert [(d.path, d.enabled, isinstance(d, ErroredDictionary))
                    for d in event_args[0].dicts] == expected_events[n], msg
    with \
            make_dict(tmp_path, b'{}', 'json', 'valid1') as valid_dict_1, \
            make_dict(tmp_path, b'{}', 'json', 'valid2') as valid_dict_2, \
            make_dict(tmp_path, b'', 'json', 'invalid1') as invalid_dict_1, \
            make_dict(tmp_path, b'', 'json', 'invalid2') as invalid_dict_2:
        valid_dict_1 = normalize_path(str(valid_dict_1))
        valid_dict_2 = normalize_path(str(valid_dict_2))
        invalid_dict_1 = normalize_path(str(invalid_dict_1))
        invalid_dict_2 = normalize_path(str(invalid_dict_2))
        engine.start()
        for new_dictionaries, *expected_events in (
                # Load one valid dictionary.
            [
                [
                    # path, enabled
                    (valid_dict_1, True),
                ],
                [
                    # path, enabled, errored
                    (valid_dict_1, True, False),
                ]
            ],
                # Load another invalid dictionary.
            [[
                (valid_dict_1, True),
                (invalid_dict_1, True),
            ], [
                (valid_dict_1, True, False),
                (invalid_dict_1, True, True),
            ]],
                # Disable first dictionary.
            [[
                (valid_dict_1, False),
                (invalid_dict_1, True),
            ], [
                (valid_dict_1, False, False),
                (invalid_dict_1, True, True),
            ]],
                # Replace invalid dictonary with another invalid one.
            [[
                (valid_dict_1, False),
                (invalid_dict_2, True),
            ], [
                (valid_dict_1, False, False),
            ], [
                (valid_dict_1, False, False),
                (invalid_dict_2, True, True),
            ]]):
            engine.events.clear()
            config_update = {
                'dictionaries':
                [DictionaryConfig(*d) for d in new_dictionaries]
            }
            engine.config = dict(config_update)
            assert engine.events[0] == ('config_changed', (config_update, ),
                                        {})
            check_loaded_events(engine.events[1:], expected_events)
        # Simulate an outdated dictionary.
        engine.events.clear()
        engine.dictionaries[valid_dict_1].timestamp -= 1
        engine.config = {}
        check_loaded_events(engine.events, [[
            (invalid_dict_2, True, True),
        ], [
            (valid_dict_1, False, False),
            (invalid_dict_2, True, True),
        ]])