Repository: hyperskill/hyperstyle (language: python)

Issue:
Change tip for CollapsibleIfStatements
```
        if (index > 0) {
            if (numbers[index - 1] == 3) {
                return true;
            }
        }
```

Current feedback:
```
    {
      "code": "CollapsibleIfStatements",
      "text": "These nested if statements could be combined",
      "line": "if (numbers[index + 1] == 3) {",
      "line_number": 23,
      "column_number": 1,
      "category": "BEST_PRACTICES",
      "influence_on_penalty": 0
    }
```

Change the tip into These nested if statements could be combined by && operator
Change tips
Change hints to be more understandable:

Java: LocalVariableNameCheck. The current message: "Name 'local_interest' must match pattern '^[a-z][a-zA-Z0-9]*$'."

Java: AvoidLiteralsInIfCondition. The current message: ""Avoid using Literals in Conditional Statements"


Discussion / hints:

Fix patch:
diff --git a/src/python/review/inspectors/checkstyle/files/config.xml b/src/python/review/inspectors/checkstyle/files/config.xml
index 00222e43..92fa6f07 100644
--- a/src/python/review/inspectors/checkstyle/files/config.xml
+++ b/src/python/review/inspectors/checkstyle/files/config.xml
@@ -87,16 +87,42 @@
         </module>
         <module name="ConstantName">
             <property name="format" value="^log(ger)?$|^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$"/>
+            <message key="name.invalidPattern"
+                     value="Name ''{0}'' must use UPPER_CASE_SNAKE_CASE (checked pattern ''{1}'')."/>
+        </module>
+        <module name="LambdaParameterName">
+            <message key="name.invalidPattern"
+                     value="Name ''{0}'' must use camelCase (checked pattern ''{1}'')."/>
+        </module>
+        <module name="LocalFinalVariableName">
+            <message key="name.invalidPattern"
+                     value="Name ''{0}'' must use camelCase (checked pattern ''{1}'')."/>
+        </module>
+        <module name="LocalVariableName">
+            <message key="name.invalidPattern"
+                     value="Name ''{0}'' must use camelCase (checked pattern ''{1}'')."/>
+        </module>
+        <module name="MemberName">
+            <message key="name.invalidPattern"
+                     value="Name ''{0}'' must use camelCase (checked pattern ''{1}'')."/>
+        </module>
+        <module name="MethodName">
+            <message key="name.invalidPattern"
+                     value="Name ''{0}'' must use camelCase (checked pattern ''{1}'')."/>
         </module>
-        <module name="LambdaParameterName"/>
-        <module name="LocalFinalVariableName"/>
-        <module name="LocalVariableName"/>
-        <module name="MemberName"/>
-        <module name="MethodName"/>
         <module name="PackageName"/>
-        <module name="ParameterName"/>
-        <module name="StaticVariableName"/>
-        <module name="TypeName"/>
+        <module name="ParameterName">
+            <message key="name.invalidPattern"
+                     value="Name ''{0}'' must use camelCase (checked pattern ''{1}'')."/>
+        </module>
+        <module name="StaticVariableName">
+            <message key="name.invalidPattern"
+                     value="Name ''{0}'' must use camelCase (checked pattern ''{1}'')."/>
+        </module>
+        <module name="TypeName">
+            <message key="name.invalidPattern"
+                     value="Name ''{0}'' must use PascalCase (checked pattern ''{1}'')."/>
+        </module>
 
         <!-- Checks for Size Violations.                    -->
         <!-- See http://checkstyle.sf.net/config_sizes.html -->
diff --git a/src/python/review/inspectors/flake8/.flake8 b/src/python/review/inspectors/flake8/.flake8
index 19edebba..f0452e5a 100644
--- a/src/python/review/inspectors/flake8/.flake8
+++ b/src/python/review/inspectors/flake8/.flake8
@@ -26,11 +26,15 @@ ignore=W291,  # trailing whitespaces
        WPS303, # Forbid underscores in numbers.
        WPS305, # Forbid f strings.
        WPS306, # Forbid writing classes without base classes.
+       WPS317, # Forbid incorrect indentation for parameters. (Because of the unnecessary strictness)
        WPS318, # Forbid extra indentation. TODO: Collision with standard flake8 indentation check
+       WPS319, # Forbid brackets in the wrong position. (Because of the unnecessary strictness)
        WPS323, # Forbid % formatting on strings.
        WPS324, # Enforce consistent return statements. TODO: Collision with flake8-return
        WPS335, # Forbid wrong for loop iter targets.
+       WPS347, # Forbid imports that may cause confusion outside of the module. (controversial)
        WPS358, # Forbid using float zeros: 0.0.
+       WPS359, # Forbids to unpack iterable objects to lists. (Because of its similarity to "WPS414")
        WPS362, # Forbid assignment to a subscript slice.
        # WPS: Best practices
        WPS404, # Forbid complex defaults. TODO: Collision with "B006"
@@ -49,6 +53,7 @@ ignore=W291,  # trailing whitespaces
        P101, # format string does contain unindexed parameters
        P102, # docstring does contain unindexed parameters
        P103, # other string does contain unindexed parameters
+       F405, # Name may be undefined, or defined from star imports (Collision with the stricter "F403")
        F522, # unused named arguments. TODO: Collision with "P302"
        F523, # unused positional arguments. TODO: Collision with "P301"
        F524, # missing argument. TODO: Collision with "P201" and "P202"
diff --git a/src/python/review/inspectors/pmd/files/bin/basic.xml b/src/python/review/inspectors/pmd/files/bin/basic.xml
index 6cacd764..612bbf0e 100644
--- a/src/python/review/inspectors/pmd/files/bin/basic.xml
+++ b/src/python/review/inspectors/pmd/files/bin/basic.xml
@@ -46,29 +46,35 @@
     <rule ref="category/java/codestyle.xml/AvoidProtectedFieldInFinalClass"/>
     <rule ref="category/java/codestyle.xml/AvoidUsingNativeCode"/>
     <rule ref="category/java/codestyle.xml/BooleanGetMethodName"/>
-    <rule ref="category/java/codestyle.xml/ClassNamingConventions">
+    <rule ref="category/java/codestyle.xml/ClassNamingConventions"
+          message="Name ''{1}'' must use PascalCase (checked pattern ''{2}'').">
       <properties>
         <property name="utilityClassPattern" value="[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)?" />
       </properties>
     </rule>
 <!--    <rule ref="category/java/codestyle.xml/ConfusingTernary"/>-->
-    <rule ref="category/java/codestyle.xml/ControlStatementBraces"/>
+    <!-- Disabled due to NeedBracesCheck duplication -->
+    <!-- <rule ref="category/java/codestyle.xml/ControlStatementBraces"/> -->
     <rule ref="category/java/codestyle.xml/DontImportJavaLang"/>
     <rule ref="category/java/codestyle.xml/DuplicateImports"/>
     <rule ref="category/java/codestyle.xml/EmptyMethodInAbstractClassShouldBeAbstract"/>
     <rule ref="category/java/codestyle.xml/ExtendsObject"/>
     <rule ref="category/java/codestyle.xml/FieldDeclarationsShouldBeAtStartOfClass"/>
-    <rule ref="category/java/codestyle.xml/FieldNamingConventions">
+    <rule ref="category/java/codestyle.xml/FieldNamingConventions"
+          message="Fields must be written using camelCase and constants using UPPER_CASE_SNAKE_CASE. (Incorrect name: ''{1}''. Checked pattern: ''{2}'').">
       <properties>
         <property name="exclusions" value="serialVersionUID|serialPersistentFields|log|logger"/>
       </properties>
     </rule>
     <rule ref="category/java/codestyle.xml/ForLoopShouldBeWhileLoop"/>
-    <rule ref="category/java/codestyle.xml/FormalParameterNamingConventions"/>
+    <rule ref="category/java/codestyle.xml/FormalParameterNamingConventions"
+          message="Name ''{1}'' must use camelCase (checked pattern ''{2}'')."/>
     <rule ref="category/java/codestyle.xml/IdenticalCatchBranches"/>
 <!--    <rule ref="category/java/codestyle.xml/LinguisticNaming"/>-->
-    <rule ref="category/java/codestyle.xml/LocalVariableNamingConventions"/>
-    <rule ref="category/java/codestyle.xml/MethodNamingConventions"/>
+    <rule ref="category/java/codestyle.xml/LocalVariableNamingConventions"
+          message="Name ''{1}'' must use camelCase (checked pattern ''{2}'')."/>
+    <rule ref="category/java/codestyle.xml/MethodNamingConventions"
+          message="Name ''{1}'' must use camelCase (checked pattern ''{2}'')."/>
     <rule ref="category/java/codestyle.xml/PackageCase"/>
 <!--    <rule ref="category/java/codestyle.xml/TooManyStaticImports">-->
 <!--      <properties>-->
@@ -90,7 +96,8 @@
     <rule ref="category/java/design.xml/AvoidRethrowingException"/>
     <rule ref="category/java/design.xml/AvoidThrowingNewInstanceOfSameException"/>
     <rule ref="category/java/design.xml/AvoidUncheckedExceptionsInSignatures"/>
-    <rule ref="category/java/design.xml/CollapsibleIfStatements"/>
+    <rule ref="category/java/design.xml/CollapsibleIfStatements"
+          message="These nested if statements could be combined by &amp;&amp; operator."/>
 <!--    <rule ref="category/java/design.xml/CouplingBetweenObjects"/>-->
 <!--    <rule ref="category/java/design.xml/CyclomaticComplexity"/>-->
     <rule ref="category/java/design.xml/DoNotExtendJavaLangError"/>
diff --git a/src/python/review/inspectors/pylint/issue_types.py b/src/python/review/inspectors/pylint/issue_types.py
index edfe8818..374b67a3 100644
--- a/src/python/review/inspectors/pylint/issue_types.py
+++ b/src/python/review/inspectors/pylint/issue_types.py
@@ -8,6 +8,7 @@
 # E errors, for probable bugs in the code
 
 CODE_TO_ISSUE_TYPE: Dict[str, IssueType] = {
+    'C0200': IssueType.BEST_PRACTICES,  # consider using enumerate
     'W0101': IssueType.ERROR_PRONE,  # unreachable code
     'W0102': IssueType.ERROR_PRONE,  # dangerous default value
     'W0104': IssueType.ERROR_PRONE,  # statement doesn't have any effect
diff --git a/src/python/review/inspectors/pylint/pylintrc b/src/python/review/inspectors/pylint/pylintrc
index c435b63b..357ba058 100644
--- a/src/python/review/inspectors/pylint/pylintrc
+++ b/src/python/review/inspectors/pylint/pylintrc
@@ -164,6 +164,8 @@ disable=invalid-name,
         no-else-raise,
         no-else-break,
         no-else-continue,
+        W0614,
+        W0622,
 
 # Enable the message, report, category or checker with the given id(s). You can
 # either give multiple identifier separated by comma (,) or put this option


Test patch:
diff --git a/test/python/inspectors/test_flake8_inspector.py b/test/python/inspectors/test_flake8_inspector.py
index f1ed0958..2a2ebf26 100644
--- a/test/python/inspectors/test_flake8_inspector.py
+++ b/test/python/inspectors/test_flake8_inspector.py
@@ -34,6 +34,8 @@
     ('case33_commas.py', 14),
     ('case34_cohesion.py', 1),
     ('case35_line_break.py', 11),
+    ('case36_unpacking.py', 3),
+    ('case37_wildcard_import.py', 7),
 ]
 
 
@@ -76,6 +78,8 @@ def test_file_with_issues(file_name: str, n_issues: int):
     ('case32_string_format.py', IssuesTestInfo(n_error_prone=28, n_other_complexity=6)),
     ('case33_commas.py', IssuesTestInfo(n_code_style=14, n_cc=4)),
     ('case34_cohesion.py', IssuesTestInfo(n_cc=6, n_cohesion=2)),
+    ('case36_unpacking.py', IssuesTestInfo(n_error_prone=2, n_cc=1, n_other_complexity=1)),
+    ('case37_wildcard_import.py', IssuesTestInfo(n_best_practices=1, n_error_prone=3, n_cc=2, n_other_complexity=2)),
 ]
 
 
diff --git a/test/python/inspectors/test_pmd_inspector.py b/test/python/inspectors/test_pmd_inspector.py
index 393a2d46..15b8006e 100644
--- a/test/python/inspectors/test_pmd_inspector.py
+++ b/test/python/inspectors/test_pmd_inspector.py
@@ -15,7 +15,7 @@
     ('test_comparing_strings.java', 3),
     ('test_constants.java', 4),
     ('test_covariant_equals.java', 1),
-    ('test_curly_braces.java', 2),
+    ('test_curly_braces.java', 0),
     ('test_double_checked_locking.java', 2),
     ('test_for_loop.java', 2),
     ('test_implementation_types.java', 0),
diff --git a/test/python/inspectors/test_pylint_inspector.py b/test/python/inspectors/test_pylint_inspector.py
index ba4be12f..fc381234 100644
--- a/test/python/inspectors/test_pylint_inspector.py
+++ b/test/python/inspectors/test_pylint_inspector.py
@@ -11,7 +11,7 @@
     ('case0_spaces.py', 0),
     ('case1_simple_valid_program.py', 0),
     ('case2_boolean_expressions.py', 3),
-    ('case3_redefining_builtin.py', 2),
+    ('case3_redefining_builtin.py', 0),
     ('case4_naming.py', 3),
     ('case5_returns.py', 1),
     ('case6_unused_variables.py', 4),
@@ -32,6 +32,8 @@
     ('case25_django.py', 0),
     ('case27_using_requests.py', 0),
     ('case30_allow_else_return.py', 0),
+    ('case36_unpacking.py', 0),
+    ('case37_wildcard_import.py', 1),
 ]
 
 
diff --git a/test/resources/inspectors/python/case36_unpacking.py b/test/resources/inspectors/python/case36_unpacking.py
new file mode 100644
index 00000000..74b4ec9c
--- /dev/null
+++ b/test/resources/inspectors/python/case36_unpacking.py
@@ -0,0 +1,10 @@
+[a, b, c], [x, y, z] = (sorted(map(int, input().split())) for _ in 'lm')
+if [a, b, c] == [x, y, z]:
+    a = "Boxes are equal"
+elif a <= x and b <= y and c <= z:
+    a = "The first box is smaller than the second one"
+elif a >= x and b >= y and c >= z:
+    a = "The first box is larger than the second one"
+else:
+    a = "Boxes are incomparable"
+print(a)
diff --git a/test/resources/inspectors/python/case37_wildcard_import.py b/test/resources/inspectors/python/case37_wildcard_import.py
new file mode 100644
index 00000000..ed12a4b1
--- /dev/null
+++ b/test/resources/inspectors/python/case37_wildcard_import.py
@@ -0,0 +1,33 @@
+from numpy import *
+
+n, m = [int(_) for _ in input().split()]
+mat = zeros((n, m))
+s = 1
+for j in range(n):
+    for i in range(j, m - j):
+        if s > n * m:
+            break
+        mat[j][i] = s
+        s += 1
+
+    for i in range(j - n + 1, -j):
+        if s > n * m:
+            break
+        mat[i][-j - 1] = s
+        s += 1
+    for i in range(-j - 2, -m + j - 1, -1):
+        if s > n * m:
+            break
+        mat[-j - 1][i] = s
+        s += 1
+
+    for i in range(-2 - j, -n + j, -1):
+        if s > n * m:
+            break
+        mat[i][j] = s
+        s += 1
+
+for r in range(n):
+    for c in range(m):
+        print(str(int(mat[r][c])).ljust(2), end=' ')
+    print()