Example #1
0
def main():
    """Launch plover."""
    description = "Run the plover stenotype engine. This is a graphical application."
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('--version', action='version', version='%s %s'
                        % (__software_name__.capitalize(), __version__))
    parser.add_argument('-l', '--log-level', choices=['debug', 'info', 'warning', 'error'],
                        default=None, help='set log level')
    args = parser.parse_args(args=sys.argv[1:])
    if args.log_level is not None:
        log.set_level(args.log_level.upper())
    try:
        # Ensure only one instance of Plover is running at a time.
        with plover.oslayer.processlock.PloverLock():
            if sys.platform.startswith('darwin'):
                appnope.nope()
            init_config_dir()
            # This must be done after calling init_config_dir, so
            # Plover's configuration directory actually exists.
            log.setup_logfile()
            log.info('Plover %s', __version__)
            config = Config()
            config.target_file = CONFIG_FILE
            gui = plover.gui.main.PloverGUI(config)
            gui.MainLoop()
            with open(config.target_file, 'wb') as f:
                config.save(f)
    except plover.oslayer.processlock.LockNotAcquiredException:
        show_error('Error', 'Another instance of Plover is already running.')
    except:
        show_error('Unexpected error', traceback.format_exc())
    os._exit(1)
Example #2
0
def main(config):

    use_qt_notifications = True
    handler_class = None
    try:
        if sys.platform.startswith('linux'):
            from plover.oslayer.log_dbus import DbusNotificationHandler
            handler_class = DbusNotificationHandler
        elif sys.platform.startswith('darwin'):
            from plover.oslayer.log_osx import OSXNotificationHandler
            handler_class = OSXNotificationHandler
    except Exception:
        log.info('could not import platform gui log', exc_info=True)
    if handler_class is not None:
        try:
            handler = handler_class()
        except Exception:
            log.info('could not initialize platform gui log', exc_info=True)
        else:
            log.add_handler(handler)
            use_qt_notifications = False

    # Setup internationalization support.
    install_gettext()

    app = Application(config, use_qt_notifications)
    app.run()
    del app

    return 0
Example #3
0
def main(config):

    handler_class = None
    try:
        if sys.platform.startswith('linux'):
            from plover.oslayer.log_dbus import DbusNotificationHandler
            handler_class = DbusNotificationHandler
        elif sys.platform.startswith('darwin'):
            from plover.oslayer.log_osx import OSXNotificationHandler
            handler_class = OSXNotificationHandler
    except Exception:
        log.info('could not import platform gui log', exc_info=True)
    if handler_class is not None:
        try:
            handler = handler_class()
        except Exception:
            log.info('could not initialize platform gui log', exc_info=True)
        else:
            log.add_handler(handler)

    engine = Engine(config, KeyboardEmulation())
    if not engine.load_config():
        return 3
    quitting = Event()
    engine.hook_connect('quit', quitting.set)
    engine.start()
    try:
        quitting.wait()
    except KeyboardInterrupt:
        pass
    engine.quit()
    engine.join()

    return 0
Example #4
0
 def load_plugins(self, plugins_dir=PLUGINS_DIR):
     log.info('loading plugins from %s', plugins_dir)
     working_set = pkg_resources.working_set
     environment = pkg_resources.Environment([plugins_dir])
     distributions, errors = working_set.find_plugins(environment)
     if errors:
         log.error("error(s) while loading plugins: %s", errors)
     list(map(working_set.add, distributions))
Example #5
0
 def start_loading(self, filename):
     op = self.dictionaries.get(filename)
     if op is not None and not op.needs_reloading():
         return op
     log.info('%s dictionary: %s', 'loading' if op is None else 'reloading', filename)
     op = DictionaryLoadingOperation(filename)
     self.dictionaries[filename] = op
     return op
Example #6
0
 def run(self):
     """Overrides base class run method. Do not call directly."""
     try:
         _loop(self.serial_port, self.finished, self._on_stroke, self._ready)
     except _StopException:
         pass
     except Exception:
         log.info("Failure starting Stentura", exc_info=True)
         self._error()
Example #7
0
 def run(self):
     """Overrides base class run method. Do not call directly."""
     try:
         _loop(self.serial_port, self.finished, self._notify, self._ready)
     except _StopException:
         pass
     except Exception as e:
         log.info("Failure starting Stentura: %s", str(e))
         self._error()
Example #8
0
 def register_plugin_from_entrypoint(self, plugin_type, entrypoint):
     log.info('%s: %s (from %s)', plugin_type,
              entrypoint.name, entrypoint.module_name)
     try:
         obj = entrypoint.resolve()
     except:
         log.error('error loading %s plugin: %s (from %s)', plugin_type,
                   entrypoint.name, entrypoint.module_name, exc_info=True)
     else:
         self.register_plugin(plugin_type, entrypoint.name, obj)
Example #9
0
 def load(self, filenames):
     start_time = time.time()
     self.dictionaries = {f: self.start_loading(f) for f in filenames}
     results = [
         self.dictionaries[f].get()
         for f in filenames
     ]
     log.info('loaded %u dictionaries in %.3fs',
              len(results), time.time() - start_time)
     return results
Example #10
0
def install_gettext():
    lang = get_language()
    log.info('setting language to: %s', lang)
    os.environ['LANGUAGE'] = lang
    locale_dir = pkg_resources.resource_filename('plover', 'gui_qt/messages')
    if PY2:
        kwargs = { 'unicode': 1 }
    else:
        kwargs = {}
    gettext.install('plover', locale_dir, *kwargs)
Example #11
0
 def _start_extensions(self, extension_list):
     for extension_name in extension_list:
         log.info('starting `%s` extension', extension_name)
         try:
             extension = registry.get_plugin('extension', extension_name).obj(self)
             extension.start()
         except Exception:
             log.error('initializing extension `%s` failed', extension_name, exc_info=True)
         else:
             self._running_extensions[extension_name] = extension
Example #12
0
 def start_capture(self):
     """Begin listening for output from the stenotype machine."""
     try:
         self._machine = hid.device(VENDOR_ID, 1)
         self._machine.set_nonblocking(1)
     except IOError as e:
         log.info('Treal device not found: %s', str(e))
         log.warning('Treal is not connected')
         self._error()
         return
     return ThreadedStenotypeBase.start_capture(self)
Example #13
0
 def start_capture(self):
     """Begin listening for output from the stenotype machine."""
     try:
         if hasattr(hid.device, 'open'):
             self._machine = hid.device()
             self._machine.open(VENDOR_ID, 1)
         else:
             self._machine = hid.device(VENDOR_ID, 1)
         self._machine.set_nonblocking(0)
     except IOError as e:
         log.info('Treal device not found: %s', str(e))
         log.warning('Treal is not connected')
         self._error()
         return
     super(Stenotype, self).start_capture()
Example #14
0
def copy_default_dictionaries(config):
    '''Copy default dictionaries to the configuration directory.

    Each default dictionary is copied to the configuration directory
    if it's in use by the current config and missing.
    '''

    config_dictionaries = set(os.path.basename(dictionary) for dictionary
                              in config.get_dictionary_file_names())
    for dictionary in config_dictionaries & set(DEFAULT_DICTIONARIES):
        dst = os.path.join(CONFIG_DIR, dictionary)
        if os.path.exists(dst):
            continue
        src = os.path.join(ASSETS_DIR, dictionary)
        log.info('copying %s to %s', src, dst)
        shutil.copy(src, dst)
Example #15
0
 def register_plugin_from_entrypoint(self, plugin_type, entrypoint):
     log.info('%s: %s (from %s)', plugin_type,
              entrypoint.name, entrypoint.dist)
     try:
         obj = entrypoint.resolve()
     except:
         log.error('error loading %s plugin: %s (from %s)', plugin_type,
                   entrypoint.name, entrypoint.module_name, exc_info=True)
     else:
         plugin = self.register_plugin(plugin_type, entrypoint.name, obj)
         # Keep track of distributions providing plugins.
         dist_id = str(entrypoint.dist)
         dist = self._distributions.get(dist_id)
         if dist is None:
             dist = PluginDistribution(entrypoint.dist, set())
             self._distributions[dist_id] = dist
         dist.plugins.add(plugin)
Example #16
0
        def start_capture(self):
            """Begin listening for output from the stenotype machine."""
            devices = hid.HidDeviceFilter(vendor_id=VENDOR_ID).get_devices()
            if len(devices) == 0:
                log.info('Treal: no devices with vendor id %s', str(VENDOR_ID))
                log.warning('Treal not connected')
                self._error()
                return
            self._machine = devices[0]
            self._machine.open()
            handler = DataHandler(self._notify)

            def callback(p):
                if len(p) != 6: return
                handler.update(p[1:])

            self._machine.set_raw_data_handler(callback)
            self._ready()
Example #17
0
    def _load(self, filename):
        ext = os.path.splitext(filename)[1]
        reader = PREFERRED_READER[ext]
        log.info('reading %r using %s reader', filename,
                 repr(reader) if reader else 'default')
        book = pyexcel.get_book_dict(file_name=filename, library=reader)

        def load():
            for sheet, entries in book.items():
                self._sheets.append(sheet)
                for row in entries:
                    if not row or not row[0]:
                        continue
                    translation = row[1] if len(row) > 1 else ''
                    steno = normalize_steno(row[0])
                    yield steno, translation
                    self._extras[steno] = (sheet, row[2:])

        self.update(load())
Example #18
0
 def register_plugin_from_entrypoint(self, plugin_type, entrypoint):
     log.info('%s: %s (from %s)', plugin_type,
              entrypoint.name, entrypoint.dist)
     try:
         obj = entrypoint.resolve()
     except:
         log.error('error loading %s plugin: %s (from %s)', plugin_type,
                   entrypoint.name, entrypoint.module_name, exc_info=True)
         if not self._suppress_errors:
             reraise(*sys.exc_info())
     else:
         plugin = self.register_plugin(plugin_type, entrypoint.name, obj)
         # Keep track of distributions providing plugins.
         dist_id = str(entrypoint.dist)
         dist = self._distributions.get(dist_id)
         if dist is None:
             dist = PluginDistribution(entrypoint.dist, set())
             self._distributions[dist_id] = dist
         dist.plugins.add(plugin)
Example #19
0
    def __init__(self, config, controller, use_qt_notifications):

        # This is done dynamically so localization
        # support can be configure beforehand.
        from plover.gui_qt.main_window import MainWindow

        self._app = None
        self._win = None
        self._engine = None
        self._translator = None

        QCoreApplication.setApplicationName(__software_name__.capitalize())
        QCoreApplication.setApplicationVersion(__version__)
        QCoreApplication.setOrganizationName('Open Steno Project')
        QCoreApplication.setOrganizationDomain('openstenoproject.org')

        self._app = QApplication([])
        self._app.setAttribute(Qt.AA_UseHighDpiPixmaps)

        # Enable localization of standard Qt controls.
        log.info('setting language to: %s', _.lang)
        self._translator = QTranslator()
        translations_dir = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
        self._translator.load('qtbase_' + _.lang, translations_dir)
        self._app.installTranslator(self._translator)

        QApplication.setQuitOnLastWindowClosed(False)

        self._app.engine = self._engine = Engine(config, controller,
                                                 KeyboardEmulation())
        # On macOS, quitting through the dock will result
        # in a direct call to `QCoreApplication.quit`.
        self._app.aboutToQuit.connect(self._app.engine.quit)

        signal.signal(signal.SIGINT, lambda signum, stack: self._engine.quit())

        # Make sure the Python interpreter runs at least every second,
        # so signals have a chance to be processed.
        self._timer = QTimer()
        self._timer.timeout.connect(lambda: None)
        self._timer.start(1000)

        self._win = MainWindow(self._engine, use_qt_notifications)
Example #20
0
def copy_default_dictionaries(dictionaries_files):
    '''Recreate default dictionaries.

    Each default dictionary is recreated if it's
    in use by the current config and missing.
    '''

    for dictionary in dictionaries_files:
        # Ignore assets.
        if dictionary.startswith(ASSET_SCHEME):
            continue
        # Nothing to do if dictionary file already exists.
        if os.path.exists(dictionary):
            continue
        # Check it's actually a default dictionary.
        basename = os.path.basename(dictionary)
        if basename not in system.DEFAULT_DICTIONARIES:
            continue
        default_dictionary = os.path.join(system.DICTIONARIES_ROOT, basename)
        log.info('recreating %s from %s', dictionary, default_dictionary)
        shutil.copyfile(resource_filename(default_dictionary), dictionary)
Example #21
0
    def start_capture(self):
        if self.serial_port:
            self.serial_port.close()

        try:
            self.serial_port = serial.Serial(**self.serial_params)
        except (serial.SerialException, OSError) as e:
            log.warning('Machine not connected')
            log.info('Can\'t open Serial port: %s', str(e))
            self._error()
            return
        if self.serial_port is None:
            log.warning('Serial port not found: %s', str(e))
            self._error()
            return
        if not self.serial_port.isOpen():
            log.warning('Serial port is not open: %s', str(e))
            self._error()
            return

        return ThreadedStenotypeBase.start_capture(self)
Example #22
0
def copy_default_dictionaries(dictionaries_files):
    '''Recreate default dictionaries.

    Each default dictionary is recreated if it's
    in use by the current config and missing.
    '''

    for dictionary in dictionaries_files:
        # Ignore assets.
        if dictionary.startswith(ASSET_SCHEME):
            continue
        # Nothing to do if dictionary file already exists.
        if os.path.exists(dictionary):
            continue
        # Check it's actually a default dictionary.
        basename = os.path.basename(dictionary)
        if basename not in system.DEFAULT_DICTIONARIES:
            continue
        default_dictionary = os.path.join(system.DICTIONARIES_ROOT, basename)
        log.info('recreating %s from %s', dictionary, default_dictionary)
        shutil.copyfile(resource_filename(default_dictionary), dictionary)
Example #23
0
    def start_capture(self):
        if self.serial_port:
            self.serial_port.close()

        try:
            self.serial_port = serial.Serial(**self.serial_params)
        except (serial.SerialException, OSError) as e:
            log.warning('Stentura not connected')
            log.info('Can\'t open Serial port: %s', str(e))
            self._error()
            return
        if self.serial_port is None:
            log.warning('Serial port not found: %s', str(e))
            self._error()
            return
        if not self.serial_port.isOpen():
            log.warning('Serial port is not open: %s', str(e))
            self._error()
            return

        return ThreadedStenotypeBase.start_capture(self)
Example #24
0
def main():
    """Launch plover."""
    description = "Run the plover stenotype engine. This is a graphical application."
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('--version',
                        action='version',
                        version='%s %s' %
                        (__software_name__.capitalize(), __version__))
    parser.add_argument('-l',
                        '--log-level',
                        choices=['debug', 'info', 'warning', 'error'],
                        default=None,
                        help='set log level')
    args = parser.parse_args(args=sys.argv[1:])
    if args.log_level is not None:
        log.set_level(args.log_level.upper())
    try:
        # Ensure only one instance of Plover is running at a time.
        with plover.oslayer.processlock.PloverLock():
            if sys.platform.startswith('darwin'):
                appnope.nope()
            init_config_dir()
            # This must be done after calling init_config_dir, so
            # Plover's configuration directory actually exists.
            log.setup_logfile()
            log.info('Plover %s', __version__)
            config = Config()
            config.target_file = CONFIG_FILE
            gui = plover.gui.main.PloverGUI(config)
            gui.MainLoop()
            with open(config.target_file, 'wb') as f:
                config.save(f)
    except plover.oslayer.processlock.LockNotAcquiredException:
        show_error('Error', 'Another instance of Plover is already running.')
    except:
        show_error('Unexpected error', traceback.format_exc())
    os._exit(1)
    def run(self):
        while not self._stop.isSet():
            if self._engine.machine_state != STATE_ERROR:
                log.info('plover-auto-reconnect-machine: machine is connected')
                # wait until notified
                self._wait()
            if self._engine.machine_state == STATE_ERROR:
                if isinstance(self._engine._machine,
                              SerialStenotypeBase) and not self._port_exists(
                                  self._engine._machine.serial_params['port']):
                    log.info(
                        'plover-auto-reconnect-machine: machine can not be reconnected, retrying later'
                    )
                else:
                    log.info(
                        'plover-auto-reconnect-machine: machine is disconnected, trying to reconnect'
                    )
                    self._engine.reset_machine()

                # prevent busy endless loop, just check again in one second
                sleep(1)
Example #26
0
 def register_plugin(self, plugin_type, entrypoint):
     log.info('%s: %s (from %s)', plugin_type,
              entrypoint.name, entrypoint.module_name)
     self._plugins[plugin_type][entrypoint.name.lower()] = entrypoint
Example #27
0
 def _update(self, config_update=None, full=False, reset_machine=False):
     original_config = self._config.as_dict()
     # Update configuration.
     if config_update is not None:
         self._config.update(**config_update)
         config = self._config.as_dict()
     else:
         config = original_config
     # Create configuration update.
     if full:
         config_update = config
     else:
         config_update = {option: value for option, value in config.items() if value != original_config[option]}
         if "machine_type" in config_update:
             for opt in ("machine_specific_options", "system_keymap"):
                 config_update[opt] = config[opt]
     # Update logging.
     log.set_stroke_filename(config["log_file_name"])
     log.enable_stroke_logging(config["enable_stroke_logging"])
     log.enable_translation_logging(config["enable_translation_logging"])
     # Update output.
     self._formatter.set_space_placement(config["space_placement"])
     self._formatter.start_attached = config["start_attached"]
     self._formatter.start_capitalized = config["start_capitalized"]
     self._translator.set_min_undo_length(config["undo_levels"])
     # Update system.
     system_name = config["system_name"]
     if system.NAME != system_name:
         log.info("loading system: %s", system_name)
         system.setup(system_name)
     # Update machine.
     update_keymap = False
     start_machine = False
     machine_params = MachineParams(
         config["machine_type"], config["machine_specific_options"], config["system_keymap"]
     )
     if reset_machine or machine_params != self._machine_params:
         if self._machine is not None:
             self._machine.stop_capture()
             self._machine = None
         machine_type = config["machine_type"]
         machine_options = config["machine_specific_options"]
         try:
             machine_class = registry.get_plugin("machine", machine_type).resolve()
         except Exception as e:
             raise InvalidConfigurationError(str(e))
         log.info("setting machine: %s", machine_type)
         self._machine = machine_class(machine_options)
         self._machine.set_suppression(self._is_running)
         self._machine.add_state_callback(self._machine_state_callback)
         self._machine.add_stroke_callback(self._machine_stroke_callback)
         self._machine_params = machine_params
         update_keymap = True
         start_machine = True
     elif self._machine is not None:
         update_keymap = "system_keymap" in config_update
     if update_keymap:
         machine_keymap = config["system_keymap"]
         if machine_keymap is not None:
             self._machine.set_keymap(machine_keymap)
     if start_machine:
         self._machine.start_capture()
     # Update dictionaries.
     dictionaries_files = config["dictionary_file_names"]
     copy_default_dictionaries(dictionaries_files)
     dictionaries = self._dictionaries_manager.load(dictionaries_files)
     self._dictionaries.set_dicts(dictionaries)
     # Trigger `config_changed` hook.
     if config_update:
         self._trigger_hook("config_changed", config_update)
Example #28
0
# See LICENSE.txt for details.

"Manager for stenotype machines types."

from plover.machine.geminipr import Stenotype as geminipr
from plover.machine.txbolt import Stenotype as txbolt
from plover.machine.sidewinder import Stenotype as sidewinder
from plover.machine.stentura import Stenotype as stentura
from plover.machine.stenturait import StenotypeIT as stenturait
from plover.machine.passport import Stenotype as passport
from plover import log

try:
    from plover.machine.treal import Stenotype as treal
except Exception as e:
    log.info('Unable to use Treal on this machine: %s', str(e))
    treal = None

class NoSuchMachineException(Exception):
    def __init__(self, id):
        self._id = id

    def __str__(self):
        return 'Unrecognized machine type: {}'.format(self._id)

class Registry(object):
    def __init__(self):
        self._machines = {}
        self._aliases = {}

    def register(self, name, machine):
Example #29
0
 def _stop_extensions(self, extension_list):
     for extension_name in list(extension_list):
         log.info('stopping `%s` extension', extension_name)
         extension = self._running_extensions.pop(extension_name)
         extension.stop()
         del extension
Example #30
0
def install_gettext():
    lang = get_language()
    log.info('setting language to: %s', lang)
    os.environ['LANGUAGE'] = lang
    locale_dir = pkg_resources.resource_filename('plover', 'gui_qt/messages')
    gettext.install('plover', locale_dir)
Example #31
0
import sys
from plover import log


handler = None

try:
    if sys.platform.startswith('linux'):
        from plover.oslayer.log_dbus import DbusNotificationHandler
        handler = DbusNotificationHandler
    elif sys.platform.startswith('darwin'):
        from plover.oslayer.log_osx import OSXNotificationHandler
        handler = OSXNotificationHandler
except Exception as e:
    log.info('could not import platform gui log', exc_info=e)

if handler is None:
    from plover.gui.log_wx import WxNotificationHandler
    handler = WxNotificationHandler

log.add_handler(handler())
 def stop(self):
     log.info('plover-auto-reconnect-machine: stopping')
     self._stop.set()
     self._notify()
     self._engine.hook_disconnect("machine_state_changed",
                                  self._on_machine_state_changed)
 def start(self):
     log.info('plover-auto-reconnect-machine: starting')
     self._engine.hook_connect("machine_state_changed",
                               self._on_machine_state_changed)
     self._thread.start()
Example #34
0
 def start(self) -> None:
     log.info("FANCY_START")
     self.engine.hook_connect("translated", self.translated)
     super().start()
Example #35
0
def main():
    """Launch plover."""
    description = "Run the plover stenotype engine. This is a graphical application."
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('--version',
                        action='version',
                        version='%s %s' %
                        (__software_name__.capitalize(), __version__))
    parser.add_argument(
        '-s',
        '--script',
        default=None,
        nargs=argparse.REMAINDER,
        help='use another plugin console script as main entrypoint, '
        'passing in the rest of the command line arguments, '
        'print list of available scripts when no argument is given')
    parser.add_argument('-l',
                        '--log-level',
                        choices=['debug', 'info', 'warning', 'error'],
                        default=None,
                        help='set log level')
    parser.add_argument('-g', '--gui', default=None, help='set gui')
    args = parser.parse_args(args=sys.argv[1:])
    if args.log_level is not None:
        log.set_level(args.log_level.upper())
    log.setup_platform_handler()

    log.info('Plover %s', __version__)
    log.info('configuration directory: %s', CONFIG_DIR)

    if PLATFORM == 'mac':
        # Fixes PyQt issue on macOS Big Sur.
        os.environ['QT_MAC_WANTS_LAYER'] = '1'

    registry.update()

    if args.gui is None:
        gui_priority = {
            'qt': 1,
            'none': -1,
        }
        gui_list = sorted(registry.list_plugins('gui'),
                          reverse=True,
                          key=lambda gui: gui_priority.get(gui.name, 0))
        gui = gui_list[0].obj
    else:
        gui = registry.get_plugin('gui', args.gui).obj

    try:
        if args.script is not None:
            if args.script:
                # Create a mapping of available console script,
                # with the following priorities (highest first):
                # - {project_name}-{version}:{script_name}
                # - {project_name}:{script_name}
                # - {script_name}
                console_scripts = {}
                for e in sorted(
                        pkg_resources.iter_entry_points('console_scripts'),
                        key=lambda e: (e.dist, e.name)):
                    for key in (
                            '%s-%s:%s' %
                        (e.dist.project_name, e.dist.version, e.name),
                            '%s:%s' % (e.dist.project_name, e.name),
                            e.name,
                    ):
                        console_scripts[key] = e
                entrypoint = console_scripts.get(args.script[0])
                if entrypoint is None:
                    log.error('no such script: %s', args.script[0])
                    code = 1
                else:
                    sys.argv = args.script
                    try:
                        code = entrypoint.load()()
                    except SystemExit as e:
                        code = e.code
                if code is None:
                    code = 0
            else:
                print('available script(s):')
                dist = None
                for e in sorted(
                        pkg_resources.iter_entry_points('console_scripts'),
                        key=lambda e: (str(e.dist), e.name)):
                    if dist != e.dist:
                        dist = e.dist
                        print('%s:' % dist)
                    print('- %s' % e.name)
                code = 0
            os._exit(code)

        # Ensure only one instance of Plover is running at a time.
        with Controller() as controller:
            if controller.is_owner:
                # Not other instance, regular startup.
                if PLATFORM == 'mac':
                    import appnope
                    appnope.nope()
                init_config_dir()
                # This must be done after calling init_config_dir, so
                # Plover's configuration directory actually exists.
                log.setup_logfile()
                config = Config(CONFIG_FILE)
                code = gui.main(config, controller)
            else:
                log.info(
                    'another instance is running, sending `focus` command')
                # Other instance? Try focusing the main window.
                try:
                    controller.send_command('focus')
                except ConnectionRefusedError:
                    log.error('connection to existing instance failed, '
                              'force cleaning before restart')
                    # Assume the previous instance died, leaving
                    # a stray socket, try cleaning it...
                    if not controller.force_cleanup():
                        raise
                    # ...and restart.
                    code = -1
                else:
                    code = 0
    except:
        gui.show_error('Unexpected error', traceback.format_exc())
        code = 2
    if code == -1:
        # Restart.
        args = sys.argv[:]
        if args[0].endswith('.py') or args[0].endswith('.pyc'):
            # We're running from source.
            spec = sys.modules['__main__'].__spec__
            assert sys.argv[0] == spec.origin
            args[0:1] = [sys.executable, '-m', spec.name]
        # Execute atexit handlers.
        atexit._run_exitfuncs()
        if PLATFORM == 'win':
            # Workaround https://bugs.python.org/issue19066
            subprocess.Popen(args, cwd=os.getcwd())
            code = 0
        else:
            os.execv(args[0], args)
    os._exit(code)
Example #36
0
 def layoutChanged_(self, event):
     log.info('Mac keyboard layout changed, updating')
     layout._update_layout()
Example #37
0
 def register_plugin(self, plugin_type, entrypoint):
     log.info('%s: %s (from %s)', plugin_type, entrypoint.name,
              entrypoint.module_name)
     self._plugins[plugin_type][entrypoint.name.lower()] = entrypoint
Example #38
0
import sys
from plover import log

handler = None

try:
    if sys.platform.startswith('linux'):
        from plover.gui.log_dbus import DbusNotificationHandler
        handler = DbusNotificationHandler
    elif sys.platform.startswith('darwin'):
        from plover.gui.log_osx import OSXNotificationHandler
        handler = OSXNotificationHandler
except Exception as e:
    log.info('could not import platform gui log', exc_info=e)

if handler is None:
    from plover.gui.log_wx import WxNotificationHandler
    handler = WxNotificationHandler

log.add_handler(handler())
Example #39
0
 def _update(self, config_update=None, full=False, reset_machine=False):
     original_config = self._config.as_dict()
     # Update configuration.
     if config_update is not None:
         self._config.update(**config_update)
         config = self._config.as_dict()
     else:
         config = original_config
     # Create configuration update.
     if full:
         config_update = config
     else:
         config_update = {
             option: value
             for option, value in config.items()
             if value != original_config[option]
         }
     # Update logging.
     log.set_stroke_filename(config['log_file_name'])
     log.enable_stroke_logging(config['enable_stroke_logging'])
     log.enable_translation_logging(config['enable_translation_logging'])
     # Update output.
     self._formatter.set_space_placement(config['space_placement'])
     self._formatter.start_attached = config['start_attached']
     self._formatter.start_capitalized = config['start_capitalized']
     self._translator.set_min_undo_length(config['undo_levels'])
     # Update system.
     system_name = config['system_name']
     if system.NAME != system_name:
         log.info('loading system: %s', system_name)
         system.setup(system_name)
     # Update machine.
     update_keymap = False
     start_machine = False
     machine_params = MachineParams(config['machine_type'],
                                    config['machine_specific_options'],
                                    config['system_keymap'])
     # Do not reset if only the keymap changed.
     if self._machine_params is None or \
        self._machine_params.type != machine_params.type or \
        self._machine_params.options != machine_params.options:
         reset_machine = True
     if reset_machine:
         if self._machine is not None:
             self._machine.stop_capture()
             self._machine = None
         machine_type = config['machine_type']
         machine_options = config['machine_specific_options']
         machine_class = registry.get_plugin('machine', machine_type).obj
         log.info('setting machine: %s', machine_type)
         self._machine = machine_class(machine_options)
         self._machine.set_suppression(self._is_running)
         self._machine.add_state_callback(self._machine_state_callback)
         self._machine.add_stroke_callback(self._machine_stroke_callback)
         self._machine_params = machine_params
         update_keymap = True
         start_machine = True
     elif self._machine is not None:
         update_keymap = 'system_keymap' in config_update
     if update_keymap:
         machine_keymap = config['system_keymap']
         if machine_keymap is not None:
             self._machine.set_keymap(machine_keymap)
     if start_machine:
         self._machine.start_capture()
     # Update running extensions.
     enabled_extensions = config['enabled_extensions']
     running_extensions = set(self._running_extensions)
     self._stop_extensions(running_extensions - enabled_extensions)
     self._start_extensions(enabled_extensions - running_extensions)
     # Trigger `config_changed` hook.
     if config_update:
         self._trigger_hook('config_changed', config_update)
     # Update dictionaries.
     config_dictionaries = OrderedDict(
         (d.path, d) for d in config['dictionaries'])
     copy_default_dictionaries(config_dictionaries.keys())
     # Start by unloading outdated dictionaries.
     self._dictionaries_manager.unload_outdated()
     self._set_dictionaries([
         d for d in self._dictionaries.dicts
         if d.path in config_dictionaries and \
            d.path in self._dictionaries_manager
     ])
     # And then (re)load all dictionaries.
     dictionaries = []
     for result in self._dictionaries_manager.load(
             config_dictionaries.keys()):
         if isinstance(result, DictionaryLoaderException):
             d = ErroredDictionary(result.path, result.exception)
             # Only show an error if it's new.
             if d != self._dictionaries.get(result.path):
                 log.error('loading dictionary `%s` failed: %s',
                           shorten_path(result.path), str(result.exception))
         else:
             d = result
         d.enabled = config_dictionaries[d.path].enabled
         dictionaries.append(d)
     self._set_dictionaries(dictionaries)
Example #40
0
# Copyright (c) 2013 Hesky Fisher
# See LICENSE.txt for details.

"Manager for stenotype machines types."

from plover.machine.geminipr import Stenotype as geminipr
from plover.machine.txbolt import Stenotype as txbolt
from plover.machine.sidewinder import Stenotype as sidewinder
from plover.machine.stentura import Stenotype as stentura
from plover.machine.passport import Stenotype as passport
from plover import log

try:
    from plover.machine.treal import Stenotype as treal
except Exception as e:
    log.info("Unable to use Treal on this machine: %s", str(e))
    treal = None


class NoSuchMachineException(Exception):
    def __init__(self, id):
        self._id = id

    def __str__(self):
        return "Unrecognized machine type: {}".format(self._id)


class Registry(object):
    def __init__(self):
        self._machines = {}
        self._aliases = {}
Example #41
0
def main():
    """Launch plover."""
    description = "Run the plover stenotype engine. This is a graphical application."
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('--version',
                        action='version',
                        version='%s %s' %
                        (__software_name__.capitalize(), __version__))
    parser.add_argument(
        '-s',
        '--script',
        default=None,
        nargs=argparse.REMAINDER,
        help='use another plugin console script as main entrypoint, '
        'passing in the rest of the command line arguments, '
        'print list of available scripts when no argument is given')
    parser.add_argument('-l',
                        '--log-level',
                        choices=['debug', 'info', 'warning', 'error'],
                        default=None,
                        help='set log level')
    parser.add_argument('-g', '--gui', default=None, help='set gui')
    args = parser.parse_args(args=sys.argv[1:])
    if args.log_level is not None:
        log.set_level(args.log_level.upper())
    log.setup_platform_handler()

    log.info('Plover %s', __version__)
    log.info('configuration directory: %s', CONFIG_DIR)
    log.info('plugins directory: %s', PLUGINS_DIR)

    registry.update()

    if args.gui is None:
        gui_priority = {
            'qt': 1,
            'none': -1,
        }
        gui_list = sorted(registry.list_plugins('gui'),
                          reverse=True,
                          key=lambda gui: gui_priority.get(gui.name, 0))
        gui = gui_list[0].obj
    else:
        gui = registry.get_plugin('gui', args.gui).obj

    try:
        if args.script is not None:
            if args.script:
                # Create a mapping of available console script,
                # with the following priorities (highest first):
                # - {project_name}-{version}:{script_name}
                # - {project_name}:{script_name}
                # - {script_name}
                console_scripts = {}
                for e in sorted(
                        pkg_resources.iter_entry_points('console_scripts'),
                        key=lambda e: (e.dist, e.name)):
                    for key in (
                            '%s-%s:%s' %
                        (e.dist.project_name, e.dist.version, e.name),
                            '%s:%s' % (e.dist.project_name, e.name),
                            e.name,
                    ):
                        console_scripts[key] = e
                entrypoint = console_scripts.get(args.script[0])
                if entrypoint is None:
                    log.error('no such script: %s', args.script[0])
                    code = 1
                else:
                    sys.argv = args.script
                    try:
                        code = entrypoint.load()()
                    except SystemExit as e:
                        code = e.code
                if code is None:
                    code = 0
            else:
                print('available script(s):')
                dist = None
                for e in sorted(
                        pkg_resources.iter_entry_points('console_scripts'),
                        key=lambda e: (str(e.dist), e.name)):
                    if dist != e.dist:
                        dist = e.dist
                        print('%s:' % dist)
                    print('- %s' % e.name)
                code = 0
            os._exit(code)

        # Ensure only one instance of Plover is running at a time.
        with plover.oslayer.processlock.PloverLock():
            if sys.platform.startswith('darwin'):
                appnope.nope()
            init_config_dir()
            # This must be done after calling init_config_dir, so
            # Plover's configuration directory actually exists.
            log.setup_logfile()
            config = Config()
            config.target_file = CONFIG_FILE
            code = gui.main(config)
            with open(config.target_file, 'wb') as f:
                config.save(f)
    except plover.oslayer.processlock.LockNotAcquiredException:
        gui.show_error('Error',
                       'Another instance of Plover is already running.')
        code = 1
    except:
        gui.show_error('Unexpected error', traceback.format_exc())
        code = 2
    if code == -1:
        # Restart.
        args = sys.argv[:]
        if args[0].endswith('.py') or args[0].endswith('.pyc'):
            # We're running from source.
            assert args[0] == __file__
            args[0:1] = [sys.executable, '-m', __spec__.name]
        # Execute atexit handlers.
        atexit._run_exitfuncs()
        if sys.platform.startswith('win32'):
            # Workaround https://bugs.python.org/issue19066
            subprocess.Popen(args, cwd=os.getcwd())
            code = 0
        else:
            os.execv(args[0], args)
    os._exit(code)
Example #42
0
 def _update(self, config_update=None, full=False, reset_machine=False):
     original_config = self._config.as_dict()
     # Update configuration.
     if config_update is not None:
         self._config.update(**config_update)
         config = self._config.as_dict()
     else:
         config = original_config
     # Create configuration update.
     if full:
         config_update = config
     else:
         config_update = {
             option: value
             for option, value in config.items()
             if value != original_config[option]
         }
         if 'machine_type' in config_update:
             for opt in (
                     'machine_specific_options',
                     'system_keymap',
             ):
                 config_update[opt] = config[opt]
     # Update logging.
     log.set_stroke_filename(config['log_file_name'])
     log.enable_stroke_logging(config['enable_stroke_logging'])
     log.enable_translation_logging(config['enable_translation_logging'])
     # Update output.
     self._formatter.set_space_placement(config['space_placement'])
     self._formatter.start_attached = config['start_attached']
     self._formatter.start_capitalized = config['start_capitalized']
     self._translator.set_min_undo_length(config['undo_levels'])
     # Update system.
     system_name = config['system_name']
     if system.NAME != system_name:
         log.info('loading system: %s', system_name)
         system.setup(system_name)
     # Update machine.
     update_keymap = False
     start_machine = False
     machine_params = MachineParams(config['machine_type'],
                                    config['machine_specific_options'],
                                    config['system_keymap'])
     if reset_machine or machine_params != self._machine_params:
         if self._machine is not None:
             self._machine.stop_capture()
             self._machine = None
         machine_type = config['machine_type']
         machine_options = config['machine_specific_options']
         try:
             machine_class = registry.get_plugin('machine',
                                                 machine_type).resolve()
         except Exception as e:
             raise InvalidConfigurationError(str(e))
         log.info('setting machine: %s', machine_type)
         self._machine = machine_class(machine_options)
         self._machine.set_suppression(self._is_running)
         self._machine.add_state_callback(self._machine_state_callback)
         self._machine.add_stroke_callback(self._machine_stroke_callback)
         self._machine_params = machine_params
         update_keymap = True
         start_machine = True
     elif self._machine is not None:
         update_keymap = 'system_keymap' in config_update
     if update_keymap:
         machine_keymap = config['system_keymap']
         if machine_keymap is not None:
             self._machine.set_keymap(machine_keymap)
     if start_machine:
         self._machine.start_capture()
     # Update dictionaries.
     dictionaries_files = config['dictionary_file_names']
     copy_default_dictionaries(dictionaries_files)
     dictionaries = self._dictionaries_manager.load(dictionaries_files)
     self._dictionaries.set_dicts(dictionaries)
     # Trigger `config_changed` hook.
     if config_update:
         self._trigger_hook('config_changed', config_update)
Example #43
0
 def _update(self, config_update=None, full=False, reset_machine=False):
     original_config = self._config.as_dict()
     # Update configuration.
     if config_update is not None:
         self._config.update(**config_update)
         config = self._config.as_dict()
     else:
         config = original_config
     # Create configuration update.
     if full:
         config_update = config
     else:
         config_update = {
             option: value
             for option, value in config.items()
             if value != original_config[option]
         }
         if 'machine_type' in config_update:
             for opt in (
                 'machine_specific_options',
                 'system_keymap',
             ):
                 config_update[opt] = config[opt]
     # Update logging.
     log.set_stroke_filename(config['log_file_name'])
     log.enable_stroke_logging(config['enable_stroke_logging'])
     log.enable_translation_logging(config['enable_translation_logging'])
     # Update output.
     self._formatter.set_space_placement(config['space_placement'])
     self._formatter.start_attached = config['start_attached']
     self._formatter.start_capitalized = config['start_capitalized']
     self._translator.set_min_undo_length(config['undo_levels'])
     # Update system.
     system_name = config['system_name']
     if system.NAME != system_name:
         log.info('loading system: %s', system_name)
         system.setup(system_name)
     # Update machine.
     update_keymap = False
     start_machine = False
     machine_params = MachineParams(config['machine_type'],
                                    config['machine_specific_options'],
                                    config['system_keymap'])
     # Do not reset if only the keymap changed.
     if self._machine_params is None or \
        self._machine_params.type != machine_params.type or \
        self._machine_params.options != machine_params.options:
         reset_machine = True
     if reset_machine:
         if self._machine is not None:
             self._machine.stop_capture()
             self._machine = None
         machine_type = config['machine_type']
         machine_options = config['machine_specific_options']
         try:
             machine_class = registry.get_plugin('machine', machine_type).obj
         except Exception as e:
             raise InvalidConfigurationError(str(e))
         log.info('setting machine: %s', machine_type)
         self._machine = machine_class(machine_options)
         self._machine.set_suppression(self._is_running)
         self._machine.add_state_callback(self._machine_state_callback)
         self._machine.add_stroke_callback(self._machine_stroke_callback)
         self._machine_params = machine_params
         update_keymap = True
         start_machine = True
     elif self._machine is not None:
         update_keymap = 'system_keymap' in config_update
     if update_keymap:
         machine_keymap = config['system_keymap']
         if machine_keymap is not None:
             self._machine.set_keymap(machine_keymap)
     if start_machine:
         self._machine.start_capture()
     # Update running extensions.
     enabled_extensions = config['enabled_extensions']
     running_extensions = set(self._running_extensions)
     self._stop_extensions(running_extensions - enabled_extensions)
     self._start_extensions(enabled_extensions - running_extensions)
     # Trigger `config_changed` hook.
     if config_update:
         self._trigger_hook('config_changed', config_update)
     # Update dictionaries.
     config_dictionaries = OrderedDict(
         (d.path, d)
         for d in config['dictionaries']
     )
     copy_default_dictionaries(config_dictionaries.keys())
     # Start by unloading outdated dictionaries.
     self._dictionaries_manager.unload_outdated()
     self._set_dictionaries([
         d for d in self._dictionaries.dicts
         if d.path in config_dictionaries and \
            d.path in self._dictionaries_manager
     ])
     # And then (re)load all dictionaries.
     dictionaries = []
     for result in self._dictionaries_manager.load(config_dictionaries.keys()):
         if isinstance(result, DictionaryLoaderException):
             d = ErroredDictionary(result.path, result.exception)
             # Only show an error if it's new.
             if d != self._dictionaries.get(result.path):
                 log.error('loading dictionary `%s` failed: %s',
                           shorten_path(result.path), str(result.exception))
         else:
             d = result
         d.enabled = config_dictionaries[d.path].enabled
         dictionaries.append(d)
     self._set_dictionaries(dictionaries)
# See LICENSE.txt for details.

"Manager for stenotype machines types."

from plover.machine.geminipr import Stenotype as geminipr
from plover.machine.txbolt import Stenotype as txbolt
from plover.machine.sidewinder import Stenotype as sidewinder
from plover.machine.stentura import Stenotype as stentura
from plover.machine.stenturait import StenotypeIT as stenturait
from plover.machine.passport import Stenotype as passport
from plover import log

try:
    from plover.machine.treal import Stenotype as treal
except Exception as e:
    log.info('Unable to use Treal on this machine: %s', str(e))
    treal = None


class NoSuchMachineException(Exception):
    def __init__(self, id):
        self._id = id

    def __str__(self):
        return 'Unrecognized machine type: {}'.format(self._id)


class Registry(object):
    def __init__(self):
        self._machines = {}
        self._aliases = {}
Example #45
0
 def _stop_extensions(self, extension_list):
     for extension_name in list(extension_list):
         log.info('stopping `%s` extension', extension_name)
         extension = self._running_extensions.pop(extension_name)
         extension.stop()
         del extension
Example #46
0
 def layoutChanged_(self, event):
     log.info('Mac keyboard layout changed, updating')
     layout._update_layout()
Example #47
0
def install_gettext():
    lang = get_language()
    log.info('setting language to: %s', lang)
    os.environ['LANGUAGE'] = lang
    locale_dir = pkg_resources.resource_filename('plover', 'gui_qt/messages')
    gettext.install('plover', locale_dir)
Example #48
0
def main():
    """Launch plover."""
    description = "Run the plover stenotype engine. This is a graphical application."
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('--version', action='version', version='%s %s'
                        % (__software_name__.capitalize(), __version__))
    parser.add_argument('-s', '--script', default=None, nargs=argparse.REMAINDER,
                        help='use another plugin console script as main entrypoint, '
                        'passing in the rest of the command line arguments, '
                        'print list of available scripts when no argument is given')
    parser.add_argument('-l', '--log-level', choices=['debug', 'info', 'warning', 'error'],
                        default=None, help='set log level')
    parser.add_argument('-g', '--gui', default=None, help='set gui')
    args = parser.parse_args(args=sys.argv[1:])
    if args.log_level is not None:
        log.set_level(args.log_level.upper())
    log.setup_platform_handler()

    log.info('Plover %s', __version__)
    log.info('configuration directory: %s', CONFIG_DIR)

    registry.update()

    if args.gui is None:
        gui_priority = {
            'qt': 1,
            'none': -1,
        }
        gui_list = sorted(registry.list_plugins('gui'), reverse=True,
                          key=lambda gui: gui_priority.get(gui.name, 0))
        gui = gui_list[0].obj
    else:
        gui = registry.get_plugin('gui', args.gui).obj

    try:
        if args.script is not None:
            if args.script:
                # Create a mapping of available console script,
                # with the following priorities (highest first):
                # - {project_name}-{version}:{script_name}
                # - {project_name}:{script_name}
                # - {script_name}
                console_scripts = {}
                for e in sorted(pkg_resources.iter_entry_points('console_scripts'),
                                key=lambda e: (e.dist, e.name)):
                    for key in (
                        '%s-%s:%s' % (e.dist.project_name, e.dist.version, e.name),
                        '%s:%s' % (e.dist.project_name, e.name),
                        e.name,
                    ):
                        console_scripts[key] = e
                entrypoint = console_scripts.get(args.script[0])
                if entrypoint is None:
                    log.error('no such script: %s', args.script[0])
                    code = 1
                else:
                    sys.argv = args.script
                    try:
                        code = entrypoint.load()()
                    except SystemExit as e:
                        code = e.code
                if code is None:
                    code = 0
            else:
                print('available script(s):')
                dist = None
                for e in sorted(pkg_resources.iter_entry_points('console_scripts'),
                                key=lambda e: (str(e.dist), e.name)):
                    if dist != e.dist:
                        dist = e.dist
                        print('%s:' % dist)
                    print('- %s' % e.name)
                code = 0
            os._exit(code)

        # Ensure only one instance of Plover is running at a time.
        with processlock.PloverLock():
            if sys.platform.startswith('darwin'):
                appnope.nope()
            init_config_dir()
            # This must be done after calling init_config_dir, so
            # Plover's configuration directory actually exists.
            log.setup_logfile()
            config = Config()
            config.target_file = CONFIG_FILE
            code = gui.main(config)
            with open(config.target_file, 'wb') as f:
                config.save(f)
    except processlock.LockNotAcquiredException:
        gui.show_error('Error', 'Another instance of Plover is already running.')
        code = 1
    except:
        gui.show_error('Unexpected error', traceback.format_exc())
        code = 2
    if code == -1:
        # Restart.
        args = sys.argv[:]
        if args[0].endswith('.py') or args[0].endswith('.pyc'):
            # We're running from source.
            assert args[0] == __file__
            args[0:1] = [sys.executable, '-m', __spec__.name]
        # Execute atexit handlers.
        atexit._run_exitfuncs()
        if sys.platform.startswith('win32'):
            # Workaround https://bugs.python.org/issue19066
            subprocess.Popen(args, cwd=os.getcwd())
            code = 0
        else:
            os.execv(args[0], args)
    os._exit(code)