19 from . import pep8 |
19 from . import pep8 |
20 |
20 |
21 import Utilities |
21 import Utilities |
22 |
22 |
23 # TODO: add fixers for some docstring issues |
23 # TODO: add fixers for some docstring issues |
24 |
24 # D111, D112, D113 |
25 Pep8FixableIssues = ["E101", "E111", "E121", "E122", "E123", "E124", |
25 |
|
26 Pep8FixableIssues = ["D121", "D131", "D141", "D142", "D143", "D144", "D145", |
|
27 "E101", "E111", "E121", "E122", "E123", "E124", |
26 "E125", "E126", "E127", "E128", "E133", "E201", |
28 "E125", "E126", "E127", "E128", "E133", "E201", |
27 "E202", "E203", "E211", "E221", "E222", "E223", |
29 "E202", "E203", "E211", "E221", "E222", "E223", |
28 "E224", "E225", "E226", "E227", "E228", "E231", |
30 "E224", "E225", "E226", "E227", "E228", "E231", |
29 "E241", "E242", "E251", "E261", "E262", "E271", |
31 "E241", "E242", "E251", "E261", "E262", "E271", |
30 "E272", "E273", "E274", "E301", "E302", "E303", |
32 "E272", "E273", "E274", "E301", "E302", "E303", |
76 self.__filename = os.path.join( |
78 self.__filename = os.path.join( |
77 os.path.dirname(self.__filename), |
79 os.path.dirname(self.__filename), |
78 "fixed_" + os.path.basename(self.__filename)) |
80 "fixed_" + os.path.basename(self.__filename)) |
79 |
81 |
80 self.__fixes = { |
82 self.__fixes = { |
|
83 "D121": self.__fixD121, |
|
84 "D131": self.__fixD131, |
|
85 "D141": self.__fixD141, |
|
86 "D142": self.__fixD142, |
|
87 "D143": self.__fixD143, |
|
88 "D144": self.__fixD144, |
|
89 "D145": self.__fixD145, |
81 "E101": self.__fixE101, |
90 "E101": self.__fixE101, |
82 "E111": self.__fixE101, |
91 "E111": self.__fixE101, |
83 "E121": self.__fixE121, |
92 "E121": self.__fixE121, |
84 "E122": self.__fixE122, |
93 "E122": self.__fixE122, |
85 "E123": self.__fixE123, |
94 "E123": self.__fixE123, |
1331 a message for the fix (string) and an ID for a deferred |
1340 a message for the fix (string) and an ID for a deferred |
1332 fix (integer) |
1341 fix (integer) |
1333 """ |
1342 """ |
1334 self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=") |
1343 self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=") |
1335 return (1, self.trUtf8("'<>' replaced by '!='."), 0) |
1344 return (1, self.trUtf8("'<>' replaced by '!='."), 0) |
|
1345 |
|
1346 def __fixD121(self, code, line, pos, apply=False): |
|
1347 """ |
|
1348 Private method to fix a single line docstring on multiple lines (D121). |
|
1349 |
|
1350 @param code code of the issue (string) |
|
1351 @param line line number of the issue (integer) |
|
1352 @param pos position inside line (integer) |
|
1353 @keyparam apply flag indicating, that the fix should be applied |
|
1354 (boolean) |
|
1355 @return value indicating an applied/deferred fix (-1, 0, 1), |
|
1356 a message for the fix (string) and an ID for a deferred |
|
1357 fix (integer) |
|
1358 """ |
|
1359 if apply: |
|
1360 line = line - 1 |
|
1361 if not self.__source[line].lstrip().startswith( |
|
1362 ('"""', 'r"""', 'u"""')): |
|
1363 # only correctly formatted docstrings will be fixed |
|
1364 return (0, "", 0) |
|
1365 |
|
1366 docstring = self.__source[line].rstrip() + \ |
|
1367 self.__source[line + 1].strip() |
|
1368 if docstring.endswith('"""'): |
|
1369 docstring += self.__getEol() |
|
1370 else: |
|
1371 docstring += self.__source[line + 2].lstrip() |
|
1372 self.__source[line + 2] = "" |
|
1373 |
|
1374 self.__source[line] = docstring |
|
1375 self.__source[line + 1] = "" |
|
1376 return ( |
|
1377 1, |
|
1378 self.trUtf8("Single line docstring put on one line."), |
|
1379 0) |
|
1380 else: |
|
1381 id = self.__getID() |
|
1382 self.__stack.append((id, code, line, pos)) |
|
1383 return (-1, "", id) |
|
1384 |
|
1385 def __fixD131(self, code, line, pos): |
|
1386 """ |
|
1387 Private method to fix a single line docstring on multiple lines (D121). |
|
1388 |
|
1389 @param code code of the issue (string) |
|
1390 @param line line number of the issue (integer) |
|
1391 @param pos position inside line (integer) |
|
1392 @return value indicating an applied/deferred fix (-1, 0, 1), |
|
1393 a message for the fix (string) and an ID for a deferred |
|
1394 fix (integer) |
|
1395 """ |
|
1396 line = line - 1 |
|
1397 newText = "" |
|
1398 if self.__source[line].rstrip().endswith(('"""', "'''")) and \ |
|
1399 self.__source[line].lstrip().startswith( ('"""', 'r"""', 'u"""')): |
|
1400 # it is a one-liner |
|
1401 newText = self.__source[line].rstrip()[:-3] + "." + \ |
|
1402 self.__source[line].rstrip()[-3:] + self.__getEol() |
|
1403 else: |
|
1404 if line < len(self.__source) - 1 and \ |
|
1405 (not self.__source[line + 1].strip() or |
|
1406 self.__source[line + 1].strip() in ('"""', "'''")): |
|
1407 newText = self.__source[line].rstrip() + "." + self.__getEol() |
|
1408 |
|
1409 if newText: |
|
1410 self.__source[line] = newText |
|
1411 return (1, self.trUtf8("Period added to summary line."), 0) |
|
1412 else: |
|
1413 return (0, "", 0) |
|
1414 |
|
1415 def __fixD141(self, code, line, pos, apply=False): |
|
1416 """ |
|
1417 Private method to fix a function/method docstring preceded by a |
|
1418 blank line (D141). |
|
1419 |
|
1420 @param code code of the issue (string) |
|
1421 @param line line number of the issue (integer) |
|
1422 @param pos position inside line (integer) |
|
1423 @keyparam apply flag indicating, that the fix should be applied |
|
1424 (boolean) |
|
1425 @return value indicating an applied/deferred fix (-1, 0, 1), |
|
1426 a message for the fix (string) and an ID for a deferred |
|
1427 fix (integer) |
|
1428 """ |
|
1429 if apply: |
|
1430 line = line - 1 |
|
1431 self.__source[line - 1] = "" |
|
1432 return ( |
|
1433 1, |
|
1434 self.trUtf8( |
|
1435 "Blank line before function/method docstring removed."), |
|
1436 0) |
|
1437 else: |
|
1438 id = self.__getID() |
|
1439 self.__stack.append((id, code, line, pos)) |
|
1440 return (-1, "", id) |
|
1441 |
|
1442 def __fixD142(self, code, line, pos, apply=False): |
|
1443 """ |
|
1444 Private method to fix a class docstring not preceded by a |
|
1445 blank line (D142). |
|
1446 |
|
1447 @param code code of the issue (string) |
|
1448 @param line line number of the issue (integer) |
|
1449 @param pos position inside line (integer) |
|
1450 @keyparam apply flag indicating, that the fix should be applied |
|
1451 (boolean) |
|
1452 @return value indicating an applied/deferred fix (-1, 0, 1), |
|
1453 a message for the fix (string) and an ID for a deferred |
|
1454 fix (integer) |
|
1455 """ |
|
1456 if apply: |
|
1457 line = line - 1 |
|
1458 self.__source[line] = self.__getEol() + self.__source[line] |
|
1459 return ( |
|
1460 1, |
|
1461 self.trUtf8("Blank line inserted before class docstring."), |
|
1462 0) |
|
1463 else: |
|
1464 id = self.__getID() |
|
1465 self.__stack.append((id, code, line, pos)) |
|
1466 return (-1, "", id) |
|
1467 |
|
1468 def __fixD143(self, code, line, pos, apply=False): |
|
1469 """ |
|
1470 Private method to fix a class docstring not followed by a |
|
1471 blank line (D143). |
|
1472 |
|
1473 @param code code of the issue (string) |
|
1474 @param line line number of the issue (integer) |
|
1475 @param pos position inside line (integer) |
|
1476 @keyparam apply flag indicating, that the fix should be applied |
|
1477 (boolean) |
|
1478 @return value indicating an applied/deferred fix (-1, 0, 1), |
|
1479 a message for the fix (string) and an ID for a deferred |
|
1480 fix (integer) |
|
1481 """ |
|
1482 if apply: |
|
1483 line = line - 1 |
|
1484 self.__source[line] += self.__getEol() |
|
1485 return ( |
|
1486 1, |
|
1487 self.trUtf8("Blank line inserted after class docstring."), |
|
1488 0) |
|
1489 else: |
|
1490 id = self.__getID() |
|
1491 self.__stack.append((id, code, line, pos)) |
|
1492 return (-1, "", id) |
|
1493 |
|
1494 def __fixD144(self, code, line, pos, apply=False): |
|
1495 """ |
|
1496 Private method to fix a docstring summary not followed by a |
|
1497 blank line (D144). |
|
1498 |
|
1499 @param code code of the issue (string) |
|
1500 @param line line number of the issue (integer) |
|
1501 @param pos position inside line (integer) |
|
1502 @keyparam apply flag indicating, that the fix should be applied |
|
1503 (boolean) |
|
1504 @return value indicating an applied/deferred fix (-1, 0, 1), |
|
1505 a message for the fix (string) and an ID for a deferred |
|
1506 fix (integer) |
|
1507 """ |
|
1508 if apply: |
|
1509 line = line - 1 |
|
1510 if not self.__source[line].rstrip().endswith("."): |
|
1511 # only correct summary lines can be fixed here |
|
1512 return (0, "", 0) |
|
1513 |
|
1514 self.__source[line] += self.__getEol() |
|
1515 return ( |
|
1516 1, |
|
1517 self.trUtf8("Blank line inserted after docstring summary."), |
|
1518 0) |
|
1519 else: |
|
1520 id = self.__getID() |
|
1521 self.__stack.append((id, code, line, pos)) |
|
1522 return (-1, "", id) |
|
1523 |
|
1524 def __fixD145(self, code, line, pos, apply=False): |
|
1525 """ |
|
1526 Private method to fix the last paragraph of a multi-line docstring |
|
1527 not followed by a blank line (D143). |
|
1528 |
|
1529 @param code code of the issue (string) |
|
1530 @param line line number of the issue (integer) |
|
1531 @param pos position inside line (integer) |
|
1532 @keyparam apply flag indicating, that the fix should be applied |
|
1533 (boolean) |
|
1534 @return value indicating an applied/deferred fix (-1, 0, 1), |
|
1535 a message for the fix (string) and an ID for a deferred |
|
1536 fix (integer) |
|
1537 """ |
|
1538 if apply: |
|
1539 line = line - 1 |
|
1540 self.__source[line] = self.__getEol() + self.__source[line] |
|
1541 return ( |
|
1542 1, |
|
1543 self.trUtf8("Blank line inserted after last paragraph" |
|
1544 " of docstring."), |
|
1545 0) |
|
1546 else: |
|
1547 id = self.__getID() |
|
1548 self.__stack.append((id, code, line, pos)) |
|
1549 return (-1, "", id) |
1336 |
1550 |
1337 |
1551 |
1338 class Pep8Reindenter(object): |
1552 class Pep8Reindenter(object): |
1339 """ |
1553 """ |
1340 Class to reindent badly-indented code to uniformly use four-space |
1554 Class to reindent badly-indented code to uniformly use four-space |