1# -*- coding: utf-8 -*- 2 3# Copyright (c) 2014 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> 4# 5 6""" 7Module implementing message translations for the code style plugin messages. 8""" 9 10import re 11import contextlib 12 13from PyQt5.QtCore import QCoreApplication 14 15from .Annotations.translations import ( 16 _annotationsMessages, _annotationsMessagesSampleArgs 17) 18from .Complexity.translations import ( 19 _complexityMessages, _complexityMessagesSampleArgs 20) 21from .DocStyle.translations import ( 22 _docStyleMessages, _docStyleMessagesSampleArgs 23) 24from .Miscellaneous.translations import ( 25 _miscellaneousMessages, _miscellaneousMessagesSampleArgs 26) 27from .Naming.translations import _namingStyleMessages 28from .PathLib.translations import _pathlibMessages 29from .Security.translations import ( 30 _securityMessages, _securityMessagesSampleArgs 31) 32from .Simplify.translations import ( 33 _simplifyMessages, _simplifyMessagesSampleArgs 34) 35 36################################################################## 37## pycodestyle error messages 38################################################################## 39 40_pycodestyleErrorMessages = { 41 "E101": QCoreApplication.translate( 42 "pycodestyle", 43 "indentation contains mixed spaces and tabs"), 44 "E111": QCoreApplication.translate( 45 "pycodestyle", 46 "indentation is not a multiple of four"), 47 "E112": QCoreApplication.translate( 48 "pycodestyle", 49 "expected an indented block"), 50 "E113": QCoreApplication.translate( 51 "pycodestyle", 52 "unexpected indentation"), 53 "E114": QCoreApplication.translate( 54 "pycodestyle", 55 "indentation is not a multiple of four (comment)"), 56 "E115": QCoreApplication.translate( 57 "pycodestyle", 58 "expected an indented block (comment)"), 59 "E116": QCoreApplication.translate( 60 "pycodestyle", 61 "unexpected indentation (comment)"), 62 "E117": QCoreApplication.translate( 63 "pycodestyle", 64 "over-indented"), 65 "E121": QCoreApplication.translate( 66 "pycodestyle", 67 "continuation line indentation is not a multiple of four"), 68 "E122": QCoreApplication.translate( 69 "pycodestyle", 70 "continuation line missing indentation or outdented"), 71 "E123": QCoreApplication.translate( 72 "pycodestyle", 73 "closing bracket does not match indentation of opening" 74 " bracket's line"), 75 "E124": QCoreApplication.translate( 76 "pycodestyle", 77 "closing bracket does not match visual indentation"), 78 "E125": QCoreApplication.translate( 79 "pycodestyle", 80 "continuation line with same indent as next logical line"), 81 "E126": QCoreApplication.translate( 82 "pycodestyle", 83 "continuation line over-indented for hanging indent"), 84 "E127": QCoreApplication.translate( 85 "pycodestyle", 86 "continuation line over-indented for visual indent"), 87 "E128": QCoreApplication.translate( 88 "pycodestyle", 89 "continuation line under-indented for visual indent"), 90 "E129": QCoreApplication.translate( 91 "pycodestyle", 92 "visually indented line with same indent as next logical line"), 93 "E131": QCoreApplication.translate( 94 "pycodestyle", 95 "continuation line unaligned for hanging indent"), 96 "E133": QCoreApplication.translate( 97 "pycodestyle", 98 "closing bracket is missing indentation"), 99 "E201": QCoreApplication.translate( 100 "pycodestyle", 101 "whitespace after '{0}'"), 102 "E202": QCoreApplication.translate( 103 "pycodestyle", 104 "whitespace before '{0}'"), 105 "E203": QCoreApplication.translate( 106 "pycodestyle", 107 "whitespace before '{0}'"), 108 "E211": QCoreApplication.translate( 109 "pycodestyle", 110 "whitespace before '{0}'"), 111 "E221": QCoreApplication.translate( 112 "pycodestyle", 113 "multiple spaces before operator"), 114 "E222": QCoreApplication.translate( 115 "pycodestyle", 116 "multiple spaces after operator"), 117 "E223": QCoreApplication.translate( 118 "pycodestyle", 119 "tab before operator"), 120 "E224": QCoreApplication.translate( 121 "pycodestyle", 122 "tab after operator"), 123 "E225": QCoreApplication.translate( 124 "pycodestyle", 125 "missing whitespace around operator"), 126 "E226": QCoreApplication.translate( 127 "pycodestyle", 128 "missing whitespace around arithmetic operator"), 129 "E227": QCoreApplication.translate( 130 "pycodestyle", 131 "missing whitespace around bitwise or shift operator"), 132 "E228": QCoreApplication.translate( 133 "pycodestyle", 134 "missing whitespace around modulo operator"), 135 "E231": QCoreApplication.translate( 136 "pycodestyle", 137 "missing whitespace after '{0}'"), 138 "E241": QCoreApplication.translate( 139 "pycodestyle", 140 "multiple spaces after '{0}'"), 141 "E242": QCoreApplication.translate( 142 "pycodestyle", 143 "tab after '{0}'"), 144 "E251": QCoreApplication.translate( 145 "pycodestyle", 146 "unexpected spaces around keyword / parameter equals"), 147 "E252": QCoreApplication.translate( 148 "pycodestyle", 149 "missing whitespace around parameter equals"), 150 "E261": QCoreApplication.translate( 151 "pycodestyle", 152 "at least two spaces before inline comment"), 153 "E262": QCoreApplication.translate( 154 "pycodestyle", 155 "inline comment should start with '# '"), 156 "E265": QCoreApplication.translate( 157 "pycodestyle", 158 "block comment should start with '# '"), 159 "E266": QCoreApplication.translate( 160 "pycodestyle", 161 "too many leading '#' for block comment"), 162 "E271": QCoreApplication.translate( 163 "pycodestyle", 164 "multiple spaces after keyword"), 165 "E272": QCoreApplication.translate( 166 "pycodestyle", 167 "multiple spaces before keyword"), 168 "E273": QCoreApplication.translate( 169 "pycodestyle", 170 "tab after keyword"), 171 "E274": QCoreApplication.translate( 172 "pycodestyle", 173 "tab before keyword"), 174 "E275": QCoreApplication.translate( 175 "pycodestyle", 176 "missing whitespace after keyword"), 177 "E301": QCoreApplication.translate( 178 "pycodestyle", 179 "expected {0} blank lines, found {1}"), 180 "E302": QCoreApplication.translate( 181 "pycodestyle", 182 "expected {0} blank lines, found {1}"), 183 "E303": QCoreApplication.translate( 184 "pycodestyle", 185 "too many blank lines ({0}), expected {1}"), 186 "E304": QCoreApplication.translate( 187 "pycodestyle", 188 "blank lines found after function decorator"), 189 "E305": QCoreApplication.translate( 190 "pycodestyle", 191 "expected {0} blank lines after class or function definition," 192 " found {1}"), 193 "E306": QCoreApplication.translate( 194 "pycodestyle", 195 "expected {0} blank lines before a nested definition, found {1}"), 196 "E307": QCoreApplication.translate( 197 "pycodestyle", 198 "too many blank lines ({0}) before a nested definition, expected {1}"), 199 "E308": QCoreApplication.translate( 200 "pycodestyle", 201 "too many blank lines ({0})"), 202 "E401": QCoreApplication.translate( 203 "pycodestyle", 204 "multiple imports on one line"), 205 "E402": QCoreApplication.translate( 206 "pycodestyle", 207 "module level import not at top of file"), 208 "E501": QCoreApplication.translate( 209 "pycodestyle", 210 "line too long ({0} > {1} characters)"), 211 "E502": QCoreApplication.translate( 212 "pycodestyle", 213 "the backslash is redundant between brackets"), 214 "E701": QCoreApplication.translate( 215 "pycodestyle", 216 "multiple statements on one line (colon)"), 217 "E702": QCoreApplication.translate( 218 "pycodestyle", 219 "multiple statements on one line (semicolon)"), 220 "E703": QCoreApplication.translate( 221 "pycodestyle", 222 "statement ends with a semicolon"), 223 "E704": QCoreApplication.translate( 224 "pycodestyle", 225 "multiple statements on one line (def)"), 226 "E711": QCoreApplication.translate( 227 "pycodestyle", 228 "comparison to {0} should be {1}"), 229 "E712": QCoreApplication.translate( 230 "pycodestyle", 231 "comparison to {0} should be {1}"), 232 "E713": QCoreApplication.translate( 233 "pycodestyle", 234 "test for membership should be 'not in'"), 235 "E714": QCoreApplication.translate( 236 "pycodestyle", 237 "test for object identity should be 'is not'"), 238 "E721": QCoreApplication.translate( 239 "pycodestyle", 240 "do not compare types, use 'isinstance()'"), 241 "E722": QCoreApplication.translate( 242 "pycodestyle", 243 "do not use bare except"), 244 "E731": QCoreApplication.translate( 245 "pycodestyle", 246 "do not assign a lambda expression, use a def"), 247 "E741": QCoreApplication.translate( 248 "pycodestyle", 249 "ambiguous variable name '{0}'"), 250 "E742": QCoreApplication.translate( 251 "pycodestyle", 252 "ambiguous class definition '{0}'"), 253 "E743": QCoreApplication.translate( 254 "pycodestyle", 255 "ambiguous function definition '{0}'"), 256 "E901": QCoreApplication.translate( 257 "pycodestyle", 258 "{0}: {1}"), 259 "E902": QCoreApplication.translate( 260 "pycodestyle", 261 "{0}"), 262} 263 264################################################################## 265## pycodestyle warning messages 266################################################################## 267 268_pycodestyleWarningMessages = { 269 "W191": QCoreApplication.translate( 270 "pycodestyle", 271 "indentation contains tabs"), 272 "W291": QCoreApplication.translate( 273 "pycodestyle", 274 "trailing whitespace"), 275 "W292": QCoreApplication.translate( 276 "pycodestyle", 277 "no newline at end of file"), 278 "W293": QCoreApplication.translate( 279 "pycodestyle", 280 "blank line contains whitespace"), 281 "W391": QCoreApplication.translate( 282 "pycodestyle", 283 "blank line at end of file"), 284 "W503": QCoreApplication.translate( 285 "pycodestyle", 286 "line break before binary operator"), 287 "W504": QCoreApplication.translate( 288 "pycodestyle", 289 "line break after binary operator"), 290 "W505": QCoreApplication.translate( 291 "pycodestyle", 292 "doc line too long ({0} > {1} characters)"), 293 "W601": QCoreApplication.translate( 294 "pycodestyle", 295 ".has_key() is deprecated, use 'in'"), 296 "W602": QCoreApplication.translate( 297 "pycodestyle", 298 "deprecated form of raising exception"), 299 "W603": QCoreApplication.translate( 300 "pycodestyle", 301 "'<>' is deprecated, use '!='"), 302 "W604": QCoreApplication.translate( 303 "pycodestyle", 304 "backticks are deprecated, use 'repr()'"), 305 "W605": QCoreApplication.translate( 306 "pycodestyle", 307 "invalid escape sequence '\\{0}'"), 308 "W606": QCoreApplication.translate( 309 "pycodestyle", 310 "'async' and 'await' are reserved keywords starting with Python 3.7"), 311} 312 313################################################################## 314## CodeStyleFixer messages 315################################################################## 316 317_fixMessages = { 318 "FIXD111": QCoreApplication.translate( 319 'CodeStyleFixer', 320 "Triple single quotes converted to triple double quotes."), 321 'FIXD112': QCoreApplication.translate( 322 'CodeStyleFixer', 323 'Introductory quotes corrected to be {0}"""'), 324 "FIXD121": QCoreApplication.translate( 325 'CodeStyleFixer', 326 "Single line docstring put on one line."), 327 "FIXD131": QCoreApplication.translate( 328 'CodeStyleFixer', 329 "Period added to summary line."), 330 "FIXD141": QCoreApplication.translate( 331 'CodeStyleFixer', 332 "Blank line before function/method docstring removed."), 333 "FIXD142": QCoreApplication.translate( 334 'CodeStyleFixer', 335 "Blank line inserted before class docstring."), 336 "FIXD143": QCoreApplication.translate( 337 'CodeStyleFixer', 338 "Blank line inserted after class docstring."), 339 "FIXD144": QCoreApplication.translate( 340 'CodeStyleFixer', 341 "Blank line inserted after docstring summary."), 342 "FIXD145": QCoreApplication.translate( 343 'CodeStyleFixer', 344 "Blank line inserted after last paragraph of docstring."), 345 "FIXD221": QCoreApplication.translate( 346 'CodeStyleFixer', 347 "Leading quotes put on separate line."), 348 "FIXD222": QCoreApplication.translate( 349 'CodeStyleFixer', 350 "Trailing quotes put on separate line."), 351 "FIXD242": QCoreApplication.translate( 352 'CodeStyleFixer', 353 "Blank line before class docstring removed."), 354 "FIXD244": QCoreApplication.translate( 355 'CodeStyleFixer', 356 "Blank line before function/method docstring removed."), 357 "FIXD243": QCoreApplication.translate( 358 'CodeStyleFixer', 359 "Blank line after class docstring removed."), 360 "FIXD245": QCoreApplication.translate( 361 'CodeStyleFixer', 362 "Blank line after function/method docstring removed."), 363 "FIXD247": QCoreApplication.translate( 364 'CodeStyleFixer', 365 "Blank line after last paragraph removed."), 366 "FIXE101": QCoreApplication.translate( 367 'CodeStyleFixer', 368 "Tab converted to 4 spaces."), 369 "FIXE111": QCoreApplication.translate( 370 'CodeStyleFixer', 371 "Indentation adjusted to be a multiple of four."), 372 "FIXE121": QCoreApplication.translate( 373 'CodeStyleFixer', 374 "Indentation of continuation line corrected."), 375 "FIXE124": QCoreApplication.translate( 376 'CodeStyleFixer', 377 "Indentation of closing bracket corrected."), 378 "FIXE122": QCoreApplication.translate( 379 'CodeStyleFixer', 380 "Missing indentation of continuation line corrected."), 381 "FIXE123": QCoreApplication.translate( 382 'CodeStyleFixer', 383 "Closing bracket aligned to opening bracket."), 384 "FIXE125": QCoreApplication.translate( 385 'CodeStyleFixer', 386 "Indentation level changed."), 387 "FIXE126": QCoreApplication.translate( 388 'CodeStyleFixer', 389 "Indentation level of hanging indentation changed."), 390 "FIXE127": QCoreApplication.translate( 391 'CodeStyleFixer', 392 "Visual indentation corrected."), 393 "FIXE201": QCoreApplication.translate( 394 'CodeStyleFixer', 395 "Extraneous whitespace removed."), 396 "FIXE225": QCoreApplication.translate( 397 'CodeStyleFixer', 398 "Missing whitespace added."), 399 "FIXE221": QCoreApplication.translate( 400 'CodeStyleFixer', 401 "Extraneous whitespace removed."), 402 "FIXE231": QCoreApplication.translate( 403 'CodeStyleFixer', 404 "Missing whitespace added."), 405 "FIXE251": QCoreApplication.translate( 406 'CodeStyleFixer', 407 "Extraneous whitespace removed."), 408 "FIXE261": QCoreApplication.translate( 409 'CodeStyleFixer', 410 "Whitespace around comment sign corrected."), 411 412 "FIXE302+": lambda n=1: QCoreApplication.translate( 413 'CodeStyleFixer', 414 "%n blank line(s) inserted.", '', n), 415 "FIXE302-": lambda n=1: QCoreApplication.translate( 416 'CodeStyleFixer', 417 "%n superfluous lines removed", '', n), 418 419 "FIXE303": QCoreApplication.translate( 420 'CodeStyleFixer', 421 "Superfluous blank lines removed."), 422 "FIXE304": QCoreApplication.translate( 423 'CodeStyleFixer', 424 "Superfluous blank lines after function decorator removed."), 425 "FIXE401": QCoreApplication.translate( 426 'CodeStyleFixer', 427 "Imports were put on separate lines."), 428 "FIXE501": QCoreApplication.translate( 429 'CodeStyleFixer', 430 "Long lines have been shortened."), 431 "FIXE502": QCoreApplication.translate( 432 'CodeStyleFixer', 433 "Redundant backslash in brackets removed."), 434 "FIXE701": QCoreApplication.translate( 435 'CodeStyleFixer', 436 "Compound statement corrected."), 437 "FIXE702": QCoreApplication.translate( 438 'CodeStyleFixer', 439 "Compound statement corrected."), 440 "FIXE711": QCoreApplication.translate( 441 'CodeStyleFixer', 442 "Comparison to None/True/False corrected."), 443 "FIXN804": QCoreApplication.translate( 444 'CodeStyleFixer', 445 "'{0}' argument added."), 446 "FIXN806": QCoreApplication.translate( 447 'CodeStyleFixer', 448 "'{0}' argument removed."), 449 "FIXW291": QCoreApplication.translate( 450 'CodeStyleFixer', 451 "Whitespace stripped from end of line."), 452 "FIXW292": QCoreApplication.translate( 453 'CodeStyleFixer', 454 "newline added to end of file."), 455 "FIXW391": QCoreApplication.translate( 456 'CodeStyleFixer', 457 "Superfluous trailing blank lines removed from end of file."), 458 "FIXW603": QCoreApplication.translate( 459 'CodeStyleFixer', 460 "'<>' replaced by '!='."), 461 462 "FIXWRITE_ERROR": QCoreApplication.translate( 463 'CodeStyleFixer', 464 "Could not save the file! Skipping it. Reason: {0}"), 465} 466 467_pycodestyleErrorMessagesSampleArgs = { 468 "E201": ["([{"], 469 "E202": ["}])"], 470 "E203": [",;:"], 471 "E211": ["(["], 472 "E231": [",;:"], 473 "E241": [",;:"], 474 "E242": [",;:"], 475 "E301": [1, 0], 476 "E302": [2, 1], 477 "E303": [3, 2], 478 "E305": [2, 1], 479 "E306": [1, 0], 480 "E307": [3, 1], 481 "E308": [3], 482 "E501": [85, 79], 483 "E711": ["None", "'if cond is None:'"], 484 "E712": ["True", "'if cond is True:' or 'if cond:'"], 485 "E741": ["l"], 486 "E742": ["l"], 487 "E743": ["l"], 488 "E901": ["SyntaxError", "Invalid Syntax"], 489 "E902": ["OSError"], 490} 491 492_pycodestyleWarningMessagesSampleArgs = { 493 "W505": [80, 72], 494 "W605": ["A"], 495} 496 497_fixMessagesSampleArgs = { 498 "FIXWRITE_ERROR": ["OSError"], 499} 500 501messageCatalogs = { 502 "A": _annotationsMessages, 503 "C": _complexityMessages, 504 "D": _docStyleMessages, 505 "E": _pycodestyleErrorMessages, 506 "M": _miscellaneousMessages, 507 "N": _namingStyleMessages, 508 "P": _pathlibMessages, 509 "S": _securityMessages, 510 "W": _pycodestyleWarningMessages, 511 "Y": _simplifyMessages, 512 513 "FIX": _fixMessages, 514} 515 516messageSampleArgsCatalog = { 517 "A": _annotationsMessagesSampleArgs, 518 "C": _complexityMessagesSampleArgs, 519 "D": _docStyleMessagesSampleArgs, 520 "E": _pycodestyleErrorMessagesSampleArgs, 521 "M": _miscellaneousMessagesSampleArgs, 522 "S": _securityMessagesSampleArgs, 523 "W": _pycodestyleWarningMessagesSampleArgs, 524 "Y": _simplifyMessagesSampleArgs, 525 526 "FIX": _fixMessagesSampleArgs, 527} 528 529messageCategoryRe = re.compile(r"([A-Z]{1,3}).+") 530 531 532def getTranslatedMessage(messageCode, messageArgs, example=False): 533 """ 534 Module function to get a translated and formatted message for a 535 given message ID. 536 537 @param messageCode the message code 538 @type str 539 @param messageArgs list of arguments or a single integer value to format 540 the message 541 @type list or int 542 @param example flag indicating a translated message filled with example 543 data is requested (messageArgs is ignored if given) 544 @type bool 545 @return translated and formatted message 546 @rtype str 547 """ 548 match = messageCategoryRe.match(messageCode) 549 if match: 550 # the message code is OK 551 messageCategory = match.group(1) 552 553 if example: 554 try: 555 argsCatalog = messageSampleArgsCatalog[messageCategory] 556 try: 557 args = argsCatalog[messageCode] 558 except KeyError: 559 args = None 560 except KeyError: 561 args = None 562 else: 563 args = messageArgs 564 565 with contextlib.suppress(KeyError): 566 catalog = messageCatalogs[messageCategory] 567 with contextlib.suppress(KeyError): 568 message = catalog[messageCode] 569 if args is None: 570 return message 571 elif isinstance(args, int): 572 # Retranslate with correct plural form 573 return message(args) 574 else: 575 return message.format(*args) 576 577 if example: 578 return None 579 else: 580 return QCoreApplication.translate( 581 "CodeStyleChecker", 582 "No message defined for code '{0}'." 583 ).format(messageCode) 584 585 586def getMessageCodes(): 587 """ 588 Module function to get a list of known message codes. 589 590 @return list of known message codes 591 @rtype set of str 592 """ 593 knownCodes = [] 594 for catalog in messageCatalogs.values(): 595 knownCodes += list(catalog.keys()) 596 return {c.split(".", 1)[0] for c in knownCodes} 597 598# 599# eflag: noqa = M201 600