Tue, 01 May 2018 12:03:52 +0200
Merged with default branch to prepare new release.
--- a/APIs/Python3/eric6.api Mon Apr 02 12:04:56 2018 +0200 +++ b/APIs/Python3/eric6.api Tue May 01 12:03:52 2018 +0200 @@ -501,6 +501,7 @@ eric6.Debugger.DebugUI.DebugUI.compileResources?7 eric6.Debugger.DebugUI.DebugUI.debuggingStarted?7 eric6.Debugger.DebugUI.DebugUI.exceptionInterrupt?7 +eric6.Debugger.DebugUI.DebugUI.executeMake?7 eric6.Debugger.DebugUI.DebugUI.getActions?4() eric6.Debugger.DebugUI.DebugUI.initActions?4() eric6.Debugger.DebugUI.DebugUI.initMenus?4() @@ -1563,6 +1564,7 @@ eric6.E5XML.Config.pluginRepositoryFileFormatVersion?7 eric6.E5XML.Config.projectFileFormatVersion?7 eric6.E5XML.Config.projectFileFormatVersionAlt?7 +eric6.E5XML.Config.projectFileFormatVersionProto?7 eric6.E5XML.Config.sessionFileFormatVersion?7 eric6.E5XML.Config.shortcutsFileFormatVersion?7 eric6.E5XML.Config.tasksFileFormatVersion?7 @@ -3905,7 +3907,7 @@ eric6.PluginManager.PluginManager.PluginManager.removePluginFromSysModules?4(pluginName, package, internalPackages) eric6.PluginManager.PluginManager.PluginManager.shutdown?7 eric6.PluginManager.PluginManager.PluginManager.unloadPlugin?4(name) -eric6.PluginManager.PluginManager.PluginManager?1(parent=None, doLoadPlugins=True, develPlugin=None) +eric6.PluginManager.PluginManager.PluginManager?1(parent=None, disabledPlugins=None, doLoadPlugins=True, develPlugin=None) eric6.PluginManager.PluginRepositoryDialog.PluginRepositoryDialog.getDownloadedPlugins?4() eric6.PluginManager.PluginRepositoryDialog.PluginRepositoryDialog?1(parent=None) eric6.PluginManager.PluginRepositoryDialog.PluginRepositoryDownloadCleanup?4(quiet=False) @@ -3991,7 +3993,7 @@ eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.CodeStyleFixer.fixIssue?4(line, pos, message) eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.CodeStyleFixer.mutualStartswith?4(b) eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.CodeStyleFixer.saveFile?4(encoding) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.CodeStyleFixer?1(filename, sourceLines, fixCodes, noFixCodes, maxLineLength, inPlace, eol, backup=False) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.CodeStyleFixer?1(filename, sourceLines, fixCodes, noFixCodes, maxLineLength, blankLines, inPlace, eol, backup=False) eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.FixableCodeStyleIssues?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.IndentationWrapper.SKIP_TOKENS?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.IndentationWrapper.pep8Expected?4() @@ -4094,41 +4096,16 @@ eric6.Plugins.CheckerPlugins.CodeStyleChecker.mccabe.PathNode?1(name, look="circle") eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.ARITHMETIC_OP?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BENCHMARK_KEYS?7 -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport.error?4(line_number, offset, text, check) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport.error_args?4(line_number, offset, text, check, *args) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport.get_count?4(prefix='') -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport.get_file_results?4() -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport.get_statistics?4(prefix='') -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport.increment_logical_line?4() -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport.init_file?4(filename, lines, expected, line_offset) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport.print_benchmark?4() +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BLANK_LINES_CONFIG?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport.print_filename?7 -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport.print_statistics?4(prefix='') -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport.start?4() -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport.stop?4() -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.BaseReport?1(options) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.COMMENT_WITH_NL?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.COMPARE_NEGATIVE_REGEX?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.COMPARE_SINGLETON_REGEX?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.COMPARE_TYPE_REGEX?7 -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.Checker.build_tokens_line?4() -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.Checker.check_all?4(expected=None, line_offset=0) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.Checker.check_ast?4() -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.Checker.check_logical?4() -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.Checker.check_physical?4(line) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.Checker.generate_tokens?4() -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.Checker.init_checker_state?4(name, argument_names) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.Checker.maybe_check_physical?4(token) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.Checker.readline?4() -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.Checker.report_invalid_syntax?4() -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.Checker.run_check?4(check, argument_names) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.Checker?1(filename=None, lines=None, options=None, report=None, **kwargs) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.DEFAULT_EXCLUDE?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.DEFAULT_IGNORE?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.DOCSTRING_REGEX?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.DUNDER_REGEX?7 -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.DiffReport.error?4(line_number, offset, text, check) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.DiffReport?1(options) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.ERRORCODE_REGEX?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.EXTRANEOUS_WHITESPACE_REGEX?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.FileReport.print_filename?7 @@ -4151,19 +4128,6 @@ eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.STARTSWITH_DEF_REGEX?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.STARTSWITH_INDENT_STATEMENT_REGEX?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.STARTSWITH_TOP_LEVEL_REGEX?7 -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StandardReport.error?4(line_number, offset, text, check) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StandardReport.error_args?4(line_number, offset, code, check, *args) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StandardReport.get_file_results?4() -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StandardReport.init_file?4(filename, lines, expected, line_offset) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StandardReport?1(options) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StyleGuide.check_files?4(paths=None) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StyleGuide.excluded?4(filename, parent=None) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StyleGuide.get_checks?4(argument_name) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StyleGuide.ignore_code?4(code) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StyleGuide.init_report?4(reporter=None) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StyleGuide.input_dir?4(dirname) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StyleGuide.input_file?4(filename, lines=None, expected=None, line_offset=0) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.StyleGuide?1(*args, **kwargs) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.TESTSUITE_PATH?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.UNARY_OPERATORS?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.WHITESPACE?7 @@ -4171,8 +4135,10 @@ eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.WS_NEEDED_OPERATORS?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.WS_OPTIONAL_OPERATORS?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle._add_check?5(check, kind, codes, args) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle._break_around_binary_operators?5(tokens) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle._checks?8 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle._get_parameters?5(function) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle._is_binary_operator?5(token_type, text) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle._is_eol_token?5(token) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle._is_eol_token?5(token, _eol_token=_is_eol_token) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle._main?5() @@ -4180,23 +4146,46 @@ eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.ambiguous_identifier?4(logical_line, tokens) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.bare_except?4(logical_line, noqa) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.blank_lines?4(logical_line, blank_lines, indent_level, line_number, blank_before, previous_logical, previous_unindented_logical_line, previous_indent_level, lines) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.break_around_binary_operator?4(logical_line, tokens) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.break_after_binary_operator?4(logical_line, tokens) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.break_before_binary_operator?4(logical_line, tokens) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.build_tokens_line?4(self) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.check_all?4(self, expected=None, line_offset=0) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.check_ast?4(self) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.check_files?4(self, paths=None) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.check_logical?4(self) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.check_physical?4(self, line) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.comparison_negative?4(logical_line) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.comparison_to_singleton?4(logical_line, noqa) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.comparison_type?4(logical_line, noqa) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.compound_statements?4(logical_line) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.continued_indentation?4(logical_line, tokens, indent_level, hang_closing, indent_char, noqa, verbose) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.error?4(self, line_number, offset, text, check) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.error_args?4(self, line_number, offset, code, check, *args) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.error_args?4(self, line_number, offset, text, check, *args) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.excluded?4(self, filename, parent=None) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.expand_indent?4(line) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.explicit_line_join?4(logical_line, tokens) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.extraneous_whitespace?4(logical_line) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.filename_match?4(filename, patterns, default=True) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.generate_tokens?4(self) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.get_checks?4(self, argument_name) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.get_count?4(self, prefix='') +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.get_file_results?4(self) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.get_parser?4(prog='pycodestyle', version=__version__) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.get_statistics?4(self, prefix='') +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.ignore_code?4(self, code) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.imports_on_separate_lines?4(logical_line) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.increment_logical_line?4(self) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.indentation?4(logical_line, previous_logical, indent_char, indent_level, previous_indent_level) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.init_checks_registry?4() -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.is_binary_operator?4(token_type, text) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.init_checker_state?4(self, name, argument_names) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.init_file?4(self, filename, lines, expected, line_offset) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.init_report?4(self, reporter=None) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.input_dir?4(self, dirname) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.input_file?4(self, filename, lines=None, expected=None, line_offset=0) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.is_string_literal?4(line) -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.maximum_line_length?4(physical_line, max_line_length, multiline, noqa) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.lru_cache?4(maxsize=128) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.maximum_line_length?4(physical_line, max_line_length, multiline, line_number, noqa) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.maybe_check_physical?4(self, token) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.missing_whitespace?4(logical_line) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.missing_whitespace_after_import_keyword?4(logical_line) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.missing_whitespace_around_operator?4(logical_line, tokens) @@ -4205,15 +4194,24 @@ eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.noqa?7 eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.normalize_paths?4(value, parent=os.curdir) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.parse_udiff?4(diff, patterns=None, parent='.') -eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.process_options?4(arglist=None, parse_argv=False, config_file=None, parser=None) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.print_benchmark?4(self) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.print_statistics?4(self, prefix='') +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.process_options?4(arglist=None, parse_argv=False, config_file=None, parser=None, verbose=None) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.python_3000_async_await_keywords?4(logical_line, tokens) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.python_3000_backticks?4(logical_line) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.python_3000_has_key?4(logical_line, noqa) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.python_3000_invalid_escape_sequence?4(logical_line, tokens) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.python_3000_not_equal?4(logical_line) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.python_3000_raise_comma?4(logical_line) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.read_config?4(options, args, arglist, parser) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.readline?4(self) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.readlines?4(filename) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.register_check?4(check, codes=None) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.report_invalid_syntax?4(self) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.run_check?4(self, check, argument_names) +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.start?4(self) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.stdin_get_value?4() +eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.stop?4(self) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.tabs_obsolete?4(physical_line) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.tabs_or_spaces?4(physical_line, indent_char) eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.trailing_blank_lines?4(physical_line, lines, line_number, total_lines) @@ -4872,7 +4870,9 @@ eric6.Plugins.UiExtensionPlugins.PipInterface.ConfigurationPage.PipPage.PipPage.on_defaultListButton_clicked?4() eric6.Plugins.UiExtensionPlugins.PipInterface.ConfigurationPage.PipPage.PipPage.save?4() eric6.Plugins.UiExtensionPlugins.PipInterface.ConfigurationPage.PipPage.PipPage?1(plugin) -eric6.Plugins.UiExtensionPlugins.PipInterface.DefaultIndexUrl?7 +eric6.Plugins.UiExtensionPlugins.PipInterface.DefaultIndexUrlPip?7 +eric6.Plugins.UiExtensionPlugins.PipInterface.DefaultIndexUrlXml?7 +eric6.Plugins.UiExtensionPlugins.PipInterface.DefaultPyPiUrl?7 eric6.Plugins.UiExtensionPlugins.PipInterface.Pip.Pip.getMenu?4(name) eric6.Plugins.UiExtensionPlugins.PipInterface.Pip.Pip.getMenuNames?4() eric6.Plugins.UiExtensionPlugins.PipInterface.Pip.Pip.initActions?4() @@ -7771,6 +7771,9 @@ eric6.Project.LexerAssociationDialog.LexerAssociationDialog.on_editorLexerList_itemClicked?4(itm, column) eric6.Project.LexerAssociationDialog.LexerAssociationDialog.transferData?4() eric6.Project.LexerAssociationDialog.LexerAssociationDialog?1(project, parent=None) +eric6.Project.MakePropertiesDialog.MakePropertiesDialog.initDialog?4() +eric6.Project.MakePropertiesDialog.MakePropertiesDialog.storeData?4() +eric6.Project.MakePropertiesDialog.MakePropertiesDialog?1(project, new, parent=None) eric6.Project.NewDialogClassDialog.NewDialogClassDialog.getData?4() eric6.Project.NewDialogClassDialog.NewDialogClassDialog.on_classnameEdit_textChanged?4(text) eric6.Project.NewDialogClassDialog.NewDialogClassDialog.on_filenameEdit_textChanged?4(text) @@ -7779,6 +7782,8 @@ eric6.Project.NewPythonPackageDialog.NewPythonPackageDialog.getData?4() eric6.Project.NewPythonPackageDialog.NewPythonPackageDialog.on_packageEdit_textChanged?4(txt) eric6.Project.NewPythonPackageDialog.NewPythonPackageDialog?1(relPath, parent=None) +eric6.Project.Project.Project.DefaultMake?7 +eric6.Project.Project.Project.DefaultMakefile?7 eric6.Project.Project.Project.addDirectory?4(fileTypeFilter=None, startdir=None) eric6.Project.Project.Project.addE5Actions?4(actions) eric6.Project.Project.Project.addFiles?4(fileTypeFilter=None, startdir=None) @@ -7797,6 +7802,8 @@ eric6.Project.Project.Project.addUiDir?4() eric6.Project.Project.Project.addUiFiles?4() eric6.Project.Project.Project.appendFile?4(fn, isSourceFile=False, updateModel=True) +eric6.Project.Project.Project.appendStderr?7 +eric6.Project.Project.Project.appendStdout?7 eric6.Project.Project.Project.checkAllScriptsDirty?4(reportSyntaxErrors=False) eric6.Project.Project.Project.checkDirty?4() eric6.Project.Project.Project.checkLanguageFiles?4() @@ -7816,6 +7823,7 @@ eric6.Project.Project.Project.directoryRemoved?7 eric6.Project.Project.Project.dirty?7 eric6.Project.Project.Project.eols?7 +eric6.Project.Project.Project.executeMake?4() eric6.Project.Project.Project.getAbsolutePath?4(fn) eric6.Project.Project.Project.getAbsoluteUniversalPath?4(fn) eric6.Project.Project.Project.getActions?4() @@ -7855,6 +7863,7 @@ eric6.Project.Project.Project.getVcs?4() eric6.Project.Project.Project.handleApplicationDiagram?4() eric6.Project.Project.Project.handlePreferencesChanged?4() +eric6.Project.Project.Project.hasDefaultMakeParameters?4() eric6.Project.Project.Project.hasEntry?4(fn) eric6.Project.Project.Project.hasProjectType?4(type_, progLanguage="") eric6.Project.Project.Project.initActions?4() @@ -7865,6 +7874,7 @@ eric6.Project.Project.Project.isDebugPropertiesLoaded?4() eric6.Project.Project.Project.isDirty?4() eric6.Project.Project.Project.isJavaScriptProject?4() +eric6.Project.Project.Project.isMakeEnabled?4() eric6.Project.Project.Project.isMixedLanguageProject?4() eric6.Project.Project.Project.isOpen?4() eric6.Project.Project.Project.isProjectFile?4(fn) @@ -8115,6 +8125,7 @@ eric6.Project.PropertiesDialog.PropertiesDialog.on_languageComboBox_currentIndexChanged?4(language) eric6.Project.PropertiesDialog.PropertiesDialog.on_mainscriptPicker_aboutToShowPathPickerDialog?4() eric6.Project.PropertiesDialog.PropertiesDialog.on_mainscriptPicker_pathSelected?4(script) +eric6.Project.PropertiesDialog.PropertiesDialog.on_makeButton_clicked?4() eric6.Project.PropertiesDialog.PropertiesDialog.on_spellPropertiesButton_clicked?4() eric6.Project.PropertiesDialog.PropertiesDialog.on_transPropertiesButton_clicked?4() eric6.Project.PropertiesDialog.PropertiesDialog.on_vcsInfoButton_clicked?4() @@ -8219,7 +8230,7 @@ eric6.QScintilla.Editor.Editor.WarningStyle?7 eric6.QScintilla.Editor.Editor.addCallTipHook?4(key, func) eric6.QScintilla.Editor.Editor.addClone?4(editor) -eric6.QScintilla.Editor.Editor.addCompletionListHook?4(key, func, async=False) +eric6.QScintilla.Editor.Editor.addCompletionListHook?4(key, func, asynchroneous=False) eric6.QScintilla.Editor.Editor.addedToProject?4() eric6.QScintilla.Editor.Editor.autoComplete?4(auto=False, context=True) eric6.QScintilla.Editor.Editor.autoCompleteQScintilla?4() @@ -9917,7 +9928,7 @@ eric6.UI.UserInterface.UserInterface.showReplaceFilesDialog?4(txt="", searchDir="", openFiles=False) eric6.UI.UserInterface.UserInterface.unregisterToolbar?4(name) eric6.UI.UserInterface.UserInterface.versionIsNewer?4(required, snapshot=None) -eric6.UI.UserInterface.UserInterface?1(app, locale, splash, plugin, noOpenAtStartup, noCrashOpenAtStartup, disableCrashSession, restartArguments) +eric6.UI.UserInterface.UserInterface?1(app, locale, splash, plugin, disabledPlugins, noOpenAtStartup, noCrashOpenAtStartup, disableCrashSession, restartArguments) eric6.Utilities.AutoSaver.AutoSaver.AUTOSAVE_IN?7 eric6.Utilities.AutoSaver.AutoSaver.MAXWAIT?7 eric6.Utilities.AutoSaver.AutoSaver.changeOccurred?4() @@ -10452,14 +10463,15 @@ eric6.ViewManager.ViewManager.ViewManager.checkActions?7 eric6.ViewManager.ViewManager.ViewManager.checkAllDirty?4() eric6.ViewManager.ViewManager.ViewManager.checkDirty?4(editor, autosave=False) +eric6.ViewManager.ViewManager.ViewManager.checkFileDirty?4(fn) eric6.ViewManager.ViewManager.ViewManager.clearRecent?4() eric6.ViewManager.ViewManager.ViewManager.cloneEditor?4(caller, filetype, fn) eric6.ViewManager.ViewManager.ViewManager.closeAllWindows?4() eric6.ViewManager.ViewManager.ViewManager.closeCurrentWindow?4() -eric6.ViewManager.ViewManager.ViewManager.closeEditor?4(editor) +eric6.ViewManager.ViewManager.ViewManager.closeEditor?4(editor, ignoreDirty=False) eric6.ViewManager.ViewManager.ViewManager.closeEditorWindow?4(editor) eric6.ViewManager.ViewManager.ViewManager.closeViewManager?4() -eric6.ViewManager.ViewManager.ViewManager.closeWindow?4(fn) +eric6.ViewManager.ViewManager.ViewManager.closeWindow?4(fn, ignoreDirty=False) eric6.ViewManager.ViewManager.ViewManager.cursorChanged?7 eric6.ViewManager.ViewManager.ViewManager.editorChanged?7 eric6.ViewManager.ViewManager.ViewManager.editorChangedEd?7 @@ -11022,6 +11034,7 @@ eric6.WebBrowser.Download.DownloadItem.DownloadItem.currentSpeed?4() eric6.WebBrowser.Download.DownloadItem.DownloadItem.downloadCanceled?4() eric6.WebBrowser.Download.DownloadItem.DownloadItem.downloadFinished?7 +eric6.WebBrowser.Download.DownloadItem.DownloadItem.downloadProgress?4() eric6.WebBrowser.Download.DownloadItem.DownloadItem.downloadedSuccessfully?4() eric6.WebBrowser.Download.DownloadItem.DownloadItem.downloading?4() eric6.WebBrowser.Download.DownloadItem.DownloadItem.fileName?4() @@ -11042,6 +11055,7 @@ eric6.WebBrowser.Download.DownloadManager.DownloadManager.RemoveExit?7 eric6.WebBrowser.Download.DownloadManager.DownloadManager.RemoveNever?7 eric6.WebBrowser.Download.DownloadManager.DownloadManager.RemoveSuccessFullDownload?7 +eric6.WebBrowser.Download.DownloadManager.DownloadManager.UpdateTimerTimeout?7 eric6.WebBrowser.Download.DownloadManager.DownloadManager.activeDownloadsCount?4() eric6.WebBrowser.Download.DownloadManager.DownloadManager.allowQuit?4() eric6.WebBrowser.Download.DownloadManager.DownloadManager.changeOccurred?4() @@ -11057,7 +11071,9 @@ eric6.WebBrowser.Download.DownloadManager.DownloadManager.save?4() eric6.WebBrowser.Download.DownloadManager.DownloadManager.setDownloadDirectory?4(directory) eric6.WebBrowser.Download.DownloadManager.DownloadManager.setRemovePolicy?4(policy) +eric6.WebBrowser.Download.DownloadManager.DownloadManager.show?4() eric6.WebBrowser.Download.DownloadManager.DownloadManager.shutdown?4() +eric6.WebBrowser.Download.DownloadManager.DownloadManager.timerEvent?4(evt) eric6.WebBrowser.Download.DownloadManager.DownloadManager?1(parent=None) eric6.WebBrowser.Download.DownloadManagerButton.DownloadManagerButton?1(parent=None) eric6.WebBrowser.Download.DownloadModel.DownloadModel.data?4(index, role) @@ -11067,6 +11083,7 @@ eric6.WebBrowser.Download.DownloadModel.DownloadModel.rowCount?4(parent=None) eric6.WebBrowser.Download.DownloadModel.DownloadModel?1(manager, parent=None) eric6.WebBrowser.Download.DownloadUtilities.dataString?4(size) +eric6.WebBrowser.Download.DownloadUtilities.speedString?4(speed) eric6.WebBrowser.Download.DownloadUtilities.timeString?4(timeRemaining) eric6.WebBrowser.FeaturePermissions.FeaturePermissionBar.FeaturePermissionBar.DefaultHeight?7 eric6.WebBrowser.FeaturePermissions.FeaturePermissionBar.FeaturePermissionBar.hide?4() @@ -11648,6 +11665,9 @@ eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.ClientId?7 eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.ClientVersion?7 eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.GsbUrlTemplate?7 +eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.definedPlatformTypes?4() +eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.definedThreatEntryTypes?4() +eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.definedThreatTypes?4() eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.fairUseDelayExpired?4() eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.getFairUseDelayExpirationDateTime?4() eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.getFullHashes?4(prefixes, clientState) @@ -11658,10 +11678,10 @@ eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.getThreatMessage?4(threatType) eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.getThreatType?4(threatType) eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.getThreatsUpdate?4(clientStates) +eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.lookupUrl?4(url, platforms) eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.networkError?7 eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient.setApiKey?4(apiKey) eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.SafeBrowsingAPIClient?1(apiKey, fairUse=True, parent=None) -eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.HashPrefixList?1(prefixLength, rawHashes) eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.SafeBrowsingCache.addThreatList?4(threatList) eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.SafeBrowsingCache.cleanupFullHashes?4(keepExpiredFor=43200) eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.SafeBrowsingCache.close?4() @@ -11692,9 +11712,6 @@ eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.SafeBrowsingCache.updateHashPrefixExpiration?4(threatList, hashPrefix, negativeCacheDuration) eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.SafeBrowsingCache.updateThreatListClientState?4(threatList, clientState) eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.SafeBrowsingCache?1(dbPath, parent=None) -eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.ThreatList.asTuple?4() -eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.ThreatList.fromApiEntry?4(entry) -eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.ThreatList?1(threatType, platformType, threatEntryType) eric6.WebBrowser.SafeBrowsing.SafeBrowsingDialog.SafeBrowsingDialog.closeEvent?4(evt) eric6.WebBrowser.SafeBrowsing.SafeBrowsingDialog.SafeBrowsingDialog.on_buttonBox_clicked?4(button) eric6.WebBrowser.SafeBrowsing.SafeBrowsingDialog.SafeBrowsingDialog.on_clearCacheButton_clicked?4() @@ -11735,6 +11752,10 @@ eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.SafeBrowsingManager.showSafeBrowsingDialog?4() eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.SafeBrowsingManager.updateHashPrefixCache?4() eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.SafeBrowsingManager?1() +eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.HashPrefixList?1(prefixLength, rawHashes) +eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.ThreatList.asTuple?4() +eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.ThreatList.fromApiEntry?4(entry) +eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.ThreatList?1(threatType, platformType, threatEntryType) eric6.WebBrowser.SafeBrowsing.SafeBrowsingUrl.SafeBrowsingUrl.canonical?4() eric6.WebBrowser.SafeBrowsing.SafeBrowsingUrl.SafeBrowsingUrl.digest?4() eric6.WebBrowser.SafeBrowsing.SafeBrowsingUrl.SafeBrowsingUrl.fullUnescape?4() @@ -12186,6 +12207,7 @@ eric6.WebBrowser.WebBrowserTabWidget.WebBrowserTabWidget.closeAllBrowsers?4(shutdown=False) eric6.WebBrowser.WebBrowserTabWidget.WebBrowserTabWidget.closeBrowser?4() eric6.WebBrowser.WebBrowserTabWidget.WebBrowserTabWidget.closeBrowserAt?4(index, shutdown=False) +eric6.WebBrowser.WebBrowserTabWidget.WebBrowserTabWidget.closeBrowserView?4(browser) eric6.WebBrowser.WebBrowserTabWidget.WebBrowserTabWidget.closedTabsManager?4() eric6.WebBrowser.WebBrowserTabWidget.WebBrowserTabWidget.currentBrowser?4() eric6.WebBrowser.WebBrowserTabWidget.WebBrowserTabWidget.currentUrlBar?4() @@ -12207,6 +12229,7 @@ eric6.WebBrowser.WebBrowserTabWidget.WebBrowserTabWidget.sourceChanged?7 eric6.WebBrowser.WebBrowserTabWidget.WebBrowserTabWidget.stackedUrlBar?4() eric6.WebBrowser.WebBrowserTabWidget.WebBrowserTabWidget.titleChanged?7 +eric6.WebBrowser.WebBrowserTabWidget.WebBrowserTabWidget.urlBarForView?4(view) eric6.WebBrowser.WebBrowserTabWidget.WebBrowserTabWidget?1(parent) eric6.WebBrowser.WebBrowserView.WebBrowserView.ZoomLevelDefault?7 eric6.WebBrowser.WebBrowserView.WebBrowserView.ZoomLevels?7 @@ -12276,6 +12299,7 @@ eric6.WebBrowser.WebBrowserView.WebBrowserView.source?4() eric6.WebBrowser.WebBrowserView.WebBrowserView.sourceChanged?7 eric6.WebBrowser.WebBrowserView.WebBrowserView.storeSessionData?4(data) +eric6.WebBrowser.WebBrowserView.WebBrowserView.tabWidget?4() eric6.WebBrowser.WebBrowserView.WebBrowserView.title?4() eric6.WebBrowser.WebBrowserView.WebBrowserView.undo?4() eric6.WebBrowser.WebBrowserView.WebBrowserView.unselect?4() @@ -12329,6 +12353,8 @@ eric6.WebBrowser.WebBrowserWindow.WebBrowserWindow.bookmarksManager?4() eric6.WebBrowser.WebBrowserWindow.WebBrowserWindow.browserAt?4(index) eric6.WebBrowser.WebBrowserWindow.WebBrowserWindow.browsers?4() +eric6.WebBrowser.WebBrowserWindow.WebBrowserWindow.closeBrowser?4(browser) +eric6.WebBrowser.WebBrowserWindow.WebBrowserWindow.closeCurrentBrowser?4() eric6.WebBrowser.WebBrowserWindow.WebBrowserWindow.closeEvent?4(e) eric6.WebBrowser.WebBrowserWindow.WebBrowserWindow.cookieJar?4() eric6.WebBrowser.WebBrowserWindow.WebBrowserWindow.createPopupMenu?4() @@ -12569,6 +12595,7 @@ eric6.install.macPythonExe?7 eric6.install.main?4(argv) eric6.install.modDir?7 +eric6.install.pipInstall?4(packageName, message) eric6.install.platBinDir?7 eric6.install.platBinDirOld?7 eric6.install.prepareInfoFile?4(fileName)
--- a/APIs/Python3/eric6.bas Mon Apr 02 12:04:56 2018 +0200 +++ b/APIs/Python3/eric6.bas Tue May 01 12:03:52 2018 +0200 @@ -580,6 +580,7 @@ LogViewerEdit QTextEdit LogViewerPage ConfigurationPageBase Ui_LogViewerPage LoggingVisitor ast.NodeVisitor +MakePropertiesDialog QDialog Ui_MakePropertiesDialog ManageDictionariesDialog QDialog Ui_ManageDictionariesDialog MarkdownProvider MarkupBase MasterPasswordEntryDialog QDialog Ui_MasterPasswordEntryDialog
--- a/DTDs/Project-4.6.dtd Mon Apr 02 12:04:56 2018 +0200 +++ b/DTDs/Project-4.6.dtd Tue May 01 12:03:52 2018 +0200 @@ -100,7 +100,7 @@ <!ELEMENT ProjectTypeSpecificData (dict)> -<!ELEMENT ProjectTypeSpecific (ExtraData?)> +<!ELEMENT ProjectTypeSpecific (ProjectTypeSpecific?)> <!ELEMENT DocumentationParams (dict)> @@ -146,7 +146,7 @@ Vcs, FiletypeAssociations, LexerAssociations?, - Extra?, + ProjectTypeSpecific?, Documentation?, Packagers?, Checkers?,
--- a/DTDs/Project-5.0.dtd Mon Apr 02 12:04:56 2018 +0200 +++ b/DTDs/Project-5.0.dtd Tue May 01 12:03:52 2018 +0200 @@ -107,7 +107,7 @@ <!ELEMENT ProjectTypeSpecificData (dict)> -<!ELEMENT ProjectTypeSpecific (ExtraData?)> +<!ELEMENT ProjectTypeSpecific (ProjectTypeSpecific?)> <!ELEMENT DocumentationParams (dict)> @@ -129,11 +129,11 @@ <!ELEMENT ProjectWordList (#PCDATA)> -<!ELEMENT ProjectExcludeList (#PCDATA)> - +<!ELEMENT ProjectExcludeList (#PCDATA)> + <!ELEMENT Hash (#PCDATA)> -<!ELEMENT Project (Language, +<!ELEMENT Project (Language, ProjectWordList?, ProjectExcludeList?, Hash, @@ -156,7 +156,7 @@ Vcs, FiletypeAssociations, LexerAssociations?, - Extra?, + ProjectTypeSpecific?, Documentation?, Packagers?, Checkers?,
--- a/DTDs/Project-5.1.dtd Mon Apr 02 12:04:56 2018 +0200 +++ b/DTDs/Project-5.1.dtd Tue May 01 12:03:52 2018 +0200 @@ -107,7 +107,7 @@ <!ELEMENT ProjectTypeSpecificData (dict)> -<!ELEMENT ProjectTypeSpecific (ExtraData?)> +<!ELEMENT ProjectTypeSpecific (ProjectTypeSpecific?)> <!ELEMENT DocumentationParams (dict)> @@ -161,7 +161,7 @@ Vcs, FiletypeAssociations, LexerAssociations?, - Extra?, + ProjectTypeSpecific?, Documentation?, Packagers?, Checkers?,
--- a/DTDs/Project-6.0.dtd Mon Apr 02 12:04:56 2018 +0200 +++ b/DTDs/Project-6.0.dtd Tue May 01 12:03:52 2018 +0200 @@ -111,7 +111,7 @@ <!ELEMENT ProjectTypeSpecificData (dict)> -<!ELEMENT ProjectTypeSpecific (ExtraData?)> +<!ELEMENT ProjectTypeSpecific (ProjectTypeSpecific?)> <!ELEMENT DocumentationParams (dict)> @@ -165,7 +165,7 @@ Vcs, FiletypeAssociations, LexerAssociations?, - Extra?, + ProjectTypeSpecific?, Documentation?, Packagers?, Checkers?,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DTDs/Project-6.1.dtd Tue May 01 12:03:52 2018 +0200 @@ -0,0 +1,179 @@ +<!-- This is the DTD for eric5's project file version 6.0 --> + +<!-- This is a copy of the Basic DTD --> +<!ELEMENT int (#PCDATA)> +<!ELEMENT long (#PCDATA)> +<!ELEMENT float (#PCDATA)> +<!ELEMENT complex (#PCDATA)> +<!ELEMENT bool (#PCDATA)> +<!ELEMENT string (#PCDATA)> +<!ELEMENT bytes (#PCDATA)> +<!ELEMENT bytearray (#PCDATA)> +<!ELEMENT none EMPTY> + +<!ELEMENT pickle (#PCDATA)> +<!ATTLIST pickle + method CDATA #REQUIRED + encoding CDATA #REQUIRED> + +<!ELEMENT key (int | long | float | complex | string | bytes)> +<!ELEMENT value (int | long | float | complex | bool | string | bytes | + bytearray | none | dict | tuple | list | set | frozenset | pickle)> + +<!ELEMENT dict (key, value)*> + +<!ELEMENT tuple (int | long | float | complex | bool | string | bytes | + bytearray | none | dict | tuple | list | set | frozenset | pickle)*> + +<!ELEMENT list (int | long | float | complex | bool | string | bytes | + bytearray | none | dict | tuple | list | set | frozenset | pickle)*> + +<!ELEMENT set (int | long | float | complex | bool | string | bytes | + bytearray | none | dict | tuple | list | set | frozenset | pickle)*> + +<!ELEMENT frozenset (int | long | float | complex | bool | string | bytes | + bytearray | none | dict | tuple | list | set | frozenset | pickle)*> +<!-- End of the Basic DTD --> + +<!ELEMENT ProgLanguage (#PCDATA)> +<!ATTLIST ProgLanguage + mixed CDATA #REQUIRED> + +<!ELEMENT ProjectType (#PCDATA)> + +<!ELEMENT Description (#PCDATA)> + +<!ELEMENT Version (#PCDATA)> + +<!ELEMENT Author (#PCDATA)> + +<!ELEMENT Email (#PCDATA)> + +<!ELEMENT TranslationPattern (#PCDATA)> + +<!ELEMENT TranslationsBinPath (#PCDATA)> + +<!ELEMENT Source (#PCDATA)> + +<!ELEMENT Sources (Source*)> + +<!ELEMENT Form (#PCDATA)> + +<!ELEMENT Forms (Form*)> + +<!ELEMENT Translation (#PCDATA)> + +<!ELEMENT Translations (Translation*)> + +<!ELEMENT TranslationException (#PCDATA)> + +<!ELEMENT TranslationExceptions (TranslationException*)> + +<!ELEMENT Resource (#PCDATA)> + +<!ELEMENT Resources (Resource*)> + +<!ELEMENT Interface (#PCDATA)> + +<!ELEMENT Interfaces (Interface*)> + +<!ELEMENT Protocol (#PCDATA)> + +<!ELEMENT Protocols (Protocol*)> + +<!ELEMENT Other (#PCDATA)> + +<!ELEMENT Others (Other*)> + +<!ELEMENT MainScript (#PCDATA)> + +<!ELEMENT VcsType (#PCDATA)> +<!ELEMENT VcsOptions (dict)> +<!ELEMENT VcsOtherData (dict)> + +<!ELEMENT Vcs (VcsType?, + VcsOptions?, + VcsOtherData?)> + +<!ELEMENT FiletypeAssociation EMPTY> +<!ATTLIST FiletypeAssociation + pattern CDATA #REQUIRED + type CDATA #REQUIRED> + +<!ELEMENT FiletypeAssociations (FiletypeAssociation*)> + +<!ELEMENT LexerAssociation EMPTY> +<!ATTLIST LexerAssociation + pattern CDATA #REQUIRED + lexer CDATA #REQUIRED> + +<!ELEMENT LexerAssociations (LexerAssociation*)> + +<!ELEMENT MakeParameters (dict)> + +<!ELEMENT Make (MakeParameters?)> + +<!ELEMENT ProjectTypeSpecificData (dict)> + +<!ELEMENT ProjectTypeSpecific (ProjectTypeSpecific?)> + +<!ELEMENT DocumentationParams (dict)> + +<!ELEMENT Documentation (DocumentationParams?)> + +<!ELEMENT PackagersParams (dict)> + +<!ELEMENT Packagers (PackagersParams?)> + +<!ELEMENT CheckersParams (dict)> + +<!ELEMENT Checkers (CheckersParams?)> + +<!ELEMENT OtherToolsParams (dict)> + +<!ELEMENT OtherTools (OtherToolsParams?)> + +<!ELEMENT Language (#PCDATA)> + +<!ELEMENT ProjectWordList (#PCDATA)> + +<!ELEMENT ProjectExcludeList (#PCDATA)> + +<!ELEMENT Hash (#PCDATA)> + +<!ELEMENT Eol EMPTY> +<!ATTLIST Eol + index CDATA #REQUIRED> + +<!ELEMENT Project (Language, + ProjectWordList?, + ProjectExcludeList?, + Hash, + ProgLanguage, + ProjectType, + Description?, + Version?, + Author?, + Email?, + TranslationPattern?, + TranslationsBinPath?, + Eol?, + Sources, + Forms, + Translations, + TranslationExceptions?, + Resources, + Interfaces, + Others, + MainScript?, + Vcs, + FiletypeAssociations, + LexerAssociations?, + Make?, + ProjectTypeSpecific?, + Documentation?, + Packagers?, + Checkers?, + OtherTools?)> +<!ATTLIST Project + version CDATA #REQUIRED>
--- a/DebugClients/Python/coverage/__init__.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/__init__.py Tue May 01 12:03:52 2018 +0200 @@ -4,7 +4,7 @@ """Code coverage measurement for Python. Ned Batchelder -http://nedbatchelder.com/code/coverage +https://nedbatchelder.com/code/coverage """ @@ -12,6 +12,7 @@ from coverage.control import Coverage, process_startup from coverage.data import CoverageData +from coverage.debug import enable_aspectlib_maybe from coverage.misc import CoverageException from coverage.plugin import CoveragePlugin, FileTracer, FileReporter from coverage.pytracer import PyTracer @@ -19,6 +20,9 @@ # Backward compatibility. coverage = Coverage +# Possibly enable aspectlib to debug our execution. +enable_aspectlib_maybe() + # On Windows, we encode and decode deep enough that something goes wrong and # the encodings.utf_8 module is loaded and then unloaded, I don't know why. # Adding a reference here prevents it from being unloaded. Yuk.
--- a/DebugClients/Python/coverage/backward.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/backward.py Tue May 01 12:03:52 2018 +0200 @@ -3,10 +3,8 @@ """Add things to old Pythons so I can pretend they are newer.""" -# This file does lots of tricky stuff, so disable a bunch of pylint warnings. -# pylint: disable=redefined-builtin +# This file does tricky stuff, so disable a pylint warning. # pylint: disable=unused-import -# pylint: disable=no-name-in-module import sys @@ -19,11 +17,14 @@ except ImportError: from io import StringIO -# In py3, ConfigParser was renamed to the more-standard configparser +# In py3, ConfigParser was renamed to the more-standard configparser. +# But there's a py3 backport that installs "configparser" in py2, and I don't +# want it because it has annoying deprecation warnings. So try the real py2 +# import first. try: + import ConfigParser as configparser +except ImportError: import configparser -except ImportError: - import ConfigParser as configparser # What's a string called? try: @@ -45,7 +46,7 @@ # range or xrange? try: - range = xrange + range = xrange # pylint: disable=redefined-builtin except NameError: range = range @@ -58,18 +59,29 @@ # in Python versions earlier than 3.3. from pipes import quote as shlex_quote -# A function to iterate listlessly over a dict's items. +# A function to iterate listlessly over a dict's items, and one to get the +# items as a list. try: {}.iteritems except AttributeError: + # Python 3 def iitems(d): """Produce the items from dict `d`.""" return d.items() + + def litems(d): + """Return a list of items from dict `d`.""" + return list(d.items()) else: + # Python 2 def iitems(d): """Produce the items from dict `d`.""" return d.iteritems() + def litems(d): + """Return a list of items from dict `d`.""" + return d.items() + # Getting the `next` function from an iterator is different in 2 and 3. try: iter([]).next @@ -143,6 +155,12 @@ PYC_MAGIC_NUMBER = imp.get_magic() +def invalidate_import_caches(): + """Invalidate any import caches that may or may not exist.""" + if importlib and hasattr(importlib, "invalidate_caches"): + importlib.invalidate_caches() + + def import_local_file(modname, modfile=None): """Import a local file as a module.
--- a/DebugClients/Python/coverage/cmdline.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/cmdline.py Tue May 01 12:03:52 2018 +0200 @@ -3,6 +3,8 @@ """Command-line support for coverage.py.""" +from __future__ import print_function + import glob import optparse import os.path @@ -12,9 +14,10 @@ from coverage import env from coverage.collector import CTracer +from coverage.debug import info_formatter, info_header from coverage.execfile import run_python_file, run_python_module -from coverage.misc import CoverageException, ExceptionDuringRun, NoSource -from coverage.debug import info_formatter, info_header +from coverage.misc import BaseCoverageException, ExceptionDuringRun, NoSource +from coverage.results import should_fail_under class Opts(object): @@ -22,7 +25,7 @@ append = optparse.make_option( '-a', '--append', action='store_true', - help="Append coverage data to .coverage, otherwise it is started clean with each run.", + help="Append coverage data to .coverage, otherwise it starts clean each time.", ) branch = optparse.make_option( '', '--branch', action='store_true', @@ -48,7 +51,7 @@ help="Write the output files to DIR.", ) fail_under = optparse.make_option( - '', '--fail-under', action='store', metavar="MIN", type="int", + '', '--fail-under', action='store', metavar="MIN", type="float", help="Exit with a status of 2 if the total coverage is less than MIN.", ) help = optparse.make_option( @@ -216,7 +219,7 @@ class CmdOptionParser(CoverageOptionParser): """Parse one of the new-style commands for coverage.py.""" - def __init__(self, action, options=None, defaults=None, usage=None, description=None): + def __init__(self, action, options, defaults=None, usage=None, description=None): """Create an OptionParser for a coverage.py command. `action` is the slug to put into `options.action`. @@ -233,8 +236,7 @@ description=description, ) self.set_defaults(action=action, **(defaults or {})) - if options: - self.add_options(options) + self.add_options(options) self.cmd = action def __eq__(self, other): @@ -242,12 +244,14 @@ # results, and they will compare equal to objects. return (other == "<CmdOptionParser:%s>" % self.cmd) + __hash__ = None # This object doesn't need to be hashed. + def get_prog_name(self): """Override of an undocumented function in optparse.OptionParser.""" program_name = super(CmdOptionParser, self).get_prog_name() # Include the sub-command for this parser as part of the command. - return "%(command)s %(subcommand)s" % {'command': program_name, 'subcommand': self.cmd} + return "{command} {subcommand}".format(command=program_name, subcommand=self.cmd) GLOBAL_ARGS = [ @@ -274,8 +278,10 @@ 'combine': CmdOptionParser( "combine", - GLOBAL_ARGS, - usage="<path1> <path2> ... <pathN>", + [ + Opts.append, + ] + GLOBAL_ARGS, + usage="[options] <path1> <path2> ... <pathN>", description=( "Combine data from multiple coverage files collected " "with 'run -p'. The combined results are written to a single " @@ -299,7 +305,6 @@ 'erase': CmdOptionParser( "erase", GLOBAL_ARGS, - usage=" ", description="Erase previously collected coverage data.", ), @@ -318,6 +323,7 @@ Opts.include, Opts.omit, Opts.title, + Opts.skip_covered, ] + GLOBAL_ARGS, usage="[options] [modules]", description=( @@ -398,7 +404,11 @@ self.coverage = None - self.program_name = os.path.basename(sys.argv[0]) + program_path = sys.argv[0] + if program_path.endswith(os.path.sep + '__main__.py'): + # The path is the main module of a package; get that path instead. + program_path = os.path.dirname(program_path) + self.program_name = os.path.basename(program_path) if env.WINDOWS: # entry_points={'console_scripts':...} on Windows makes files # called coverage.exe, coverage3.exe, and coverage-3.5.exe. These @@ -443,10 +453,6 @@ if self.do_help(options, args, parser): return OK - # Check for conflicts and problems in the options. - if not self.args_ok(options, args): - return ERR - # We need to be able to import from the current directory, because # plugins may try to, for example, to read Django settings. sys.path[0] = '' @@ -458,7 +464,7 @@ debug = unshell_list(options.debug) # Do something. - self.coverage = self.covpkg.coverage( + self.coverage = self.covpkg.Coverage( data_suffix=options.parallel_mode, cover_pylib=options.pylib, timid=options.timid, @@ -482,9 +488,10 @@ return self.do_run(options, args) elif options.action == "combine": - self.coverage.load() + if options.append: + self.coverage.load() data_dirs = args or None - self.coverage.combine(data_dirs) + self.coverage.combine(data_dirs, strict=True) self.coverage.save() return OK @@ -509,7 +516,7 @@ elif options.action == "html": total = self.coverage.html_report( directory=options.directory, title=options.title, - **report_args) + skip_covered=options.skip_covered, **report_args) elif options.action == "xml": outfile = options.outfile total = self.coverage.xml_report(outfile=outfile, **report_args) @@ -520,20 +527,10 @@ if options.fail_under is not None: self.coverage.set_option("report:fail_under", options.fail_under) - if self.coverage.get_option("report:fail_under"): - - # Total needs to be rounded, but be careful of 0 and 100. - if 0 < total < 1: - total = 1 - elif 99 < total < 100: - total = 99 - else: - total = round(total) - - if total >= self.coverage.get_option("report:fail_under"): - return OK - else: - return FAIL_UNDER + fail_under = self.coverage.get_option("report:fail_under") + precision = self.coverage.get_option("report:precision") + if should_fail_under(total, fail_under, precision): + return FAIL_UNDER return OK @@ -541,8 +538,8 @@ """Display an error message, or the named topic.""" assert error or topic or parser if error: - print(error) - print("Use '%s help' for help." % (self.program_name,)) + print(error, file=sys.stderr) + print("Use '%s help' for help." % (self.program_name,), file=sys.stderr) elif parser: print(parser.format_help().strip()) else: @@ -591,25 +588,30 @@ return False - def args_ok(self, options, args): - """Check for conflicts and problems in the options. - - Returns True if everything is OK, or False if not. - - """ - if options.action == "run" and not args: - self.help_fn("Nothing to do.") - return False - - return True - def do_run(self, options, args): """Implementation of 'coverage run'.""" + if not args: + self.help_fn("Nothing to do.") + return ERR + if options.append and self.coverage.get_option("run:parallel"): self.help_fn("Can't append to data files in parallel mode.") return ERR + if options.concurrency == "multiprocessing": + # Can't set other run-affecting command line options with + # multiprocessing. + for opt_name in ['branch', 'include', 'omit', 'pylib', 'source', 'timid']: + # As it happens, all of these options have no default, meaning + # they will be None if they have not been specified. + if getattr(options, opt_name) is not None: + self.help_fn( + "Options affecting multiprocessing must be specified " + "in a configuration file." + ) + return ERR + if not self.coverage.get_option("run:parallel"): if not options.append: self.coverage.erase() @@ -641,7 +643,7 @@ """Implementation of 'coverage debug'.""" if not args: - self.help_fn("What information would you like: data, sys?") + self.help_fn("What information would you like: config, data, sys?") return ERR for info in args: @@ -668,6 +670,11 @@ print(line) else: print("No data collected") + elif info == 'config': + print(info_header("config")) + config_info = self.coverage.config.__dict__.items() + for line in info_formatter(config_info): + print(" %s" % line) else: self.help_fn("Don't know what you mean by %r" % info) return ERR @@ -748,9 +755,9 @@ # An exception was caught while running the product code. The # sys.exc_info() return tuple is packed into an ExceptionDuringRun # exception. - traceback.print_exception(*err.args) + traceback.print_exception(*err.args) # pylint: disable=no-value-for-parameter status = ERR - except CoverageException as err: + except BaseCoverageException as err: # A controlled error inside coverage.py: print the message to the user. print(err) status = ERR
--- a/DebugClients/Python/coverage/collector.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/collector.py Tue May 01 12:03:52 2018 +0200 @@ -7,7 +7,8 @@ import sys from coverage import env -from coverage.backward import iitems +from coverage.backward import litems, range # pylint: disable=redefined-builtin +from coverage.debug import short_stack from coverage.files import abs_file from coverage.misc import CoverageException, isolate_module from coverage.pytracer import PyTracer @@ -17,7 +18,7 @@ try: # Use the C extension code when we can, for speed. - from coverage.tracer import CTracer, CFileDisposition # pylint: disable=no-name-in-module + from coverage.tracer import CTracer, CFileDisposition except ImportError: # Couldn't import the C extension, maybe it isn't built. if os.getenv('COVERAGE_TEST_TRACER') == 'c': @@ -42,6 +43,7 @@ fn_name = frame.f_code.co_name if fn_name.startswith("test"): return fn_name + return None class Collector(object): @@ -65,11 +67,14 @@ # the top, and resumed when they become the top again. _collectors = [] + # The concurrency settings we support here. + SUPPORTED_CONCURRENCIES = set(["greenlet", "eventlet", "gevent", "thread"]) + def __init__(self, should_trace, check_include, timid, branch, warn, concurrency): """Create a collector. - `should_trace` is a function, taking a file name, and returning a - `coverage.FileDisposition object`. + `should_trace` is a function, taking a file name and a frame, and + returning a `coverage.FileDisposition object`. `check_include` is a function taking a file name and a frame. It returns a boolean: True if the file should be traced, False if not. @@ -83,12 +88,14 @@ collecting data on which statements followed each other (arcs). Use `get_arc_data` to get the arc data. - `warn` is a warning function, taking a single string message argument, - to be used if a warning needs to be issued. + `warn` is a warning function, taking a single string message argument + and an optional slug argument which will be a string or None, to be + used if a warning needs to be issued. - `concurrency` is a string indicating the concurrency library in use. - Valid values are "greenlet", "eventlet", "gevent", or "thread" (the - default). + `concurrency` is a list of strings indicating the concurrency libraries + in use. Valid values are "greenlet", "eventlet", "gevent", or "thread" + (the default). Of these four values, only one can be supplied. Other + values are ignored. """ self.should_trace = should_trace @@ -96,21 +103,28 @@ self.warn = warn self.branch = branch self.threading = None - self.concurrency = concurrency + + self.origin = short_stack() self.concur_id_func = None + # We can handle a few concurrency options here, but only one at a time. + these_concurrencies = self.SUPPORTED_CONCURRENCIES.intersection(concurrency) + if len(these_concurrencies) > 1: + raise CoverageException("Conflicting concurrency settings: %s" % concurrency) + self.concurrency = these_concurrencies.pop() if these_concurrencies else '' + try: - if concurrency == "greenlet": + if self.concurrency == "greenlet": import greenlet self.concur_id_func = greenlet.getcurrent - elif concurrency == "eventlet": + elif self.concurrency == "eventlet": import eventlet.greenthread # pylint: disable=import-error,useless-suppression self.concur_id_func = eventlet.greenthread.getcurrent - elif concurrency == "gevent": + elif self.concurrency == "gevent": import gevent # pylint: disable=import-error,useless-suppression self.concur_id_func = gevent.getcurrent - elif concurrency == "thread" or not concurrency: + elif self.concurrency == "thread" or not self.concurrency: # It's important to import threading only if we need it. If # it's imported early, and the program being measured uses # gevent, then gevent's monkey-patching won't work properly. @@ -120,7 +134,9 @@ raise CoverageException("Don't understand concurrency=%s" % concurrency) except ImportError: raise CoverageException( - "Couldn't trace with concurrency=%s, the module isn't installed." % concurrency + "Couldn't trace with concurrency=%s, the module isn't installed." % ( + self.concurrency, + ) ) # Who-Tests-What is just a hack at the moment, so turn it on with an @@ -151,6 +167,13 @@ """Return the class name of the tracer we're using.""" return self._trace_class.__name__ + def _clear_data(self): + """Clear out existing data, but stay ready for more collection.""" + self.data.clear() + + for tracer in self.tracers: + tracer.reset_activity() + def reset(self): """Clear collected data, and prepare to collect more.""" # A dictionary mapping file names to dicts with line number keys (if not @@ -197,6 +220,8 @@ # Our active Tracers. self.tracers = [] + self._clear_data() + def _start_tracer(self): """Start a new Tracer object, and store it in self.tracers.""" tracer = self._trace_class() @@ -256,6 +281,8 @@ if self._collectors: self._collectors[-1].pause() + self.tracers = [] + # Check to see whether we had a fullcoverage tracer installed. If so, # get the stack frames it stashed away for us. traces0 = [] @@ -285,7 +312,7 @@ except TypeError: raise Exception("fullcoverage must be run with the C trace function.") - # Install our installation tracer in threading, to jump start other + # Install our installation tracer in threading, to jump-start other # threads. if self.threading: self.threading.settrace(self._installation_trace) @@ -293,12 +320,15 @@ def stop(self): """Stop collecting trace information.""" assert self._collectors + if self._collectors[-1] is not self: + print("self._collectors:") + for c in self._collectors: + print(" {!r}\n{}".format(c, c.origin)) assert self._collectors[-1] is self, ( "Expected current collector to be %r, but it's %r" % (self, self._collectors[-1]) ) self.pause() - self.tracers = [] # Remove this Collector from the stack, and resume the one underneath # (if any). @@ -327,6 +357,14 @@ else: self._start_tracer() + def _activity(self): + """Has any activity been traced? + + Returns a boolean, True if any trace function was invoked. + + """ + return any(tracer.activity() for tracer in self.tracers) + def switch_context(self, new_context): """Who-Tests-What hack: switch to a new who-context.""" # Make a new data dict, or find the existing one, and switch all the @@ -338,12 +376,29 @@ def save_data(self, covdata): """Save the collected data to a `CoverageData`. - Also resets the collector. + Returns True if there was data to save, False if not. + """ + if not self._activity(): + return False - """ def abs_file_dict(d): """Return a dict like d, but with keys modified by `abs_file`.""" - return dict((abs_file(k), v) for k, v in iitems(d)) + # The call to litems() ensures that the GIL protects the dictionary + # iterator against concurrent modifications by tracers running + # in other threads. We try three times in case of concurrent + # access, hoping to get a clean copy. + runtime_err = None + for _ in range(3): + try: + items = litems(d) + except RuntimeError as ex: + runtime_err = ex + else: + break + else: + raise runtime_err # pylint: disable=raising-bad-type + + return dict((abs_file(k), v) for k, v in items) if self.branch: covdata.add_arcs(abs_file_dict(self.data)) @@ -358,4 +413,5 @@ with open(out_file, "w") as wtw_out: pprint.pprint(self.contexts, wtw_out) - self.reset() + self._clear_data() + return True
--- a/DebugClients/Python/coverage/config.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/config.py Tue May 01 12:03:52 2018 +0200 @@ -9,7 +9,7 @@ import sys from coverage.backward import configparser, iitems, string_class -from coverage.misc import CoverageException, isolate_module +from coverage.misc import contract, CoverageException, isolate_module os = isolate_module(os) @@ -17,28 +17,48 @@ class HandyConfigParser(configparser.RawConfigParser): """Our specialization of ConfigParser.""" - def __init__(self, section_prefix): + def __init__(self, our_file): + """Create the HandyConfigParser. + + `our_file` is True if this config file is specifically for coverage, + False if we are examining another config file (tox.ini, setup.cfg) + for possible settings. + """ + configparser.RawConfigParser.__init__(self) - self.section_prefix = section_prefix + self.section_prefixes = ["coverage:"] + if our_file: + self.section_prefixes.append("") - def read(self, filename): + def read(self, filenames): """Read a file name as UTF-8 configuration data.""" kwargs = {} if sys.version_info >= (3, 2): kwargs['encoding'] = "utf-8" - return configparser.RawConfigParser.read(self, filename, **kwargs) + return configparser.RawConfigParser.read(self, filenames, **kwargs) def has_option(self, section, option): - section = self.section_prefix + section - return configparser.RawConfigParser.has_option(self, section, option) + for section_prefix in self.section_prefixes: + real_section = section_prefix + section + has = configparser.RawConfigParser.has_option(self, real_section, option) + if has: + return has + return False def has_section(self, section): - section = self.section_prefix + section - return configparser.RawConfigParser.has_section(self, section) + for section_prefix in self.section_prefixes: + real_section = section_prefix + section + has = configparser.RawConfigParser.has_section(self, real_section) + if has: + return real_section + return False def options(self, section): - section = self.section_prefix + section - return configparser.RawConfigParser.options(self, section) + for section_prefix in self.section_prefixes: + real_section = section_prefix + section + if configparser.RawConfigParser.has_section(self, real_section): + return configparser.RawConfigParser.options(self, real_section) + raise configparser.NoSectionError def get_section(self, section): """Get the contents of a section, as a dictionary.""" @@ -47,7 +67,7 @@ d[opt] = self.get(section, opt) return d - def get(self, section, *args, **kwargs): + def get(self, section, option, *args, **kwargs): # pylint: disable=arguments-differ """Get a value, replacing environment variables also. The arguments are the same as `RawConfigParser.get`, but in the found @@ -57,8 +77,14 @@ Returns the finished value. """ - section = self.section_prefix + section - v = configparser.RawConfigParser.get(self, section, *args, **kwargs) + for section_prefix in self.section_prefixes: + real_section = section_prefix + section + if configparser.RawConfigParser.has_option(self, real_section, option): + break + else: + raise configparser.NoOptionError + + v = configparser.RawConfigParser.get(self, real_section, option, *args, **kwargs) def dollar_replace(m): """Called for each $replacement.""" # Only one of the groups will have matched, just get its text. @@ -122,12 +148,12 @@ # The default line exclusion regexes. DEFAULT_EXCLUDE = [ - r'(?i)#\s*pragma[:\s]?\s*no\s*cover', + r'#\s*(pragma|PRAGMA)[:\s]?\s*(no|NO)\s*(cover|COVER)', ] # The default partial branch regexes, to be modified by the user. DEFAULT_PARTIAL = [ - r'(?i)#\s*pragma[:\s]?\s*no\s*branch', + r'#\s*(pragma|PRAGMA)[:\s]?\s*(no|NO)\s*(branch|BRANCH)', ] # The default partial branch regexes, based on Python semantics. @@ -152,24 +178,31 @@ self.attempted_config_files = [] self.config_files = [] + # Defaults for [run] and [report] + self._include = None + self._omit = None + # Defaults for [run] self.branch = False self.concurrency = None self.cover_pylib = False self.data_file = ".coverage" self.debug = [] + self.disable_warnings = [] self.note = None self.parallel = False self.plugins = [] self.source = None + self.run_include = None + self.run_omit = None self.timid = False # Defaults for [report] self.exclude_list = DEFAULT_EXCLUDE[:] - self.fail_under = 0 + self.fail_under = 0.0 self.ignore_errors = False - self.include = None - self.omit = None + self.report_include = None + self.report_omit = None self.partial_always_list = DEFAULT_PARTIAL_ALWAYS[:] self.partial_list = DEFAULT_PARTIAL[:] self.precision = 0 @@ -191,7 +224,11 @@ # Options for plugins self.plugin_options = {} - MUST_BE_LIST = ["omit", "include", "debug", "plugins"] + MUST_BE_LIST = [ + "debug", "concurrency", "plugins", + "report_omit", "report_include", + "run_omit", "run_include", + ] def from_args(self, **kwargs): """Read config values from `kwargs`.""" @@ -201,17 +238,23 @@ v = [v] setattr(self, k, v) - def from_file(self, filename, section_prefix=""): + @contract(filename=str) + def from_file(self, filename, our_file): """Read configuration from a .rc file. `filename` is a file name to read. - Returns True or False, whether the file could be read. + `our_file` is True if this config file is specifically for coverage, + False if we are examining another config file (tox.ini, setup.cfg) + for possible settings. + + Returns True or False, whether the file could be read, and it had some + coverage.py settings in it. """ self.attempted_config_files.append(filename) - cp = HandyConfigParser(section_prefix) + cp = HandyConfigParser(our_file) try: files_read = cp.read(filename) except configparser.Error as err: @@ -221,9 +264,12 @@ self.config_files.extend(files_read) + any_set = False try: for option_spec in self.CONFIG_FILE_OPTIONS: - self._set_attr_from_config_option(cp, *option_spec) + was_set = self._set_attr_from_config_option(cp, *option_spec) + if was_set: + any_set = True except ValueError as err: raise CoverageException("Couldn't read config file %s: %s" % (filename, err)) @@ -234,13 +280,12 @@ all_options[section].add(option) for section, options in iitems(all_options): - if cp.has_section(section): + real_section = cp.has_section(section) + if real_section: for unknown in set(cp.options(section)) - options: - if section_prefix: - section = section_prefix + section raise CoverageException( "Unrecognized option '[%s] %s=' in config file %s" % ( - section, unknown, filename + real_section, unknown, filename ) ) @@ -248,13 +293,21 @@ if cp.has_section('paths'): for option in cp.options('paths'): self.paths[option] = cp.getlist('paths', option) + any_set = True # plugins can have options for plugin in self.plugins: if cp.has_section(plugin): self.plugin_options[plugin] = cp.get_section(plugin) + any_set = True - return True + # Was this file used as a config file? If it's specifically our file, + # then it was used. If we're piggybacking on someone else's file, + # then it was only used if we found some settings in it. + if our_file: + return True + else: + return any_set CONFIG_FILE_OPTIONS = [ # These are *args for _set_attr_from_config_option: @@ -267,29 +320,31 @@ # [run] ('branch', 'run:branch', 'boolean'), - ('concurrency', 'run:concurrency'), + ('concurrency', 'run:concurrency', 'list'), ('cover_pylib', 'run:cover_pylib', 'boolean'), ('data_file', 'run:data_file'), ('debug', 'run:debug', 'list'), - ('include', 'run:include', 'list'), + ('disable_warnings', 'run:disable_warnings', 'list'), ('note', 'run:note'), - ('omit', 'run:omit', 'list'), ('parallel', 'run:parallel', 'boolean'), ('plugins', 'run:plugins', 'list'), + ('run_include', 'run:include', 'list'), + ('run_omit', 'run:omit', 'list'), ('source', 'run:source', 'list'), ('timid', 'run:timid', 'boolean'), # [report] ('exclude_list', 'report:exclude_lines', 'regexlist'), - ('fail_under', 'report:fail_under', 'int'), + ('fail_under', 'report:fail_under', 'float'), ('ignore_errors', 'report:ignore_errors', 'boolean'), - ('include', 'report:include', 'list'), - ('omit', 'report:omit', 'list'), ('partial_always_list', 'report:partial_branches_always', 'regexlist'), ('partial_list', 'report:partial_branches', 'regexlist'), ('precision', 'report:precision', 'int'), + ('report_include', 'report:include', 'list'), + ('report_omit', 'report:omit', 'list'), ('show_missing', 'report:show_missing', 'boolean'), ('skip_covered', 'report:skip_covered', 'boolean'), + ('sort', 'report:sort'), # [html] ('extra_css', 'html:extra_css'), @@ -302,11 +357,17 @@ ] def _set_attr_from_config_option(self, cp, attr, where, type_=''): - """Set an attribute on self if it exists in the ConfigParser.""" + """Set an attribute on self if it exists in the ConfigParser. + + Returns True if the attribute was set. + + """ section, option = where.split(":") if cp.has_option(section, option): method = getattr(cp, 'get' + type_) setattr(self, attr, method(section, option)) + return True + return False def get_plugin_options(self, plugin): """Get a dictionary of options for the plugin named `plugin`.""" @@ -349,7 +410,6 @@ Returns the value of the option. """ - # Check all the hard-coded options. for option_spec in self.CONFIG_FILE_OPTIONS: attr, where = option_spec[:2] @@ -363,3 +423,67 @@ # If we get here, we didn't find the option. raise CoverageException("No such option: %r" % option_name) + + +def read_coverage_config(config_file, **kwargs): + """Read the coverage.py configuration. + + Arguments: + config_file: a boolean or string, see the `Coverage` class for the + tricky details. + all others: keyword arguments from the `Coverage` class, used for + setting values in the configuration. + + Returns: + config_file, config: + config_file is the value to use for config_file in other + invocations of coverage. + + config is a CoverageConfig object read from the appropriate + configuration file. + + """ + # Build the configuration from a number of sources: + # 1) defaults: + config = CoverageConfig() + + # 2) from a file: + if config_file: + # Some API users were specifying ".coveragerc" to mean the same as + # True, so make it so. + if config_file == ".coveragerc": + config_file = True + specified_file = (config_file is not True) + if not specified_file: + config_file = ".coveragerc" + + for fname, our_file in [(config_file, True), + ("setup.cfg", False), + ("tox.ini", False)]: + config_read = config.from_file(fname, our_file=our_file) + is_config_file = fname == config_file + + if not config_read and is_config_file and specified_file: + raise CoverageException("Couldn't read '%s' as a config file" % fname) + + if config_read: + break + + # 3) from environment variables: + env_data_file = os.environ.get('COVERAGE_FILE') + if env_data_file: + config.data_file = env_data_file + debugs = os.environ.get('COVERAGE_DEBUG') + if debugs: + config.debug.extend(d.strip() for d in debugs.split(",")) + + # 4) from constructor arguments: + config.from_args(**kwargs) + + # Once all the config has been collected, there's a little post-processing + # to do. + config.data_file = os.path.expanduser(config.data_file) + config.html_dir = os.path.expanduser(config.html_dir) + config.xml_output = os.path.expanduser(config.xml_output) + + return config_file, config
--- a/DebugClients/Python/coverage/control.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/control.py Tue May 01 12:03:52 2018 +0200 @@ -3,43 +3,61 @@ """Core control stuff for coverage.py.""" + import atexit import inspect +import itertools import os import platform import re import sys +import time import traceback -from coverage import env, files +from coverage import env from coverage.annotate import AnnotateReporter from coverage.backward import string_class, iitems from coverage.collector import Collector -from coverage.config import CoverageConfig +from coverage.config import read_coverage_config from coverage.data import CoverageData, CoverageDataFiles -from coverage.debug import DebugControl +from coverage.debug import DebugControl, write_formatted_info from coverage.files import TreeMatcher, FnmatchMatcher from coverage.files import PathAliases, find_python_files, prep_patterns +from coverage.files import canonical_filename, set_relative_directory from coverage.files import ModuleMatcher, abs_file from coverage.html import HtmlReporter from coverage.misc import CoverageException, bool_or_none, join_regex from coverage.misc import file_be_gone, isolate_module -from coverage.monkey import patch_multiprocessing from coverage.plugin import FileReporter from coverage.plugin_support import Plugins -from coverage.python import PythonFileReporter +from coverage.python import PythonFileReporter, source_for_file from coverage.results import Analysis, Numbers from coverage.summary import SummaryReporter from coverage.xmlreport import XmlReporter +try: + from coverage.multiproc import patch_multiprocessing +except ImportError: # pragma: only jython + # Jython has no multiprocessing module. + patch_multiprocessing = None + os = isolate_module(os) # Pypy has some unusual stuff in the "stdlib". Consider those locations -# when deciding where the stdlib is. -try: - import _structseq -except ImportError: - _structseq = None +# when deciding where the stdlib is. These modules are not used for anything, +# they are modules importable from the pypy lib directories, so that we can +# find those directories. +_structseq = _pypy_irc_topic = None +if env.PYPY: + try: + import _structseq + except ImportError: + pass + + try: + import _pypy_irc_topic + except ImportError: + pass class Coverage(object): @@ -92,8 +110,8 @@ file can't be read, it is an error. * If it is True, then a few standard files names are tried - (".coveragerc", "setup.cfg"). It is not an error for these files - to not be found. + (".coveragerc", "setup.cfg", "tox.ini"). It is not an error for + these files to not be found. * If it is False, then no configuration file is read. @@ -110,55 +128,31 @@ `concurrency` is a string indicating the concurrency library being used in the measured code. Without this, coverage.py will get incorrect - results. Valid strings are "greenlet", "eventlet", "gevent", - "multiprocessing", or "thread" (the default). + results if these libraries are in use. Valid strings are "greenlet", + "eventlet", "gevent", "multiprocessing", or "thread" (the default). + This can also be a list of these strings. .. versionadded:: 4.0 The `concurrency` parameter. - """ - # Build our configuration from a number of sources: - # 1: defaults: - self.config = CoverageConfig() - - # 2: from the rcfile, .coveragerc or setup.cfg file: - if config_file: - did_read_rc = False - # Some API users were specifying ".coveragerc" to mean the same as - # True, so make it so. - if config_file == ".coveragerc": - config_file = True - specified_file = (config_file is not True) - if not specified_file: - config_file = ".coveragerc" - - did_read_rc = self.config.from_file(config_file) + .. versionadded:: 4.2 + The `concurrency` parameter can now be a list of strings. - if not did_read_rc: - if specified_file: - raise CoverageException( - "Couldn't read '%s' as a config file" % config_file - ) - self.config.from_file("setup.cfg", section_prefix="coverage:") - - # 3: from environment variables: - env_data_file = os.environ.get('COVERAGE_FILE') - if env_data_file: - self.config.data_file = env_data_file - debugs = os.environ.get('COVERAGE_DEBUG') - if debugs: - self.config.debug.extend(debugs.split(",")) - - # 4: from constructor arguments: - self.config.from_args( + """ + # Build our configuration from a number of sources. + self.config_file, self.config = read_coverage_config( + config_file=config_file, data_file=data_file, cover_pylib=cover_pylib, timid=timid, branch=branch, parallel=bool_or_none(data_suffix), - source=source, omit=omit, include=include, debug=debug, + source=source, run_omit=omit, run_include=include, debug=debug, + report_omit=omit, report_include=include, concurrency=concurrency, ) + # This is injectable by tests. self._debug_file = None - self._auto_data = auto_data + + self._auto_load = self._auto_save = auto_data self._data_suffix = data_suffix # The matchers for _should_trace. @@ -176,10 +170,11 @@ # Other instance attributes, set later. self.omit = self.include = self.source = None + self.source_pkgs_unmatched = None self.source_pkgs = None self.data = self.data_files = self.collector = None self.plugins = None - self.pylib_dirs = self.cover_dirs = None + self.pylib_paths = self.cover_paths = None self.data_suffix = self.run_suffix = None self._exclude_re = None self.debug = None @@ -189,8 +184,14 @@ self._inited = False # Have we started collecting and not stopped it? self._started = False - # Have we measured some data and not harvested it? - self._measured = False + + # If we have sub-process measurement happening automatically, then we + # want any explicit creation of a Coverage object to mean, this process + # is already coverage-aware, so don't auto-measure it. By now, the + # auto-creation of a Coverage object has already happened. But we can + # find it and tell it not to save its data. + if not env.METACOV: + _prevent_sub_process_measurement() def _init(self): """Set all the initial state. @@ -203,6 +204,8 @@ if self._inited: return + self._inited = True + # Create and configure the debugging controller. COVERAGE_DEBUG_FILE # is an environment variable, the name of a file to append debug logs # to. @@ -214,32 +217,45 @@ self._debug_file = sys.stderr self.debug = DebugControl(self.config.debug, self._debug_file) + # _exclude_re is a dict that maps exclusion list names to compiled regexes. + self._exclude_re = {} + + set_relative_directory() + # Load plugins self.plugins = Plugins.load_plugins(self.config.plugins, self.config, self.debug) - # _exclude_re is a dict that maps exclusion list names to compiled - # regexes. - self._exclude_re = {} - self._exclude_regex_stale() - - files.set_relative_directory() + # Run configuring plugins. + for plugin in self.plugins.configurers: + # We need an object with set_option and get_option. Either self or + # self.config will do. Choosing randomly stops people from doing + # other things with those objects, against the public API. Yes, + # this is a bit childish. :) + plugin.configure([self, self.config][int(time.time()) % 2]) # The source argument can be directories or package names. self.source = [] self.source_pkgs = [] for src in self.config.source or []: - if os.path.exists(src): - self.source.append(files.canonical_filename(src)) + if os.path.isdir(src): + self.source.append(canonical_filename(src)) else: self.source_pkgs.append(src) + self.source_pkgs_unmatched = self.source_pkgs[:] - self.omit = prep_patterns(self.config.omit) - self.include = prep_patterns(self.config.include) + self.omit = prep_patterns(self.config.run_omit) + self.include = prep_patterns(self.config.run_include) - concurrency = self.config.concurrency - if concurrency == "multiprocessing": - patch_multiprocessing() - concurrency = None + concurrency = self.config.concurrency or [] + if "multiprocessing" in concurrency: + if not patch_multiprocessing: + raise CoverageException( # pragma: only jython + "multiprocessing is not supported on this Python" + ) + patch_multiprocessing(rcfile=self.config_file) + # Multi-processing uses parallel for the subprocesses, so also use + # it for the main process. + self.config.parallel = True self.collector = Collector( should_trace=self._should_trace, @@ -281,19 +297,22 @@ # data file will be written into the directory where the process # started rather than wherever the process eventually chdir'd to. self.data = CoverageData(debug=self.debug) - self.data_files = CoverageDataFiles(basename=self.config.data_file, warn=self._warn) + self.data_files = CoverageDataFiles( + basename=self.config.data_file, warn=self._warn, debug=self.debug, + ) # The directories for files considered "installed with the interpreter". - self.pylib_dirs = set() + self.pylib_paths = set() if not self.config.cover_pylib: # Look at where some standard modules are located. That's the # indication for "installed with the interpreter". In some # environments (virtualenv, for example), these modules may be # spread across a few locations. Look at all the candidate modules # we've imported, and take all the different ones. - for m in (atexit, inspect, os, platform, re, _structseq, traceback): + for m in (atexit, inspect, os, platform, _pypy_irc_topic, re, _structseq, traceback): if m is not None and hasattr(m, "__file__"): - self.pylib_dirs.add(self._canonical_dir(m)) + self.pylib_paths.add(self._canonical_path(m, directory=True)) + if _structseq and not hasattr(_structseq, '__file__'): # PyPy 2.4 has no __file__ in the builtin modules, but the code # objects still have the file names. So dig into one to find @@ -303,94 +322,77 @@ structseq_file = structseq_new.func_code.co_filename except AttributeError: structseq_file = structseq_new.__code__.co_filename - self.pylib_dirs.add(self._canonical_dir(structseq_file)) + self.pylib_paths.add(self._canonical_path(structseq_file)) # To avoid tracing the coverage.py code itself, we skip anything # located where we are. - self.cover_dirs = [self._canonical_dir(__file__)] + self.cover_paths = [self._canonical_path(__file__, directory=True)] if env.TESTING: + # Don't include our own test code. + self.cover_paths.append(os.path.join(self.cover_paths[0], "tests")) + # When testing, we use PyContracts, which should be considered # part of coverage.py, and it uses six. Exclude those directories # just as we exclude ourselves. - import contracts, six + import contracts + import six for mod in [contracts, six]: - self.cover_dirs.append(self._canonical_dir(mod)) + self.cover_paths.append(self._canonical_path(mod)) # Set the reporting precision. Numbers.set_precision(self.config.precision) atexit.register(self._atexit) - self._inited = True - # Create the matchers we need for _should_trace if self.source or self.source_pkgs: self.source_match = TreeMatcher(self.source) self.source_pkgs_match = ModuleMatcher(self.source_pkgs) else: - if self.cover_dirs: - self.cover_match = TreeMatcher(self.cover_dirs) - if self.pylib_dirs: - self.pylib_match = TreeMatcher(self.pylib_dirs) + if self.cover_paths: + self.cover_match = TreeMatcher(self.cover_paths) + if self.pylib_paths: + self.pylib_match = TreeMatcher(self.pylib_paths) if self.include: self.include_match = FnmatchMatcher(self.include) if self.omit: self.omit_match = FnmatchMatcher(self.omit) # The user may want to debug things, show info if desired. - wrote_any = False - if self.debug.should('config'): - config_info = sorted(self.config.__dict__.items()) - self.debug.write_formatted_info("config", config_info) - wrote_any = True + self._write_startup_debug() - if self.debug.should('sys'): - self.debug.write_formatted_info("sys", self.sys_info()) - for plugin in self.plugins: - header = "sys: " + plugin._coverage_plugin_name - info = plugin.sys_info() - self.debug.write_formatted_info(header, info) - wrote_any = True + def _write_startup_debug(self): + """Write out debug info at startup if needed.""" + wrote_any = False + with self.debug.without_callers(): + if self.debug.should('config'): + config_info = sorted(self.config.__dict__.items()) + write_formatted_info(self.debug, "config", config_info) + wrote_any = True + + if self.debug.should('sys'): + write_formatted_info(self.debug, "sys", self.sys_info()) + for plugin in self.plugins: + header = "sys: " + plugin._coverage_plugin_name + info = plugin.sys_info() + write_formatted_info(self.debug, header, info) + wrote_any = True if wrote_any: - self.debug.write_formatted_info("end", ()) + write_formatted_info(self.debug, "end", ()) - def _canonical_dir(self, morf): - """Return the canonical directory of the module or file `morf`.""" - morf_filename = PythonFileReporter(morf, self).filename - return os.path.split(morf_filename)[0] + def _canonical_path(self, morf, directory=False): + """Return the canonical path of the module or file `morf`. - def _source_for_file(self, filename): - """Return the source file for `filename`. - - Given a file name being traced, return the best guess as to the source - file to attribute it to. + If the module is a package, then return its directory. If it is a + module, then return its file, unless `directory` is True, in which + case return its enclosing directory. """ - if filename.endswith(".py"): - # .py files are themselves source files. - return filename - - elif filename.endswith((".pyc", ".pyo")): - # Bytecode files probably have source files near them. - py_filename = filename[:-1] - if os.path.exists(py_filename): - # Found a .py file, use that. - return py_filename - if env.WINDOWS: - # On Windows, it could be a .pyw file. - pyw_filename = py_filename + "w" - if os.path.exists(pyw_filename): - return pyw_filename - # Didn't find source, but it's probably the .py file we want. - return py_filename - - elif filename.endswith("$py.class"): - # Jython is easy to guess. - return filename[:-9] + ".py" - - # No idea, just use the file name as-is. - return filename + morf_path = PythonFileReporter(morf, self).filename + if morf_path.endswith("__init__.py") or directory: + morf_path = os.path.split(morf_path)[0] + return morf_path def _name_for_module(self, module_globals, filename): """Get the name of the module for a set of globals and file name. @@ -404,6 +406,10 @@ can't be determined, None is returned. """ + if module_globals is None: # pragma: only ironpython + # IronPython doesn't provide globals: https://github.com/IronLanguages/main/issues/1296 + module_globals = {} + dunder_name = module_globals.get('__name__', None) if isinstance(dunder_name, str) and dunder_name != '__main__': @@ -452,9 +458,9 @@ # .pyc files can be moved after compilation (for example, by being # installed), we look for __file__ in the frame and prefer it to the # co_filename value. - dunder_file = frame.f_globals.get('__file__') + dunder_file = frame.f_globals and frame.f_globals.get('__file__') if dunder_file: - filename = self._source_for_file(dunder_file) + filename = source_for_file(dunder_file) if original_filename and not original_filename.startswith('<'): orig = os.path.basename(original_filename) if orig != os.path.basename(filename): @@ -486,7 +492,7 @@ if filename.endswith("$py.class"): filename = filename[:-9] + ".py" - canonical = files.canonical_filename(filename) + canonical = canonical_filename(filename) disp.canonical_filename = canonical # Try the plugins, see if they have an opinion about the file. @@ -504,13 +510,13 @@ if file_tracer.has_dynamic_source_filename(): disp.has_dynamic_filename = True else: - disp.source_filename = files.canonical_filename( + disp.source_filename = canonical_filename( file_tracer.source_filename() ) break except Exception: self._warn( - "Disabling plugin %r due to an exception:" % ( + "Disabling plug-in %r due to an exception:" % ( plugin._coverage_plugin_name ) ) @@ -551,11 +557,9 @@ # stdlib and coverage.py directories. if self.source_match: if self.source_pkgs_match.match(modulename): - if modulename in self.source_pkgs: - self.source_pkgs.remove(modulename) - return None # There's no reason to skip this file. - - if not self.source_match.match(filename): + if modulename in self.source_pkgs_unmatched: + self.source_pkgs_unmatched.remove(modulename) + elif not self.source_match.match(filename): return "falls outside the --source trees" elif self.include_match: if not self.include_match.match(filename): @@ -605,9 +609,18 @@ return not reason - def _warn(self, msg): - """Use `msg` as a warning.""" + def _warn(self, msg, slug=None): + """Use `msg` as a warning. + + For warning suppression, use `slug` as the shorthand. + """ + if slug in self.config.disable_warnings: + # Don't issue the warning + return + self._warnings.append(msg) + if slug: + msg = "%s (%s)" % (msg, slug) if self.debug.should('pid'): msg = "[%d] %s" % (os.getpid(), msg) sys.stderr.write("Coverage.py warning: %s\n" % msg) @@ -633,8 +646,8 @@ option name. For example, the ``branch`` option in the ``[run]`` section of the config file would be indicated with ``"run:branch"``. - `value` is the new value for the option. This should be a Python - value where appropriate. For example, use True for booleans, not the + `value` is the new value for the option. This should be an + appropriate Python value. For example, use True for booleans, not the string ``"True"``. As an example, calling:: @@ -666,7 +679,7 @@ def start(self): """Start measuring code coverage. - Coverage measurement actually occurs in functions called after + Coverage measurement only occurs in functions called after :meth:`start` is invoked. Statements in the same scope as :meth:`start` won't be measured. @@ -675,16 +688,18 @@ """ self._init() + if self.include: + if self.source or self.source_pkgs: + self._warn("--include is ignored because --source is set", slug="include-ignored") if self.run_suffix: # Calling start() means we're running code, so use the run_suffix # as the data_suffix when we eventually save the data. self.data_suffix = self.run_suffix - if self._auto_data: + if self._auto_load: self.load() self.collector.start() self._started = True - self._measured = True def stop(self): """Stop measuring code coverage.""" @@ -694,9 +709,11 @@ def _atexit(self): """Clean up on process shutdown.""" + if self.debug.should("process"): + self.debug.write("atexit: {0!r}".format(self)) if self._started: self.stop() - if self._auto_data: + if self._auto_save: self.save() def erase(self): @@ -764,7 +781,7 @@ self.get_data() self.data_files.write(self.data, suffix=self.data_suffix) - def combine(self, data_paths=None): + def combine(self, data_paths=None, strict=False): """Combine together a number of similarly-named coverage data files. All coverage data files whose name starts with `data_file` (from the @@ -776,9 +793,15 @@ directory indicated by the current data file (probably the current directory) will be combined. + If `strict` is true, then it is an error to attempt to combine when + there are no data files to combine. + .. versionadded:: 4.0 The `data_paths` parameter. + .. versionadded:: 4.3 + The `strict` parameter. + """ self._init() self.get_data() @@ -791,10 +814,12 @@ for pattern in paths[1:]: aliases.add(pattern, result) - self.data_files.combine_parallel_data(self.data, aliases=aliases, data_paths=data_paths) + self.data_files.combine_parallel_data( + self.data, aliases=aliases, data_paths=data_paths, strict=strict, + ) def get_data(self): - """Get the collected data and reset the collector. + """Get the collected data. Also warn about various problems collecting data. @@ -804,46 +829,98 @@ """ self._init() - if not self._measured: - return self.data + + if self.collector.save_data(self.data): + self._post_save_work() + + return self.data - self.collector.save_data(self.data) + def _post_save_work(self): + """After saving data, look for warnings, post-work, etc. - # If there are still entries in the source_pkgs list, then we never - # encountered those packages. + Warn about things that should have happened but didn't. + Look for unexecuted files. + + """ + # If there are still entries in the source_pkgs_unmatched list, + # then we never encountered those packages. if self._warn_unimported_source: - for pkg in self.source_pkgs: - if pkg not in sys.modules: - self._warn("Module %s was never imported." % pkg) - elif not ( - hasattr(sys.modules[pkg], '__file__') and - os.path.exists(sys.modules[pkg].__file__) - ): - self._warn("Module %s has no Python source." % pkg) - else: - self._warn("Module %s was previously imported, but not measured." % pkg) + for pkg in self.source_pkgs_unmatched: + self._warn_about_unmeasured_code(pkg) # Find out if we got any data. if not self.data and self._warn_no_data: - self._warn("No data was collected.") + self._warn("No data was collected.", slug="no-data-collected") # Find files that were never executed at all. - for src in self.source: - for py_file in find_python_files(src): - py_file = files.canonical_filename(py_file) + for pkg in self.source_pkgs: + if (not pkg in sys.modules or + not hasattr(sys.modules[pkg], '__file__') or + not os.path.exists(sys.modules[pkg].__file__)): + continue + pkg_file = source_for_file(sys.modules[pkg].__file__) + self._find_unexecuted_files(self._canonical_path(pkg_file)) - if self.omit_match and self.omit_match.match(py_file): - # Turns out this file was omitted, so don't pull it back - # in as unexecuted. - continue - - self.data.touch_file(py_file) + for src in self.source: + self._find_unexecuted_files(src) if self.config.note: self.data.add_run_info(note=self.config.note) - self._measured = False - return self.data + def _warn_about_unmeasured_code(self, pkg): + """Warn about a package or module that we never traced. + + `pkg` is a string, the name of the package or module. + + """ + mod = sys.modules.get(pkg) + if mod is None: + self._warn("Module %s was never imported." % pkg, slug="module-not-imported") + return + + is_namespace = hasattr(mod, '__path__') and not hasattr(mod, '__file__') + has_file = hasattr(mod, '__file__') and os.path.exists(mod.__file__) + + if is_namespace: + # A namespace package. It's OK for this not to have been traced, + # since there is no code directly in it. + return + + if not has_file: + self._warn("Module %s has no Python source." % pkg, slug="module-not-python") + return + + # The module was in sys.modules, and seems like a module with code, but + # we never measured it. I guess that means it was imported before + # coverage even started. + self._warn( + "Module %s was previously imported, but not measured" % pkg, + slug="module-not-measured", + ) + + def _find_plugin_files(self, src_dir): + """Get executable files from the plugins.""" + for plugin in self.plugins.file_tracers: + for x_file in plugin.find_executable_files(src_dir): + yield x_file, plugin._coverage_plugin_name + + def _find_unexecuted_files(self, src_dir): + """Find unexecuted files in `src_dir`. + + Search for files in `src_dir` that are probably importable, + and add them as unexecuted files in `self.data`. + + """ + py_files = ((py_file, None) for py_file in find_python_files(src_dir)) + plugin_files = self._find_plugin_files(src_dir) + + for file_path, plugin_name in itertools.chain(py_files, plugin_files): + file_path = canonical_filename(file_path) + if self.omit_match and self.omit_match.match(file_path): + # Turns out this file was omitted, so don't pull it back + # in as unexecuted. + continue + self.data.touch_file(file_path, plugin_name) # Backward compatibility with version 1. def analysis(self, morf): @@ -954,12 +1031,14 @@ included in the report. Files matching `omit` will not be included in the report. + If `skip_covered` is True, don't report on files with 100% coverage. + Returns a float, the total percentage covered. """ self.get_data() self.config.from_args( - ignore_errors=ignore_errors, omit=omit, include=include, + ignore_errors=ignore_errors, report_omit=omit, report_include=include, show_missing=show_missing, skip_covered=skip_covered, ) reporter = SummaryReporter(self, self.config) @@ -981,13 +1060,14 @@ """ self.get_data() self.config.from_args( - ignore_errors=ignore_errors, omit=omit, include=include + ignore_errors=ignore_errors, report_omit=omit, report_include=include ) reporter = AnnotateReporter(self, self.config) reporter.report(morfs, directory=directory) def html_report(self, morfs=None, directory=None, ignore_errors=None, - omit=None, include=None, extra_css=None, title=None): + omit=None, include=None, extra_css=None, title=None, + skip_covered=None): """Generate an HTML report. The HTML is written to `directory`. The file "index.html" is the @@ -1007,8 +1087,9 @@ """ self.get_data() self.config.from_args( - ignore_errors=ignore_errors, omit=omit, include=include, + ignore_errors=ignore_errors, report_omit=omit, report_include=include, html_dir=directory, extra_css=extra_css, html_title=title, + skip_covered=skip_covered, ) reporter = HtmlReporter(self, self.config) return reporter.report(morfs) @@ -1031,7 +1112,7 @@ """ self.get_data() self.config.from_args( - ignore_errors=ignore_errors, omit=omit, include=include, + ignore_errors=ignore_errors, report_omit=omit, report_include=include, xml_output=outfile, ) file_to_close = None @@ -1071,20 +1152,24 @@ self._init() - ft_plugins = [] - for ft in self.plugins.file_tracers: - ft_name = ft._coverage_plugin_name - if not ft._coverage_enabled: - ft_name += " (disabled)" - ft_plugins.append(ft_name) + def plugin_info(plugins): + """Make an entry for the sys_info from a list of plug-ins.""" + entries = [] + for plugin in plugins: + entry = plugin._coverage_plugin_name + if not plugin._coverage_enabled: + entry += " (disabled)" + entries.append(entry) + return entries info = [ ('version', covmod.__version__), ('coverage', covmod.__file__), - ('cover_dirs', self.cover_dirs), - ('pylib_dirs', self.pylib_dirs), + ('cover_paths', self.cover_paths), + ('pylib_paths', self.pylib_paths), ('tracer', self.collector.tracer_name()), - ('plugins.file_tracers', ft_plugins), + ('plugins.file_tracers', plugin_info(self.plugins.file_tracers)), + ('plugins.configurers', plugin_info(self.plugins.configurers)), ('config_files', self.config.attempted_config_files), ('configs_read', self.config.config_files), ('data_path', self.data_files.filename), @@ -1185,15 +1270,23 @@ # https://bitbucket.org/ned/coveragepy/issue/340/keyerror-subpy has more # details. - if hasattr(process_startup, "done"): + if hasattr(process_startup, "coverage"): # We've annotated this function before, so we must have already # started coverage.py in this process. Nothing to do. return None - process_startup.done = True - cov = Coverage(config_file=cps, auto_data=True) + cov = Coverage(config_file=cps) + process_startup.coverage = cov cov.start() cov._warn_no_data = False cov._warn_unimported_source = False + cov._auto_save = True return cov + + +def _prevent_sub_process_measurement(): + """Stop any subprocess auto-measurement from writing data.""" + auto_created_coverage = getattr(process_startup, "coverage", None) + if auto_created_coverage is not None: + auto_created_coverage._auto_save = False
--- a/DebugClients/Python/coverage/data.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/data.py Tue May 01 12:03:52 2018 +0200 @@ -416,8 +416,12 @@ self._runs[0].update(kwargs) self._validate() - def touch_file(self, filename): - """Ensure that `filename` appears in the data, empty if needed.""" + def touch_file(self, filename, plugin_name=""): + """Ensure that `filename` appears in the data, empty if needed. + + `plugin_name` is the name of the plugin resposible for this file. It is used + to associate the right filereporter, etc. + """ if self._debug and self._debug.should('dataop'): self._debug.write("Touching %r" % (filename,)) if not self._has_arcs() and not self._has_lines(): @@ -428,6 +432,9 @@ else: where = self._lines where.setdefault(filename, []) + if plugin_name: + # Set the tracer for this file + self._file_tracers[filename] = plugin_name self._validate() @@ -451,7 +458,7 @@ # Write the data to the file. file_obj.write(self._GO_AWAY) - json.dump(file_data, file_obj) + json.dump(file_data, file_obj, separators=(',', ':')) def write_file(self, filename): """Write the coverage data to `filename`.""" @@ -605,15 +612,19 @@ class CoverageDataFiles(object): """Manage the use of coverage data files.""" - def __init__(self, basename=None, warn=None): + def __init__(self, basename=None, warn=None, debug=None): """Create a CoverageDataFiles to manage data files. `warn` is the warning function to use. `basename` is the name of the file to use for storing data. + `debug` is a `DebugControl` object for writing debug messages. + """ self.warn = warn + self.debug = debug + # Construct the file name that will be used for data storage. self.filename = os.path.abspath(basename or ".coverage") @@ -624,12 +635,16 @@ basename by parallel-mode. """ + if self.debug and self.debug.should('dataio'): + self.debug.write("Erasing data file %r" % (self.filename,)) file_be_gone(self.filename) if parallel: data_dir, local = os.path.split(self.filename) localdot = local + '.*' pattern = os.path.join(os.path.abspath(data_dir), localdot) for filename in glob.glob(pattern): + if self.debug and self.debug.should('dataio'): + self.debug.write("Erasing parallel data file %r" % (filename,)) file_be_gone(filename) def read(self, data): @@ -657,16 +672,14 @@ with open(_TEST_NAME_FILE) as f: test_name = f.read() extra = "." + test_name - suffix = "%s%s.%s.%06d" % ( - socket.gethostname(), extra, os.getpid(), - random.randint(0, 999999) - ) + dice = random.Random(os.urandom(8)).randint(0, 999999) + suffix = "%s%s.%s.%06d" % (socket.gethostname(), extra, os.getpid(), dice) if suffix: filename += "." + suffix data.write_file(filename) - def combine_parallel_data(self, data, aliases=None, data_paths=None): + def combine_parallel_data(self, data, aliases=None, data_paths=None, strict=False): """Combine a number of data files together. Treat `self.filename` as a file prefix, and combine the data from all @@ -686,6 +699,9 @@ cannot be read, a warning will be issued, and the file will not be deleted. + If `strict` is true, and no files are found to combine, an error is + raised. + """ # Because of the os.path.abspath in the constructor, data_dir will # never be an empty string. @@ -703,8 +719,12 @@ else: raise CoverageException("Couldn't combine from non-existent path '%s'" % (p,)) + if strict and not files_to_combine: + raise CoverageException("No data to combine") + + files_combined = 0 for f in files_to_combine: - new_data = CoverageData() + new_data = CoverageData(debug=self.debug) try: new_data.read_file(f) except CoverageException as exc: @@ -714,8 +734,14 @@ self.warn(str(exc)) else: data.update(new_data, aliases=aliases) + files_combined += 1 + if self.debug and self.debug.should('dataio'): + self.debug.write("Deleting combined data file %r" % (f,)) file_be_gone(f) + if strict and not files_combined: + raise CoverageException("No usable data files") + def canonicalize_json_data(data): """Canonicalize our JSON data so it can be compared."""
--- a/DebugClients/Python/coverage/debug.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/debug.py Tue May 01 12:03:52 2018 +0200 @@ -3,10 +3,17 @@ """Control of and utilities for debugging.""" +import contextlib import inspect import os +import re import sys +try: + import _thread +except ImportError: + import thread as _thread +from coverage.backward import StringIO from coverage.misc import isolate_module os = isolate_module(os) @@ -26,30 +33,58 @@ def __init__(self, options, output): """Configure the options and output file for debugging.""" - self.options = options - self.output = output + self.options = list(options) + FORCED_DEBUG + self.raw_output = output + self.suppress_callers = False + + filters = [] + if self.should('pid'): + filters.append(add_pid_and_tid) + self.output = DebugOutputFile( + self.raw_output, + show_process=self.should('process'), + filters=filters, + ) def __repr__(self): - return "<DebugControl options=%r output=%r>" % (self.options, self.output) + return "<DebugControl options=%r raw_output=%r>" % (self.options, self.raw_output) def should(self, option): """Decide whether to output debug information in category `option`.""" - return (option in self.options or option in FORCED_DEBUG) + if option == "callers" and self.suppress_callers: + return False + return (option in self.options) + + @contextlib.contextmanager + def without_callers(self): + """A context manager to prevent call stacks from being logged.""" + old = self.suppress_callers + self.suppress_callers = True + try: + yield + finally: + self.suppress_callers = old def write(self, msg): - """Write a line of debug output.""" - if self.should('pid'): - msg = "pid %5d: %s" % (os.getpid(), msg) + """Write a line of debug output. + + `msg` is the line to write. A newline will be appended. + + """ self.output.write(msg+"\n") if self.should('callers'): - dump_stack_frames(out=self.output) + dump_stack_frames(out=self.output, skip=1) self.output.flush() - def write_formatted_info(self, header, info): - """Write a sequence of (label,data) pairs nicely.""" - self.write(info_header(header)) - for line in info_formatter(info): - self.write(" %s" % line) + +class DebugControlString(DebugControl): + """A `DebugControl` that writes to a StringIO, for testing.""" + def __init__(self, options): + super(DebugControlString, self).__init__(options, StringIO()) + + def get_output(self): + """Get the output text from the `DebugControl`.""" + return self.raw_output.getvalue() def info_header(label): @@ -80,7 +115,14 @@ yield "%*s: %s" % (label_len, label, data) -def short_stack(limit=None): # pragma: debugging +def write_formatted_info(writer, header, info): + """Write a sequence of (label,data) pairs nicely.""" + writer.write(info_header(header)) + for line in info_formatter(info): + writer.write(" %s" % line) + + +def short_stack(limit=None, skip=0): """Return a string summarizing the call stack. The string is multi-line, with one line per stack frame. Each line shows @@ -94,13 +136,160 @@ `limit` is the number of frames to include, defaulting to all of them. + `skip` is the number of frames to skip, so that debugging functions can + call this and not be included in the result. + """ - stack = inspect.stack()[limit:0:-1] + stack = inspect.stack()[limit:skip:-1] return "\n".join("%30s : %s @%d" % (t[3], t[1], t[2]) for t in stack) -def dump_stack_frames(limit=None, out=None): # pragma: debugging - """Print a summary of the stack to stdout, or some place else.""" +def dump_stack_frames(limit=None, out=None, skip=0): + """Print a summary of the stack to stdout, or someplace else.""" out = out or sys.stdout - out.write(short_stack(limit=limit)) + out.write(short_stack(limit=limit, skip=skip+1)) out.write("\n") + + +def short_id(id64): + """Given a 64-bit id, make a shorter 16-bit one.""" + id16 = 0 + for offset in range(0, 64, 16): + id16 ^= id64 >> offset + return id16 & 0xFFFF + + +def add_pid_and_tid(text): + """A filter to add pid and tid to debug messages.""" + # Thread ids are useful, but too long. Make a shorter one. + tid = "{0:04x}".format(short_id(_thread.get_ident())) + text = "{0:5d}.{1}: {2}".format(os.getpid(), tid, text) + return text + + +def filter_text(text, filters): + """Run `text` through a series of filters. + + `filters` is a list of functions. Each takes a string and returns a + string. Each is run in turn. + + Returns: the final string that results after all of the filters have + run. + + """ + clean_text = text.rstrip() + ending = text[len(clean_text):] + text = clean_text + for fn in filters: + lines = [] + for line in text.splitlines(): + lines.extend(fn(line).splitlines()) + text = "\n".join(lines) + return text + ending + + +class CwdTracker(object): # pragma: debugging + """A class to add cwd info to debug messages.""" + def __init__(self): + self.cwd = None + + def filter(self, text): + """Add a cwd message for each new cwd.""" + cwd = os.getcwd() + if cwd != self.cwd: + text = "cwd is now {0!r}\n".format(cwd) + text + self.cwd = cwd + return text + + +class DebugOutputFile(object): # pragma: debugging + """A file-like object that includes pid and cwd information.""" + def __init__(self, outfile, show_process, filters): + self.outfile = outfile + self.show_process = show_process + self.filters = list(filters) + + if self.show_process: + self.filters.append(CwdTracker().filter) + cmd = " ".join(getattr(sys, 'argv', ['???'])) + self.write("New process: executable: %s\n" % (sys.executable,)) + self.write("New process: cmd: %s\n" % (cmd,)) + if hasattr(os, 'getppid'): + self.write("New process: parent pid: %s\n" % (os.getppid(),)) + + SYS_MOD_NAME = '$coverage.debug.DebugOutputFile.the_one' + + @classmethod + def the_one(cls, fileobj=None, show_process=True, filters=()): + """Get the process-wide singleton DebugOutputFile. + + If it doesn't exist yet, then create it as a wrapper around the file + object `fileobj`. `show_process` controls whether the debug file adds + process-level information. + + """ + # Because of the way igor.py deletes and re-imports modules, + # this class can be defined more than once. But we really want + # a process-wide singleton. So stash it in sys.modules instead of + # on a class attribute. Yes, this is aggressively gross. + the_one = sys.modules.get(cls.SYS_MOD_NAME) + if the_one is None: + assert fileobj is not None + sys.modules[cls.SYS_MOD_NAME] = the_one = cls(fileobj, show_process, filters) + return the_one + + def write(self, text): + """Just like file.write, but filter through all our filters.""" + self.outfile.write(filter_text(text, self.filters)) + self.outfile.flush() + + def flush(self): + """Flush our file.""" + self.outfile.flush() + + +def log(msg, stack=False): # pragma: debugging + """Write a log message as forcefully as possible.""" + out = DebugOutputFile.the_one() + out.write(msg+"\n") + if stack: + dump_stack_frames(out=out, skip=1) + + +def filter_aspectlib_frames(text): # pragma: debugging + """Aspectlib prints stack traces, but includes its own frames. Scrub those out.""" + # <<< aspectlib/__init__.py:257:function_wrapper < igor.py:143:run_tests < ... + text = re.sub(r"(?<= )aspectlib/[^.]+\.py:\d+:\w+ < ", "", text) + return text + + +def enable_aspectlib_maybe(): # pragma: debugging + """For debugging, we can use aspectlib to trace execution. + + Define COVERAGE_ASPECTLIB to enable and configure aspectlib to trace + execution:: + + $ export COVERAGE_LOG=covaspect.txt + $ export COVERAGE_ASPECTLIB=coverage.Coverage:coverage.data.CoverageData + $ coverage run blah.py ... + + This will trace all the public methods on Coverage and CoverageData, + writing the information to covaspect.txt. + + """ + aspects = os.environ.get("COVERAGE_ASPECTLIB", "") + if not aspects: + return + + import aspectlib # pylint: disable=import-error + import aspectlib.debug # pylint: disable=import-error + + filename = os.environ.get("COVERAGE_LOG", "/tmp/covlog.txt") + filters = [add_pid_and_tid, filter_aspectlib_frames] + aspects_file = DebugOutputFile.the_one(open(filename, "a"), show_process=True, filters=filters) + aspect_log = aspectlib.debug.log( + print_to=aspects_file, attributes=['id'], stacktrace=30, use_logging=False + ) + public_methods = re.compile(r'^(__init__|[a-zA-Z].*)$') + for aspect in aspects.split(':'): + aspectlib.weave(aspect, aspect_log, methods=public_methods)
--- a/DebugClients/Python/coverage/doc/CHANGES.rst Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/doc/CHANGES.rst Tue May 01 12:03:52 2018 +0200 @@ -5,6 +5,490 @@ Change history for Coverage.py ============================== + .. When updating the "Unreleased" header to a specific version, use this + .. format. Don't forget the jump target: + .. + .. + .. .. _changes_781: + .. + .. + .. Version 7.8.1 --- 2021-07-27 + .. ---------------------------- + + +.. _changes_451: + +Version 4.5.1 --- 2018-02-10 +---------------------------- + +- Now that 4.5 properly separated the ``[run] omit`` and ``[report] omit`` + settings, an old bug has become apparent. If you specified a package name + for ``[run] source``, then omit patterns weren't matched inside that package. + This bug (`issue 638`_) is now fixed. + +- On Python 3.7, reporting about a decorated function with no body other than a + docstring would crash coverage.py with an IndexError (`issue 640`_). This is + now fixed. + +- Configurer plugins are now reported in the output of ``--debug=sys``. + +.. _issue 638: https://bitbucket.org/ned/coveragepy/issues/638/run-omit-is-ignored-since-45 +.. _issue 640: https://bitbucket.org/ned/coveragepy/issues/640/indexerror-reporting-on-an-empty-decorated + + +.. _changes_45: + +Version 4.5 --- 2018-02-03 +-------------------------- + +- A new kind of plugin is supported: configurators are invoked at start-up to + allow more complex configuration than the .coveragerc file can easily do. + See :ref:`api_plugin` for details. This solves the complex configuration + problem described in `issue 563`_. + +- The ``fail_under`` option can now be a float. Note that you must specify the + ``[report] precision`` configuration option for the fractional part to be + used. Thanks to Lars Hupfeldt Nielsen for help with the implementation. + Fixes `issue 631`_. + +- The ``include`` and ``omit`` options can be specified for both the ``[run]`` + and ``[report]`` phases of execution. 4.4.2 introduced some incorrect + interactions between those phases, where the options for one were confused + for the other. This is now corrected, fixing `issue 621`_ and `issue 622`_. + Thanks to Daniel Hahler for seeing more clearly than I could. + +- The ``coverage combine`` command used to always overwrite the data file, even + when no data had been read from apparently combinable files. Now, an error + is raised if we thought there were files to combine, but in fact none of them + could be used. Fixes `issue 629`_. + +- The ``coverage combine`` command could get confused about path separators + when combining data collected on Windows with data collected on Linux, as + described in `issue 618`_. This is now fixed: the result path always uses + the path separator specified in the ``[paths]`` result. + +- On Windows, the HTML report could fail when source trees are deeply nested, + due to attempting to create HTML filenames longer than the 250-character + maximum. Now filenames will never get much larger than 200 characters, + fixing `issue 627`_. Thanks to Alex Sandro for helping with the fix. + +.. _issue 563: https://bitbucket.org/ned/coveragepy/issues/563/platform-specific-configuration +.. _issue 618: https://bitbucket.org/ned/coveragepy/issues/618/problem-when-combining-windows-generated +.. _issue 621: https://bitbucket.org/ned/coveragepy/issues/621/include-ignored-warning-when-using +.. _issue 622: https://bitbucket.org/ned/coveragepy/issues/622/report-omit-overwrites-run-omit +.. _issue 627: https://bitbucket.org/ned/coveragepy/issues/627/failure-generating-html-reports-when-the +.. _issue 629: https://bitbucket.org/ned/coveragepy/issues/629/multiple-use-of-combine-leads-to-empty +.. _issue 631: https://bitbucket.org/ned/coveragepy/issues/631/precise-coverage-percentage-value + + +.. _changes_442: + +Version 4.4.2 --- 2017-11-05 +---------------------------- + +- Support for Python 3.7. In some cases, class and module docstrings are no + longer counted in statement totals, which could slightly change your total + results. + +- Specifying both ``--source`` and ``--include`` no longer silently ignores the + include setting, instead it displays a warning. Thanks, Loïc Dachary. Closes + `issue 265`_ and `issue 101`_. + +- Fixed a race condition when saving data and multiple threads are tracing + (`issue 581`_). It could produce a "dictionary changed size during iteration" + RuntimeError. I believe this mostly but not entirely fixes the race + condition. A true fix would likely be too expensive. Thanks, Peter Baughman + for the debugging, and Olivier Grisel for the fix with tests. + +- Configuration values which are file paths will now apply tilde-expansion, + closing `issue 589`_. + +- Now secondary config files like tox.ini and setup.cfg can be specified + explicitly, and prefixed sections like `[coverage:run]` will be read. Fixes + `issue 588`_. + +- Be more flexible about the command name displayed by help, fixing + `issue 600`_. Thanks, Ben Finney. + +.. _issue 101: https://bitbucket.org/ned/coveragepy/issues/101/settings-under-report-affect-running +.. _issue 581: https://bitbucket.org/ned/coveragepy/issues/581/race-condition-when-saving-data-under +.. _issue 588: https://bitbucket.org/ned/coveragepy/issues/588/using-rcfile-path-to-toxini-uses-run +.. _issue 589: https://bitbucket.org/ned/coveragepy/issues/589/allow-expansion-in-coveragerc +.. _issue 600: https://bitbucket.org/ned/coveragepy/issues/600/get-program-name-from-command-line-when + + +.. _changes_441: + +Version 4.4.1 --- 2017-05-14 +---------------------------- + +- No code changes: just corrected packaging for Python 2.7 Linux wheels. + + +.. _changes_44: + +Version 4.4 --- 2017-05-07 +-------------------------- + +- Reports could produce the wrong file names for packages, reporting ``pkg.py`` + instead of the correct ``pkg/__init__.py``. This is now fixed. Thanks, Dirk + Thomas. + +- XML reports could produce ``<source>`` and ``<class>`` lines that together + didn't specify a valid source file path. This is now fixed. (`issue 526`_) + +- Namespace packages are no longer warned as having no code. (`issue 572`_) + +- Code that uses ``sys.settrace(sys.gettrace())`` in a file that wasn't being + coverage-measured would prevent correct coverage measurement in following + code. An example of this was running doctests programmatically. This is now + fixed. (`issue 575`_) + +- Errors printed by the ``coverage`` command now go to stderr instead of + stdout. + +- Running ``coverage xml`` in a directory named with non-ASCII characters would + fail under Python 2. This is now fixed. (`issue 573`_) + +.. _issue 526: https://bitbucket.org/ned/coveragepy/issues/526/generated-xml-invalid-paths-for-cobertura +.. _issue 572: https://bitbucket.org/ned/coveragepy/issues/572/no-python-source-warning-for-namespace +.. _issue 573: https://bitbucket.org/ned/coveragepy/issues/573/cant-generate-xml-report-if-some-source +.. _issue 575: https://bitbucket.org/ned/coveragepy/issues/575/running-doctest-prevents-complete-coverage + + +Version 4.4b1 --- 2017-04-04 +---------------------------- + +- Some warnings can now be individually disabled. Warnings that can be + disabled have a short name appended. The ``[run] disable_warnings`` setting + takes a list of these warning names to disable. Closes both `issue 96`_ and + `issue 355`_. + +- The XML report now includes attributes from version 4 of the Cobertura XML + format, fixing `issue 570`_. + +- In previous versions, calling a method that used collected data would prevent + further collection. For example, `save()`, `report()`, `html_report()`, and + others would all stop collection. An explicit `start()` was needed to get it + going again. This is no longer true. Now you can use the collected data and + also continue measurement. Both `issue 79`_ and `issue 448`_ described this + problem, and have been fixed. + +- Plugins can now find unexecuted files if they choose, by implementing the + `find_executable_files` method. Thanks, Emil Madsen. + +- Minimal IronPython support. You should be able to run IronPython programs + under ``coverage run``, though you will still have to do the reporting phase + with CPython. + +- Coverage.py has long had a special hack to support CPython's need to measure + the coverage of the standard library tests. This code was not installed by + kitted versions of coverage.py. Now it is. + +.. _issue 79: https://bitbucket.org/ned/coveragepy/issues/79/save-prevents-harvesting-on-stop +.. _issue 96: https://bitbucket.org/ned/coveragepy/issues/96/unhelpful-warnings-produced-when-using +.. _issue 355: https://bitbucket.org/ned/coveragepy/issues/355/warnings-should-be-suppressable +.. _issue 448: https://bitbucket.org/ned/coveragepy/issues/448/save-and-html_report-prevent-further +.. _issue 570: https://bitbucket.org/ned/coveragepy/issues/570/cobertura-coverage-04dtd-support + + +.. _changes_434: + +Version 4.3.4 --- 2017-01-17 +---------------------------- + +- Fixing 2.6 in version 4.3.3 broke other things, because the too-tricky + exception wasn't properly derived from Exception, described in `issue 556`_. + A newb mistake; it hasn't been a good few days. + +.. _issue 556: https://bitbucket.org/ned/coveragepy/issues/556/43-fails-if-there-are-html-files-in-the + + +.. _changes_433: + +Version 4.3.3 --- 2017-01-17 +---------------------------- + +- Python 2.6 support was broken due to a testing exception imported for the + benefit of the coverage.py test suite. Properly conditionalizing it fixed + `issue 554`_ so that Python 2.6 works again. + +.. _issue 554: https://bitbucket.org/ned/coveragepy/issues/554/traceback-on-python-26-starting-with-432 + + +.. _changes_432: + +Version 4.3.2 --- 2017-01-16 +---------------------------- + +- Using the ``--skip-covered`` option on an HTML report with 100% coverage + would cause a "No data to report" error, as reported in `issue 549`_. This is + now fixed; thanks, Loïc Dachary. + +- If-statements can be optimized away during compilation, for example, `if 0:` + or `if __debug__:`. Coverage.py had problems properly understanding these + statements which existed in the source, but not in the compiled bytecode. + This problem, reported in `issue 522`_, is now fixed. + +- If you specified ``--source`` as a directory, then coverage.py would look for + importable Python files in that directory, and could identify ones that had + never been executed at all. But if you specified it as a package name, that + detection wasn't performed. Now it is, closing `issue 426`_. Thanks to Loïc + Dachary for the fix. + +- If you started and stopped coverage measurement thousands of times in your + process, you could crash Python with a "Fatal Python error: deallocating + None" error. This is now fixed. Thanks to Alex Groce for the bug report. + +- On PyPy, measuring coverage in subprocesses could produce a warning: "Trace + function changed, measurement is likely wrong: None". This was spurious, and + has been suppressed. + +- Previously, coverage.py couldn't start on Jython, due to that implementation + missing the multiprocessing module (`issue 551`_). This problem has now been + fixed. Also, `issue 322`_ about not being able to invoke coverage + conveniently, seems much better: ``jython -m coverage run myprog.py`` works + properly. + +- Let's say you ran the HTML report over and over again in the same output + directory, with ``--skip-covered``. And imagine due to your heroic + test-writing efforts, a file just achieved the goal of 100% coverage. With + coverage.py 4.3, the old HTML file with the less-than-100% coverage would be + left behind. This file is now properly deleted. + +.. _issue 322: https://bitbucket.org/ned/coveragepy/issues/322/cannot-use-coverage-with-jython +.. _issue 426: https://bitbucket.org/ned/coveragepy/issues/426/difference-between-coverage-results-with +.. _issue 522: https://bitbucket.org/ned/coveragepy/issues/522/incorrect-branch-reporting-with-__debug__ +.. _issue 549: https://bitbucket.org/ned/coveragepy/issues/549/skip-covered-with-100-coverage-throws-a-no +.. _issue 551: https://bitbucket.org/ned/coveragepy/issues/551/coveragepy-cannot-be-imported-in-jython27 + + +.. _changes_431: + +Version 4.3.1 --- 2016-12-28 +---------------------------- + +- Some environments couldn't install 4.3, as described in `issue 540`_. This is + now fixed. + +- The check for conflicting ``--source`` and ``--include`` was too simple in a + few different ways, breaking a few perfectly reasonable use cases, described + in `issue 541`_. The check has been reverted while we re-think the fix for + `issue 265`_. + +.. _issue 540: https://bitbucket.org/ned/coveragepy/issues/540/cant-install-coverage-v43-into-under +.. _issue 541: https://bitbucket.org/ned/coveragepy/issues/541/coverage-43-breaks-nosetest-with-coverage + + +.. _changes_43: + +Version 4.3 --- 2016-12-27 +-------------------------- + +Special thanks to **Loïc Dachary**, who took an extraordinary interest in +coverage.py and contributed a number of improvements in this release. + +- Subprocesses that are measured with `automatic subprocess measurement`_ used + to read in any pre-existing data file. This meant data would be incorrectly + carried forward from run to run. Now those files are not read, so each + subprocess only writes its own data. Fixes `issue 510`_. + +- The ``coverage combine`` command will now fail if there are no data files to + combine. The combine changes in 4.2 meant that multiple combines could lose + data, leaving you with an empty .coverage data file. Fixes + `issue 525`_, `issue 412`_, `issue 516`_, and probably `issue 511`_. + +- Coverage.py wouldn't execute `sys.excepthook`_ when an exception happened in + your program. Now it does, thanks to Andrew Hoos. Closes `issue 535`_. + +- Branch coverage fixes: + + - Branch coverage could misunderstand a finally clause on a try block that + never continued on to the following statement, as described in `issue + 493`_. This is now fixed. Thanks to Joe Doherty for the report and Loïc + Dachary for the fix. + + - A while loop with a constant condition (while True) and a continue + statement would be mis-analyzed, as described in `issue 496`_. This is now + fixed, thanks to a bug report by Eli Skeggs and a fix by Loïc Dachary. + + - While loops with constant conditions that were never executed could result + in a non-zero coverage report. Artem Dayneko reported this in `issue + 502`_, and Loïc Dachary provided the fix. + +- The HTML report now supports a ``--skip-covered`` option like the other + reporting commands. Thanks, Loïc Dachary for the implementation, closing + `issue 433`_. + +- Options can now be read from a tox.ini file, if any. Like setup.cfg, sections + are prefixed with "coverage:", so ``[run]`` options will be read from the + ``[coverage:run]`` section of tox.ini. Implements part of `issue 519`_. + Thanks, Stephen Finucane. + +- Specifying both ``--source`` and ``--include`` no longer silently ignores the + include setting, instead it fails with a message. Thanks, Nathan Land and + Loïc Dachary. Closes `issue 265`_. + +- The ``Coverage.combine`` method has a new parameter, ``strict=False``, to + support failing if there are no data files to combine. + +- When forking subprocesses, the coverage data files would have the same random + number appended to the file name. This didn't cause problems, because the + file names had the process id also, making collisions (nearly) impossible. + But it was disconcerting. This is now fixed. + +- The text report now properly sizes headers when skipping some files, fixing + `issue 524`_. Thanks, Anthony Sottile and Loïc Dachary. + +- Coverage.py can now search .pex files for source, just as it can .zip and + .egg. Thanks, Peter Ebden. + +- Data files are now about 15% smaller. + +- Improvements in the ``[run] debug`` setting: + + - The "dataio" debug setting now also logs when data files are deleted during + combining or erasing. + + - A new debug option, "multiproc", for logging the behavior of + ``concurrency=multiprocessing``. + + - If you used the debug options "config" and "callers" together, you'd get a + call stack printed for every line in the multi-line config output. This is + now fixed. + +- Fixed an unusual bug involving multiple coding declarations affecting code + containing code in multi-line strings: `issue 529`_. + +- Coverage.py will no longer be misled into thinking that a plain file is a + package when interpreting ``--source`` options. Thanks, Cosimo Lupo. + +- If you try to run a non-Python file with coverage.py, you will now get a more + useful error message. `Issue 514`_. + +- The default pragma regex changed slightly, but this will only matter to you + if you are deranged and use mixed-case pragmas. + +- Deal properly with non-ASCII file names in an ASCII-only world, `issue 533`_. + +- Programs that set Unicode configuration values could cause UnicodeErrors when + generating HTML reports. Pytest-cov is one example. This is now fixed. + +- Prevented deprecation warnings from configparser that happened in some + circumstances, closing `issue 530`_. + +- Corrected the name of the jquery.ba-throttle-debounce.js library. Thanks, + Ben Finney. Closes `issue 505`_. + +- Testing against PyPy 5.6 and PyPy3 5.5. + +- Switched to pytest from nose for running the coverage.py tests. + +- Renamed AUTHORS.txt to CONTRIBUTORS.txt, since there are other ways to + contribute than by writing code. Also put the count of contributors into the + author string in setup.py, though this might be too cute. + +.. _sys.excepthook: https://docs.python.org/3/library/sys.html#sys.excepthook +.. _issue 265: https://bitbucket.org/ned/coveragepy/issues/265/when-using-source-include-is-silently +.. _issue 412: https://bitbucket.org/ned/coveragepy/issues/412/coverage-combine-should-error-if-no +.. _issue 433: https://bitbucket.org/ned/coveragepy/issues/433/coverage-html-does-not-suport-skip-covered +.. _issue 493: https://bitbucket.org/ned/coveragepy/issues/493/confusing-branching-failure +.. _issue 496: https://bitbucket.org/ned/coveragepy/issues/496/incorrect-coverage-with-branching-and +.. _issue 502: https://bitbucket.org/ned/coveragepy/issues/502/incorrect-coverage-report-with-cover +.. _issue 505: https://bitbucket.org/ned/coveragepy/issues/505/use-canonical-filename-for-debounce +.. _issue 514: https://bitbucket.org/ned/coveragepy/issues/514/path-to-problem-file-not-reported-when +.. _issue 510: https://bitbucket.org/ned/coveragepy/issues/510/erase-still-needed-in-42 +.. _issue 511: https://bitbucket.org/ned/coveragepy/issues/511/version-42-coverage-combine-empties +.. _issue 516: https://bitbucket.org/ned/coveragepy/issues/516/running-coverage-combine-twice-deletes-all +.. _issue 519: https://bitbucket.org/ned/coveragepy/issues/519/coverage-run-sections-in-toxini-or-as +.. _issue 524: https://bitbucket.org/ned/coveragepy/issues/524/coverage-report-with-skip-covered-column +.. _issue 525: https://bitbucket.org/ned/coveragepy/issues/525/coverage-combine-when-not-in-parallel-mode +.. _issue 529: https://bitbucket.org/ned/coveragepy/issues/529/encoding-marker-may-only-appear-on-the +.. _issue 530: https://bitbucket.org/ned/coveragepy/issues/530/deprecationwarning-you-passed-a-bytestring +.. _issue 533: https://bitbucket.org/ned/coveragepy/issues/533/exception-on-unencodable-file-name +.. _issue 535: https://bitbucket.org/ned/coveragepy/issues/535/sysexcepthook-is-not-called + + +.. _changes_42: + +Version 4.2 --- 2016-07-26 +-------------------------- + +- Since ``concurrency=multiprocessing`` uses subprocesses, options specified on + the coverage.py command line will not be communicated down to them. Only + options in the configuration file will apply to the subprocesses. + Previously, the options didn't apply to the subprocesses, but there was no + indication. Now it is an error to use ``--concurrency=multiprocessing`` and + other run-affecting options on the command line. This prevents + failures like those reported in `issue 495`_. + +- Filtering the HTML report is now faster, thanks to Ville Skyttä. + +.. _issue 495: https://bitbucket.org/ned/coveragepy/issues/495/branch-and-concurrency-are-conflicting + + +Version 4.2b1 --- 2016-07-04 +---------------------------- + +Work from the PyCon 2016 Sprints! + +- BACKWARD INCOMPATIBILITY: the ``coverage combine`` command now ignores an + existing ``.coverage`` data file. It used to include that file in its + combining. This caused confusing results, and extra tox "clean" steps. If + you want the old behavior, use the new ``coverage combine --append`` option. + +- The ``concurrency`` option can now take multiple values, to support programs + using multiprocessing and another library such as eventlet. This is only + possible in the configuration file, not from the command line. The + configuration file is the only way for sub-processes to all run with the same + options. Fixes `issue 484`_. Thanks to Josh Williams for prototyping. + +- Using a ``concurrency`` setting of ``multiprocessing`` now implies + ``--parallel`` so that the main program is measured similarly to the + sub-processes. + +- When using `automatic subprocess measurement`_, running coverage commands + would create spurious data files. This is now fixed, thanks to diagnosis and + testing by Dan Riti. Closes `issue 492`_. + +- A new configuration option, ``report:sort``, controls what column of the + text report is used to sort the rows. Thanks to Dan Wandschneider, this + closes `issue 199`_. + +- The HTML report has a more-visible indicator for which column is being + sorted. Closes `issue 298`_, thanks to Josh Williams. + +- If the HTML report cannot find the source for a file, the message now + suggests using the ``-i`` flag to allow the report to continue. Closes + `issue 231`_, thanks, Nathan Land. + +- When reports are ignoring errors, there's now a warning if a file cannot be + parsed, rather than being silently ignored. Closes `issue 396`_. Thanks, + Matthew Boehm. + +- A new option for ``coverage debug`` is available: ``coverage debug config`` + shows the current configuration. Closes `issue 454`_, thanks to Matthew + Boehm. + +- Running coverage as a module (``python -m coverage``) no longer shows the + program name as ``__main__.py``. Fixes `issue 478`_. Thanks, Scott Belden. + +- The `test_helpers` module has been moved into a separate pip-installable + package: `unittest-mixins`_. + +.. _automatic subprocess measurement: https://coverage.readthedocs.io/en/latest/subprocess.html +.. _issue 199: https://bitbucket.org/ned/coveragepy/issues/199/add-a-way-to-sort-the-text-report +.. _issue 231: https://bitbucket.org/ned/coveragepy/issues/231/various-default-behavior-in-report-phase +.. _issue 298: https://bitbucket.org/ned/coveragepy/issues/298/show-in-html-report-that-the-columns-are +.. _issue 396: https://bitbucket.org/ned/coveragepy/issues/396/coverage-xml-shouldnt-bail-out-on-parse +.. _issue 454: https://bitbucket.org/ned/coveragepy/issues/454/coverage-debug-config-should-be +.. _issue 478: https://bitbucket.org/ned/coveragepy/issues/478/help-shows-silly-program-name-when-running +.. _issue 484: https://bitbucket.org/ned/coveragepy/issues/484/multiprocessing-greenlet-concurrency +.. _issue 492: https://bitbucket.org/ned/coveragepy/issues/492/subprocess-coverage-strange-detection-of +.. _unittest-mixins: https://pypi.python.org/pypi/unittest-mixins + + +.. _changes_41: Version 4.1 --- 2016-05-21 -------------------------- @@ -160,6 +644,8 @@ .. _issue 461: https://bitbucket.org/ned/coveragepy/issues/461/multiline-asserts-need-too-many-pragma +.. _changes_403: + Version 4.0.3 --- 2015-11-24 ---------------------------- @@ -185,6 +671,8 @@ .. _issue 445: https://bitbucket.org/ned/coveragepy/issues/445/django-app-cannot-connect-to-cassandra +.. _changes_402: + Version 4.0.2 --- 2015-11-04 ---------------------------- @@ -204,6 +692,8 @@ .. _issue 436: https://bitbucket.org/ned/coveragepy/issues/436/disabled-coverage-ctracer-may-rise-from +.. _changes_401: + Version 4.0.1 --- 2015-10-13 ---------------------------- @@ -250,6 +740,8 @@ .. _issue 423: https://bitbucket.org/ned/coveragepy/issues/423/skip_covered-changes-reported-total +.. _changes_40: + Version 4.0 --- 2015-09-20 -------------------------- @@ -276,7 +768,6 @@ .. _issue 404: https://bitbucket.org/ned/coveragepy/issues/404/shiningpanda-jenkins-plugin-cant-find-html - Version 4.0b2 --- 2015-08-22 ---------------------------- @@ -410,8 +901,9 @@ persisted in pursuing this despite Ned's pessimism. Fixes `issue 308`_ and `issue 324`_. -- The COVERAGE_DEBUG environment variable can be used to set the ``[run] debug`` - configuration option to control what internal operations are logged. +- The COVERAGE_DEBUG environment variable can be used to set the + ``[run] debug`` configuration option to control what internal operations are + logged. - HTML reports were truncated at formfeed characters. This is now fixed (`issue 360`_). It's always fun when the problem is due to a `bug in the @@ -437,17 +929,17 @@ - Plugin support had some bugs fixed, closing `issue 374`_ and `issue 375`_. Thanks, Stefan Behnel. -.. _issue 299: https://bitbucket.org/ned/coveragepy/issue/299/inserted-created-on-yyyy-mm-dd-hh-mm-in -.. _issue 308: https://bitbucket.org/ned/coveragepy/issue/308/yield-lambda-branch-coverage -.. _issue 324: https://bitbucket.org/ned/coveragepy/issue/324/yield-in-loop-confuses-branch-coverage -.. _issue 351: https://bitbucket.org/ned/coveragepy/issue/351/files-with-incorrect-encoding-are-ignored -.. _issue 354: https://bitbucket.org/ned/coveragepy/issue/354/coverage-combine-should-take-a-list-of -.. _issue 359: https://bitbucket.org/ned/coveragepy/issue/359/xml-report-chunk-error -.. _issue 360: https://bitbucket.org/ned/coveragepy/issue/360/html-reports-get-confused-by-l-in-the-code -.. _issue 361: https://bitbucket.org/ned/coveragepy/issue/361/use-double-quotes-in-html-output-to -.. _issue 363: https://bitbucket.org/ned/coveragepy/issue/363/annotate-command-hits-unicode-happy-fun -.. _issue 374: https://bitbucket.org/ned/coveragepy/issue/374/c-tracer-lookups-fail-in -.. _issue 375: https://bitbucket.org/ned/coveragepy/issue/375/ctracer_handle_return-reads-byte-code +.. _issue 299: https://bitbucket.org/ned/coveragepy/issues/299/inserted-created-on-yyyy-mm-dd-hh-mm-in +.. _issue 308: https://bitbucket.org/ned/coveragepy/issues/308/yield-lambda-branch-coverage +.. _issue 324: https://bitbucket.org/ned/coveragepy/issues/324/yield-in-loop-confuses-branch-coverage +.. _issue 351: https://bitbucket.org/ned/coveragepy/issues/351/files-with-incorrect-encoding-are-ignored +.. _issue 354: https://bitbucket.org/ned/coveragepy/issues/354/coverage-combine-should-take-a-list-of +.. _issue 359: https://bitbucket.org/ned/coveragepy/issues/359/xml-report-chunk-error +.. _issue 360: https://bitbucket.org/ned/coveragepy/issues/360/html-reports-get-confused-by-l-in-the-code +.. _issue 361: https://bitbucket.org/ned/coveragepy/issues/361/use-double-quotes-in-html-output-to +.. _issue 363: https://bitbucket.org/ned/coveragepy/issues/363/annotate-command-hits-unicode-happy-fun +.. _issue 374: https://bitbucket.org/ned/coveragepy/issues/374/c-tracer-lookups-fail-in +.. _issue 375: https://bitbucket.org/ned/coveragepy/issues/375/ctracer_handle_return-reads-byte-code Version 4.0a5 --- 2015-02-16 @@ -477,11 +969,11 @@ - Added 3.5.0a1 to the list of supported CPython versions. -.. _issue 117: https://bitbucket.org/ned/coveragepy/issue/117/enable-coverage-measurement-of-code-run-by -.. _issue 340: https://bitbucket.org/ned/coveragepy/issue/340/keyerror-subpy -.. _issue 353: https://bitbucket.org/ned/coveragepy/issue/353/40a3-introduces-an-unexpected-third-case -.. _issue 357: https://bitbucket.org/ned/coveragepy/issue/357/behavior-changed-when-coveragerc-is -.. _issue 358: https://bitbucket.org/ned/coveragepy/issue/358/all-coverage-commands-should-adjust +.. _issue 117: https://bitbucket.org/ned/coveragepy/issues/117/enable-coverage-measurement-of-code-run-by +.. _issue 340: https://bitbucket.org/ned/coveragepy/issues/340/keyerror-subpy +.. _issue 353: https://bitbucket.org/ned/coveragepy/issues/353/40a3-introduces-an-unexpected-third-case +.. _issue 357: https://bitbucket.org/ned/coveragepy/issues/357/behavior-changed-when-coveragerc-is +.. _issue 358: https://bitbucket.org/ned/coveragepy/issues/358/all-coverage-commands-should-adjust Version 4.0a4 --- 2015-01-25 @@ -521,11 +1013,11 @@ - Regexes in the configuration file are now compiled as soon as they are read, to provide error messages earlier (`issue 349`_). -.. _issue 69: https://bitbucket.org/ned/coveragepy/issue/69/coverage-html-overwrite-files-that-doesnt -.. _issue 235: https://bitbucket.org/ned/coveragepy/issue/235/package-name-is-missing-in-xml-report -.. _issue 290: https://bitbucket.org/ned/coveragepy/issue/290/running-programmatically-with-pyw-files -.. _issue 345: https://bitbucket.org/ned/coveragepy/issue/345/xml-reports-line-rate-0-for-empty-files -.. _issue 349: https://bitbucket.org/ned/coveragepy/issue/349/bad-regex-in-config-should-get-an-earlier +.. _issue 69: https://bitbucket.org/ned/coveragepy/issues/69/coverage-html-overwrite-files-that-doesnt +.. _issue 235: https://bitbucket.org/ned/coveragepy/issues/235/package-name-is-missing-in-xml-report +.. _issue 290: https://bitbucket.org/ned/coveragepy/issues/290/running-programmatically-with-pyw-files +.. _issue 345: https://bitbucket.org/ned/coveragepy/issues/345/xml-reports-line-rate-0-for-empty-files +.. _issue 349: https://bitbucket.org/ned/coveragepy/issues/349/bad-regex-in-config-should-get-an-earlier Version 4.0a2 --- 2015-01-14 @@ -585,15 +1077,15 @@ haven't changed is now a JSON file instead of a pickle file. This obviates `issue 287`_ and `issue 237`_. -.. _issue 237: https://bitbucket.org/ned/coveragepy/issue/237/htmlcov-with-corrupt-statusdat -.. _issue 287: https://bitbucket.org/ned/coveragepy/issue/287/htmlpy-doesnt-specify-pickle-protocol -.. _issue 293: https://bitbucket.org/ned/coveragepy/issue/293/number-of-statement-detection-wrong-if-no -.. _issue 314: https://bitbucket.org/ned/coveragepy/issue/314/fail_under-param-not-working-in-coveragerc -.. _issue 315: https://bitbucket.org/ned/coveragepy/issue/315/option-to-omit-empty-files-eg-__init__py -.. _issue 328: https://bitbucket.org/ned/coveragepy/issue/328/misbehavior-in-run-source -.. _issue 334: https://bitbucket.org/ned/coveragepy/issue/334/pragma-not-recognized-if-tab-character -.. _issue 342: https://bitbucket.org/ned/coveragepy/issue/342/console-and-html-coverage-reports-differ -.. _issue 343: https://bitbucket.org/ned/coveragepy/issue/343/an-explicitly-named-non-existent-config +.. _issue 237: https://bitbucket.org/ned/coveragepy/issues/237/htmlcov-with-corrupt-statusdat +.. _issue 287: https://bitbucket.org/ned/coveragepy/issues/287/htmlpy-doesnt-specify-pickle-protocol +.. _issue 293: https://bitbucket.org/ned/coveragepy/issues/293/number-of-statement-detection-wrong-if-no +.. _issue 314: https://bitbucket.org/ned/coveragepy/issues/314/fail_under-param-not-working-in-coveragerc +.. _issue 315: https://bitbucket.org/ned/coveragepy/issues/315/option-to-omit-empty-files-eg-__init__py +.. _issue 328: https://bitbucket.org/ned/coveragepy/issues/328/misbehavior-in-run-source +.. _issue 334: https://bitbucket.org/ned/coveragepy/issues/334/pragma-not-recognized-if-tab-character +.. _issue 342: https://bitbucket.org/ned/coveragepy/issues/342/console-and-html-coverage-reports-differ +.. _issue 343: https://bitbucket.org/ned/coveragepy/issues/343/an-explicitly-named-non-existent-config Version 4.0a1 --- 2014-09-27 @@ -638,17 +1130,19 @@ - Encoding declarations in source files are only considered if they are truly comments. Thanks, Anthony Sottile. -.. _issue 57: https://bitbucket.org/ned/coveragepy/issue/57/annotate-command-fails-to-annotate-many -.. _issue 94: https://bitbucket.org/ned/coveragepy/issue/94/coverage-xml-doesnt-produce-sources -.. _issue 149: https://bitbucket.org/ned/coveragepy/issue/149/coverage-gevent-looks-broken -.. _issue 230: https://bitbucket.org/ned/coveragepy/issue/230/show-line-no-for-missing-branches-in -.. _issue 284: https://bitbucket.org/ned/coveragepy/issue/284/fail-under-should-show-more-precision -.. _issue 285: https://bitbucket.org/ned/coveragepy/issue/285/xml-report-fails-if-output-file-directory -.. _issue 303: https://bitbucket.org/ned/coveragepy/issue/303/unicodedecodeerror -.. _issue 304: https://bitbucket.org/ned/coveragepy/issue/304/attempt-to-get-configuration-from-setupcfg -.. _issue 305: https://bitbucket.org/ned/coveragepy/issue/305/pendingdeprecationwarning-the-imp-module -.. _issue 331: https://bitbucket.org/ned/coveragepy/issue/331/failure-of-encoding-detection-on-python2 - +.. _issue 57: https://bitbucket.org/ned/coveragepy/issues/57/annotate-command-fails-to-annotate-many +.. _issue 94: https://bitbucket.org/ned/coveragepy/issues/94/coverage-xml-doesnt-produce-sources +.. _issue 149: https://bitbucket.org/ned/coveragepy/issues/149/coverage-gevent-looks-broken +.. _issue 230: https://bitbucket.org/ned/coveragepy/issues/230/show-line-no-for-missing-branches-in +.. _issue 284: https://bitbucket.org/ned/coveragepy/issues/284/fail-under-should-show-more-precision +.. _issue 285: https://bitbucket.org/ned/coveragepy/issues/285/xml-report-fails-if-output-file-directory +.. _issue 303: https://bitbucket.org/ned/coveragepy/issues/303/unicodedecodeerror +.. _issue 304: https://bitbucket.org/ned/coveragepy/issues/304/attempt-to-get-configuration-from-setupcfg +.. _issue 305: https://bitbucket.org/ned/coveragepy/issues/305/pendingdeprecationwarning-the-imp-module +.. _issue 331: https://bitbucket.org/ned/coveragepy/issues/331/failure-of-encoding-detection-on-python2 + + +.. _changes_371: Version 3.7.1 --- 2013-12-13 ---------------------------- @@ -659,6 +1153,8 @@ so that it will actually find OS-installed static files. +.. _changes_37: + Version 3.7 --- 2013-10-06 -------------------------- @@ -702,19 +1198,21 @@ - The source kit now includes the ``__main__.py`` file in the root coverage directory, fixing `issue 255`_. -.. _issue 92: https://bitbucket.org/ned/coveragepy/issue/92/finally-clauses-arent-treated-properly-in -.. _issue 164: https://bitbucket.org/ned/coveragepy/issue/164/trace-function-changed-warning-when-using -.. _issue 175: https://bitbucket.org/ned/coveragepy/issue/175/branch-coverage-gets-confused-in-certain -.. _issue 207: https://bitbucket.org/ned/coveragepy/issue/207/run-m-cannot-find-module-or-package-in -.. _issue 242: https://bitbucket.org/ned/coveragepy/issue/242/running-a-two-level-package-doesnt-work -.. _issue 218: https://bitbucket.org/ned/coveragepy/issue/218/run-command-does-not-respect-the-omit-flag -.. _issue 250: https://bitbucket.org/ned/coveragepy/issue/250/uncaught-zerodivisionerror-when-generating -.. _issue 255: https://bitbucket.org/ned/coveragepy/issue/255/directory-level-__main__py-not-included-in -.. _issue 259: https://bitbucket.org/ned/coveragepy/issue/259/allow-use-of-system-installed-third-party -.. _issue 261: https://bitbucket.org/ned/coveragepy/issue/261/pyw-files-arent-reported-properly -.. _issue 264: https://bitbucket.org/ned/coveragepy/issue/264/coverage-wont-run-pyc-files -.. _issue 267: https://bitbucket.org/ned/coveragepy/issue/267/relative-path-aliases-dont-work - +.. _issue 92: https://bitbucket.org/ned/coveragepy/issues/92/finally-clauses-arent-treated-properly-in +.. _issue 164: https://bitbucket.org/ned/coveragepy/issues/164/trace-function-changed-warning-when-using +.. _issue 175: https://bitbucket.org/ned/coveragepy/issues/175/branch-coverage-gets-confused-in-certain +.. _issue 207: https://bitbucket.org/ned/coveragepy/issues/207/run-m-cannot-find-module-or-package-in +.. _issue 242: https://bitbucket.org/ned/coveragepy/issues/242/running-a-two-level-package-doesnt-work +.. _issue 218: https://bitbucket.org/ned/coveragepy/issues/218/run-command-does-not-respect-the-omit-flag +.. _issue 250: https://bitbucket.org/ned/coveragepy/issues/250/uncaught-zerodivisionerror-when-generating +.. _issue 255: https://bitbucket.org/ned/coveragepy/issues/255/directory-level-__main__py-not-included-in +.. _issue 259: https://bitbucket.org/ned/coveragepy/issues/259/allow-use-of-system-installed-third-party +.. _issue 261: https://bitbucket.org/ned/coveragepy/issues/261/pyw-files-arent-reported-properly +.. _issue 264: https://bitbucket.org/ned/coveragepy/issues/264/coverage-wont-run-pyc-files +.. _issue 267: https://bitbucket.org/ned/coveragepy/issues/267/relative-path-aliases-dont-work + + +.. _changes_36: Version 3.6 --- 2013-01-05 -------------------------- @@ -722,8 +1220,8 @@ - Added a page to the docs about troublesome situations, closing `issue 226`_, and added some info to the TODO file, closing `issue 227`_. -.. _issue 226: https://bitbucket.org/ned/coveragepy/issue/226/make-readme-section-to-describe-when -.. _issue 227: https://bitbucket.org/ned/coveragepy/issue/227/update-todo +.. _issue 226: https://bitbucket.org/ned/coveragepy/issues/226/make-readme-section-to-describe-when +.. _issue 227: https://bitbucket.org/ned/coveragepy/issues/227/update-todo Version 3.6b3 --- 2012-12-29 @@ -731,7 +1229,7 @@ - Beta 2 broke the nose plugin. It's fixed again, closing `issue 224`_. -.. _issue 224: https://bitbucket.org/ned/coveragepy/issue/224/36b2-breaks-nosexcover +.. _issue 224: https://bitbucket.org/ned/coveragepy/issues/224/36b2-breaks-nosexcover Version 3.6b2 --- 2012-12-23 @@ -751,7 +1249,7 @@ file name, coverage.py no longer associates it with the directory name, fixing `issue 221`_. -.. _issue 221: https://bitbucket.org/ned/coveragepy/issue/221/coveragepy-incompatible-with-pyratemp +.. _issue 221: https://bitbucket.org/ned/coveragepy/issues/221/coveragepy-incompatible-with-pyratemp Version 3.6b1 --- 2012-11-28 @@ -845,28 +1343,30 @@ ``'NoneType' object has no attribute 'isabs'``. It no longer does, so kiss `issue 153`_ goodbye. -.. _issue 60: https://bitbucket.org/ned/coveragepy/issue/60/incorrect-path-to-orphaned-pyc-files -.. _issue 67: https://bitbucket.org/ned/coveragepy/issue/67/xml-report-filenames-may-be-generated -.. _issue 89: https://bitbucket.org/ned/coveragepy/issue/89/on-windows-all-packages-are-reported-in -.. _issue 97: https://bitbucket.org/ned/coveragepy/issue/97/allow-environment-variables-to-be -.. _issue 100: https://bitbucket.org/ned/coveragepy/issue/100/source-directive-doesnt-work-for-packages -.. _issue 111: https://bitbucket.org/ned/coveragepy/issue/111/when-installing-coverage-with-pip-not -.. _issue 137: https://bitbucket.org/ned/coveragepy/issue/137/provide-docs-with-source-distribution -.. _issue 139: https://bitbucket.org/ned/coveragepy/issue/139/easy-check-for-a-certain-coverage-in-tests -.. _issue 143: https://bitbucket.org/ned/coveragepy/issue/143/omit-doesnt-seem-to-work-in-coverage -.. _issue 153: https://bitbucket.org/ned/coveragepy/issue/153/non-existent-filename-triggers -.. _issue 156: https://bitbucket.org/ned/coveragepy/issue/156/a-completely-unexecuted-file-shows-14 -.. _issue 163: https://bitbucket.org/ned/coveragepy/issue/163/problem-with-include-and-omit-filename -.. _issue 171: https://bitbucket.org/ned/coveragepy/issue/171/how-to-contribute-and-run-tests -.. _issue 193: https://bitbucket.org/ned/coveragepy/issue/193/unicodedecodeerror-on-htmlpy -.. _issue 201: https://bitbucket.org/ned/coveragepy/issue/201/coverage-using-django-14-with-pydb-on -.. _issue 202: https://bitbucket.org/ned/coveragepy/issue/202/get-rid-of-ez_setuppy-and -.. _issue 203: https://bitbucket.org/ned/coveragepy/issue/203/duplicate-filenames-reported-when-filename -.. _issue 205: https://bitbucket.org/ned/coveragepy/issue/205/make-pydoc-coverage-more-friendly -.. _issue 206: https://bitbucket.org/ned/coveragepy/issue/206/pydoc-coveragecoverage-fails-with-an-error -.. _issue 210: https://bitbucket.org/ned/coveragepy/issue/210/if-theres-no-coverage-data-coverage-xml -.. _issue 214: https://bitbucket.org/ned/coveragepy/issue/214/coveragepy-measures-itself-on-precise - +.. _issue 60: https://bitbucket.org/ned/coveragepy/issues/60/incorrect-path-to-orphaned-pyc-files +.. _issue 67: https://bitbucket.org/ned/coveragepy/issues/67/xml-report-filenames-may-be-generated +.. _issue 89: https://bitbucket.org/ned/coveragepy/issues/89/on-windows-all-packages-are-reported-in +.. _issue 97: https://bitbucket.org/ned/coveragepy/issues/97/allow-environment-variables-to-be +.. _issue 100: https://bitbucket.org/ned/coveragepy/issues/100/source-directive-doesnt-work-for-packages +.. _issue 111: https://bitbucket.org/ned/coveragepy/issues/111/when-installing-coverage-with-pip-not +.. _issue 137: https://bitbucket.org/ned/coveragepy/issues/137/provide-docs-with-source-distribution +.. _issue 139: https://bitbucket.org/ned/coveragepy/issues/139/easy-check-for-a-certain-coverage-in-tests +.. _issue 143: https://bitbucket.org/ned/coveragepy/issues/143/omit-doesnt-seem-to-work-in-coverage +.. _issue 153: https://bitbucket.org/ned/coveragepy/issues/153/non-existent-filename-triggers +.. _issue 156: https://bitbucket.org/ned/coveragepy/issues/156/a-completely-unexecuted-file-shows-14 +.. _issue 163: https://bitbucket.org/ned/coveragepy/issues/163/problem-with-include-and-omit-filename +.. _issue 171: https://bitbucket.org/ned/coveragepy/issues/171/how-to-contribute-and-run-tests +.. _issue 193: https://bitbucket.org/ned/coveragepy/issues/193/unicodedecodeerror-on-htmlpy +.. _issue 201: https://bitbucket.org/ned/coveragepy/issues/201/coverage-using-django-14-with-pydb-on +.. _issue 202: https://bitbucket.org/ned/coveragepy/issues/202/get-rid-of-ez_setuppy-and +.. _issue 203: https://bitbucket.org/ned/coveragepy/issues/203/duplicate-filenames-reported-when-filename +.. _issue 205: https://bitbucket.org/ned/coveragepy/issues/205/make-pydoc-coverage-more-friendly +.. _issue 206: https://bitbucket.org/ned/coveragepy/issues/206/pydoc-coveragecoverage-fails-with-an-error +.. _issue 210: https://bitbucket.org/ned/coveragepy/issues/210/if-theres-no-coverage-data-coverage-xml +.. _issue 214: https://bitbucket.org/ned/coveragepy/issues/214/coveragepy-measures-itself-on-precise + + +.. _changes_353: Version 3.5.3 --- 2012-09-29 ---------------------------- @@ -898,14 +1398,16 @@ - Testing is now done with `tox`_, thanks, Marc Abramowitz. -.. _issue 147: https://bitbucket.org/ned/coveragepy/issue/147/massive-memory-usage-by-ctracer -.. _issue 179: https://bitbucket.org/ned/coveragepy/issue/179/htmlreporter-fails-when-source-file-is -.. _issue 183: https://bitbucket.org/ned/coveragepy/issue/183/install-fails-for-python-23 -.. _issue 194: https://bitbucket.org/ned/coveragepy/issue/194/filelocatorrelative_filename-could-mangle -.. _issue 195: https://bitbucket.org/ned/coveragepy/issue/195/pyo-file-handling-in-codeunit -.. _issue 197: https://bitbucket.org/ned/coveragepy/issue/197/line-numbers-in-html-report-do-not-align -.. _tox: http://tox.readthedocs.org/ - +.. _issue 147: https://bitbucket.org/ned/coveragepy/issues/147/massive-memory-usage-by-ctracer +.. _issue 179: https://bitbucket.org/ned/coveragepy/issues/179/htmlreporter-fails-when-source-file-is +.. _issue 183: https://bitbucket.org/ned/coveragepy/issues/183/install-fails-for-python-23 +.. _issue 194: https://bitbucket.org/ned/coveragepy/issues/194/filelocatorrelative_filename-could-mangle +.. _issue 195: https://bitbucket.org/ned/coveragepy/issues/195/pyo-file-handling-in-codeunit +.. _issue 197: https://bitbucket.org/ned/coveragepy/issues/197/line-numbers-in-html-report-do-not-align +.. _tox: https://tox.readthedocs.io/ + + +.. _changes_352: Version 3.5.2 --- 2012-05-04 ---------------------------- @@ -949,13 +1451,15 @@ - When installing into pypy, we no longer attempt (and fail) to compile the C tracer function, closing `issue 166`_. -.. _issue 142: https://bitbucket.org/ned/coveragepy/issue/142/executing-python-file-syspath-is-replaced -.. _issue 155: https://bitbucket.org/ned/coveragepy/issue/155/cant-use-coverage-run-m-unittest-discover -.. _issue 157: https://bitbucket.org/ned/coveragepy/issue/157/chokes-on-source-files-with-non-utf-8 -.. _issue 166: https://bitbucket.org/ned/coveragepy/issue/166/dont-try-to-compile-c-extension-on-pypy -.. _issue 168: https://bitbucket.org/ned/coveragepy/issue/168/dont-be-alarmed-by-emacs-droppings -.. _issue 173: https://bitbucket.org/ned/coveragepy/issue/173/theres-no-way-to-specify-show-missing-in - +.. _issue 142: https://bitbucket.org/ned/coveragepy/issues/142/executing-python-file-syspath-is-replaced +.. _issue 155: https://bitbucket.org/ned/coveragepy/issues/155/cant-use-coverage-run-m-unittest-discover +.. _issue 157: https://bitbucket.org/ned/coveragepy/issues/157/chokes-on-source-files-with-non-utf-8 +.. _issue 166: https://bitbucket.org/ned/coveragepy/issues/166/dont-try-to-compile-c-extension-on-pypy +.. _issue 168: https://bitbucket.org/ned/coveragepy/issues/168/dont-be-alarmed-by-emacs-droppings +.. _issue 173: https://bitbucket.org/ned/coveragepy/issues/173/theres-no-way-to-specify-show-missing-in + + +.. _changes_351: Version 3.5.1 --- 2011-09-23 ---------------------------- @@ -996,13 +1500,15 @@ into running some coverage.py code before anything else in the process. See the coverage/fullcoverage directory if you are interested. -.. _issue 17: http://bitbucket.org/ned/coveragepy/issue/17/support-combining-coverage-data-from -.. _issue 122: http://bitbucket.org/ned/coveragepy/issue/122/for-else-always-reports-missing-branch -.. _issue 124: http://bitbucket.org/ned/coveragepy/issue/124/no-arbitrary-unicode-in-html-reports-in -.. _issue 128: http://bitbucket.org/ned/coveragepy/issue/128/branch-coverage-of-with-statement-in-27 -.. _issue 138: http://bitbucket.org/ned/coveragepy/issue/138/include-should-take-precedence-over-is -.. _issue 144: http://bitbucket.org/ned/coveragepy/issue/144/failure-generating-html-output-for - +.. _issue 17: https://bitbucket.org/ned/coveragepy/issues/17/support-combining-coverage-data-from +.. _issue 122: https://bitbucket.org/ned/coveragepy/issues/122/for-else-always-reports-missing-branch +.. _issue 124: https://bitbucket.org/ned/coveragepy/issues/124/no-arbitrary-unicode-in-html-reports-in +.. _issue 128: https://bitbucket.org/ned/coveragepy/issues/128/branch-coverage-of-with-statement-in-27 +.. _issue 138: https://bitbucket.org/ned/coveragepy/issues/138/include-should-take-precedence-over-is +.. _issue 144: https://bitbucket.org/ned/coveragepy/issues/144/failure-generating-html-output-for + + +.. _changes_35: Version 3.5 --- 2011-06-29 -------------------------- @@ -1032,9 +1538,9 @@ - Partial branch warnings can now be pragma'd away. The configuration option ``partial_branches`` is a list of regular expressions. Lines matching any of those expressions will never be marked as a partial branch. In addition, - there's a built-in list of regular expressions marking statements which should - never be marked as partial. This list includes ``while True:``, ``while 1:``, - ``if 1:``, and ``if 0:``. + there's a built-in list of regular expressions marking statements which + should never be marked as partial. This list includes ``while True:``, + ``while 1:``, ``if 1:``, and ``if 0:``. - The ``coverage()`` constructor accepts single strings for the ``omit=`` and ``include=`` arguments, adapting to a common error in programmatic use. @@ -1081,16 +1587,18 @@ - Internally, files are now closed explicitly, fixing `issue 104`_. Thanks, Brett Cannon. -.. _issue 80: https://bitbucket.org/ned/coveragepy/issue/80/is-there-a-duck-typing-way-to-know-we-cant -.. _issue 93: http://bitbucket.org/ned/coveragepy/issue/93/copying-a-mock-object-breaks-coverage -.. _issue 95: https://bitbucket.org/ned/coveragepy/issue/95/run-subcommand-should-take-a-module-name -.. _issue 104: https://bitbucket.org/ned/coveragepy/issue/104/explicitly-close-files -.. _issue 107: https://bitbucket.org/ned/coveragepy/issue/107/codeparser-not-opening-source-files-with -.. _issue 115: https://bitbucket.org/ned/coveragepy/issue/115/fail-gracefully-when-reporting-on-file -.. _issue 121: https://bitbucket.org/ned/coveragepy/issue/121/filename-patterns-are-applied-stupidly -.. _issue 123: https://bitbucket.org/ned/coveragepy/issue/123/pyeval_settrace-used-in-way-that-breaks -.. _issue 125: https://bitbucket.org/ned/coveragepy/issue/125/coverage-removes-decoratortoolss-tracing - +.. _issue 80: https://bitbucket.org/ned/coveragepy/issues/80/is-there-a-duck-typing-way-to-know-we-cant +.. _issue 93: https://bitbucket.org/ned/coveragepy/issues/93/copying-a-mock-object-breaks-coverage +.. _issue 95: https://bitbucket.org/ned/coveragepy/issues/95/run-subcommand-should-take-a-module-name +.. _issue 104: https://bitbucket.org/ned/coveragepy/issues/104/explicitly-close-files +.. _issue 107: https://bitbucket.org/ned/coveragepy/issues/107/codeparser-not-opening-source-files-with +.. _issue 115: https://bitbucket.org/ned/coveragepy/issues/115/fail-gracefully-when-reporting-on-file +.. _issue 121: https://bitbucket.org/ned/coveragepy/issues/121/filename-patterns-are-applied-stupidly +.. _issue 123: https://bitbucket.org/ned/coveragepy/issues/123/pyeval_settrace-used-in-way-that-breaks +.. _issue 125: https://bitbucket.org/ned/coveragepy/issues/125/coverage-removes-decoratortoolss-tracing + + +.. _changes_34: Version 3.4 --- 2010-09-19 -------------------------- @@ -1100,7 +1608,7 @@ - Programs that exited with ``sys.exit()`` with no argument weren't handled properly, producing a coverage.py stack trace. That is now fixed. -.. _issue 88: http://bitbucket.org/ned/coveragepy/issue/88/xml-report-lists-packages-in-random-order +.. _issue 88: https://bitbucket.org/ned/coveragepy/issues/88/xml-report-lists-packages-in-random-order Version 3.4b2 --- 2010-09-06 @@ -1125,12 +1633,12 @@ would report no coverage for the `run` method. This is now fixed, closing `issue 85`_. -.. _issue 16: http://bitbucket.org/ned/coveragepy/issue/16/allow-configuration-of-accuracy-of-percentage-totals -.. _issue 41: http://bitbucket.org/ned/coveragepy/issue/41/report-says-100-when-it-isnt-quite-there -.. _issue 65: http://bitbucket.org/ned/coveragepy/issue/65/branch-option-not-reported-in-cobertura -.. _issue 70: http://bitbucket.org/ned/coveragepy/issue/70/text-report-and-html-report-disagree-on-coverage -.. _issue 81: http://bitbucket.org/ned/coveragepy/issue/81/xml-report-does-not-have-condition-coverage-attribute-for-lines-with-a -.. _issue 85: http://bitbucket.org/ned/coveragepy/issue/85/threadrun-isnt-measured +.. _issue 16: https://bitbucket.org/ned/coveragepy/issues/16/allow-configuration-of-accuracy-of-percentage-totals +.. _issue 41: https://bitbucket.org/ned/coveragepy/issues/41/report-says-100-when-it-isnt-quite-there +.. _issue 65: https://bitbucket.org/ned/coveragepy/issues/65/branch-option-not-reported-in-cobertura +.. _issue 70: https://bitbucket.org/ned/coveragepy/issues/70/text-report-and-html-report-disagree-on-coverage +.. _issue 81: https://bitbucket.org/ned/coveragepy/issues/81/xml-report-does-not-have-condition-coverage-attribute-for-lines-with-a +.. _issue 85: https://bitbucket.org/ned/coveragepy/issues/85/threadrun-isnt-measured Version 3.4b1 --- 2010-08-21 @@ -1206,18 +1714,20 @@ - Asking for an HTML report with no files now shows a nice error message rather than a cryptic failure ('int' object is unsubscriptable). Fixes `issue 59`_. -.. _issue 1: http://bitbucket.org/ned/coveragepy/issue/1/empty-__init__py-files-are-reported-as-1-executable -.. _issue 34: http://bitbucket.org/ned/coveragepy/issue/34/enhanced-omit-globbing-handling -.. _issue 36: http://bitbucket.org/ned/coveragepy/issue/36/provide-regex-style-omit -.. _issue 46: http://bitbucket.org/ned/coveragepy/issue/46 -.. _issue 53: http://bitbucket.org/ned/coveragepy/issue/53 -.. _issue 52: http://bitbucket.org/ned/coveragepy/issue/52/doctesttestfile-confuses-source-detection -.. _issue 56: http://bitbucket.org/ned/coveragepy/issue/56 -.. _issue 61: http://bitbucket.org/ned/coveragepy/issue/61/annotate-i-doesnt-work -.. _issue 62: http://bitbucket.org/ned/coveragepy/issue/62 -.. _issue 59: http://bitbucket.org/ned/coveragepy/issue/59/html-report-fails-with-int-object-is -.. _issue 82: http://bitbucket.org/ned/coveragepy/issue/82/tokenerror-when-generating-html-report - +.. _issue 1: https://bitbucket.org/ned/coveragepy/issues/1/empty-__init__py-files-are-reported-as-1-executable +.. _issue 34: https://bitbucket.org/ned/coveragepy/issues/34/enhanced-omit-globbing-handling +.. _issue 36: https://bitbucket.org/ned/coveragepy/issues/36/provide-regex-style-omit +.. _issue 46: https://bitbucket.org/ned/coveragepy/issues/46 +.. _issue 53: https://bitbucket.org/ned/coveragepy/issues/53 +.. _issue 52: https://bitbucket.org/ned/coveragepy/issues/52/doctesttestfile-confuses-source-detection +.. _issue 56: https://bitbucket.org/ned/coveragepy/issues/56 +.. _issue 61: https://bitbucket.org/ned/coveragepy/issues/61/annotate-i-doesnt-work +.. _issue 62: https://bitbucket.org/ned/coveragepy/issues/62 +.. _issue 59: https://bitbucket.org/ned/coveragepy/issues/59/html-report-fails-with-int-object-is +.. _issue 82: https://bitbucket.org/ned/coveragepy/issues/82/tokenerror-when-generating-html-report + + +.. _changes_331: Version 3.3.1 --- 2010-03-06 ---------------------------- @@ -1228,9 +1738,11 @@ - When running your code with "coverage run", if you call `sys.exit()`, coverage.py will exit with that status code, fixing `issue 50`_. -.. _issue 49: http://bitbucket.org/ned/coveragepy/issue/49 -.. _issue 50: http://bitbucket.org/ned/coveragepy/issue/50 - +.. _issue 49: https://bitbucket.org/ned/coveragepy/issues/49 +.. _issue 50: https://bitbucket.org/ned/coveragepy/issues/50 + + +.. _changes_33: Version 3.3 --- 2010-02-24 -------------------------- @@ -1266,10 +1778,12 @@ - Added an AUTHORS.txt file. -.. _issue 39: http://bitbucket.org/ned/coveragepy/issue/39 -.. _issue 40: http://bitbucket.org/ned/coveragepy/issue/40 -.. _issue 47: http://bitbucket.org/ned/coveragepy/issue/47 - +.. _issue 39: https://bitbucket.org/ned/coveragepy/issues/39 +.. _issue 40: https://bitbucket.org/ned/coveragepy/issues/40 +.. _issue 47: https://bitbucket.org/ned/coveragepy/issues/47 + + +.. _changes_32: Version 3.2 --- 2009-12-05 -------------------------- @@ -1290,7 +1804,7 @@ - On Python 3.x, setuptools has been replaced by `Distribute`_. -.. _Distribute: http://packages.python.org/distribute/ +.. _Distribute: https://pypi.python.org/pypi/distribute Version 3.2b3 --- 2009-11-23 @@ -1305,7 +1819,7 @@ - The table of contents in the HTML report is now sortable: click the headers on any column. Thanks, `Chris Adams`_. -.. _Chris Adams: http://improbable.org/chris/ +.. _Chris Adams: http://chris.improbable.org Version 3.2b2 --- 2009-11-19 @@ -1324,12 +1838,12 @@ - The --omit option now works much better than before, fixing `issue 14`_ and `issue 33`_. Thanks, Danek Duvall. -.. _issue 14: http://bitbucket.org/ned/coveragepy/issue/14 -.. _issue 30: http://bitbucket.org/ned/coveragepy/issue/30 -.. _issue 31: http://bitbucket.org/ned/coveragepy/issue/31 -.. _issue 32: http://bitbucket.org/ned/coveragepy/issue/32 -.. _issue 33: http://bitbucket.org/ned/coveragepy/issue/33 -.. _issue 35: http://bitbucket.org/ned/coveragepy/issue/35 +.. _issue 14: https://bitbucket.org/ned/coveragepy/issues/14 +.. _issue 30: https://bitbucket.org/ned/coveragepy/issues/30 +.. _issue 31: https://bitbucket.org/ned/coveragepy/issues/31 +.. _issue 32: https://bitbucket.org/ned/coveragepy/issues/32 +.. _issue 33: https://bitbucket.org/ned/coveragepy/issues/33 +.. _issue 35: https://bitbucket.org/ned/coveragepy/issues/35 Version 3.2b1 --- 2009-11-10 @@ -1344,8 +1858,10 @@ - Some exceptions reported by the command line interface have been cleaned up so that tracebacks inside coverage.py aren't shown. Fixes `issue 23`_. -.. _issue 23: http://bitbucket.org/ned/coveragepy/issue/23 - +.. _issue 23: https://bitbucket.org/ned/coveragepy/issues/23 + + +.. _changes_31: Version 3.1 --- 2009-10-04 -------------------------- @@ -1353,7 +1869,7 @@ - Source code can now be read from eggs. Thanks, Ross Lawley. Fixes `issue 25`_. -.. _issue 25: http://bitbucket.org/ned/coveragepy/issue/25 +.. _issue 25: https://bitbucket.org/ned/coveragepy/issues/25 Version 3.1b1 --- 2009-09-27 @@ -1383,11 +1899,13 @@ - Added a "coverage debug" command for getting diagnostic information about the coverage.py installation. -.. _issue 11: http://bitbucket.org/ned/coveragepy/issue/11 -.. _issue 12: http://bitbucket.org/ned/coveragepy/issue/12 -.. _issue 13: http://bitbucket.org/ned/coveragepy/issue/13 -.. _issue 24: http://bitbucket.org/ned/coveragepy/issue/24 - +.. _issue 11: https://bitbucket.org/ned/coveragepy/issues/11 +.. _issue 12: https://bitbucket.org/ned/coveragepy/issues/12 +.. _issue 13: https://bitbucket.org/ned/coveragepy/issues/13 +.. _issue 24: https://bitbucket.org/ned/coveragepy/issues/24 + + +.. _changes_301: Version 3.0.1 --- 2009-07-07 ---------------------------- @@ -1409,10 +1927,12 @@ mode just like Python does. This lets it run Windows files on Mac, for example. -.. _issue 9: http://bitbucket.org/ned/coveragepy/issue/9 -.. _issue 10: http://bitbucket.org/ned/coveragepy/issue/10 -.. _issue 8: http://bitbucket.org/ned/coveragepy/issue/8 - +.. _issue 9: https://bitbucket.org/ned/coveragepy/issues/9 +.. _issue 10: https://bitbucket.org/ned/coveragepy/issues/10 +.. _issue 8: https://bitbucket.org/ned/coveragepy/issues/8 + + +.. _changes_30: Version 3.0 --- 2009-06-13 -------------------------- @@ -1425,7 +1945,7 @@ - Nested modules now get a proper flat_rootname. Thanks, Christian Heimes. -.. _issue 6: http://bitbucket.org/ned/coveragepy/issue/6 +.. _issue 6: https://bitbucket.org/ned/coveragepy/issues/6 Version 3.0b3 --- 2009-05-16 @@ -1523,8 +2043,8 @@ --------------------------- - Don't try to predict whether a file is Python source based on the extension. - Extension-less files are often Pythons scripts. Instead, simply parse the file - and catch the syntax errors. Hat tip to Ben Finney. + Extension-less files are often Pythons scripts. Instead, simply parse the + file and catch the syntax errors. Hat tip to Ben Finney. Version 2.77 --- 2007-07-29
--- a/DebugClients/Python/coverage/doc/README.rst Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/doc/README.rst Tue May 01 12:03:52 2018 +0200 @@ -9,20 +9,39 @@ | |license| |versions| |status| |docs| | |ci-status| |win-ci-status| |codecov| -| |kit| |format| |downloads| +| |kit| |format| |saythanks| + +.. downloads badge seems to be broken... |downloads| Coverage.py measures code coverage, typically during test execution. It uses the code analysis tools and tracing hooks provided in the Python standard library to determine which lines are executable, and which have been executed. -Coverage.py runs on CPython 2.6, 2.7, and 3.3 through 3.6; PyPy 4.0 and 5.1; -and PyPy3 2.4. +Coverage.py runs on many versions of Python: + +* CPython 2.6, 2.7 and 3.3 through 3.7. +* PyPy2 5.10 and PyPy3 5.10. +* Jython 2.7.1, though not for reporting. +* IronPython 2.7.7, though not for reporting. + +Documentation is on `Read the Docs`_. Code repository and issue tracker are on +`Bitbucket`_, with a mirrored repository on `GitHub`_. -Documentation is on `Read the Docs <http://coverage.readthedocs.io>`_. -Code repository and issue tracker are on `Bitbucket <http://bitbucket.org/ned/coveragepy>`_, -with a mirrored repository on `GitHub <https://github.com/nedbat/coveragepy>`_. +.. _Read the Docs: https://coverage.readthedocs.io/ +.. _Bitbucket: https://bitbucket.org/ned/coveragepy +.. _GitHub: https://github.com/nedbat/coveragepy + + +**New in 4.5:** Configurator plug-ins. -**New in 4.1:** much-improved branch coverage. +New in 4.4: Suppressable warnings, continuous coverage measurement. + +New in 4.3: HTML ``--skip-covered``, sys.excepthook support, tox.ini +support. + +New in 4.2: better support for multiprocessing and combining data. + +New in 4.1: much-improved branch coverage. New in 4.0: ``--concurrency``, plugins for non-Python files, setup.cfg support, --skip-covered, HTML filtering, and more than 50 issues closed. @@ -31,25 +50,36 @@ Getting Started --------------- -See the `quick start <http://coverage.readthedocs.io/#quick-start>`_ -section of the docs. +See the `Quick Start section`_ of the docs. + +.. _Quick Start section: https://coverage.readthedocs.io/#quick-start + + +Contributing +------------ + +See the `Contributing section`_ of the docs. + +.. _Contributing section: https://coverage.readthedocs.io/en/latest/contributing.html License ------- -Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0. -For details, see https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt. +Licensed under the `Apache 2.0 License`_. For details, see `NOTICE.txt`_. + +.. _Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0 +.. _NOTICE.txt: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt .. |ci-status| image:: https://travis-ci.org/nedbat/coveragepy.svg?branch=master :target: https://travis-ci.org/nedbat/coveragepy :alt: Build status -.. |win-ci-status| image:: https://ci.appveyor.com/api/projects/status/bitbucket/ned/coveragepy?svg=true +.. |win-ci-status| image:: https://ci.appveyor.com/api/projects/status/kmeqpdje7h9r6vsf/branch/master?svg=true :target: https://ci.appveyor.com/project/nedbat/coveragepy :alt: Windows build status .. |docs| image:: https://readthedocs.org/projects/coverage/badge/?version=latest&style=flat - :target: http://coverage.readthedocs.io + :target: https://coverage.readthedocs.io/ :alt: Documentation .. |reqs| image:: https://requires.io/github/nedbat/coveragepy/requirements.svg?branch=master :target: https://requires.io/github/nedbat/coveragepy/requirements/?branch=master @@ -72,6 +102,9 @@ .. |license| image:: https://img.shields.io/pypi/l/coverage.svg :target: https://pypi.python.org/pypi/coverage :alt: License -.. |codecov| image:: http://codecov.io/github/nedbat/coveragepy/coverage.svg?branch=master +.. |codecov| image:: http://codecov.io/github/nedbat/coveragepy/coverage.svg?branch=master&precision=2 :target: http://codecov.io/github/nedbat/coveragepy?branch=master :alt: Coverage! +.. |saythanks| image:: https://img.shields.io/badge/saythanks.io-%E2%98%BC-1EAEDB.svg + :target: https://saythanks.io/to/nedbat + :alt: Say thanks :)
--- a/DebugClients/Python/coverage/env.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/env.py Tue May 01 12:03:52 2018 +0200 @@ -4,6 +4,7 @@ """Determine facts about the environment.""" import os +import platform import sys # Operating systems. @@ -11,7 +12,12 @@ LINUX = sys.platform == "linux2" # Python implementations. -PYPY = '__pypy__' in sys.builtin_module_names +PYPY = (platform.python_implementation() == 'PyPy') +if PYPY: + PYPYVERSION = sys.pypy_version_info + +JYTHON = (platform.python_implementation() == 'Jython') +IRONPYTHON = (platform.python_implementation() == 'IronPython') # Python versions. PYVERSION = sys.version_info
--- a/DebugClients/Python/coverage/execfile.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/execfile.py Tue May 01 12:03:52 2018 +0200 @@ -5,12 +5,13 @@ import marshal import os +import struct import sys import types from coverage.backward import BUILTINS from coverage.backward import PYC_MAGIC_NUMBER, imp, importlib_util_find_spec -from coverage.misc import ExceptionDuringRun, NoCode, NoSource, isolate_module +from coverage.misc import CoverageException, ExceptionDuringRun, NoCode, NoSource, isolate_module from coverage.phystokens import compile_unicode from coverage.python import get_python_source @@ -166,11 +167,17 @@ sys.path[0] = path0 if path0 is not None else my_path0 try: - # Make a code object somehow. - if filename.endswith((".pyc", ".pyo")): - code = make_code_from_pyc(filename) - else: - code = make_code_from_py(filename) + try: + # Make a code object somehow. + if filename.endswith((".pyc", ".pyo")): + code = make_code_from_pyc(filename) + else: + code = make_code_from_py(filename) + except CoverageException: + raise + except Exception as exc: + msg = "Couldn't run {filename!r} as Python code: {exc.__class__.__name__}: {exc}" + raise CoverageException(msg.format(filename=filename, exc=exc)) # Execute the code object. try: @@ -179,7 +186,7 @@ # The user called sys.exit(). Just pass it along to the upper # layers, where it will be handled. raise - except: + except Exception: # Something went wrong while executing the user code. # Get the exc_info, and pack them into an exception that we can # throw up to the outer loop. We peel one layer off the traceback @@ -193,7 +200,27 @@ # it somehow? https://bitbucket.org/pypy/pypy/issue/1903 getattr(err, '__context__', None) - raise ExceptionDuringRun(typ, err, tb.tb_next) + # Call the excepthook. + try: + if hasattr(err, "__traceback__"): + err.__traceback__ = err.__traceback__.tb_next + sys.excepthook(typ, err, tb.tb_next) + except SystemExit: + raise + except Exception: + # Getting the output right in the case of excepthook + # shenanigans is kind of involved. + sys.stderr.write("Error in sys.excepthook:\n") + typ2, err2, tb2 = sys.exc_info() + err2.__suppress_context__ = True + if hasattr(err2, "__traceback__"): + err2.__traceback__ = err2.__traceback__.tb_next + sys.__excepthook__(typ2, err2, tb2.tb_next) + sys.stderr.write("\nOriginal exception was:\n") + raise ExceptionDuringRun(typ, err, tb.tb_next) + else: + sys.exit(1) + finally: # Restore the old __main__, argv, and path. sys.modules['__main__'] = old_main_mod @@ -227,11 +254,19 @@ if magic != PYC_MAGIC_NUMBER: raise NoCode("Bad magic number in .pyc file") - # Skip the junk in the header that we don't need. - fpyc.read(4) # Skip the moddate. - if sys.version_info >= (3, 3): - # 3.3 added another long to the header (size), skip it. - fpyc.read(4) + date_based = True + if sys.version_info >= (3, 7, 0, 'alpha', 4): + flags = struct.unpack('<L', fpyc.read(4))[0] + hash_based = flags & 0x01 + if hash_based: + fpyc.read(8) # Skip the hash. + date_based = False + if date_based: + # Skip the junk in the header that we don't need. + fpyc.read(4) # Skip the moddate. + if sys.version_info >= (3, 3): + # 3.3 added another long to the header (size), skip it. + fpyc.read(4) # The rest of the file is the code object we want. code = marshal.load(fpyc)
--- a/DebugClients/Python/coverage/files.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/files.py Tue May 01 12:03:52 2018 +0200 @@ -3,6 +3,7 @@ """File wrangling.""" +import hashlib import fnmatch import ntpath import os @@ -63,7 +64,11 @@ if path is None: continue f = os.path.join(path, filename) - if os.path.exists(f): + try: + exists = os.path.exists(f) + except UnicodeError: + exists = False + if exists: filename = f break cf = abs_file(filename) @@ -71,6 +76,9 @@ return CANONICAL_FILENAME_CACHE[filename] +MAX_FLAT = 200 + +@contract(filename='unicode', returns='unicode') def flat_rootname(filename): """A base for a flat file name to correspond to this file. @@ -82,7 +90,11 @@ """ name = ntpath.splitdrive(filename)[1] - return re.sub(r"[\\/.:]", "_", name) + name = re.sub(r"[\\/.:]", "_", name) + if len(name) > MAX_FLAT: + h = hashlib.sha1(name.encode('UTF-8')).hexdigest() + name = name[-(MAX_FLAT-len(h)-1):] + '_' + h + return name if env.WINDOWS: @@ -147,7 +159,11 @@ def abs_file(filename): """Return the absolute normalized form of `filename`.""" path = os.path.expandvars(os.path.expanduser(filename)) - path = os.path.abspath(os.path.realpath(path)) + try: + path = os.path.realpath(path) + except UnicodeError: + pass + path = os.path.abspath(path) path = actual_path(path) path = unicode_filename(path) return path @@ -183,25 +199,31 @@ class TreeMatcher(object): - """A matcher for files in a tree.""" - def __init__(self, directories): - self.dirs = list(directories) + """A matcher for files in a tree. + + Construct with a list of paths, either files or directories. Paths match + with the `match` method if they are one of the files, or if they are + somewhere in a subtree rooted at one of the directories. + + """ + def __init__(self, paths): + self.paths = list(paths) def __repr__(self): - return "<TreeMatcher %r>" % self.dirs + return "<TreeMatcher %r>" % self.paths def info(self): """A list of strings for displaying when dumping state.""" - return self.dirs + return self.paths def match(self, fpath): """Does `fpath` indicate a file in one of our trees?""" - for d in self.dirs: - if fpath.startswith(d): - if fpath == d: + for p in self.paths: + if fpath.startswith(p): + if fpath == p: # This is the same file! return True - if fpath[len(d)] == os.sep: + if fpath[len(p)] == os.sep: # This is a file in the directory return True return False @@ -243,13 +265,14 @@ # of treating / and \ as equivalent. But on other platforms, we need to # take care of that ourselves. fnpats = (fnmatch.translate(p) for p in pats) - fnpats = (p.replace(r"\/", r"[\\/]") for p in fnpats) + # Python3.7 fnmatch translates "/" as "/", before that, it translates as "\/", + # so we have to deal with maybe a backslash. + fnpats = (re.sub(r"\\?/", r"[\\\\/]", p) for p in fnpats) + flags = 0 if env.WINDOWS: - # Windows is also case-insensitive. BTW: the regex docs say that - # flags like (?i) have to be at the beginning, but fnmatch puts - # them at the end, and having two there seems to work fine. - fnpats = (p + "(?i)" for p in fnpats) - self.re = re.compile(join_regex(fnpats)) + # Windows is also case-insensitive, so make the regex case-insensitive. + flags |= re.IGNORECASE + self.re = re.compile(join_regex(fnpats), flags=flags) def __repr__(self): return "<FnmatchMatcher %r>" % self.pats @@ -287,6 +310,11 @@ def __init__(self): self.aliases = [] + def pprint(self): # pragma: debugging + """Dump the important parts of the PathAliases, for debugging.""" + for regex, result in self.aliases: + print("{0!r} --> {1!r}".format(regex.pattern, result)) + def add(self, pattern, result): """Add the `pattern`/`result` pair to the list of aliases. @@ -300,8 +328,10 @@ match an entire tree, and not just its root. """ + if len(pattern) > 1: + pattern = pattern.rstrip(r"\/") + # The pattern can't end with a wildcard component. - pattern = pattern.rstrip(r"\/") if pattern.endswith("*"): raise CoverageException("Pattern must not end with wildcards.") pattern_sep = sep(pattern) @@ -310,11 +340,15 @@ # unless it already is, or is meant to match any prefix. if not pattern.startswith('*') and not isabs_anywhere(pattern): pattern = abs_file(pattern) - pattern += pattern_sep + if not pattern.endswith(pattern_sep): + pattern += pattern_sep # Make a regex from the pattern. fnmatch always adds a \Z to - # match the whole string, which we don't want. - regex_pat = fnmatch.translate(pattern).replace(r'\Z(', '(') + # match the whole string, which we don't want, so we remove the \Z. + # While removing it, we only replace \Z if followed by paren, or at + # end, to keep from destroying a literal \Z in the pattern. + regex_pat = fnmatch.translate(pattern) + regex_pat = re.sub(r'\\Z(\(|$)', r'\1', regex_pat) # We want */a/b.py to match on Windows too, so change slash to match # either separator. @@ -325,7 +359,7 @@ # Normalize the result: it must end with a path separator. result_sep = sep(result) result = result.rstrip(r"\/") + result_sep - self.aliases.append((regex, result, pattern_sep, result_sep)) + self.aliases.append((regex, result)) def map(self, path): """Map `path` through the aliases. @@ -343,12 +377,11 @@ of `path` unchanged. """ - for regex, result, pattern_sep, result_sep in self.aliases: + for regex, result in self.aliases: m = regex.match(path) if m: new = path.replace(m.group(0), result) - if pattern_sep != result_sep: - new = new.replace(pattern_sep, result_sep) + new = new.replace(sep(path), sep(result)) new = canonical_filename(new) return new return path
--- a/DebugClients/Python/coverage/html.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/html.py Tue May 01 12:03:52 2018 +0200 @@ -12,7 +12,7 @@ from coverage import env from coverage.backward import iitems from coverage.files import flat_rootname -from coverage.misc import CoverageException, Hasher, isolate_module +from coverage.misc import CoverageException, file_be_gone, Hasher, isolate_module from coverage.report import Reporter from coverage.results import Numbers from coverage.templite import Templite @@ -78,7 +78,7 @@ STATIC_FILES = [ ("style.css", ""), ("jquery.min.js", "jquery"), - ("jquery.debounce.min.js", "jquery-debounce"), + ("jquery.ba-throttle-debounce.min.js", "jquery-throttle-debounce"), ("jquery.hotkeys.js", "jquery-hotkeys"), ("jquery.isonscreen.js", "jquery-isonscreen"), ("jquery.tablesorter.min.js", "jquery-tablesorter"), @@ -105,6 +105,7 @@ self.coverage = cov self.files = [] + self.all_files_nums = [] self.has_arcs = self.coverage.data.has_arcs() self.status = HtmlStatus() self.extra_css = None @@ -137,7 +138,7 @@ # Process all the files. self.report_files(self.html_file, morfs, self.config.html_dir) - if not self.files: + if not self.all_files_nums: raise CoverageException("No data to report.") # Write the index file. @@ -171,10 +172,26 @@ def html_file(self, fr, analysis): """Generate an HTML file for one source file.""" + rootname = flat_rootname(fr.relative_filename()) + html_filename = rootname + ".html" + html_path = os.path.join(self.directory, html_filename) + + # Get the numbers for this file. + nums = analysis.numbers + self.all_files_nums.append(nums) + + if self.config.skip_covered: + # Don't report on 100% files. + no_missing_lines = (nums.n_missing == 0) + no_missing_branches = (nums.n_partial_branches == 0) + if no_missing_lines and no_missing_branches: + # If there's an existing file, remove it. + file_be_gone(html_path) + return + source = fr.source() # Find out if the file on disk is already correct. - rootname = flat_rootname(fr.relative_filename()) this_hash = self.file_hash(source.encode('utf-8'), fr) that_hash = self.status.file_hash(rootname) if this_hash == that_hash: @@ -184,9 +201,6 @@ self.status.set_file_hash(rootname, this_hash) - # Get the numbers for this file. - nums = analysis.numbers - if self.has_arcs: missing_branch_arcs = analysis.missing_branch_arcs() arcs_executed = analysis.arcs_executed() @@ -269,8 +283,6 @@ 'time_stamp': self.time_stamp, }) - html_filename = rootname + ".html" - html_path = os.path.join(self.directory, html_filename) write_html(html_path, html) # Save this file's information for the index file. @@ -286,7 +298,7 @@ """Write the index.html file for this report.""" index_tmpl = Templite(read_data("index.html"), self.template_globals) - self.totals = sum(f['nums'] for f in self.files) + self.totals = sum(self.all_files_nums) html = index_tmpl.render({ 'has_arcs': self.has_arcs, @@ -384,10 +396,10 @@ 'files': files, } with open(status_file, "w") as fout: - json.dump(status, fout) + json.dump(status, fout, separators=(',', ':')) # Older versions of ShiningPanda look for the old name, status.dat. - # Accomodate them if we are running under Jenkins. + # Accommodate them if we are running under Jenkins. # https://issues.jenkins-ci.org/browse/JENKINS-28428 if "JENKINS_URL" in os.environ: with open(os.path.join(directory, "status.dat"), "w") as dat:
--- a/DebugClients/Python/coverage/misc.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/misc.py Tue May 01 12:03:52 2018 +0200 @@ -12,7 +12,7 @@ import types from coverage import env -from coverage.backward import string_class, to_bytes, unicode_class +from coverage.backward import to_bytes, unicode_class ISOLATED_MODULES = {} @@ -38,6 +38,13 @@ os = isolate_module(os) +def dummy_decorator_with_args(*args_unused, **kwargs_unused): + """Dummy no-op implementation of a decorator with arguments.""" + def _decorator(func): + return func + return _decorator + + # Use PyContracts for assertion testing on parameters and returns, but only if # we are running our own test suite. if env.TESTING: @@ -57,12 +64,22 @@ new_contract('bytes', lambda v: isinstance(v, bytes)) if env.PY3: new_contract('unicode', lambda v: isinstance(v, unicode_class)) -else: # pragma: not covered - # We aren't using real PyContracts, so just define a no-op decorator as a - # stunt double. - def contract(**unused): - """Dummy no-op implementation of `contract`.""" - return lambda func: func + + def one_of(argnames): + """Ensure that only one of the argnames is non-None.""" + def _decorator(func): + argnameset = set(name.strip() for name in argnames.split(",")) + def _wrapped(*args, **kwargs): + vals = [kwargs.get(name) for name in argnameset] + assert sum(val is not None for val in vals) == 1 + return func(*args, **kwargs) + return _wrapped + return _decorator +else: # pragma: not testing + # We aren't using real PyContracts, so just define our decorators as + # stunt-double no-ops. + contract = dummy_decorator_with_args + one_of = dummy_decorator_with_args def new_contract(*args_unused, **kwargs_unused): """Dummy no-op implementation of `new_contract`.""" @@ -93,23 +110,28 @@ For example, if `statements` is [1,2,3,4,5,10,11,12,13,14] and `lines` is [1,2,5,10,11,13,14] then the result will be "1-2, 5-11, 13-14". + Both `lines` and `statements` can be any iterable. All of the elements of + `lines` must be in `statements`, and all of the values must be positive + integers. + """ - pairs = [] - i = 0 - j = 0 - start = None statements = sorted(statements) lines = sorted(lines) - while i < len(statements) and j < len(lines): - if statements[i] == lines[j]: - if start is None: - start = lines[j] - end = lines[j] - j += 1 + + pairs = [] + start = None + lidx = 0 + for stmt in statements: + if lidx >= len(lines): + break + if stmt == lines[lidx]: + lidx += 1 + if not start: + start = stmt + end = stmt elif start: pairs.append((start, end)) start = None - i += 1 if start: pairs.append((start, end)) ret = ', '.join(map(nice_pair, pairs)) @@ -129,12 +151,12 @@ def _wrapped(self): """Inner function that checks the cache.""" if hasattr(self, attr): - raise Exception("Shouldn't have called %s more than once" % fn.__name__) + raise AssertionError("Shouldn't have called %s more than once" % fn.__name__) setattr(self, attr, True) return fn(self) return _wrapped else: - return fn + return fn # pragma: not testing def bool_or_none(b): @@ -179,8 +201,8 @@ def update(self, v): """Add `v` to the hash, recursively if needed.""" self.md5.update(to_bytes(str(type(v)))) - if isinstance(v, string_class): - self.md5.update(to_bytes(v)) + if isinstance(v, unicode_class): + self.md5.update(v.encode('utf8')) elif isinstance(v, bytes): self.md5.update(v) elif v is None: @@ -227,8 +249,23 @@ ) -class CoverageException(Exception): - """An exception specific to coverage.py.""" +class SimpleRepr(object): + """A mixin implementing a simple __repr__.""" + def __repr__(self): + return "<{klass} @{id:x} {attrs}>".format( + klass=self.__class__.__name__, + id=id(self) & 0xFFFFFF, + attrs=" ".join("{}={!r}".format(k, v) for k, v in self.__dict__.items()), + ) + + +class BaseCoverageException(Exception): + """The base of all Coverage exceptions.""" + pass + + +class CoverageException(BaseCoverageException): + """A run-of-the-mill exception specific to coverage.py.""" pass @@ -254,3 +291,13 @@ """ pass + + +class StopEverything(BaseCoverageException): + """An exception that means everything should stop. + + The CoverageTest class converts these to SkipTest, so that when running + tests, raising this exception will automatically skip the test. + + """ + pass
--- a/DebugClients/Python/coverage/monkey.py Mon Apr 02 12:04:56 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 -# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt - -"""Monkey-patching to make coverage.py work right in some cases.""" - -import multiprocessing -import multiprocessing.process -import sys - -# An attribute that will be set on modules to indicate that they have been -# monkey-patched. -PATCHED_MARKER = "_coverage$patched" - -if sys.version_info >= (3, 4): - klass = multiprocessing.process.BaseProcess -else: - klass = multiprocessing.Process - -original_bootstrap = klass._bootstrap - - -class ProcessWithCoverage(klass): - """A replacement for multiprocess.Process that starts coverage.""" - def _bootstrap(self): - """Wrapper around _bootstrap to start coverage.""" - from coverage import Coverage - cov = Coverage(data_suffix=True) - cov.start() - try: - return original_bootstrap(self) - finally: - cov.stop() - cov.save() - - -class Stowaway(object): - """An object to pickle, so when it is unpickled, it can apply the monkey-patch.""" - def __getstate__(self): - return {} - - def __setstate__(self, state_unused): - patch_multiprocessing() - - -def patch_multiprocessing(): - """Monkey-patch the multiprocessing module. - - This enables coverage measurement of processes started by multiprocessing. - This is wildly experimental! - - """ - if hasattr(multiprocessing, PATCHED_MARKER): - return - - if sys.version_info >= (3, 4): - klass._bootstrap = ProcessWithCoverage._bootstrap - else: - multiprocessing.Process = ProcessWithCoverage - - # When spawning processes rather than forking them, we have no state in the - # new process. We sneak in there with a Stowaway: we stuff one of our own - # objects into the data that gets pickled and sent to the sub-process. When - # the Stowaway is unpickled, it's __setstate__ method is called, which - # re-applies the monkey-patch. - # Windows only spawns, so this is needed to keep Windows working. - try: - from multiprocessing import spawn # pylint: disable=no-name-in-module - original_get_preparation_data = spawn.get_preparation_data - except (ImportError, AttributeError): - pass - else: - def get_preparation_data_with_stowaway(name): - """Get the original preparation data, and also insert our stowaway.""" - d = original_get_preparation_data(name) - d['stowaway'] = Stowaway() - return d - - spawn.get_preparation_data = get_preparation_data_with_stowaway - - setattr(multiprocessing, PATCHED_MARKER, True)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DebugClients/Python/coverage/multiproc.py Tue May 01 12:03:52 2018 +0200 @@ -0,0 +1,105 @@ +# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 +# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt + +"""Monkey-patching to add multiprocessing support for coverage.py""" + +import multiprocessing +import multiprocessing.process +import os +import sys + +from coverage.misc import contract + +# An attribute that will be set on the module to indicate that it has been +# monkey-patched. +PATCHED_MARKER = "_coverage$patched" + +# The environment variable that specifies the rcfile for subprocesses. +COVERAGE_RCFILE_ENV = "_COVERAGE_RCFILE" + + +if sys.version_info >= (3, 4): + OriginalProcess = multiprocessing.process.BaseProcess +else: + OriginalProcess = multiprocessing.Process + +original_bootstrap = OriginalProcess._bootstrap + +class ProcessWithCoverage(OriginalProcess): + """A replacement for multiprocess.Process that starts coverage.""" + + def _bootstrap(self): + """Wrapper around _bootstrap to start coverage.""" + from coverage import Coverage # avoid circular import + rcfile = os.environ[COVERAGE_RCFILE_ENV] + cov = Coverage(data_suffix=True, config_file=rcfile) + cov.start() + debug = cov.debug + try: + if debug.should("multiproc"): + debug.write("Calling multiprocessing bootstrap") + return original_bootstrap(self) + finally: + if debug.should("multiproc"): + debug.write("Finished multiprocessing bootstrap") + cov.stop() + cov.save() + if debug.should("multiproc"): + debug.write("Saved multiprocessing data") + +class Stowaway(object): + """An object to pickle, so when it is unpickled, it can apply the monkey-patch.""" + def __init__(self, rcfile): + self.rcfile = rcfile + + def __getstate__(self): + return {'rcfile': self.rcfile} + + def __setstate__(self, state): + patch_multiprocessing(state['rcfile']) + + +@contract(rcfile=str) +def patch_multiprocessing(rcfile): + """Monkey-patch the multiprocessing module. + + This enables coverage measurement of processes started by multiprocessing. + This involves aggressive monkey-patching. + + `rcfile` is the path to the rcfile being used. + + """ + + if hasattr(multiprocessing, PATCHED_MARKER): + return + + if sys.version_info >= (3, 4): + OriginalProcess._bootstrap = ProcessWithCoverage._bootstrap + else: + multiprocessing.Process = ProcessWithCoverage + + # Set the value in ProcessWithCoverage that will be pickled into the child + # process. + os.environ[COVERAGE_RCFILE_ENV] = rcfile + + # When spawning processes rather than forking them, we have no state in the + # new process. We sneak in there with a Stowaway: we stuff one of our own + # objects into the data that gets pickled and sent to the sub-process. When + # the Stowaway is unpickled, it's __setstate__ method is called, which + # re-applies the monkey-patch. + # Windows only spawns, so this is needed to keep Windows working. + try: + from multiprocessing import spawn + original_get_preparation_data = spawn.get_preparation_data + except (ImportError, AttributeError): + pass + else: + def get_preparation_data_with_stowaway(name): + """Get the original preparation data, and also insert our stowaway.""" + d = original_get_preparation_data(name) + d['stowaway'] = Stowaway(rcfile) + return d + + spawn.get_preparation_data = get_preparation_data_with_stowaway + + setattr(multiprocessing, PATCHED_MARKER, True)
--- a/DebugClients/Python/coverage/parser.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/parser.py Tue May 01 12:03:52 2018 +0200 @@ -15,8 +15,8 @@ from coverage.backward import bytes_to_ints, string_class from coverage.bytecode import CodeObjects from coverage.debug import short_stack -from coverage.misc import contract, new_contract, nice_pair, join_regex -from coverage.misc import CoverageException, NoSource, NotPython +from coverage.misc import contract, join_regex, new_contract, nice_pair, one_of +from coverage.misc import NoSource, NotPython, StopEverything from coverage.phystokens import compile_unicode, generate_tokens, neuter_encoding_declaration @@ -137,7 +137,7 @@ tokgen = generate_tokens(self.text) for toktype, ttext, (slineno, _), (elineno, _), ltext in tokgen: - if self.show_tokens: # pragma: not covered + if self.show_tokens: # pragma: debugging print("%10s %5s %-20r %r" % ( tokenize.tok_name.get(toktype, toktype), nice_pair((slineno, elineno)), ttext, ltext @@ -370,11 +370,11 @@ # Alternative Python implementations don't always provide all the # attributes on code objects that we need to do the analysis. - for attr in ['co_lnotab', 'co_firstlineno', 'co_consts']: + for attr in ['co_lnotab', 'co_firstlineno']: if not hasattr(self.code, attr): - raise CoverageException( + raise StopEverything( # pragma: only jython "This implementation of Python doesn't support code analysis.\n" - "Run coverage.py under CPython for this command." + "Run coverage.py under another Python for this command." ) def child_parsers(self): @@ -432,23 +432,35 @@ class LoopBlock(object): """A block on the block stack representing a `for` or `while` loop.""" + @contract(start=int) def __init__(self, start): + # The line number where the loop starts. self.start = start + # A set of ArcStarts, the arcs from break statements exiting this loop. self.break_exits = set() class FunctionBlock(object): """A block on the block stack representing a function definition.""" + @contract(start=int, name=str) def __init__(self, start, name): + # The line number where the function starts. self.start = start + # The name of the function. self.name = name class TryBlock(object): """A block on the block stack representing a `try` block.""" - def __init__(self, handler_start=None, final_start=None): + @contract(handler_start='int|None', final_start='int|None') + def __init__(self, handler_start, final_start): + # The line number of the first "except" handler, if any. self.handler_start = handler_start + # The line number of the "finally:" clause, if any. self.final_start = final_start + + # The ArcStarts for breaks/continues/returns/raises inside the "try:" + # that need to route through the "finally:" clause. self.break_from = set() self.continue_from = set() self.return_from = set() @@ -458,8 +470,13 @@ class ArcStart(collections.namedtuple("Arc", "lineno, cause")): """The information needed to start an arc. - `lineno` is the line number the arc starts from. `cause` is a fragment - used as the startmsg for AstArcAnalyzer.missing_arc_fragments. + `lineno` is the line number the arc starts from. + + `cause` is an English text fragment used as the `startmsg` for + AstArcAnalyzer.missing_arc_fragments. It will be used to describe why an + arc wasn't executed, so should fit well into a sentence of the form, + "Line 17 didn't run because {cause}." The fragment can include "{lineno}" + to have `lineno` interpolated into it. """ def __new__(cls, lineno, cause=None): @@ -471,6 +488,21 @@ new_contract('ArcStarts', lambda seq: all(isinstance(x, ArcStart) for x in seq)) +# Turn on AST dumps with an environment variable. +AST_DUMP = bool(int(os.environ.get("COVERAGE_AST_DUMP", 0))) + +class NodeList(object): + """A synthetic fictitious node, containing a sequence of nodes. + + This is used when collapsing optimized if-statements, to represent the + unconditional execution of one of the clauses. + + """ + def __init__(self, body): + self.body = body + self.lineno = body[0].lineno + + class AstArcAnalyzer(object): """Analyze source text with an AST to find executable code paths.""" @@ -481,15 +513,17 @@ self.statements = set(multiline.get(l, l) for l in statements) self.multiline = multiline - if int(os.environ.get("COVERAGE_ASTDUMP", 0)): # pragma: debugging + if AST_DUMP: # pragma: debugging # Dump the AST so that failing tests have helpful output. - print("Statements: {}".format(self.statements)) - print("Multiline map: {}".format(self.multiline)) + print("Statements: {0}".format(self.statements)) + print("Multiline map: {0}".format(self.multiline)) ast_dump(self.root_node) self.arcs = set() - # A map from arc pairs to a pair of sentence fragments: (startmsg, endmsg). + # A map from arc pairs to a list of pairs of sentence fragments: + # { (start, end): [(startmsg, endmsg), ...], } + # # For an arc from line 17, they should be usable like: # "Line 17 {endmsg}, because {startmsg}" self.missing_arc_fragments = collections.defaultdict(list) @@ -512,7 +546,7 @@ def add_arc(self, start, end, smsg=None, emsg=None): """Add an arc, including message fragments to use if it is missing.""" - if self.debug: + if self.debug: # pragma: debugging print("\nAdding arc: ({}, {}): {!r}, {!r}".format(start, end, smsg, emsg)) print(short_stack(limit=6)) self.arcs.add((start, end)) @@ -563,9 +597,10 @@ if node.body: return self.line_for_node(node.body[0]) else: - # Modules have no line number, they always start at 1. + # Empty modules have no line number, they always start at 1. return 1 + # The node types that just flow to the next node with no complications. OK_TO_DEFAULT = set([ "Assign", "Assert", "AugAssign", "Delete", "Exec", "Expr", "Global", "Import", "ImportFrom", "Nonlocal", "Pass", "Print", @@ -575,20 +610,35 @@ def add_arcs(self, node): """Add the arcs for `node`. - Return a set of ArcStarts, exits from this node to the next. + Return a set of ArcStarts, exits from this node to the next. Because a + node represents an entire sub-tree (including its children), the exits + from a node can be arbitrarily complex:: + + if something(1): + if other(2): + doit(3) + else: + doit(5) + + There are two exits from line 1: they start at line 3 and line 5. """ node_name = node.__class__.__name__ handler = getattr(self, "_handle__" + node_name, None) if handler is not None: return handler(node) + else: + # No handler: either it's something that's ok to default (a simple + # statement), or it's something we overlooked. Change this 0 to 1 + # to see if it's overlooked. + if 0: + if node_name not in self.OK_TO_DEFAULT: + print("*** Unhandled: {0}".format(node)) - if 0: - node_name = node.__class__.__name__ - if node_name not in self.OK_TO_DEFAULT: - print("*** Unhandled: {0}".format(node)) - return set([ArcStart(self.line_for_node(node), cause=None)]) + # Default for simple statements: one exit from this node. + return set([ArcStart(self.line_for_node(node))]) + @one_of("from_start, prev_starts") @contract(returns='ArcStarts') def add_body_arcs(self, body, from_start=None, prev_starts=None): """Add arcs for the body of a compound statement. @@ -607,28 +657,91 @@ lineno = self.line_for_node(body_node) first_line = self.multiline.get(lineno, lineno) if first_line not in self.statements: - continue + body_node = self.find_non_missing_node(body_node) + if body_node is None: + continue + lineno = self.line_for_node(body_node) for prev_start in prev_starts: self.add_arc(prev_start.lineno, lineno, prev_start.cause) prev_starts = self.add_arcs(body_node) return prev_starts + def find_non_missing_node(self, node): + """Search `node` looking for a child that has not been optimized away. + + This might return the node you started with, or it will work recursively + to find a child node in self.statements. + + Returns a node, or None if none of the node remains. + + """ + # This repeats work just done in add_body_arcs, but this duplication + # means we can avoid a function call in the 99.9999% case of not + # optimizing away statements. + lineno = self.line_for_node(node) + first_line = self.multiline.get(lineno, lineno) + if first_line in self.statements: + return node + + missing_fn = getattr(self, "_missing__" + node.__class__.__name__, None) + if missing_fn: + node = missing_fn(node) + else: + node = None + return node + + def _missing__If(self, node): + # If the if-node is missing, then one of its children might still be + # here, but not both. So return the first of the two that isn't missing. + # Use a NodeList to hold the clauses as a single node. + non_missing = self.find_non_missing_node(NodeList(node.body)) + if non_missing: + return non_missing + if node.orelse: + return self.find_non_missing_node(NodeList(node.orelse)) + return None + + def _missing__NodeList(self, node): + # A NodeList might be a mixture of missing and present nodes. Find the + # ones that are present. + non_missing_children = [] + for child in node.body: + child = self.find_non_missing_node(child) + if child is not None: + non_missing_children.append(child) + + # Return the simplest representation of the present children. + if not non_missing_children: + return None + if len(non_missing_children) == 1: + return non_missing_children[0] + return NodeList(non_missing_children) + def is_constant_expr(self, node): """Is this a compile-time constant?""" node_name = node.__class__.__name__ if node_name in ["NameConstant", "Num"]: - return True + return "Num" elif node_name == "Name": - if env.PY3 and node.id in ["True", "False", "None"]: - return True - return False + if node.id in ["True", "False", "None", "__debug__"]: + return "Name" + return None - # tests to write: - # TODO: while EXPR: - # TODO: while False: - # TODO: listcomps hidden deep in other expressions - # TODO: listcomps hidden in lists: x = [[i for i in range(10)]] - # TODO: nested function definitions + # In the fullness of time, these might be good tests to write: + # while EXPR: + # while False: + # listcomps hidden deep in other expressions + # listcomps hidden in lists: x = [[i for i in range(10)]] + # nested function definitions + + + # Exit processing: process_*_exits + # + # These functions process the four kinds of jump exits: break, continue, + # raise, and return. To figure out where an exit goes, we have to look at + # the block stack context. For example, a break will jump to the nearest + # enclosing loop block, or the nearest enclosing finally block, whichever + # is nearer. @contract(exits='ArcStarts') def process_break_exits(self, exits): @@ -688,7 +801,14 @@ ) break - ## Handlers + + # Handlers: _handle__* + # + # Each handler deals with a specific AST node type, dispatched from + # add_arcs. Each deals with a particular kind of node type, and returns + # the set of exits from that node. These functions mirror the Python + # semantics of each syntactic construct. See the docstring for add_arcs to + # understand the concept of exits from a node. @contract(returns='ArcStarts') def _handle__Break(self, node): @@ -711,14 +831,15 @@ # in `self.statements`. For some constructs, `line_for_node` is # not what we'd think of as the first line in the statement, so map # it to the first one. - body_start = self.line_for_node(node.body[0]) - body_start = self.multiline.get(body_start, body_start) - for lineno in range(last+1, body_start): - if lineno in self.statements: - self.add_arc(last, lineno) - last = lineno + if node.body: + body_start = self.line_for_node(node.body[0]) + body_start = self.multiline.get(body_start, body_start) + for lineno in range(last+1, body_start): + if lineno in self.statements: + self.add_arc(last, lineno) + last = lineno # The body is handled in collect_arcs. - return set([ArcStart(last, cause=None)]) + return set([ArcStart(last)]) _handle__ClassDef = _handle_decorated @@ -745,7 +866,7 @@ else_exits = self.add_body_arcs(node.orelse, from_start=from_start) exits |= else_exits else: - # no else clause: exit from the for line. + # No else clause: exit from the for line. exits.add(from_start) return exits @@ -764,6 +885,12 @@ return exits @contract(returns='ArcStarts') + def _handle__NodeList(self, node): + start = self.line_for_node(node) + exits = self.add_body_arcs(node.body, from_start=ArcStart(start)) + return exits + + @contract(returns='ArcStarts') def _handle__Raise(self, node): here = self.line_for_node(node) raise_start = ArcStart(here, cause="the raise on line {lineno} wasn't executed") @@ -791,11 +918,11 @@ else: final_start = None - try_block = TryBlock(handler_start=handler_start, final_start=final_start) + try_block = TryBlock(handler_start, final_start) self.block_stack.append(try_block) start = self.line_for_node(node) - exits = self.add_body_arcs(node.body, from_start=ArcStart(start, cause=None)) + exits = self.add_body_arcs(node.body, from_start=ArcStart(start)) # We're done with the `try` body, so this block no longer handles # exceptions. We keep the block so the `finally` clause can pick up @@ -838,30 +965,46 @@ try_block.return_from # or a `return`. ) - exits = self.add_body_arcs(node.finalbody, prev_starts=final_from) + final_exits = self.add_body_arcs(node.finalbody, prev_starts=final_from) + if try_block.break_from: - break_exits = self._combine_finally_starts(try_block.break_from, exits) - self.process_break_exits(break_exits) + self.process_break_exits( + self._combine_finally_starts(try_block.break_from, final_exits) + ) if try_block.continue_from: - continue_exits = self._combine_finally_starts(try_block.continue_from, exits) - self.process_continue_exits(continue_exits) + self.process_continue_exits( + self._combine_finally_starts(try_block.continue_from, final_exits) + ) if try_block.raise_from: - raise_exits = self._combine_finally_starts(try_block.raise_from, exits) - self.process_raise_exits(raise_exits) + self.process_raise_exits( + self._combine_finally_starts(try_block.raise_from, final_exits) + ) if try_block.return_from: - return_exits = self._combine_finally_starts(try_block.return_from, exits) - self.process_return_exits(return_exits) + self.process_return_exits( + self._combine_finally_starts(try_block.return_from, final_exits) + ) + + if exits: + # The finally clause's exits are only exits for the try block + # as a whole if the try block had some exits to begin with. + exits = final_exits return exits + @contract(starts='ArcStarts', exits='ArcStarts', returns='ArcStarts') def _combine_finally_starts(self, starts, exits): - """Helper for building the cause of `finally` branches.""" + """Helper for building the cause of `finally` branches. + + "finally" clauses might not execute their exits, and the causes could + be due to a failure to execute any of the exits in the try block. So + we use the causes from `starts` as the causes for `exits`. + """ causes = [] - for lineno, cause in sorted(starts): - if cause is not None: - causes.append(cause.format(lineno=lineno)) + for start in sorted(starts): + if start.cause is not None: + causes.append(start.cause.format(lineno=start.lineno)) cause = " or ".join(causes) - exits = set(ArcStart(ex.lineno, cause) for ex in exits) + exits = set(ArcStart(xit.lineno, cause) for xit in exits) return exits @contract(returns='ArcStarts') @@ -893,9 +1036,9 @@ def _handle__While(self, node): constant_test = self.is_constant_expr(node.test) start = to_top = self.line_for_node(node.test) - if constant_test: + if constant_test and (env.PY3 or constant_test == "Num"): to_top = self.line_for_node(node.body[0]) - self.block_stack.append(LoopBlock(start=start)) + self.block_stack.append(LoopBlock(start=to_top)) from_start = ArcStart(start, cause="the condition on line {lineno} was never true") exits = self.add_body_arcs(node.body, from_start=from_start) for xit in exits: @@ -970,62 +1113,64 @@ _code_object__ListComp = _make_oneline_code_method("list comprehension") -SKIP_DUMP_FIELDS = ["ctx"] +if AST_DUMP: # pragma: debugging + # Code only used when dumping the AST for debugging. + + SKIP_DUMP_FIELDS = ["ctx"] -def _is_simple_value(value): - """Is `value` simple enough to be displayed on a single line?""" - return ( - value in [None, [], (), {}, set()] or - isinstance(value, (string_class, int, float)) - ) + def _is_simple_value(value): + """Is `value` simple enough to be displayed on a single line?""" + return ( + value in [None, [], (), {}, set()] or + isinstance(value, (string_class, int, float)) + ) -# TODO: a test of ast_dump? -def ast_dump(node, depth=0): - """Dump the AST for `node`. + def ast_dump(node, depth=0): + """Dump the AST for `node`. - This recursively walks the AST, printing a readable version. + This recursively walks the AST, printing a readable version. - """ - indent = " " * depth - if not isinstance(node, ast.AST): - print("{0}<{1} {2!r}>".format(indent, node.__class__.__name__, node)) - return + """ + indent = " " * depth + if not isinstance(node, ast.AST): + print("{0}<{1} {2!r}>".format(indent, node.__class__.__name__, node)) + return - lineno = getattr(node, "lineno", None) - if lineno is not None: - linemark = " @ {0}".format(node.lineno) - else: - linemark = "" - head = "{0}<{1}{2}".format(indent, node.__class__.__name__, linemark) + lineno = getattr(node, "lineno", None) + if lineno is not None: + linemark = " @ {0}".format(node.lineno) + else: + linemark = "" + head = "{0}<{1}{2}".format(indent, node.__class__.__name__, linemark) - named_fields = [ - (name, value) - for name, value in ast.iter_fields(node) - if name not in SKIP_DUMP_FIELDS - ] - if not named_fields: - print("{0}>".format(head)) - elif len(named_fields) == 1 and _is_simple_value(named_fields[0][1]): - field_name, value = named_fields[0] - print("{0} {1}: {2!r}>".format(head, field_name, value)) - else: - print(head) - if 0: - print("{0}# mro: {1}".format( - indent, ", ".join(c.__name__ for c in node.__class__.__mro__[1:]), - )) - next_indent = indent + " " - for field_name, value in named_fields: - prefix = "{0}{1}:".format(next_indent, field_name) - if _is_simple_value(value): - print("{0} {1!r}".format(prefix, value)) - elif isinstance(value, list): - print("{0} [".format(prefix)) - for n in value: - ast_dump(n, depth + 8) - print("{0}]".format(next_indent)) - else: - print(prefix) - ast_dump(value, depth + 8) + named_fields = [ + (name, value) + for name, value in ast.iter_fields(node) + if name not in SKIP_DUMP_FIELDS + ] + if not named_fields: + print("{0}>".format(head)) + elif len(named_fields) == 1 and _is_simple_value(named_fields[0][1]): + field_name, value = named_fields[0] + print("{0} {1}: {2!r}>".format(head, field_name, value)) + else: + print(head) + if 0: + print("{0}# mro: {1}".format( + indent, ", ".join(c.__name__ for c in node.__class__.__mro__[1:]), + )) + next_indent = indent + " " + for field_name, value in named_fields: + prefix = "{0}{1}:".format(next_indent, field_name) + if _is_simple_value(value): + print("{0} {1!r}".format(prefix, value)) + elif isinstance(value, list): + print("{0} [".format(prefix)) + for n in value: + ast_dump(n, depth + 8) + print("{0}]".format(next_indent)) + else: + print(prefix) + ast_dump(value, depth + 8) - print("{0}>".format(indent)) + print("{0}>".format(indent))
--- a/DebugClients/Python/coverage/phystokens.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/phystokens.py Tue May 01 12:03:52 2018 +0200 @@ -11,7 +11,7 @@ import tokenize from coverage import env -from coverage.backward import iternext +from coverage.backward import iternext, unicode_class from coverage.misc import contract @@ -281,7 +281,7 @@ """ source = neuter_encoding_declaration(source) - if env.PY2 and isinstance(filename, unicode): + if env.PY2 and isinstance(filename, unicode_class): filename = filename.encode(sys.getfilesystemencoding(), "replace") code = compile(source, filename, mode) return code @@ -290,5 +290,9 @@ @contract(source='unicode', returns='unicode') def neuter_encoding_declaration(source): """Return `source`, with any encoding declaration neutered.""" - source = COOKIE_RE.sub("# (deleted declaration)", source, count=2) + if COOKIE_RE.search(source): + source_lines = source.splitlines(True) + for lineno in range(min(2, len(source_lines))): + source_lines[lineno] = COOKIE_RE.sub("# (deleted declaration)", source_lines[lineno]) + source = "".join(source_lines) return source
--- a/DebugClients/Python/coverage/plugin.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/plugin.py Tue May 01 12:03:52 2018 +0200 @@ -1,70 +1,118 @@ # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt -"""Plugin interfaces for coverage.py""" +""" +.. versionadded:: 4.0 + +Plug-in interfaces for coverage.py. + +Coverage.py supports a few different kinds of plug-ins that change its +behavior: + +* File tracers implement tracing of non-Python file types. + +* Configurers add custom configuration, using Python code to change the + configuration. + +To write a coverage.py plug-in, create a module with a subclass of +:class:`~coverage.CoveragePlugin`. You will override methods in your class to +participate in various aspects of coverage.py's processing. +Different types of plug-ins have to override different methods. + +Any plug-in can optionally implement :meth:`~coverage.CoveragePlugin.sys_info` +to provide debugging information about their operation. + +Your module must also contain a ``coverage_init`` function that registers an +instance of your plug-in class:: + + import coverage + + class MyPlugin(coverage.CoveragePlugin): + ... + + def coverage_init(reg, options): + reg.add_file_tracer(MyPlugin()) + +You use the `reg` parameter passed to your ``coverage_init`` function to +register your plug-in object. The registration method you call depends on +what kind of plug-in it is. + +If your plug-in takes options, the `options` parameter is a dictionary of your +plug-in's options from the coverage.py configuration file. Use them however +you want to configure your object before registering it. + +Coverage.py will store its own information on your plug-in object, using +attributes whose names start with ``_coverage_``. Don't be startled. + +.. warning:: + Plug-ins are imported by coverage.py before it begins measuring code. + If you write a plugin in your own project, it might import your product + code before coverage.py can start measuring. This can result in your + own code being reported as missing. + + One solution is to put your plugins in your project tree, but not in + your importable Python package. + + +File Tracers +============ + +File tracers implement measurement support for non-Python files. File tracers +implement the :meth:`~coverage.CoveragePlugin.file_tracer` method to claim +files and the :meth:`~coverage.CoveragePlugin.file_reporter` method to report +on those files. + +In your ``coverage_init`` function, use the ``add_file_tracer`` method to +register your file tracer. + + +Configurers +=========== + +.. versionadded:: 4.5 + +Configurers modify the configuration of coverage.py during start-up. +Configurers implement the :meth:`~coverage.CoveragePlugin.configure` method to +change the configuration. + +In your ``coverage_init`` function, use the ``add_configurer`` method to +register your configurer. + +""" from coverage import files from coverage.misc import contract, _needs_to_implement class CoveragePlugin(object): - """Base class for coverage.py plugins. - - To write a coverage.py plugin, create a module with a subclass of - :class:`CoveragePlugin`. You will override methods in your class to - participate in various aspects of coverage.py's processing. - - Currently the only plugin type is a file tracer, for implementing - measurement support for non-Python files. File tracer plugins implement - the :meth:`file_tracer` method to claim files and the :meth:`file_reporter` - method to report on those files. - - Any plugin can optionally implement :meth:`sys_info` to provide debugging - information about their operation. - - Coverage.py will store its own information on your plugin object, using - attributes whose names start with ``_coverage_``. Don't be startled. - - To register your plugin, define a function called `coverage_init` in your - module:: - - def coverage_init(reg, options): - reg.add_file_tracer(MyPlugin()) - - You use the `reg` parameter passed to your `coverage_init` function to - register your plugin object. It has one method, `add_file_tracer`, which - takes a newly created instance of your plugin. - - If your plugin takes options, the `options` parameter is a dictionary of - your plugin's options from the coverage.py configuration file. Use them - however you want to configure your object before registering it. - - """ + """Base class for coverage.py plug-ins.""" def file_tracer(self, filename): # pylint: disable=unused-argument """Get a :class:`FileTracer` object for a file. - Every Python source file is offered to the plugin to give it a chance - to take responsibility for tracing the file. If your plugin can handle - the file, then return a :class:`FileTracer` object. Otherwise return - None. + Plug-in type: file tracer. - There is no way to register your plugin for particular files. Instead, - this method is invoked for all files, and the plugin decides whether it - can trace the file or not. Be prepared for `filename` to refer to all - kinds of files that have nothing to do with your plugin. + Every Python source file is offered to your plug-in to give it a chance + to take responsibility for tracing the file. If your plug-in can + handle the file, then return a :class:`FileTracer` object. Otherwise + return None. + + There is no way to register your plug-in for particular files. + Instead, this method is invoked for all files, and the plug-in decides + whether it can trace the file or not. Be prepared for `filename` to + refer to all kinds of files that have nothing to do with your plug-in. The file name will be a Python file being executed. There are two - broad categories of behavior for a plugin, depending on the kind of - files your plugin supports: + broad categories of behavior for a plug-in, depending on the kind of + files your plug-in supports: * Static file names: each of your original source files has been - converted into a distinct Python file. Your plugin is invoked with + converted into a distinct Python file. Your plug-in is invoked with the Python file name, and it maps it back to its original source file. * Dynamic file names: all of your source files are executed by the same - Python file. In this case, your plugin implements + Python file. In this case, your plug-in implements :meth:`FileTracer.dynamic_source_filename` to provide the actual source file for each execution frame. @@ -73,7 +121,7 @@ paths, be sure to take this into account. Returns a :class:`FileTracer` object to use to trace `filename`, or - None if this plugin cannot trace this file. + None if this plug-in cannot trace this file. """ return None @@ -81,6 +129,8 @@ def file_reporter(self, filename): # pylint: disable=unused-argument """Get the :class:`FileReporter` class to use for a file. + Plug-in type: file tracer. + This will only be invoked if `filename` returns non-None from :meth:`file_tracer`. It's an error to return None from this method. @@ -89,11 +139,42 @@ """ _needs_to_implement(self, "file_reporter") + def find_executable_files(self, src_dir): # pylint: disable=unused-argument + """Yield all of the executable files in `src_dir`, recursively. + + Plug-in type: file tracer. + + Executability is a plug-in-specific property, but generally means files + which would have been considered for coverage analysis, had they been + included automatically. + + Returns or yields a sequence of strings, the paths to files that could + have been executed, including files that had been executed. + + """ + return [] + + def configure(self, config): + """Modify the configuration of coverage.py. + + Plug-in type: configurer. + + This method is called during coverage.py start-up, to give your plug-in + a chance to change the configuration. The `config` parameter is an + object with :meth:`~coverage.Coverage.get_option` and + :meth:`~coverage.Coverage.set_option` methods. Do not call any other + methods on the `config` object. + + """ + pass + def sys_info(self): """Get a list of information useful for debugging. + Plug-in type: any. + This method will be invoked for ``--debug=sys``. Your - plugin can return any information it wants to be displayed. + plug-in can return any information it wants to be displayed. Returns a list of pairs: `[(name, value), ...]`. @@ -104,6 +185,9 @@ class FileTracer(object): """Support needed for files during the execution phase. + File tracer plug-ins implement subclasses of FileTracer to return from + their :meth:`~CoveragePlugin.file_tracer` method. + You may construct this object from :meth:`CoveragePlugin.file_tracer` any way you like. A natural choice would be to pass the file name given to `file_tracer`. @@ -118,7 +202,7 @@ def source_filename(self): """The source file name for this file. - This may be any file name you like. A key responsibility of a plugin + This may be any file name you like. A key responsibility of a plug-in is to own the mapping from Python execution back to whatever source file name was originally the source of the code. @@ -151,7 +235,7 @@ def dynamic_source_filename(self, filename, frame): # pylint: disable=unused-argument """Get a dynamically computed source file name. - Some plugins need to compute the source file name dynamically for each + Some plug-ins need to compute the source file name dynamically for each frame. This function will not be invoked if @@ -184,14 +268,14 @@ class FileReporter(object): """Support needed for files during the analysis and reporting phases. - See :ref:`howitworks` for details of the different coverage.py phases. - - `FileReporter` objects should only be created in the - :meth:`CoveragePlugin.file_reporter` method. + File tracer plug-ins implement a subclass of `FileReporter`, and return + instances from their :meth:`CoveragePlugin.file_reporter` method. There are many methods here, but only :meth:`lines` is required, to provide the set of executable lines in the file. + See :ref:`howitworks` for details of the different coverage.py phases. + """ def __init__(self, filename): @@ -235,7 +319,7 @@ def lines(self): """Get the executable lines in this file. - Your plugin must determine which lines in the file were possibly + Your plug-in must determine which lines in the file were possibly executable. This method returns a set of those line numbers. Returns a set of line numbers. @@ -246,7 +330,7 @@ def excluded_lines(self): """Get the excluded executable lines in this file. - Your plugin can use any method it likes to allow the user to exclude + Your plug-in can use any method it likes to allow the user to exclude executable lines from consideration. Returns a set of line numbers. @@ -264,8 +348,8 @@ multi-line statement, but reports are nicer if they mention the first line. - Your plugin can optionally define this method to perform these kinds of - adjustment. + Your plug-in can optionally define this method to perform these kinds + of adjustment. `lines` is a sequence of integers, the recorded line numbers. @@ -279,7 +363,7 @@ def arcs(self): """Get the executable arcs in this file. - To support branch coverage, your plugin needs to be able to indicate + To support branch coverage, your plug-in needs to be able to indicate possible execution paths, as a set of line number pairs. Each pair is a `(prev, next)` pair indicating that execution can transition from the `prev` line number to the `next` line number. @@ -293,7 +377,7 @@ def no_branch_lines(self): """Get the lines excused from branch coverage in this file. - Your plugin can use any method it likes to allow the user to exclude + Your plug-in can use any method it likes to allow the user to exclude lines from consideration of branch coverage. Returns a set of line numbers. @@ -324,7 +408,7 @@ executable line number to a count of how many exits it has. To be honest, this feels wrong, and should be refactored. Let me know - if you attempt to implement this method in your plugin... + if you attempt to implement this method in your plug-in... """ return {} @@ -394,3 +478,5 @@ def __ge__(self, other): return self.filename >= other.filename + + __hash__ = None # This object doesn't need to be hashed.
--- a/DebugClients/Python/coverage/plugin_support.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/plugin_support.py Tue May 01 12:03:52 2018 +0200 @@ -20,6 +20,7 @@ self.order = [] self.names = {} self.file_tracers = [] + self.configurers = [] self.current_module = None self.debug = None @@ -28,7 +29,7 @@ def load_plugins(cls, modules, config, debug=None): """Load plugins from `modules`. - Returns a list of loaded and configured plugins. + Returns a Plugins object with the loaded and configured plugins. """ plugins = cls() @@ -60,6 +61,15 @@ """ self._add_plugin(plugin, self.file_tracers) + def add_configurer(self, plugin): + """Add a configuring plugin. + + `plugin` is an instance of a third-party plugin class. It must + implement the :meth:`CoveragePlugin.configure` method. + + """ + self._add_plugin(plugin, self.configurers) + def add_noop(self, plugin): """Add a plugin that does nothing.
--- a/DebugClients/Python/coverage/python.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/python.py Tue May 01 12:03:52 2018 +0200 @@ -8,9 +8,8 @@ import zipimport from coverage import env, files -from coverage.misc import ( - contract, CoverageException, expensive, NoSource, join_regex, isolate_module, -) +from coverage.misc import contract, expensive, isolate_module, join_regex +from coverage.misc import CoverageException, NoSource from coverage.parser import PythonParser from coverage.phystokens import source_token_lines, source_encoding from coverage.plugin import FileReporter @@ -26,7 +25,13 @@ """ with open(filename, "rb") as f: - return f.read().replace(b"\r\n", b"\n").replace(b"\r", b"\n") + source = f.read() + + if env.IRONPYTHON: + # IronPython reads Unicode strings even for "rb" files. + source = bytes(source) + + return source.replace(b"\r\n", b"\n").replace(b"\r", b"\n") @contract(returns='unicode') @@ -51,7 +56,9 @@ break else: # Couldn't find source. - raise NoSource("No source for code: '%s'." % filename) + exc_msg = "No source for code: '%s'.\n" % (filename,) + exc_msg += "Aborting report output, consider using -i." + raise NoSource(exc_msg) # Replace \f because of http://bugs.python.org/issue19035 source = source.replace(b'\f', b' ') @@ -73,7 +80,7 @@ an empty string if the file is empty. """ - markers = ['.zip'+os.sep, '.egg'+os.sep] + markers = ['.zip'+os.sep, '.egg'+os.sep, '.pex'+os.sep] for marker in markers: if marker in filename: parts = filename.split(marker) @@ -89,6 +96,39 @@ return None +def source_for_file(filename): + """Return the source file for `filename`. + + Given a file name being traced, return the best guess as to the source + file to attribute it to. + + """ + if filename.endswith(".py"): + # .py files are themselves source files. + return filename + + elif filename.endswith((".pyc", ".pyo")): + # Bytecode files probably have source files near them. + py_filename = filename[:-1] + if os.path.exists(py_filename): + # Found a .py file, use that. + return py_filename + if env.WINDOWS: + # On Windows, it could be a .pyw file. + pyw_filename = py_filename + "w" + if os.path.exists(pyw_filename): + return pyw_filename + # Didn't find source, but it's probably the .py file we want. + return py_filename + + elif filename.endswith("$py.class"): + # Jython is easy to guess. + return filename[:-9] + ".py" + + # No idea, just use the file name as-is. + return filename + + class PythonFileReporter(FileReporter): """Report support for a Python file.""" @@ -104,19 +144,15 @@ else: filename = morf - filename = files.unicode_filename(filename) - - # .pyc files should always refer to a .py instead. - if filename.endswith(('.pyc', '.pyo')): - filename = filename[:-1] - elif filename.endswith('$py.class'): # Jython - filename = filename[:-9] + ".py" + filename = source_for_file(files.unicode_filename(filename)) super(PythonFileReporter, self).__init__(files.canonical_filename(filename)) if hasattr(morf, '__name__'): - name = morf.__name__ - name = name.replace(".", os.sep) + ".py" + name = morf.__name__.replace(".", os.sep) + if os.path.basename(filename).startswith('__init__.'): + name += os.sep + "__init__" + name += ".py" name = files.unicode_filename(name) else: name = files.relative_filename(filename) @@ -127,6 +163,9 @@ self._statements = None self._excluded = None + def __repr__(self): + return "<PythonFileReporter {0!r}>".format(self.filename) + @contract(returns='unicode') def relative_filename(self): return self.relname
--- a/DebugClients/Python/coverage/pytracer.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/pytracer.py Tue May 01 12:03:52 2018 +0200 @@ -3,6 +3,7 @@ """Raw data collector for coverage.py.""" +import atexit import dis import sys @@ -43,27 +44,51 @@ # The threading module to use, if any. self.threading = None - self.cur_file_dict = [] - self.last_line = [0] + self.cur_file_dict = None + self.last_line = 0 # int, but uninitialized. + self.cur_file_name = None self.data_stack = [] self.last_exc_back = None self.last_exc_firstlineno = 0 self.thread = None self.stopped = False + self._activity = False + + self.in_atexit = False + # On exit, self.in_atexit = True + atexit.register(setattr, self, 'in_atexit', True) def __repr__(self): - return "<PyTracer at 0x{0:0x}: {1} lines in {2} files>".format( + return "<PyTracer at {0}: {1} lines in {2} files>".format( id(self), sum(len(v) for v in self.data.values()), len(self.data), ) + def log(self, marker, *args): + """For hard-core logging of what this tracer is doing.""" + with open("/tmp/debug_trace.txt", "a") as f: + f.write("{} {:x}.{:x}[{}] {:x} {}\n".format( + marker, + id(self), + self.thread.ident, + len(self.data_stack), + self.threading.currentThread().ident, + " ".join(map(str, args)) + )) + def _trace(self, frame, event, arg_unused): """The trace function passed to sys.settrace.""" - if self.stopped: - return + #self.log(":", frame.f_code.co_filename, frame.f_lineno, event) + + if (self.stopped and sys.gettrace() == self._trace): + # The PyTrace.stop() method has been called, possibly by another + # thread, let's deactivate ourselves now. + #self.log("X", frame.f_code.co_filename, frame.f_lineno) + sys.settrace(None) + return None if self.last_exc_back: if frame == self.last_exc_back: @@ -71,14 +96,16 @@ if self.trace_arcs and self.cur_file_dict: pair = (self.last_line, -self.last_exc_firstlineno) self.cur_file_dict[pair] = None - self.cur_file_dict, self.last_line = self.data_stack.pop() + self.cur_file_dict, self.cur_file_name, self.last_line = self.data_stack.pop() self.last_exc_back = None if event == 'call': # Entering a new function context. Decide if we should trace # in this file. - self.data_stack.append((self.cur_file_dict, self.last_line)) + self._activity = True + self.data_stack.append((self.cur_file_dict, self.cur_file_name, self.last_line)) filename = frame.f_code.co_filename + self.cur_file_name = filename disp = self.should_trace_cache.get(filename) if disp is None: disp = self.should_trace(filename, frame) @@ -94,7 +121,7 @@ # function calls and re-entering generators. The f_lasti field is # -1 for calls, and a real offset for generators. Use <0 as the # line number for calls, and the real line number for generators. - if frame.f_lasti < 0: + if getattr(frame, 'f_lasti', -1) < 0: self.last_line = -frame.f_code.co_firstlineno else: self.last_line = frame.f_lineno @@ -102,6 +129,8 @@ # Record an executed line. if self.cur_file_dict is not None: lineno = frame.f_lineno + #if frame.f_code.co_filename != self.cur_file_name: + # self.log("*", frame.f_code.co_filename, self.cur_file_name, lineno) if self.trace_arcs: self.cur_file_dict[(self.last_line, lineno)] = None else: @@ -111,12 +140,13 @@ if self.trace_arcs and self.cur_file_dict: # Record an arc leaving the function, but beware that a # "return" event might just mean yielding from a generator. - bytecode = frame.f_code.co_code[frame.f_lasti] - if bytecode != YIELD_VALUE: + # Jython seems to have an empty co_code, so just assume return. + code = frame.f_code.co_code + if (not code) or code[frame.f_lasti] != YIELD_VALUE: first = frame.f_code.co_firstlineno self.cur_file_dict[(self.last_line, -first)] = None # Leaving this function, pop the filename stack. - self.cur_file_dict, self.last_line = self.data_stack.pop() + self.cur_file_dict, self.cur_file_name, self.last_line = self.data_stack.pop() elif event == 'exception': self.last_exc_back = frame.f_back self.last_exc_firstlineno = frame.f_code.co_firstlineno @@ -128,27 +158,57 @@ Return a Python function suitable for use with sys.settrace(). """ + self.stopped = False if self.threading: - self.thread = self.threading.currentThread() + if self.thread is None: + self.thread = self.threading.currentThread() + else: + if self.thread.ident != self.threading.currentThread().ident: + # Re-starting from a different thread!? Don't set the trace + # function, but we are marked as running again, so maybe it + # will be ok? + #self.log("~", "starting on different threads") + return self._trace + sys.settrace(self._trace) - self.stopped = False return self._trace def stop(self): """Stop this Tracer.""" + # Get the activate tracer callback before setting the stop flag to be + # able to detect if the tracer was changed prior to stopping it. + tf = sys.gettrace() + + # Set the stop flag. The actual call to sys.settrace(None) will happen + # in the self._trace callback itself to make sure to call it from the + # right thread. self.stopped = True + if self.threading and self.thread.ident != self.threading.currentThread().ident: # Called on a different thread than started us: we can't unhook # ourselves, but we've set the flag that we should stop, so we # won't do any more tracing. + #self.log("~", "stopping on different threads") return if self.warn: - if sys.gettrace() != self._trace: - msg = "Trace function changed, measurement is likely wrong: %r" - self.warn(msg % (sys.gettrace(),)) + # PyPy clears the trace function before running atexit functions, + # so don't warn if we are in atexit on PyPy and the trace function + # has changed to None. + dont_warn = (env.PYPY and env.PYPYVERSION >= (5, 4) and self.in_atexit and tf is None) + if (not dont_warn) and tf != self._trace: + self.warn( + "Trace function changed, measurement is likely wrong: %r" % (tf,), + slug="trace-changed", + ) - sys.settrace(None) + def activity(self): + """Has there been any activity?""" + return self._activity + + def reset_activity(self): + """Reset the activity() flag.""" + self._activity = False def get_stats(self): """Return a dictionary of statistics, or None."""
--- a/DebugClients/Python/coverage/report.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/report.py Tue May 01 12:03:52 2018 +0200 @@ -54,12 +54,12 @@ """ reporters = self.coverage._get_file_reporters(morfs) - if self.config.include: - matcher = FnmatchMatcher(prep_patterns(self.config.include)) + if self.config.report_include: + matcher = FnmatchMatcher(prep_patterns(self.config.report_include)) reporters = [fr for fr in reporters if matcher.match(fr.filename)] - if self.config.omit: - matcher = FnmatchMatcher(prep_patterns(self.config.omit)) + if self.config.report_omit: + matcher = FnmatchMatcher(prep_patterns(self.config.report_omit)) reporters = [fr for fr in reporters if not matcher.match(fr.filename)] self._file_reporters = sorted(reporters) @@ -97,5 +97,8 @@ # explicitly suppress those errors. # NotPython is only raised by PythonFileReporter, which has a # should_be_python() method. - if fr.should_be_python() and not self.config.ignore_errors: - raise + if fr.should_be_python(): + if self.config.ignore_errors: + self.coverage._warn("Could not parse Python file {0}".format(fr.filename)) + else: + raise
--- a/DebugClients/Python/coverage/results.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/results.py Tue May 01 12:03:52 2018 +0200 @@ -6,7 +6,7 @@ import collections from coverage.backward import iitems -from coverage.misc import format_lines +from coverage.misc import contract, format_lines, SimpleRepr class Analysis(object): @@ -157,7 +157,7 @@ return stats -class Numbers(object): +class Numbers(SimpleRepr): """The numerical results of measuring coverage. This holds the basic statistics from `Analysis`, and is used to roll @@ -269,3 +269,21 @@ if other == 0: return self return NotImplemented + + +@contract(total='number', fail_under='number', precision=int, returns=bool) +def should_fail_under(total, fail_under, precision): + """Determine if a total should fail due to fail-under. + + `total` is a float, the coverage measurement total. `fail_under` is the + fail_under setting to compare with. `precision` is the number of digits + to consider after the decimal point. + + Returns True if the total should fail. + + """ + # Special case for fail_under=100, it must really be 100. + if fail_under == 100.0 and total != 100.0: + return True + + return round(total, precision) < fail_under
--- a/DebugClients/Python/coverage/summary.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/summary.py Tue May 01 12:03:52 2018 +0200 @@ -8,7 +8,7 @@ from coverage import env from coverage.report import Reporter from coverage.results import Numbers -from coverage.misc import NotPython, CoverageException, output_encoding +from coverage.misc import NotPython, CoverageException, output_encoding, StopEverything class SummaryReporter(Reporter): @@ -25,12 +25,53 @@ for native strings (bytes on Python 2, Unicode on Python 3). """ - file_reporters = self.find_file_reporters(morfs) + if outfile is None: + outfile = sys.stdout + + def writeout(line): + """Write a line to the output, adding a newline.""" + if env.PY2: + line = line.encode(output_encoding()) + outfile.write(line.rstrip()) + outfile.write("\n") + + fr_analysis = [] + skipped_count = 0 + total = Numbers() + + fmt_err = u"%s %s: %s" + + for fr in self.find_file_reporters(morfs): + try: + analysis = self.coverage._analyze(fr) + nums = analysis.numbers + total += nums - # Prepare the formatting strings - max_name = max([len(fr.relative_filename()) for fr in file_reporters] + [5]) + if self.config.skip_covered: + # Don't report on 100% files. + no_missing_lines = (nums.n_missing == 0) + no_missing_branches = (nums.n_partial_branches == 0) + if no_missing_lines and no_missing_branches: + skipped_count += 1 + continue + fr_analysis.append((fr, analysis)) + except StopEverything: + # Don't report this on single files, it's a systemic problem. + raise + except Exception: + report_it = not self.config.ignore_errors + if report_it: + typ, msg = sys.exc_info()[:2] + # NotPython is only raised by PythonFileReporter, which has a + # should_be_python() method. + if issubclass(typ, NotPython) and not fr.should_be_python(): + report_it = False + if report_it: + writeout(fmt_err % (fr.relative_filename(), typ.__name__, msg)) + + # Prepare the formatting strings, header, and column sorting. + max_name = max([len(fr.relative_filename()) for (fr, analysis) in fr_analysis] + [5]) fmt_name = u"%%- %ds " % max_name - fmt_err = u"%s %s: %s" fmt_skip_covered = u"\n%s file%s skipped due to complete coverage." header = (fmt_name % "Name") + u" Stmts Miss" @@ -46,36 +87,22 @@ fmt_coverage += u" %s" rule = u"-" * len(header) - if outfile is None: - outfile = sys.stdout - - def writeout(line): - """Write a line to the output, adding a newline.""" - if env.PY2: - line = line.encode(output_encoding()) - outfile.write(line.rstrip()) - outfile.write("\n") + column_order = dict(name=0, stmts=1, miss=2, cover=-1) + if self.branches: + column_order.update(dict(branch=3, brpart=4)) # Write the header writeout(header) writeout(rule) - total = Numbers() - skipped_count = 0 + # `lines` is a list of pairs, (line text, line values). The line text + # is a string that will be printed, and line values is a tuple of + # sortable values. + lines = [] - for fr in file_reporters: + for (fr, analysis) in fr_analysis: try: - analysis = self.coverage._analyze(fr) nums = analysis.numbers - total += nums - - if self.config.skip_covered: - # Don't report on 100% files. - no_missing_lines = (nums.n_missing == 0) - no_missing_branches = (nums.n_partial_branches == 0) - if no_missing_lines and no_missing_branches: - skipped_count += 1 - continue args = (fr.relative_filename(), nums.n_statements, nums.n_missing) if self.branches: @@ -90,7 +117,10 @@ missing_fmtd += ", " missing_fmtd += branches_fmtd args += (missing_fmtd,) - writeout(fmt_coverage % args) + text = fmt_coverage % args + # Add numeric percent coverage so that sorting makes sense. + args += (nums.pc_covered,) + lines.append((text, args)) except Exception: report_it = not self.config.ignore_errors if report_it: @@ -102,6 +132,17 @@ if report_it: writeout(fmt_err % (fr.relative_filename(), typ.__name__, msg)) + # Sort the lines and write them out. + if getattr(self.config, 'sort', None): + position = column_order.get(self.config.sort.lower()) + if position is None: + raise CoverageException("Invalid sorting option: {0!r}".format(self.config.sort)) + lines.sort(key=lambda l: (l[1][position], l[0])) + + for line in lines: + writeout(line[0]) + + # Write a TOTAl line if we had more than one file. if total.n_files > 1: writeout(rule) args = ("TOTAL", total.n_statements, total.n_missing) @@ -112,6 +153,7 @@ args += ("",) writeout(fmt_coverage % args) + # Write other final lines. if not total.n_files and not skipped_count: raise CoverageException("No data to report.")
--- a/DebugClients/Python/coverage/templite.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/templite.py Tue May 01 12:03:52 2018 +0200 @@ -170,7 +170,8 @@ # An expression to evaluate. expr = self._expr_code(token[start:end].strip()) buffered.append("to_str(%s)" % expr) - elif token.startswith('{%'): + else: + # token.startswith('{%') # Action tag: split into words and parse further. flush_output()
--- a/DebugClients/Python/coverage/test_helpers.py Mon Apr 02 12:04:56 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,390 +0,0 @@ -# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 -# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt - -"""Mixin classes to help make good tests.""" - -import atexit -import collections -import contextlib -import os -import random -import shutil -import sys -import tempfile -import textwrap - -from coverage.backunittest import TestCase -from coverage.backward import StringIO, to_bytes - - -class Tee(object): - """A file-like that writes to all the file-likes it has.""" - - def __init__(self, *files): - """Make a Tee that writes to all the files in `files.`""" - self._files = files - if hasattr(files[0], "encoding"): - self.encoding = files[0].encoding - - def write(self, data): - """Write `data` to all the files.""" - for f in self._files: - f.write(data) - - def flush(self): - """Flush the data on all the files.""" - for f in self._files: - f.flush() - - if 0: - # Use this if you need to use a debugger, though it makes some tests - # fail, I'm not sure why... - def __getattr__(self, name): - return getattr(self._files[0], name) - - -@contextlib.contextmanager -def change_dir(new_dir): - """Change directory, and then change back. - - Use as a context manager, it will give you the new directory, and later - restore the old one. - - """ - old_dir = os.getcwd() - os.chdir(new_dir) - try: - yield os.getcwd() - finally: - os.chdir(old_dir) - - -@contextlib.contextmanager -def saved_sys_path(): - """Save sys.path, and restore it later.""" - old_syspath = sys.path[:] - try: - yield - finally: - sys.path = old_syspath - - -def setup_with_context_manager(testcase, cm): - """Use a contextmanager to setUp a test case. - - If you have a context manager you like:: - - with ctxmgr(a, b, c) as v: - # do something with v - - and you want to have that effect for a test case, call this function from - your setUp, and it will start the context manager for your test, and end it - when the test is done:: - - def setUp(self): - self.v = setup_with_context_manager(self, ctxmgr(a, b, c)) - - def test_foo(self): - # do something with self.v - - """ - val = cm.__enter__() - testcase.addCleanup(cm.__exit__, None, None, None) - return val - - -class ModuleAwareMixin(TestCase): - """A test case mixin that isolates changes to sys.modules.""" - - def setUp(self): - super(ModuleAwareMixin, self).setUp() - - # Record sys.modules here so we can restore it in cleanup_modules. - self.old_modules = list(sys.modules) - self.addCleanup(self.cleanup_modules) - - def cleanup_modules(self): - """Remove any new modules imported during the test run. - - This lets us import the same source files for more than one test. - - """ - for m in [m for m in sys.modules if m not in self.old_modules]: - del sys.modules[m] - - -class SysPathAwareMixin(TestCase): - """A test case mixin that isolates changes to sys.path.""" - - def setUp(self): - super(SysPathAwareMixin, self).setUp() - setup_with_context_manager(self, saved_sys_path()) - - -class EnvironmentAwareMixin(TestCase): - """A test case mixin that isolates changes to the environment.""" - - def setUp(self): - super(EnvironmentAwareMixin, self).setUp() - - # Record environment variables that we changed with set_environ. - self.environ_undos = {} - - self.addCleanup(self.cleanup_environ) - - def set_environ(self, name, value): - """Set an environment variable `name` to be `value`. - - The environment variable is set, and record is kept that it was set, - so that `cleanup_environ` can restore its original value. - - """ - if name not in self.environ_undos: - self.environ_undos[name] = os.environ.get(name) - os.environ[name] = value - - def cleanup_environ(self): - """Undo all the changes made by `set_environ`.""" - for name, value in self.environ_undos.items(): - if value is None: - del os.environ[name] - else: - os.environ[name] = value - - -class StdStreamCapturingMixin(TestCase): - """A test case mixin that captures stdout and stderr.""" - - def setUp(self): - super(StdStreamCapturingMixin, self).setUp() - - # Capture stdout and stderr so we can examine them in tests. - # nose keeps stdout from littering the screen, so we can safely Tee it, - # but it doesn't capture stderr, so we don't want to Tee stderr to the - # real stderr, since it will interfere with our nice field of dots. - old_stdout = sys.stdout - self.captured_stdout = StringIO() - sys.stdout = Tee(sys.stdout, self.captured_stdout) - - old_stderr = sys.stderr - self.captured_stderr = StringIO() - sys.stderr = self.captured_stderr - - self.addCleanup(self.cleanup_std_streams, old_stdout, old_stderr) - - def cleanup_std_streams(self, old_stdout, old_stderr): - """Restore stdout and stderr.""" - sys.stdout = old_stdout - sys.stderr = old_stderr - - def stdout(self): - """Return the data written to stdout during the test.""" - return self.captured_stdout.getvalue() - - def stderr(self): - """Return the data written to stderr during the test.""" - return self.captured_stderr.getvalue() - - -class DelayedAssertionMixin(TestCase): - """A test case mixin that provides a `delayed_assertions` context manager. - - Use it like this:: - - with self.delayed_assertions(): - self.assertEqual(x, y) - self.assertEqual(z, w) - - All of the assertions will run. The failures will be displayed at the end - of the with-statement. - - NOTE: this only works with some assertions. These are known to work: - - - `assertEqual(str, str)` - - - `assertMultilineEqual(str, str)` - - """ - def __init__(self, *args, **kwargs): - super(DelayedAssertionMixin, self).__init__(*args, **kwargs) - # This mixin only works with assert methods that call `self.fail`. In - # Python 2.7, `assertEqual` didn't, but we can do what Python 3 does, - # and use `assertMultiLineEqual` for comparing strings. - self.addTypeEqualityFunc(str, 'assertMultiLineEqual') - self._delayed_assertions = None - - @contextlib.contextmanager - def delayed_assertions(self): - """The context manager: assert that we didn't collect any assertions.""" - self._delayed_assertions = [] - old_fail = self.fail - self.fail = self._delayed_fail - try: - yield - finally: - self.fail = old_fail - if self._delayed_assertions: - if len(self._delayed_assertions) == 1: - self.fail(self._delayed_assertions[0]) - else: - self.fail( - "{0} failed assertions:\n{1}".format( - len(self._delayed_assertions), - "\n".join(self._delayed_assertions), - ) - ) - - def _delayed_fail(self, msg=None): - """The stand-in for TestCase.fail during delayed_assertions.""" - self._delayed_assertions.append(msg) - - -class TempDirMixin(SysPathAwareMixin, ModuleAwareMixin, TestCase): - """A test case mixin that creates a temp directory and files in it. - - Includes SysPathAwareMixin and ModuleAwareMixin, because making and using - temp directories like this will also need that kind of isolation. - - """ - - # Our own setting: most of these tests run in their own temp directory. - # Set this to False in your subclass if you don't want a temp directory - # created. - run_in_temp_dir = True - - # Set this if you aren't creating any files with make_file, but still want - # the temp directory. This will stop the test behavior checker from - # complaining. - no_files_in_temp_dir = False - - def setUp(self): - super(TempDirMixin, self).setUp() - - if self.run_in_temp_dir: - # Create a temporary directory. - self.temp_dir = self.make_temp_dir("test_cover") - self.chdir(self.temp_dir) - - # Modules should be importable from this temp directory. We don't - # use '' because we make lots of different temp directories and - # nose's caching importer can get confused. The full path prevents - # problems. - sys.path.insert(0, os.getcwd()) - - class_behavior = self.class_behavior() - class_behavior.tests += 1 - class_behavior.temp_dir = self.run_in_temp_dir - class_behavior.no_files_ok = self.no_files_in_temp_dir - - self.addCleanup(self.check_behavior) - - def make_temp_dir(self, slug="test_cover"): - """Make a temp directory that is cleaned up when the test is done.""" - name = "%s_%08d" % (slug, random.randint(0, 99999999)) - temp_dir = os.path.join(tempfile.gettempdir(), name) - os.makedirs(temp_dir) - self.addCleanup(shutil.rmtree, temp_dir) - return temp_dir - - def chdir(self, new_dir): - """Change directory, and change back when the test is done.""" - old_dir = os.getcwd() - os.chdir(new_dir) - self.addCleanup(os.chdir, old_dir) - - def check_behavior(self): - """Check that we did the right things.""" - - class_behavior = self.class_behavior() - if class_behavior.test_method_made_any_files: - class_behavior.tests_making_files += 1 - - def make_file(self, filename, text="", newline=None): - """Create a file for testing. - - `filename` is the relative path to the file, including directories if - desired, which will be created if need be. - - `text` is the content to create in the file, a native string (bytes in - Python 2, unicode in Python 3). - - If `newline` is provided, it is a string that will be used as the line - endings in the created file, otherwise the line endings are as provided - in `text`. - - Returns `filename`. - - """ - # Tests that call `make_file` should be run in a temp environment. - assert self.run_in_temp_dir - self.class_behavior().test_method_made_any_files = True - - text = textwrap.dedent(text) - if newline: - text = text.replace("\n", newline) - - # Make sure the directories are available. - dirs, _ = os.path.split(filename) - if dirs and not os.path.exists(dirs): - os.makedirs(dirs) - - # Create the file. - with open(filename, 'wb') as f: - f.write(to_bytes(text)) - - return filename - - # We run some tests in temporary directories, because they may need to make - # files for the tests. But this is expensive, so we can change per-class - # whether a temp directory is used or not. It's easy to forget to set that - # option properly, so we track information about what the tests did, and - # then report at the end of the process on test classes that were set - # wrong. - - class ClassBehavior(object): - """A value object to store per-class.""" - def __init__(self): - self.tests = 0 - self.skipped = 0 - self.temp_dir = True - self.no_files_ok = False - self.tests_making_files = 0 - self.test_method_made_any_files = False - - # Map from class to info about how it ran. - class_behaviors = collections.defaultdict(ClassBehavior) - - @classmethod - def report_on_class_behavior(cls): - """Called at process exit to report on class behavior.""" - for test_class, behavior in cls.class_behaviors.items(): - bad = "" - if behavior.tests <= behavior.skipped: - bad = "" - elif behavior.temp_dir and behavior.tests_making_files == 0: - if not behavior.no_files_ok: - bad = "Inefficient" - elif not behavior.temp_dir and behavior.tests_making_files > 0: - bad = "Unsafe" - - if bad: - if behavior.temp_dir: - where = "in a temp directory" - else: - where = "without a temp directory" - print( - "%s: %s ran %d tests, %d made files %s" % ( - bad, - test_class.__name__, - behavior.tests, - behavior.tests_making_files, - where, - ) - ) - - def class_behavior(self): - """Get the ClassBehavior instance for this test.""" - return self.class_behaviors[self.__class__] - -# When the process ends, find out about bad classes. -atexit.register(TempDirMixin.report_on_class_behavior)
--- a/DebugClients/Python/coverage/version.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/version.py Tue May 01 12:03:52 2018 +0200 @@ -5,7 +5,7 @@ # This file is exec'ed in setup.py, don't import anything! # Same semantics as sys.version_info. -version_info = (4, 1, 0, 'final', 0) +version_info = (4, 5, 1, 'final', 0) def _make_version(major, minor, micro, releaselevel, serial):
--- a/DebugClients/Python/coverage/xmlreport.py Mon Apr 02 12:04:56 2018 +0200 +++ b/DebugClients/Python/coverage/xmlreport.py Tue May 01 12:03:52 2018 +0200 @@ -18,11 +18,7 @@ os = isolate_module(os) -DTD_URL = ( - 'https://raw.githubusercontent.com/cobertura/web/' - 'f0366e5e2cf18f111cbd61fc34ef720a6584ba02' - '/htdocs/xml/coverage-03.dtd' -) +DTD_URL = 'https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd' def rate(hit, num): @@ -114,12 +110,18 @@ bnum_tot += bnum bhits_tot += bhits + xcoverage.setAttribute("lines-valid", str(lnum_tot)) + xcoverage.setAttribute("lines-covered", str(lhits_tot)) xcoverage.setAttribute("line-rate", rate(lhits_tot, lnum_tot)) if self.has_arcs: - branch_rate = rate(bhits_tot, bnum_tot) + xcoverage.setAttribute("branches-valid", str(bnum_tot)) + xcoverage.setAttribute("branches-covered", str(bhits_tot)) + xcoverage.setAttribute("branch-rate", rate(bhits_tot, bnum_tot)) else: - branch_rate = "0" - xcoverage.setAttribute("branch-rate", branch_rate) + xcoverage.setAttribute("branches-covered", "0") + xcoverage.setAttribute("branches-valid", "0") + xcoverage.setAttribute("branch-rate", "0") + xcoverage.setAttribute("complexity", "0") # Use the DOM to write the output file. out = self.xml_out.toprettyxml() @@ -148,7 +150,7 @@ else: rel_name = fr.relative_filename() - dirname = os.path.dirname(rel_name) or "." + dirname = os.path.dirname(rel_name) or u"." dirname = "/".join(dirname.split("/")[:self.config.xml_package_depth]) package_name = dirname.replace("/", ".") @@ -164,7 +166,7 @@ xclass.appendChild(xlines) xclass.setAttribute("name", os.path.relpath(rel_name, dirname)) - xclass.setAttribute("filename", fr.relative_filename().replace("\\", "/")) + xclass.setAttribute("filename", rel_name.replace("\\", "/")) xclass.setAttribute("complexity", "0") branch_stats = analysis.branch_stats() @@ -185,7 +187,7 @@ xline.setAttribute("branch", "true") xline.setAttribute( "condition-coverage", - "%d%% (%d/%d)" % (100*taken/total, taken, total) + "%d%% (%d/%d)" % (100*taken//total, taken, total) ) if line in missing_branch_arcs: annlines = ["exit" if b < 0 else str(b) for b in missing_branch_arcs[line]]
--- a/Debugger/DebugUI.py Mon Apr 02 12:04:56 2018 +0200 +++ b/Debugger/DebugUI.py Tue May 01 12:03:52 2018 +0200 @@ -38,6 +38,8 @@ @signal compileForms() emitted if changed project forms should be compiled @signal compileResources() emitted if changed project resources should be compiled + @signal executeMake() emitted if a project specific make run should be + performed @signal debuggingStarted(filename) emitted when a debugging session was started @signal resetUI() emitted to reset the UI @@ -51,6 +53,7 @@ exceptionInterrupt = pyqtSignal() compileForms = pyqtSignal() compileResources = pyqtSignal() + executeMake = pyqtSignal() debuggingStarted = pyqtSignal(str) appendStdout = pyqtSignal(str) @@ -1540,6 +1543,8 @@ self.compileForms.emit() if Preferences.getProject("AutoCompileResources"): self.compileResources.emit() + if Preferences.getProject("AutoExecuteMake"): + self.executeMake.emit() QApplication.processEvents() def __coverageScript(self):
--- a/Documentation/Help/source.qhp Mon Apr 02 12:04:56 2018 +0200 +++ b/Documentation/Help/source.qhp Tue May 01 12:03:52 2018 +0200 @@ -974,6 +974,7 @@ <section title="eric6.Project.DebuggerPropertiesDialog" ref="eric6.Project.DebuggerPropertiesDialog.html" /> <section title="eric6.Project.FiletypeAssociationDialog" ref="eric6.Project.FiletypeAssociationDialog.html" /> <section title="eric6.Project.LexerAssociationDialog" ref="eric6.Project.LexerAssociationDialog.html" /> + <section title="eric6.Project.MakePropertiesDialog" ref="eric6.Project.MakePropertiesDialog.html" /> <section title="eric6.Project.NewDialogClassDialog" ref="eric6.Project.NewDialogClassDialog.html" /> <section title="eric6.Project.NewPythonPackageDialog" ref="eric6.Project.NewPythonPackageDialog.html" /> <section title="eric6.Project.Project" ref="eric6.Project.Project.html" /> @@ -1362,6 +1363,7 @@ <section title="eric6.WebBrowser.SafeBrowsing.SafeBrowsingInfoWidget" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingInfoWidget.html" /> <section title="eric6.WebBrowser.SafeBrowsing.SafeBrowsingLabel" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingLabel.html" /> <section title="eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.html" /> + <section title="eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.html" /> <section title="eric6.WebBrowser.SafeBrowsing.SafeBrowsingUrl" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingUrl.html" /> <section title="eric6.WebBrowser.SafeBrowsing.SafeBrowsingUtilities" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingUtilities.html" /> <section title="eric6.WebBrowser.SafeBrowsing.__init__" ref="eric6.WebBrowser.SafeBrowsing.__init__.html" /> @@ -2158,18 +2160,6 @@ <keyword name="BackgroundService.serviceDisconnect" id="BackgroundService.serviceDisconnect" ref="eric6.Utilities.BackgroundService.html#BackgroundService.serviceDisconnect" /> <keyword name="BackgroundService.shutdown" id="BackgroundService.shutdown" ref="eric6.Utilities.BackgroundService.html#BackgroundService.shutdown" /> <keyword name="BaseReport" id="BaseReport" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport" /> - <keyword name="BaseReport (Constructor)" id="BaseReport (Constructor)" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport.__init__" /> - <keyword name="BaseReport.error" id="BaseReport.error" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport.error" /> - <keyword name="BaseReport.error_args" id="BaseReport.error_args" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport.error_args" /> - <keyword name="BaseReport.get_count" id="BaseReport.get_count" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport.get_count" /> - <keyword name="BaseReport.get_file_results" id="BaseReport.get_file_results" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport.get_file_results" /> - <keyword name="BaseReport.get_statistics" id="BaseReport.get_statistics" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport.get_statistics" /> - <keyword name="BaseReport.increment_logical_line" id="BaseReport.increment_logical_line" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport.increment_logical_line" /> - <keyword name="BaseReport.init_file" id="BaseReport.init_file" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport.init_file" /> - <keyword name="BaseReport.print_benchmark" id="BaseReport.print_benchmark" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport.print_benchmark" /> - <keyword name="BaseReport.print_statistics" id="BaseReport.print_statistics" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport.print_statistics" /> - <keyword name="BaseReport.start" id="BaseReport.start" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport.start" /> - <keyword name="BaseReport.stop" id="BaseReport.stop" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#BaseReport.stop" /> <keyword name="BaseResolver" id="BaseResolver" ref="eric6.DebugClients.Python.DebugVariables.html#BaseResolver" /> <keyword name="BaseResolver.getDictionary" id="BaseResolver.getDictionary" ref="eric6.DebugClients.Python.DebugVariables.html#BaseResolver.getDictionary" /> <keyword name="BaseResolver.resolve" id="BaseResolver.resolve" ref="eric6.DebugClients.Python.DebugVariables.html#BaseResolver.resolve" /> @@ -2821,18 +2811,6 @@ <keyword name="ChatWidget.preferencesChanged" id="ChatWidget.preferencesChanged" ref="eric6.Cooperation.ChatWidget.html#ChatWidget.preferencesChanged" /> <keyword name="ChatWidget.shutdown" id="ChatWidget.shutdown" ref="eric6.Cooperation.ChatWidget.html#ChatWidget.shutdown" /> <keyword name="Checker" id="Checker" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker" /> - <keyword name="Checker (Constructor)" id="Checker (Constructor)" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker.__init__" /> - <keyword name="Checker.build_tokens_line" id="Checker.build_tokens_line" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker.build_tokens_line" /> - <keyword name="Checker.check_all" id="Checker.check_all" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker.check_all" /> - <keyword name="Checker.check_ast" id="Checker.check_ast" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker.check_ast" /> - <keyword name="Checker.check_logical" id="Checker.check_logical" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker.check_logical" /> - <keyword name="Checker.check_physical" id="Checker.check_physical" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker.check_physical" /> - <keyword name="Checker.generate_tokens" id="Checker.generate_tokens" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker.generate_tokens" /> - <keyword name="Checker.init_checker_state" id="Checker.init_checker_state" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker.init_checker_state" /> - <keyword name="Checker.maybe_check_physical" id="Checker.maybe_check_physical" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker.maybe_check_physical" /> - <keyword name="Checker.readline" id="Checker.readline" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker.readline" /> - <keyword name="Checker.report_invalid_syntax" id="Checker.report_invalid_syntax" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker.report_invalid_syntax" /> - <keyword name="Checker.run_check" id="Checker.run_check" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#Checker.run_check" /> <keyword name="CheckerPlugins (Package)" id="CheckerPlugins (Package)" ref="index-eric6.Plugins.CheckerPlugins.html" /> <keyword name="ChromeImporter" id="ChromeImporter" ref="eric6.Helpviewer.Bookmarks.BookmarksImporters.ChromeImporter.html#ChromeImporter" /> <keyword name="ChromeImporter" id="ChromeImporter" ref="eric6.WebBrowser.Bookmarks.BookmarksImporters.ChromeImporter.html#ChromeImporter" /> @@ -2967,11 +2945,13 @@ <keyword name="CodeDocumentationViewer" id="CodeDocumentationViewer" ref="eric6.UI.CodeDocumentationViewer.html#CodeDocumentationViewer" /> <keyword name="CodeDocumentationViewer (Constructor)" id="CodeDocumentationViewer (Constructor)" ref="eric6.UI.CodeDocumentationViewer.html#CodeDocumentationViewer.__init__" /> <keyword name="CodeDocumentationViewer (Module)" id="CodeDocumentationViewer (Module)" ref="eric6.UI.CodeDocumentationViewer.html" /> + <keyword name="CodeDocumentationViewer.__selectProvider" id="CodeDocumentationViewer.__selectProvider" ref="eric6.UI.CodeDocumentationViewer.html#CodeDocumentationViewer.__selectProvider" /> <keyword name="CodeDocumentationViewer.__setHtml" id="CodeDocumentationViewer.__setHtml" ref="eric6.UI.CodeDocumentationViewer.html#CodeDocumentationViewer.__setHtml" /> <keyword name="CodeDocumentationViewer.__setHtmlWarning" id="CodeDocumentationViewer.__setHtmlWarning" ref="eric6.UI.CodeDocumentationViewer.html#CodeDocumentationViewer.__setHtmlWarning" /> <keyword name="CodeDocumentationViewer.__setupUi" id="CodeDocumentationViewer.__setupUi" ref="eric6.UI.CodeDocumentationViewer.html#CodeDocumentationViewer.__setupUi" /> <keyword name="CodeDocumentationViewer.__showDisabledMessage" id="CodeDocumentationViewer.__showDisabledMessage" ref="eric6.UI.CodeDocumentationViewer.html#CodeDocumentationViewer.__showDisabledMessage" /> <keyword name="CodeDocumentationViewer.__showTextViewer" id="CodeDocumentationViewer.__showTextViewer" ref="eric6.UI.CodeDocumentationViewer.html#CodeDocumentationViewer.__showTextViewer" /> + <keyword name="CodeDocumentationViewer.__unregisterTimerTimeout" id="CodeDocumentationViewer.__unregisterTimerTimeout" ref="eric6.UI.CodeDocumentationViewer.html#CodeDocumentationViewer.__unregisterTimerTimeout" /> <keyword name="CodeDocumentationViewer.documentationReady" id="CodeDocumentationViewer.documentationReady" ref="eric6.UI.CodeDocumentationViewer.html#CodeDocumentationViewer.documentationReady" /> <keyword name="CodeDocumentationViewer.finalizeSetup" id="CodeDocumentationViewer.finalizeSetup" ref="eric6.UI.CodeDocumentationViewer.html#CodeDocumentationViewer.finalizeSetup" /> <keyword name="CodeDocumentationViewer.getProviders" id="CodeDocumentationViewer.getProviders" ref="eric6.UI.CodeDocumentationViewer.html#CodeDocumentationViewer.getProviders" /> @@ -3087,6 +3067,7 @@ <keyword name="CodeStyleFixer (Module)" id="CodeStyleFixer (Module)" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html" /> <keyword name="CodeStyleFixer.__codeMatch" id="CodeStyleFixer.__codeMatch" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__codeMatch" /> <keyword name="CodeStyleFixer.__findLogical" id="CodeStyleFixer.__findLogical" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__findLogical" /> + <keyword name="CodeStyleFixer.__fixBlankLinesBefore" id="CodeStyleFixer.__fixBlankLinesBefore" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixBlankLinesBefore" /> <keyword name="CodeStyleFixer.__fixD111" id="CodeStyleFixer.__fixD111" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixD111" /> <keyword name="CodeStyleFixer.__fixD112" id="CodeStyleFixer.__fixD112" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixD112" /> <keyword name="CodeStyleFixer.__fixD131" id="CodeStyleFixer.__fixD131" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixD131" /> @@ -3112,9 +3093,6 @@ <keyword name="CodeStyleFixer.__fixE231" id="CodeStyleFixer.__fixE231" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixE231" /> <keyword name="CodeStyleFixer.__fixE251" id="CodeStyleFixer.__fixE251" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixE251" /> <keyword name="CodeStyleFixer.__fixE261" id="CodeStyleFixer.__fixE261" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixE261" /> - <keyword name="CodeStyleFixer.__fixE301" id="CodeStyleFixer.__fixE301" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixE301" /> - <keyword name="CodeStyleFixer.__fixE302" id="CodeStyleFixer.__fixE302" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixE302" /> - <keyword name="CodeStyleFixer.__fixE303" id="CodeStyleFixer.__fixE303" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixE303" /> <keyword name="CodeStyleFixer.__fixE304" id="CodeStyleFixer.__fixE304" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixE304" /> <keyword name="CodeStyleFixer.__fixE401" id="CodeStyleFixer.__fixE401" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixE401" /> <keyword name="CodeStyleFixer.__fixE501" id="CodeStyleFixer.__fixE501" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#CodeStyleFixer.__fixE501" /> @@ -4024,8 +4002,6 @@ <keyword name="DiffHighlighter (Module)" id="DiffHighlighter (Module)" ref="eric6.UI.DiffHighlighter.html" /> <keyword name="DiffHighlighter.generateRules" id="DiffHighlighter.generateRules" ref="eric6.UI.DiffHighlighter.html#DiffHighlighter.generateRules" /> <keyword name="DiffReport" id="DiffReport" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#DiffReport" /> - <keyword name="DiffReport (Constructor)" id="DiffReport (Constructor)" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#DiffReport.__init__" /> - <keyword name="DiffReport.error" id="DiffReport.error" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#DiffReport.error" /> <keyword name="DiffWindow" id="DiffWindow" ref="eric6.UI.DiffDialog.html#DiffWindow" /> <keyword name="DiffWindow (Constructor)" id="DiffWindow (Constructor)" ref="eric6.UI.DiffDialog.html#DiffWindow.__init__" /> <keyword name="DiffWindow.eventFilter" id="DiffWindow.eventFilter" ref="eric6.UI.DiffDialog.html#DiffWindow.eventFilter" /> @@ -4199,6 +4175,7 @@ <keyword name="DownloadItem.currentSpeed" id="DownloadItem.currentSpeed" ref="eric6.WebBrowser.Download.DownloadItem.html#DownloadItem.currentSpeed" /> <keyword name="DownloadItem.downloadCanceled" id="DownloadItem.downloadCanceled" ref="eric6.Helpviewer.Download.DownloadItem.html#DownloadItem.downloadCanceled" /> <keyword name="DownloadItem.downloadCanceled" id="DownloadItem.downloadCanceled" ref="eric6.WebBrowser.Download.DownloadItem.html#DownloadItem.downloadCanceled" /> + <keyword name="DownloadItem.downloadProgress" id="DownloadItem.downloadProgress" ref="eric6.WebBrowser.Download.DownloadItem.html#DownloadItem.downloadProgress" /> <keyword name="DownloadItem.downloadedSuccessfully" id="DownloadItem.downloadedSuccessfully" ref="eric6.Helpviewer.Download.DownloadItem.html#DownloadItem.downloadedSuccessfully" /> <keyword name="DownloadItem.downloadedSuccessfully" id="DownloadItem.downloadedSuccessfully" ref="eric6.WebBrowser.Download.DownloadItem.html#DownloadItem.downloadedSuccessfully" /> <keyword name="DownloadItem.downloading" id="DownloadItem.downloading" ref="eric6.Helpviewer.Download.DownloadItem.html#DownloadItem.downloading" /> @@ -4237,6 +4214,7 @@ <keyword name="DownloadManager (Module)" id="DownloadManager (Module)" ref="eric6.WebBrowser.Download.DownloadManager.html" /> <keyword name="DownloadManager.__addItem" id="DownloadManager.__addItem" ref="eric6.Helpviewer.Download.DownloadManager.html#DownloadManager.__addItem" /> <keyword name="DownloadManager.__addItem" id="DownloadManager.__addItem" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.__addItem" /> + <keyword name="DownloadManager.__closeDownloadTab" id="DownloadManager.__closeDownloadTab" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.__closeDownloadTab" /> <keyword name="DownloadManager.__contextMenuCancel" id="DownloadManager.__contextMenuCancel" ref="eric6.Helpviewer.Download.DownloadManager.html#DownloadManager.__contextMenuCancel" /> <keyword name="DownloadManager.__contextMenuCancel" id="DownloadManager.__contextMenuCancel" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.__contextMenuCancel" /> <keyword name="DownloadManager.__contextMenuCopyLink" id="DownloadManager.__contextMenuCopyLink" ref="eric6.Helpviewer.Download.DownloadManager.html#DownloadManager.__contextMenuCopyLink" /> @@ -4260,10 +4238,12 @@ <keyword name="DownloadManager.__finished" id="DownloadManager.__finished" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.__finished" /> <keyword name="DownloadManager.__load" id="DownloadManager.__load" ref="eric6.Helpviewer.Download.DownloadManager.html#DownloadManager.__load" /> <keyword name="DownloadManager.__load" id="DownloadManager.__load" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.__load" /> + <keyword name="DownloadManager.__startUpdateTimer" id="DownloadManager.__startUpdateTimer" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.__startUpdateTimer" /> + <keyword name="DownloadManager.__stopUpdateTimer" id="DownloadManager.__stopUpdateTimer" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.__stopUpdateTimer" /> + <keyword name="DownloadManager.__taskbarButton" id="DownloadManager.__taskbarButton" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.__taskbarButton" /> + <keyword name="DownloadManager.__testWebBrowserView" id="DownloadManager.__testWebBrowserView" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.__testWebBrowserView" /> <keyword name="DownloadManager.__updateActiveItemCount" id="DownloadManager.__updateActiveItemCount" ref="eric6.Helpviewer.Download.DownloadManager.html#DownloadManager.__updateActiveItemCount" /> - <keyword name="DownloadManager.__updateActiveItemCount" id="DownloadManager.__updateActiveItemCount" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.__updateActiveItemCount" /> <keyword name="DownloadManager.__updateItemCount" id="DownloadManager.__updateItemCount" ref="eric6.Helpviewer.Download.DownloadManager.html#DownloadManager.__updateItemCount" /> - <keyword name="DownloadManager.__updateItemCount" id="DownloadManager.__updateItemCount" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.__updateItemCount" /> <keyword name="DownloadManager.__updateRow" id="DownloadManager.__updateRow" ref="eric6.Helpviewer.Download.DownloadManager.html#DownloadManager.__updateRow" /> <keyword name="DownloadManager.__updateRow" id="DownloadManager.__updateRow" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.__updateRow" /> <keyword name="DownloadManager.activeDownloads" id="DownloadManager.activeDownloads" ref="eric6.Helpviewer.Download.DownloadManager.html#DownloadManager.activeDownloads" /> @@ -4294,8 +4274,10 @@ <keyword name="DownloadManager.setDownloadDirectory" id="DownloadManager.setDownloadDirectory" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.setDownloadDirectory" /> <keyword name="DownloadManager.setRemovePolicy" id="DownloadManager.setRemovePolicy" ref="eric6.Helpviewer.Download.DownloadManager.html#DownloadManager.setRemovePolicy" /> <keyword name="DownloadManager.setRemovePolicy" id="DownloadManager.setRemovePolicy" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.setRemovePolicy" /> + <keyword name="DownloadManager.show" id="DownloadManager.show" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.show" /> <keyword name="DownloadManager.shutdown" id="DownloadManager.shutdown" ref="eric6.Helpviewer.Download.DownloadManager.html#DownloadManager.shutdown" /> <keyword name="DownloadManager.shutdown" id="DownloadManager.shutdown" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.shutdown" /> + <keyword name="DownloadManager.timerEvent" id="DownloadManager.timerEvent" ref="eric6.WebBrowser.Download.DownloadManager.html#DownloadManager.timerEvent" /> <keyword name="DownloadManagerButton" id="DownloadManagerButton" ref="eric6.WebBrowser.Download.DownloadManagerButton.html#DownloadManagerButton" /> <keyword name="DownloadManagerButton (Constructor)" id="DownloadManagerButton (Constructor)" ref="eric6.WebBrowser.Download.DownloadManagerButton.html#DownloadManagerButton.__init__" /> <keyword name="DownloadManagerButton (Module)" id="DownloadManagerButton (Module)" ref="eric6.WebBrowser.Download.DownloadManagerButton.html" /> @@ -7537,10 +7519,10 @@ <keyword name="HTMLGenerator" id="HTMLGenerator" ref="eric6.QScintilla.Exporters.ExporterHTML.html#HTMLGenerator" /> <keyword name="HTMLGenerator (Constructor)" id="HTMLGenerator (Constructor)" ref="eric6.QScintilla.Exporters.ExporterHTML.html#HTMLGenerator.__init__" /> <keyword name="HTMLGenerator.generate" id="HTMLGenerator.generate" ref="eric6.QScintilla.Exporters.ExporterHTML.html#HTMLGenerator.generate" /> - <keyword name="HashPrefixList" id="HashPrefixList" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.html#HashPrefixList" /> - <keyword name="HashPrefixList (Constructor)" id="HashPrefixList (Constructor)" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.html#HashPrefixList.__init__" /> - <keyword name="HashPrefixList.__iter__" id="HashPrefixList.__iter__" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.html#HashPrefixList.__iter__" /> - <keyword name="HashPrefixList.__len__" id="HashPrefixList.__len__" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.html#HashPrefixList.__len__" /> + <keyword name="HashPrefixList" id="HashPrefixList" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.html#HashPrefixList" /> + <keyword name="HashPrefixList (Constructor)" id="HashPrefixList (Constructor)" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.html#HashPrefixList.__init__" /> + <keyword name="HashPrefixList.__iter__" id="HashPrefixList.__iter__" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.html#HashPrefixList.__iter__" /> + <keyword name="HashPrefixList.__len__" id="HashPrefixList.__len__" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.html#HashPrefixList.__len__" /> <keyword name="HashableWrapper" id="HashableWrapper" ref="eric6.Utilities.binplistlib.html#HashableWrapper" /> <keyword name="HashableWrapper (Constructor)" id="HashableWrapper (Constructor)" ref="eric6.Utilities.binplistlib.html#HashableWrapper.__init__" /> <keyword name="HashableWrapper.__repr__" id="HashableWrapper.__repr__" ref="eric6.Utilities.binplistlib.html#HashableWrapper.__repr__" /> @@ -10806,6 +10788,12 @@ <keyword name="LoginForm (Module)" id="LoginForm (Module)" ref="eric6.WebBrowser.Passwords.LoginForm.html" /> <keyword name="LoginForm.isValid" id="LoginForm.isValid" ref="eric6.Helpviewer.Passwords.LoginForm.html#LoginForm.isValid" /> <keyword name="LoginForm.isValid" id="LoginForm.isValid" ref="eric6.WebBrowser.Passwords.LoginForm.html#LoginForm.isValid" /> + <keyword name="MakePropertiesDialog" id="MakePropertiesDialog" ref="eric6.Project.MakePropertiesDialog.html#MakePropertiesDialog" /> + <keyword name="MakePropertiesDialog (Constructor)" id="MakePropertiesDialog (Constructor)" ref="eric6.Project.MakePropertiesDialog.html#MakePropertiesDialog.__init__" /> + <keyword name="MakePropertiesDialog (Module)" id="MakePropertiesDialog (Module)" ref="eric6.Project.MakePropertiesDialog.html" /> + <keyword name="MakePropertiesDialog.__updateOkButton" id="MakePropertiesDialog.__updateOkButton" ref="eric6.Project.MakePropertiesDialog.html#MakePropertiesDialog.__updateOkButton" /> + <keyword name="MakePropertiesDialog.initDialog" id="MakePropertiesDialog.initDialog" ref="eric6.Project.MakePropertiesDialog.html#MakePropertiesDialog.initDialog" /> + <keyword name="MakePropertiesDialog.storeData" id="MakePropertiesDialog.storeData" ref="eric6.Project.MakePropertiesDialog.html#MakePropertiesDialog.storeData" /> <keyword name="ManageDictionariesDialog" id="ManageDictionariesDialog" ref="eric6.WebBrowser.SpellCheck.ManageDictionariesDialog.html#ManageDictionariesDialog" /> <keyword name="ManageDictionariesDialog (Constructor)" id="ManageDictionariesDialog (Constructor)" ref="eric6.WebBrowser.SpellCheck.ManageDictionariesDialog.html#ManageDictionariesDialog.__init__" /> <keyword name="ManageDictionariesDialog (Module)" id="ManageDictionariesDialog (Module)" ref="eric6.WebBrowser.SpellCheck.ManageDictionariesDialog.html" /> @@ -12465,17 +12453,22 @@ <keyword name="Project.__binaryTranslationFile" id="Project.__binaryTranslationFile" ref="eric6.Project.Project.html#Project.__binaryTranslationFile" /> <keyword name="Project.__checkFilesExist" id="Project.__checkFilesExist" ref="eric6.Project.Project.html#Project.__checkFilesExist" /> <keyword name="Project.__checkProjectFileGroup" id="Project.__checkProjectFileGroup" ref="eric6.Project.Project.html#Project.__checkProjectFileGroup" /> + <keyword name="Project.__cleanupMake" id="Project.__cleanupMake" ref="eric6.Project.Project.html#Project.__cleanupMake" /> <keyword name="Project.__closeAllWindows" id="Project.__closeAllWindows" ref="eric6.Project.Project.html#Project.__closeAllWindows" /> <keyword name="Project.__createSnapshotSource" id="Project.__createSnapshotSource" ref="eric6.Project.Project.html#Project.__createSnapshotSource" /> <keyword name="Project.__createZipDirEntries" id="Project.__createZipDirEntries" ref="eric6.Project.Project.html#Project.__createZipDirEntries" /> <keyword name="Project.__deleteDebugProperties" id="Project.__deleteDebugProperties" ref="eric6.Project.Project.html#Project.__deleteDebugProperties" /> <keyword name="Project.__deleteSession" id="Project.__deleteSession" ref="eric6.Project.Project.html#Project.__deleteSession" /> <keyword name="Project.__doSearchNewFiles" id="Project.__doSearchNewFiles" ref="eric6.Project.Project.html#Project.__doSearchNewFiles" /> + <keyword name="Project.__executeMake" id="Project.__executeMake" ref="eric6.Project.Project.html#Project.__executeMake" /> <keyword name="Project.__initData" id="Project.__initData" ref="eric6.Project.Project.html#Project.__initData" /> <keyword name="Project.__initDebugProperties" id="Project.__initDebugProperties" ref="eric6.Project.Project.html#Project.__initDebugProperties" /> <keyword name="Project.__initProjectTypes" id="Project.__initProjectTypes" ref="eric6.Project.Project.html#Project.__initProjectTypes" /> <keyword name="Project.__loadDiagram" id="Project.__loadDiagram" ref="eric6.Project.Project.html#Project.__loadDiagram" /> <keyword name="Project.__loadRecent" id="Project.__loadRecent" ref="eric6.Project.Project.html#Project.__loadRecent" /> + <keyword name="Project.__makeFinished" id="Project.__makeFinished" ref="eric6.Project.Project.html#Project.__makeFinished" /> + <keyword name="Project.__makeReadStdErr" id="Project.__makeReadStdErr" ref="eric6.Project.Project.html#Project.__makeReadStdErr" /> + <keyword name="Project.__makeReadStdOut" id="Project.__makeReadStdOut" ref="eric6.Project.Project.html#Project.__makeReadStdOut" /> <keyword name="Project.__openRecent" id="Project.__openRecent" ref="eric6.Project.Project.html#Project.__openRecent" /> <keyword name="Project.__pluginCreateArchives" id="Project.__pluginCreateArchives" ref="eric6.Project.Project.html#Project.__pluginCreateArchives" /> <keyword name="Project.__pluginCreatePkgList" id="Project.__pluginCreatePkgList" ref="eric6.Project.Project.html#Project.__pluginCreatePkgList" /> @@ -12497,6 +12490,7 @@ <keyword name="Project.__showContextMenuChecks" id="Project.__showContextMenuChecks" ref="eric6.Project.Project.html#Project.__showContextMenuChecks" /> <keyword name="Project.__showContextMenuDebugger" id="Project.__showContextMenuDebugger" ref="eric6.Project.Project.html#Project.__showContextMenuDebugger" /> <keyword name="Project.__showContextMenuGraphics" id="Project.__showContextMenuGraphics" ref="eric6.Project.Project.html#Project.__showContextMenuGraphics" /> + <keyword name="Project.__showContextMenuMake" id="Project.__showContextMenuMake" ref="eric6.Project.Project.html#Project.__showContextMenuMake" /> <keyword name="Project.__showContextMenuPackagers" id="Project.__showContextMenuPackagers" ref="eric6.Project.Project.html#Project.__showContextMenuPackagers" /> <keyword name="Project.__showContextMenuRecent" id="Project.__showContextMenuRecent" ref="eric6.Project.Project.html#Project.__showContextMenuRecent" /> <keyword name="Project.__showContextMenuSession" id="Project.__showContextMenuSession" ref="eric6.Project.Project.html#Project.__showContextMenuSession" /> @@ -12549,6 +12543,7 @@ <keyword name="Project.deleteDirectory" id="Project.deleteDirectory" ref="eric6.Project.Project.html#Project.deleteDirectory" /> <keyword name="Project.deleteFile" id="Project.deleteFile" ref="eric6.Project.Project.html#Project.deleteFile" /> <keyword name="Project.deleteLanguageFile" id="Project.deleteLanguageFile" ref="eric6.Project.Project.html#Project.deleteLanguageFile" /> + <keyword name="Project.executeMake" id="Project.executeMake" ref="eric6.Project.Project.html#Project.executeMake" /> <keyword name="Project.getAbsolutePath" id="Project.getAbsolutePath" ref="eric6.Project.Project.html#Project.getAbsolutePath" /> <keyword name="Project.getAbsoluteUniversalPath" id="Project.getAbsoluteUniversalPath" ref="eric6.Project.Project.html#Project.getAbsoluteUniversalPath" /> <keyword name="Project.getActions" id="Project.getActions" ref="eric6.Project.Project.html#Project.getActions" /> @@ -12588,6 +12583,7 @@ <keyword name="Project.getVcs" id="Project.getVcs" ref="eric6.Project.Project.html#Project.getVcs" /> <keyword name="Project.handleApplicationDiagram" id="Project.handleApplicationDiagram" ref="eric6.Project.Project.html#Project.handleApplicationDiagram" /> <keyword name="Project.handlePreferencesChanged" id="Project.handlePreferencesChanged" ref="eric6.Project.Project.html#Project.handlePreferencesChanged" /> + <keyword name="Project.hasDefaultMakeParameters" id="Project.hasDefaultMakeParameters" ref="eric6.Project.Project.html#Project.hasDefaultMakeParameters" /> <keyword name="Project.hasEntry" id="Project.hasEntry" ref="eric6.Project.Project.html#Project.hasEntry" /> <keyword name="Project.hasProjectType" id="Project.hasProjectType" ref="eric6.Project.Project.html#Project.hasProjectType" /> <keyword name="Project.initActions" id="Project.initActions" ref="eric6.Project.Project.html#Project.initActions" /> @@ -12598,6 +12594,7 @@ <keyword name="Project.isDebugPropertiesLoaded" id="Project.isDebugPropertiesLoaded" ref="eric6.Project.Project.html#Project.isDebugPropertiesLoaded" /> <keyword name="Project.isDirty" id="Project.isDirty" ref="eric6.Project.Project.html#Project.isDirty" /> <keyword name="Project.isJavaScriptProject" id="Project.isJavaScriptProject" ref="eric6.Project.Project.html#Project.isJavaScriptProject" /> + <keyword name="Project.isMakeEnabled" id="Project.isMakeEnabled" ref="eric6.Project.Project.html#Project.isMakeEnabled" /> <keyword name="Project.isMixedLanguageProject" id="Project.isMixedLanguageProject" ref="eric6.Project.Project.html#Project.isMixedLanguageProject" /> <keyword name="Project.isOpen" id="Project.isOpen" ref="eric6.Project.Project.html#Project.isOpen" /> <keyword name="Project.isProjectFile" id="Project.isProjectFile" ref="eric6.Project.Project.html#Project.isProjectFile" /> @@ -13010,6 +13007,7 @@ <keyword name="PropertiesDialog.on_languageComboBox_currentIndexChanged" id="PropertiesDialog.on_languageComboBox_currentIndexChanged" ref="eric6.Project.PropertiesDialog.html#PropertiesDialog.on_languageComboBox_currentIndexChanged" /> <keyword name="PropertiesDialog.on_mainscriptPicker_aboutToShowPathPickerDialog" id="PropertiesDialog.on_mainscriptPicker_aboutToShowPathPickerDialog" ref="eric6.Project.PropertiesDialog.html#PropertiesDialog.on_mainscriptPicker_aboutToShowPathPickerDialog" /> <keyword name="PropertiesDialog.on_mainscriptPicker_pathSelected" id="PropertiesDialog.on_mainscriptPicker_pathSelected" ref="eric6.Project.PropertiesDialog.html#PropertiesDialog.on_mainscriptPicker_pathSelected" /> + <keyword name="PropertiesDialog.on_makeButton_clicked" id="PropertiesDialog.on_makeButton_clicked" ref="eric6.Project.PropertiesDialog.html#PropertiesDialog.on_makeButton_clicked" /> <keyword name="PropertiesDialog.on_spellPropertiesButton_clicked" id="PropertiesDialog.on_spellPropertiesButton_clicked" ref="eric6.Project.PropertiesDialog.html#PropertiesDialog.on_spellPropertiesButton_clicked" /> <keyword name="PropertiesDialog.on_transPropertiesButton_clicked" id="PropertiesDialog.on_transPropertiesButton_clicked" ref="eric6.Project.PropertiesDialog.html#PropertiesDialog.on_transPropertiesButton_clicked" /> <keyword name="PropertiesDialog.on_vcsInfoButton_clicked" id="PropertiesDialog.on_vcsInfoButton_clicked" ref="eric6.Project.PropertiesDialog.html#PropertiesDialog.on_vcsInfoButton_clicked" /> @@ -13734,6 +13732,9 @@ <keyword name="SafeBrowsingAPIClient (Module)" id="SafeBrowsingAPIClient (Module)" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html" /> <keyword name="SafeBrowsingAPIClient.__extractData" id="SafeBrowsingAPIClient.__extractData" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.__extractData" /> <keyword name="SafeBrowsingAPIClient.__setWaitDuration" id="SafeBrowsingAPIClient.__setWaitDuration" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.__setWaitDuration" /> + <keyword name="SafeBrowsingAPIClient.definedPlatformTypes" id="SafeBrowsingAPIClient.definedPlatformTypes" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.definedPlatformTypes" /> + <keyword name="SafeBrowsingAPIClient.definedThreatEntryTypes" id="SafeBrowsingAPIClient.definedThreatEntryTypes" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.definedThreatEntryTypes" /> + <keyword name="SafeBrowsingAPIClient.definedThreatTypes" id="SafeBrowsingAPIClient.definedThreatTypes" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.definedThreatTypes" /> <keyword name="SafeBrowsingAPIClient.fairUseDelayExpired" id="SafeBrowsingAPIClient.fairUseDelayExpired" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.fairUseDelayExpired" /> <keyword name="SafeBrowsingAPIClient.getFairUseDelayExpirationDateTime" id="SafeBrowsingAPIClient.getFairUseDelayExpirationDateTime" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.getFairUseDelayExpirationDateTime" /> <keyword name="SafeBrowsingAPIClient.getFullHashes" id="SafeBrowsingAPIClient.getFullHashes" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.getFullHashes" /> @@ -13744,6 +13745,7 @@ <keyword name="SafeBrowsingAPIClient.getThreatMessage" id="SafeBrowsingAPIClient.getThreatMessage" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.getThreatMessage" /> <keyword name="SafeBrowsingAPIClient.getThreatType" id="SafeBrowsingAPIClient.getThreatType" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.getThreatType" /> <keyword name="SafeBrowsingAPIClient.getThreatsUpdate" id="SafeBrowsingAPIClient.getThreatsUpdate" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.getThreatsUpdate" /> + <keyword name="SafeBrowsingAPIClient.lookupUrl" id="SafeBrowsingAPIClient.lookupUrl" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.lookupUrl" /> <keyword name="SafeBrowsingAPIClient.setApiKey" id="SafeBrowsingAPIClient.setApiKey" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingAPIClient.html#SafeBrowsingAPIClient.setApiKey" /> <keyword name="SafeBrowsingCache" id="SafeBrowsingCache" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.html#SafeBrowsingCache" /> <keyword name="SafeBrowsingCache (Constructor)" id="SafeBrowsingCache (Constructor)" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.html#SafeBrowsingCache.__init__" /> @@ -13803,6 +13805,7 @@ <keyword name="SafeBrowsingManager (Module)" id="SafeBrowsingManager (Module)" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.html" /> <keyword name="SafeBrowsingManager.__lookupHashes" id="SafeBrowsingManager.__lookupHashes" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.html#SafeBrowsingManager.__lookupHashes" /> <keyword name="SafeBrowsingManager.__setAutoUpdateThreatLists" id="SafeBrowsingManager.__setAutoUpdateThreatLists" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.html#SafeBrowsingManager.__setAutoUpdateThreatLists" /> + <keyword name="SafeBrowsingManager.__setLookupMethod" id="SafeBrowsingManager.__setLookupMethod" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.html#SafeBrowsingManager.__setLookupMethod" /> <keyword name="SafeBrowsingManager.__setPlatforms" id="SafeBrowsingManager.__setPlatforms" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.html#SafeBrowsingManager.__setPlatforms" /> <keyword name="SafeBrowsingManager.__showNotificationMessage" id="SafeBrowsingManager.__showNotificationMessage" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.html#SafeBrowsingManager.__showNotificationMessage" /> <keyword name="SafeBrowsingManager.__syncFullHashes" id="SafeBrowsingManager.__syncFullHashes" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.html#SafeBrowsingManager.__syncFullHashes" /> @@ -13823,6 +13826,7 @@ <keyword name="SafeBrowsingManager.lookupUrl" id="SafeBrowsingManager.lookupUrl" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.html#SafeBrowsingManager.lookupUrl" /> <keyword name="SafeBrowsingManager.showSafeBrowsingDialog" id="SafeBrowsingManager.showSafeBrowsingDialog" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.html#SafeBrowsingManager.showSafeBrowsingDialog" /> <keyword name="SafeBrowsingManager.updateHashPrefixCache" id="SafeBrowsingManager.updateHashPrefixCache" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.html#SafeBrowsingManager.updateHashPrefixCache" /> + <keyword name="SafeBrowsingThreatList (Module)" id="SafeBrowsingThreatList (Module)" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.html" /> <keyword name="SafeBrowsingUrl" id="SafeBrowsingUrl" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingUrl.html#SafeBrowsingUrl" /> <keyword name="SafeBrowsingUrl (Constructor)" id="SafeBrowsingUrl (Constructor)" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingUrl.html#SafeBrowsingUrl.__init__" /> <keyword name="SafeBrowsingUrl (Module)" id="SafeBrowsingUrl (Module)" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingUrl.html" /> @@ -14669,11 +14673,6 @@ <keyword name="StackedWidget.setCurrentIndex" id="StackedWidget.setCurrentIndex" ref="eric6.Plugins.ViewManagerPlugins.Listspace.Listspace.html#StackedWidget.setCurrentIndex" /> <keyword name="StackedWidget.setCurrentWidget" id="StackedWidget.setCurrentWidget" ref="eric6.Plugins.ViewManagerPlugins.Listspace.Listspace.html#StackedWidget.setCurrentWidget" /> <keyword name="StandardReport" id="StandardReport" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StandardReport" /> - <keyword name="StandardReport (Constructor)" id="StandardReport (Constructor)" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StandardReport.__init__" /> - <keyword name="StandardReport.error" id="StandardReport.error" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StandardReport.error" /> - <keyword name="StandardReport.error_args" id="StandardReport.error_args" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StandardReport.error_args" /> - <keyword name="StandardReport.get_file_results" id="StandardReport.get_file_results" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StandardReport.get_file_results" /> - <keyword name="StandardReport.init_file" id="StandardReport.init_file" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StandardReport.init_file" /> <keyword name="StartDialog" id="StartDialog" ref="eric6.Debugger.StartDialog.html#StartDialog" /> <keyword name="StartDialog (Constructor)" id="StartDialog (Constructor)" ref="eric6.Debugger.StartDialog.html#StartDialog.__init__" /> <keyword name="StartDialog (Module)" id="StartDialog (Module)" ref="eric6.Debugger.StartDialog.html" /> @@ -14737,14 +14736,6 @@ <keyword name="StripProjectHelper.initMenu" id="StripProjectHelper.initMenu" ref="eric6.Plugins.VcsPlugins.vcsMercurial.StripExtension.ProjectHelper.html#StripProjectHelper.initMenu" /> <keyword name="StripProjectHelper.menuTitle" id="StripProjectHelper.menuTitle" ref="eric6.Plugins.VcsPlugins.vcsMercurial.StripExtension.ProjectHelper.html#StripProjectHelper.menuTitle" /> <keyword name="StyleGuide" id="StyleGuide" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StyleGuide" /> - <keyword name="StyleGuide (Constructor)" id="StyleGuide (Constructor)" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StyleGuide.__init__" /> - <keyword name="StyleGuide.check_files" id="StyleGuide.check_files" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StyleGuide.check_files" /> - <keyword name="StyleGuide.excluded" id="StyleGuide.excluded" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StyleGuide.excluded" /> - <keyword name="StyleGuide.get_checks" id="StyleGuide.get_checks" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StyleGuide.get_checks" /> - <keyword name="StyleGuide.ignore_code" id="StyleGuide.ignore_code" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StyleGuide.ignore_code" /> - <keyword name="StyleGuide.init_report" id="StyleGuide.init_report" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StyleGuide.init_report" /> - <keyword name="StyleGuide.input_dir" id="StyleGuide.input_dir" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StyleGuide.input_dir" /> - <keyword name="StyleGuide.input_file" id="StyleGuide.input_file" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#StyleGuide.input_file" /> <keyword name="Subversion" id="Subversion" ref="eric6.Plugins.VcsPlugins.vcsPySvn.subversion.html#Subversion" /> <keyword name="Subversion" id="Subversion" ref="eric6.Plugins.VcsPlugins.vcsSubversion.subversion.html#Subversion" /> <keyword name="Subversion (Constructor)" id="Subversion (Constructor)" ref="eric6.Plugins.VcsPlugins.vcsPySvn.subversion.html#Subversion.__init__" /> @@ -16146,11 +16137,11 @@ <keyword name="ThreadExtension.updateThreadList" id="ThreadExtension.updateThreadList" ref="eric6.DebugClients.Python.ThreadExtension.html#ThreadExtension.updateThreadList" /> <keyword name="ThreadWrapper" id="ThreadWrapper" ref="eric6.DebugClients.Python.ThreadExtension.html#ThreadWrapper" /> <keyword name="ThreadWrapper (Constructor)" id="ThreadWrapper (Constructor)" ref="eric6.DebugClients.Python.ThreadExtension.html#ThreadWrapper.__init__" /> - <keyword name="ThreatList" id="ThreatList" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.html#ThreatList" /> - <keyword name="ThreatList (Constructor)" id="ThreatList (Constructor)" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.html#ThreatList.__init__" /> - <keyword name="ThreatList.__repr__" id="ThreatList.__repr__" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.html#ThreatList.__repr__" /> - <keyword name="ThreatList.asTuple" id="ThreatList.asTuple" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.html#ThreatList.asTuple" /> - <keyword name="ThreatList.fromApiEntry" id="ThreatList.fromApiEntry" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingCache.html#ThreatList.fromApiEntry" /> + <keyword name="ThreatList" id="ThreatList" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.html#ThreatList" /> + <keyword name="ThreatList (Constructor)" id="ThreatList (Constructor)" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.html#ThreatList.__init__" /> + <keyword name="ThreatList.__repr__" id="ThreatList.__repr__" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.html#ThreatList.__repr__" /> + <keyword name="ThreatList.asTuple" id="ThreatList.asTuple" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.html#ThreatList.asTuple" /> + <keyword name="ThreatList.fromApiEntry" id="ThreatList.fromApiEntry" ref="eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.html#ThreatList.fromApiEntry" /> <keyword name="TimerWrapper" id="TimerWrapper" ref="eric6.DebugClients.Python.ThreadExtension.html#TimerWrapper" /> <keyword name="TimerWrapper (Constructor)" id="TimerWrapper (Constructor)" ref="eric6.DebugClients.Python.ThreadExtension.html#TimerWrapper.__init__" /> <keyword name="Token" id="Token" ref="eric6.DataViews.CodeMetrics.html#Token" /> @@ -17247,6 +17238,7 @@ <keyword name="ViewManager.cascade" id="ViewManager.cascade" ref="eric6.ViewManager.ViewManager.html#ViewManager.cascade" /> <keyword name="ViewManager.checkAllDirty" id="ViewManager.checkAllDirty" ref="eric6.ViewManager.ViewManager.html#ViewManager.checkAllDirty" /> <keyword name="ViewManager.checkDirty" id="ViewManager.checkDirty" ref="eric6.ViewManager.ViewManager.html#ViewManager.checkDirty" /> + <keyword name="ViewManager.checkFileDirty" id="ViewManager.checkFileDirty" ref="eric6.ViewManager.ViewManager.html#ViewManager.checkFileDirty" /> <keyword name="ViewManager.clearRecent" id="ViewManager.clearRecent" ref="eric6.ViewManager.ViewManager.html#ViewManager.clearRecent" /> <keyword name="ViewManager.cloneEditor" id="ViewManager.cloneEditor" ref="eric6.ViewManager.ViewManager.html#ViewManager.cloneEditor" /> <keyword name="ViewManager.closeAllWindows" id="ViewManager.closeAllWindows" ref="eric6.ViewManager.ViewManager.html#ViewManager.closeAllWindows" /> @@ -17576,6 +17568,7 @@ <keyword name="WebBrowserPage (Module)" id="WebBrowserPage (Module)" ref="eric6.WebBrowser.WebBrowserPage.html" /> <keyword name="WebBrowserPage.__featurePermissionRequested" id="WebBrowserPage.__featurePermissionRequested" ref="eric6.WebBrowser.WebBrowserPage.html#WebBrowserPage.__featurePermissionRequested" /> <keyword name="WebBrowserPage.__fullScreenRequested" id="WebBrowserPage.__fullScreenRequested" ref="eric6.WebBrowser.WebBrowserPage.html#WebBrowserPage.__fullScreenRequested" /> + <keyword name="WebBrowserPage.__loadProgress" id="WebBrowserPage.__loadProgress" ref="eric6.WebBrowser.WebBrowserPage.html#WebBrowserPage.__loadProgress" /> <keyword name="WebBrowserPage.__setupChannelTimeout" id="WebBrowserPage.__setupChannelTimeout" ref="eric6.WebBrowser.WebBrowserPage.html#WebBrowserPage.__setupChannelTimeout" /> <keyword name="WebBrowserPage.__setupWebChannelForUrl" id="WebBrowserPage.__setupWebChannelForUrl" ref="eric6.WebBrowser.WebBrowserPage.html#WebBrowserPage.__setupWebChannelForUrl" /> <keyword name="WebBrowserPage.__urlChanged" id="WebBrowserPage.__urlChanged" ref="eric6.WebBrowser.WebBrowserPage.html#WebBrowserPage.__urlChanged" /> @@ -17663,6 +17656,7 @@ <keyword name="WebBrowserTabWidget.closeAllBrowsers" id="WebBrowserTabWidget.closeAllBrowsers" ref="eric6.WebBrowser.WebBrowserTabWidget.html#WebBrowserTabWidget.closeAllBrowsers" /> <keyword name="WebBrowserTabWidget.closeBrowser" id="WebBrowserTabWidget.closeBrowser" ref="eric6.WebBrowser.WebBrowserTabWidget.html#WebBrowserTabWidget.closeBrowser" /> <keyword name="WebBrowserTabWidget.closeBrowserAt" id="WebBrowserTabWidget.closeBrowserAt" ref="eric6.WebBrowser.WebBrowserTabWidget.html#WebBrowserTabWidget.closeBrowserAt" /> + <keyword name="WebBrowserTabWidget.closeBrowserView" id="WebBrowserTabWidget.closeBrowserView" ref="eric6.WebBrowser.WebBrowserTabWidget.html#WebBrowserTabWidget.closeBrowserView" /> <keyword name="WebBrowserTabWidget.closedTabsManager" id="WebBrowserTabWidget.closedTabsManager" ref="eric6.WebBrowser.WebBrowserTabWidget.html#WebBrowserTabWidget.closedTabsManager" /> <keyword name="WebBrowserTabWidget.currentBrowser" id="WebBrowserTabWidget.currentBrowser" ref="eric6.WebBrowser.WebBrowserTabWidget.html#WebBrowserTabWidget.currentBrowser" /> <keyword name="WebBrowserTabWidget.currentUrlBar" id="WebBrowserTabWidget.currentUrlBar" ref="eric6.WebBrowser.WebBrowserTabWidget.html#WebBrowserTabWidget.currentUrlBar" /> @@ -17680,6 +17674,7 @@ <keyword name="WebBrowserTabWidget.restoreClosedTab" id="WebBrowserTabWidget.restoreClosedTab" ref="eric6.WebBrowser.WebBrowserTabWidget.html#WebBrowserTabWidget.restoreClosedTab" /> <keyword name="WebBrowserTabWidget.shallShutDown" id="WebBrowserTabWidget.shallShutDown" ref="eric6.WebBrowser.WebBrowserTabWidget.html#WebBrowserTabWidget.shallShutDown" /> <keyword name="WebBrowserTabWidget.stackedUrlBar" id="WebBrowserTabWidget.stackedUrlBar" ref="eric6.WebBrowser.WebBrowserTabWidget.html#WebBrowserTabWidget.stackedUrlBar" /> + <keyword name="WebBrowserTabWidget.urlBarForView" id="WebBrowserTabWidget.urlBarForView" ref="eric6.WebBrowser.WebBrowserTabWidget.html#WebBrowserTabWidget.urlBarForView" /> <keyword name="WebBrowserTools (Module)" id="WebBrowserTools (Module)" ref="eric6.WebBrowser.Tools.WebBrowserTools.html" /> <keyword name="WebBrowserView" id="WebBrowserView" ref="eric6.WebBrowser.WebBrowserView.html#WebBrowserView" /> <keyword name="WebBrowserView (Constructor)" id="WebBrowserView (Constructor)" ref="eric6.WebBrowser.WebBrowserView.html#WebBrowserView.__init__" /> @@ -17794,6 +17789,7 @@ <keyword name="WebBrowserView.showEvent" id="WebBrowserView.showEvent" ref="eric6.WebBrowser.WebBrowserView.html#WebBrowserView.showEvent" /> <keyword name="WebBrowserView.source" id="WebBrowserView.source" ref="eric6.WebBrowser.WebBrowserView.html#WebBrowserView.source" /> <keyword name="WebBrowserView.storeSessionData" id="WebBrowserView.storeSessionData" ref="eric6.WebBrowser.WebBrowserView.html#WebBrowserView.storeSessionData" /> + <keyword name="WebBrowserView.tabWidget" id="WebBrowserView.tabWidget" ref="eric6.WebBrowser.WebBrowserView.html#WebBrowserView.tabWidget" /> <keyword name="WebBrowserView.title" id="WebBrowserView.title" ref="eric6.WebBrowser.WebBrowserView.html#WebBrowserView.title" /> <keyword name="WebBrowserView.undo" id="WebBrowserView.undo" ref="eric6.WebBrowser.WebBrowserView.html#WebBrowserView.undo" /> <keyword name="WebBrowserView.unselect" id="WebBrowserView.unselect" ref="eric6.WebBrowser.WebBrowserView.html#WebBrowserView.unselect" /> @@ -17951,6 +17947,8 @@ <keyword name="WebBrowserWindow.bookmarksManager" id="WebBrowserWindow.bookmarksManager" ref="eric6.WebBrowser.WebBrowserWindow.html#WebBrowserWindow.bookmarksManager" /> <keyword name="WebBrowserWindow.browserAt" id="WebBrowserWindow.browserAt" ref="eric6.WebBrowser.WebBrowserWindow.html#WebBrowserWindow.browserAt" /> <keyword name="WebBrowserWindow.browsers" id="WebBrowserWindow.browsers" ref="eric6.WebBrowser.WebBrowserWindow.html#WebBrowserWindow.browsers" /> + <keyword name="WebBrowserWindow.closeBrowser" id="WebBrowserWindow.closeBrowser" ref="eric6.WebBrowser.WebBrowserWindow.html#WebBrowserWindow.closeBrowser" /> + <keyword name="WebBrowserWindow.closeCurrentBrowser" id="WebBrowserWindow.closeCurrentBrowser" ref="eric6.WebBrowser.WebBrowserWindow.html#WebBrowserWindow.closeCurrentBrowser" /> <keyword name="WebBrowserWindow.closeEvent" id="WebBrowserWindow.closeEvent" ref="eric6.WebBrowser.WebBrowserWindow.html#WebBrowserWindow.closeEvent" /> <keyword name="WebBrowserWindow.cookieJar" id="WebBrowserWindow.cookieJar" ref="eric6.WebBrowser.WebBrowserWindow.html#WebBrowserWindow.cookieJar" /> <keyword name="WebBrowserWindow.createPopupMenu" id="WebBrowserWindow.createPopupMenu" ref="eric6.WebBrowser.WebBrowserWindow.html#WebBrowserWindow.createPopupMenu" /> @@ -18316,6 +18314,11 @@ <keyword name="__getMasterPassword" id="__getMasterPassword" ref="eric6.Utilities.crypto.__init__.html#__getMasterPassword" /> <keyword name="__getPygmentsLexer" id="__getPygmentsLexer" ref="eric6.QScintilla.Lexers.__init__.html#__getPygmentsLexer" /> <keyword name="__initChannelModesDict" id="__initChannelModesDict" ref="eric6.Network.IRC.IrcUtilities.html#__initChannelModesDict" /> + <keyword name="__init__" id="__init__" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#__init__" /> + <keyword name="__init___1" id="__init___1" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#__init___1" /> + <keyword name="__init___2" id="__init___2" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#__init___2" /> + <keyword name="__init___3" id="__init___3" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#__init___3" /> + <keyword name="__init___4" id="__init___4" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#__init___4" /> <keyword name="__jsSyntaxCheck" id="__jsSyntaxCheck" ref="eric6.Plugins.CheckerPlugins.SyntaxChecker.jsCheckSyntax.html#__jsSyntaxCheck" /> <keyword name="__messageBox" id="__messageBox" ref="eric6.E5Gui.E5MessageBox.html#__messageBox" /> <keyword name="__pyName" id="__pyName" ref="eric6.Utilities.uic.html#__pyName" /> @@ -18330,6 +18333,7 @@ <keyword name="__showwarning" id="__showwarning" ref="eric6.Utilities.__init__.html#__showwarning" /> <keyword name="__syntaxAndPyflakesCheck" id="__syntaxAndPyflakesCheck" ref="eric6.Plugins.CheckerPlugins.SyntaxChecker.SyntaxCheck.html#__syntaxAndPyflakesCheck" /> <keyword name="_add_check" id="_add_check" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#_add_check" /> + <keyword name="_break_around_binary_operators" id="_break_around_binary_operators" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#_break_around_binary_operators" /> <keyword name="_buildChildrenLists" id="_buildChildrenLists" ref="eric6.Graphics.GraphicsUtilities.html#_buildChildrenLists" /> <keyword name="_encode_base64" id="_encode_base64" ref="eric6.UI.EmailDialog.html#_encode_base64" /> <keyword name="_findDefaultExecutables" id="_findDefaultExecutables" ref="eric6.Plugins.PluginPipInterface.html#_findDefaultExecutables" /> @@ -18338,6 +18342,7 @@ <keyword name="_indent" id="_indent" ref="eric6.Utilities.ClassBrowsers.pyclbr.html#_indent" /> <keyword name="_indent" id="_indent" ref="eric6.Utilities.ModuleParser.html#_indent" /> <keyword name="_initTypeMap" id="_initTypeMap" ref="eric6.DebugClients.Python.DebugVariables.html#_initTypeMap" /> + <keyword name="_is_binary_operator" id="_is_binary_operator" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#_is_binary_operator" /> <keyword name="_is_eol_token" id="_is_eol_token" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#_is_eol_token" /> <keyword name="_is_eol_token_1" id="_is_eol_token_1" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#_is_eol_token_1" /> <keyword name="_main" id="_main" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#_main" /> @@ -18358,11 +18363,18 @@ <keyword name="batchCheck" id="batchCheck" ref="eric6.Plugins.CheckerPlugins.Tabnanny.Tabnanny.html#batchCheck" /> <keyword name="binplistlib (Module)" id="binplistlib (Module)" ref="eric6.Utilities.binplistlib.html" /> <keyword name="blank_lines" id="blank_lines" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#blank_lines" /> - <keyword name="break_around_binary_operator" id="break_around_binary_operator" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#break_around_binary_operator" /> + <keyword name="break_after_binary_operator" id="break_after_binary_operator" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#break_after_binary_operator" /> + <keyword name="break_before_binary_operator" id="break_before_binary_operator" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#break_before_binary_operator" /> + <keyword name="build_tokens_line" id="build_tokens_line" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#build_tokens_line" /> <keyword name="changeRememberedMaster" id="changeRememberedMaster" ref="eric6.Utilities.crypto.__init__.html#changeRememberedMaster" /> <keyword name="check" id="check" ref="eric6.Plugins.CheckerPlugins.Tabnanny.Tabnanny.html#check" /> <keyword name="checkBlacklistedVersions" id="checkBlacklistedVersions" ref="eric6.Globals.__init__.html#checkBlacklistedVersions" /> <keyword name="checkPyside" id="checkPyside" ref="eric6.Utilities.__init__.html#checkPyside" /> + <keyword name="check_all" id="check_all" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#check_all" /> + <keyword name="check_ast" id="check_ast" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#check_ast" /> + <keyword name="check_files" id="check_files" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#check_files" /> + <keyword name="check_logical" id="check_logical" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#check_logical" /> + <keyword name="check_physical" id="check_physical" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#check_physical" /> <keyword name="cleanUp" id="cleanUp" ref="eric6.install-debugclients.html#cleanUp" /> <keyword name="cleanUp" id="cleanUp" ref="eric6.install.html#cleanUp" /> <keyword name="cleanupSource" id="cleanupSource" ref="eric6.cleanupSource.html#cleanupSource" /> @@ -18556,9 +18568,15 @@ <keyword name="eric6_webbrowser (Module)" id="eric6_webbrowser (Module)" ref="eric6.eric6_webbrowser.html" /> <keyword name="eric6config (Module)" id="eric6config (Module)" ref="eric6.eric6config.html" /> <keyword name="eric6dbgstub (Module)" id="eric6dbgstub (Module)" ref="eric6.DebugClients.Python.eric6dbgstub.html" /> + <keyword name="error" id="error" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#error" /> + <keyword name="error_1" id="error_1" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#error_1" /> + <keyword name="error_2" id="error_2" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#error_2" /> + <keyword name="error_args" id="error_args" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#error_args" /> + <keyword name="error_args_1" id="error_args_1" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#error_args_1" /> <keyword name="escape_entities" id="escape_entities" ref="eric6.Utilities.__init__.html#escape_entities" /> <keyword name="escape_uentities" id="escape_uentities" ref="eric6.Utilities.__init__.html#escape_uentities" /> <keyword name="excepthook" id="excepthook" ref="eric6.eric6.html#excepthook" /> + <keyword name="excluded" id="excluded" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#excluded" /> <keyword name="exeDisplayData" id="exeDisplayData" ref="eric6.Plugins.PluginEricapi.html#exeDisplayData" /> <keyword name="exeDisplayData" id="exeDisplayData" ref="eric6.Plugins.PluginVcsGit.html#exeDisplayData" /> <keyword name="exeDisplayData" id="exeDisplayData" ref="eric6.Plugins.PluginVcsMercurial.html#exeDisplayData" /> @@ -18603,6 +18621,7 @@ <keyword name="generatePySideToolPath" id="generatePySideToolPath" ref="eric6.Utilities.__init__.html#generatePySideToolPath" /> <keyword name="generateQtToolName" id="generateQtToolName" ref="eric6.Utilities.__init__.html#generateQtToolName" /> <keyword name="generateVersionInfo" id="generateVersionInfo" ref="eric6.Utilities.__init__.html#generateVersionInfo" /> + <keyword name="generate_tokens" id="generate_tokens" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#generate_tokens" /> <keyword name="getAllImages" id="getAllImages" ref="eric6.WebBrowser.Tools.Scripts.html#getAllImages" /> <keyword name="getAllMetaAttributes" id="getAllMetaAttributes" ref="eric6.WebBrowser.Tools.Scripts.html#getAllMetaAttributes" /> <keyword name="getBasicHelper" id="getBasicHelper" ref="eric6.VCS.__init__.html#getBasicHelper" /> @@ -18751,10 +18770,15 @@ <keyword name="getWebBrowser" id="getWebBrowser" ref="eric6.Preferences.__init__.html#getWebBrowser" /> <keyword name="getWebEngineVersions" id="getWebEngineVersions" ref="eric6.WebBrowser.Tools.WebBrowserTools.html#getWebEngineVersions" /> <keyword name="getWindowsExecutablePath" id="getWindowsExecutablePath" ref="eric6.Utilities.__init__.html#getWindowsExecutablePath" /> + <keyword name="get_checks" id="get_checks" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#get_checks" /> <keyword name="get_class_members" id="get_class_members" ref="eric6.DebugClients.Python.FlexCompleter.html#get_class_members" /> <keyword name="get_coding" id="get_coding" ref="eric6.Utilities.__init__.html#get_coding" /> <keyword name="get_codingBytes" id="get_codingBytes" ref="eric6.Utilities.__init__.html#get_codingBytes" /> + <keyword name="get_count" id="get_count" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#get_count" /> + <keyword name="get_file_results" id="get_file_results" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#get_file_results" /> + <keyword name="get_file_results_1" id="get_file_results_1" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#get_file_results_1" /> <keyword name="get_parser" id="get_parser" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#get_parser" /> + <keyword name="get_statistics" id="get_statistics" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#get_statistics" /> <keyword name="getargvalues" id="getargvalues" ref="eric6.DebugClients.Python.DebugUtilities.html#getargvalues" /> <keyword name="getpass" id="getpass" ref="eric6.DebugClients.Python.getpass.html#getpass" /> <keyword name="getpass (Module)" id="getpass (Module)" ref="eric6.DebugClients.Python.getpass.html" /> @@ -18774,9 +18798,11 @@ <keyword name="html_uencode" id="html_uencode" ref="eric6.Utilities.__init__.html#html_uencode" /> <keyword name="idlclbr (Module)" id="idlclbr (Module)" ref="eric6.Utilities.ClassBrowsers.idlclbr.html" /> <keyword name="ignoreCode" id="ignoreCode" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleChecker.html#ignoreCode" /> + <keyword name="ignore_code" id="ignore_code" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#ignore_code" /> <keyword name="importPreferences" id="importPreferences" ref="eric6.Preferences.__init__.html#importPreferences" /> <keyword name="importShortcuts" id="importShortcuts" ref="eric6.Preferences.Shortcuts.html#importShortcuts" /> <keyword name="imports_on_separate_lines" id="imports_on_separate_lines" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#imports_on_separate_lines" /> + <keyword name="increment_logical_line" id="increment_logical_line" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#increment_logical_line" /> <keyword name="indentation" id="indentation" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#indentation" /> <keyword name="information" id="information" ref="eric6.E5Gui.E5MessageBox.html#information" /> <keyword name="initBatchService" id="initBatchService" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleChecker.html#initBatchService" /> @@ -18796,8 +18822,13 @@ <keyword name="initService" id="initService" ref="eric6.Plugins.CheckerPlugins.SyntaxChecker.SyntaxCheck.html#initService" /> <keyword name="initService" id="initService" ref="eric6.Plugins.CheckerPlugins.SyntaxChecker.jsCheckSyntax.html#initService" /> <keyword name="initService" id="initService" ref="eric6.Plugins.CheckerPlugins.Tabnanny.Tabnanny.html#initService" /> - <keyword name="init_checks_registry" id="init_checks_registry" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#init_checks_registry" /> + <keyword name="init_checker_state" id="init_checker_state" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#init_checker_state" /> + <keyword name="init_file" id="init_file" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#init_file" /> + <keyword name="init_file_1" id="init_file_1" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#init_file_1" /> + <keyword name="init_report" id="init_report" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#init_report" /> <keyword name="initializeResourceSearchPath" id="initializeResourceSearchPath" ref="eric6.Toolbox.Startup.html#initializeResourceSearchPath" /> + <keyword name="input_dir" id="input_dir" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#input_dir" /> + <keyword name="input_file" id="input_file" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#input_file" /> <keyword name="install (Module)" id="install (Module)" ref="eric6.install.html" /> <keyword name="install-debugclients (Module)" id="install-debugclients (Module)" ref="eric6.install-debugclients.html" /> <keyword name="install-i18n (Module)" id="install-i18n (Module)" ref="eric6.install-i18n.html" /> @@ -18820,7 +18851,6 @@ <keyword name="isValidIPv4Address" id="isValidIPv4Address" ref="eric6.E5Network.__init__.html#isValidIPv4Address" /> <keyword name="isValidIPv6Address" id="isValidIPv6Address" ref="eric6.E5Network.__init__.html#isValidIPv6Address" /> <keyword name="isWindowsPlatform" id="isWindowsPlatform" ref="eric6.Globals.__init__.html#isWindowsPlatform" /> - <keyword name="is_binary_operator" id="is_binary_operator" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#is_binary_operator" /> <keyword name="is_stream_binary_plist" id="is_stream_binary_plist" ref="eric6.Utilities.binplistlib.html#is_stream_binary_plist" /> <keyword name="is_string_literal" id="is_string_literal" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#is_string_literal" /> <keyword name="isinpath" id="isinpath" ref="eric6.Utilities.__init__.html#isinpath" /> @@ -18835,6 +18865,7 @@ <keyword name="loadTranslatorForLocale" id="loadTranslatorForLocale" ref="eric6.Toolbox.Startup.html#loadTranslatorForLocale" /> <keyword name="loadTranslators" id="loadTranslators" ref="eric6.Toolbox.Startup.html#loadTranslators" /> <keyword name="load_sourceAsStr" id="load_sourceAsStr" ref="eric6.Globals.compatibility_fixes.html#load_sourceAsStr" /> + <keyword name="lru_cache" id="lru_cache" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#lru_cache" /> <keyword name="main" id="main" ref="eric6.Plugins.VcsPlugins.vcsMercurial.HisteditExtension.HgHisteditEditor.html#main" /> <keyword name="main" id="main" ref="eric6.Plugins.WizardPlugins.QRegularExpressionWizard.QRegularExpressionWizardServer.html#main" /> <keyword name="main" id="main" ref="eric6.cleanupSource.html#main" /> @@ -18871,6 +18902,7 @@ <keyword name="main" id="main" ref="eric6.uninstall.html#main" /> <keyword name="makeAppInfo" id="makeAppInfo" ref="eric6.Globals.AppInfo.html#makeAppInfo" /> <keyword name="maximum_line_length" id="maximum_line_length" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#maximum_line_length" /> + <keyword name="maybe_check_physical" id="maybe_check_physical" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#maybe_check_physical" /> <keyword name="mccabe (Module)" id="mccabe (Module)" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.mccabe.html" /> <keyword name="messageHandler" id="messageHandler" ref="eric6.E5Gui.E5ErrorMessage.html#messageHandler" /> <keyword name="messageHandlerInstalled" id="messageHandlerInstalled" ref="eric6.E5Gui.E5ErrorMessage.html#messageHandlerInstalled" /> @@ -18901,6 +18933,7 @@ <keyword name="parse_udiff" id="parse_udiff" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#parse_udiff" /> <keyword name="patch_modpython (Module)" id="patch_modpython (Module)" ref="eric6.patch_modpython.html" /> <keyword name="pbkdf2" id="pbkdf2" ref="eric6.Utilities.crypto.py3PBKDF2.html#pbkdf2" /> + <keyword name="pipInstall" id="pipInstall" ref="eric6.install.html#pipInstall" /> <keyword name="pixmapFromByteArray" id="pixmapFromByteArray" ref="eric6.WebBrowser.Tools.WebBrowserTools.html#pixmapFromByteArray" /> <keyword name="pixmapToByteArray" id="pixmapToByteArray" ref="eric6.WebBrowser.Tools.WebBrowserTools.html#pixmapToByteArray" /> <keyword name="pixmapToDataUrl" id="pixmapToDataUrl" ref="eric6.WebBrowser.Tools.WebBrowserTools.html#pixmapToDataUrl" /> @@ -18921,6 +18954,8 @@ <keyword name="previewPix" id="previewPix" ref="eric6.Plugins.PluginVmListspace.html#previewPix" /> <keyword name="previewPix" id="previewPix" ref="eric6.Plugins.PluginVmTabview.html#previewPix" /> <keyword name="printFile" id="printFile" ref="eric6.WebBrowser.Tools.FilePrinter.html#printFile" /> + <keyword name="print_benchmark" id="print_benchmark" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#print_benchmark" /> + <keyword name="print_statistics" id="print_statistics" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#print_statistics" /> <keyword name="printerr" id="printerr" ref="eric6.DebugClients.Python.DebugBase.html#printerr" /> <keyword name="process_options" id="process_options" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#process_options" /> <keyword name="process_tokens" id="process_tokens" ref="eric6.Plugins.CheckerPlugins.Tabnanny.Tabnanny.html#process_tokens" /> @@ -18939,8 +18974,10 @@ <keyword name="py3PBKDF2 (Module)" id="py3PBKDF2 (Module)" ref="eric6.Utilities.crypto.py3PBKDF2.html" /> <keyword name="pyclbr (Module)" id="pyclbr (Module)" ref="eric6.Utilities.ClassBrowsers.pyclbr.html" /> <keyword name="pycodestyle (Module)" id="pycodestyle (Module)" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html" /> + <keyword name="python_3000_async_await_keywords" id="python_3000_async_await_keywords" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#python_3000_async_await_keywords" /> <keyword name="python_3000_backticks" id="python_3000_backticks" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#python_3000_backticks" /> <keyword name="python_3000_has_key" id="python_3000_has_key" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#python_3000_has_key" /> + <keyword name="python_3000_invalid_escape_sequence" id="python_3000_invalid_escape_sequence" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#python_3000_invalid_escape_sequence" /> <keyword name="python_3000_not_equal" id="python_3000_not_equal" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#python_3000_not_equal" /> <keyword name="python_3000_raise_comma" id="python_3000_raise_comma" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#python_3000_raise_comma" /> <keyword name="qVersionTuple" id="qVersionTuple" ref="eric6.Globals.__init__.html#qVersionTuple" /> @@ -18961,6 +18998,7 @@ <keyword name="readStringFromStream" id="readStringFromStream" ref="eric6.Utilities.__init__.html#readStringFromStream" /> <keyword name="readToolGroups" id="readToolGroups" ref="eric6.Preferences.__init__.html#readToolGroups" /> <keyword name="read_config" id="read_config" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#read_config" /> + <keyword name="readline" id="readline" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#readline" /> <keyword name="readlines" id="readlines" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#readlines" /> <keyword name="readlines_1" id="readlines_1" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#readlines_1" /> <keyword name="readmodule" id="readmodule" ref="eric6.Utilities.ClassBrowsers.__init__.html#readmodule" /> @@ -18984,10 +19022,12 @@ <keyword name="removeProjectBrowserFlags" id="removeProjectBrowserFlags" ref="eric6.Preferences.__init__.html#removeProjectBrowserFlags" /> <keyword name="renderTabPreview" id="renderTabPreview" ref="eric6.Helpviewer.HelpSnap.html#renderTabPreview" /> <keyword name="renderTabPreview" id="renderTabPreview" ref="eric6.WebBrowser.WebBrowserSnap.html#renderTabPreview" /> + <keyword name="report_invalid_syntax" id="report_invalid_syntax" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#report_invalid_syntax" /> <keyword name="resetLayout" id="resetLayout" ref="eric6.Preferences.__init__.html#resetLayout" /> <keyword name="resetParsedModule" id="resetParsedModule" ref="eric6.Utilities.ModuleParser.html#resetParsedModule" /> <keyword name="resetParsedModules" id="resetParsedModules" ref="eric6.Utilities.ModuleParser.html#resetParsedModules" /> <keyword name="retryAbort" id="retryAbort" ref="eric6.E5Gui.E5MessageBox.html#retryAbort" /> + <keyword name="run_check" id="run_check" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#run_check" /> <keyword name="runcall" id="runcall" ref="eric6.DebugClients.Python.eric6dbgstub.html#runcall" /> <keyword name="rxExecute" id="rxExecute" ref="eric6.Plugins.WizardPlugins.QRegularExpressionWizard.QRegularExpressionWizardServer.html#rxExecute" /> <keyword name="rxValidate" id="rxValidate" ref="eric6.Plugins.WizardPlugins.QRegularExpressionWizard.QRegularExpressionWizardServer.html#rxValidate" /> @@ -19060,10 +19100,13 @@ <keyword name="shutilCopy" id="shutilCopy" ref="eric6.install.html#shutilCopy" /> <keyword name="simpleAppStartup" id="simpleAppStartup" ref="eric6.Toolbox.Startup.html#simpleAppStartup" /> <keyword name="sort" id="sort" ref="eric6.Graphics.GraphicsUtilities.html#sort" /> + <keyword name="speedString" id="speedString" ref="eric6.WebBrowser.Download.DownloadUtilities.html#speedString" /> <keyword name="splitPath" id="splitPath" ref="eric6.Utilities.__init__.html#splitPath" /> + <keyword name="start" id="start" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#start" /> <keyword name="startDebugger" id="startDebugger" ref="eric6.DebugClients.Python.eric6dbgstub.html#startDebugger" /> <keyword name="startswithPath" id="startswithPath" ref="eric6.Utilities.__init__.html#startswithPath" /> <keyword name="stdin_get_value" id="stdin_get_value" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#stdin_get_value" /> + <keyword name="stop" id="stop" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#stop" /> <keyword name="strGroup" id="strGroup" ref="eric6.Globals.__init__.html#strGroup" /> <keyword name="strToQByteArray" id="strToQByteArray" ref="eric6.Globals.__init__.html#strToQByteArray" /> <keyword name="strToQByteArray" id="strToQByteArray" ref="eric6.Plugins.VcsPlugins.vcsGit.GitUtilities.html#strToQByteArray" /> @@ -19909,6 +19952,7 @@ <file>eric6.Project.DebuggerPropertiesDialog.html</file> <file>eric6.Project.FiletypeAssociationDialog.html</file> <file>eric6.Project.LexerAssociationDialog.html</file> + <file>eric6.Project.MakePropertiesDialog.html</file> <file>eric6.Project.NewDialogClassDialog.html</file> <file>eric6.Project.NewPythonPackageDialog.html</file> <file>eric6.Project.Project.html</file> @@ -20214,6 +20258,7 @@ <file>eric6.WebBrowser.SafeBrowsing.SafeBrowsingInfoWidget.html</file> <file>eric6.WebBrowser.SafeBrowsing.SafeBrowsingLabel.html</file> <file>eric6.WebBrowser.SafeBrowsing.SafeBrowsingManager.html</file> + <file>eric6.WebBrowser.SafeBrowsing.SafeBrowsingThreatList.html</file> <file>eric6.WebBrowser.SafeBrowsing.SafeBrowsingUrl.html</file> <file>eric6.WebBrowser.SafeBrowsing.SafeBrowsingUtilities.html</file> <file>eric6.WebBrowser.SafeBrowsing.__init__.html</file>
--- a/Documentation/Source/eric6.Debugger.DebugUI.html Mon Apr 02 12:04:56 2018 +0200 +++ b/Documentation/Source/eric6.Debugger.DebugUI.html Tue May 01 12:03:52 2018 +0200 @@ -67,6 +67,10 @@ <dd> emitted after the execution was interrupted by an exception and acknowledged by the user +</dd><dt>executeMake()</dt> +<dd> +emitted if a project specific make run should be + performed </dd><dt>resetUI()</dt> <dd> emitted to reset the UI
--- a/Documentation/Source/eric6.E5XML.Config.html Mon Apr 02 12:04:56 2018 +0200 +++ b/Documentation/Source/eric6.E5XML.Config.html Tue May 01 12:03:52 2018 +0200 @@ -25,7 +25,7 @@ </p> <h3>Global Attributes</h3> <table> -<tr><td>debuggerPropertiesFileFormatVersion</td></tr><tr><td>dictionariesListFileFormatVersion</td></tr><tr><td>highlightingStylesFileFormatVersion</td></tr><tr><td>multiProjectFileFormatVersion</td></tr><tr><td>pluginRepositoryFileFormatVersion</td></tr><tr><td>projectFileFormatVersion</td></tr><tr><td>projectFileFormatVersionAlt</td></tr><tr><td>sessionFileFormatVersion</td></tr><tr><td>shortcutsFileFormatVersion</td></tr><tr><td>tasksFileFormatVersion</td></tr><tr><td>templatesFileFormatVersion</td></tr><tr><td>userProjectFileFormatVersion</td></tr> +<tr><td>debuggerPropertiesFileFormatVersion</td></tr><tr><td>dictionariesListFileFormatVersion</td></tr><tr><td>highlightingStylesFileFormatVersion</td></tr><tr><td>multiProjectFileFormatVersion</td></tr><tr><td>pluginRepositoryFileFormatVersion</td></tr><tr><td>projectFileFormatVersion</td></tr><tr><td>projectFileFormatVersionAlt</td></tr><tr><td>projectFileFormatVersionProto</td></tr><tr><td>sessionFileFormatVersion</td></tr><tr><td>shortcutsFileFormatVersion</td></tr><tr><td>tasksFileFormatVersion</td></tr><tr><td>templatesFileFormatVersion</td></tr><tr><td>userProjectFileFormatVersion</td></tr> </table> <h3>Classes</h3> <table>
--- a/Documentation/Source/eric6.PluginManager.PluginManager.html Mon Apr 02 12:04:56 2018 +0200 +++ b/Documentation/Source/eric6.PluginManager.PluginManager.html Tue May 01 12:03:52 2018 +0200 @@ -219,7 +219,7 @@ </table> <a NAME="PluginManager.__init__" ID="PluginManager.__init__"></a> <h4>PluginManager (Constructor)</h4> -<b>PluginManager</b>(<i>parent=None, doLoadPlugins=True, develPlugin=None</i>) +<b>PluginManager</b>(<i>parent=None, disabledPlugins=None, doLoadPlugins=True, develPlugin=None</i>) <p> Constructor </p><p> @@ -230,17 +230,21 @@ is the user plugin directory located inside the .eric6 directory of the users home directory. </p><dl> -<dt><i>parent</i></dt> +<dt><i>parent</i> (QObject)</dt> <dd> -reference to the parent object (QObject) -</dd><dt><i>doLoadPlugins=</i></dt> +reference to the parent object +</dd><dt><i>disabledPlugins</i> (list of str)</dt> <dd> -flag indicating, that plugins should - be loaded (boolean) -</dd><dt><i>develPlugin=</i></dt> +list of plug-ins that have been disabled via + the command line parameters '--disable-plugin=' +</dd><dt><i>doLoadPlugins</i> (bool)</dt> <dd> -filename of a plugin to be loaded for - development (string) +flag indicating, that plug-ins should + be loaded +</dd><dt><i>develPlugin</i> (str)</dt> +<dd> +filename of a plug-in to be loaded for + development </dd> </dl><dl> <dt>Raises <b>PluginModulesError</b>:</dt>
--- a/Documentation/Source/eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleChecker.html Mon Apr 02 12:04:56 2018 +0200 +++ b/Documentation/Source/eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleChecker.html Tue May 01 12:03:52 2018 +0200 @@ -44,7 +44,7 @@ <td>Module function to check code style for a batch of files.</td> </tr><tr> <td><a href="#codeStyleCheck">codeStyleCheck</a></td> -<td>Do the code style check and/ or fix found errors.</td> +<td>Do the code style check and/or fix found errors.</td> </tr><tr> <td><a href="#extractLineFlags">extractLineFlags</a></td> <td>Function to extract flags starting and ending with '__' from a line comment.</td> @@ -139,28 +139,33 @@ Private module function to perform the code style check and/or fix found errors. </p><dl> -<dt><i>filename</i></dt> +<dt><i>filename</i> (str)</dt> <dd> -source filename (string) -</dd><dt><i>source</i></dt> +source filename +</dd><dt><i>source</i> (str)</dt> <dd> -string containing the code to check (string) -</dd><dt><i>args</i></dt> +string containing the code to check +</dd><dt><i>args</i> (list of (str, str, bool, str, str, bool, int, list of (int, int),)</dt> <dd> arguments used by the codeStyleCheck function (list of - excludeMessages (str), includeMessages (str), repeatMessages - (bool), fixCodes (str), noFixCodes (str), fixIssues (bool), - maxLineLength (int), hangClosing (bool), docType (str), dictionary - with arguments for the code complexity checker (dict), dictionary - with arguments for the miscellaneous checker (dict), errors (list - of str), eol (str), encoding (str), backup (bool)) + excludeMessages, includeMessages, repeatMessages, fixCodes, + noFixCodes, fixIssues, maxLineLength, blankLines, hangClosing, + docType, codeComplexityArgs, miscellaneousArgs, errors, eol, + encoding, backup) + bool, str, dict, dict, list of str, str, str, bool) </dd> </dl><dl> <dt>Returns:</dt> <dd> -tuple of statistics (dict) and results (tuple for each found - violation of style (tuple of lineno (int), position (int), text (str), - ignored (bool), fixed (bool), autofixing (bool), fixedMsg (str))) +tuple of statistics (dict) and list of results (tuple for each + found violation of style (lineno, position, text, ignored, fixed, + autofixing, fixedMsg)) +</dd> +</dl><dl> +<dt>Return Type:</dt> +<dd> +tuple of (dict, list of tuples of (int, int, str, bool, bool, bool, + str)) </dd> </dl> <div align="right"><a href="#top">Up</a></div> @@ -194,28 +199,35 @@ <h2>codeStyleCheck</h2> <b>codeStyleCheck</b>(<i>filename, source, args</i>) <p> - Do the code style check and/ or fix found errors. + Do the code style check and/or fix found errors. </p><dl> -<dt><i>filename</i></dt> +<dt><i>filename</i> (str)</dt> <dd> -source filename (string) -</dd><dt><i>source</i></dt> +source filename +</dd><dt><i>source</i> (str)</dt> <dd> -string containing the code to check (string) -</dd><dt><i>args</i></dt> +string containing the code to check +</dd><dt><i>args</i> (list of (str, str, bool, str, str, bool, int, list of (int, int),)</dt> <dd> arguments used by the codeStyleCheck function (list of - excludeMessages (str), includeMessages (str), repeatMessages - (bool), fixCodes (str), noFixCodes (str), fixIssues (bool), - maxLineLength (int), hangClosing (bool), docType (str), errors - (list of str), eol (str), encoding (str), backup (bool)) + excludeMessages, includeMessages, repeatMessages, fixCodes, + noFixCodes, fixIssues, maxLineLength, blankLines, hangClosing, + docType, codeComplexityArgs, miscellaneousArgs, errors, eol, + encoding, backup) + bool, str, dict, dict, list of str, str, str, bool) </dd> </dl><dl> <dt>Returns:</dt> <dd> -tuple of stats (dict) and results (tuple for each found violation - of style (tuple of lineno (int), position (int), text (str), ignored - (bool), fixed (bool), autofixing (bool), fixedMsg (str))) +tuple of statistics (dict) and list of results (tuple for each + found violation of style (lineno, position, text, ignored, fixed, + autofixing, fixedMsg)) +</dd> +</dl><dl> +<dt>Return Type:</dt> +<dd> +tuple of (dict, list of tuples of (int, int, str, bool, bool, bool, + str)) </dd> </dl> <div align="right"><a href="#top">Up</a></div>
--- a/Documentation/Source/eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html Mon Apr 02 12:04:56 2018 +0200 +++ b/Documentation/Source/eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html Tue May 01 12:03:52 2018 +0200 @@ -75,6 +75,9 @@ <td><a href="#CodeStyleFixer.__findLogical">__findLogical</a></td> <td>Private method to extract the index of all the starts and ends of lines.</td> </tr><tr> +<td><a href="#CodeStyleFixer.__fixBlankLinesBefore">__fixBlankLinesBefore</a></td> +<td>Private method to fix the need for blank lines before class, function and method definitions.</td> +</tr><tr> <td><a href="#CodeStyleFixer.__fixD111">__fixD111</a></td> <td>Private method to fix docstring enclosed in wrong quotes.</td> </tr><tr> @@ -150,15 +153,6 @@ <td><a href="#CodeStyleFixer.__fixE261">__fixE261</a></td> <td>Private method to fix whitespace before or after inline comment.</td> </tr><tr> -<td><a href="#CodeStyleFixer.__fixE301">__fixE301</a></td> -<td>Private method to fix the need for one blank line.</td> -</tr><tr> -<td><a href="#CodeStyleFixer.__fixE302">__fixE302</a></td> -<td>Private method to fix the need for two blank lines.</td> -</tr><tr> -<td><a href="#CodeStyleFixer.__fixE303">__fixE303</a></td> -<td>Private method to fix superfluous blank lines.</td> -</tr><tr> <td><a href="#CodeStyleFixer.__fixE304">__fixE304</a></td> <td>Private method to fix superfluous blank lines after a function decorator.</td> </tr><tr> @@ -238,38 +232,42 @@ </table> <a NAME="CodeStyleFixer.__init__" ID="CodeStyleFixer.__init__"></a> <h4>CodeStyleFixer (Constructor)</h4> -<b>CodeStyleFixer</b>(<i>filename, sourceLines, fixCodes, noFixCodes, maxLineLength, inPlace, eol, backup=False</i>) +<b>CodeStyleFixer</b>(<i>filename, sourceLines, fixCodes, noFixCodes, maxLineLength, blankLines, inPlace, eol, backup=False</i>) <p> Constructor </p><dl> -<dt><i>filename</i></dt> +<dt><i>filename</i> (str)</dt> <dd> -name of the file to be fixed (string) -</dd><dt><i>sourceLines</i></dt> +name of the file to be fixed +</dd><dt><i>sourceLines</i> (list of str)</dt> <dd> list of source lines including eol marker - (list of string) -</dd><dt><i>fixCodes</i></dt> +</dd><dt><i>fixCodes</i> (str)</dt> <dd> list of codes to be fixed as a comma separated - string (string) -</dd><dt><i>noFixCodes</i></dt> + string +</dd><dt><i>noFixCodes</i> (str)</dt> <dd> list of codes not to be fixed as a comma - separated string (string) -</dd><dt><i>maxLineLength</i></dt> + separated string +</dd><dt><i>maxLineLength</i> (int)</dt> <dd> -maximum allowed line length (integer) -</dd><dt><i>inPlace</i></dt> +maximum allowed line length +</dd><dt><i>blankLines</i> (tuple of (int, int))</dt> <dd> -flag indicating to modify the file in place (boolean) -</dd><dt><i>eol</i></dt> +tuple containg the number of blank lines before + a top level class or function and before a method or nested class + or function +</dd><dt><i>inPlace</i> (bool)</dt> <dd> -end of line character(s) (string) -</dd><dt><i>backup</i></dt> +flag indicating to modify the file in place +</dd><dt><i>eol</i> (str)</dt> +<dd> +end of line character(s) +</dd><dt><i>backup</i> (bool)</dt> <dd> flag indicating to create a backup before fixing - anything (boolean) + anything </dd> </dl><a NAME="CodeStyleFixer.__codeMatch" ID="CodeStyleFixer.__codeMatch"></a> <h4>CodeStyleFixer.__codeMatch</h4> @@ -298,6 +296,36 @@ tuple containing two lists of integer with start and end tuples of lines </dd> +</dl><a NAME="CodeStyleFixer.__fixBlankLinesBefore" ID="CodeStyleFixer.__fixBlankLinesBefore"></a> +<h4>CodeStyleFixer.__fixBlankLinesBefore</h4> +<b>__fixBlankLinesBefore</b>(<i>code, line, pos, apply=False</i>) +<p> + Private method to fix the need for blank lines before class, function + and method definitions. +</p><p> + Codes: E301, E302, E303, E305, E306, E307, E308 +</p><dl> +<dt><i>code</i></dt> +<dd> +code of the issue (string) +</dd><dt><i>line</i></dt> +<dd> +line number of the issue (integer) +</dd><dt><i>pos</i></dt> +<dd> +position inside line (integer) +</dd><dt><i>apply=</i></dt> +<dd> +flag indicating, that the fix should be applied + (boolean) +</dd> +</dl><dl> +<dt>Returns:</dt> +<dd> +value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) +</dd> </dl><a NAME="CodeStyleFixer.__fixD111" ID="CodeStyleFixer.__fixD111"></a> <h4>CodeStyleFixer.__fixD111</h4> <b>__fixD111</b>(<i>code, line, pos</i>) @@ -998,93 +1026,6 @@ a message for the fix (string) and an ID for a deferred fix (integer) </dd> -</dl><a NAME="CodeStyleFixer.__fixE301" ID="CodeStyleFixer.__fixE301"></a> -<h4>CodeStyleFixer.__fixE301</h4> -<b>__fixE301</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix the need for one blank line. -</p><p> - Codes: E301 -</p><dl> -<dt><i>code</i></dt> -<dd> -code of the issue (string) -</dd><dt><i>line</i></dt> -<dd> -line number of the issue (integer) -</dd><dt><i>pos</i></dt> -<dd> -position inside line (integer) -</dd><dt><i>apply=</i></dt> -<dd> -flag indicating, that the fix should be applied - (boolean) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) -</dd> -</dl><a NAME="CodeStyleFixer.__fixE302" ID="CodeStyleFixer.__fixE302"></a> -<h4>CodeStyleFixer.__fixE302</h4> -<b>__fixE302</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix the need for two blank lines. -</p><p> - Codes: E302 -</p><dl> -<dt><i>code</i></dt> -<dd> -code of the issue (string) -</dd><dt><i>line</i></dt> -<dd> -line number of the issue (integer) -</dd><dt><i>pos</i></dt> -<dd> -position inside line (integer) -</dd><dt><i>apply=</i></dt> -<dd> -flag indicating, that the fix should be applied - (boolean) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) -</dd> -</dl><a NAME="CodeStyleFixer.__fixE303" ID="CodeStyleFixer.__fixE303"></a> -<h4>CodeStyleFixer.__fixE303</h4> -<b>__fixE303</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix superfluous blank lines. -</p><p> - Codes: E303 -</p><dl> -<dt><i>code</i></dt> -<dd> -code of the issue (string) -</dd><dt><i>line</i></dt> -<dd> -line number of the issue (integer) -</dd><dt><i>pos</i></dt> -<dd> -position inside line (integer) -</dd><dt><i>apply=</i></dt> -<dd> -flag indicating, that the fix should be applied - (boolean) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) -</dd> </dl><a NAME="CodeStyleFixer.__fixE304" ID="CodeStyleFixer.__fixE304"></a> <h4>CodeStyleFixer.__fixE304</h4> <b>__fixE304</b>(<i>code, line, pos, apply=False</i>)
--- a/Documentation/Source/eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html Mon Apr 02 12:04:56 2018 +0200 +++ b/Documentation/Source/eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html Tue May 01 12:03:52 2018 +0200 @@ -23,7 +23,7 @@ <h3>Global Attributes</h3> <table> -<tr><td>ARITHMETIC_OP</td></tr><tr><td>BENCHMARK_KEYS</td></tr><tr><td>COMMENT_WITH_NL</td></tr><tr><td>COMPARE_NEGATIVE_REGEX</td></tr><tr><td>COMPARE_SINGLETON_REGEX</td></tr><tr><td>COMPARE_TYPE_REGEX</td></tr><tr><td>DEFAULT_EXCLUDE</td></tr><tr><td>DEFAULT_IGNORE</td></tr><tr><td>DOCSTRING_REGEX</td></tr><tr><td>DUNDER_REGEX</td></tr><tr><td>ERRORCODE_REGEX</td></tr><tr><td>EXTRANEOUS_WHITESPACE_REGEX</td></tr><tr><td>HUNK_REGEX</td></tr><tr><td>INDENT_REGEX</td></tr><tr><td>KEYWORDS</td></tr><tr><td>KEYWORD_REGEX</td></tr><tr><td>LAMBDA_REGEX</td></tr><tr><td>MAX_LINE_LENGTH</td></tr><tr><td>NEWLINE</td></tr><tr><td>OPERATOR_REGEX</td></tr><tr><td>PROJECT_CONFIG</td></tr><tr><td>PyCF_ONLY_AST</td></tr><tr><td>RAISE_COMMA_REGEX</td></tr><tr><td>REPORT_FORMAT</td></tr><tr><td>RERAISE_COMMA_REGEX</td></tr><tr><td>SINGLETONS</td></tr><tr><td>SKIP_COMMENTS</td></tr><tr><td>SKIP_TOKENS</td></tr><tr><td>STARTSWITH_DEF_REGEX</td></tr><tr><td>STARTSWITH_INDENT_STATEMENT_REGEX</td></tr><tr><td>STARTSWITH_TOP_LEVEL_REGEX</td></tr><tr><td>TESTSUITE_PATH</td></tr><tr><td>UNARY_OPERATORS</td></tr><tr><td>WHITESPACE</td></tr><tr><td>WHITESPACE_AFTER_COMMA_REGEX</td></tr><tr><td>WS_NEEDED_OPERATORS</td></tr><tr><td>WS_OPTIONAL_OPERATORS</td></tr><tr><td>__version__</td></tr><tr><td>_checks</td></tr><tr><td>noqa</td></tr> +<tr><td>ARITHMETIC_OP</td></tr><tr><td>BENCHMARK_KEYS</td></tr><tr><td>BLANK_LINES_CONFIG</td></tr><tr><td>COMMENT_WITH_NL</td></tr><tr><td>COMPARE_NEGATIVE_REGEX</td></tr><tr><td>COMPARE_SINGLETON_REGEX</td></tr><tr><td>COMPARE_TYPE_REGEX</td></tr><tr><td>DEFAULT_EXCLUDE</td></tr><tr><td>DEFAULT_IGNORE</td></tr><tr><td>DOCSTRING_REGEX</td></tr><tr><td>DUNDER_REGEX</td></tr><tr><td>ERRORCODE_REGEX</td></tr><tr><td>EXTRANEOUS_WHITESPACE_REGEX</td></tr><tr><td>HUNK_REGEX</td></tr><tr><td>INDENT_REGEX</td></tr><tr><td>KEYWORDS</td></tr><tr><td>KEYWORD_REGEX</td></tr><tr><td>LAMBDA_REGEX</td></tr><tr><td>MAX_LINE_LENGTH</td></tr><tr><td>NEWLINE</td></tr><tr><td>OPERATOR_REGEX</td></tr><tr><td>PROJECT_CONFIG</td></tr><tr><td>PyCF_ONLY_AST</td></tr><tr><td>RAISE_COMMA_REGEX</td></tr><tr><td>REPORT_FORMAT</td></tr><tr><td>RERAISE_COMMA_REGEX</td></tr><tr><td>SINGLETONS</td></tr><tr><td>SKIP_COMMENTS</td></tr><tr><td>SKIP_TOKENS</td></tr><tr><td>STARTSWITH_DEF_REGEX</td></tr><tr><td>STARTSWITH_INDENT_STATEMENT_REGEX</td></tr><tr><td>STARTSWITH_TOP_LEVEL_REGEX</td></tr><tr><td>TESTSUITE_PATH</td></tr><tr><td>UNARY_OPERATORS</td></tr><tr><td>WHITESPACE</td></tr><tr><td>WHITESPACE_AFTER_COMMA_REGEX</td></tr><tr><td>WS_NEEDED_OPERATORS</td></tr><tr><td>WS_OPTIONAL_OPERATORS</td></tr><tr><td>__version__</td></tr><tr><td>_checks</td></tr><tr><td>noqa</td></tr> </table> <h3>Classes</h3> <table> @@ -50,12 +50,33 @@ <h3>Functions</h3> <table> <tr> +<td><a href="#__init__">__init__</a></td> +<td></td> +</tr><tr> +<td><a href="#__init___1">__init__</a></td> +<td></td> +</tr><tr> +<td><a href="#__init___2">__init__</a></td> +<td></td> +</tr><tr> +<td><a href="#__init___3">__init__</a></td> +<td></td> +</tr><tr> +<td><a href="#__init___4">__init__</a></td> +<td></td> +</tr><tr> <td><a href="#_add_check">_add_check</a></td> <td></td> </tr><tr> +<td><a href="#_break_around_binary_operators">_break_around_binary_operators</a></td> +<td>Private function to reduce duplication.</td> +</tr><tr> <td><a href="#_get_parameters">_get_parameters</a></td> <td></td> </tr><tr> +<td><a href="#_is_binary_operator">_is_binary_operator</a></td> +<td></td> +</tr><tr> <td><a href="#_is_eol_token">_is_eol_token</a></td> <td></td> </tr><tr> @@ -72,14 +93,35 @@ <td>Never use the characters 'l', 'O', or 'I' as variable names.</td> </tr><tr> <td><a href="#bare_except">bare_except</a></td> -<td>When catching exceptions, mention specific exceptions whenever possible.</td> +<td>When catching exceptions, mention specific exceptions when possible.</td> </tr><tr> <td><a href="#blank_lines">blank_lines</a></td> <td>Separate top-level function and class definitions with two blank lines.</td> </tr><tr> -<td><a href="#break_around_binary_operator">break_around_binary_operator</a></td> +<td><a href="#break_after_binary_operator">break_after_binary_operator</a></td> +<td>Avoid breaks after binary operators.</td> +</tr><tr> +<td><a href="#break_before_binary_operator">break_before_binary_operator</a></td> <td>Avoid breaks before binary operators.</td> </tr><tr> +<td><a href="#build_tokens_line">build_tokens_line</a></td> +<td>Build a logical line from tokens.</td> +</tr><tr> +<td><a href="#check_all">check_all</a></td> +<td>Run all checks on the input file.</td> +</tr><tr> +<td><a href="#check_ast">check_ast</a></td> +<td>Build the file's AST and run all AST checks.</td> +</tr><tr> +<td><a href="#check_files">check_files</a></td> +<td>Run all checks on the paths.</td> +</tr><tr> +<td><a href="#check_logical">check_logical</a></td> +<td>Build a line from tokens and run all logical checks on it.</td> +</tr><tr> +<td><a href="#check_physical">check_physical</a></td> +<td>Run all physical checks on a raw input line.</td> +</tr><tr> <td><a href="#comparison_negative">comparison_negative</a></td> <td>Negative comparison should be done using "not in" and "is not".</td> </tr><tr> @@ -95,6 +137,24 @@ <td><a href="#continued_indentation">continued_indentation</a></td> <td>Continuation lines indentation.</td> </tr><tr> +<td><a href="#error">error</a></td> +<td>Report an error, according to options.</td> +</tr><tr> +<td><a href="#error_1">error</a></td> +<td>Report an error, according to options.</td> +</tr><tr> +<td><a href="#error_2">error</a></td> +<td></td> +</tr><tr> +<td><a href="#error_args">error_args</a></td> +<td>Report an error, according to options.</td> +</tr><tr> +<td><a href="#error_args_1">error_args</a></td> +<td>Report an error, according to options.</td> +</tr><tr> +<td><a href="#excluded">excluded</a></td> +<td>Check if the file should be excluded.</td> +</tr><tr> <td><a href="#expand_indent">expand_indent</a></td> <td>Return the amount of indentation.</td> </tr><tr> @@ -107,27 +167,69 @@ <td><a href="#filename_match">filename_match</a></td> <td>Check if patterns contains a pattern that matches filename.</td> </tr><tr> +<td><a href="#generate_tokens">generate_tokens</a></td> +<td>Tokenize the file, run physical line checks and yield tokens.</td> +</tr><tr> +<td><a href="#get_checks">get_checks</a></td> +<td>Get all the checks for this category.</td> +</tr><tr> +<td><a href="#get_count">get_count</a></td> +<td>Return the total count of errors and warnings.</td> +</tr><tr> +<td><a href="#get_file_results">get_file_results</a></td> +<td>Return the count of errors and warnings for this file.</td> +</tr><tr> +<td><a href="#get_file_results_1">get_file_results</a></td> +<td>Print the result and return the overall count for this file.</td> +</tr><tr> <td><a href="#get_parser">get_parser</a></td> <td>Create the parser for the program.</td> </tr><tr> +<td><a href="#get_statistics">get_statistics</a></td> +<td>Get statistics for message codes that start with the prefix.</td> +</tr><tr> +<td><a href="#ignore_code">ignore_code</a></td> +<td>Check if the error code should be ignored.</td> +</tr><tr> <td><a href="#imports_on_separate_lines">imports_on_separate_lines</a></td> <td>Place imports on separate lines.</td> </tr><tr> +<td><a href="#increment_logical_line">increment_logical_line</a></td> +<td>Signal a new logical line.</td> +</tr><tr> <td><a href="#indentation">indentation</a></td> <td>Use 4 spaces per indentation level.</td> </tr><tr> -<td><a href="#init_checks_registry">init_checks_registry</a></td> -<td>Register all globally visible functions.</td> +<td><a href="#init_checker_state">init_checker_state</a></td> +<td>Prepare custom state for the specific checker plugin.</td> +</tr><tr> +<td><a href="#init_file">init_file</a></td> +<td>Signal a new file.</td> +</tr><tr> +<td><a href="#init_file_1">init_file</a></td> +<td>Signal a new file.</td> </tr><tr> -<td><a href="#is_binary_operator">is_binary_operator</a></td> -<td></td> +<td><a href="#init_report">init_report</a></td> +<td>Initialize the report instance.</td> +</tr><tr> +<td><a href="#input_dir">input_dir</a></td> +<td>Check all files in this directory and all subdirectories.</td> +</tr><tr> +<td><a href="#input_file">input_file</a></td> +<td>Run all checks on a Python source file.</td> </tr><tr> <td><a href="#is_string_literal">is_string_literal</a></td> <td></td> </tr><tr> +<td><a href="#lru_cache">lru_cache</a></td> +<td></td> +</tr><tr> <td><a href="#maximum_line_length">maximum_line_length</a></td> <td>Limit all lines to a maximum of 79 characters.</td> </tr><tr> +<td><a href="#maybe_check_physical">maybe_check_physical</a></td> +<td>If appropriate (based on token), check current physical line(s).</td> +</tr><tr> <td><a href="#missing_whitespace">missing_whitespace</a></td> <td>Each comma, semicolon or colon should be followed by whitespace.</td> </tr><tr> @@ -149,15 +251,27 @@ <td><a href="#parse_udiff">parse_udiff</a></td> <td>Return a dictionary of matching lines.</td> </tr><tr> +<td><a href="#print_benchmark">print_benchmark</a></td> +<td>Print benchmark numbers.</td> +</tr><tr> +<td><a href="#print_statistics">print_statistics</a></td> +<td>Print overall statistics (number of errors and warnings).</td> +</tr><tr> <td><a href="#process_options">process_options</a></td> <td>Process options passed either via arglist or via command line args.</td> </tr><tr> +<td><a href="#python_3000_async_await_keywords">python_3000_async_await_keywords</a></td> +<td>'async' and 'await' are reserved keywords starting with Python 3.7</td> +</tr><tr> <td><a href="#python_3000_backticks">python_3000_backticks</a></td> <td>Use repr() instead of backticks in Python 3.</td> </tr><tr> <td><a href="#python_3000_has_key">python_3000_has_key</a></td> <td>The {}.has_key() method is removed in Python 3: use the 'in' operator.</td> </tr><tr> +<td><a href="#python_3000_invalid_escape_sequence">python_3000_invalid_escape_sequence</a></td> +<td>Invalid escape sequences are deprecated in Python 3.6.</td> +</tr><tr> <td><a href="#python_3000_not_equal">python_3000_not_equal</a></td> <td>New code should always use != instead of <>.</td> </tr><tr> @@ -167,6 +281,9 @@ <td><a href="#read_config">read_config</a></td> <td>Read and parse configurations.</td> </tr><tr> +<td><a href="#readline">readline</a></td> +<td>Get the next line from the input buffer.</td> +</tr><tr> <td><a href="#readlines">readlines</a></td> <td>Read the source code.</td> </tr><tr> @@ -176,9 +293,21 @@ <td><a href="#register_check">register_check</a></td> <td>Register a new check object.</td> </tr><tr> +<td><a href="#report_invalid_syntax">report_invalid_syntax</a></td> +<td>Check if the syntax is valid.</td> +</tr><tr> +<td><a href="#run_check">run_check</a></td> +<td>Run a check plugin.</td> +</tr><tr> +<td><a href="#start">start</a></td> +<td>Start the timer.</td> +</tr><tr> <td><a href="#stdin_get_value">stdin_get_value</a></td> <td>Read the value from stdin.</td> </tr><tr> +<td><a href="#stop">stop</a></td> +<td>Stop the timer.</td> +</tr><tr> <td><a href="#tabs_obsolete">tabs_obsolete</a></td> <td>For new projects, spaces-only are strongly recommended over tabs.</td> </tr><tr> @@ -231,112 +360,13 @@ </table> <h3>Methods</h3> <table> -<tr> -<td><a href="#BaseReport.__init__">BaseReport</a></td> -<td></td> -</tr><tr> -<td><a href="#BaseReport.error">error</a></td> -<td>Report an error, according to options.</td> -</tr><tr> -<td><a href="#BaseReport.error_args">error_args</a></td> -<td>Report an error, according to options.</td> -</tr><tr> -<td><a href="#BaseReport.get_count">get_count</a></td> -<td>Return the total count of errors and warnings.</td> -</tr><tr> -<td><a href="#BaseReport.get_file_results">get_file_results</a></td> -<td>Return the count of errors and warnings for this file.</td> -</tr><tr> -<td><a href="#BaseReport.get_statistics">get_statistics</a></td> -<td>Get statistics for message codes that start with the prefix.</td> -</tr><tr> -<td><a href="#BaseReport.increment_logical_line">increment_logical_line</a></td> -<td>Signal a new logical line.</td> -</tr><tr> -<td><a href="#BaseReport.init_file">init_file</a></td> -<td>Signal a new file.</td> -</tr><tr> -<td><a href="#BaseReport.print_benchmark">print_benchmark</a></td> -<td>Print benchmark numbers.</td> -</tr><tr> -<td><a href="#BaseReport.print_statistics">print_statistics</a></td> -<td>Print overall statistics (number of errors and warnings).</td> -</tr><tr> -<td><a href="#BaseReport.start">start</a></td> -<td>Start the timer.</td> -</tr><tr> -<td><a href="#BaseReport.stop">stop</a></td> -<td>Stop the timer.</td> -</tr> +<tr><td>None</td></tr> </table> <h3>Static Methods</h3> <table> <tr><td>None</td></tr> </table> -<a NAME="BaseReport.__init__" ID="BaseReport.__init__"></a> -<h4>BaseReport (Constructor)</h4> -<b>BaseReport</b>(<i>options</i>) -<a NAME="BaseReport.error" ID="BaseReport.error"></a> -<h4>BaseReport.error</h4> -<b>error</b>(<i>line_number, offset, text, check</i>) -<p> -Report an error, according to options. -</p><a NAME="BaseReport.error_args" ID="BaseReport.error_args"></a> -<h4>BaseReport.error_args</h4> -<b>error_args</b>(<i>line_number, offset, text, check, *args</i>) -<p> -Report an error, according to options. -</p><a NAME="BaseReport.get_count" ID="BaseReport.get_count"></a> -<h4>BaseReport.get_count</h4> -<b>get_count</b>(<i>prefix=''</i>) -<p> -Return the total count of errors and warnings. -</p><a NAME="BaseReport.get_file_results" ID="BaseReport.get_file_results"></a> -<h4>BaseReport.get_file_results</h4> -<b>get_file_results</b>(<i></i>) -<p> -Return the count of errors and warnings for this file. -</p><a NAME="BaseReport.get_statistics" ID="BaseReport.get_statistics"></a> -<h4>BaseReport.get_statistics</h4> -<b>get_statistics</b>(<i>prefix=''</i>) -<p> -Get statistics for message codes that start with the prefix. -</p><p> - prefix='' matches all errors and warnings - prefix='E' matches all errors - prefix='W' matches all warnings - prefix='E4' matches all errors that have to do with imports -</p><a NAME="BaseReport.increment_logical_line" ID="BaseReport.increment_logical_line"></a> -<h4>BaseReport.increment_logical_line</h4> -<b>increment_logical_line</b>(<i></i>) -<p> -Signal a new logical line. -</p><a NAME="BaseReport.init_file" ID="BaseReport.init_file"></a> -<h4>BaseReport.init_file</h4> -<b>init_file</b>(<i>filename, lines, expected, line_offset</i>) -<p> -Signal a new file. -</p><a NAME="BaseReport.print_benchmark" ID="BaseReport.print_benchmark"></a> -<h4>BaseReport.print_benchmark</h4> -<b>print_benchmark</b>(<i></i>) -<p> -Print benchmark numbers. -</p><a NAME="BaseReport.print_statistics" ID="BaseReport.print_statistics"></a> -<h4>BaseReport.print_statistics</h4> -<b>print_statistics</b>(<i>prefix=''</i>) -<p> -Print overall statistics (number of errors and warnings). -</p><a NAME="BaseReport.start" ID="BaseReport.start"></a> -<h4>BaseReport.start</h4> -<b>start</b>(<i></i>) -<p> -Start the timer. -</p><a NAME="BaseReport.stop" ID="BaseReport.stop"></a> -<h4>BaseReport.stop</h4> -<b>stop</b>(<i></i>) -<p> -Stop the timer. -</p> + <div align="right"><a href="#top">Up</a></div> <hr /><hr /> <a NAME="Checker" ID="Checker"></a> @@ -356,107 +386,13 @@ </table> <h3>Methods</h3> <table> -<tr> -<td><a href="#Checker.__init__">Checker</a></td> -<td></td> -</tr><tr> -<td><a href="#Checker.build_tokens_line">build_tokens_line</a></td> -<td>Build a logical line from tokens.</td> -</tr><tr> -<td><a href="#Checker.check_all">check_all</a></td> -<td>Run all checks on the input file.</td> -</tr><tr> -<td><a href="#Checker.check_ast">check_ast</a></td> -<td>Build the file's AST and run all AST checks.</td> -</tr><tr> -<td><a href="#Checker.check_logical">check_logical</a></td> -<td>Build a line from tokens and run all logical checks on it.</td> -</tr><tr> -<td><a href="#Checker.check_physical">check_physical</a></td> -<td>Run all physical checks on a raw input line.</td> -</tr><tr> -<td><a href="#Checker.generate_tokens">generate_tokens</a></td> -<td>Tokenize the file, run physical line checks and yield tokens.</td> -</tr><tr> -<td><a href="#Checker.init_checker_state">init_checker_state</a></td> -<td>Prepare custom state for the specific checker plugin.</td> -</tr><tr> -<td><a href="#Checker.maybe_check_physical">maybe_check_physical</a></td> -<td>If appropriate (based on token), check current physical line(s).</td> -</tr><tr> -<td><a href="#Checker.readline">readline</a></td> -<td>Get the next line from the input buffer.</td> -</tr><tr> -<td><a href="#Checker.report_invalid_syntax">report_invalid_syntax</a></td> -<td>Check if the syntax is valid.</td> -</tr><tr> -<td><a href="#Checker.run_check">run_check</a></td> -<td>Run a check plugin.</td> -</tr> +<tr><td>None</td></tr> </table> <h3>Static Methods</h3> <table> <tr><td>None</td></tr> </table> -<a NAME="Checker.__init__" ID="Checker.__init__"></a> -<h4>Checker (Constructor)</h4> -<b>Checker</b>(<i>filename=None, lines=None, options=None, report=None, **kwargs</i>) -<a NAME="Checker.build_tokens_line" ID="Checker.build_tokens_line"></a> -<h4>Checker.build_tokens_line</h4> -<b>build_tokens_line</b>(<i></i>) -<p> -Build a logical line from tokens. -</p><a NAME="Checker.check_all" ID="Checker.check_all"></a> -<h4>Checker.check_all</h4> -<b>check_all</b>(<i>expected=None, line_offset=0</i>) -<p> -Run all checks on the input file. -</p><a NAME="Checker.check_ast" ID="Checker.check_ast"></a> -<h4>Checker.check_ast</h4> -<b>check_ast</b>(<i></i>) -<p> -Build the file's AST and run all AST checks. -</p><a NAME="Checker.check_logical" ID="Checker.check_logical"></a> -<h4>Checker.check_logical</h4> -<b>check_logical</b>(<i></i>) -<p> -Build a line from tokens and run all logical checks on it. -</p><a NAME="Checker.check_physical" ID="Checker.check_physical"></a> -<h4>Checker.check_physical</h4> -<b>check_physical</b>(<i>line</i>) -<p> -Run all physical checks on a raw input line. -</p><a NAME="Checker.generate_tokens" ID="Checker.generate_tokens"></a> -<h4>Checker.generate_tokens</h4> -<b>generate_tokens</b>(<i></i>) -<p> -Tokenize the file, run physical line checks and yield tokens. -</p><a NAME="Checker.init_checker_state" ID="Checker.init_checker_state"></a> -<h4>Checker.init_checker_state</h4> -<b>init_checker_state</b>(<i>name, argument_names</i>) -<p> -Prepare custom state for the specific checker plugin. -</p><a NAME="Checker.maybe_check_physical" ID="Checker.maybe_check_physical"></a> -<h4>Checker.maybe_check_physical</h4> -<b>maybe_check_physical</b>(<i>token</i>) -<p> -If appropriate (based on token), check current physical line(s). -</p><a NAME="Checker.readline" ID="Checker.readline"></a> -<h4>Checker.readline</h4> -<b>readline</b>(<i></i>) -<p> -Get the next line from the input buffer. -</p><a NAME="Checker.report_invalid_syntax" ID="Checker.report_invalid_syntax"></a> -<h4>Checker.report_invalid_syntax</h4> -<b>report_invalid_syntax</b>(<i></i>) -<p> -Check if the syntax is valid. -</p><a NAME="Checker.run_check" ID="Checker.run_check"></a> -<h4>Checker.run_check</h4> -<b>run_check</b>(<i>check, argument_names</i>) -<p> -Run a check plugin. -</p> + <div align="right"><a href="#top">Up</a></div> <hr /><hr /> <a NAME="DiffReport" ID="DiffReport"></a> @@ -476,24 +412,12 @@ </table> <h3>Methods</h3> <table> -<tr> -<td><a href="#DiffReport.__init__">DiffReport</a></td> -<td></td> -</tr><tr> -<td><a href="#DiffReport.error">error</a></td> -<td></td> -</tr> +<tr><td>None</td></tr> </table> <h3>Static Methods</h3> <table> <tr><td>None</td></tr> </table> -<a NAME="DiffReport.__init__" ID="DiffReport.__init__"></a> -<h4>DiffReport (Constructor)</h4> -<b>DiffReport</b>(<i>options</i>) -<a NAME="DiffReport.error" ID="DiffReport.error"></a> -<h4>DiffReport.error</h4> -<b>error</b>(<i>line_number, offset, text, check</i>) <div align="right"><a href="#top">Up</a></div> <hr /><hr /> @@ -540,51 +464,13 @@ </table> <h3>Methods</h3> <table> -<tr> -<td><a href="#StandardReport.__init__">StandardReport</a></td> -<td></td> -</tr><tr> -<td><a href="#StandardReport.error">error</a></td> -<td>Report an error, according to options.</td> -</tr><tr> -<td><a href="#StandardReport.error_args">error_args</a></td> -<td>Report an error, according to options.</td> -</tr><tr> -<td><a href="#StandardReport.get_file_results">get_file_results</a></td> -<td>Print the result and return the overall count for this file.</td> -</tr><tr> -<td><a href="#StandardReport.init_file">init_file</a></td> -<td>Signal a new file.</td> -</tr> +<tr><td>None</td></tr> </table> <h3>Static Methods</h3> <table> <tr><td>None</td></tr> </table> -<a NAME="StandardReport.__init__" ID="StandardReport.__init__"></a> -<h4>StandardReport (Constructor)</h4> -<b>StandardReport</b>(<i>options</i>) -<a NAME="StandardReport.error" ID="StandardReport.error"></a> -<h4>StandardReport.error</h4> -<b>error</b>(<i>line_number, offset, text, check</i>) -<p> -Report an error, according to options. -</p><a NAME="StandardReport.error_args" ID="StandardReport.error_args"></a> -<h4>StandardReport.error_args</h4> -<b>error_args</b>(<i>line_number, offset, code, check, *args</i>) -<p> -Report an error, according to options. -</p><a NAME="StandardReport.get_file_results" ID="StandardReport.get_file_results"></a> -<h4>StandardReport.get_file_results</h4> -<b>get_file_results</b>(<i></i>) -<p> -Print the result and return the overall count for this file. -</p><a NAME="StandardReport.init_file" ID="StandardReport.init_file"></a> -<h4>StandardReport.init_file</h4> -<b>init_file</b>(<i>filename, lines, expected, line_offset</i>) -<p> -Signal a new file. -</p> + <div align="right"><a href="#top">Up</a></div> <hr /><hr /> <a NAME="StyleGuide" ID="StyleGuide"></a> @@ -604,84 +490,43 @@ </table> <h3>Methods</h3> <table> -<tr> -<td><a href="#StyleGuide.__init__">StyleGuide</a></td> -<td></td> -</tr><tr> -<td><a href="#StyleGuide.check_files">check_files</a></td> -<td>Run all checks on the paths.</td> -</tr><tr> -<td><a href="#StyleGuide.excluded">excluded</a></td> -<td>Check if the file should be excluded.</td> -</tr><tr> -<td><a href="#StyleGuide.get_checks">get_checks</a></td> -<td>Get all the checks for this category.</td> -</tr><tr> -<td><a href="#StyleGuide.ignore_code">ignore_code</a></td> -<td>Check if the error code should be ignored.</td> -</tr><tr> -<td><a href="#StyleGuide.init_report">init_report</a></td> -<td>Initialize the report instance.</td> -</tr><tr> -<td><a href="#StyleGuide.input_dir">input_dir</a></td> -<td>Check all files in this directory and all subdirectories.</td> -</tr><tr> -<td><a href="#StyleGuide.input_file">input_file</a></td> -<td>Run all checks on a Python source file.</td> -</tr> +<tr><td>None</td></tr> </table> <h3>Static Methods</h3> <table> <tr><td>None</td></tr> </table> -<a NAME="StyleGuide.__init__" ID="StyleGuide.__init__"></a> -<h4>StyleGuide (Constructor)</h4> -<b>StyleGuide</b>(<i>*args, **kwargs</i>) -<a NAME="StyleGuide.check_files" ID="StyleGuide.check_files"></a> -<h4>StyleGuide.check_files</h4> -<b>check_files</b>(<i>paths=None</i>) -<p> -Run all checks on the paths. -</p><a NAME="StyleGuide.excluded" ID="StyleGuide.excluded"></a> -<h4>StyleGuide.excluded</h4> -<b>excluded</b>(<i>filename, parent=None</i>) -<p> -Check if the file should be excluded. -</p><p> - Check if 'options.exclude' contains a pattern that matches filename. -</p><a NAME="StyleGuide.get_checks" ID="StyleGuide.get_checks"></a> -<h4>StyleGuide.get_checks</h4> -<b>get_checks</b>(<i>argument_name</i>) -<p> -Get all the checks for this category. -</p><p> - Find all globally visible functions where the first argument name - starts with argument_name and which contain selected tests. -</p><a NAME="StyleGuide.ignore_code" ID="StyleGuide.ignore_code"></a> -<h4>StyleGuide.ignore_code</h4> -<b>ignore_code</b>(<i>code</i>) -<p> -Check if the error code should be ignored. -</p><p> - If 'options.select' contains a prefix of the error code, - return False. Else, if 'options.ignore' contains a prefix of - the error code, return True. -</p><a NAME="StyleGuide.init_report" ID="StyleGuide.init_report"></a> -<h4>StyleGuide.init_report</h4> -<b>init_report</b>(<i>reporter=None</i>) -<p> -Initialize the report instance. -</p><a NAME="StyleGuide.input_dir" ID="StyleGuide.input_dir"></a> -<h4>StyleGuide.input_dir</h4> -<b>input_dir</b>(<i>dirname</i>) -<p> -Check all files in this directory and all subdirectories. -</p><a NAME="StyleGuide.input_file" ID="StyleGuide.input_file"></a> -<h4>StyleGuide.input_file</h4> -<b>input_file</b>(<i>filename, lines=None, expected=None, line_offset=0</i>) -<p> -Run all checks on a Python source file. -</p> + +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="__init__" ID="__init__"></a> +<h2>__init__</h2> +<b>__init__</b>(<i>self, filename=None, lines=None, options=None, report=None, **kwargs</i>) + +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="__init___1" ID="__init___1"></a> +<h2>__init__</h2> +<b>__init__</b>(<i>self, options</i>) + +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="__init___2" ID="__init___2"></a> +<h2>__init__</h2> +<b>__init__</b>(<i>self, options</i>) + +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="__init___3" ID="__init___3"></a> +<h2>__init__</h2> +<b>__init__</b>(<i>self, options</i>) + +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="__init___4" ID="__init___4"></a> +<h2>__init__</h2> +<b>__init__</b>(<i>self, *args, **kwargs</i>) + <div align="right"><a href="#top">Up</a></div> <hr /><hr /> <a NAME="_add_check" ID="_add_check"></a> @@ -690,12 +535,30 @@ <div align="right"><a href="#top">Up</a></div> <hr /><hr /> +<a NAME="_break_around_binary_operators" ID="_break_around_binary_operators"></a> +<h2>_break_around_binary_operators</h2> +<b>_break_around_binary_operators</b>(<i>tokens</i>) +<p> +Private function to reduce duplication. +</p><p> + This factors out the shared details between + :func:`break_before_binary_operator` and + :func:`break_after_binary_operator`. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> <a NAME="_get_parameters" ID="_get_parameters"></a> <h2>_get_parameters</h2> <b>_get_parameters</b>(<i>function</i>) <div align="right"><a href="#top">Up</a></div> <hr /><hr /> +<a NAME="_is_binary_operator" ID="_is_binary_operator"></a> +<h2>_is_binary_operator</h2> +<b>_is_binary_operator</b>(<i>token_type, text</i>) + +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> <a NAME="_is_eol_token" ID="_is_eol_token"></a> <h2>_is_eol_token</h2> <b>_is_eol_token</b>(<i>token</i>) @@ -766,7 +629,7 @@ <h2>bare_except</h2> <b>bare_except</b>(<i>logical_line, noqa</i>) <p> -When catching exceptions, mention specific exceptions whenever possible. +When catching exceptions, mention specific exceptions when possible. </p><p> Okay: except Exception: Okay: except BaseException: @@ -798,16 +661,43 @@ E302: def a():\n pass\n\ndef b(n):\n pass E302: def a():\n pass\n\nasync def b(n):\n pass E303: def a():\n pass\n\n\n\ndef b(n):\n pass - E303: def a():\n\n\n\n pass E304: @decorator\n\ndef a():\n pass E305: def a():\n pass\na() E306: def a():\n def b():\n pass\n def c():\n pass + E307: def a():\n def b():\n pass\n\n\n def c():\n pass + E308: def a():\n\n\n\n pass </p> <div align="right"><a href="#top">Up</a></div> <hr /><hr /> -<a NAME="break_around_binary_operator" ID="break_around_binary_operator"></a> -<h2>break_around_binary_operator</h2> -<b>break_around_binary_operator</b>(<i>logical_line, tokens</i>) +<a NAME="break_after_binary_operator" ID="break_after_binary_operator"></a> +<h2>break_after_binary_operator</h2> +<b>break_after_binary_operator</b>(<i>logical_line, tokens</i>) +<p> + Avoid breaks after binary operators. +</p><p> + The preferred place to break around a binary operator is before the + operator, not after it. +</p><p> + W504: (width == 0 +\n height == 0) + W504: (width == 0 and\n height == 0) + W504: var = (1 &\n ~2) +</p><p> + Okay: foo(\n -x) + Okay: foo(x\n []) + Okay: x = '''\n''' + '' + Okay: x = '' + '''\n''' + Okay: foo(x,\n -y) + Okay: foo(x, # comment\n -y) +</p><p> + The following should be W504 but unary_context is tricky with these + Okay: var = (1 /\n -2) + Okay: var = (1 +\n -1 +\n -2) +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="break_before_binary_operator" ID="break_before_binary_operator"></a> +<h2>break_before_binary_operator</h2> +<b>break_before_binary_operator</b>(<i>logical_line, tokens</i>) <p> Avoid breaks before binary operators. </p><p> @@ -816,16 +706,63 @@ </p><p> W503: (width == 0\n + height == 0) W503: (width == 0\n and height == 0) + W503: var = (1\n & ~2) + W503: var = (1\n / -2) + W503: var = (1\n + -1\n + -2) </p><p> - Okay: (width == 0 +\n height == 0) Okay: foo(\n -x) Okay: foo(x\n []) Okay: x = '''\n''' + '' Okay: foo(x,\n -y) Okay: foo(x, # comment\n -y) - Okay: var = (1 &\n ~2) - Okay: var = (1 /\n -2) - Okay: var = (1 +\n -1 +\n -2) +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="build_tokens_line" ID="build_tokens_line"></a> +<h2>build_tokens_line</h2> +<b>build_tokens_line</b>(<i>self</i>) +<p> +Build a logical line from tokens. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="check_all" ID="check_all"></a> +<h2>check_all</h2> +<b>check_all</b>(<i>self, expected=None, line_offset=0</i>) +<p> +Run all checks on the input file. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="check_ast" ID="check_ast"></a> +<h2>check_ast</h2> +<b>check_ast</b>(<i>self</i>) +<p> +Build the file's AST and run all AST checks. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="check_files" ID="check_files"></a> +<h2>check_files</h2> +<b>check_files</b>(<i>self, paths=None</i>) +<p> +Run all checks on the paths. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="check_logical" ID="check_logical"></a> +<h2>check_logical</h2> +<b>check_logical</b>(<i>self</i>) +<p> +Build a line from tokens and run all logical checks on it. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="check_physical" ID="check_physical"></a> +<h2>check_physical</h2> +<b>check_physical</b>(<i>self, line</i>) +<p> +Run all physical checks on a raw input line. </p> <div align="right"><a href="#top">Up</a></div> <hr /><hr /> @@ -953,6 +890,54 @@ </p> <div align="right"><a href="#top">Up</a></div> <hr /><hr /> +<a NAME="error" ID="error"></a> +<h2>error</h2> +<b>error</b>(<i>self, line_number, offset, text, check</i>) +<p> +Report an error, according to options. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="error_1" ID="error_1"></a> +<h2>error</h2> +<b>error</b>(<i>self, line_number, offset, text, check</i>) +<p> +Report an error, according to options. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="error_2" ID="error_2"></a> +<h2>error</h2> +<b>error</b>(<i>self, line_number, offset, text, check</i>) + +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="error_args" ID="error_args"></a> +<h2>error_args</h2> +<b>error_args</b>(<i>self, line_number, offset, text, check, *args</i>) +<p> +Report an error, according to options. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="error_args_1" ID="error_args_1"></a> +<h2>error_args</h2> +<b>error_args</b>(<i>self, line_number, offset, code, check, *args</i>) +<p> +Report an error, according to options. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="excluded" ID="excluded"></a> +<h2>excluded</h2> +<b>excluded</b>(<i>self, filename, parent=None</i>) +<p> +Check if the file should be excluded. +</p><p> + Check if 'options.exclude' contains a pattern that matches filename. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> <a NAME="expand_indent" ID="expand_indent"></a> <h2>expand_indent</h2> <b>expand_indent</b>(<i>line</i>) @@ -1027,6 +1012,49 @@ </p> <div align="right"><a href="#top">Up</a></div> <hr /><hr /> +<a NAME="generate_tokens" ID="generate_tokens"></a> +<h2>generate_tokens</h2> +<b>generate_tokens</b>(<i>self</i>) +<p> +Tokenize the file, run physical line checks and yield tokens. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="get_checks" ID="get_checks"></a> +<h2>get_checks</h2> +<b>get_checks</b>(<i>self, argument_name</i>) +<p> +Get all the checks for this category. +</p><p> + Find all globally visible functions where the first argument name + starts with argument_name and which contain selected tests. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="get_count" ID="get_count"></a> +<h2>get_count</h2> +<b>get_count</b>(<i>self, prefix=''</i>) +<p> +Return the total count of errors and warnings. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="get_file_results" ID="get_file_results"></a> +<h2>get_file_results</h2> +<b>get_file_results</b>(<i>self</i>) +<p> +Return the count of errors and warnings for this file. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> +<a NAME="get_file_results_1" ID="get_file_results_1"></a> +<h2>get_file_results</h2> +<b>get_file_results</b>(<i>self</i>) +<p> +Print the result and return the overall count for this file. +</p> +<div align="right"><a href="#top">Up</a></div> +<hr /><hr /> <a NAME="get_parser" ID="get_parser"></a> <h2>get_parser</h2> <b>get_parser</b>(<i>prog='pycodestyle', version=__version__</i>) @@ -1035,6 +1063,31 @@ </p> <div align="right"><a href="#top">Up</a></div> <hr /><hr /> +<a NAME="get_statistics" ID="get_statistics"></a> +<