Example #1
0
 def __init__(self, app):
     super().__init__(app)
     QtGui.QIcon.setThemeName(Settings().icon_theme)
     self._page = -1
     self._perspective = 'default'
     self._nav_was_visible = True
     self._offset_was_visible = True
     self.setup_icons()
     self.ui.tabWidgetEditors.setContextMenuPolicy(
         QtCore.Qt.CustomContextMenu)
     self.ui.tabWidgetEditors.customContextMenuRequested.connect(
         self.show_main_menu_as_context_menu)
     self.ui.tabWidgetEditors.tab_bar_double_clicked.connect(
         self.toggle_perspective)
     self.ui.actionFullscreen.triggered.connect(self.toggle_fullscreen)
     self.bt_mnu = QtWidgets.QToolButton()
     self.main_window.addActions(self.make_main_menu().actions())
     window_mnu = self.main_window.createPopupMenu()
     self.ui.menuWindows.addActions(window_mnu.actions())
     if system.darwin:
         self.ui.toolBarCode.setIconSize(QtCore.QSize(20, 20))
         self.ui.toolBarFile.setIconSize(QtCore.QSize(20, 20))
         self.ui.toolBarFile.setStyleSheet(
             '''QToolButton
             {
                  background-color: rgba(255, 255,255,0);
             }
             ''')
         self.ui.toolBarCode.setStyleSheet(
             '''QToolButton
             {
                  background-color: rgba(255, 255,255,0);
             }
             ''')
     self.ui.actionFullscreen.setChecked(Settings().fullscreen)
Example #2
0
def test_functional_external_terminal(app):
    """
    Does what a typical user expect from an IDE: open a file, compile it
    and finally run the program.

    :type app: open_cobol_ide.app.Application
    """
    app.win.show()
    # Open a cobol file
    Settings().external_terminal = True
    app.file.open_file(path_ok)
    assert app.win.ui.actionCompile.isEnabled()
    assert app.edit.current_editor.file.path == path_ok
    assert app.view.ui.stackedWidget.currentIndex() == int(Page.EDIT)
    QTest.qWait(500)
    # compile it
    app.cobol.compile()
    QTest.qWait(1000)
    assert app.cobol.ui.errorsTable.rowCount() == 1
    assert app.win.ui.errorsTable.item(0, 0).text() == 'Info'
    # run it
    assert app.win.ui.actionRun.isEnabled()
    app.cobol.run()
    QTest.qWait(1000)
    assert 'Launched in external terminal' in app.win.ui.consoleOutput.toPlainText(
    )

    Settings().external_terminal = False
Example #3
0
    def show_page(self, page):
        """
        Changes the active page.

        :param page: page
        :type page: open_cobol_ide.core.constants.Page
        """
        _logger().debug('showing page %r' % page)
        self.ui.stackedWidget.setCurrentIndex(int(page))
        if page == Page.HOME:
            if self._page != -1:
                s = Settings()
                s.outline_visible = self.ui.dockWidgetNavPanel.isVisible()
            if not system.ubuntu:
                self.ui.menuBar.hide()
            self.ui.statusbar.hide()
            self.ui.toolBarCode.hide()
            self.ui.toolBarFile.hide()
            self.ui.dockWidgetLogs.hide()
            self.ui.dockWidgetNavPanel.hide()
            self.ui.dockWidgetOffsets.hide()
            self.ui.dockWidgetFileSystem.hide()
            if self.ui.consoleOutput.is_running:
                self.ui.consoleOutput.stop_process()
            self.ui.widgetHome.show()
        else:
            self._apply_perspective()
            self.ui.dockWidgetNavPanel.setVisible(Settings().outline_visible)
            self.ui.dockWidgetFileSystem.setVisible(True)
            self.ui.widgetHome.hide()
Example #4
0
    def prepare_bin_dir(self, path, output_full_path):
        assert not os.path.isfile(path)  # must be a directory
        if not os.path.exists(path):
            os.makedirs(path)
        if Settings().copy_runtime_dlls:
            # copy runtime dlls to output directory
            files = glob.glob(
                os.path.join(os.path.dirname(Settings().full_compiler_path),
                             "*.dll"))
            for f in files:
                shutil.copy(f, path)
        if os.path.exists(output_full_path):
            try:
                os.remove(output_full_path)
            except OSError:
                _logger().exception('Failed to previous binary file: %s' %
                                    output_full_path)

        # check for possible permission error
        test_path = os.path.join(path, 'test_write_access.ocide')
        try:
            with open(test_path, 'w'):
                pass
        except PermissionError:
            msg = 'Build directory not writeable (%s)' % path
            _logger().exception(msg)
            raise PermissionError(msg)
        else:
            os.remove(test_path)
Example #5
0
def test_update_style(app):
    Settings().dark_style = True
    app.update_app_style()
    assert app.app.styleSheet() != ''
    Settings().dark_style = False
    app.update_app_style()
    assert app.app.styleSheet() == ''
Example #6
0
    def show_page(self, page):
        """
        Changes the active page.

        :param page: page
        :type page: open_cobol_ide.core.constants.Page
        """
        _logger().debug('showing page %r' % page)
        self.ui.stackedWidget.setCurrentIndex(int(page))
        if page == Page.HOME:
            if self._page != -1:
                s = Settings()
                s.outline_visible = self.ui.dockWidgetNavPanel.isVisible()
            if not system.ubuntu:
                self.ui.menuBar.hide()
            self.ui.statusbar.hide()
            self.ui.toolBarCOBOL.hide()
            self.ui.toolBarFile.hide()
            self.ui.dockWidgetLogs.hide()
            self.ui.dockWidgetNavPanel.hide()
            self.ui.dockWidgetOffsets.hide()
            self.ui.dockWidgetFileSystem.hide()
            if self.ui.consoleOutput.is_running:
                self.ui.consoleOutput.stop_process()
            self.ui.widgetHome.show()
            self.ui.btOpenFile.setFocus()
        else:
            self._apply_perspective()
            self.ui.dockWidgetNavPanel.setVisible(Settings().outline_visible)
            self.ui.dockWidgetFileSystem.setVisible(True)
            self.ui.widgetHome.hide()
Example #7
0
    def __init__(self, parse_args=True):
        super().__init__()
        if system.darwin:
            Application._osx_init()
        self.app = QtWidgets.QApplication(sys.argv)

        self._reported_tracebacks = []
        qcrash.get_system_information = system.get_system_infos
        qcrash.get_application_log = logger.get_application_log
        qcrash.install_backend(
            qcrash.backends.GithubBackend(QCRASH_GH_OWNER, QCRASH_GH_REPO),
            qcrash.backends.EmailBackend(QCRASH_EMAIL, 'OpenCobolIDE'))
        qcrash.set_qsettings(Settings()._settings)
        qcrash.install_except_hook(except_hook=self._report_exception)
        # if hasattr(sys, 'frozen') and sys.platform == 'win32':
        #     sys.stdout = open(os.path.join(system.get_cache_directory(),
        #                                    'ocide_stdout.log'), 'w')
        #     sys.stderr = open(os.path.join(system.get_cache_directory(),
        #                                    'ocide_stderr.log'), 'w')
        if parse_args and not system.darwin:
            files = self.handle_command_line_args()
        else:
            files = []
        _logger().info('files to open: %r' % files)
        self.name = 'OpenCobolIDE'
        self.version = __version__
        self.title = '%s %s' % (self.name, self.version)

        self.apply_mimetypes_preferences()

        self.win = MainWindow()
        self.win.setWindowTitle(self.title)
        self.file = FileController(self)
        self.view = ViewController(self)
        self.home = HomeController(self)
        self.edit = EditController(self)
        self.cobol = CobolController(self)
        self.help = HelpController(self)
        self.win.app = self

        self.view.show_perspective(Settings().perspective)

        self.update_app_style()

        try:
            check_compiler()
        except CompilerNotFound:
            msg = 'Failed to find a working GnuCOBOL compiler!\n' \
                "The IDE will continue to work but you won't be able to " \
                'compile...'
            if system.windows:
                msg += '\n\nTip: Ensure that there is no additional ' \
                    'installation of MinGW in %s:\MinGW' % sys.executable[0]
            QtWidgets.QMessageBox.warning(
                self.win, 'COBOL compiler not found or not working', msg)
        else:
            _logger().info('GnuCOBOL version: %s',
                           GnuCobolCompiler.get_version(include_all=False))
        self._files = files
Example #8
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.checkBoxVerbose.setChecked(Settings().verbose)
        self.tabWidget.setCurrentIndex(0)
        self.tbwVersions.setColumnCount(1)
        self.tbwVersions.setRowCount(len(self.HEADERS))
        self.tbwVersions.setVerticalHeaderLabels(self.HEADERS)
        self.tbwVersions.setHorizontalHeaderLabels(['Version'])
        self.tbwVersions.verticalHeader().setStretchLastSection(False)
        self.labelMain.setText(self.labelMain.text() % __version__)
        self.setMinimumWidth(640)
        self.setMinimumHeight(480)
        self.setWindowIcon(
            QtGui.QIcon.fromTheme(
                'help-about',
                QtGui.QIcon(':/ide-icons/rc/dialog-information.png')))
        try:
            import qdarkstyle
        except ImportError:
            qdarkstyle_version = 'Not installed'
        else:
            qdarkstyle_version = qdarkstyle.__version__
        versions = [
            GnuCobolCompiler().get_version(), QtCore.QT_VERSION_STR,
            QtCore.PYQT_VERSION_STR, pyqode.core.__version__,
            pyqode.cobol.__version__, pygments.__version__, qdarkstyle_version
        ]
        for i, version in enumerate(versions):
            item = QtWidgets.QTableWidgetItem(version)
            self.tbwVersions.setItem(i, 0, item)
        with open(logger.get_path(), 'r') as f:
            self.textEditLog.setText(f.read())
        self.checkBoxVerbose.toggled.connect(self._on_verbose_toggled)

        self.edit_compiler_infos.setFont(QtGui.QFont(Settings().font, 9))

        # from pyqode.core._forms.pyqode_core_rc
        QtGui.QFontDatabase.addApplicationFont(
            ':/fonts/rc/SourceCodePro-Regular.ttf')
        QtGui.QFontDatabase.addApplicationFont(
            ':/fonts/rc/SourceCodePro-Bold.ttf')

        template = '''cobc --info
============

%(cobc_infos)s

cobcrun --runtime-env
=====================

%(cobcrun_infos)s
'''

        gnucobol_infos = template % {
            'cobc_infos': GnuCobolCompiler.get_cobc_infos(),
            'cobcrun_infos': GnuCobolCompiler.get_cobcrun_infos()
        }
        self.edit_compiler_infos.setPlainText(gnucobol_infos)
Example #9
0
    def make_command(self, file_path):
        """
        Make the dbpre command.

        :param file_path: .scb path
        """
        source = os.path.splitext(os.path.split(file_path)[1])[0]
        return self.dbpre_path, [source, '-I%s' % Settings().dbpre_framework,
                                 '-ts=%d' % Settings().tab_len]
Example #10
0
    def make_command(self,
                     input_file_names,
                     file_type,
                     output_dir=None,
                     additional_options=None):
        """
        Makes the command needed to compile the specified file.

        :param input_file_names: Input file names (without path).
            The first name must be the source file, other entries can
            be used to link with additional object files.
        :param output_file_name: Output file base name (without path and
            extension). None to use the input_file_name base name.
        :param file_type: file type (exe or dll).

        :return: a tuple made up of the program name and the command arguments.
        """
        from .settings import Settings
        settings = Settings()
        output_file_name = self._get_output_filename(input_file_names,
                                                     file_type)
        options = []
        if file_type == FileType.EXECUTABLE:
            options.append('-x')
        options.append('-o')
        options.append(os.path.join(output_dir, output_file_name))
        options.append(
            '-std=%s' %
            str(settings.cobol_standard).replace('GnuCobolStandard.', ''))
        options += settings.compiler_flags
        if settings.free_format:
            options.append('-free')
        if settings.copybook_paths:
            for pth in settings.copybook_paths.split(';'):
                if not pth:
                    continue
                options.append('-I%s' % pth)
        if settings.library_search_path:
            for pth in settings.library_search_path.split(';'):
                if pth:
                    options.append('-L%s' % pth)
        if settings.libraries:
            for lib in settings.libraries.split(' '):
                if lib:
                    options.append('-l%s' % lib)
        if additional_options:
            options += additional_options
        for ifn in input_file_names:
            if system.windows and ' ' in ifn:
                ifn = '"%s"' % ifn
            options.append(ifn)
        if Settings().compiler_path and Settings().vcvars32:
            VisualStudioWrapperBatch.generate()
            pgm = VisualStudioWrapperBatch.path()
        else:
            pgm = Settings().compiler_path
        return pgm, options
Example #11
0
    def __init__(self, parse_args=True):
        if hasattr(sys, 'frozen') and sys.platform == 'win32':
            sys.stdout = open(
                os.path.join(system.get_cache_directory(), 'ocide_stdout.log'),
                'w')
            sys.stderr = open(
                os.path.join(system.get_cache_directory(), 'ocide_stderr.log'),
                'w')
        self.init_env()
        self.app = QtWidgets.QApplication(sys.argv)
        if parse_args and not system.darwin:
            args = self.parse_args()
            verbose = args.verbose
            files = args.files
        else:
            verbose = False
            files = []
        logger.setup_logging(__version__, debug=verbose or Settings().verbose)
        self.name = 'OpenCobolIDE'
        self.version = __version__
        self.title = '%s %s' % (self.name, self.version)

        self.apply_mimetypes_preferences()

        self.win = MainWindow()
        self.win.setWindowTitle(self.title)
        self.file = FileController(self)
        self.view = ViewController(self)
        self.home = HomeController(self)
        self.edit = EditController(self)
        self.cobol = CobolController(self)
        self.help = HelpController(self)

        self.view.show_perspective(Settings().perspective)
        self.view.show_home_page()

        self.update_app_style()

        try:
            check_compiler()
        except CompilerNotFound as e:
            QtWidgets.QMessageBox.warning(
                self.win, 'COBOL compiler not found',
                'Failed to find GnuCOBOL compiler!\n\n%s\n\n'
                "The IDE will continue to work but you won't be able to "
                'compile any file...' % e)
        else:
            _logger().info('GnuCOBOL version: %s',
                           GnuCobolCompiler.get_version())
        # open specified files
        for f in files:
            self.file.open_file(f)
Example #12
0
def test_toggle_perspective(app):
    assert Settings().perspective == 'default'
    assert app.win.ui.toolBarCode.isVisible()
    assert app.win.ui.toolBarFile.isVisible()
    app.view.toggle_perspective()
    QTest.qWait(1000)
    assert Settings().perspective == 'minimal'
    assert not app.win.ui.toolBarCode.isVisible()
    assert not app.win.ui.toolBarFile.isVisible()
    app.view.toggle_perspective()
    QTest.qWait(1000)
    assert Settings().perspective == 'default'
    assert app.win.ui.toolBarCode.isVisible()
    assert app.win.ui.toolBarFile.isVisible()
Example #13
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.tabWidget.setCurrentIndex(0)
        self.tbwVersions.setColumnCount(1)
        self.tbwVersions.setRowCount(len(self.HEADERS))
        self.tbwVersions.setVerticalHeaderLabels(self.HEADERS)
        self.tbwVersions.setHorizontalHeaderLabels(['Version'])
        self.tbwVersions.verticalHeader().setStretchLastSection(False)
        self.labelMain.setText(self.labelMain.text() % __version__)
        self.setMinimumWidth(640)
        self.setMinimumHeight(480)
        self.setWindowIcon(
            QtGui.QIcon.fromTheme(
                'help-about',
                QtGui.QIcon(':/ide-icons/rc/dialog-information.png')))

        for i, (name, version) in enumerate(
                sorted(list(DlgAbout.get_runtime_env().items()),
                       key=lambda x: x[0])):
            item = QtWidgets.QTableWidgetItem(name)
            self.tbwVersions.setVerticalHeaderItem(i, item)
            item = QtWidgets.QTableWidgetItem(version)
            self.tbwVersions.setItem(i, 0, item)
        try:
            with open(logger.get_path(), 'r') as f:
                self.textEditLog.setPlainText('\n'.join(
                    f.read().splitlines()[-1000:]))
        except FileNotFoundError:
            self.textEditLog.setPlainText('')

        self.edit_compiler_infos.setFont(QtGui.QFont(Settings().font, 9))

        # from pyqode.core._forms.pyqode_core_rc
        QtGui.QFontDatabase.addApplicationFont(
            ':/fonts/rc/SourceCodePro-Regular.ttf')
        QtGui.QFontDatabase.addApplicationFont(
            ':/fonts/rc/SourceCodePro-Bold.ttf')

        self.edit_compiler_infos.setPlainText(DlgAbout.get_cobc_runtime_env())

        try:
            name = LEVEL_NAMES[Settings().log_level]
        except KeyError:
            name = 'INFO'
        self.combo_log_level.setCurrentText(name)
        self.combo_log_level.currentIndexChanged.connect(
            self._on_log_level_changed)

        self.bt_clear_logs.clicked.connect(self._clear_logs)
Example #14
0
 def update_app_style(self):
     if Settings().dark_style:
         try:
             import qdarkstyle
         except ImportError:
             Settings().dark_style = False
         else:
             qt_api = os.environ[QT_API]
             if qt_api in PYQT5_API:
                 qss = qdarkstyle.load_stylesheet_pyqt5()
             else:
                 qss = qdarkstyle.load_stylesheet(qt_api in PYSIDE_API)
             self.app.setStyleSheet(qss)
             return
     self.app.setStyleSheet('')
Example #15
0
 def check_compiler(self, dotted_extension):
     compiler_works = False
     msg = 'Invalid extension'
     if dotted_extension.lower() in Settings().cobc_extensions:
         compiler_works = GnuCobolCompiler().is_working()
         msg = 'GnuCOBOL compiler not found or not working'
     elif dotted_extension.lower() in Settings().dbpre_extensions:
         compiler_works = DbpreCompiler().is_working()
         msg = 'dbpre compiler not working, please check your SQL COBOL ' \
             'configuration'
     elif dotted_extension.lower() in Settings().esqloc_extensions:
         compiler_works = EsqlOCCompiler().is_working()
         msg = 'esqlOC compiler not working, please check your SQL COBOL ' \
             'configuration'
     return compiler_works, msg
Example #16
0
 def __init__(self, parent, path):
     super().__init__(parent)
     self.setupUi(self)
     self.enable_ok()
     completer = QtWidgets.QCompleter(self)
     completer.setModel(QtWidgets.QDirModel(completer))
     self.lineEditPath.setCompleter(completer)
     if not path:
         self.lineEditPath.setText(os.path.expanduser("~"))
     else:
         self.lineEditPath.setText(path)
     self.prev_pth = ""
     self.comboBoxExtension.addItems(sorted(Settings().all_extensions))
     self.comboBoxExtension.addItems(
         [ext.upper() for ext in Settings().all_extensions])
Example #17
0
    def create_new_file(cls, parent, path=None):
        """
        Creates a new file. Shows the new file dialog and creates the file
        on disk if the dialog has been accepted and the destination does not
        overwrite any file (or the user choose to overwrite existing file).

        :param parent: Parent widget
        :return: Path or None if the dialog has been cancelled.

        """
        dlg = cls(parent, path=path)
        if dlg.exec_() == dlg.Accepted:
            path = dlg.path()
            if os.path.exists(path):
                answer = QtWidgets.QMessageBox.question(
                    parent, 'Overwrite file', 'The file %s already exists. '
                    'Do you want to overwrite it?' % path,
                    QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                    QtWidgets.QMessageBox.No)
                if answer == QtWidgets.QMessageBox.No:
                    return None
            eol = FileManager.EOL.string(Settings().preferred_eol)
            text = eol.join(dlg.template().splitlines()) + eol
            data = text.encode(locale.getpreferredencoding())
            with open(path, 'wb') as f:
                f.write(data)
            return path
        return None
Example #18
0
def update_editor_settings(editor):
    from open_cobol_ide.settings import Settings
    settings = Settings()
    # general settings for all editors
    editor.tab_length = settings.tab_len
    editor.font_name = settings.font
    editor.font_size = settings.font_size
    editor.show_whitespaces = settings.show_whitespaces
    editor.syntax_highlighter.color_scheme = ColorScheme(settings.color_scheme)
    editor.panels.get('FoldingPanel').native_look = not settings.dark_style
    try:
        # cobol editor specific settings
        editor.backspace_mode.enabled = settings.enable_smart_backspace
        editor.comment_indicator = settings.comment_indicator
        editor.free_format = settings.free_format
        editor.caret_line_mode.enabled = settings.highlight_caret
        editor.auto_indent_mode.enabled = settings.enable_autoindent
        editor.code_completion_mode.trigger_length = \
            settings.code_completion_trigger_len
        editor.line_nbr_panel.enabled = settings.display_lines
        editor.line_nbr_panel.setVisible(settings.display_lines)
        editor.linter_mode.enabled = settings.show_errors
        editor.lower_case_keywords = settings.lower_case_keywords
        editor.file.autodetect_eol = settings.autodetect_eol
        editor.file.preferred_eol = settings.preferred_eol
        editor.modes.get('CodeCompletionMode').smart_completion = \
            bool(settings.completion_filter_mode)
        editor.enable_linter()
    except AttributeError:
        editor.syntax_highlighter.pygments_style = settings.color_scheme
Example #19
0
 def save_as(self):
     """
     Saves the currend editor content as.
     """
     fn = self.ui.tabWidgetEditors.save_current_as()
     self.recent_files_manager.open_file(fn)
     Settings().last_path = fn
Example #20
0
def app(request):
    global _app
    # always starts with default settings
    s = Settings()
    s.clear()
    s.perspective = 'default'
    _app = Application(parse_args=False)

    def fin():
        global _app
        _app.exit()
        del _app

    # _app.win.hide()
    request.addfinalizer(fin)
    return _app
Example #21
0
 def __init__(self, parent=None):
     super().__init__(parent)
     self.setupUi(self)
     self.checkBoxVerbose.setChecked(Settings().verbose)
     self.tabWidget.setCurrentIndex(0)
     self.tbwVersions.setColumnCount(1)
     self.tbwVersions.setRowCount(len(self.HEADERS))
     self.tbwVersions.setVerticalHeaderLabels(self.HEADERS)
     self.tbwVersions.setHorizontalHeaderLabels(['Version'])
     self.tbwVersions.verticalHeader().setStretchLastSection(False)
     self.labelMain.setText(self.labelMain.text() % __version__)
     self.setMinimumWidth(640)
     self.setMinimumHeight(480)
     self.setWindowIcon(QtGui.QIcon.fromTheme(
         'help-about', QtGui.QIcon(
             ':/ide-icons/rc/dialog-information.png')))
     try:
         import qdarkstyle
     except ImportError:
         qdarkstyle_version = 'Not installed'
     else:
         qdarkstyle_version = qdarkstyle.__version__
     versions = [GnuCobolCompiler().get_version(),
                 QtCore.QT_VERSION_STR,
                 QtCore.PYQT_VERSION_STR,
                 pyqode.core.__version__,
                 pyqode.cobol.__version__,
                 pygments.__version__,
                 qdarkstyle_version]
     for i, version in enumerate(versions):
         item = QtWidgets.QTableWidgetItem(version)
         self.tbwVersions.setItem(i, 0, item)
     with open(logger.get_path(), 'r') as f:
         self.textEditLog.setText(f.read())
     self.checkBoxVerbose.toggled.connect(self._on_verbose_toggled)
Example #22
0
 def _on_verbose_toggled(self, state):
     Settings().verbose = state
     if not DlgAbout._flg_verbose:
         QtWidgets.QMessageBox.information(
             self, 'Restart required',
             'You need to restart the IDE for the change to be applied.')
         DlgAbout._flg_verbose = True
Example #23
0
 def _on_command_started(self, cmd):
     old_color = self.ui.textEditCompilerOutput.textColor()
     color = QtGui.QColor('#629755') if Settings().dark_style else \
         QtGui.QColor('#000080')
     self.ui.textEditCompilerOutput.setTextColor(color)
     self.ui.textEditCompilerOutput.append(cmd)
     self.ui.textEditCompilerOutput.setTextColor(old_color)
Example #24
0
 def _on_file_compiled(self, filename, status, messages):
     """
     Displays compilation status in errors table.
     """
     self.ui.dockWidgetLogs.show()
     self.ui.tabWidgetLogs.setCurrentIndex(LOG_PAGE_COMPILER)
     if len(messages) == 0 and status == 0:
         ext = GnuCobolCompiler().extension_for_type(
             get_file_type(filename))
         name = os.path.splitext(os.path.split(filename)[1])[0]
         output_dir = Settings().output_directory
         if not os.path.isabs(output_dir):
             path = os.path.dirname(filename)
             output_dir = os.path.abspath(os.path.join(path, output_dir))
         path = os.path.join(output_dir, name + ext)
         self.ui.errorsTable.add_message(
             CheckerMessage('Compilation succeeded (output: %s)' % path,
                            CheckerMessages.INFO,
                            -1,
                            path=filename))
     else:
         for msg in messages:
             msg = CheckerMessage(*msg)
             if msg.status == CheckerMessages.ERROR:
                 self._errors += 1
             if len(msg.description.splitlines()) > 1:
                 msg.description = 'For full output see compiler tab...'
             self.ui.errorsTable.add_message(msg)
Example #25
0
 def show_perspective(self, perspective):
     """
     TODO
     """
     self._perspective = perspective
     self._apply_perspective()
     Settings().perspective = perspective
Example #26
0
def app(request):
    global _app
    # always starts with default settings
    s = Settings()
    s.clear()
    s.perspective = 'default'
    _app = Application(parse_args=False)

    def fin():
        global _app
        _app.exit()
        del _app

    # _app.win.hide()
    request.addfinalizer(fin)
    return _app
Example #27
0
 def _run(self):
     """
     Runs the current editor program.
     :return:
     """
     # compilation has finished, we can run the program that corresponds
     # to the current editor file
     editor = self.app.edit.current_editor
     file_type = editor.file_type
     self.ui.tabWidgetLogs.setCurrentIndex(LOG_PAGE_RUN)
     self.ui.dockWidgetLogs.show()
     self.ui.consoleOutput.clear()
     output_dir = Settings().output_directory
     if not os.path.isabs(output_dir):
         output_dir = os.path.join(
             os.path.dirname(editor.file.path), output_dir)
     if Settings().working_dir:
         wd = Settings().working_dir
     else:
         wd = output_dir
     filename = os.path.splitext(editor.file.name)[0] + \
         GnuCobolCompiler().extension_for_type(file_type)
     program = os.path.join(output_dir, filename)
     if not os.path.exists(program):
         _logger().warning('cannot run %s, file does not exists',
                           program)
         return
     _logger().info('running program: %r (working dir=%r)', program, wd)
     if Settings().external_terminal:
         self._run_in_external_terminal(program, wd, file_type)
         self.enable_run(True)
         self.enable_compile(True)
     else:
         self.ui.consoleOutput.setFocus(True)
         for item in self.run_buttons + [self.ui.actionRun]:
             item.setEnabled(False)
         path = GnuCobolCompiler.setup_process_environment().value('PATH')
         env = Settings().run_environemnt
         if 'PATH' not in env.keys():
             env['PATH'] = path
         if file_type == FileType.MODULE:
             cobcrun = system.which('cobcrun')
             self.ui.consoleOutput.start_process(
                 cobcrun, [os.path.splitext(editor.file.name)[0]], working_dir=wd, env=env)
         else:
             self.ui.consoleOutput.start_process(program, working_dir=wd, env=env, print_command=True)
Example #28
0
 def template(self):
     """
     Gets the selected file template
     """
     if Settings().free_format:
         return FREE_TEMPLATES[self.comboBoxType.currentIndex()]
     else:
         return TEMPLATES[self.comboBoxType.currentIndex()]
Example #29
0
 def __init__(self, bt_compile=None, bt_run=None, parent=None):
     self._buttons = (bt_compile, bt_run)
     super().__init__(parent)
     self.syntax_highlighter.color_scheme = ColorScheme(
         Settings().color_scheme)
     self.linter_mode = self.modes.append(CobolLinterMode())
     self.app = None
     self.enable_linter()
Example #30
0
 def _select_dbpre(self):
     path, _ = QtWidgets.QFileDialog.getOpenFileName(
         self, 'Select dbpre executable', self.lineEditDbpre.text())
     if path:
         self.lineEditDbpre.setText(system.normpath(path))
         self.labelDbpreVersion.setText(
             compilers.DbpreCompiler(path).get_version(
             ) if Settings().dbpre != '' else '')
Example #31
0
 def icon(self, file_infos):
     try:
         if '.%s' % file_infos.suffix().lower() in Settings(
         ).all_extensions:
             return QtGui.QIcon(icons.ICON_MIMETYPE)
     except AttributeError:
         pass
     return super().icon(file_infos)
Example #32
0
    def handle_command_line_args(self):
        args = self.parse_args()
        files = args.files

        # setup logger
        debug = args.verbose or Settings().verbose
        logger.setup_logging(__version__, level=Settings().log_level)

        # show runtime env
        if args.runtime_env:
            print(('OpenCobolIDE %s' % __version__))
            for k, v in sorted(list(DlgAbout.get_runtime_env().items()),
                               key=lambda x: x[0]):
                print(('%s %s' % (k, v)))
            sys.exit(0)

        # show cobc runtime env
        if args.cobc_runtime_env:
            print((DlgAbout.get_cobc_runtime_env()))
            sys.exit(0)

        # import preferences
        if args.conf:
            try:
                with open(args.conf, 'rb') as f:
                    Settings().import_from_dict(pickle.load(f))
            except (ValueError, IOError, OSError):
                _logger().exception('failed to restore preferences from %r',
                                    args.conf)
            else:
                _logger().info('preferences imported from %r', args.conf)

        # compile specified files
        if args.compile:
            thread = CompilationThread()
            for path in files:
                if os.path.exists(path):
                    CobolController.clean_file(path)
                    thread.file_path = path
                    thread.run()
                else:
                    print('cannot compile %r, file not found')
            sys.exit(0)

        return files
Example #33
0
    def _generate_param_file(self, source_path):
        """
        Generate the bin/EXECUTABLE.param file based on the settings defined in
        the preferences dialog.

        :param source_path: path of the .scb file.
        """
        name = os.path.splitext(os.path.split(source_path)[1])[0] + '.param'
        content = PARAM_FILE_CONTENT % {
            'host': Settings().dbhost,
            'user': Settings().dbuser,
            'pswd': Settings().dbpasswd,
            'dbname': Settings().dbname,
            'port': Settings().dbport,
            'socket': Settings().dbsocket
        }
        output_dir = Settings().output_directory
        if not os.path.isabs(output_dir):
            output_dir = os.path.abspath(
                os.path.join(os.path.dirname(source_path), output_dir))
        path = os.path.join(output_dir, name)
        if not os.path.exists(path):
            _logger().info('creating %s', name)
            with open(path, 'w') as f:
                f.write(content)
 def save_state(self):
     """
     Saves the window state and geometry to the settings.
     """
     s = Settings()
     s.geometry = self.saveGeometry()
     s.state = self.saveState()
     s.maximised = self.isMaximized()
     s.size = self.size()
     if self.ui.stackedWidget.currentIndex() == 1:
         s.outline_visible = self.ui.dockWidgetNavPanel.isVisible()
         s.fullscreen = self.isFullScreen()
def test_make_command_exe(free, std, ftype, expected_opts):
    compiler = GnuCobolCompiler()
    settings = Settings()
    settings.free_format = free
    settings.cobol_standard = std
    pgm, options = compiler.make_command(['HelloWorld.cbl'], ftype, 'bin')
    assert pgm == Settings().compiler_path
    for o, eo in zip(options, expected_opts):
        assert o == eo
    settings.free_format = free
    settings.cobol_standard = GnuCobolStandard.default
    settings.free_format = False
Example #36
0
 def save_state(dlg):
     s = Settings()
     s.preferences_width = dlg.width()
     s.preferences_height = dlg.height()
     s.preferences_index = dlg.tabWidget.currentIndex()
Example #37
0
    def reset(self, all_tabs=False):
        settings = Settings()
        # Editor
        if self.tabWidget.currentIndex() == 0 or all_tabs:
            self.checkBoxShowErrors.setChecked(settings.show_errors)
            self.checkBoxViewLineNumber.setChecked(settings.display_lines)
            self.checkBoxHighlightCurrentLine.setChecked(settings.highlight_caret)
            self.checkBoxHighlightWhitespaces.setChecked(settings.show_whitespaces)
            self.spinBoxEditorTabLen.setValue(settings.tab_len)
            self.checkBoxEditorAutoIndent.setChecked(settings.enable_autoindent)
            self.spinBoxEditorCCTriggerLen.setValue(settings.code_completion_trigger_len)
            self.rbLowerCaseKwds.setChecked(settings.lower_case_keywords)
            self.rbUpperCaseKwds.setChecked(not settings.lower_case_keywords)
            self.lineEditCommentIndicator.setText(settings.comment_indicator)
            self.checkBoxSmartBackspace.setChecked(settings.enable_smart_backspace)
            self.checkBoxAutodetectEOL.setChecked(settings.autodetect_eol)
            self.comboBoxPreferredEOL.setCurrentIndex(settings.preferred_eol)
            self.comboCcFilterMode.setCurrentIndex(settings.completion_filter_mode)
        # Style
        if self.tabWidget.currentIndex() == 1 or all_tabs:
            rb = self.radioButtonColorDark if settings.dark_style else self.radioButtonColorWhite
            rb.setChecked(True)
            index = self.comboBoxIconTheme.findText(settings.icon_theme)
            if index != -1:
                self.comboBoxIconTheme.setCurrentIndex(index)
            self.fontComboBox.setCurrentFont(QtGui.QFont(settings.font))
            self.spinBoxFontSize.setValue(settings.font_size)
            self.listWidgetColorSchemes.clear()
            current_index = None
            self.listWidgetColorSchemes.clear()
            for style in PYGMENTS_STYLES:
                self.listWidgetColorSchemes.addItem(style)
                if style == settings.color_scheme:
                    current_index = self.listWidgetColorSchemes.count() - 1
            if current_index:
                self.listWidgetColorSchemes.setCurrentRow(current_index)
        # Run
        if self.tabWidget.currentIndex() == 3 or all_tabs:
            self.checkBoxRunExtTerm.setChecked(settings.external_terminal)
            self.lineEditRunTerm.setVisible(sys.platform != "win32")
            self.lineEditRunTerm.setEnabled(settings.external_terminal)
            self.lineEditRunTerm.setText(settings.external_terminal_command)
        # compiler
        if self.tabWidget.currentIndex() == 2 or all_tabs:
            self.cbAutoDetectSublmodules.setChecked(Settings().autodetect_submodules)
            self.lineEditOutputDirectory.setText(Settings().output_directory)
            self.lineEditCobcExts.setText(";".join(Settings().cobc_extensions))
            self.checkBoxFreeFormat.setChecked(settings.free_format)
            self.comboBoxStandard.setCurrentIndex(int(settings.cobol_standard))
            self.lineEditCompilerPath.setText(settings.compiler_path)
            flags = Settings().compiler_flags
            self.cb_debugging_line.setChecked(self.cb_debugging_line.text() in flags)
            self.cb_ftrace.setChecked(self.cb_ftrace.text().replace("&", "") in flags)
            self.cb_ftraceall.setChecked(self.cb_ftraceall.text().replace("&", "") in flags)
            self.cb_g.setChecked(self.cb_g.text().replace("&", "") in flags)
            self.cb_static.setChecked(self.cb_static.text().replace("&", "") in flags)
            self.cb_debug.setChecked(self.cb_debug.text().replace("&", "") in flags)
            for v in self.flags_in_checkbox:
                try:
                    flags.remove(v)
                except ValueError:
                    pass
            self.lineEditLibs.setText(settings.libraries)
            self.listWidgetLibPaths.addItems([pth for pth in settings.library_search_path.split(";") if pth])
            self.listWidgetCopyPaths.addItems([pth for pth in settings.copybook_paths.split(";") if pth])
            self.le_compiler_flags.setText(" ".join(flags))
            if system.windows:
                self.lineEditVCVARS.setText(settings.vcvars32)
            self.PATH.setText(settings.path)
            self.cbPATH.setChecked(settings.path_enabled)
            self.COB_CONFIG_DIR.setText(settings.cob_config_dir)
            self.cbCOB_CONFIG_DIR.setChecked(settings.cob_config_dir_enabled)
            self.COB_COPY_DIR.setText(settings.cob_copy_dir)
            self.cbCOB_COPY_DIR.setChecked(settings.cob_copy_dir_enabled)
            self.COB_INCLUDE_PATH.setText(settings.cob_include_path)
            self.cbCOB_INCLUDE_PATH.setChecked(settings.cob_include_path_enabled)
            self.COB_LIB_PATH.setText(settings.cob_lib_path)
            self.cbCOB_LIB_PATH.setChecked(settings.cob_lib_path_enabled)

        # SQL Cobol
        if self.tabWidget.currentIndex() == 4 or all_tabs:
            self.lineEditDbpreExts.setText(";".join(Settings().dbpre_extensions))
            self.lineEditDbpre.setText(settings.dbpre)
            self.lineEditDbpreFramework.setText(settings.dbpre_framework)
            self.lineEditCobmysqlapi.setText(settings.cobmysqlapi)
            self.lineEditDBHOST.setText(settings.dbhost)
            self.lineEditDBUSER.setText(settings.dbuser)
            self.lineEditDBPASSWD.setText(settings.dbpasswd)
            self.lineEditDBNAME.setText(settings.dbname)
            self.lineEditDBPORT.setText(settings.dbport)
            self.lineEditDBSOCKET.setText(settings.dbsocket)
            self.labelDbpreVersion.setText(compilers.DbpreCompiler().get_version() if Settings().dbpre != "" else "")
            self.lineEditESQLOC.setText(settings.esqloc)
            self.lineEditesqlOcExts.setText(";".join(Settings().esqloc_extensions))
 def restore_defaults(self):
     settings = Settings()
     index = self.tabWidget.currentIndex()
     # Editor
     if index == 0:
         settings.show_cursor_pos_in_bytes = False
         settings.show_error = True
         settings.display_lines = True
         settings.highlight_caret = True
         settings.show_whitespaces = False
         settings.tab_len = 4
         settings.enable_autoindent = True
         settings.code_completion_trigger_len = 1
         settings.comment_indicator = '*> '
         settings.enable_smart_backspace = False
         settings.lower_case_keywords = False
         settings.autodetect_eol = True
         settings.preferred_eol = 0
         settings.code_completion_trigger_len = 1
     # Style
     elif index == 1:
         settings.dark_style = False
         settings.icon_theme = 'default'
         settings.font = 'Source Code Pro'
         settings.font_size = 11
         settings.colorScheme = 'qt'
     # run
     elif index == 3:
         settings.external_terminal = False
         settings.external_terminal_command = None
     # compiler
     elif index == 2:
         settings.autodetect_submodules = True
         settings.output_directory = 'bin'
         settings.free_format = False
         settings.cobol_standard = GnuCobolStandard.default
         settings.compiler_path = Settings.default_compiler_path()
         settings.compiler_flags = ['-debug']
         settings.copybook_paths = ''
         settings.library_search_path = ''
         settings.libraries = ''
         settings.cobc_extensions = ['.cob', '.cbl', '.pco', '.cpy', '.lst']
         if system.windows:
             settings.vcvarsall = ''
             settings.vcvarsall_arch = 'x86'
         settings.path = settings.default_path()
         settings.path_enabled = True
         settings.cob_config_dir = settings.default_config_dir()
         settings.cob_config_dir_enabled = True
         settings.cob_copy_dir = settings.default_copy_dir()
         settings.cob_copy_dir_enabled = True
         settings.cob_include_path = settings.default_include_dir()
         settings.cob_include_path_enabled = True
         settings.cob_lib_path = settings.default_lib_path()
         settings.cob_lib_path_enabled = True
     elif index == 4:
         settings.dbpre = ''
         settings.dbpre_extensions = ['.scb']
         settings.dbpre_framework = ''
         settings.cobmysqlapi = ''
         settings.dbhost = 'localhost'
         settings.dbuser = ''
         settings.dbpasswd = ''
         settings.dbname = ''
         settings.dbport = '03306'
         settings.dbsocket = 'null'
         settings.esqloc = ''
         settings.esqloc_extensions = ['.sqb']
     self.reset()
Example #39
0
 def restore_defaults(self):
     settings = Settings()
     index = self.tabWidget.currentIndex()
     # Editor
     if index == 0:
         settings.show_error = True
         settings.display_lines = True
         settings.highlight_caret = True
         settings.show_whitespaces = False
         settings.tab_len = 4
         settings.enable_autoindent = True
         settings.code_completion_trigger_len = 1
         settings.comment_indicator = "*> "
         settings.enable_smart_backspace = False
         settings.lower_case_keywords = False
         settings.autodetect_eol = True
         settings.preferred_eol = 0
         settings.code_completion_trigger_len = 1
     # Style
     elif index == 1:
         settings.dark_style = False
         settings.icon_theme = "default"
         settings.font = "Source Code Pro"
         settings.font_size = 11
         settings.colorScheme = "qt"
     # run
     elif index == 3:
         settings.external_terminal = False
         settings.external_terminal_command = None
     # compiler
     elif index == 2:
         settings.autodetect_submodules = True
         settings.output_directory = "bin"
         settings.free_format = False
         settings.cobol_standard = GnuCobolStandard.default
         settings.compiler_path = Settings.default_compiler_path()
         settings.compiler_flags = ["-debug"]
         settings.copybook_paths = ""
         settings.library_search_path = ""
         settings.libraries = ""
         settings.cobc_extensions = [".cob", ".cbl", ".pco", ".cpy", ".lst"]
         if system.windows:
             settings.vcvars32 = ""
         settings.path = settings.default_path()
         settings.path_enabled = True
         settings.cob_config_dir = settings.default_config_dir()
         settings.cob_config_dir_enabled = True
         settings.cob_copy_dir = settings.default_copy_dir()
         settings.cob_copy_dir_enabled = True
         settings.cob_include_path = settings.default_include_dir()
         settings.cob_include_path_enabled = True
         settings.cob_lib_path = settings.default_lib_path()
         settings.cob_lib_path_enabled = True
     elif index == 4:
         settings.dbpre = ""
         settings.dbpre_extensions = [".scb"]
         settings.dbpre_framework = ""
         settings.cobmysqlapi = ""
         settings.dbhost = "localhost"
         settings.dbuser = ""
         settings.dbpasswd = ""
         settings.dbname = ""
         settings.dbport = "03306"
         settings.dbsocket = "null"
         settings.esqloc = ""
         settings.esqloc_extensions = [".sqb"]
     self.reset()
Example #40
0
 def apply(self):
     # force next check (otherwise the cached result will be used)
     compilers.GnuCobolCompiler.check_compiler.reset()
     settings = Settings()
     settings.display_lines = self.checkBoxViewLineNumber.isChecked()
     settings.highlight_caret = self.checkBoxHighlightCurrentLine.isChecked()
     settings.show_whitespaces = self.checkBoxHighlightWhitespaces.isChecked()
     settings.tab_len = self.spinBoxEditorTabLen.value()
     settings.enable_autoindent = self.checkBoxEditorAutoIndent.isChecked()
     settings.code_completion_trigger_len = self.spinBoxEditorCCTriggerLen.value()
     settings.preferred_eol = self.comboBoxPreferredEOL.currentIndex()
     settings.autodetect_eol = self.checkBoxAutodetectEOL.isChecked()
     settings.dark_style = self.radioButtonColorDark.isChecked()
     settings.font = self.fontComboBox.currentFont().family()
     settings.font_size = self.spinBoxFontSize.value()
     settings.color_scheme = self.listWidgetColorSchemes.currentItem().text()
     settings.external_terminal = self.checkBoxRunExtTerm.isChecked()
     settings.external_terminal_command = self.lineEditRunTerm.text()
     settings.lower_case_keywords = self.rbLowerCaseKwds.isChecked()
     settings.compiler_path = self.lineEditCompilerPath.text()
     settings.vcvars32 = self.lineEditVCVARS.text()
     settings.path = self.PATH.text()
     settings.path_enabled = self.cbPATH.isChecked()
     settings.cob_config_dir = self.COB_CONFIG_DIR.text()
     settings.cob_config_dir_enabled = self.cbCOB_CONFIG_DIR.isChecked()
     settings.cob_copy_dir = self.COB_COPY_DIR.text()
     settings.cob_copy_dir_enabled = self.cbCOB_COPY_DIR.isChecked()
     settings.cob_include_path = self.COB_INCLUDE_PATH.text()
     settings.cob_include_path_enabled = self.cbCOB_INCLUDE_PATH.isChecked()
     settings.cob_lib_path = self.COB_LIB_PATH.text()
     settings.cob_lib_path_enabled = self.cbCOB_LIB_PATH.isChecked()
     settings.free_format = self.checkBoxFreeFormat.isChecked()
     settings.comment_indicator = self.lineEditCommentIndicator.text()
     settings.autodetect_submodules = self.cbAutoDetectSublmodules.isChecked()
     settings.cobol_standard = GnuCobolStandard(self.comboBoxStandard.currentIndex())
     settings.icon_theme = self.comboBoxIconTheme.currentText()
     settings.show_errors = self.checkBoxShowErrors.isChecked()
     settings.enable_smart_backspace = self.checkBoxSmartBackspace.isChecked()
     paths = []
     for i in range(self.listWidgetLibPaths.count()):
         paths.append(self.listWidgetLibPaths.item(i).text())
     settings.library_search_path = ";".join(paths)
     paths = []
     for i in range(self.listWidgetCopyPaths.count()):
         paths.append(self.listWidgetCopyPaths.item(i).text())
     settings.copybook_paths = ";".join(paths)
     settings.libraries = self.lineEditLibs.text()
     settings.output_directory = self.lineEditOutputDirectory.text()
     cb_flags = [self.cb_g, self.cb_ftrace, self.cb_ftraceall, self.cb_debugging_line, self.cb_static, self.cb_debug]
     flags = [cb.text() for cb in cb_flags if cb.isChecked()]
     flags += self.le_compiler_flags.text().split(" ")
     settings.compiler_flags = flags
     # sql
     settings.dbpre = self.lineEditDbpre.text()
     settings.dbpre_framework = self.lineEditDbpreFramework.text()
     settings.cobmysqlapi = self.lineEditCobmysqlapi.text()
     settings.dbhost = self.lineEditDBHOST.text()
     settings.dbuser = self.lineEditDBUSER.text()
     settings.dbpasswd = self.lineEditDBPASSWD.text()
     settings.dbname = self.lineEditDBNAME.text()
     settings.dbport = self.lineEditDBPORT.text()
     settings.dbsocket = self.lineEditDBSOCKET.text()
     settings.esqloc = self.lineEditESQLOC.text()
     settings.completion_filter_mode = self.comboCcFilterMode.currentIndex()
     settings.cobc_extensions = [ext.lower() for ext in self.lineEditCobcExts.text().split(";") if ext]
     settings.dbpre_extensions = [ext.lower() for ext in self.lineEditDbpreExts.text().split(";") if ext]
     settings.esqloc_extensions = [ext for ext in self.lineEditesqlOcExts.text().split(";") if ext]
Example #41
0
 def save_state(dlg):
     s = Settings()
     s.preferences_width = dlg.width()
     s.preferences_height = dlg.height()
Example #42
0
def which(cmd, mode=os.F_OK | os.X_OK, path=None,
          include_settings_path=True):
    """Given a command, mode, and a PATH string, return the path which
    conforms to the given mode on the PATH, or None if there is no such
    file.

    `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
    of os.environ.get("PATH"), or can be overridden with a custom search
    path.

    TAKEN from the shutil module (cause it is not available on python <= 3.3)
    """
    from open_cobol_ide.settings import Settings

    # Check that a given file can be accessed with the correct mode.
    # Additionally check that `file` is not a directory, as on Windows
    # directories pass the os.access check.
    def _access_check(fn, mode):
        return (os.path.exists(fn) and os.access(fn, mode)
                and not os.path.isdir(fn))

    # If we're given a path with a directory part, look it up directly rather
    # than referring to PATH directories. This includes checking relative to the
    # current directory, e.g. ./script
    if os.path.dirname(cmd):
        if _access_check(cmd, mode):
            return cmd
        return None

    if path is None:
        path = os.environ.get("PATH", os.defpath)
    if not path:
        return None

    path = path.split(os.pathsep)
    if include_settings_path and Settings().path:
        path = Settings().path.split(os.pathsep) + path

    if sys.platform == "win32":
        # The current directory takes precedence on Windows.
        if not os.curdir in path:
            path.insert(0, os.curdir)

        # PATHEXT is necessary to check on Windows.
        pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
        # See if the given file matches any of the expected path extensions.
        # This will allow us to short circuit when given "python.exe".
        # If it does match, only test that one, otherwise we have to try
        # others.
        if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
            files = [cmd]
        else:
            files = [cmd + ext for ext in pathext]
    else:
        # On other platforms you don't have things like PATHEXT to tell you
        # what file suffixes are executable, so just pass on cmd as-is.
        files = [cmd]

    seen = set()

    for dir in path:
        normdir = os.path.normcase(dir)
        if not normdir in seen:
            seen.add(normdir)
            for thefile in files:
                name = os.path.join(dir, thefile)
                if _access_check(name, mode):
                    return name
    return None