Esempio n. 1
0
 def test_pluginmanager(self):
     plugin.SpreadsNamedExtensionManager = Mock()
     pm = plugin.get_pluginmanager()
     assert plugin.SpreadsNamedExtensionManager.call_count == 1
     assert plugin.SpreadsNamedExtensionManager.call_args_list == ([call(
         invoke_on_load=True, namespace=u'spreadsplug.hooks', names=[],
         name_order=True, invoke_args=[spreads.config])])
     pm_new = plugin.get_pluginmanager()
     assert plugin.SpreadsNamedExtensionManager.call_count == 1
     assert pm is pm_new
Esempio n. 2
0
def download(devices, path):
    if not devices:
        raise DeviceException("Could not find any compatible devices!")
    keep = config['download']['keep'].get(bool) or config['keep'].get(bool)
    if config['parallel_download'].get(bool):
        num_devices = len(devices)
    else:
        num_devices = 1
    logger.info("Downloading images from devices to {0}, files will "
                "{1} remain on the devices."
                .format(path, ("not" if not keep else "")))
    if not os.path.exists(path):
        logger.debug("Creating project directory")
        os.mkdir(path)
    out_paths = [os.path.join(path, x.orientation) for x in devices]
    if out_paths:
        logger.debug("Creating camera directories")

    # Flag for when the images are already present
    skip_download = False
    for subpath in out_paths:
        if not os.path.exists(subpath):
            os.mkdir(subpath)
        else:
            logger.info("Images already present, skipping download")
            skip_download = True
    if not skip_download:
        with ThreadPoolExecutor(num_devices) as executor:
            logger.debug("Starting download process")
            futures = []
            for dev in devices:
                futures.append(executor.submit(
                    dev.download_files,
                    os.path.join(path, dev.orientation))
                )
        if any(x.exception() for x in futures):
            exc = next(x for x in futures if x.exception()).exception()
            raise exc
    logger.debug("Running download hooks")
    for ext in get_pluginmanager():
        ext.obj.download(devices, path)
    # NOTE: Just to be safe...
    time.sleep(5)
    if not keep:
        logger.info("Deleting images from devices")
        with ThreadPoolExecutor(num_devices) as executor:
            logger.debug("Starting delete process")
            for dev in devices:
                executor.submit(dev.delete_files)
        logger.debug("Running delete hooks")
        for ext in get_pluginmanager():
            ext.obj.delete(devices)
Esempio n. 3
0
def download(devices, path):
    if not devices:
        raise DeviceException("Could not find any compatible devices!")
    keep = config['download']['keep'].get(bool) or config['keep'].get(bool)
    if config['parallel_download'].get(bool):
        num_devices = len(devices)
    else:
        num_devices = 1
    logger.info("Downloading images from devices to {0}, files will "
                "{1} remain on the devices.".format(
                    path, ("not" if not keep else "")))
    if not os.path.exists(path):
        logger.debug("Creating project directory")
        os.mkdir(path)
    out_paths = [os.path.join(path, x.orientation) for x in devices]
    if out_paths:
        logger.debug("Creating camera directories")

    # Flag for when the images are already present
    skip_download = False
    for subpath in out_paths:
        if not os.path.exists(subpath):
            os.mkdir(subpath)
        else:
            logger.info("Images already present, skipping download")
            skip_download = True
    if not skip_download:
        with ThreadPoolExecutor(num_devices) as executor:
            logger.debug("Starting download process")
            futures = []
            for dev in devices:
                futures.append(
                    executor.submit(dev.download_files,
                                    os.path.join(path, dev.orientation)))
        if any(x.exception() for x in futures):
            exc = next(x for x in futures if x.exception()).exception()
            raise exc
    logger.debug("Running download hooks")
    for ext in get_pluginmanager():
        ext.obj.download(devices, path)
    # NOTE: Just to be safe...
    time.sleep(5)
    if not keep:
        logger.info("Deleting images from devices")
        with ThreadPoolExecutor(num_devices) as executor:
            logger.debug("Starting delete process")
            for dev in devices:
                executor.submit(dev.delete_files)
        logger.debug("Running delete hooks")
        for ext in get_pluginmanager():
            ext.obj.delete(devices)
Esempio n. 4
0
 def test_pluginmanager(self):
     plugin.SpreadsNamedExtensionManager = Mock()
     pm = plugin.get_pluginmanager()
     assert plugin.SpreadsNamedExtensionManager.call_count == 1
     assert plugin.SpreadsNamedExtensionManager.call_args_list == ([
         call(invoke_on_load=True,
              namespace=u'spreadsplug.hooks',
              names=[],
              name_order=True,
              invoke_args=[spreads.config])
     ])
     pm_new = plugin.get_pluginmanager()
     assert plugin.SpreadsNamedExtensionManager.call_count == 1
     assert pm is pm_new
Esempio n. 5
0
def test_get_relevant_extensions(mock_plugin_mgr):
    plugin_manager = plugin.get_pluginmanager()
    exts = list(plugin.get_relevant_extensions(
        plugin_manager, [plugin.ProcessHookMixin]))
    assert len(exts) == 2
    assert exts[0].name == "test_process"
    assert exts[1].name == "test_process2"
Esempio n. 6
0
 def doDownload(self):
     with ThreadPoolExecutor(max_workers=1) as executor:
         future = executor.submit(workflow.download,
                                  self.wizard().selected_devices,
                                  self.wizard().project_path)
         while future.running():
             QtGui.qApp.processEvents()
             self.progressbar.setValue(1)
             time.sleep(0.001)
         if future.exception():
             raise future.exception()
     self.progressbar.hide()
     if ('combine' in self.wizard().active_plugins and not
             os.listdir(os.path.join(self.wizard().project_path, 'raw'))):
         msg_box = QtGui.QMessageBox()
         msg_box.setText("It seems that combining the images has failed."
                         "Please fix the issue manually and retry.")
         # TODO: Add a 'combine' button to retry combining.
         msg_box.setIcon(QtGui.QMessageBox.Critical)
         self.combine_btn = msg_box.addButton("Combine",
                                              QtGui.QMessageBox.ApplyRole)
         self.combine_btn.clicked.connect(get_pluginmanager()['combine']
                                          .download(self.wizard()
                                          .project_path))
         msg_box.exec_()
Esempio n. 7
0
 def doDownload(self):
     with ThreadPoolExecutor(max_workers=1) as executor:
         future = executor.submit(workflow.download,
                                  self.wizard().selected_devices,
                                  self.wizard().project_path)
         while future.running():
             QtGui.qApp.processEvents()
             self.progressbar.setValue(1)
             time.sleep(0.001)
         if future.exception():
             raise future.exception()
     self.progressbar.hide()
     if ('combine' in self.wizard().active_plugins and not os.listdir(
             os.path.join(self.wizard().project_path, 'raw'))):
         msg_box = QtGui.QMessageBox()
         msg_box.setText("It seems that combining the images has failed."
                         "Please fix the issue manually and retry.")
         # TODO: Add a 'combine' button to retry combining.
         msg_box.setIcon(QtGui.QMessageBox.Critical)
         self.combine_btn = msg_box.addButton("Combine",
                                              QtGui.QMessageBox.ApplyRole)
         self.combine_btn.clicked.connect(
             get_pluginmanager()['combine'].download(
                 self.wizard().project_path))
         msg_box.exec_()
Esempio n. 8
0
    def initializePage(self):
        wizard = self.wizard()
        self.pluginmanager = get_pluginmanager(wizard.config)
        wizard.active_plugins = self.pluginmanager.names()
        self.setTitle("Welcome!")

        intro_label = QtGui.QLabel(
            "This wizard will guide you through the digitization workflow. "
        )
        intro_label.setWordWrap(True)

        dirpick_layout = QtGui.QHBoxLayout()
        self.line_edit = QtGui.QLineEdit()
        self.line_edit.textChanged.connect(self.completeChanged)
        browse_btn = QtGui.QPushButton("Browse")
        dirpick_layout.addWidget(self.line_edit)
        dirpick_layout.addWidget(browse_btn)
        browse_btn.clicked.connect(self.show_filepicker)

        self.stack_widget = QtGui.QStackedWidget()
        page_combobox = QtGui.QComboBox()
        page_combobox.activated.connect(self.stack_widget.setCurrentIndex)
        #QtCore.QObject.connect(page_combobox, SIGNAL("activated(int)"),
        #        self.stack_widget, SLOT("setCurrentIndex(int)"))

        # Add configuration widgets from plugins
        self.plugin_widgets = {}
        for ext in self.pluginmanager:
            tmpl = ext.plugin.configuration_template()
            if not tmpl:
                continue
            page = QtGui.QGroupBox()
            layout = QtGui.QFormLayout()
            widgets = self._get_plugin_config_widgets(tmpl)
            self.plugin_widgets[ext.name] = widgets
            for label, widget in widgets.values():
                # We don't need a label for QCheckBoxes
                if isinstance(widget, QtGui.QCheckBox):
                    layout.addRow(widget)
                else:
                    layout.addRow(label, widget)
            page.setLayout(layout)
            self.stack_widget.addWidget(page)
            page_combobox.addItem(ext.name.title())

        main_layout = QtGui.QVBoxLayout()
        main_layout.addWidget(intro_label)
        main_layout.addSpacing(30)
        main_layout.addWidget(
            QtGui.QLabel("Please select a project directory.")
        )
        main_layout.addLayout(dirpick_layout)
        main_layout.addSpacing(30)
        main_layout.addWidget(page_combobox)
        main_layout.addWidget(self.stack_widget)
        main_layout.setSizeConstraint(QtGui.QLayout.SetNoConstraint)

        self.setLayout(main_layout)
        self.adjustSize()
Esempio n. 9
0
def output(path):
    logger.info("Generating output files...")
    logger.debug("Running output hooks")
    out_path = os.path.join(path, 'out')
    if not os.path.exists(out_path):
        os.mkdir(out_path)
    for ext in get_pluginmanager():
        ext.obj.output(path)
    logger.info("Done generating output files!")
Esempio n. 10
0
def output(path):
    logger.info("Generating output files...")
    logger.debug("Running output hooks")
    out_path = os.path.join(path, 'out')
    if not os.path.exists(out_path):
        os.mkdir(out_path)
    for ext in get_pluginmanager():
        ext.obj.output(path)
    logger.info("Done generating output files!")
Esempio n. 11
0
def capture(devices):
    logger.info("Triggering capture.")
    with ThreadPoolExecutor(len(devices)) as executor:
        futures = []
        logger.debug("Sending capture command to devices")
        for dev in devices:
            futures.append(executor.submit(dev.capture))
    if any(x.exception() for x in futures):
        exc = next(x for x in futures if x.exception()).exception()
        raise exc
    logger.debug("Running capture hooks")
    for ext in get_pluginmanager():
        ext.obj.capture(devices)
Esempio n. 12
0
def prepare_capture(devices):
    logger.debug("Preparing capture.")
    with ThreadPoolExecutor(len(devices)) as executor:
        futures = []
        logger.debug("Preparing capture in devices")
        for dev in devices:
            futures.append(executor.submit(dev.prepare_capture))
    if any(x.exception() for x in futures):
        exc = next(x for x in futures if x.exception()).exception()
        raise exc
    for ext in get_pluginmanager():
        logger.debug("Running prepare_capture hooks")
        ext.obj.prepare_capture(devices)
Esempio n. 13
0
def prepare_capture(devices):
    logger.debug("Preparing capture.")
    with ThreadPoolExecutor(len(devices)) as executor:
        futures = []
        logger.debug("Preparing capture in devices")
        for dev in devices:
            futures.append(executor.submit(dev.prepare_capture))
    if any(x.exception() for x in futures):
        exc = next(x for x in futures if x.exception()).exception()
        raise exc
    for ext in get_pluginmanager():
        logger.debug("Running prepare_capture hooks")
        ext.obj.prepare_capture(devices)
Esempio n. 14
0
def capture(devices):
    logger.info("Triggering capture.")
    with ThreadPoolExecutor(len(devices)) as executor:
        futures = []
        logger.debug("Sending capture command to devices")
        for dev in devices:
            futures.append(executor.submit(dev.capture))
    if any(x.exception() for x in futures):
        exc = next(x for x in futures if x.exception()).exception()
        raise exc
    logger.debug("Running capture hooks")
    for ext in get_pluginmanager():
        ext.obj.capture(devices)
Esempio n. 15
0
def _setup_processing_pipeline(config):
    pm = get_pluginmanager(config)
    extensions = [ext.name for ext in get_relevant_extensions(pm, ['process'])]
    print("The following postprocessing plugins were detected:")
    print("\n".join(" - {0}".format(ext) for ext in extensions))
    while True:
        answer = raw_input("Please enter the extensions in the order that they"
                           " should be invoked, separated by commas:\n")
        plugins = [x.strip() for x in answer.split(',')]
        if any(x not in extensions for x in plugins):
            print(colorize("At least one of the entered extensions was not"
                           "found, please try again!", colorama.Fore.RED))
        else:
            break
    config["plugins"] = plugins + [x for x in config["plugins"].get()
                                   if x not in plugins]
Esempio n. 16
0
def capture(devices):
    logger.info("Triggering capture.")
    if not devices:
        raise DeviceException("Could not find any compatible devices!")
    if config['parallel_capture'].get(bool):
        num_devices = len(devices)
    else:
        num_devices = 1
    with ThreadPoolExecutor(num_devices) as executor:
        futures = []
        logger.debug("Sending capture command to devices")
        for dev in devices:
            futures.append(executor.submit(dev.capture))
    if any(x.exception() for x in futures):
        exc = next(x for x in futures if x.exception()).exception()
        raise exc
    logger.debug("Running capture hooks")
    for ext in get_pluginmanager():
        ext.obj.capture(devices)
Esempio n. 17
0
def capture(devices):
    logger.info("Triggering capture.")
    if not devices:
        raise DeviceException("Could not find any compatible devices!")
    if config['parallel_capture'].get(bool):
        num_devices = len(devices)
    else:
        num_devices = 1
    with ThreadPoolExecutor(num_devices) as executor:
        futures = []
        logger.debug("Sending capture command to devices")
        for dev in devices:
            futures.append(executor.submit(dev.capture))
    if any(x.exception() for x in futures):
        exc = next(x for x in futures if x.exception()).exception()
        raise exc
    logger.debug("Running capture hooks")
    for ext in get_pluginmanager():
        ext.obj.capture(devices)
Esempio n. 18
0
def capture(devices):
    logger.info("Triggering capture.")
    if config['parallel_capture'].get(bool):
        num_devices = len(devices)
    else:
        num_devices = 1
    with ThreadPoolExecutor(num_devices) as executor:
        futures = []
        logger.debug("Sending capture command to devices")
        for dev in devices:
            futures.append(executor.submit(dev.capture))
            # NOTE: Wait before triggering the next camera, as triggering
            #       at the same time seems to be problematic...
            time.sleep(0.25)
    if any(x.exception() for x in futures):
        exc = next(x for x in futures if x.exception()).exception()
        raise exc
    logger.debug("Running capture hooks")
    for ext in get_pluginmanager():
        ext.obj.capture(devices)
Esempio n. 19
0
def capture(devices):
    logger.info("Triggering capture.")
    if config['parallel_capture'].get(bool):
        num_devices = len(devices)
    else:
        num_devices = 1
    with ThreadPoolExecutor(num_devices) as executor:
        futures = []
        logger.debug("Sending capture command to devices")
        for dev in devices:
            futures.append(executor.submit(dev.capture))
            # NOTE: Wait before triggering the next camera, as triggering      
            #       at the same time seems to be problematic...  
            time.sleep(0.25)
    if any(x.exception() for x in futures):
        exc = next(x for x in futures if x.exception()).exception()
        raise exc
    logger.debug("Running capture hooks")
    for ext in get_pluginmanager():
        ext.obj.capture(devices)
Esempio n. 20
0
def setup_parser():
    def _add_device_arguments(name, parser):
        try:
            for dev in get_devices():
                dev.add_arguments(name, parser)
        except:
            return

    pluginmanager = get_pluginmanager()
    rootparser = argparse.ArgumentParser(
        description="Scanning Tool for  DIY Book Scanner")
    subparsers = rootparser.add_subparsers()

    rootparser.add_argument('--verbose',
                            '-v',
                            dest="verbose",
                            action="store_true")

    wizard_parser = subparsers.add_parser('wizard', help="Interactive mode")
    wizard_parser.add_argument(
        "path", help="Path where scanned images are to be stored")
    wizard_parser.set_defaults(func=wizard)

    config_parser = subparsers.add_parser(
        'configure', help="Perform initial configuration of the devices.")
    config_parser.set_defaults(func=configure)

    capture_parser = subparsers.add_parser('capture',
                                           help="Start the capturing workflow")
    capture_parser.set_defaults(func=capture)
    # Add arguments from plugins
    for parser in (capture_parser, wizard_parser):
        pluginmanager.map(lambda x, y, z: x.plugin.add_arguments(y, z),
                          'capture', parser)
        _add_device_arguments('capture', parser)

    download_parser = subparsers.add_parser('download',
                                            help="Download scanned images.")
    download_parser.add_argument(
        "path", help="Path where scanned images are to be stored")
    for subparser in (download_parser, wizard_parser):
        subparser.add_argument("--keep",
                               "-k",
                               dest="keep",
                               action="store_true",
                               help="Keep files on devices after download")
    download_parser.set_defaults(func=download)
    # Add arguments from plugins
    for parser in (download_parser, wizard_parser):
        pluginmanager.map(lambda x, y, z: x.plugin.add_arguments(y, z),
                          'download', parser)
        _add_device_arguments('download', parser)

    postprocess_parser = subparsers.add_parser(
        'postprocess', help="Postprocess scanned images.")
    postprocess_parser.add_argument(
        "path", help="Path where scanned images are stored")
    postprocess_parser.add_argument("--jobs",
                                    "-j",
                                    dest="jobs",
                                    type=int,
                                    default=None,
                                    metavar="<int>",
                                    help="Number of concurrent processes")
    postprocess_parser.set_defaults(func=postprocess)
    # Add arguments from plugins
    for parser in (download_parser, wizard_parser):
        pluginmanager.map(lambda x, y, z: x.plugin.add_arguments(y, z),
                          'postprocess', parser)

    output_parser = subparsers.add_parser('output',
                                          help="Generate output files.")
    output_parser.add_argument(
        "path", help="Path where scanned and postprocessed images are stored")
    output_parser.set_defaults(func=output)
    # Add arguments from plugins
    for parser in (download_parser, wizard_parser):
        pluginmanager.map(lambda x, y, z: x.plugin.add_arguments(y, z),
                          'output', parser)

    pluginmanager.map(lambda x, y: x.plugin.add_command_parser(y), subparsers)
    return rootparser
Esempio n. 21
0
def finish_capture(devices):
    logger.debug("Running finish_capture hooks")
    if not devices:
        raise DeviceException("Could not find any compatible devices!")
    for ext in get_pluginmanager():
        ext.obj.finish_capture(devices)
Esempio n. 22
0
def finish_capture(devices):
    logger.debug("Running finish_capture hooks")
    if not devices:
        raise DeviceException("Could not find any compatible devices!")
    for ext in get_pluginmanager():
        ext.obj.finish_capture(devices)
Esempio n. 23
0
def setup_parser(config):
    def _add_argument_from_option(extname, key, option, parser):
        flag = "--{0}".format(key.replace('_', '-'))
        default = (option.value
                   if not option.selectable
                   else option.value[0])
        kwargs = {'help': ("{0} [default: {1}]"
                           .format(option.docstring, default)),
                  'dest': "{0}.{1}".format(extname, key)}
        if isinstance(option.value, basestring):
            kwargs['type'] = unicode
            kwargs['metavar'] = "<str>"
        elif isinstance(option.value, bool):
            kwargs['help'] = option.docstring
            if option.value:
                flag = "--no-{0}".format(key.replace('_', '-'))
                kwargs['help'] = ("Disable {0}"
                                  .format(option.docstring.lower()))
                kwargs['action'] = "store_false"
            else:
                kwargs['action'] = "store_true"
        elif isinstance(option.value, float):
            kwargs['type'] = float
            kwargs['metavar'] = "<float>"
        elif isinstance(option.value, int):
            kwargs['type'] = int
            kwargs['metavar'] = "<int>"
        elif option.selectable:
            kwargs['type'] = type(option.value[0])
            kwargs['metavar'] = "<{0}>".format("/".join(option.value))
            kwargs['choices'] = option.value
        else:
            raise TypeError("Unsupported option type")
        parser.add_argument(flag, **kwargs)

    def _add_device_arguments(name, parser):
        tmpl = get_driver(config["driver"]
                          .get()).driver.configuration_template()
        if not tmpl:
            return
        for key, option in tmpl.iteritems():
            try:
                _add_argument_from_option('device', key, option, parser)
            except:
                return

    def _add_plugin_arguments(hooks, parser):
        extensions = get_relevant_extensions(pluginmanager, hooks)
        for ext in extensions:
            tmpl = ext.plugin.configuration_template()
            if not tmpl:
                continue
            for key, option in tmpl.iteritems():
                try:
                    _add_argument_from_option(ext.name, key, option, parser)
                except:
                    continue

    pluginmanager = get_pluginmanager(config)
    rootparser = argparse.ArgumentParser(
        description="Scanning Tool for  DIY Book Scanner")
    subparsers = rootparser.add_subparsers()

    rootparser.add_argument(
        '--verbose', '-v', dest="loglevel", action="store_const",
        const="debug")

    wizard_parser = subparsers.add_parser(
        'wizard', help="Interactive mode")
    wizard_parser.add_argument(
        "path", type=unicode, help="Project path")
    wizard_parser.set_defaults(subcommand=wizard)

    config_parser = subparsers.add_parser(
        'configure', help="Perform initial configuration")
    config_parser.set_defaults(subcommand=configure)

    capture_parser = subparsers.add_parser(
        'capture', help="Start the capturing workflow")
    capture_parser.add_argument(
        "path", type=unicode, help="Project path")
    capture_parser.set_defaults(subcommand=capture)
    # Add arguments from plugins
    for parser in (capture_parser, wizard_parser):
        _add_plugin_arguments(['prepare_capture', 'capture', 'finish_capture'],
                              parser)
        if 'driver' in config.keys():
            _add_device_arguments('capture', parser)

    postprocess_parser = subparsers.add_parser(
        'postprocess',
        help="Postprocess scanned images.")
    postprocess_parser.add_argument(
        "path", type=unicode, help="Project path")
    postprocess_parser.add_argument(
        "--jobs", "-j", dest="jobs", type=int, default=None,
        metavar="<int>", help="Number of concurrent processes")
    postprocess_parser.set_defaults(subcommand=postprocess)
    # Add arguments from plugins
    for parser in (postprocess_parser, wizard_parser):
        _add_plugin_arguments(['process'], parser)

    output_parser = subparsers.add_parser(
        'output',
        help="Generate output files.")
    output_parser.add_argument(
        "path", type=unicode, help="Project path")
    output_parser.set_defaults(subcommand=output)
    # Add arguments from plugins
    for parser in (output_parser, wizard_parser):
        _add_plugin_arguments(['output'], parser)

    # Add custom subcommands from plugins
    if config["plugins"].get():
        pluginmanager.map(lambda x, y: x.plugin.add_command_parser(y),
                          subparsers)
    return rootparser
Esempio n. 24
0
def process(path):
    logger.info("Starting postprocessing...")
    logger.debug("Running process hooks")
    for ext in get_pluginmanager():
        ext.obj.process(path)
    logger.info("Done with postprocessing!")
Esempio n. 25
0
def setup_parser():
    def _add_device_arguments(name, parser):
        try:
            for dev in get_devices():
                dev.add_arguments(name, parser)
        except:
            return

    pluginmanager = get_pluginmanager()
    rootparser = argparse.ArgumentParser(
        description="Scanning Tool for  DIY Book Scanner")
    subparsers = rootparser.add_subparsers()

    rootparser.add_argument(
        '--verbose', '-v', dest="verbose", action="store_true")

    wizard_parser = subparsers.add_parser(
        'wizard', help="Interactive mode")
    wizard_parser.add_argument(
        "path", help="Path where scanned images are to be stored")
    wizard_parser.set_defaults(func=wizard)

    config_parser = subparsers.add_parser(
        'configure', help="Perform initial configuration of the devices.")
    config_parser.set_defaults(func=configure)

    capture_parser = subparsers.add_parser(
        'capture', help="Start the capturing workflow")
    capture_parser.set_defaults(func=capture)
    # Add arguments from plugins
    for parser in (capture_parser, wizard_parser):
        parser.add_argument("--no-parallel-capture", dest="parallel_capture",
            action="store_false", default=True,
            help="Do not trigger capture on multiple devices at once.")
        pluginmanager.map(lambda x, y, z: x.plugin.add_arguments(y, z),
                          'capture', parser)
        _add_device_arguments('capture', parser)

    download_parser = subparsers.add_parser(
        'download', help="Download scanned images.")
    download_parser.add_argument(
        "path", help="Path where scanned images are to be stored")
    for subparser in (download_parser, wizard_parser):
        subparser.add_argument("--no-parallel-download",
            dest="parallel_download", action="store_false", default=True,
            help="Do not download from multiple devices at once.")
        subparser.add_argument(
            "--keep", "-k", dest="keep", action="store_true",
            help="Keep files on devices after download")
    download_parser.set_defaults(func=download)
    # Add arguments from plugins
    for parser in (download_parser, wizard_parser):
        pluginmanager.map(lambda x, y, z: x.plugin.add_arguments(y, z),
                          'download', parser)
        _add_device_arguments('download', parser)

    postprocess_parser = subparsers.add_parser(
        'postprocess',
        help="Postprocess scanned images.")
    postprocess_parser.add_argument(
        "path", help="Path where scanned images are stored")
    postprocess_parser.add_argument(
        "--jobs", "-j", dest="jobs", type=int, default=None,
        metavar="<int>", help="Number of concurrent processes")
    postprocess_parser.set_defaults(func=postprocess)
    # Add arguments from plugins
    for parser in (postprocess_parser, wizard_parser):
        pluginmanager.map(lambda x, y, z: x.plugin.add_arguments(y, z),
                          'postprocess', parser)

    output_parser = subparsers.add_parser(
        'output',
        help="Generate output files.")
    output_parser.add_argument(
        "path", help="Path where scanned and postprocessed images are stored")
    output_parser.set_defaults(func=output)
    # Add arguments from plugins
    for parser in (download_parser, wizard_parser):
        pluginmanager.map(lambda x, y, z: x.plugin.add_arguments(y, z),
                          'output', parser)

    pluginmanager.map(lambda x, y: x.plugin.add_command_parser(y),
                      subparsers)
    return rootparser
Esempio n. 26
0
def setup_parser(config):
    def _add_device_arguments(name, parser):
        tmpl = plugin.get_driver(config["driver"]
                                 .get()).driver.configuration_template()
        if not tmpl:
            return
        for key, option in tmpl.iteritems():
            try:
                add_argument_from_option('device', key, option, parser)
            except:
                return

    def _add_plugin_arguments(hooks, parser):
        extensions = plugin.get_relevant_extensions(pluginmanager, hooks)
        for ext in extensions:
            tmpl = ext.plugin.configuration_template()
            if not tmpl:
                continue
            for key, option in tmpl.iteritems():
                try:
                    add_argument_from_option(ext.name, key, option, parser)
                except:
                    continue

    root_options = {
        'verbose': plugin.PluginOption(value=False,
                                       docstring="Enable verbose output"),
        'logfile': plugin.PluginOption(value="~/.config/spreads/spreads.log",
                                       docstring="Path to logfile"),
        'loglevel': plugin.PluginOption(value=['info', 'critical', 'error',
                                               'warning', 'debug'],
                                        docstring="Logging level for logfile",
                                        selectable=True)
    }

    pluginmanager = plugin.get_pluginmanager(config)
    rootparser = argparse.ArgumentParser(
        description="Scanning Tool for  DIY Book Scanner")
    subparsers = rootparser.add_subparsers()
    for key, option in root_options.iteritems():
        add_argument_from_option('', key, option, rootparser)

    wizard_parser = subparsers.add_parser(
        'wizard', help="Interactive mode")
    wizard_parser.add_argument(
        "path", type=unicode, help="Project path")
    wizard_parser.set_defaults(subcommand=wizard)

    config_parser = subparsers.add_parser(
        'configure', help="Perform initial configuration")
    config_parser.set_defaults(subcommand=configure)

    capture_parser = subparsers.add_parser(
        'capture', help="Start the capturing workflow")
    capture_parser.add_argument(
        "path", type=unicode, help="Project path")
    capture_parser.set_defaults(subcommand=capture)
    # Add arguments from plugins
    for parser in (capture_parser, wizard_parser):
        _add_plugin_arguments(
            [plugin.CaptureHooksMixin, plugin.TriggerHooksMixin], parser)
        if 'driver' in config.keys():
            _add_device_arguments('capture', parser)

    postprocess_parser = subparsers.add_parser(
        'postprocess',
        help="Postprocess scanned images.")
    postprocess_parser.add_argument(
        "path", type=unicode, help="Project path")
    postprocess_parser.add_argument(
        "--jobs", "-j", dest="jobs", type=int, default=None,
        metavar="<int>", help="Number of concurrent processes")
    postprocess_parser.set_defaults(subcommand=postprocess)
    # Add arguments from plugins
    for parser in (postprocess_parser, wizard_parser):
        _add_plugin_arguments([plugin.ProcessHookMixin], parser)

    output_parser = subparsers.add_parser(
        'output',
        help="Generate output files.")
    output_parser.add_argument(
        "path", type=unicode, help="Project path")
    output_parser.set_defaults(subcommand=output)
    # Add arguments from plugins
    for parser in (output_parser, wizard_parser):
        _add_plugin_arguments([plugin.OutputHookMixin], parser)

    # Add custom subcommands from plugins
    if config["plugins"].get():
        exts = plugin.get_relevant_extensions(pluginmanager,
                                              [plugin.SubcommandHookMixin])

        for ext in exts:
            ext.plugin.add_command_parser(subparsers)
    return rootparser
Esempio n. 27
0
def finish_capture(devices):
    logger.debug("Running finish_capture hooks")
    for ext in get_pluginmanager():
        ext.obj.finish_capture(devices)
Esempio n. 28
0
 def plugins(self):
     if self._pluginmanager is None:
         self._pluginmanager = get_pluginmanager(self.config)
     return [ext.obj for ext in self._pluginmanager]
Esempio n. 29
0
    def initializePage(self):
        self.wizard().active_plugins = get_pluginmanager().names()
        self.setTitle("Welcome!")

        intro_label = QtGui.QLabel(
            "This wizard will guide you through the digitization workflow. "
        )

        dirpick_layout = QtGui.QHBoxLayout()
        self.line_edit = QtGui.QLineEdit()
        browse_btn = QtGui.QPushButton("Browse")
        dirpick_layout.addWidget(self.line_edit)
        dirpick_layout.addWidget(browse_btn)
        browse_btn.clicked.connect(self.show_filepicker)

        form_layout = QtGui.QFormLayout()

        self.keep_box = QtGui.QCheckBox("Keep files on devices")
        form_layout.addRow(self.keep_box)

        self.even_device = None
        if ('combine' in self.wizard().active_plugins
                or 'autorotate' in self.wizard().active_plugins):
            self.even_device = QtGui.QComboBox()
            self.even_device.addItem("Left")
            self.even_device.addItem("Right")
            self.even_device.setCurrentIndex(0)
            form_layout.addRow("Device for even pages", self.even_device)

        self.st_auto = None
        self.st_detection = None
        if 'scantailor' in self.wizard().active_plugins:
            self.st_auto = QtGui.QCheckBox("Don't Inspect ScanTailor"
                                           " configuration")
            form_layout.addRow(self.st_auto)
            self.st_detection = QtGui.QComboBox()
            self.st_detection.addItem("Content")
            self.st_detection.addItem("Page")
            self.st_detection.setCurrentIndex(0)
            form_layout.addRow("ScanTailor layout mode", self.st_detection)

        self.ocr_lang = None
        if 'tesseract' in self.wizard().active_plugins:
            langs = (subprocess.check_output(["tesseract", "--list-langs"],
                                             stderr=subprocess.STDOUT)
                     .split("\n")[1:-1])
            self.ocr_lang = QtGui.QComboBox()
            for lang in langs:
                self.ocr_lang.addItem(lang)
            self.ocr_lang.setCurrentIndex(0)
            form_layout.addRow("OCR language", self.ocr_lang)

        main_layout = QtGui.QVBoxLayout()
        main_layout.addWidget(intro_label)
        main_layout.addSpacing(30)
        main_layout.addWidget(
            QtGui.QLabel("Please select a project directory.")
        )
        main_layout.addLayout(dirpick_layout)
        main_layout.addSpacing(30)
        main_layout.addLayout(form_layout)

        self.setLayout(main_layout)
Esempio n. 30
0
def process(path):
    logger.info("Starting postprocessing...")
    logger.debug("Running process hooks")
    for ext in get_pluginmanager():
        ext.obj.process(path)
    logger.info("Done with postprocessing!")
Esempio n. 31
0
    def initializePage(self):
        self.wizard().active_plugins = get_pluginmanager().names()
        self.setTitle("Welcome!")

        intro_label = QtGui.QLabel(
            "This wizard will guide you through the digitization workflow. ")

        dirpick_layout = QtGui.QHBoxLayout()
        self.line_edit = QtGui.QLineEdit()
        browse_btn = QtGui.QPushButton("Browse")
        dirpick_layout.addWidget(self.line_edit)
        dirpick_layout.addWidget(browse_btn)
        browse_btn.clicked.connect(self.show_filepicker)

        form_layout = QtGui.QFormLayout()

        self.keep_box = QtGui.QCheckBox("Keep files on devices")
        form_layout.addRow(self.keep_box)

        self.even_device = None
        if ('combine' in self.wizard().active_plugins
                or 'autorotate' in self.wizard().active_plugins):
            self.even_device = QtGui.QComboBox()
            self.even_device.addItem("Left")
            self.even_device.addItem("Right")
            self.even_device.setCurrentIndex(0)
            form_layout.addRow("Device for even pages", self.even_device)

        self.st_auto = None
        self.st_detection = None
        if 'scantailor' in self.wizard().active_plugins:
            self.st_auto = QtGui.QCheckBox("Don't Inspect ScanTailor"
                                           " configuration")
            form_layout.addRow(self.st_auto)
            self.st_detection = QtGui.QComboBox()
            self.st_detection.addItem("Content")
            self.st_detection.addItem("Page")
            self.st_detection.setCurrentIndex(0)
            form_layout.addRow("ScanTailor layout mode", self.st_detection)

        self.ocr_lang = None
        if 'tesseract' in self.wizard().active_plugins:
            langs = (subprocess.check_output(
                ["tesseract", "--list-langs"],
                stderr=subprocess.STDOUT).split("\n")[1:-1])
            self.ocr_lang = QtGui.QComboBox()
            for lang in langs:
                self.ocr_lang.addItem(lang)
            self.ocr_lang.setCurrentIndex(0)
            form_layout.addRow("OCR language", self.ocr_lang)

        main_layout = QtGui.QVBoxLayout()
        main_layout.addWidget(intro_label)
        main_layout.addSpacing(30)
        main_layout.addWidget(
            QtGui.QLabel("Please select a project directory."))
        main_layout.addLayout(dirpick_layout)
        main_layout.addSpacing(30)
        main_layout.addLayout(form_layout)

        self.setLayout(main_layout)
Esempio n. 32
0
def finish_capture(devices):
    logger.debug("Running finish_capture hooks")
    for ext in get_pluginmanager():
        ext.obj.finish_capture(devices)