Tue, 01 Oct 2013 18:31:05 +0200
Continued changing the names of the various code style checkers to make them more appropriate to the broadened scope.
--- a/Documentation/Source/eric5.Plugins.CheckerPlugins.Pep8.Pep8Fixer.html Tue Oct 01 18:22:33 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2078 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric5.Plugins.CheckerPlugins.Pep8.Pep8Fixer</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric5.Plugins.CheckerPlugins.Pep8.Pep8Fixer</h1> -<p> -Module implementing a class to fix certain code style issues. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>Pep8FixableIssues</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#Pep8Fixer">Pep8Fixer</a></td> -<td>Class implementing a fixer for certain code style issues.</td> -</tr><tr> -<td><a href="#Pep8IndentationWrapper">Pep8IndentationWrapper</a></td> -<td>Class used by fixers dealing with indentation.</td> -</tr><tr> -<td><a href="#Pep8LineShortener">Pep8LineShortener</a></td> -<td>Class used to shorten lines to a given maximum of characters.</td> -</tr><tr> -<td><a href="#Pep8Reindenter">Pep8Reindenter</a></td> -<td>Class to reindent badly-indented code to uniformly use four-space indentation.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="Pep8Fixer" ID="Pep8Fixer"></a> -<h2>Pep8Fixer</h2> -<p> - Class implementing a fixer for certain code style issues. -</p> -<h3>Derived from</h3> -QObject -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#Pep8Fixer.__init__">Pep8Fixer</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#Pep8Fixer.__codeMatch">__codeMatch</a></td> -<td>Private method to check, if the code should be fixed.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__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="#Pep8Fixer.__fixD111">__fixD111</a></td> -<td>Private method to fix docstring enclosed in wrong quotes.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixD112">__fixD112</a></td> -<td>Private method to fix docstring 'r' or 'u' in leading quotes.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixD121">__fixD121</a></td> -<td>Private method to fix a single line docstring on multiple lines.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixD131">__fixD131</a></td> -<td>Private method to fix a docstring summary not ending with a period.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixD141">__fixD141</a></td> -<td>Private method to fix a function/method docstring preceded by a blank line.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixD142">__fixD142</a></td> -<td>Private method to fix a class docstring not preceded by a blank line.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixD143">__fixD143</a></td> -<td>Private method to fix a class docstring not followed by a blank line.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixD144">__fixD144</a></td> -<td>Private method to fix a docstring summary not followed by a blank line.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixD145">__fixD145</a></td> -<td>Private method to fix the last paragraph of a multi-line docstring not followed by a blank line.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixD221">__fixD221</a></td> -<td>Private method to fix leading and trailing quotes of docstring not on separate lines.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixD242">__fixD242</a></td> -<td>Private method to fix a class or function/method docstring preceded by a blank line.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixD243">__fixD243</a></td> -<td>Private method to fix a class or function/method docstring followed by a blank line.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixD247">__fixD247</a></td> -<td>Private method to fix a last paragraph of a docstring followed by a blank line.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE101">__fixE101</a></td> -<td>Private method to fix obsolete tab usage and indentation errors.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE121">__fixE121</a></td> -<td>Private method to fix the indentation of continuation lines and closing brackets.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE122">__fixE122</a></td> -<td>Private method to fix a missing indentation of continuation lines.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE123">__fixE123</a></td> -<td>Private method to fix the indentation of a closing bracket lines.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE125">__fixE125</a></td> -<td>Private method to fix the indentation of continuation lines not distinguishable from next logical line.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE126">__fixE126</a></td> -<td>Private method to fix over-indented/under-indented hanging indentation.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE127">__fixE127</a></td> -<td>Private method to fix over/under indented lines.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE201">__fixE201</a></td> -<td>Private method to fix extraneous whitespace.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE221">__fixE221</a></td> -<td>Private method to fix extraneous whitespace around operator or keyword.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE231">__fixE231</a></td> -<td>Private method to fix missing whitespace after ',;:'.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE251">__fixE251</a></td> -<td>Private method to fix extraneous whitespace around keyword and default parameter equals.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE261">__fixE261</a></td> -<td>Private method to fix whitespace before or after inline comment.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE301">__fixE301</a></td> -<td>Private method to fix the need for one blank line.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE302">__fixE302</a></td> -<td>Private method to fix the need for two blank lines.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE303">__fixE303</a></td> -<td>Private method to fix superfluous blank lines.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE304">__fixE304</a></td> -<td>Private method to fix superfluous blank lines after a function decorator.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE401">__fixE401</a></td> -<td>Private method to fix multiple imports on one line.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE501">__fixE501</a></td> -<td>Private method to fix the long lines by breaking them.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE502">__fixE502</a></td> -<td>Private method to fix redundant backslash within brackets.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE701">__fixE701</a></td> -<td>Private method to fix colon-separated compound statements.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE702">__fixE702</a></td> -<td>Private method to fix semicolon-separated compound statements.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixE711">__fixE711</a></td> -<td>Private method to fix comparison with None.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixN804">__fixN804</a></td> -<td>Private method to fix a wrong first argument of normal and class methods.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixN806">__fixN806</a></td> -<td>Private method to fix a wrong first argument of static methods.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixReindent">__fixReindent</a></td> -<td>Private method to fix a badly indented line.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixW291">__fixW291</a></td> -<td>Private method to fix trailing whitespace.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixW292">__fixW292</a></td> -<td>Private method to fix a missing newline at the end of file.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixW391">__fixW391</a></td> -<td>Private method to fix trailing blank lines.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixW603">__fixW603</a></td> -<td>Private method to fix the not equal notation.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__fixWhitespace">__fixWhitespace</a></td> -<td>Private method to correct whitespace at the given offset.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__getEol">__getEol</a></td> -<td>Private method to get the applicable eol string.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__getID">__getID</a></td> -<td>Private method to get the ID for a deferred fix.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__getIndent">__getIndent</a></td> -<td>Private method to get the indentation string.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__getIndentWord">__getIndentWord</a></td> -<td>Private method to determine the indentation type.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__getLogical">__getLogical</a></td> -<td>Private method to get the logical line corresponding to the given position.</td> -</tr><tr> -<td><a href="#Pep8Fixer.__multilineStringLines">__multilineStringLines</a></td> -<td>Private method to determine the line numbers that are within multi line strings and these which are part of a documentation string.</td> -</tr><tr> -<td><a href="#Pep8Fixer.finalize">finalize</a></td> -<td>Public method to apply all deferred fixes.</td> -</tr><tr> -<td><a href="#Pep8Fixer.fixIssue">fixIssue</a></td> -<td>Public method to fix the fixable issues.</td> -</tr><tr> -<td><a href="#Pep8Fixer.mutualStartswith">mutualStartswith</a></td> -<td>Local helper method to compare the beginnings of two strings against each other.</td> -</tr><tr> -<td><a href="#Pep8Fixer.saveFile">saveFile</a></td> -<td>Public method to save the modified file.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="Pep8Fixer.__init__" ID="Pep8Fixer.__init__"></a> -<h4>Pep8Fixer (Constructor)</h4> -<b>Pep8Fixer</b>(<i>project, filename, sourceLines, fixCodes, noFixCodes, maxLineLength, inPlace</i>) -<p> - Constructor -</p><dl> -<dt><i>project</i></dt> -<dd> -reference to the project object (Project) -</dd><dt><i>filename</i></dt> -<dd> -name of the file to be fixed (string) -</dd><dt><i>sourceLines</i></dt> -<dd> -list of source lines including eol marker - (list of string) -</dd><dt><i>fixCodes</i></dt> -<dd> -list of codes to be fixed as a comma separated - string (string) -</dd><dt><i>noFixCodes</i></dt> -<dd> -list of codes not to be fixed as a comma - separated string (string) -</dd><dt><i>maxLineLength</i></dt> -<dd> -maximum allowed line length (integer) -</dd><dt><i>inPlace</i></dt> -<dd> -flag indicating to modify the file in place (boolean) -</dd> -</dl><a NAME="Pep8Fixer.__codeMatch" ID="Pep8Fixer.__codeMatch"></a> -<h4>Pep8Fixer.__codeMatch</h4> -<b>__codeMatch</b>(<i>code</i>) -<p> - Private method to check, if the code should be fixed. -</p><dl> -<dt><i>code</i></dt> -<dd> -to check (string) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -flag indicating it should be fixed (boolean) -</dd> -</dl><a NAME="Pep8Fixer.__findLogical" ID="Pep8Fixer.__findLogical"></a> -<h4>Pep8Fixer.__findLogical</h4> -<b>__findLogical</b>(<i></i>) -<p> - Private method to extract the index of all the starts and ends of - lines. -</p><dl> -<dt>Returns:</dt> -<dd> -tuple containing two lists of integer with start and end tuples - of lines -</dd> -</dl><a NAME="Pep8Fixer.__fixD111" ID="Pep8Fixer.__fixD111"></a> -<h4>Pep8Fixer.__fixD111</h4> -<b>__fixD111</b>(<i>code, line, pos</i>) -<p> - Private method to fix docstring enclosed in wrong quotes. -</p><p> - Codes: D111 -</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> -</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="Pep8Fixer.__fixD112" ID="Pep8Fixer.__fixD112"></a> -<h4>Pep8Fixer.__fixD112</h4> -<b>__fixD112</b>(<i>code, line, pos</i>) -<p> - Private method to fix docstring 'r' or 'u' in leading quotes. -</p><p> - Codes: D112, D113 -</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> -</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="Pep8Fixer.__fixD121" ID="Pep8Fixer.__fixD121"></a> -<h4>Pep8Fixer.__fixD121</h4> -<b>__fixD121</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix a single line docstring on multiple lines. -</p><p> - Codes: D121 -</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="Pep8Fixer.__fixD131" ID="Pep8Fixer.__fixD131"></a> -<h4>Pep8Fixer.__fixD131</h4> -<b>__fixD131</b>(<i>code, line, pos</i>) -<p> - Private method to fix a docstring summary not ending with a - period. -</p><p> - Codes: D131 -</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> -</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="Pep8Fixer.__fixD141" ID="Pep8Fixer.__fixD141"></a> -<h4>Pep8Fixer.__fixD141</h4> -<b>__fixD141</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix a function/method docstring preceded by a - blank line. -</p><p> - Codes: D141 -</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="Pep8Fixer.__fixD142" ID="Pep8Fixer.__fixD142"></a> -<h4>Pep8Fixer.__fixD142</h4> -<b>__fixD142</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix a class docstring not preceded by a - blank line. -</p><p> - Codes: D142 -</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="Pep8Fixer.__fixD143" ID="Pep8Fixer.__fixD143"></a> -<h4>Pep8Fixer.__fixD143</h4> -<b>__fixD143</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix a class docstring not followed by a - blank line. -</p><p> - Codes: D143 -</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="Pep8Fixer.__fixD144" ID="Pep8Fixer.__fixD144"></a> -<h4>Pep8Fixer.__fixD144</h4> -<b>__fixD144</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix a docstring summary not followed by a - blank line. -</p><p> - Codes: D144 -</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="Pep8Fixer.__fixD145" ID="Pep8Fixer.__fixD145"></a> -<h4>Pep8Fixer.__fixD145</h4> -<b>__fixD145</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix the last paragraph of a multi-line docstring - not followed by a blank line. -</p><p> - Codes: D143 -</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="Pep8Fixer.__fixD221" ID="Pep8Fixer.__fixD221"></a> -<h4>Pep8Fixer.__fixD221</h4> -<b>__fixD221</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix leading and trailing quotes of docstring - not on separate lines. -</p><p> - Codes: D221, D222 -</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="Pep8Fixer.__fixD242" ID="Pep8Fixer.__fixD242"></a> -<h4>Pep8Fixer.__fixD242</h4> -<b>__fixD242</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix a class or function/method docstring preceded - by a blank line. -</p><p> - Codes: D242, D244 -</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="Pep8Fixer.__fixD243" ID="Pep8Fixer.__fixD243"></a> -<h4>Pep8Fixer.__fixD243</h4> -<b>__fixD243</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix a class or function/method docstring followed - by a blank line. -</p><p> - Codes: D243, D245 -</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="Pep8Fixer.__fixD247" ID="Pep8Fixer.__fixD247"></a> -<h4>Pep8Fixer.__fixD247</h4> -<b>__fixD247</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix a last paragraph of a docstring followed - by a blank line. -</p><p> - Codes: D247 -</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="Pep8Fixer.__fixE101" ID="Pep8Fixer.__fixE101"></a> -<h4>Pep8Fixer.__fixE101</h4> -<b>__fixE101</b>(<i>code, line, pos</i>) -<p> - Private method to fix obsolete tab usage and indentation errors. -</p><p> - Codes: E101, E111, W191 -</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> -</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="Pep8Fixer.__fixE121" ID="Pep8Fixer.__fixE121"></a> -<h4>Pep8Fixer.__fixE121</h4> -<b>__fixE121</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix the indentation of continuation lines and - closing brackets. -</p><p> - Codes: E121, E124 -</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="Pep8Fixer.__fixE122" ID="Pep8Fixer.__fixE122"></a> -<h4>Pep8Fixer.__fixE122</h4> -<b>__fixE122</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix a missing indentation of continuation lines. -</p><p> - Codes: E122 -</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="Pep8Fixer.__fixE123" ID="Pep8Fixer.__fixE123"></a> -<h4>Pep8Fixer.__fixE123</h4> -<b>__fixE123</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix the indentation of a closing bracket lines. -</p><p> - Codes: E123 -</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="Pep8Fixer.__fixE125" ID="Pep8Fixer.__fixE125"></a> -<h4>Pep8Fixer.__fixE125</h4> -<b>__fixE125</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix the indentation of continuation lines not - distinguishable from next logical line. -</p><p> - Codes: E125 -</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="Pep8Fixer.__fixE126" ID="Pep8Fixer.__fixE126"></a> -<h4>Pep8Fixer.__fixE126</h4> -<b>__fixE126</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix over-indented/under-indented hanging - indentation. -</p><p> - Codes: E126, E133 -</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="Pep8Fixer.__fixE127" ID="Pep8Fixer.__fixE127"></a> -<h4>Pep8Fixer.__fixE127</h4> -<b>__fixE127</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix over/under indented lines. -</p><p> - Codes: E127, E128 -</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="Pep8Fixer.__fixE201" ID="Pep8Fixer.__fixE201"></a> -<h4>Pep8Fixer.__fixE201</h4> -<b>__fixE201</b>(<i>code, line, pos</i>) -<p> - Private method to fix extraneous whitespace. -</p><p> - Codes: E201, E202, E203, E211 -</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> -</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="Pep8Fixer.__fixE221" ID="Pep8Fixer.__fixE221"></a> -<h4>Pep8Fixer.__fixE221</h4> -<b>__fixE221</b>(<i>code, line, pos</i>) -<p> - Private method to fix extraneous whitespace around operator or - keyword. -</p><p> - Codes: E221, E222, E223, E224, E225, E226, E227, E228, E241, - E242, E271, E272, E273, E274). -</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> -</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="Pep8Fixer.__fixE231" ID="Pep8Fixer.__fixE231"></a> -<h4>Pep8Fixer.__fixE231</h4> -<b>__fixE231</b>(<i>code, line, pos</i>) -<p> - Private method to fix missing whitespace after ',;:'. -</p><p> - Codes: E231 -</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> -</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="Pep8Fixer.__fixE251" ID="Pep8Fixer.__fixE251"></a> -<h4>Pep8Fixer.__fixE251</h4> -<b>__fixE251</b>(<i>code, line, pos</i>) -<p> - Private method to fix extraneous whitespace around keyword and - default parameter equals. -</p><p> - Codes: E251 -</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> -</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="Pep8Fixer.__fixE261" ID="Pep8Fixer.__fixE261"></a> -<h4>Pep8Fixer.__fixE261</h4> -<b>__fixE261</b>(<i>code, line, pos</i>) -<p> - Private method to fix whitespace before or after inline comment. -</p><p> - Codes: E261, E262 -</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> -</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="Pep8Fixer.__fixE301" ID="Pep8Fixer.__fixE301"></a> -<h4>Pep8Fixer.__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="Pep8Fixer.__fixE302" ID="Pep8Fixer.__fixE302"></a> -<h4>Pep8Fixer.__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="Pep8Fixer.__fixE303" ID="Pep8Fixer.__fixE303"></a> -<h4>Pep8Fixer.__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="Pep8Fixer.__fixE304" ID="Pep8Fixer.__fixE304"></a> -<h4>Pep8Fixer.__fixE304</h4> -<b>__fixE304</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix superfluous blank lines after a function - decorator. -</p><p> - Codes: E304 -</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="Pep8Fixer.__fixE401" ID="Pep8Fixer.__fixE401"></a> -<h4>Pep8Fixer.__fixE401</h4> -<b>__fixE401</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix multiple imports on one line. -</p><p> - Codes: E401 -</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="Pep8Fixer.__fixE501" ID="Pep8Fixer.__fixE501"></a> -<h4>Pep8Fixer.__fixE501</h4> -<b>__fixE501</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix the long lines by breaking them. -</p><p> - Codes: E501 -</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="Pep8Fixer.__fixE502" ID="Pep8Fixer.__fixE502"></a> -<h4>Pep8Fixer.__fixE502</h4> -<b>__fixE502</b>(<i>code, line, pos</i>) -<p> - Private method to fix redundant backslash within brackets. -</p><p> - Codes: E502 -</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> -</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="Pep8Fixer.__fixE701" ID="Pep8Fixer.__fixE701"></a> -<h4>Pep8Fixer.__fixE701</h4> -<b>__fixE701</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix colon-separated compound statements. -</p><p> - Codes: E701 -</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="Pep8Fixer.__fixE702" ID="Pep8Fixer.__fixE702"></a> -<h4>Pep8Fixer.__fixE702</h4> -<b>__fixE702</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix semicolon-separated compound statements. -</p><p> - Codes: E702, E703 -</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="Pep8Fixer.__fixE711" ID="Pep8Fixer.__fixE711"></a> -<h4>Pep8Fixer.__fixE711</h4> -<b>__fixE711</b>(<i>code, line, pos</i>) -<p> - Private method to fix comparison with None. -</p><p> - Codes: E711, E712 -</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> -</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="Pep8Fixer.__fixN804" ID="Pep8Fixer.__fixN804"></a> -<h4>Pep8Fixer.__fixN804</h4> -<b>__fixN804</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix a wrong first argument of normal and - class methods. -</p><p> - Codes: N804, N805 -</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="Pep8Fixer.__fixN806" ID="Pep8Fixer.__fixN806"></a> -<h4>Pep8Fixer.__fixN806</h4> -<b>__fixN806</b>(<i>code, line, pos, apply=False</i>) -<p> - Private method to fix a wrong first argument of static methods. -</p><p> - Codes: N806 -</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="Pep8Fixer.__fixReindent" ID="Pep8Fixer.__fixReindent"></a> -<h4>Pep8Fixer.__fixReindent</h4> -<b>__fixReindent</b>(<i>line, pos, logical</i>) -<p> - Private method to fix a badly indented line. -</p><p> - This is done by adding or removing from its initial indent only. -</p><dl> -<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>logical</i></dt> -<dd> -logical line structure -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -flag indicating a change was done (boolean) -</dd> -</dl><a NAME="Pep8Fixer.__fixW291" ID="Pep8Fixer.__fixW291"></a> -<h4>Pep8Fixer.__fixW291</h4> -<b>__fixW291</b>(<i>code, line, pos</i>) -<p> - Private method to fix trailing whitespace. -</p><p> - Codes: W291, W293 -</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> -</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="Pep8Fixer.__fixW292" ID="Pep8Fixer.__fixW292"></a> -<h4>Pep8Fixer.__fixW292</h4> -<b>__fixW292</b>(<i>code, line, pos</i>) -<p> - Private method to fix a missing newline at the end of file. -</p><p> - Codes: W292 -</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> -</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="Pep8Fixer.__fixW391" ID="Pep8Fixer.__fixW391"></a> -<h4>Pep8Fixer.__fixW391</h4> -<b>__fixW391</b>(<i>code, line, pos</i>) -<p> - Private method to fix trailing blank lines. -</p><p> - Codes: W391 -</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> -</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="Pep8Fixer.__fixW603" ID="Pep8Fixer.__fixW603"></a> -<h4>Pep8Fixer.__fixW603</h4> -<b>__fixW603</b>(<i>code, line, pos</i>) -<p> - Private method to fix the not equal notation. -</p><p> - Codes: W603 -</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> -</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="Pep8Fixer.__fixWhitespace" ID="Pep8Fixer.__fixWhitespace"></a> -<h4>Pep8Fixer.__fixWhitespace</h4> -<b>__fixWhitespace</b>(<i>line, offset, replacement</i>) -<p> - Private method to correct whitespace at the given offset. -</p><dl> -<dt><i>line</i></dt> -<dd> -line to be corrected (string) -</dd><dt><i>offset</i></dt> -<dd> -offset within line (integer) -</dd><dt><i>replacement</i></dt> -<dd> -replacement string (string) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -corrected line -</dd> -</dl><a NAME="Pep8Fixer.__getEol" ID="Pep8Fixer.__getEol"></a> -<h4>Pep8Fixer.__getEol</h4> -<b>__getEol</b>(<i></i>) -<p> - Private method to get the applicable eol string. -</p><dl> -<dt>Returns:</dt> -<dd> -eol string (string) -</dd> -</dl><a NAME="Pep8Fixer.__getID" ID="Pep8Fixer.__getID"></a> -<h4>Pep8Fixer.__getID</h4> -<b>__getID</b>(<i></i>) -<p> - Private method to get the ID for a deferred fix. -</p><dl> -<dt>Returns:</dt> -<dd> -ID for a deferred fix (integer) -</dd> -</dl><a NAME="Pep8Fixer.__getIndent" ID="Pep8Fixer.__getIndent"></a> -<h4>Pep8Fixer.__getIndent</h4> -<b>__getIndent</b>(<i>line</i>) -<p> - Private method to get the indentation string. -</p><dl> -<dt><i>line</i></dt> -<dd> -line to determine the indentation string from (string) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -indentation string (string) -</dd> -</dl><a NAME="Pep8Fixer.__getIndentWord" ID="Pep8Fixer.__getIndentWord"></a> -<h4>Pep8Fixer.__getIndentWord</h4> -<b>__getIndentWord</b>(<i></i>) -<p> - Private method to determine the indentation type. -</p><dl> -<dt>Returns:</dt> -<dd> -string to be used for an indentation (string) -</dd> -</dl><a NAME="Pep8Fixer.__getLogical" ID="Pep8Fixer.__getLogical"></a> -<h4>Pep8Fixer.__getLogical</h4> -<b>__getLogical</b>(<i>line, pos</i>) -<p> - Private method to get the logical line corresponding to the given - position. -</p><dl> -<dt><i>line</i></dt> -<dd> -line number of the issue (integer) -</dd><dt><i>pos</i></dt> -<dd> -position inside line (integer) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -tuple of a tuple of two integers giving the start of the - logical line, another tuple of two integers giving the end - of the logical line and a list of strings with the original - source lines -</dd> -</dl><a NAME="Pep8Fixer.__multilineStringLines" ID="Pep8Fixer.__multilineStringLines"></a> -<h4>Pep8Fixer.__multilineStringLines</h4> -<b>__multilineStringLines</b>(<i></i>) -<p> - Private method to determine the line numbers that are within multi line - strings and these which are part of a documentation string. -</p><dl> -<dt>Returns:</dt> -<dd> -tuple of a set of line numbers belonging to a multi line - string and a set of line numbers belonging to a multi line - documentation string (tuple of two set of integer) -</dd> -</dl><a NAME="Pep8Fixer.finalize" ID="Pep8Fixer.finalize"></a> -<h4>Pep8Fixer.finalize</h4> -<b>finalize</b>(<i></i>) -<p> - Public method to apply all deferred fixes. -</p><dl> -<dt>Returns:</dt> -<dd> -dictionary containing the fix results -</dd> -</dl><a NAME="Pep8Fixer.fixIssue" ID="Pep8Fixer.fixIssue"></a> -<h4>Pep8Fixer.fixIssue</h4> -<b>fixIssue</b>(<i>line, pos, message</i>) -<p> - Public method to fix the fixable issues. -</p><dl> -<dt><i>line</i></dt> -<dd> -line number of issue (integer) -</dd><dt><i>pos</i></dt> -<dd> -character position of issue (integer) -</dd><dt><i>message</i></dt> -<dd> -message text (string) -</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="Pep8Fixer.mutualStartswith" ID="Pep8Fixer.mutualStartswith"></a> -<h4>Pep8Fixer.mutualStartswith</h4> -<b>mutualStartswith</b>(<i>b</i>) -<p> - Local helper method to compare the beginnings of two strings - against each other. -</p><dl> -<dt>Returns:</dt> -<dd> -flag indicating that one string starts with the other - (boolean) -</dd> -</dl><a NAME="Pep8Fixer.saveFile" ID="Pep8Fixer.saveFile"></a> -<h4>Pep8Fixer.saveFile</h4> -<b>saveFile</b>(<i>encoding</i>) -<p> - Public method to save the modified file. -</p><dl> -<dt><i>encoding</i></dt> -<dd> -encoding of the source file (string) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -flag indicating success (boolean) -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /><hr /> -<a NAME="Pep8IndentationWrapper" ID="Pep8IndentationWrapper"></a> -<h2>Pep8IndentationWrapper</h2> -<p> - Class used by fixers dealing with indentation. -</p><p> - Each instance operates on a single logical line. -</p> -<h3>Derived from</h3> -object -<h3>Class Attributes</h3> -<table> -<tr><td>SKIP_TOKENS</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#Pep8IndentationWrapper.__init__">Pep8IndentationWrapper</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#Pep8IndentationWrapper.__buildTokensLogical">__buildTokensLogical</a></td> -<td>Private method to build a logical line from a list of tokens.</td> -</tr><tr> -<td><a href="#Pep8IndentationWrapper.pep8Expected">pep8Expected</a></td> -<td>Public method to replicate logic in pep8.py, to know what level to indent things to.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="Pep8IndentationWrapper.__init__" ID="Pep8IndentationWrapper.__init__"></a> -<h4>Pep8IndentationWrapper (Constructor)</h4> -<b>Pep8IndentationWrapper</b>(<i>physical_lines</i>) -<p> - Constructor -</p><dl> -<dt><i>physical_lines</i></dt> -<dd> -list of physical lines to operate on - (list of strings) -</dd> -</dl><a NAME="Pep8IndentationWrapper.__buildTokensLogical" ID="Pep8IndentationWrapper.__buildTokensLogical"></a> -<h4>Pep8IndentationWrapper.__buildTokensLogical</h4> -<b>__buildTokensLogical</b>(<i>tokens</i>) -<p> - Private method to build a logical line from a list of tokens. -</p><dl> -<dt><i>tokens</i></dt> -<dd> -list of tokens as generated by tokenize.generate_tokens -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -logical line (string) -</dd> -</dl><a NAME="Pep8IndentationWrapper.pep8Expected" ID="Pep8IndentationWrapper.pep8Expected"></a> -<h4>Pep8IndentationWrapper.pep8Expected</h4> -<b>pep8Expected</b>(<i></i>) -<p> - Public method to replicate logic in pep8.py, to know what level to - indent things to. -</p><dl> -<dt>Returns:</dt> -<dd> -list of lists, where each list represents valid indent levels - for the line in question, relative from the initial indent. However, - the first entry is the indent level which was expected. -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /><hr /> -<a NAME="Pep8LineShortener" ID="Pep8LineShortener"></a> -<h2>Pep8LineShortener</h2> -<p> - Class used to shorten lines to a given maximum of characters. -</p> -<h3>Derived from</h3> -object -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#Pep8LineShortener.__init__">Pep8LineShortener</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#Pep8LineShortener.__breakMultiline">__breakMultiline</a></td> -<td>Private method to break multi line strings.</td> -</tr><tr> -<td><a href="#Pep8LineShortener.__checkSyntax">__checkSyntax</a></td> -<td>Private method to check the syntax of the given code fragment.</td> -</tr><tr> -<td><a href="#Pep8LineShortener.__countUnbalancedBrackets">__countUnbalancedBrackets</a></td> -<td>Private method to determine the number of unmatched open/close brackets.</td> -</tr><tr> -<td><a href="#Pep8LineShortener.__getIndent">__getIndent</a></td> -<td>Private method to get the indentation string.</td> -</tr><tr> -<td><a href="#Pep8LineShortener.__isProbablyInsideStringOrComment">__isProbablyInsideStringOrComment</a></td> -<td>Private method to check, if the given string might be inside a string or comment.</td> -</tr><tr> -<td><a href="#Pep8LineShortener.__lineShorteningRank">__lineShorteningRank</a></td> -<td>Private method to rank a candidate.</td> -</tr><tr> -<td><a href="#Pep8LineShortener.__normalizeMultiline">__normalizeMultiline</a></td> -<td>Private method to remove multiline-related code that will cause syntax error.</td> -</tr><tr> -<td><a href="#Pep8LineShortener.__shortenComment">__shortenComment</a></td> -<td>Private method to shorten a comment line.</td> -</tr><tr> -<td><a href="#Pep8LineShortener.__shortenLine">__shortenLine</a></td> -<td>Private method to shorten a line of code at an operator.</td> -</tr><tr> -<td><a href="#Pep8LineShortener.shorten">shorten</a></td> -<td>Public method to shorten the line wrapped by the class instance.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="Pep8LineShortener.__init__" ID="Pep8LineShortener.__init__"></a> -<h4>Pep8LineShortener (Constructor)</h4> -<b>Pep8LineShortener</b>(<i>curLine, prevLine, nextLine, maxLength=79, eol="\n", indentWord=" ", isDocString=False</i>) -<p> - Constructor -</p><dl> -<dt><i>curLine</i></dt> -<dd> -text to work on (string) -</dd><dt><i>prevLine</i></dt> -<dd> -line before the text to work on (string) -</dd><dt><i>nextLine</i></dt> -<dd> -line after the text to work on (string) -</dd><dt><i>maxLength=</i></dt> -<dd> -maximum allowed line length (integer) -</dd><dt><i>eol=</i></dt> -<dd> -eond-of-line marker (string) -</dd><dt><i>indentWord=</i></dt> -<dd> -string used for indentation (string) -</dd><dt><i>isDocString=</i></dt> -<dd> -flag indicating that the line belongs to - a documentation string (boolean) -</dd> -</dl><a NAME="Pep8LineShortener.__breakMultiline" ID="Pep8LineShortener.__breakMultiline"></a> -<h4>Pep8LineShortener.__breakMultiline</h4> -<b>__breakMultiline</b>(<i></i>) -<p> - Private method to break multi line strings. -</p><dl> -<dt>Returns:</dt> -<dd> -tuple of the shortened line and the changed next line - (string, string) -</dd> -</dl><a NAME="Pep8LineShortener.__checkSyntax" ID="Pep8LineShortener.__checkSyntax"></a> -<h4>Pep8LineShortener.__checkSyntax</h4> -<b>__checkSyntax</b>(<i>code</i>) -<p> - Private method to check the syntax of the given code fragment. -</p><dl> -<dt><i>code</i></dt> -<dd> -code fragment to check (string) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -flag indicating syntax is ok (boolean) -</dd> -</dl><a NAME="Pep8LineShortener.__countUnbalancedBrackets" ID="Pep8LineShortener.__countUnbalancedBrackets"></a> -<h4>Pep8LineShortener.__countUnbalancedBrackets</h4> -<b>__countUnbalancedBrackets</b>(<i>line</i>) -<p> - Private method to determine the number of unmatched open/close - brackets. -</p><dl> -<dt><i>line</i></dt> -<dd> -line to work at (string) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -number of unmatched open/close brackets (integer) -</dd> -</dl><a NAME="Pep8LineShortener.__getIndent" ID="Pep8LineShortener.__getIndent"></a> -<h4>Pep8LineShortener.__getIndent</h4> -<b>__getIndent</b>(<i>line</i>) -<p> - Private method to get the indentation string. -</p><dl> -<dt><i>line</i></dt> -<dd> -line to determine the indentation string from (string) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -indentation string (string) -</dd> -</dl><a NAME="Pep8LineShortener.__isProbablyInsideStringOrComment" ID="Pep8LineShortener.__isProbablyInsideStringOrComment"></a> -<h4>Pep8LineShortener.__isProbablyInsideStringOrComment</h4> -<b>__isProbablyInsideStringOrComment</b>(<i>line, index</i>) -<p> - Private method to check, if the given string might be inside a string - or comment. -</p><dl> -<dt><i>line</i></dt> -<dd> -line to check (string) -</dd><dt><i>index</i></dt> -<dd> -position inside line to check (integer) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -flag indicating the possibility of being inside a string - or comment -</dd> -</dl><a NAME="Pep8LineShortener.__lineShorteningRank" ID="Pep8LineShortener.__lineShorteningRank"></a> -<h4>Pep8LineShortener.__lineShorteningRank</h4> -<b>__lineShorteningRank</b>(<i>candidate</i>) -<p> - Private method to rank a candidate. -</p><dl> -<dt><i>candidate</i></dt> -<dd> -candidate line to rank (string) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -rank of the candidate (integer) -</dd> -</dl><a NAME="Pep8LineShortener.__normalizeMultiline" ID="Pep8LineShortener.__normalizeMultiline"></a> -<h4>Pep8LineShortener.__normalizeMultiline</h4> -<b>__normalizeMultiline</b>(<i>text</i>) -<p> - Private method to remove multiline-related code that will cause syntax - error. -</p><dl> -<dt><i>text</i></dt> -<dd> -code line to work on (string) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -normalized code line (string) -</dd> -</dl><a NAME="Pep8LineShortener.__shortenComment" ID="Pep8LineShortener.__shortenComment"></a> -<h4>Pep8LineShortener.__shortenComment</h4> -<b>__shortenComment</b>(<i>isLast</i>) -<p> - Private method to shorten a comment line. -</p><dl> -<dt><i>isLast</i></dt> -<dd> -flag indicating, that the line is the last comment line - (boolean) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -shortened comment line (string) -</dd> -</dl><a NAME="Pep8LineShortener.__shortenLine" ID="Pep8LineShortener.__shortenLine"></a> -<h4>Pep8LineShortener.__shortenLine</h4> -<b>__shortenLine</b>(<i>tokens, source, indent</i>) -<p> - Private method to shorten a line of code at an operator. -</p><dl> -<dt><i>tokens</i></dt> -<dd> -tokens of the line as generated by tokenize - (list of token) -</dd><dt><i>source</i></dt> -<dd> -code string to work at (string) -</dd><dt><i>indent</i></dt> -<dd> -indentation string of the code line (string) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -list of candidates (list of string) -</dd> -</dl><a NAME="Pep8LineShortener.shorten" ID="Pep8LineShortener.shorten"></a> -<h4>Pep8LineShortener.shorten</h4> -<b>shorten</b>(<i></i>) -<p> - Public method to shorten the line wrapped by the class instance. -</p><dl> -<dt>Returns:</dt> -<dd> -tuple of a flag indicating successful shortening, the - shortened line and the changed next line (boolean, string, string) -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /><hr /> -<a NAME="Pep8Reindenter" ID="Pep8Reindenter"></a> -<h2>Pep8Reindenter</h2> -<p> - Class to reindent badly-indented code to uniformly use four-space - indentation. -</p><p> - Released to the public domain, by Tim Peters, 03 October 2000. -</p> -<h3>Derived from</h3> -object -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#Pep8Reindenter.__init__">Pep8Reindenter</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#Pep8Reindenter.__genStats">__genStats</a></td> -<td>Private method to generate the re-indent statistics.</td> -</tr><tr> -<td><a href="#Pep8Reindenter.__getlspace">__getlspace</a></td> -<td>Private method to count number of leading blanks.</td> -</tr><tr> -<td><a href="#Pep8Reindenter.fixedLine">fixedLine</a></td> -<td>Public method to get a fixed line.</td> -</tr><tr> -<td><a href="#Pep8Reindenter.getline">getline</a></td> -<td>Public method to get a line of text for tokenize.</td> -</tr><tr> -<td><a href="#Pep8Reindenter.run">run</a></td> -<td>Public method to run the re-indenter.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="Pep8Reindenter.__init__" ID="Pep8Reindenter.__init__"></a> -<h4>Pep8Reindenter (Constructor)</h4> -<b>Pep8Reindenter</b>(<i>sourceLines</i>) -<p> - Constructor -</p><dl> -<dt><i>sourceLines</i></dt> -<dd> -list of source lines including eol marker - (list of string) -</dd> -</dl><a NAME="Pep8Reindenter.__genStats" ID="Pep8Reindenter.__genStats"></a> -<h4>Pep8Reindenter.__genStats</h4> -<b>__genStats</b>(<i>tokens</i>) -<p> - Private method to generate the re-indent statistics. -</p><dl> -<dt><i>tokens</i></dt> -<dd> -tokens generator (tokenize._tokenize) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -reference to the generated statistics -</dd> -</dl><a NAME="Pep8Reindenter.__getlspace" ID="Pep8Reindenter.__getlspace"></a> -<h4>Pep8Reindenter.__getlspace</h4> -<b>__getlspace</b>(<i>line</i>) -<p> - Private method to count number of leading blanks. -</p><dl> -<dt><i>line</i></dt> -<dd> -line to check (string) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -number of leading blanks (integer) -</dd> -</dl><a NAME="Pep8Reindenter.fixedLine" ID="Pep8Reindenter.fixedLine"></a> -<h4>Pep8Reindenter.fixedLine</h4> -<b>fixedLine</b>(<i>line</i>) -<p> - Public method to get a fixed line. -</p><dl> -<dt><i>line</i></dt> -<dd> -number of the line to retrieve (integer) -</dd> -</dl><dl> -<dt>Returns:</dt> -<dd> -fixed line (string) -</dd> -</dl><a NAME="Pep8Reindenter.getline" ID="Pep8Reindenter.getline"></a> -<h4>Pep8Reindenter.getline</h4> -<b>getline</b>(<i></i>) -<p> - Public method to get a line of text for tokenize. -</p><dl> -<dt>Returns:</dt> -<dd> -line of text (string) -</dd> -</dl><a NAME="Pep8Reindenter.run" ID="Pep8Reindenter.run"></a> -<h4>Pep8Reindenter.run</h4> -<b>run</b>(<i></i>) -<p> - Public method to run the re-indenter. -</p><dl> -<dt>Returns:</dt> -<dd> -flag indicating that a change was done (boolean) -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Plugins/CheckerPlugins/Pep8/CodeStyleCheckerDialog.py Tue Oct 01 18:22:33 2013 +0200 +++ b/Plugins/CheckerPlugins/Pep8/CodeStyleCheckerDialog.py Tue Oct 01 18:31:05 2013 +0200 @@ -145,7 +145,7 @@ automatically (boolean) @return reference to the created item (QTreeWidgetItem) """ - from .Pep8Fixer import Pep8FixableIssues + from .CodeStyleFixer import FixableCodeStyleIssues if self.__lastFileItem is None: # It's a new file @@ -168,7 +168,7 @@ itm.setIcon(1, UI.PixmapCache.getIcon("syntaxError.png")) if fixed: itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed.png")) - elif code in Pep8FixableIssues and not autofixing: + elif code in FixableCodeStyleIssues and not autofixing: itm.setIcon(0, UI.PixmapCache.getIcon("issueFixable.png")) fixable = True @@ -213,7 +213,7 @@ @param statistics dictionary of statistical data with message code as key and message count as value - @param fixer reference to the PEP 8 fixer (Pep8Fixer) + @param fixer reference to the PEP 8 fixer (CodeStyleFixer) """ self.__statistics["_FilesCount"] += 1 stats = {v: k for v, k in statistics.items() if v[0].isupper()} @@ -231,7 +231,7 @@ """ Private method to update the collected fixer related statistics. - @param fixer reference to the PEP 8 fixer (Pep8Fixer) + @param fixer reference to the PEP 8 fixer (CodeStyleFixer) """ self.__statistics["_IssuesFixed"] += fixer.fixed @@ -405,8 +405,8 @@ flags = Utilities.extractFlags(source) ext = os.path.splitext(file)[1] if fixIssues: - from .Pep8Fixer import Pep8Fixer - fixer = Pep8Fixer(self.__project, file, source, + from .CodeStyleFixer import CodeStyleFixer + fixer = CodeStyleFixer(self.__project, file, source, fixCodes, noFixCodes, maxLineLength, True) # always fix in place else: @@ -803,7 +803,7 @@ """ Private slot to fix selected issues. """ - from .Pep8Fixer import Pep8Fixer + from .CodeStyleFixer import CodeStyleFixer # build a dictionary of issues to fix fixableItems = self.__getSelectedFixableItems() @@ -843,7 +843,7 @@ continue deferredFixes = {} - fixer = Pep8Fixer(self.__project, file, source, + fixer = CodeStyleFixer(self.__project, file, source, fixCodes, noFixCodes, maxLineLength, True) # always fix in place errors = fixesDict[file]
--- a/Plugins/CheckerPlugins/Pep8/CodeStyleCodeSelectionDialog.py Tue Oct 01 18:22:33 2013 +0200 +++ b/Plugins/CheckerPlugins/Pep8/CodeStyleCodeSelectionDialog.py Tue Oct 01 18:31:05 2013 +0200 @@ -38,8 +38,8 @@ codeList = [code.strip() for code in codes.split(",") if code.strip()] if showFixCodes: - from .Pep8Fixer import Pep8FixableIssues - selectableCodes = Pep8FixableIssues + from .CodeStyleFixer import FixableCodeStyleIssues + selectableCodes = FixableCodeStyleIssues else: selectableCodes = list(pep8.pep8_messages.keys()) selectableCodes.extend(Pep8NamingChecker.Messages.keys())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/CheckerPlugins/Pep8/CodeStyleFixer.py Tue Oct 01 18:31:05 2013 +0200 @@ -0,0 +1,2704 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2011 - 2013 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a class to fix certain code style issues. +""" + +import os +import re +import tokenize +import io + +from PyQt4.QtCore import QObject + +from E5Gui import E5MessageBox + +from . import pep8 + +import Utilities + +FixableCodeStyleIssues = [ + "D111", "D112", "D113", "D121", "D131", "D141", + "D142", "D143", "D144", "D145", + "D221", "D222", "D231", "D242", "D243", "D244", + "D245", "D246", "D247", + "E101", "E111", "E121", "E122", "E123", "E124", + "E125", "E126", "E127", "E128", "E133", "E201", + "E202", "E203", "E211", "E221", "E222", "E223", + "E224", "E225", "E226", "E227", "E228", "E231", + "E241", "E242", "E251", "E261", "E262", "E271", + "E272", "E273", "E274", "E301", "E302", "E303", + "E304", "E401", "E501", "E502", "E701", "E702", + "E703", "E711", "E712", + "N804", "N805", "N806", + "W191", "W291", "W292", "W293", "W391", "W603", +] + + +class CodeStyleFixer(QObject): + """ + Class implementing a fixer for certain code style issues. + """ + def __init__(self, project, filename, sourceLines, fixCodes, noFixCodes, + maxLineLength, inPlace): + """ + Constructor + + @param project reference to the project object (Project) + @param filename name of the file to be fixed (string) + @param sourceLines list of source lines including eol marker + (list of string) + @param fixCodes list of codes to be fixed as a comma separated + string (string) + @param noFixCodes list of codes not to be fixed as a comma + separated string (string) + @param maxLineLength maximum allowed line length (integer) + @param inPlace flag indicating to modify the file in place (boolean) + """ + super().__init__() + + self.__project = project + self.__filename = filename + self.__origName = "" + self.__source = sourceLines[:] # save a copy + self.__fixCodes = [c.strip() for c in fixCodes.split(",") if c.strip()] + self.__noFixCodes = [ + c.strip() for c in noFixCodes.split(",") if c.strip()] + self.__maxLineLength = maxLineLength + self.fixed = 0 + + self.__reindenter = None + self.__eol = "" + self.__indentWord = self.__getIndentWord() + + if not inPlace: + self.__origName = self.__filename + self.__filename = os.path.join( + os.path.dirname(self.__filename), + "fixed_" + os.path.basename(self.__filename)) + + self.__fixes = { + "D111": self.__fixD111, + "D112": self.__fixD112, + "D113": self.__fixD112, + "D121": self.__fixD121, + "D131": self.__fixD131, + "D141": self.__fixD141, + "D142": self.__fixD142, + "D143": self.__fixD143, + "D144": self.__fixD144, + "D145": self.__fixD145, + "D221": self.__fixD221, + "D222": self.__fixD221, + "D231": self.__fixD131, + "D242": self.__fixD242, + "D243": self.__fixD243, + "D244": self.__fixD242, + "D245": self.__fixD243, + "D246": self.__fixD144, + "D247": self.__fixD247, + "E101": self.__fixE101, + "E111": self.__fixE101, + "E121": self.__fixE121, + "E122": self.__fixE122, + "E123": self.__fixE123, + "E124": self.__fixE121, + "E125": self.__fixE125, + "E126": self.__fixE126, + "E127": self.__fixE127, + "E128": self.__fixE127, + "E133": self.__fixE126, + "E201": self.__fixE201, + "E202": self.__fixE201, + "E203": self.__fixE201, + "E211": self.__fixE201, + "E221": self.__fixE221, + "E222": self.__fixE221, + "E223": self.__fixE221, + "E224": self.__fixE221, + "E225": self.__fixE221, + "E226": self.__fixE221, + "E227": self.__fixE221, + "E228": self.__fixE221, + "E231": self.__fixE231, + "E241": self.__fixE221, + "E242": self.__fixE221, + "E251": self.__fixE251, + "E261": self.__fixE261, + "E262": self.__fixE261, + "E271": self.__fixE221, + "E272": self.__fixE221, + "E273": self.__fixE221, + "E274": self.__fixE221, + "E301": self.__fixE301, + "E302": self.__fixE302, + "E303": self.__fixE303, + "E304": self.__fixE304, + "E401": self.__fixE401, + "E501": self.__fixE501, + "E502": self.__fixE502, + "E701": self.__fixE701, + "E702": self.__fixE702, + "E703": self.__fixE702, + "E711": self.__fixE711, + "E712": self.__fixE711, + "N804": self.__fixN804, + "N805": self.__fixN804, + "N806": self.__fixN806, + "W191": self.__fixE101, + "W291": self.__fixW291, + "W292": self.__fixW292, + "W293": self.__fixW291, + "W391": self.__fixW391, + "W603": self.__fixW603, + } + self.__modified = False + self.__stackLogical = [] # these need to be fixed before the file + # is saved but after all other inline + # fixes. These work with logical lines. + self.__stack = [] # these need to be fixed before the file + # is saved but after all inline fixes + + self.__multiLineNumbers = None + self.__docLineNumbers = None + + self.__lastID = 0 + + def saveFile(self, encoding): + """ + Public method to save the modified file. + + @param encoding encoding of the source file (string) + @return flag indicating success (boolean) + """ + if not self.__modified: + # no need to write + return True + + txt = "".join(self.__source) + try: + Utilities.writeEncodedFile(self.__filename, txt, encoding) + except (IOError, Utilities.CodingError, UnicodeError) as err: + E5MessageBox.critical( + self, + self.trUtf8("Fix Code Style Issues"), + self.trUtf8( + """<p>Could not save the file <b>{0}</b>.""" + """ Skipping it.</p><p>Reason: {1}</p>""") + .format(self.__filename, str(err)) + ) + return False + + return True + + def __codeMatch(self, code): + """ + Private method to check, if the code should be fixed. + + @param code to check (string) + @return flag indicating it should be fixed (boolean) + """ + def mutualStartswith(a, b): + """ + Local helper method to compare the beginnings of two strings + against each other. + + @return flag indicating that one string starts with the other + (boolean) + """ + return b.startswith(a) or a.startswith(b) + + if self.__noFixCodes: + for noFixCode in [c.strip() for c in self.__noFixCodes]: + if mutualStartswith(code.lower(), noFixCode.lower()): + return False + + if self.__fixCodes: + for fixCode in [c.strip() for c in self.__fixCodes]: + if mutualStartswith(code.lower(), fixCode.lower()): + return True + return False + + return True + + def fixIssue(self, line, pos, message): + """ + Public method to fix the fixable issues. + + @param line line number of issue (integer) + @param pos character position of issue (integer) + @param message message text (string) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + code = message.split(None, 1)[0].strip() + + if line <= len(self.__source) and \ + self.__codeMatch(code) and \ + code in self.__fixes: + res = self.__fixes[code](code, line, pos) + if res[0] == 1: + self.__modified = True + self.fixed += 1 + else: + res = (0, "", 0) + + return res + + def finalize(self): + """ + Public method to apply all deferred fixes. + + @return dictionary containing the fix results + """ + results = {} + + # step 1: do fixes operating on logical lines first + for id_, code, line, pos in self.__stackLogical: + res, msg, _ = self.__fixes[code](code, line, pos, apply=True) + if res == 1: + self.__modified = True + self.fixed += 1 + results[id_] = (res, msg) + + # step 2: do fixes that change the number of lines + for id_, code, line, pos in reversed(self.__stack): + res, msg, _ = self.__fixes[code](code, line, pos, apply=True) + if res == 1: + self.__modified = True + self.fixed += 1 + results[id_] = (res, msg) + + return results + + def __getID(self): + """ + Private method to get the ID for a deferred fix. + + @return ID for a deferred fix (integer) + """ + self.__lastID += 1 + return self.__lastID + + def __getEol(self): + """ + Private method to get the applicable eol string. + + @return eol string (string) + """ + if not self.__eol: + if self.__origName: + fn = self.__origName + else: + fn = self.__filename + + if self.__project.isOpen() and self.__project.isProjectFile(fn): + self.__eol = self.__project.getEolString() + else: + self.__eol = Utilities.linesep() + return self.__eol + + def __findLogical(self): + """ + Private method to extract the index of all the starts and ends of + lines. + + @return tuple containing two lists of integer with start and end tuples + of lines + """ + logical_start = [] + logical_end = [] + last_newline = True + sio = io.StringIO("".join(self.__source)) + parens = 0 + for t in tokenize.generate_tokens(sio.readline): + if t[0] in [tokenize.COMMENT, tokenize.DEDENT, + tokenize.INDENT, tokenize.NL, + tokenize.ENDMARKER]: + continue + if not parens and t[0] in [tokenize.NEWLINE, tokenize.SEMI]: + last_newline = True + logical_end.append((t[3][0] - 1, t[2][1])) + continue + if last_newline and not parens: + logical_start.append((t[2][0] - 1, t[2][1])) + last_newline = False + if t[0] == tokenize.OP: + if t[1] in '([{': + parens += 1 + elif t[1] in '}])': + parens -= 1 + return logical_start, logical_end + + def __getLogical(self, line, pos): + """ + Private method to get the logical line corresponding to the given + position. + + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return tuple of a tuple of two integers giving the start of the + logical line, another tuple of two integers giving the end + of the logical line and a list of strings with the original + source lines + """ + try: + (logical_start, logical_end) = self.__findLogical() + except (SyntaxError, tokenize.TokenError): + return None + + line = line - 1 + ls = None + le = None + for i in range(0, len(logical_start)): + x = logical_end[i] + if x[0] > line or (x[0] == line and x[1] > pos): + le = x + ls = logical_start[i] + break + if ls is None: + return None + + original = self.__source[ls[0]:le[0] + 1] + return ls, le, original + + def __getIndentWord(self): + """ + Private method to determine the indentation type. + + @return string to be used for an indentation (string) + """ + sio = io.StringIO("".join(self.__source)) + indentWord = " " # default in case of failure + try: + for token in tokenize.generate_tokens(sio.readline): + if token[0] == tokenize.INDENT: + indentWord = token[1] + break + except (SyntaxError, tokenize.TokenError): + pass + return indentWord + + def __getIndent(self, line): + """ + Private method to get the indentation string. + + @param line line to determine the indentation string from (string) + @return indentation string (string) + """ + return line.replace(line.lstrip(), "") + + def __multilineStringLines(self): + """ + Private method to determine the line numbers that are within multi line + strings and these which are part of a documentation string. + + @return tuple of a set of line numbers belonging to a multi line + string and a set of line numbers belonging to a multi line + documentation string (tuple of two set of integer) + """ + if self.__multiLineNumbers is None: + source = "".join(self.__source) + sio = io.StringIO(source) + self.__multiLineNumbers = set() + self.__docLineNumbers = set() + previousTokenType = '' + try: + for t in tokenize.generate_tokens(sio.readline): + tokenType = t[0] + startRow = t[2][0] + endRow = t[3][0] + + if (tokenType == tokenize.STRING and startRow != endRow): + if previousTokenType != tokenize.INDENT: + self.__multiLineNumbers |= set( + range(startRow, 1 + endRow)) + else: + self.__docLineNumbers |= set( + range(startRow, 1 + endRow)) + + previousTokenType = tokenType + except (SyntaxError, tokenize.TokenError): + pass + + return self.__multiLineNumbers, self.__docLineNumbers + + def __fixReindent(self, line, pos, logical): + """ + Private method to fix a badly indented line. + + This is done by adding or removing from its initial indent only. + + @param line line number of the issue (integer) + @param pos position inside line (integer) + @param logical logical line structure + @return flag indicating a change was done (boolean) + """ + assert logical + ls, _, original = logical + + rewrapper = IndentationWrapper(original) + valid_indents = rewrapper.pep8Expected() + if not rewrapper.rel_indent: + return False + + if line > ls[0]: + # got a valid continuation line number + row = line - ls[0] - 1 + # always pick the first option for this + valid = valid_indents[row] + got = rewrapper.rel_indent[row] + else: + return False + + line1 = ls[0] + row + # always pick the expected indent, for now. + indent_to = valid[0] + + if got != indent_to: + orig_line = self.__source[line1] + new_line = ' ' * (indent_to) + orig_line.lstrip() + if new_line == orig_line: + return False + else: + self.__source[line1] = new_line + return True + else: + return False + + def __fixWhitespace(self, line, offset, replacement): + """ + Private method to correct whitespace at the given offset. + + @param line line to be corrected (string) + @param offset offset within line (integer) + @param replacement replacement string (string) + @return corrected line + """ + left = line[:offset].rstrip(" \t") + right = line[offset:].lstrip(" \t") + if right.startswith("#"): + return line + else: + return left + replacement + right + + def __fixD111(self, code, line, pos): + """ + Private method to fix docstring enclosed in wrong quotes. + + Codes: D111 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + line = line - 1 + left, right = self.__source[line].split("'''", 1) + self.__source[line] = left + '"""' + right + while line < len(self.__source): + if self.__source[line].rstrip().endswith("'''"): + left, right = self.__source[line].rsplit("'''", 1) + self.__source[line] = left + '"""' + right + break + line += 1 + + return ( + 1, + self.trUtf8( + "Triple single quotes converted to triple double quotes."), + 0) + + def __fixD112(self, code, line, pos): + """ + Private method to fix docstring 'r' or 'u' in leading quotes. + + Codes: D112, D113 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + line = line - 1 + if code == "D112": + insertChar = "r" + elif code == "D113": + insertChar = "u" + else: + return (0, "", 0) + + newText = self.__getIndent(self.__source[line]) + \ + insertChar + self.__source[line].lstrip() + self.__source[line] = newText + return ( + 1, + self.trUtf8('Introductory quotes corrected to be {0}"""') + .format(insertChar), + 0) + + def __fixD121(self, code, line, pos, apply=False): + """ + Private method to fix a single line docstring on multiple lines. + + Codes: D121 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + if not self.__source[line].lstrip().startswith( + ('"""', 'r"""', 'u"""')): + # only correctly formatted docstrings will be fixed + return (0, "", 0) + + docstring = self.__source[line].rstrip() + \ + self.__source[line + 1].strip() + if docstring.endswith('"""'): + docstring += self.__getEol() + else: + docstring += self.__source[line + 2].lstrip() + self.__source[line + 2] = "" + + self.__source[line] = docstring + self.__source[line + 1] = "" + return ( + 1, + self.trUtf8("Single line docstring put on one line."), + 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixD131(self, code, line, pos): + """ + Private method to fix a docstring summary not ending with a + period. + + Codes: D131 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + line = line - 1 + newText = "" + if self.__source[line].rstrip().endswith(('"""', "'''")) and \ + self.__source[line].lstrip().startswith(('"""', 'r"""', 'u"""')): + # it is a one-liner + newText = self.__source[line].rstrip()[:-3].rstrip() + "." + \ + self.__source[line].rstrip()[-3:] + self.__getEol() + else: + if line < len(self.__source) - 1 and \ + (not self.__source[line + 1].strip() or + self.__source[line + 1].lstrip().startswith("@") or + (self.__source[line + 1].strip() in ('"""', "'''") and + not self.__source[line].lstrip().startswith("@"))): + newText = self.__source[line].rstrip() + "." + self.__getEol() + + if newText: + self.__source[line] = newText + return (1, self.trUtf8("Period added to summary line."), 0) + else: + return (0, "", 0) + + def __fixD141(self, code, line, pos, apply=False): + """ + Private method to fix a function/method docstring preceded by a + blank line. + + Codes: D141 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + self.__source[line - 1] = "" + return ( + 1, + self.trUtf8( + "Blank line before function/method docstring removed."), + 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixD142(self, code, line, pos, apply=False): + """ + Private method to fix a class docstring not preceded by a + blank line. + + Codes: D142 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + self.__source[line] = self.__getEol() + self.__source[line] + return ( + 1, + self.trUtf8("Blank line inserted before class docstring."), + 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixD143(self, code, line, pos, apply=False): + """ + Private method to fix a class docstring not followed by a + blank line. + + Codes: D143 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + self.__source[line] += self.__getEol() + return ( + 1, + self.trUtf8("Blank line inserted after class docstring."), + 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixD144(self, code, line, pos, apply=False): + """ + Private method to fix a docstring summary not followed by a + blank line. + + Codes: D144 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + if not self.__source[line].rstrip().endswith("."): + # only correct summary lines can be fixed here + return (0, "", 0) + + self.__source[line] += self.__getEol() + return ( + 1, + self.trUtf8("Blank line inserted after docstring summary."), + 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixD145(self, code, line, pos, apply=False): + """ + Private method to fix the last paragraph of a multi-line docstring + not followed by a blank line. + + Codes: D143 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + self.__source[line] = self.__getEol() + self.__source[line] + return ( + 1, + self.trUtf8("Blank line inserted after last paragraph" + " of docstring."), + 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixD221(self, code, line, pos, apply=False): + """ + Private method to fix leading and trailing quotes of docstring + not on separate lines. + + Codes: D221, D222 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + indent = self.__getIndent(self.__source[line]) + source = self.__source[line].strip() + if code == "D221": + # leading + if source.startswith(("r", "u")): + first, second = source[:4], source[4:].strip() + else: + first, second = source[:3], source[3:].strip() + else: + # trailing + first, second = source[:-3].strip(), source[-3:] + newText = indent + first + self.__getEol() + \ + indent + second + self.__getEol() + self.__source[line] = newText + if code == "D221": + msg = self.trUtf8("Leading quotes put on separate line.") + else: + msg = self.trUtf8("Trailing quotes put on separate line.") + return (1, msg, 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixD242(self, code, line, pos, apply=False): + """ + Private method to fix a class or function/method docstring preceded + by a blank line. + + Codes: D242, D244 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + self.__source[line - 1] = "" + if code == "D242": + msg = self.trUtf8("Blank line before class docstring removed.") + else: + msg = self.trUtf8( + "Blank line before function/method docstring removed.") + return (1, msg, 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixD243(self, code, line, pos, apply=False): + """ + Private method to fix a class or function/method docstring followed + by a blank line. + + Codes: D243, D245 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + self.__source[line + 1] = "" + if code == "D243": + msg = self.trUtf8("Blank line after class docstring removed.") + else: + msg = self.trUtf8( + "Blank line after function/method docstring removed.") + return (1, msg, 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixD247(self, code, line, pos, apply=False): + """ + Private method to fix a last paragraph of a docstring followed + by a blank line. + + Codes: D247 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + self.__source[line - 1] = "" + return ( + 1, + self.trUtf8("Blank line after last paragraph removed."), + 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE101(self, code, line, pos): + """ + Private method to fix obsolete tab usage and indentation errors. + + Codes: E101, E111, W191 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if self.__reindenter is None: + self.__reindenter = Reindenter(self.__source) + self.__reindenter.run() + fixedLine = self.__reindenter.fixedLine(line - 1) + if fixedLine is not None and fixedLine != self.__source[line - 1]: + self.__source[line - 1] = fixedLine + if code in ["E101", "W191"]: + msg = self.trUtf8("Tab converted to 4 spaces.") + else: + msg = self.trUtf8( + "Indentation adjusted to be a multiple of four.") + return (1, msg, 0) + else: + return (0, "", 0) + + def __fixE121(self, code, line, pos, apply=False): + """ + Private method to fix the indentation of continuation lines and + closing brackets. + + Codes: E121, E124 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + logical = self.__getLogical(line, pos) + if logical: + # Fix by adjusting initial indent level. + changed = self.__fixReindent(line, pos, logical) + if changed: + if code == "E121": + msg = self.trUtf8( + "Indentation of continuation line corrected.") + elif code == "E124": + msg = self.trUtf8( + "Indentation of closing bracket corrected.") + return (1, msg, 0) + return (0, "", 0) + else: + id = self.__getID() + self.__stackLogical.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE122(self, code, line, pos, apply=False): + """ + Private method to fix a missing indentation of continuation lines. + + Codes: E122 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + logical = self.__getLogical(line, pos) + if logical: + # Fix by adding an initial indent. + modified = self.__fixReindent(line, pos, logical) + if not modified: + # fall back to simple method + line = line - 1 + text = self.__source[line] + indentation = self.__getIndent(text) + self.__source[line] = indentation + \ + self.__indentWord + text.lstrip() + return ( + 1, + self.trUtf8( + "Missing indentation of continuation line corrected."), + 0) + return (0, "", 0) + else: + id = self.__getID() + self.__stackLogical.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE123(self, code, line, pos, apply=False): + """ + Private method to fix the indentation of a closing bracket lines. + + Codes: E123 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + logical = self.__getLogical(line, pos) + if logical: + # Fix by deleting whitespace to the correct level. + logicalLines = logical[2] + row = line - 1 + text = self.__source[row] + newText = self.__getIndent(logicalLines[0]) + text.lstrip() + if newText == text: + # fall back to slower method + changed = self.__fixReindent(line, pos, logical) + else: + self.__source[row] = newText + changed = True + if changed: + return (1, self.trUtf8( + "Closing bracket aligned to opening bracket."), + 0) + return (0, "", 0) + else: + id = self.__getID() + self.__stackLogical.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE125(self, code, line, pos, apply=False): + """ + Private method to fix the indentation of continuation lines not + distinguishable from next logical line. + + Codes: E125 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + logical = self.__getLogical(line, pos) + if logical: + # Fix by adjusting initial indent level. + modified = self.__fixReindent(line, pos, logical) + if not modified: + row = line - 1 + text = self.__source[row] + self.__source[row] = self.__getIndent(text) + \ + self.__indentWord + text.lstrip() + return (1, self.trUtf8("Indentation level changed."), 0) + return (0, "", 0) + else: + id = self.__getID() + self.__stackLogical.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE126(self, code, line, pos, apply=False): + """ + Private method to fix over-indented/under-indented hanging + indentation. + + Codes: E126, E133 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + logical = self.__getLogical(line, pos) + if logical: + # Fix by deleting whitespace to the left. + logicalLines = logical[2] + row = line - 1 + text = self.__source[row] + newText = self.__getIndent(logicalLines[0]) + \ + self.__indentWord + text.lstrip() + if newText == text: + # fall back to slower method + changed = self.__fixReindent(line, pos, logical) + else: + self.__source[row] = newText + changed = True + if changed: + return (1, self.trUtf8( + "Indentation level of hanging indentation changed."), + 0) + return (0, "", 0) + else: + id = self.__getID() + self.__stackLogical.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE127(self, code, line, pos, apply=False): + """ + Private method to fix over/under indented lines. + + Codes: E127, E128 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + logical = self.__getLogical(line, pos) + if logical: + # Fix by inserting/deleting whitespace to the correct level. + logicalLines = logical[2] + row = line - 1 + text = self.__source[row] + newText = text + + if logicalLines[0].rstrip().endswith('\\'): + newText = self.__getIndent(logicalLines[0]) + \ + self.__indentWord + text.lstrip() + else: + startIndex = None + for symbol in '([{': + if symbol in logicalLines[0]: + foundIndex = logicalLines[0].find(symbol) + 1 + if startIndex is None: + startIndex = foundIndex + else: + startIndex = min(startIndex, foundIndex) + + if startIndex is not None: + newText = startIndex * ' ' + text.lstrip() + + if newText == text: + # fall back to slower method + changed = self.__fixReindent(line, pos, logical) + else: + self.__source[row] = newText + changed = True + if changed: + return (1, self.trUtf8("Visual indentation corrected."), 0) + return (0, "", 0) + else: + id = self.__getID() + self.__stackLogical.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE201(self, code, line, pos): + """ + Private method to fix extraneous whitespace. + + Codes: E201, E202, E203, E211 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + line = line - 1 + text = self.__source[line] + + if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): + return (0, "", 0) + + newText = self.__fixWhitespace(text, pos, '') + if newText == text: + return (0, "", 0) + + self.__source[line] = newText + return (1, self.trUtf8("Extraneous whitespace removed."), 0) + + def __fixE221(self, code, line, pos): + """ + Private method to fix extraneous whitespace around operator or + keyword. + + Codes: E221, E222, E223, E224, E225, E226, E227, E228, E241, + E242, E271, E272, E273, E274). + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + line = line - 1 + text = self.__source[line] + + if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): + return (0, "", 0) + + newText = self.__fixWhitespace(text, pos, ' ') + if newText == text: + return (0, "", 0) + + self.__source[line] = newText + if code in ["E225", "E226", "E227", "E228"]: + return (1, self.trUtf8("Missing whitespace added."), 0) + else: + return (1, self.trUtf8("Extraneous whitespace removed."), 0) + + def __fixE231(self, code, line, pos): + """ + Private method to fix missing whitespace after ',;:'. + + Codes: E231 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + line = line - 1 + pos = pos + 1 + self.__source[line] = self.__source[line][:pos] + \ + " " + self.__source[line][pos:] + return (1, self.trUtf8("Missing whitespace added."), 0) + + def __fixE251(self, code, line, pos): + """ + Private method to fix extraneous whitespace around keyword and + default parameter equals. + + Codes: E251 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + line = line - 1 + text = self.__source[line] + + # This is necessary since pep8 sometimes reports columns that goes + # past the end of the physical line. This happens in cases like, + # foo(bar\n=None) + col = min(pos, len(text) - 1) + if text[col].strip(): + newText = text + else: + newText = text[:col].rstrip() + text[col:].lstrip() + + # There could be an escaped newline + # + # def foo(a=\ + # 1) + if newText.endswith(('=\\\n', '=\\\r\n', '=\\\r')): + self.__source[line] = newText.rstrip("\n\r \t\\") + self.__source[line + 1] = self.__source[line + 1].lstrip() + else: + self.__source[line] = newText + return (1, self.trUtf8("Extraneous whitespace removed."), 0) + + def __fixE261(self, code, line, pos): + """ + Private method to fix whitespace before or after inline comment. + + Codes: E261, E262 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + line = line - 1 + text = self.__source[line] + left = text[:pos].rstrip(' \t#') + right = text[pos:].lstrip(' \t#') + newText = left + (" # " + right if right.strip() else right) + self.__source[line] = newText + return (1, self.trUtf8("Whitespace around comment sign corrected."), 0) + + def __fixE301(self, code, line, pos, apply=False): + """ + Private method to fix the need for one blank line. + + Codes: E301 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + self.__source.insert(line - 1, self.__getEol()) + return (1, self.trUtf8("One blank line inserted."), 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE302(self, code, line, pos, apply=False): + """ + Private method to fix the need for two blank lines. + + Codes: E302 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + # count blank lines + index = line - 1 + blanks = 0 + while index: + if self.__source[index - 1].strip() == "": + blanks += 1 + index -= 1 + else: + break + delta = blanks - 2 + + line -= 1 + if delta < 0: + # insert blank lines (one or two) + while delta < 0: + self.__source.insert(line, self.__getEol()) + delta += 1 + changed = True + elif delta > 0: + # delete superfluous blank lines + while delta > 0: + del self.__source[line - 1] + line -= 1 + delta -= 1 + changed = True + else: + changed = False + + if changed: + if delta < 0: + msg = self.trUtf8( + "%n blank line(s) inserted.", "", -delta) + elif delta > 0: + msg = self.trUtf8( + "%n superfluous lines removed", "", delta) + else: + msg = "" + return (1, msg, 0) + return (0, "", 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE303(self, code, line, pos, apply=False): + """ + Private method to fix superfluous blank lines. + + Codes: E303 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + index = line - 3 + while index: + if self.__source[index].strip() == "": + del self.__source[index] + index -= 1 + else: + break + return (1, self.trUtf8("Superfluous blank lines removed."), 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE304(self, code, line, pos, apply=False): + """ + Private method to fix superfluous blank lines after a function + decorator. + + Codes: E304 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + index = line - 2 + while index: + if self.__source[index].strip() == "": + del self.__source[index] + index -= 1 + else: + break + return (1, self.trUtf8( + "Superfluous blank lines after function decorator removed."), + 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE401(self, code, line, pos, apply=False): + """ + Private method to fix multiple imports on one line. + + Codes: E401 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + text = self.__source[line] + if not text.lstrip().startswith("import"): + return (0, "", 0) + + # pep8 (1.3.1) reports false positive if there is an import + # statement followed by a semicolon and some unrelated + # statement with commas in it. + if ';' in text: + return (0, "", 0) + + newText = text[:pos].rstrip("\t ,") + self.__getEol() + \ + self.__getIndent(text) + "import " + text[pos:].lstrip("\t ,") + self.__source[line] = newText + return (1, self.trUtf8("Imports were put on separate lines."), 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE501(self, code, line, pos, apply=False): + """ + Private method to fix the long lines by breaking them. + + Codes: E501 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + multilineStringLines, docStringLines = \ + self.__multilineStringLines() + isDocString = line in docStringLines + line = line - 1 + text = self.__source[line] + if line > 0: + prevText = self.__source[line - 1] + else: + prevText = "" + if line < len(self.__source) - 1: + nextText = self.__source[line + 1] + else: + nextText = "" + shortener = LineShortener( + text, prevText, nextText, + maxLength=self.__maxLineLength, eol=self.__getEol(), + indentWord=self.__indentWord, isDocString=isDocString) + changed, newText, newNextText = shortener.shorten() + if changed: + if newText != text: + self.__source[line] = newText + if newNextText and newNextText != nextText: + self.__source[line + 1] = newNextText + return (1, self.trUtf8("Long lines have been shortened."), 0) + else: + return (0, "", 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE502(self, code, line, pos): + """ + Private method to fix redundant backslash within brackets. + + Codes: E502 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + self.__source[line - 1] = \ + self.__source[line - 1].rstrip("\n\r \t\\") + self.__getEol() + return (1, self.trUtf8("Redundant backslash in brackets removed."), 0) + + def __fixE701(self, code, line, pos, apply=False): + """ + Private method to fix colon-separated compound statements. + + Codes: E701 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + text = self.__source[line] + pos = pos + 1 + + newText = text[:pos] + self.__getEol() + self.__getIndent(text) + \ + self.__indentWord + text[pos:].lstrip("\n\r \t\\") + \ + self.__getEol() + self.__source[line] = newText + return (1, self.trUtf8("Compound statement corrected."), 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE702(self, code, line, pos, apply=False): + """ + Private method to fix semicolon-separated compound statements. + + Codes: E702, E703 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + text = self.__source[line] + + if text.rstrip().endswith("\\"): + # normalize '1; \\\n2' into '1; 2' + self.__source[line] = text.rstrip("\n\r \t\\") + self.__source[line + 1] = self.__source[line + 1].lstrip() + elif text.rstrip().endswith(";"): + self.__source[line] = text.rstrip("\n\r \t;") + self.__getEol() + else: + first = text[:pos].rstrip("\n\r \t;") + self.__getEol() + second = text[pos:].lstrip("\n\r \t;") + self.__source[line] = first + self.__getIndent(text) + second + return (1, self.trUtf8("Compound statement corrected."), 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixE711(self, code, line, pos): + """ + Private method to fix comparison with None. + + Codes: E711, E712 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + line = line - 1 + text = self.__source[line] + + rightPos = pos + 2 + if rightPos >= len(text): + return (0, "", 0) + + left = text[:pos].rstrip() + center = text[pos:rightPos] + right = text[rightPos:].lstrip() + + if not right.startswith(("None", "True", "False")): + return (0, "", 0) + + if center.strip() == "==": + center = "is" + elif center.strip() == "!=": + center = "is not" + else: + return (0, "", 0) + + self.__source[line] = " ".join([left, center, right]) + return (1, self.trUtf8("Comparison to None/True/False corrected."), 0) + + def __fixN804(self, code, line, pos, apply=False): + """ + Private method to fix a wrong first argument of normal and + class methods. + + Codes: N804, N805 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + text = self.__source[line] + if code == "N804": + arg = "cls" + else: + arg = "self" + + if text.rstrip().endswith("("): + newText = text + self.__getIndent(text) + \ + self.__indentWord + arg + "," + self.__getEol() + else: + index = text.find("(") + 1 + left = text[:index] + right = text[index:] + if right.startswith(")"): + center = arg + else: + center = arg + ", " + newText = left + center + right + self.__source[line] = newText + return (1, self.trUtf8("'{0}' argument added.").format(arg), 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixN806(self, code, line, pos, apply=False): + """ + Private method to fix a wrong first argument of static methods. + + Codes: N806 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @keyparam apply flag indicating, that the fix should be applied + (boolean) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + if apply: + line = line - 1 + text = self.__source[line] + index = text.find("(") + 1 + left = text[:index] + right = text[index:] + + if right.startswith(("cls", "self")): + # cls or self are on the definition line + if right.startswith("cls"): + right = right[3:] + arg = "cls" + else: + right = right[4:] + arg = "self" + right = right.lstrip(", ") + newText = left + right + self.__source[line] = newText + else: + # they are on the next line + line = line + 1 + text = self.__source[line] + indent = self.__getIndent(text) + right = text.lstrip() + if right.startswith("cls"): + right = right[3:] + arg = "cls" + else: + right = right[4:] + arg = "self" + right = right.lstrip(", ") + if right.startswith("):"): + # merge with previous line + self.__source[line - 1] = \ + self.__source[line - 1].rstrip() + right + self.__source[line] = "" + else: + self.__source[line] = indent + right + + return (1, self.trUtf8("'{0}' argument removed.").format(arg), 0) + else: + id = self.__getID() + self.__stack.append((id, code, line, pos)) + return (-1, "", id) + + def __fixW291(self, code, line, pos): + """ + Private method to fix trailing whitespace. + + Codes: W291, W293 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + self.__source[line - 1] = re.sub(r'[\t ]+(\r?)$', r"\1", + self.__source[line - 1]) + return (1, self.trUtf8("Whitespace stripped from end of line."), 0) + + def __fixW292(self, code, line, pos): + """ + Private method to fix a missing newline at the end of file. + + Codes: W292 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + self.__source[line - 1] += self.__getEol() + return (1, self.trUtf8("newline added to end of file."), 0) + + def __fixW391(self, code, line, pos): + """ + Private method to fix trailing blank lines. + + Codes: W391 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + index = line - 1 + while index: + if self.__source[index].strip() == "": + del self.__source[index] + index -= 1 + else: + break + return (1, self.trUtf8( + "Superfluous trailing blank lines removed from end of file."), 0) + + def __fixW603(self, code, line, pos): + """ + Private method to fix the not equal notation. + + Codes: W603 + + @param code code of the issue (string) + @param line line number of the issue (integer) + @param pos position inside line (integer) + @return value indicating an applied/deferred fix (-1, 0, 1), + a message for the fix (string) and an ID for a deferred + fix (integer) + """ + self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=") + return (1, self.trUtf8("'<>' replaced by '!='."), 0) + + +class Reindenter(object): + """ + Class to reindent badly-indented code to uniformly use four-space + indentation. + + Released to the public domain, by Tim Peters, 03 October 2000. + """ + def __init__(self, sourceLines): + """ + Constructor + + @param sourceLines list of source lines including eol marker + (list of string) + """ + # Raw file lines. + self.raw = sourceLines + self.after = [] + + # File lines, rstripped & tab-expanded. Dummy at start is so + # that we can use tokenize's 1-based line numbering easily. + # Note that a line is all-blank iff it's "\n". + self.lines = [line.rstrip().expandtabs() + "\n" + for line in self.raw] + self.lines.insert(0, None) + self.index = 1 # index into self.lines of next line + + # List of (lineno, indentlevel) pairs, one for each stmt and + # comment line. indentlevel is -1 for comment lines, as a + # signal that tokenize doesn't know what to do about them; + # indeed, they're our headache! + self.stats = [] + + def run(self): + """ + Public method to run the re-indenter. + + @return flag indicating that a change was done (boolean) + """ + try: + stats = self.__genStats(tokenize.generate_tokens(self.getline)) + except (SyntaxError, tokenize.TokenError): + return False + + # Remove trailing empty lines. + lines = self.lines + while lines and lines[-1] == "\n": + lines.pop() + # Sentinel. + stats.append((len(lines), 0)) + # Map count of leading spaces to # we want. + have2want = {} + # Program after transformation. + after = self.after = [] + # Copy over initial empty lines -- there's nothing to do until + # we see a line with *something* on it. + i = stats[0][0] + after.extend(lines[1:i]) + for i in range(len(stats) - 1): + thisstmt, thislevel = stats[i] + nextstmt = stats[i + 1][0] + have = self.__getlspace(lines[thisstmt]) + want = thislevel * 4 + if want < 0: + # A comment line. + if have: + # An indented comment line. If we saw the same + # indentation before, reuse what it most recently + # mapped to. + want = have2want.get(have, -1) + if want < 0: + # Then it probably belongs to the next real stmt. + for j in range(i + 1, len(stats) - 1): + jline, jlevel = stats[j] + if jlevel >= 0: + if have == self.__getlspace(lines[jline]): + want = jlevel * 4 + break + if want < 0: # Maybe it's a hanging + # comment like this one, + # in which case we should shift it like its base + # line got shifted. + for j in range(i - 1, -1, -1): + jline, jlevel = stats[j] + if jlevel >= 0: + want = \ + have + \ + self.__getlspace(after[jline - 1]) - \ + self.__getlspace(lines[jline]) + break + if want < 0: + # Still no luck -- leave it alone. + want = have + else: + want = 0 + assert want >= 0 + have2want[have] = want + diff = want - have + if diff == 0 or have == 0: + after.extend(lines[thisstmt:nextstmt]) + else: + for line in lines[thisstmt:nextstmt]: + if diff > 0: + if line == "\n": + after.append(line) + else: + after.append(" " * diff + line) + else: + remove = min(self.__getlspace(line), -diff) + after.append(line[remove:]) + return self.raw != self.after + + def fixedLine(self, line): + """ + Public method to get a fixed line. + + @param line number of the line to retrieve (integer) + @return fixed line (string) + """ + if line < len(self.after): + return self.after[line] + + def getline(self): + """ + Public method to get a line of text for tokenize. + + @return line of text (string) + """ + if self.index >= len(self.lines): + line = "" + else: + line = self.lines[self.index] + self.index += 1 + return line + + def __genStats(self, tokens): + """ + Private method to generate the re-indent statistics. + + @param tokens tokens generator (tokenize._tokenize) + @return reference to the generated statistics + """ + find_stmt = True # next token begins a fresh stmt? + level = 0 # current indent level + stats = [] + + for t in tokens: + token_type = t[0] + sline = t[2][0] + line = t[4] + + if token_type == tokenize.NEWLINE: + # A program statement, or ENDMARKER, will eventually follow, + # after some (possibly empty) run of tokens of the form + # (NL | COMMENT)* (INDENT | DEDENT+)? + self.find_stmt = True + + elif token_type == tokenize.INDENT: + find_stmt = True + level += 1 + + elif token_type == tokenize.DEDENT: + find_stmt = True + level -= 1 + + elif token_type == tokenize.COMMENT: + if find_stmt: + stats.append((sline, -1)) + # but we're still looking for a new stmt, so leave + # find_stmt alone + + elif token_type == tokenize.NL: + pass + + elif find_stmt: + # This is the first "real token" following a NEWLINE, so it + # must be the first token of the next program statement, or an + # ENDMARKER. + find_stmt = False + if line: # not endmarker + stats.append((sline, level)) + + return stats + + def __getlspace(self, line): + """ + Private method to count number of leading blanks. + + @param line line to check (string) + @return number of leading blanks (integer) + """ + i = 0 + n = len(line) + while i < n and line[i] == " ": + i += 1 + return i + + +class IndentationWrapper(object): + """ + Class used by fixers dealing with indentation. + + Each instance operates on a single logical line. + """ + SKIP_TOKENS = frozenset([ + tokenize.COMMENT, tokenize.NL, tokenize.INDENT, + tokenize.DEDENT, tokenize.NEWLINE, tokenize.ENDMARKER + ]) + + def __init__(self, physical_lines): + """ + Constructor + + @param physical_lines list of physical lines to operate on + (list of strings) + """ + self.lines = physical_lines + self.tokens = [] + self.rel_indent = None + sio = io.StringIO(''.join(physical_lines)) + for t in tokenize.generate_tokens(sio.readline): + if not len(self.tokens) and t[0] in self.SKIP_TOKENS: + continue + if t[0] != tokenize.ENDMARKER: + self.tokens.append(t) + + self.logical_line = self.__buildTokensLogical(self.tokens) + + def __buildTokensLogical(self, tokens): + """ + Private method to build a logical line from a list of tokens. + + @param tokens list of tokens as generated by tokenize.generate_tokens + @return logical line (string) + """ + # from pep8.py with minor modifications + logical = [] + previous = None + for t in tokens: + token_type, text = t[0:2] + if token_type in self.SKIP_TOKENS: + continue + if previous: + end_line, end = previous[3] + start_line, start = t[2] + if end_line != start_line: # different row + prev_text = self.lines[end_line - 1][end - 1] + if prev_text == ',' or (prev_text not in '{[(' + and text not in '}])'): + logical.append(' ') + elif end != start: # different column + fill = self.lines[end_line - 1][end:start] + logical.append(fill) + logical.append(text) + previous = t + logical_line = ''.join(logical) + assert logical_line.lstrip() == logical_line + assert logical_line.rstrip() == logical_line + return logical_line + + def pep8Expected(self): + """ + Public method to replicate logic in pep8.py, to know what level to + indent things to. + + @return list of lists, where each list represents valid indent levels + for the line in question, relative from the initial indent. However, + the first entry is the indent level which was expected. + """ + # What follows is an adjusted version of + # pep8.py:continuation_line_indentation. All of the comments have been + # stripped and the 'yield' statements replaced with 'pass'. + if not self.tokens: + return + + first_row = self.tokens[0][2][0] + nrows = 1 + self.tokens[-1][2][0] - first_row + + # here are the return values + valid_indents = [list()] * nrows + indent_level = self.tokens[0][2][1] + valid_indents[0].append(indent_level) + + if nrows == 1: + # bug, really. + return valid_indents + + indent_next = self.logical_line.endswith(':') + + row = depth = 0 + parens = [0] * nrows + self.rel_indent = rel_indent = [0] * nrows + indent = [indent_level] + indent_chances = {} + last_indent = (0, 0) + last_token_multiline = None + + for token_type, text, start, end, line in self.tokens: + newline = row < start[0] - first_row + if newline: + row = start[0] - first_row + newline = (not last_token_multiline and + token_type not in (tokenize.NL, tokenize.NEWLINE)) + + if newline: + # This is where the differences start. Instead of looking at + # the line and determining whether the observed indent matches + # our expectations, we decide which type of indentation is in + # use at the given indent level, and return the offset. This + # algorithm is susceptible to "carried errors", but should + # through repeated runs eventually solve indentation for + # multiline expressions. + + if depth: + for open_row in range(row - 1, -1, -1): + if parens[open_row]: + break + else: + open_row = 0 + + # That's all we get to work with. This code attempts to + # "reverse" the below logic, and place into the valid indents + # list + vi = [] + add_second_chances = False + if token_type == tokenize.OP and text in ']})': + # this line starts with a closing bracket, so it needs to + # be closed at the same indent as the opening one. + if indent[depth]: + # hanging indent + vi.append(indent[depth]) + else: + # visual indent + vi.append(indent_level + rel_indent[open_row]) + elif depth and indent[depth]: + # visual indent was previously confirmed. + vi.append(indent[depth]) + add_second_chances = True + elif depth and True in indent_chances.values(): + # visual indent happened before, so stick to + # visual indent this time. + if depth > 1 and indent[depth - 1]: + vi.append(indent[depth - 1]) + else: + # stupid fallback + vi.append(indent_level + 4) + add_second_chances = True + elif not depth: + vi.append(indent_level + 4) + else: + # must be in hanging indent + hang = rel_indent[open_row] + 4 + vi.append(indent_level + hang) + + # about the best we can do without look-ahead + if (indent_next and vi[0] == indent_level + 4 and + nrows == row + 1): + vi[0] += 4 + + if add_second_chances: + # visual indenters like to line things up. + min_indent = vi[0] + for col, what in indent_chances.items(): + if col > min_indent and ( + what is True or + (what == str and token_type == tokenize.STRING) or + (what == text and token_type == tokenize.OP) + ): + vi.append(col) + vi = sorted(vi) + + valid_indents[row] = vi + + # Returning to original continuation_line_indentation() from + # pep8. + visual_indent = indent_chances.get(start[1]) + last_indent = start + rel_indent[row] = pep8.expand_indent(line) - indent_level + hang = rel_indent[row] - rel_indent[open_row] + + if token_type == tokenize.OP and text in ']})': + pass + elif visual_indent is True: + if not indent[depth]: + indent[depth] = start[1] + + # line altered: comments shouldn't define a visual indent + if parens[row] and not indent[depth] and token_type not in ( + tokenize.NL, tokenize.COMMENT + ): + indent[depth] = start[1] + indent_chances[start[1]] = True + elif token_type == tokenize.STRING or text in ( + 'u', 'ur', 'b', 'br' + ): + indent_chances[start[1]] = str + + if token_type == tokenize.OP: + if text in '([{': + depth += 1 + indent.append(0) + parens[row] += 1 + elif text in ')]}' and depth > 0: + prev_indent = indent.pop() or last_indent[1] + for d in range(depth): + if indent[d] > prev_indent: + indent[d] = 0 + for ind in list(indent_chances): + if ind >= prev_indent: + del indent_chances[ind] + depth -= 1 + if depth and indent[depth]: # modified + indent_chances[indent[depth]] = True + for idx in range(row, -1, -1): + if parens[idx]: + parens[idx] -= 1 + break + assert len(indent) == depth + 1 + if start[1] not in indent_chances: + indent_chances[start[1]] = text + + last_token_multiline = (start[0] != end[0]) + + return valid_indents + + +class LineShortener(object): + """ + Class used to shorten lines to a given maximum of characters. + """ + def __init__(self, curLine, prevLine, nextLine, maxLength=79, eol="\n", + indentWord=" ", isDocString=False): + """ + Constructor + + @param curLine text to work on (string) + @param prevLine line before the text to work on (string) + @param nextLine line after the text to work on (string) + @keyparam maxLength maximum allowed line length (integer) + @keyparam eol eond-of-line marker (string) + @keyparam indentWord string used for indentation (string) + @keyparam isDocString flag indicating that the line belongs to + a documentation string (boolean) + """ + self.__text = curLine + self.__prevText = prevLine + self.__nextText = nextLine + self.__maxLength = maxLength + self.__eol = eol + self.__indentWord = indentWord + self.__isDocString = isDocString + + def shorten(self): + """ + Public method to shorten the line wrapped by the class instance. + + @return tuple of a flag indicating successful shortening, the + shortened line and the changed next line (boolean, string, string) + """ + # 1. check for comment + if self.__text.lstrip().startswith('#'): + lastComment = True + if self.__nextText.lstrip().startswith('#'): + lastComment = False + + # Wrap commented lines. + newText = self.__shortenComment(lastComment) + if newText == self.__text: + return False, "", "" + else: + return True, newText, "" + elif '#' in self.__text: + pos = self.__text.rfind("#") + newText = self.__text[:pos].rstrip() + self.__eol + \ + self.__getIndent(self.__text) + self.__text[pos:] + if newText == self.__text: + return False, "", "" + else: + return True, newText, "" + + # Do multi line doc strings + if self.__isDocString: + source = self.__text.rstrip() + blank = source.rfind(" ") + while blank > self.__maxLength and blank != -1: + blank = source.rfind(" ", 0, blank) + if blank == -1: + # Cannot break + return False, "", "" + else: + first = self.__text[:blank] + second = self.__text[blank:].lstrip() + if self.__nextText.strip(): + if self.__nextText.lstrip().startswith("@"): + # eric doc comment + # create a new line and indent it + newText = first + self.__eol + \ + self.__getIndent(first) + self.__indentWord + \ + second + newNext = "" + else: + newText = first + self.__eol + newNext = self.__getIndent(self.__nextText) + \ + second.rstrip() + " " + self.__nextText.lstrip() + else: + # empty line, add a new line + newText = first + self.__eol + self.__getIndent(first) + \ + second + newNext = "" + return True, newText, newNext + + indent = self.__getIndent(self.__text) + source = self.__text[len(indent):] + assert source.lstrip() == source + sio = io.StringIO(source) + + # Check for multi line string. + try: + tokens = list(tokenize.generate_tokens(sio.readline)) + except (SyntaxError, tokenize.TokenError): + if source.rstrip().endswith("\\"): + # just join the continuation line and let the next run + # handle it once it tokenizes ok + newText = indent + source.rstrip()[:-1].rstrip() + " " + \ + self.__nextText.lstrip() + if indent: + newNext = indent + else: + newNext = " " + return True, newText, newNext + else: + multilineCandidate = self.__breakMultiline() + if multilineCandidate: + return True, multilineCandidate[0], multilineCandidate[1] + else: + return False, "", "" + + # Handle statements by putting the right hand side on a line by itself. + # This should let the next pass shorten it. + if source.startswith('return '): + newText = ( + indent + + 'return (' + + self.__eol + + indent + self.__indentWord + re.sub('^return ', '', source) + + indent + ')' + self.__eol + ) + return True, newText, "" + + candidates = self.__shortenLine(tokens, source, indent) + if candidates: + candidates = list(sorted( + set(candidates).union([self.__text]), + key=lambda x: self.__lineShorteningRank(x))) + if candidates[0] == self.__text: + return False, "", "" + return True, candidates[0], "" + + source = self.__text + rs = source.rstrip() + if rs.endswith(("'", '"')) and " " in source: + if rs.endswith(('"""', "'''")): + quote = rs[-3:] + else: + quote = rs[-1] + blank = source.rfind(" ") + maxLen = self.__maxLength - 2 - len(quote) + while blank > maxLen and blank != -1: + blank = source.rfind(" ", 0, blank) + if blank != -1: + if source[blank + 1:].startswith(quote): + first = source[:maxLen] + second = source[maxLen:] + else: + first = source[:blank] + second = source[blank + 1:] + return ( + True, + first + quote + " \\" + self.__eol + + indent + self.__indentWord + quote + second, + "") + else: + # Cannot break + return False, "", "" + + return False, "", "" + + def __shortenComment(self, isLast): + """ + Private method to shorten a comment line. + + @param isLast flag indicating, that the line is the last comment line + (boolean) + @return shortened comment line (string) + """ + if len(self.__text) <= self.__maxLength: + return self.__text + + newText = self.__text.rstrip() + + # PEP 8 recommends 72 characters for comment text. + indentation = self.__getIndent(newText) + '# ' + maxLength = min(self.__maxLength, + len(indentation) + 72) + + MIN_CHARACTER_REPEAT = 5 + if len(newText) - len(newText.rstrip(newText[-1])) >= \ + MIN_CHARACTER_REPEAT and \ + not newText[-1].isalnum(): + # Trim comments that end with things like --------- + return newText[:maxLength] + self.__eol + elif isLast and re.match(r"\s*#+\s*\w+", newText): + import textwrap + splitLines = textwrap.wrap(newText.lstrip(" \t#"), + initial_indent=indentation, + subsequent_indent=indentation, + width=maxLength, + break_long_words=False, + break_on_hyphens=False) + return self.__eol.join(splitLines) + self.__eol + else: + return newText + self.__eol + + def __breakMultiline(self): + """ + Private method to break multi line strings. + + @return tuple of the shortened line and the changed next line + (string, string) + """ + indentation = self.__getIndent(self.__text) + + # Handle special case. + for symbol in '([{': + # Only valid if symbol is not on a line by itself. + if ( + symbol in self.__text and + self.__text.strip() != symbol and + self.__text.rstrip().endswith((',', '%')) + ): + index = 1 + self.__text.find(symbol) + + if index <= len(self.__indentWord) + len(indentation): + continue + + if self.__isProbablyInsideStringOrComment( + self.__text, index - 1): + continue + + return (self.__text[:index].rstrip() + self.__eol + + indentation + self.__indentWord + + self.__text[index:].lstrip(), "") + + newText = self.__text + newNext = self.__nextText + blank = newText.rfind(" ") + while blank > self.__maxLength and blank != -1: + blank = newText.rfind(" ", 0, blank) + if blank != -1: + first = self.__text[:blank] + second = self.__text[blank:].strip() + if newNext.strip(): + newText = first + self.__eol + newNext = self.__getIndent(newNext) + \ + second + " " + newNext.lstrip() + else: + # empty line, add a new line + newText = first + self.__eol + newNext = self.__getIndent(newNext) + \ + second + self.__eol + newNext.lstrip() + return newText, newNext + + def __isProbablyInsideStringOrComment(self, line, index): + """ + Private method to check, if the given string might be inside a string + or comment. + + @param line line to check (string) + @param index position inside line to check (integer) + @return flag indicating the possibility of being inside a string + or comment + """ + # Check against being in a string. + for quote in ['"', "'"]: + pos = line.find(quote) + if pos != -1 and pos <= index: + return True + + # Check against being in a comment. + pos = line.find('#') + if pos != -1 and pos <= index: + return True + + return False + + def __shortenLine(self, tokens, source, indent): + """ + Private method to shorten a line of code at an operator. + + @param tokens tokens of the line as generated by tokenize + (list of token) + @param source code string to work at (string) + @param indent indentation string of the code line (string) + @return list of candidates (list of string) + """ + candidates = [] + + for tkn in tokens: + tokenType = tkn[0] + tokenString = tkn[1] + + if ( + tokenType == tokenize.COMMENT and + not self.__prevText.rstrip().endswith('\\') + ): + # Move inline comments to previous line. + offset = tkn[2][1] + first = source[:offset] + second = source[offset:] + candidates.append( + indent + second.strip() + self.__eol + + indent + first.strip() + self.__eol) + elif tokenType == tokenize.OP and tokenString != '=': + # Don't break on '=' after keyword as this violates PEP 8. + + assert tokenType != tokenize.INDENT + + offset = tkn[2][1] + 1 + first = source[:offset] + + secondIndent = indent + if first.rstrip().endswith('('): + secondIndent += self.__indentWord + elif '(' in first: + secondIndent += ' ' * (1 + first.find('(')) + else: + secondIndent += self.__indentWord + + second = (secondIndent + source[offset:].lstrip()) + if not second.strip(): + continue + + # Do not begin a line with a comma + if second.lstrip().startswith(','): + continue + + # Do end a line with a dot + if first.rstrip().endswith('.'): + continue + + if tokenString in '+-*/': + newText = first + ' \\' + self.__eol + second + else: + newText = first + self.__eol + second + + # Only fix if syntax is okay. + if self.__checkSyntax(self.__normalizeMultiline(newText)): + candidates.append(indent + newText) + + return candidates + + def __normalizeMultiline(self, text): + """ + Private method to remove multiline-related code that will cause syntax + error. + + @param text code line to work on (string) + @return normalized code line (string) + """ + for quote in '\'"': + dictPattern = r"^{q}[^{q}]*{q} *: *".format(q=quote) + if re.match(dictPattern, text): + if not text.strip().endswith('}'): + text += '}' + return '{' + text + + if text.startswith('def ') and text.rstrip().endswith(':'): + # Do not allow ':' to be alone. That is invalid. + splitText = [item.strip() for item in text.split(self.__eol)] + if ':' not in splitText and 'def' not in splitText: + return text[len('def'):].strip().rstrip(':') + + return text + + def __lineShorteningRank(self, candidate): + """ + Private method to rank a candidate. + + @param candidate candidate line to rank (string) + @return rank of the candidate (integer) + """ + rank = 0 + if candidate.strip(): + if candidate == self.__text: + # give the original a disadvantage + rank += 50 + + lines = candidate.split(self.__eol) + + offset = 0 + if lines[0].rstrip()[-1] not in '([{': + for symbol in '([{': + offset = max(offset, 1 + lines[0].find(symbol)) + + maxLength = max([offset + len(x.strip()) for x in lines]) + rank += maxLength + rank += len(lines) + + badStartingSymbol = { + '(': ')', + '[': ']', + '{': '}'}.get(lines[0][-1], None) + + if len(lines) > 1: + if (badStartingSymbol and + lines[1].lstrip().startswith(badStartingSymbol)): + rank += 20 + + if re.match(r".*[+\-\*/] \($", lines[0]): + # "1 * (\n" is ugly as hell. + rank += 100 + + for currentLine in lines: + for badStart in ['.', '%', '+', '-', '/']: + if currentLine.startswith(badStart): + rank += 100 + + for ending in '([{': + # Avoid lonely opening. They result in longer lines. + if currentLine.endswith(ending) and \ + len(currentLine.strip()) <= len(self.__indentWord): + rank += 100 + + if currentLine.endswith('%'): + rank -= 20 + + # Try to break list comprehensions at the "for". + if currentLine.lstrip().startswith('for'): + rank -= 50 + + rank += 10 * self.__countUnbalancedBrackets(currentLine) + else: + rank = 100000 + + return max(0, rank) + + def __countUnbalancedBrackets(self, line): + """ + Private method to determine the number of unmatched open/close + brackets. + + @param line line to work at (string) + @return number of unmatched open/close brackets (integer) + """ + count = 0 + for opening, closing in ['()', '[]', '{}']: + count += abs(line.count(opening) - line.count(closing)) + + return count + + def __getIndent(self, line): + """ + Private method to get the indentation string. + + @param line line to determine the indentation string from (string) + @return indentation string (string) + """ + # copied from CodeStyleFixer + return line.replace(line.lstrip(), "") + + def __checkSyntax(self, code): + """ + Private method to check the syntax of the given code fragment. + + @param code code fragment to check (string) + @return flag indicating syntax is ok (boolean) + """ + code = code.replace("\r\n", "\n").replace("\r", "\n") + try: + return compile(code, '<string>', 'exec') + except (SyntaxError, TypeError, UnicodeDecodeError): + return False
--- a/Plugins/CheckerPlugins/Pep8/Pep8Fixer.py Tue Oct 01 18:22:33 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2703 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2011 - 2013 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing a class to fix certain code style issues. -""" - -import os -import re -import tokenize -import io - -from PyQt4.QtCore import QObject - -from E5Gui import E5MessageBox - -from . import pep8 - -import Utilities - -Pep8FixableIssues = ["D111", "D112", "D113", "D121", "D131", "D141", - "D142", "D143", "D144", "D145", - "D221", "D222", "D231", "D242", "D243", "D244", - "D245", "D246", "D247", - "E101", "E111", "E121", "E122", "E123", "E124", - "E125", "E126", "E127", "E128", "E133", "E201", - "E202", "E203", "E211", "E221", "E222", "E223", - "E224", "E225", "E226", "E227", "E228", "E231", - "E241", "E242", "E251", "E261", "E262", "E271", - "E272", "E273", "E274", "E301", "E302", "E303", - "E304", "E401", "E501", "E502", "E701", "E702", - "E703", "E711", "E712", - "N804", "N805", "N806", - "W191", "W291", "W292", "W293", "W391", "W603", - ] - - -class Pep8Fixer(QObject): - """ - Class implementing a fixer for certain code style issues. - """ - def __init__(self, project, filename, sourceLines, fixCodes, noFixCodes, - maxLineLength, inPlace): - """ - Constructor - - @param project reference to the project object (Project) - @param filename name of the file to be fixed (string) - @param sourceLines list of source lines including eol marker - (list of string) - @param fixCodes list of codes to be fixed as a comma separated - string (string) - @param noFixCodes list of codes not to be fixed as a comma - separated string (string) - @param maxLineLength maximum allowed line length (integer) - @param inPlace flag indicating to modify the file in place (boolean) - """ - super().__init__() - - self.__project = project - self.__filename = filename - self.__origName = "" - self.__source = sourceLines[:] # save a copy - self.__fixCodes = [c.strip() for c in fixCodes.split(",") if c.strip()] - self.__noFixCodes = [ - c.strip() for c in noFixCodes.split(",") if c.strip()] - self.__maxLineLength = maxLineLength - self.fixed = 0 - - self.__reindenter = None - self.__eol = "" - self.__indentWord = self.__getIndentWord() - - if not inPlace: - self.__origName = self.__filename - self.__filename = os.path.join( - os.path.dirname(self.__filename), - "fixed_" + os.path.basename(self.__filename)) - - self.__fixes = { - "D111": self.__fixD111, - "D112": self.__fixD112, - "D113": self.__fixD112, - "D121": self.__fixD121, - "D131": self.__fixD131, - "D141": self.__fixD141, - "D142": self.__fixD142, - "D143": self.__fixD143, - "D144": self.__fixD144, - "D145": self.__fixD145, - "D221": self.__fixD221, - "D222": self.__fixD221, - "D231": self.__fixD131, - "D242": self.__fixD242, - "D243": self.__fixD243, - "D244": self.__fixD242, - "D245": self.__fixD243, - "D246": self.__fixD144, - "D247": self.__fixD247, - "E101": self.__fixE101, - "E111": self.__fixE101, - "E121": self.__fixE121, - "E122": self.__fixE122, - "E123": self.__fixE123, - "E124": self.__fixE121, - "E125": self.__fixE125, - "E126": self.__fixE126, - "E127": self.__fixE127, - "E128": self.__fixE127, - "E133": self.__fixE126, - "E201": self.__fixE201, - "E202": self.__fixE201, - "E203": self.__fixE201, - "E211": self.__fixE201, - "E221": self.__fixE221, - "E222": self.__fixE221, - "E223": self.__fixE221, - "E224": self.__fixE221, - "E225": self.__fixE221, - "E226": self.__fixE221, - "E227": self.__fixE221, - "E228": self.__fixE221, - "E231": self.__fixE231, - "E241": self.__fixE221, - "E242": self.__fixE221, - "E251": self.__fixE251, - "E261": self.__fixE261, - "E262": self.__fixE261, - "E271": self.__fixE221, - "E272": self.__fixE221, - "E273": self.__fixE221, - "E274": self.__fixE221, - "E301": self.__fixE301, - "E302": self.__fixE302, - "E303": self.__fixE303, - "E304": self.__fixE304, - "E401": self.__fixE401, - "E501": self.__fixE501, - "E502": self.__fixE502, - "E701": self.__fixE701, - "E702": self.__fixE702, - "E703": self.__fixE702, - "E711": self.__fixE711, - "E712": self.__fixE711, - "N804": self.__fixN804, - "N805": self.__fixN804, - "N806": self.__fixN806, - "W191": self.__fixE101, - "W291": self.__fixW291, - "W292": self.__fixW292, - "W293": self.__fixW291, - "W391": self.__fixW391, - "W603": self.__fixW603, - } - self.__modified = False - self.__stackLogical = [] # these need to be fixed before the file - # is saved but after all other inline - # fixes. These work with logical lines. - self.__stack = [] # these need to be fixed before the file - # is saved but after all inline fixes - - self.__multiLineNumbers = None - self.__docLineNumbers = None - - self.__lastID = 0 - - def saveFile(self, encoding): - """ - Public method to save the modified file. - - @param encoding encoding of the source file (string) - @return flag indicating success (boolean) - """ - if not self.__modified: - # no need to write - return True - - txt = "".join(self.__source) - try: - Utilities.writeEncodedFile(self.__filename, txt, encoding) - except (IOError, Utilities.CodingError, UnicodeError) as err: - E5MessageBox.critical( - self, - self.trUtf8("Fix Code Style Issues"), - self.trUtf8( - """<p>Could not save the file <b>{0}</b>.""" - """ Skipping it.</p><p>Reason: {1}</p>""") - .format(self.__filename, str(err)) - ) - return False - - return True - - def __codeMatch(self, code): - """ - Private method to check, if the code should be fixed. - - @param code to check (string) - @return flag indicating it should be fixed (boolean) - """ - def mutualStartswith(a, b): - """ - Local helper method to compare the beginnings of two strings - against each other. - - @return flag indicating that one string starts with the other - (boolean) - """ - return b.startswith(a) or a.startswith(b) - - if self.__noFixCodes: - for noFixCode in [c.strip() for c in self.__noFixCodes]: - if mutualStartswith(code.lower(), noFixCode.lower()): - return False - - if self.__fixCodes: - for fixCode in [c.strip() for c in self.__fixCodes]: - if mutualStartswith(code.lower(), fixCode.lower()): - return True - return False - - return True - - def fixIssue(self, line, pos, message): - """ - Public method to fix the fixable issues. - - @param line line number of issue (integer) - @param pos character position of issue (integer) - @param message message text (string) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - code = message.split(None, 1)[0].strip() - - if line <= len(self.__source) and \ - self.__codeMatch(code) and \ - code in self.__fixes: - res = self.__fixes[code](code, line, pos) - if res[0] == 1: - self.__modified = True - self.fixed += 1 - else: - res = (0, "", 0) - - return res - - def finalize(self): - """ - Public method to apply all deferred fixes. - - @return dictionary containing the fix results - """ - results = {} - - # step 1: do fixes operating on logical lines first - for id_, code, line, pos in self.__stackLogical: - res, msg, _ = self.__fixes[code](code, line, pos, apply=True) - if res == 1: - self.__modified = True - self.fixed += 1 - results[id_] = (res, msg) - - # step 2: do fixes that change the number of lines - for id_, code, line, pos in reversed(self.__stack): - res, msg, _ = self.__fixes[code](code, line, pos, apply=True) - if res == 1: - self.__modified = True - self.fixed += 1 - results[id_] = (res, msg) - - return results - - def __getID(self): - """ - Private method to get the ID for a deferred fix. - - @return ID for a deferred fix (integer) - """ - self.__lastID += 1 - return self.__lastID - - def __getEol(self): - """ - Private method to get the applicable eol string. - - @return eol string (string) - """ - if not self.__eol: - if self.__origName: - fn = self.__origName - else: - fn = self.__filename - - if self.__project.isOpen() and self.__project.isProjectFile(fn): - self.__eol = self.__project.getEolString() - else: - self.__eol = Utilities.linesep() - return self.__eol - - def __findLogical(self): - """ - Private method to extract the index of all the starts and ends of - lines. - - @return tuple containing two lists of integer with start and end tuples - of lines - """ - logical_start = [] - logical_end = [] - last_newline = True - sio = io.StringIO("".join(self.__source)) - parens = 0 - for t in tokenize.generate_tokens(sio.readline): - if t[0] in [tokenize.COMMENT, tokenize.DEDENT, - tokenize.INDENT, tokenize.NL, - tokenize.ENDMARKER]: - continue - if not parens and t[0] in [tokenize.NEWLINE, tokenize.SEMI]: - last_newline = True - logical_end.append((t[3][0] - 1, t[2][1])) - continue - if last_newline and not parens: - logical_start.append((t[2][0] - 1, t[2][1])) - last_newline = False - if t[0] == tokenize.OP: - if t[1] in '([{': - parens += 1 - elif t[1] in '}])': - parens -= 1 - return logical_start, logical_end - - def __getLogical(self, line, pos): - """ - Private method to get the logical line corresponding to the given - position. - - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return tuple of a tuple of two integers giving the start of the - logical line, another tuple of two integers giving the end - of the logical line and a list of strings with the original - source lines - """ - try: - (logical_start, logical_end) = self.__findLogical() - except (SyntaxError, tokenize.TokenError): - return None - - line = line - 1 - ls = None - le = None - for i in range(0, len(logical_start)): - x = logical_end[i] - if x[0] > line or (x[0] == line and x[1] > pos): - le = x - ls = logical_start[i] - break - if ls is None: - return None - - original = self.__source[ls[0]:le[0] + 1] - return ls, le, original - - def __getIndentWord(self): - """ - Private method to determine the indentation type. - - @return string to be used for an indentation (string) - """ - sio = io.StringIO("".join(self.__source)) - indentWord = " " # default in case of failure - try: - for token in tokenize.generate_tokens(sio.readline): - if token[0] == tokenize.INDENT: - indentWord = token[1] - break - except (SyntaxError, tokenize.TokenError): - pass - return indentWord - - def __getIndent(self, line): - """ - Private method to get the indentation string. - - @param line line to determine the indentation string from (string) - @return indentation string (string) - """ - return line.replace(line.lstrip(), "") - - def __multilineStringLines(self): - """ - Private method to determine the line numbers that are within multi line - strings and these which are part of a documentation string. - - @return tuple of a set of line numbers belonging to a multi line - string and a set of line numbers belonging to a multi line - documentation string (tuple of two set of integer) - """ - if self.__multiLineNumbers is None: - source = "".join(self.__source) - sio = io.StringIO(source) - self.__multiLineNumbers = set() - self.__docLineNumbers = set() - previousTokenType = '' - try: - for t in tokenize.generate_tokens(sio.readline): - tokenType = t[0] - startRow = t[2][0] - endRow = t[3][0] - - if (tokenType == tokenize.STRING and startRow != endRow): - if previousTokenType != tokenize.INDENT: - self.__multiLineNumbers |= set( - range(startRow, 1 + endRow)) - else: - self.__docLineNumbers |= set( - range(startRow, 1 + endRow)) - - previousTokenType = tokenType - except (SyntaxError, tokenize.TokenError): - pass - - return self.__multiLineNumbers, self.__docLineNumbers - - def __fixReindent(self, line, pos, logical): - """ - Private method to fix a badly indented line. - - This is done by adding or removing from its initial indent only. - - @param line line number of the issue (integer) - @param pos position inside line (integer) - @param logical logical line structure - @return flag indicating a change was done (boolean) - """ - assert logical - ls, _, original = logical - - rewrapper = Pep8IndentationWrapper(original) - valid_indents = rewrapper.pep8Expected() - if not rewrapper.rel_indent: - return False - - if line > ls[0]: - # got a valid continuation line number - row = line - ls[0] - 1 - # always pick the first option for this - valid = valid_indents[row] - got = rewrapper.rel_indent[row] - else: - return False - - line1 = ls[0] + row - # always pick the expected indent, for now. - indent_to = valid[0] - - if got != indent_to: - orig_line = self.__source[line1] - new_line = ' ' * (indent_to) + orig_line.lstrip() - if new_line == orig_line: - return False - else: - self.__source[line1] = new_line - return True - else: - return False - - def __fixWhitespace(self, line, offset, replacement): - """ - Private method to correct whitespace at the given offset. - - @param line line to be corrected (string) - @param offset offset within line (integer) - @param replacement replacement string (string) - @return corrected line - """ - left = line[:offset].rstrip(" \t") - right = line[offset:].lstrip(" \t") - if right.startswith("#"): - return line - else: - return left + replacement + right - - def __fixD111(self, code, line, pos): - """ - Private method to fix docstring enclosed in wrong quotes. - - Codes: D111 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - line = line - 1 - left, right = self.__source[line].split("'''", 1) - self.__source[line] = left + '"""' + right - while line < len(self.__source): - if self.__source[line].rstrip().endswith("'''"): - left, right = self.__source[line].rsplit("'''", 1) - self.__source[line] = left + '"""' + right - break - line += 1 - - return ( - 1, - self.trUtf8( - "Triple single quotes converted to triple double quotes."), - 0) - - def __fixD112(self, code, line, pos): - """ - Private method to fix docstring 'r' or 'u' in leading quotes. - - Codes: D112, D113 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - line = line - 1 - if code == "D112": - insertChar = "r" - elif code == "D113": - insertChar = "u" - else: - return (0, "", 0) - - newText = self.__getIndent(self.__source[line]) + \ - insertChar + self.__source[line].lstrip() - self.__source[line] = newText - return ( - 1, - self.trUtf8('Introductory quotes corrected to be {0}"""') - .format(insertChar), - 0) - - def __fixD121(self, code, line, pos, apply=False): - """ - Private method to fix a single line docstring on multiple lines. - - Codes: D121 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - if not self.__source[line].lstrip().startswith( - ('"""', 'r"""', 'u"""')): - # only correctly formatted docstrings will be fixed - return (0, "", 0) - - docstring = self.__source[line].rstrip() + \ - self.__source[line + 1].strip() - if docstring.endswith('"""'): - docstring += self.__getEol() - else: - docstring += self.__source[line + 2].lstrip() - self.__source[line + 2] = "" - - self.__source[line] = docstring - self.__source[line + 1] = "" - return ( - 1, - self.trUtf8("Single line docstring put on one line."), - 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixD131(self, code, line, pos): - """ - Private method to fix a docstring summary not ending with a - period. - - Codes: D131 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - line = line - 1 - newText = "" - if self.__source[line].rstrip().endswith(('"""', "'''")) and \ - self.__source[line].lstrip().startswith(('"""', 'r"""', 'u"""')): - # it is a one-liner - newText = self.__source[line].rstrip()[:-3].rstrip() + "." + \ - self.__source[line].rstrip()[-3:] + self.__getEol() - else: - if line < len(self.__source) - 1 and \ - (not self.__source[line + 1].strip() or - self.__source[line + 1].lstrip().startswith("@") or - (self.__source[line + 1].strip() in ('"""', "'''") and - not self.__source[line].lstrip().startswith("@"))): - newText = self.__source[line].rstrip() + "." + self.__getEol() - - if newText: - self.__source[line] = newText - return (1, self.trUtf8("Period added to summary line."), 0) - else: - return (0, "", 0) - - def __fixD141(self, code, line, pos, apply=False): - """ - Private method to fix a function/method docstring preceded by a - blank line. - - Codes: D141 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - self.__source[line - 1] = "" - return ( - 1, - self.trUtf8( - "Blank line before function/method docstring removed."), - 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixD142(self, code, line, pos, apply=False): - """ - Private method to fix a class docstring not preceded by a - blank line. - - Codes: D142 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - self.__source[line] = self.__getEol() + self.__source[line] - return ( - 1, - self.trUtf8("Blank line inserted before class docstring."), - 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixD143(self, code, line, pos, apply=False): - """ - Private method to fix a class docstring not followed by a - blank line. - - Codes: D143 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - self.__source[line] += self.__getEol() - return ( - 1, - self.trUtf8("Blank line inserted after class docstring."), - 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixD144(self, code, line, pos, apply=False): - """ - Private method to fix a docstring summary not followed by a - blank line. - - Codes: D144 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - if not self.__source[line].rstrip().endswith("."): - # only correct summary lines can be fixed here - return (0, "", 0) - - self.__source[line] += self.__getEol() - return ( - 1, - self.trUtf8("Blank line inserted after docstring summary."), - 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixD145(self, code, line, pos, apply=False): - """ - Private method to fix the last paragraph of a multi-line docstring - not followed by a blank line. - - Codes: D143 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - self.__source[line] = self.__getEol() + self.__source[line] - return ( - 1, - self.trUtf8("Blank line inserted after last paragraph" - " of docstring."), - 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixD221(self, code, line, pos, apply=False): - """ - Private method to fix leading and trailing quotes of docstring - not on separate lines. - - Codes: D221, D222 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - indent = self.__getIndent(self.__source[line]) - source = self.__source[line].strip() - if code == "D221": - # leading - if source.startswith(("r", "u")): - first, second = source[:4], source[4:].strip() - else: - first, second = source[:3], source[3:].strip() - else: - # trailing - first, second = source[:-3].strip(), source[-3:] - newText = indent + first + self.__getEol() + \ - indent + second + self.__getEol() - self.__source[line] = newText - if code == "D221": - msg = self.trUtf8("Leading quotes put on separate line.") - else: - msg = self.trUtf8("Trailing quotes put on separate line.") - return (1, msg, 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixD242(self, code, line, pos, apply=False): - """ - Private method to fix a class or function/method docstring preceded - by a blank line. - - Codes: D242, D244 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - self.__source[line - 1] = "" - if code == "D242": - msg = self.trUtf8("Blank line before class docstring removed.") - else: - msg = self.trUtf8( - "Blank line before function/method docstring removed.") - return (1, msg, 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixD243(self, code, line, pos, apply=False): - """ - Private method to fix a class or function/method docstring followed - by a blank line. - - Codes: D243, D245 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - self.__source[line + 1] = "" - if code == "D243": - msg = self.trUtf8("Blank line after class docstring removed.") - else: - msg = self.trUtf8( - "Blank line after function/method docstring removed.") - return (1, msg, 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixD247(self, code, line, pos, apply=False): - """ - Private method to fix a last paragraph of a docstring followed - by a blank line. - - Codes: D247 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - self.__source[line - 1] = "" - return ( - 1, - self.trUtf8("Blank line after last paragraph removed."), - 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE101(self, code, line, pos): - """ - Private method to fix obsolete tab usage and indentation errors. - - Codes: E101, E111, W191 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if self.__reindenter is None: - self.__reindenter = Pep8Reindenter(self.__source) - self.__reindenter.run() - fixedLine = self.__reindenter.fixedLine(line - 1) - if fixedLine is not None and fixedLine != self.__source[line - 1]: - self.__source[line - 1] = fixedLine - if code in ["E101", "W191"]: - msg = self.trUtf8("Tab converted to 4 spaces.") - else: - msg = self.trUtf8( - "Indentation adjusted to be a multiple of four.") - return (1, msg, 0) - else: - return (0, "", 0) - - def __fixE121(self, code, line, pos, apply=False): - """ - Private method to fix the indentation of continuation lines and - closing brackets. - - Codes: E121, E124 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - logical = self.__getLogical(line, pos) - if logical: - # Fix by adjusting initial indent level. - changed = self.__fixReindent(line, pos, logical) - if changed: - if code == "E121": - msg = self.trUtf8( - "Indentation of continuation line corrected.") - elif code == "E124": - msg = self.trUtf8( - "Indentation of closing bracket corrected.") - return (1, msg, 0) - return (0, "", 0) - else: - id = self.__getID() - self.__stackLogical.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE122(self, code, line, pos, apply=False): - """ - Private method to fix a missing indentation of continuation lines. - - Codes: E122 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - logical = self.__getLogical(line, pos) - if logical: - # Fix by adding an initial indent. - modified = self.__fixReindent(line, pos, logical) - if not modified: - # fall back to simple method - line = line - 1 - text = self.__source[line] - indentation = self.__getIndent(text) - self.__source[line] = indentation + \ - self.__indentWord + text.lstrip() - return ( - 1, - self.trUtf8( - "Missing indentation of continuation line corrected."), - 0) - return (0, "", 0) - else: - id = self.__getID() - self.__stackLogical.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE123(self, code, line, pos, apply=False): - """ - Private method to fix the indentation of a closing bracket lines. - - Codes: E123 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - logical = self.__getLogical(line, pos) - if logical: - # Fix by deleting whitespace to the correct level. - logicalLines = logical[2] - row = line - 1 - text = self.__source[row] - newText = self.__getIndent(logicalLines[0]) + text.lstrip() - if newText == text: - # fall back to slower method - changed = self.__fixReindent(line, pos, logical) - else: - self.__source[row] = newText - changed = True - if changed: - return (1, self.trUtf8( - "Closing bracket aligned to opening bracket."), - 0) - return (0, "", 0) - else: - id = self.__getID() - self.__stackLogical.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE125(self, code, line, pos, apply=False): - """ - Private method to fix the indentation of continuation lines not - distinguishable from next logical line. - - Codes: E125 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - logical = self.__getLogical(line, pos) - if logical: - # Fix by adjusting initial indent level. - modified = self.__fixReindent(line, pos, logical) - if not modified: - row = line - 1 - text = self.__source[row] - self.__source[row] = self.__getIndent(text) + \ - self.__indentWord + text.lstrip() - return (1, self.trUtf8("Indentation level changed."), 0) - return (0, "", 0) - else: - id = self.__getID() - self.__stackLogical.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE126(self, code, line, pos, apply=False): - """ - Private method to fix over-indented/under-indented hanging - indentation. - - Codes: E126, E133 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - logical = self.__getLogical(line, pos) - if logical: - # Fix by deleting whitespace to the left. - logicalLines = logical[2] - row = line - 1 - text = self.__source[row] - newText = self.__getIndent(logicalLines[0]) + \ - self.__indentWord + text.lstrip() - if newText == text: - # fall back to slower method - changed = self.__fixReindent(line, pos, logical) - else: - self.__source[row] = newText - changed = True - if changed: - return (1, self.trUtf8( - "Indentation level of hanging indentation changed."), - 0) - return (0, "", 0) - else: - id = self.__getID() - self.__stackLogical.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE127(self, code, line, pos, apply=False): - """ - Private method to fix over/under indented lines. - - Codes: E127, E128 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - logical = self.__getLogical(line, pos) - if logical: - # Fix by inserting/deleting whitespace to the correct level. - logicalLines = logical[2] - row = line - 1 - text = self.__source[row] - newText = text - - if logicalLines[0].rstrip().endswith('\\'): - newText = self.__getIndent(logicalLines[0]) + \ - self.__indentWord + text.lstrip() - else: - startIndex = None - for symbol in '([{': - if symbol in logicalLines[0]: - foundIndex = logicalLines[0].find(symbol) + 1 - if startIndex is None: - startIndex = foundIndex - else: - startIndex = min(startIndex, foundIndex) - - if startIndex is not None: - newText = startIndex * ' ' + text.lstrip() - - if newText == text: - # fall back to slower method - changed = self.__fixReindent(line, pos, logical) - else: - self.__source[row] = newText - changed = True - if changed: - return (1, self.trUtf8("Visual indentation corrected."), 0) - return (0, "", 0) - else: - id = self.__getID() - self.__stackLogical.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE201(self, code, line, pos): - """ - Private method to fix extraneous whitespace. - - Codes: E201, E202, E203, E211 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - line = line - 1 - text = self.__source[line] - - if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): - return (0, "", 0) - - newText = self.__fixWhitespace(text, pos, '') - if newText == text: - return (0, "", 0) - - self.__source[line] = newText - return (1, self.trUtf8("Extraneous whitespace removed."), 0) - - def __fixE221(self, code, line, pos): - """ - Private method to fix extraneous whitespace around operator or - keyword. - - Codes: E221, E222, E223, E224, E225, E226, E227, E228, E241, - E242, E271, E272, E273, E274). - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - line = line - 1 - text = self.__source[line] - - if '"""' in text or "'''" in text or text.rstrip().endswith('\\'): - return (0, "", 0) - - newText = self.__fixWhitespace(text, pos, ' ') - if newText == text: - return (0, "", 0) - - self.__source[line] = newText - if code in ["E225", "E226", "E227", "E228"]: - return (1, self.trUtf8("Missing whitespace added."), 0) - else: - return (1, self.trUtf8("Extraneous whitespace removed."), 0) - - def __fixE231(self, code, line, pos): - """ - Private method to fix missing whitespace after ',;:'. - - Codes: E231 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - line = line - 1 - pos = pos + 1 - self.__source[line] = self.__source[line][:pos] + \ - " " + self.__source[line][pos:] - return (1, self.trUtf8("Missing whitespace added."), 0) - - def __fixE251(self, code, line, pos): - """ - Private method to fix extraneous whitespace around keyword and - default parameter equals. - - Codes: E251 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - line = line - 1 - text = self.__source[line] - - # This is necessary since pep8 sometimes reports columns that goes - # past the end of the physical line. This happens in cases like, - # foo(bar\n=None) - col = min(pos, len(text) - 1) - if text[col].strip(): - newText = text - else: - newText = text[:col].rstrip() + text[col:].lstrip() - - # There could be an escaped newline - # - # def foo(a=\ - # 1) - if newText.endswith(('=\\\n', '=\\\r\n', '=\\\r')): - self.__source[line] = newText.rstrip("\n\r \t\\") - self.__source[line + 1] = self.__source[line + 1].lstrip() - else: - self.__source[line] = newText - return (1, self.trUtf8("Extraneous whitespace removed."), 0) - - def __fixE261(self, code, line, pos): - """ - Private method to fix whitespace before or after inline comment. - - Codes: E261, E262 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - line = line - 1 - text = self.__source[line] - left = text[:pos].rstrip(' \t#') - right = text[pos:].lstrip(' \t#') - newText = left + (" # " + right if right.strip() else right) - self.__source[line] = newText - return (1, self.trUtf8("Whitespace around comment sign corrected."), 0) - - def __fixE301(self, code, line, pos, apply=False): - """ - Private method to fix the need for one blank line. - - Codes: E301 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - self.__source.insert(line - 1, self.__getEol()) - return (1, self.trUtf8("One blank line inserted."), 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE302(self, code, line, pos, apply=False): - """ - Private method to fix the need for two blank lines. - - Codes: E302 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - # count blank lines - index = line - 1 - blanks = 0 - while index: - if self.__source[index - 1].strip() == "": - blanks += 1 - index -= 1 - else: - break - delta = blanks - 2 - - line -= 1 - if delta < 0: - # insert blank lines (one or two) - while delta < 0: - self.__source.insert(line, self.__getEol()) - delta += 1 - changed = True - elif delta > 0: - # delete superfluous blank lines - while delta > 0: - del self.__source[line - 1] - line -= 1 - delta -= 1 - changed = True - else: - changed = False - - if changed: - if delta < 0: - msg = self.trUtf8( - "%n blank line(s) inserted.", "", -delta) - elif delta > 0: - msg = self.trUtf8( - "%n superfluous lines removed", "", delta) - else: - msg = "" - return (1, msg, 0) - return (0, "", 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE303(self, code, line, pos, apply=False): - """ - Private method to fix superfluous blank lines. - - Codes: E303 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - index = line - 3 - while index: - if self.__source[index].strip() == "": - del self.__source[index] - index -= 1 - else: - break - return (1, self.trUtf8("Superfluous blank lines removed."), 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE304(self, code, line, pos, apply=False): - """ - Private method to fix superfluous blank lines after a function - decorator. - - Codes: E304 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - index = line - 2 - while index: - if self.__source[index].strip() == "": - del self.__source[index] - index -= 1 - else: - break - return (1, self.trUtf8( - "Superfluous blank lines after function decorator removed."), - 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE401(self, code, line, pos, apply=False): - """ - Private method to fix multiple imports on one line. - - Codes: E401 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - text = self.__source[line] - if not text.lstrip().startswith("import"): - return (0, "", 0) - - # pep8 (1.3.1) reports false positive if there is an import - # statement followed by a semicolon and some unrelated - # statement with commas in it. - if ';' in text: - return (0, "", 0) - - newText = text[:pos].rstrip("\t ,") + self.__getEol() + \ - self.__getIndent(text) + "import " + text[pos:].lstrip("\t ,") - self.__source[line] = newText - return (1, self.trUtf8("Imports were put on separate lines."), 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE501(self, code, line, pos, apply=False): - """ - Private method to fix the long lines by breaking them. - - Codes: E501 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - multilineStringLines, docStringLines = \ - self.__multilineStringLines() - isDocString = line in docStringLines - line = line - 1 - text = self.__source[line] - if line > 0: - prevText = self.__source[line - 1] - else: - prevText = "" - if line < len(self.__source) - 1: - nextText = self.__source[line + 1] - else: - nextText = "" - shortener = Pep8LineShortener( - text, prevText, nextText, - maxLength=self.__maxLineLength, eol=self.__getEol(), - indentWord=self.__indentWord, isDocString=isDocString) - changed, newText, newNextText = shortener.shorten() - if changed: - if newText != text: - self.__source[line] = newText - if newNextText and newNextText != nextText: - self.__source[line + 1] = newNextText - return (1, self.trUtf8("Long lines have been shortened."), 0) - else: - return (0, "", 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE502(self, code, line, pos): - """ - Private method to fix redundant backslash within brackets. - - Codes: E502 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - self.__source[line - 1] = \ - self.__source[line - 1].rstrip("\n\r \t\\") + self.__getEol() - return (1, self.trUtf8("Redundant backslash in brackets removed."), 0) - - def __fixE701(self, code, line, pos, apply=False): - """ - Private method to fix colon-separated compound statements. - - Codes: E701 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - text = self.__source[line] - pos = pos + 1 - - newText = text[:pos] + self.__getEol() + self.__getIndent(text) + \ - self.__indentWord + text[pos:].lstrip("\n\r \t\\") + \ - self.__getEol() - self.__source[line] = newText - return (1, self.trUtf8("Compound statement corrected."), 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE702(self, code, line, pos, apply=False): - """ - Private method to fix semicolon-separated compound statements. - - Codes: E702, E703 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - text = self.__source[line] - - if text.rstrip().endswith("\\"): - # normalize '1; \\\n2' into '1; 2' - self.__source[line] = text.rstrip("\n\r \t\\") - self.__source[line + 1] = self.__source[line + 1].lstrip() - elif text.rstrip().endswith(";"): - self.__source[line] = text.rstrip("\n\r \t;") + self.__getEol() - else: - first = text[:pos].rstrip("\n\r \t;") + self.__getEol() - second = text[pos:].lstrip("\n\r \t;") - self.__source[line] = first + self.__getIndent(text) + second - return (1, self.trUtf8("Compound statement corrected."), 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixE711(self, code, line, pos): - """ - Private method to fix comparison with None. - - Codes: E711, E712 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - line = line - 1 - text = self.__source[line] - - rightPos = pos + 2 - if rightPos >= len(text): - return (0, "", 0) - - left = text[:pos].rstrip() - center = text[pos:rightPos] - right = text[rightPos:].lstrip() - - if not right.startswith(("None", "True", "False")): - return (0, "", 0) - - if center.strip() == "==": - center = "is" - elif center.strip() == "!=": - center = "is not" - else: - return (0, "", 0) - - self.__source[line] = " ".join([left, center, right]) - return (1, self.trUtf8("Comparison to None/True/False corrected."), 0) - - def __fixN804(self, code, line, pos, apply=False): - """ - Private method to fix a wrong first argument of normal and - class methods. - - Codes: N804, N805 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - text = self.__source[line] - if code == "N804": - arg = "cls" - else: - arg = "self" - - if text.rstrip().endswith("("): - newText = text + self.__getIndent(text) + \ - self.__indentWord + arg + "," + self.__getEol() - else: - index = text.find("(") + 1 - left = text[:index] - right = text[index:] - if right.startswith(")"): - center = arg - else: - center = arg + ", " - newText = left + center + right - self.__source[line] = newText - return (1, self.trUtf8("'{0}' argument added.").format(arg), 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixN806(self, code, line, pos, apply=False): - """ - Private method to fix a wrong first argument of static methods. - - Codes: N806 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @keyparam apply flag indicating, that the fix should be applied - (boolean) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - if apply: - line = line - 1 - text = self.__source[line] - index = text.find("(") + 1 - left = text[:index] - right = text[index:] - - if right.startswith(("cls", "self")): - # cls or self are on the definition line - if right.startswith("cls"): - right = right[3:] - arg = "cls" - else: - right = right[4:] - arg = "self" - right = right.lstrip(", ") - newText = left + right - self.__source[line] = newText - else: - # they are on the next line - line = line + 1 - text = self.__source[line] - indent = self.__getIndent(text) - right = text.lstrip() - if right.startswith("cls"): - right = right[3:] - arg = "cls" - else: - right = right[4:] - arg = "self" - right = right.lstrip(", ") - if right.startswith("):"): - # merge with previous line - self.__source[line - 1] = \ - self.__source[line - 1].rstrip() + right - self.__source[line] = "" - else: - self.__source[line] = indent + right - - return (1, self.trUtf8("'{0}' argument removed.").format(arg), 0) - else: - id = self.__getID() - self.__stack.append((id, code, line, pos)) - return (-1, "", id) - - def __fixW291(self, code, line, pos): - """ - Private method to fix trailing whitespace. - - Codes: W291, W293 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - self.__source[line - 1] = re.sub(r'[\t ]+(\r?)$', r"\1", - self.__source[line - 1]) - return (1, self.trUtf8("Whitespace stripped from end of line."), 0) - - def __fixW292(self, code, line, pos): - """ - Private method to fix a missing newline at the end of file. - - Codes: W292 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - self.__source[line - 1] += self.__getEol() - return (1, self.trUtf8("newline added to end of file."), 0) - - def __fixW391(self, code, line, pos): - """ - Private method to fix trailing blank lines. - - Codes: W391 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - index = line - 1 - while index: - if self.__source[index].strip() == "": - del self.__source[index] - index -= 1 - else: - break - return (1, self.trUtf8( - "Superfluous trailing blank lines removed from end of file."), 0) - - def __fixW603(self, code, line, pos): - """ - Private method to fix the not equal notation. - - Codes: W603 - - @param code code of the issue (string) - @param line line number of the issue (integer) - @param pos position inside line (integer) - @return value indicating an applied/deferred fix (-1, 0, 1), - a message for the fix (string) and an ID for a deferred - fix (integer) - """ - self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=") - return (1, self.trUtf8("'<>' replaced by '!='."), 0) - - -class Pep8Reindenter(object): - """ - Class to reindent badly-indented code to uniformly use four-space - indentation. - - Released to the public domain, by Tim Peters, 03 October 2000. - """ - def __init__(self, sourceLines): - """ - Constructor - - @param sourceLines list of source lines including eol marker - (list of string) - """ - # Raw file lines. - self.raw = sourceLines - self.after = [] - - # File lines, rstripped & tab-expanded. Dummy at start is so - # that we can use tokenize's 1-based line numbering easily. - # Note that a line is all-blank iff it's "\n". - self.lines = [line.rstrip().expandtabs() + "\n" - for line in self.raw] - self.lines.insert(0, None) - self.index = 1 # index into self.lines of next line - - # List of (lineno, indentlevel) pairs, one for each stmt and - # comment line. indentlevel is -1 for comment lines, as a - # signal that tokenize doesn't know what to do about them; - # indeed, they're our headache! - self.stats = [] - - def run(self): - """ - Public method to run the re-indenter. - - @return flag indicating that a change was done (boolean) - """ - try: - stats = self.__genStats(tokenize.generate_tokens(self.getline)) - except (SyntaxError, tokenize.TokenError): - return False - - # Remove trailing empty lines. - lines = self.lines - while lines and lines[-1] == "\n": - lines.pop() - # Sentinel. - stats.append((len(lines), 0)) - # Map count of leading spaces to # we want. - have2want = {} - # Program after transformation. - after = self.after = [] - # Copy over initial empty lines -- there's nothing to do until - # we see a line with *something* on it. - i = stats[0][0] - after.extend(lines[1:i]) - for i in range(len(stats) - 1): - thisstmt, thislevel = stats[i] - nextstmt = stats[i + 1][0] - have = self.__getlspace(lines[thisstmt]) - want = thislevel * 4 - if want < 0: - # A comment line. - if have: - # An indented comment line. If we saw the same - # indentation before, reuse what it most recently - # mapped to. - want = have2want.get(have, -1) - if want < 0: - # Then it probably belongs to the next real stmt. - for j in range(i + 1, len(stats) - 1): - jline, jlevel = stats[j] - if jlevel >= 0: - if have == self.__getlspace(lines[jline]): - want = jlevel * 4 - break - if want < 0: # Maybe it's a hanging - # comment like this one, - # in which case we should shift it like its base - # line got shifted. - for j in range(i - 1, -1, -1): - jline, jlevel = stats[j] - if jlevel >= 0: - want = \ - have + \ - self.__getlspace(after[jline - 1]) - \ - self.__getlspace(lines[jline]) - break - if want < 0: - # Still no luck -- leave it alone. - want = have - else: - want = 0 - assert want >= 0 - have2want[have] = want - diff = want - have - if diff == 0 or have == 0: - after.extend(lines[thisstmt:nextstmt]) - else: - for line in lines[thisstmt:nextstmt]: - if diff > 0: - if line == "\n": - after.append(line) - else: - after.append(" " * diff + line) - else: - remove = min(self.__getlspace(line), -diff) - after.append(line[remove:]) - return self.raw != self.after - - def fixedLine(self, line): - """ - Public method to get a fixed line. - - @param line number of the line to retrieve (integer) - @return fixed line (string) - """ - if line < len(self.after): - return self.after[line] - - def getline(self): - """ - Public method to get a line of text for tokenize. - - @return line of text (string) - """ - if self.index >= len(self.lines): - line = "" - else: - line = self.lines[self.index] - self.index += 1 - return line - - def __genStats(self, tokens): - """ - Private method to generate the re-indent statistics. - - @param tokens tokens generator (tokenize._tokenize) - @return reference to the generated statistics - """ - find_stmt = True # next token begins a fresh stmt? - level = 0 # current indent level - stats = [] - - for t in tokens: - token_type = t[0] - sline = t[2][0] - line = t[4] - - if token_type == tokenize.NEWLINE: - # A program statement, or ENDMARKER, will eventually follow, - # after some (possibly empty) run of tokens of the form - # (NL | COMMENT)* (INDENT | DEDENT+)? - self.find_stmt = True - - elif token_type == tokenize.INDENT: - find_stmt = True - level += 1 - - elif token_type == tokenize.DEDENT: - find_stmt = True - level -= 1 - - elif token_type == tokenize.COMMENT: - if find_stmt: - stats.append((sline, -1)) - # but we're still looking for a new stmt, so leave - # find_stmt alone - - elif token_type == tokenize.NL: - pass - - elif find_stmt: - # This is the first "real token" following a NEWLINE, so it - # must be the first token of the next program statement, or an - # ENDMARKER. - find_stmt = False - if line: # not endmarker - stats.append((sline, level)) - - return stats - - def __getlspace(self, line): - """ - Private method to count number of leading blanks. - - @param line line to check (string) - @return number of leading blanks (integer) - """ - i = 0 - n = len(line) - while i < n and line[i] == " ": - i += 1 - return i - - -class Pep8IndentationWrapper(object): - """ - Class used by fixers dealing with indentation. - - Each instance operates on a single logical line. - """ - SKIP_TOKENS = frozenset([ - tokenize.COMMENT, tokenize.NL, tokenize.INDENT, - tokenize.DEDENT, tokenize.NEWLINE, tokenize.ENDMARKER - ]) - - def __init__(self, physical_lines): - """ - Constructor - - @param physical_lines list of physical lines to operate on - (list of strings) - """ - self.lines = physical_lines - self.tokens = [] - self.rel_indent = None - sio = io.StringIO(''.join(physical_lines)) - for t in tokenize.generate_tokens(sio.readline): - if not len(self.tokens) and t[0] in self.SKIP_TOKENS: - continue - if t[0] != tokenize.ENDMARKER: - self.tokens.append(t) - - self.logical_line = self.__buildTokensLogical(self.tokens) - - def __buildTokensLogical(self, tokens): - """ - Private method to build a logical line from a list of tokens. - - @param tokens list of tokens as generated by tokenize.generate_tokens - @return logical line (string) - """ - # from pep8.py with minor modifications - logical = [] - previous = None - for t in tokens: - token_type, text = t[0:2] - if token_type in self.SKIP_TOKENS: - continue - if previous: - end_line, end = previous[3] - start_line, start = t[2] - if end_line != start_line: # different row - prev_text = self.lines[end_line - 1][end - 1] - if prev_text == ',' or (prev_text not in '{[(' - and text not in '}])'): - logical.append(' ') - elif end != start: # different column - fill = self.lines[end_line - 1][end:start] - logical.append(fill) - logical.append(text) - previous = t - logical_line = ''.join(logical) - assert logical_line.lstrip() == logical_line - assert logical_line.rstrip() == logical_line - return logical_line - - def pep8Expected(self): - """ - Public method to replicate logic in pep8.py, to know what level to - indent things to. - - @return list of lists, where each list represents valid indent levels - for the line in question, relative from the initial indent. However, - the first entry is the indent level which was expected. - """ - # What follows is an adjusted version of - # pep8.py:continuation_line_indentation. All of the comments have been - # stripped and the 'yield' statements replaced with 'pass'. - if not self.tokens: - return - - first_row = self.tokens[0][2][0] - nrows = 1 + self.tokens[-1][2][0] - first_row - - # here are the return values - valid_indents = [list()] * nrows - indent_level = self.tokens[0][2][1] - valid_indents[0].append(indent_level) - - if nrows == 1: - # bug, really. - return valid_indents - - indent_next = self.logical_line.endswith(':') - - row = depth = 0 - parens = [0] * nrows - self.rel_indent = rel_indent = [0] * nrows - indent = [indent_level] - indent_chances = {} - last_indent = (0, 0) - last_token_multiline = None - - for token_type, text, start, end, line in self.tokens: - newline = row < start[0] - first_row - if newline: - row = start[0] - first_row - newline = (not last_token_multiline and - token_type not in (tokenize.NL, tokenize.NEWLINE)) - - if newline: - # This is where the differences start. Instead of looking at - # the line and determining whether the observed indent matches - # our expectations, we decide which type of indentation is in - # use at the given indent level, and return the offset. This - # algorithm is susceptible to "carried errors", but should - # through repeated runs eventually solve indentation for - # multiline expressions. - - if depth: - for open_row in range(row - 1, -1, -1): - if parens[open_row]: - break - else: - open_row = 0 - - # That's all we get to work with. This code attempts to - # "reverse" the below logic, and place into the valid indents - # list - vi = [] - add_second_chances = False - if token_type == tokenize.OP and text in ']})': - # this line starts with a closing bracket, so it needs to - # be closed at the same indent as the opening one. - if indent[depth]: - # hanging indent - vi.append(indent[depth]) - else: - # visual indent - vi.append(indent_level + rel_indent[open_row]) - elif depth and indent[depth]: - # visual indent was previously confirmed. - vi.append(indent[depth]) - add_second_chances = True - elif depth and True in indent_chances.values(): - # visual indent happened before, so stick to - # visual indent this time. - if depth > 1 and indent[depth - 1]: - vi.append(indent[depth - 1]) - else: - # stupid fallback - vi.append(indent_level + 4) - add_second_chances = True - elif not depth: - vi.append(indent_level + 4) - else: - # must be in hanging indent - hang = rel_indent[open_row] + 4 - vi.append(indent_level + hang) - - # about the best we can do without look-ahead - if (indent_next and vi[0] == indent_level + 4 and - nrows == row + 1): - vi[0] += 4 - - if add_second_chances: - # visual indenters like to line things up. - min_indent = vi[0] - for col, what in indent_chances.items(): - if col > min_indent and ( - what is True or - (what == str and token_type == tokenize.STRING) or - (what == text and token_type == tokenize.OP) - ): - vi.append(col) - vi = sorted(vi) - - valid_indents[row] = vi - - # Returning to original continuation_line_indentation() from - # pep8. - visual_indent = indent_chances.get(start[1]) - last_indent = start - rel_indent[row] = pep8.expand_indent(line) - indent_level - hang = rel_indent[row] - rel_indent[open_row] - - if token_type == tokenize.OP and text in ']})': - pass - elif visual_indent is True: - if not indent[depth]: - indent[depth] = start[1] - - # line altered: comments shouldn't define a visual indent - if parens[row] and not indent[depth] and token_type not in ( - tokenize.NL, tokenize.COMMENT - ): - indent[depth] = start[1] - indent_chances[start[1]] = True - elif token_type == tokenize.STRING or text in ( - 'u', 'ur', 'b', 'br' - ): - indent_chances[start[1]] = str - - if token_type == tokenize.OP: - if text in '([{': - depth += 1 - indent.append(0) - parens[row] += 1 - elif text in ')]}' and depth > 0: - prev_indent = indent.pop() or last_indent[1] - for d in range(depth): - if indent[d] > prev_indent: - indent[d] = 0 - for ind in list(indent_chances): - if ind >= prev_indent: - del indent_chances[ind] - depth -= 1 - if depth and indent[depth]: # modified - indent_chances[indent[depth]] = True - for idx in range(row, -1, -1): - if parens[idx]: - parens[idx] -= 1 - break - assert len(indent) == depth + 1 - if start[1] not in indent_chances: - indent_chances[start[1]] = text - - last_token_multiline = (start[0] != end[0]) - - return valid_indents - - -class Pep8LineShortener(object): - """ - Class used to shorten lines to a given maximum of characters. - """ - def __init__(self, curLine, prevLine, nextLine, maxLength=79, eol="\n", - indentWord=" ", isDocString=False): - """ - Constructor - - @param curLine text to work on (string) - @param prevLine line before the text to work on (string) - @param nextLine line after the text to work on (string) - @keyparam maxLength maximum allowed line length (integer) - @keyparam eol eond-of-line marker (string) - @keyparam indentWord string used for indentation (string) - @keyparam isDocString flag indicating that the line belongs to - a documentation string (boolean) - """ - self.__text = curLine - self.__prevText = prevLine - self.__nextText = nextLine - self.__maxLength = maxLength - self.__eol = eol - self.__indentWord = indentWord - self.__isDocString = isDocString - - def shorten(self): - """ - Public method to shorten the line wrapped by the class instance. - - @return tuple of a flag indicating successful shortening, the - shortened line and the changed next line (boolean, string, string) - """ - # 1. check for comment - if self.__text.lstrip().startswith('#'): - lastComment = True - if self.__nextText.lstrip().startswith('#'): - lastComment = False - - # Wrap commented lines. - newText = self.__shortenComment(lastComment) - if newText == self.__text: - return False, "", "" - else: - return True, newText, "" - elif '#' in self.__text: - pos = self.__text.rfind("#") - newText = self.__text[:pos].rstrip() + self.__eol + \ - self.__getIndent(self.__text) + self.__text[pos:] - if newText == self.__text: - return False, "", "" - else: - return True, newText, "" - - # Do multi line doc strings - if self.__isDocString: - source = self.__text.rstrip() - blank = source.rfind(" ") - while blank > self.__maxLength and blank != -1: - blank = source.rfind(" ", 0, blank) - if blank == -1: - # Cannot break - return False, "", "" - else: - first = self.__text[:blank] - second = self.__text[blank:].lstrip() - if self.__nextText.strip(): - if self.__nextText.lstrip().startswith("@"): - # eric doc comment - # create a new line and indent it - newText = first + self.__eol + \ - self.__getIndent(first) + self.__indentWord + \ - second - newNext = "" - else: - newText = first + self.__eol - newNext = self.__getIndent(self.__nextText) + \ - second.rstrip() + " " + self.__nextText.lstrip() - else: - # empty line, add a new line - newText = first + self.__eol + self.__getIndent(first) + \ - second - newNext = "" - return True, newText, newNext - - indent = self.__getIndent(self.__text) - source = self.__text[len(indent):] - assert source.lstrip() == source - sio = io.StringIO(source) - - # Check for multi line string. - try: - tokens = list(tokenize.generate_tokens(sio.readline)) - except (SyntaxError, tokenize.TokenError): - if source.rstrip().endswith("\\"): - # just join the continuation line and let the next run - # handle it once it tokenizes ok - newText = indent + source.rstrip()[:-1].rstrip() + " " + \ - self.__nextText.lstrip() - if indent: - newNext = indent - else: - newNext = " " - return True, newText, newNext - else: - multilineCandidate = self.__breakMultiline() - if multilineCandidate: - return True, multilineCandidate[0], multilineCandidate[1] - else: - return False, "", "" - - # Handle statements by putting the right hand side on a line by itself. - # This should let the next pass shorten it. - if source.startswith('return '): - newText = ( - indent + - 'return (' + - self.__eol + - indent + self.__indentWord + re.sub('^return ', '', source) + - indent + ')' + self.__eol - ) - return True, newText, "" - - candidates = self.__shortenLine(tokens, source, indent) - if candidates: - candidates = list(sorted( - set(candidates).union([self.__text]), - key=lambda x: self.__lineShorteningRank(x))) - if candidates[0] == self.__text: - return False, "", "" - return True, candidates[0], "" - - source = self.__text - rs = source.rstrip() - if rs.endswith(("'", '"')) and " " in source: - if rs.endswith(('"""', "'''")): - quote = rs[-3:] - else: - quote = rs[-1] - blank = source.rfind(" ") - maxLen = self.__maxLength - 2 - len(quote) - while blank > maxLen and blank != -1: - blank = source.rfind(" ", 0, blank) - if blank != -1: - if source[blank + 1:].startswith(quote): - first = source[:maxLen] - second = source[maxLen:] - else: - first = source[:blank] - second = source[blank + 1:] - return ( - True, - first + quote + " \\" + self.__eol + - indent + self.__indentWord + quote + second, - "") - else: - # Cannot break - return False, "", "" - - return False, "", "" - - def __shortenComment(self, isLast): - """ - Private method to shorten a comment line. - - @param isLast flag indicating, that the line is the last comment line - (boolean) - @return shortened comment line (string) - """ - if len(self.__text) <= self.__maxLength: - return self.__text - - newText = self.__text.rstrip() - - # PEP 8 recommends 72 characters for comment text. - indentation = self.__getIndent(newText) + '# ' - maxLength = min(self.__maxLength, - len(indentation) + 72) - - MIN_CHARACTER_REPEAT = 5 - if len(newText) - len(newText.rstrip(newText[-1])) >= \ - MIN_CHARACTER_REPEAT and \ - not newText[-1].isalnum(): - # Trim comments that end with things like --------- - return newText[:maxLength] + self.__eol - elif isLast and re.match(r"\s*#+\s*\w+", newText): - import textwrap - splitLines = textwrap.wrap(newText.lstrip(" \t#"), - initial_indent=indentation, - subsequent_indent=indentation, - width=maxLength, - break_long_words=False, - break_on_hyphens=False) - return self.__eol.join(splitLines) + self.__eol - else: - return newText + self.__eol - - def __breakMultiline(self): - """ - Private method to break multi line strings. - - @return tuple of the shortened line and the changed next line - (string, string) - """ - indentation = self.__getIndent(self.__text) - - # Handle special case. - for symbol in '([{': - # Only valid if symbol is not on a line by itself. - if ( - symbol in self.__text and - self.__text.strip() != symbol and - self.__text.rstrip().endswith((',', '%')) - ): - index = 1 + self.__text.find(symbol) - - if index <= len(self.__indentWord) + len(indentation): - continue - - if self.__isProbablyInsideStringOrComment( - self.__text, index - 1): - continue - - return (self.__text[:index].rstrip() + self.__eol + - indentation + self.__indentWord + - self.__text[index:].lstrip(), "") - - newText = self.__text - newNext = self.__nextText - blank = newText.rfind(" ") - while blank > self.__maxLength and blank != -1: - blank = newText.rfind(" ", 0, blank) - if blank != -1: - first = self.__text[:blank] - second = self.__text[blank:].strip() - if newNext.strip(): - newText = first + self.__eol - newNext = self.__getIndent(newNext) + \ - second + " " + newNext.lstrip() - else: - # empty line, add a new line - newText = first + self.__eol - newNext = self.__getIndent(newNext) + \ - second + self.__eol + newNext.lstrip() - return newText, newNext - - def __isProbablyInsideStringOrComment(self, line, index): - """ - Private method to check, if the given string might be inside a string - or comment. - - @param line line to check (string) - @param index position inside line to check (integer) - @return flag indicating the possibility of being inside a string - or comment - """ - # Check against being in a string. - for quote in ['"', "'"]: - pos = line.find(quote) - if pos != -1 and pos <= index: - return True - - # Check against being in a comment. - pos = line.find('#') - if pos != -1 and pos <= index: - return True - - return False - - def __shortenLine(self, tokens, source, indent): - """ - Private method to shorten a line of code at an operator. - - @param tokens tokens of the line as generated by tokenize - (list of token) - @param source code string to work at (string) - @param indent indentation string of the code line (string) - @return list of candidates (list of string) - """ - candidates = [] - - for tkn in tokens: - tokenType = tkn[0] - tokenString = tkn[1] - - if ( - tokenType == tokenize.COMMENT and - not self.__prevText.rstrip().endswith('\\') - ): - # Move inline comments to previous line. - offset = tkn[2][1] - first = source[:offset] - second = source[offset:] - candidates.append( - indent + second.strip() + self.__eol + - indent + first.strip() + self.__eol) - elif tokenType == tokenize.OP and tokenString != '=': - # Don't break on '=' after keyword as this violates PEP 8. - - assert tokenType != tokenize.INDENT - - offset = tkn[2][1] + 1 - first = source[:offset] - - secondIndent = indent - if first.rstrip().endswith('('): - secondIndent += self.__indentWord - elif '(' in first: - secondIndent += ' ' * (1 + first.find('(')) - else: - secondIndent += self.__indentWord - - second = (secondIndent + source[offset:].lstrip()) - if not second.strip(): - continue - - # Do not begin a line with a comma - if second.lstrip().startswith(','): - continue - - # Do end a line with a dot - if first.rstrip().endswith('.'): - continue - - if tokenString in '+-*/': - newText = first + ' \\' + self.__eol + second - else: - newText = first + self.__eol + second - - # Only fix if syntax is okay. - if self.__checkSyntax(self.__normalizeMultiline(newText)): - candidates.append(indent + newText) - - return candidates - - def __normalizeMultiline(self, text): - """ - Private method to remove multiline-related code that will cause syntax - error. - - @param text code line to work on (string) - @return normalized code line (string) - """ - for quote in '\'"': - dictPattern = r"^{q}[^{q}]*{q} *: *".format(q=quote) - if re.match(dictPattern, text): - if not text.strip().endswith('}'): - text += '}' - return '{' + text - - if text.startswith('def ') and text.rstrip().endswith(':'): - # Do not allow ':' to be alone. That is invalid. - splitText = [item.strip() for item in text.split(self.__eol)] - if ':' not in splitText and 'def' not in splitText: - return text[len('def'):].strip().rstrip(':') - - return text - - def __lineShorteningRank(self, candidate): - """ - Private method to rank a candidate. - - @param candidate candidate line to rank (string) - @return rank of the candidate (integer) - """ - rank = 0 - if candidate.strip(): - if candidate == self.__text: - # give the original a disadvantage - rank += 50 - - lines = candidate.split(self.__eol) - - offset = 0 - if lines[0].rstrip()[-1] not in '([{': - for symbol in '([{': - offset = max(offset, 1 + lines[0].find(symbol)) - - maxLength = max([offset + len(x.strip()) for x in lines]) - rank += maxLength - rank += len(lines) - - badStartingSymbol = { - '(': ')', - '[': ']', - '{': '}'}.get(lines[0][-1], None) - - if len(lines) > 1: - if (badStartingSymbol and - lines[1].lstrip().startswith(badStartingSymbol)): - rank += 20 - - if re.match(r".*[+\-\*/] \($", lines[0]): - # "1 * (\n" is ugly as hell. - rank += 100 - - for currentLine in lines: - for badStart in ['.', '%', '+', '-', '/']: - if currentLine.startswith(badStart): - rank += 100 - - for ending in '([{': - # Avoid lonely opening. They result in longer lines. - if currentLine.endswith(ending) and \ - len(currentLine.strip()) <= len(self.__indentWord): - rank += 100 - - if currentLine.endswith('%'): - rank -= 20 - - # Try to break list comprehensions at the "for". - if currentLine.lstrip().startswith('for'): - rank -= 50 - - rank += 10 * self.__countUnbalancedBrackets(currentLine) - else: - rank = 100000 - - return max(0, rank) - - def __countUnbalancedBrackets(self, line): - """ - Private method to determine the number of unmatched open/close - brackets. - - @param line line to work at (string) - @return number of unmatched open/close brackets (integer) - """ - count = 0 - for opening, closing in ['()', '[]', '{}']: - count += abs(line.count(opening) - line.count(closing)) - - return count - - def __getIndent(self, line): - """ - Private method to get the indentation string. - - @param line line to determine the indentation string from (string) - @return indentation string (string) - """ - # copied from Pep8Fixer - return line.replace(line.lstrip(), "") - - def __checkSyntax(self, code): - """ - Private method to check the syntax of the given code fragment. - - @param code code fragment to check (string) - @return flag indicating syntax is ok (boolean) - """ - code = code.replace("\r\n", "\n").replace("\r", "\n") - try: - return compile(code, '<string>', 'exec') - except (SyntaxError, TypeError, UnicodeDecodeError): - return False
--- a/eric5.e4p Tue Oct 01 18:22:33 2013 +0200 +++ b/eric5.e4p Tue Oct 01 18:31:05 2013 +0200 @@ -809,7 +809,6 @@ <Source>Plugins/PluginPep8Checker.py</Source> <Source>UtilitiesPython2/pep8.py</Source> <Source>UtilitiesPython2/Pep8Checker.py</Source> - <Source>Plugins/CheckerPlugins/Pep8/Pep8Fixer.py</Source> <Source>eric5_compare.py</Source> <Source>eric5_compare.pyw</Source> <Source>eric5_configure.py</Source> @@ -1110,6 +1109,7 @@ <Source>Plugins/CheckerPlugins/Pep8/CodeStyleStatisticsDialog.py</Source> <Source>Plugins/CheckerPlugins/Pep8/CodeStyleCodeSelectionDialog.py</Source> <Source>Plugins/CheckerPlugins/Pep8/CodeStyleCheckerDialog.py</Source> + <Source>Plugins/CheckerPlugins/Pep8/CodeStyleFixer.py</Source> </Sources> <Forms> <Form>PyUnit/UnittestDialog.ui</Form>