def pyls_lint(config: Config, workspace: Workspace, document: Document, is_saved: bool) -> List[Dict[str, Any]]: """ Lints. Parameters ---------- config : Config The pyls config. workspace : Workspace The pyls workspace. document : Document The document to be linted. is_saved : bool Weather the document is saved. Returns ------- List[Dict[str, Any]] List of the linting data. """ settings = config.plugin_settings('pyls_mypy') live_mode = settings.get('live_mode', True) args = settings.get('args', []) args.extend([ '--incremental', '--show-column-numbers', '--follow-imports', 'silent' ]) global tmpFile if live_mode and not is_saved and tmpFile: tmpFile = open(tmpFile.name, "w") tmpFile.write(document.source) tmpFile.close() args.extend(['--shadow-file', document.path, tmpFile.name]) elif not is_saved: return [] if mypyConfigFile: args.append('--config-file') args.append(mypyConfigFile) args.append(document.path) if settings.get('strict', False): args.append('--strict') report, errors, _ = mypy_api.run(args) diagnostics = [] for line in report.splitlines(): diag = parse_line(line, document) if diag: diagnostics.append(diag) return diagnostics
def pyls_document_symbols(config: Config, workspace: Workspace, document: Document) -> List[Dict]: """Cell and block comment extraction.""" settings = config.plugin_settings('pyls_spyder') group_cells = settings.get('group_cells', True) enable_block_comments = settings.get('enable_block_comments', True) lines = document.lines cells = [] blocks = [] cell_stack = [] unnamed_cell = 1 unnamed_block = 1 for line_num, line in enumerate(lines): cell_rule, cell_match = CELL_REGEX.match(line) block_rule, block_match = BLOCK_REGEX.match(line) if cell_match is not None: percentages = cell_match.group(1) cell_name = cell_match.group(2).strip() if cell_name == '': cell_name = 'Unnamed cell {0}'.format(unnamed_cell) unnamed_cell += 1 if not group_cells or cell_rule != CELL_PERCENTAGE: cells.append( create_symbol(cell_name, document, line_num, line_num + 1)) else: current_line, current_level, current_name = peek_symbol( cell_stack) cell_level = len(percentages) - 1 if cell_level > current_level: cell_stack.insert(0, (line_num, cell_level, cell_name)) else: while current_level >= cell_level: cell_stack.pop(0) cells.append( create_symbol(current_name, document, current_line, line_num)) (current_line, current_level, current_name) = peek_symbol(cell_stack) cell_stack.insert(0, (line_num, cell_level, cell_name)) elif block_match is not None and enable_block_comments: block_name = block_match.group(1).strip() if block_name == '': block_name = 'Unnamed comment {0}'.format(unnamed_block) unnamed_block += 1 blocks.append( create_symbol(block_name, document, line_num, line_num + 1, False)) for line, _, name in cell_stack: cells.append(create_symbol(name, document, line, line_num + 1)) spyder_symbols = cells + blocks spyder_symbols = sorted( spyder_symbols, key=lambda x: x['location']['range']['start']['line']) return spyder_symbols
def pyls_lint(config: Config, workspace: Workspace, document: Document, is_saved: bool) -> List[Dict[str, Any]]: """ Lints. Parameters ---------- config : Config The pyls config. workspace : Workspace The pyls workspace. document : Document The document to be linted. is_saved : bool Weather the document is saved. Returns ------- List[Dict[str, Any]] List of the linting data. """ settings = config.plugin_settings('mypy-ls') log.info( "lint settings = %s document.path = %s is_saved = %s", settings, document.path, is_saved ) live_mode = settings.get('live_mode', True) dmypy = settings.get("dmypy", False) if dmypy and live_mode: # dmypy can only be efficiently run on files that have been saved, see: # https://github.com/python/mypy/issues/9309 log.warning("live_mode is not supported with dmypy, disabling") live_mode = False args = ['--show-column-numbers'] prepend = settings.get('prepend') if prepend: args = prepend + args modified_time = os.path.getmtime(document.path) global tmpFile if live_mode and not is_saved and tmpFile: log.info("live_mode tmpFile = %s", live_mode) tmpFile = open(tmpFile.name, "w") tmpFile.write(document.source) tmpFile.close() args.extend(['--shadow-file', document.path, tmpFile.name]) elif ( not is_saved and document.path in last_diagnostics and last_updated[document.path] == modified_time ): # On-launch the document isn't marked as saved, so fall through and run # the diagnostics anyway even if the file contents may be out of date. log.info( "non-live, returning cached diagnostics len(cached) = %s", last_diagnostics[document.path] ) return last_diagnostics[document.path] last_updated[document.path] = modified_time if mypyConfigFile: args.append('--config-file') args.append(mypyConfigFile) args.append(document.path) if settings.get('strict', False): args.append('--strict') if not dmypy: args.extend([ "--incremental", "--follow-imports", "silent" ]) log.info(f"executing mypy {args=}") report, errors, _ = mypy_api.run(args) else: args = ["run", "--"] + args log.info(f"executing dmypy {args=}") report, errors, _ = mypy_api.run_dmypy(args) log.debug("report: \n" + report) log.debug("errors: \n" + errors) diagnostics = [] for line in report.splitlines(): log.debug(f"parsing: {line=}") diag = parse_line(line, document) if diag: diagnostics.append(diag) logging.info("mypy-ls len(diagnostics) = %s", len(diagnostics)) last_diagnostics[document.path] = diagnostics return diagnostics