Plugins/CheckerPlugins/Pep8/Pep257Checker.py

changeset 2949
e8f41288a688
parent 2948
ea04689ee599
child 2952
94fc661a54a2
equal deleted inserted replaced
2948:ea04689ee599 2949:e8f41288a688
113 113
114 "D203", "D205", 114 "D203", "D205",
115 "D221", "D222", 115 "D221", "D222",
116 "D231", "D234", "D235", "D236", "D237", "D238", "D239", 116 "D231", "D234", "D235", "D236", "D237", "D238", "D239",
117 "D242", "D243", "D244", "D245", "D246", "D247", 117 "D242", "D243", "D244", "D245", "D246", "D247",
118 "D250", "D251",
118 ] 119 ]
119 120
120 Messages = { 121 Messages = {
121 "D101": QT_TRANSLATE_NOOP( 122 "D101": QT_TRANSLATE_NOOP(
122 "Pep257Checker", "module is missing a docstring"), 123 "Pep257Checker", "module is missing a docstring"),
180 "trailing quotes of docstring not on separate line"), 181 "trailing quotes of docstring not on separate line"),
181 "D231": QT_TRANSLATE_NOOP( 182 "D231": QT_TRANSLATE_NOOP(
182 "Pep257Checker", "docstring summary does not end with a period"), 183 "Pep257Checker", "docstring summary does not end with a period"),
183 "D234": QT_TRANSLATE_NOOP( 184 "D234": QT_TRANSLATE_NOOP(
184 "Pep257Checker", 185 "Pep257Checker",
185 "docstring does not contain a @return line but returns something"), 186 "docstring does not contain a @return line but function/method"
187 " returns something"),
186 "D235": QT_TRANSLATE_NOOP( 188 "D235": QT_TRANSLATE_NOOP(
187 "Pep257Checker", 189 "Pep257Checker",
188 "docstring contains a @return line but doesn't return anything"), 190 "docstring contains a @return line but function/method doesn't"
191 " return anything"),
189 "D236": QT_TRANSLATE_NOOP( 192 "D236": QT_TRANSLATE_NOOP(
190 "Pep257Checker", 193 "Pep257Checker",
191 "docstring does not contain enough @param/@keyparam lines"), 194 "docstring does not contain enough @param/@keyparam lines"),
192 "D237": QT_TRANSLATE_NOOP( 195 "D237": QT_TRANSLATE_NOOP(
193 "Pep257Checker", 196 "Pep257Checker",
212 "Pep257Checker", 215 "Pep257Checker",
213 "docstring summary is not followed by a blank line"), 216 "docstring summary is not followed by a blank line"),
214 "D247": QT_TRANSLATE_NOOP( 217 "D247": QT_TRANSLATE_NOOP(
215 "Pep257Checker", 218 "Pep257Checker",
216 "last paragraph of docstring is followed by a blank line"), 219 "last paragraph of docstring is followed by a blank line"),
220 "D250": QT_TRANSLATE_NOOP(
221 "Pep257Checker",
222 "docstring does not contain a @exception line but function/method"
223 " raises an exception"),
224 "D251": QT_TRANSLATE_NOOP(
225 "Pep257Checker",
226 "docstring contains a @exception line but function/method doesn't"
227 " raise an exception"),
217 } 228 }
218 229
219 def __init__(self, source, filename, select, ignore, expected, repeat, 230 def __init__(self, source, filename, select, ignore, expected, repeat,
220 maxLineLength=79, docType="pep257"): 231 maxLineLength=79, docType="pep257"):
221 """ 232 """
314 (self.__checkEricReturn, ("D234", "D235")), 325 (self.__checkEricReturn, ("D234", "D235")),
315 (self.__checkEricFunctionArguments, 326 (self.__checkEricFunctionArguments,
316 ("D236", "D237", "D238", "D239")), 327 ("D236", "D237", "D238", "D239")),
317 (self.__checkEricNoBlankBeforeAndAfterClassOrFunction, 328 (self.__checkEricNoBlankBeforeAndAfterClassOrFunction,
318 ("D244", "D245")), 329 ("D244", "D245")),
330 (self.__checkEricException, ("D250", "D251")),
319 ], 331 ],
320 "docstring": [ 332 "docstring": [
321 (self.__checkTripleDoubleQuotes, ("D111",)), 333 (self.__checkTripleDoubleQuotes, ("D111",)),
322 (self.__checkBackslashes, ("D112",)), 334 (self.__checkBackslashes, ("D112",)),
323 (self.__checkUnicode, ("D113",)), 335 (self.__checkUnicode, ("D113",)),
371 383
372 if code and (self.counters[code] == 1 or self.__repeat): 384 if code and (self.counters[code] == 1 or self.__repeat):
373 if code in Pep257Checker.Codes: 385 if code in Pep257Checker.Codes:
374 text = self.getMessage(code, *args) 386 text = self.getMessage(code, *args)
375 else: 387 else:
376 text = code + " " + QCoreApplication.translate("Pep257Checker", 388 text = code + " " + QCoreApplication.translate(
377 "no message for this code defined") 389 "Pep257Checker", "no message for this code defined")
378 # record the issue with one based line number 390 # record the issue with one based line number
379 self.errors.append((self.__filename, lineNumber + 1, offset, text)) 391 self.errors.append((self.__filename, lineNumber + 1, offset, text))
380 392
381 @classmethod 393 @classmethod
382 def getMessage(cls, code, *args): 394 def getMessage(cls, code, *args):
460 """ 472 """
461 summaries = [] 473 summaries = []
462 lines = docstringContext.source() 474 lines = docstringContext.source()
463 475
464 line0 = (lines[0] 476 line0 = (lines[0]
465 .replace('r"""', "", 1) 477 .replace('r"""', "", 1)
466 .replace('u"""', "", 1) 478 .replace('u"""', "", 1)
467 .replace('"""', "") 479 .replace('"""', "")
468 .replace("r'''", "", 1) 480 .replace("r'''", "", 1)
469 .replace("u'''", "", 1) 481 .replace("u'''", "", 1)
470 .replace("'''", "") 482 .replace("'''", "")
471 .strip()) 483 .strip())
472 if len(lines) > 1: 484 if len(lines) > 1:
473 line1 = lines[1].strip().replace('"""', "").replace("'''", "") 485 line1 = lines[1].strip().replace('"""', "").replace("'''", "")
474 else: 486 else:
475 line1 = "" 487 line1 = ""
476 if len(lines) > 2: 488 if len(lines) > 2:
568 def __parseDocstring(self, context, what=''): 580 def __parseDocstring(self, context, what=''):
569 """ 581 """
570 Private method to extract a docstring given `def` or `class` source. 582 Private method to extract a docstring given `def` or `class` source.
571 583
572 @param context context data to get the docstring from (Pep257Context) 584 @param context context data to get the docstring from (Pep257Context)
585 @param what string denoting what is being parsed (string)
573 @return context of extracted docstring (Pep257Context) 586 @return context of extracted docstring (Pep257Context)
574 """ 587 """
575 moduleDocstring = self.__parseModuleDocstring(context.source()) 588 moduleDocstring = self.__parseModuleDocstring(context.source())
576 if what.startswith('module') or context.contextType() == "module": 589 if what.startswith('module') or context.contextType() == "module":
577 return moduleDocstring 590 return moduleDocstring
1105 docstringContext.start() + lineNumber + len(summaryLines) - 1, 1118 docstringContext.start() + lineNumber + len(summaryLines) - 1,
1106 0, "D231") 1119 0, "D231")
1107 1120
1108 def __checkEricReturn(self, docstringContext, context): 1121 def __checkEricReturn(self, docstringContext, context):
1109 """ 1122 """
1110 Private method to check, that docstrings contain an @return line 1123 Private method to check, that docstrings contain an @return line
1111 if they return anything and don't otherwise. 1124 if they return anything and don't otherwise.
1112 1125
1113 @param docstringContext docstring context (Pep257Context) 1126 @param docstringContext docstring context (Pep257Context)
1114 @param context context of the docstring (Pep257Context) 1127 @param context context of the docstring (Pep257Context)
1115 """ 1128 """
1131 set([])): 1144 set([])):
1132 self.__error(docstringContext.end(), 0, "D235") 1145 self.__error(docstringContext.end(), 0, "D235")
1133 1146
1134 def __checkEricFunctionArguments(self, docstringContext, context): 1147 def __checkEricFunctionArguments(self, docstringContext, context):
1135 """ 1148 """
1136 Private method to check, that docstrings contain an @param line 1149 Private method to check, that docstrings contain an @param and/or
1137 for each argument. 1150 @keyparam line for each argument.
1138 1151
1139 @param docstringContext docstring context (Pep257Context) 1152 @param docstringContext docstring context (Pep257Context)
1140 @param context context of the docstring (Pep257Context) 1153 @param context context of the docstring (Pep257Context)
1141 """ 1154 """
1142 if docstringContext is None or self.__isScript: 1155 if docstringContext is None or self.__isScript:
1154 argNames.remove("self") 1167 argNames.remove("self")
1155 if "cls" in argNames: 1168 if "cls" in argNames:
1156 argNames.remove("cls") 1169 argNames.remove("cls")
1157 1170
1158 docstring = docstringContext.ssource() 1171 docstring = docstringContext.ssource()
1159 if (docstring.count("@param") + docstring.count("@keyparam") < 1172 if (docstring.count("@param") + docstring.count("@keyparam") <
1160 len(argNames + kwNames)): 1173 len(argNames + kwNames)):
1161 self.__error(docstringContext.end(), 0, "D236") 1174 self.__error(docstringContext.end(), 0, "D236")
1162 elif (docstring.count("@param") + docstring.count("@keyparam") > 1175 elif (docstring.count("@param") + docstring.count("@keyparam") >
1163 len(argNames + kwNames)): 1176 len(argNames + kwNames)):
1164 self.__error(docstringContext.end(), 0, "D237") 1177 self.__error(docstringContext.end(), 0, "D237")
1165 else: 1178 else:
1166 # extract @param and @keyparam from docstring 1179 # extract @param and @keyparam from docstring
1167 args = [] 1180 args = []
1179 self.__error(docstringContext.end(), 0, "D238") 1192 self.__error(docstringContext.end(), 0, "D238")
1180 return 1193 return
1181 if argNames + kwNames != args: 1194 if argNames + kwNames != args:
1182 self.__error(docstringContext.end(), 0, "D239") 1195 self.__error(docstringContext.end(), 0, "D239")
1183 1196
1197 def __checkEricException(self, docstringContext, context):
1198 """
1199 Private method to check, that docstrings contain an &#64;exception line
1200 if they raise an exception and don't otherwise.
1201
1202 @param docstringContext docstring context (Pep257Context)
1203 @param context context of the docstring (Pep257Context)
1204 """
1205 if docstringContext is None or self.__isScript:
1206 return
1207
1208 tokens = list(
1209 tokenize.generate_tokens(StringIO(context.ssource()).readline))
1210 exception = [tokens[i + 1][0] for i, token in enumerate(tokens)
1211 if token[1] == "raise"]
1212 if "@exception" not in docstringContext.ssource() and \
1213 "@throws" not in docstringContext.ssource() and \
1214 "@raise" not in docstringContext.ssource():
1215 if (set(exception) -
1216 set([tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE]) !=
1217 set([])):
1218 self.__error(docstringContext.end(), 0, "D250")
1219 else:
1220 if (set(exception) -
1221 set([tokenize.COMMENT, tokenize.NL, tokenize.NEWLINE]) ==
1222 set([])):
1223 self.__error(docstringContext.end(), 0, "D251")
1224
1184 def __checkEricBlankAfterSummary(self, docstringContext, context): 1225 def __checkEricBlankAfterSummary(self, docstringContext, context):
1185 """ 1226 """
1186 Private method to check, that docstring summaries are followed 1227 Private method to check, that docstring summaries are followed
1187 by a blank line. 1228 by a blank line.
1188 1229

eric ide

mercurial