prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  WPS472 only detecting one pure variable assignment
  ### What's wrong
  
  WPS472 detects `name, *_ = get_address()`. 
  When it comes to slightly more complex value assignments, it does not work:
  1. `names[0], *_ = get_address()` 
  2. `self.name, *_ = get_address()`
  3. `(name, street), *_ = get_address()`
  
  Also when extracting a second (or more values) the detection fails:
  1. `name, street, *_ = get_address()`
  2. `name, _, city, *_ = get_address()`
  3. `name, _, self.city, *_ = get_address()`
  
  ### How it should be
  
  It would be nice if all of the examples would also be detected as WPS472 violations.
  
  ### Flake8 version and plugins
  
  {
    "dependencies": [],
    "platform": {
      "python_implementation": "CPython",
      "python_version": "3.9.6",
      "system": "Darwin"
    },
    "plugins": [
      {
        "is_local": false,
        "plugin": "flake8-bandit",
        "version": "2.1.2"
      },
      {
        "is_local": false,
        "plugin": "flake8-broken-line",
        "version": "0.3.0"
      },
      {
        "is_local": false,
        "plugin": "flake8-bugbear",
        "version": "20.11.1"
      },
      {
        "is_local": false,
        "plugin": "flake8-comprehensions",
        "version": "3.4.0"
      },
      {
        "is_local": false,
        "plugin": "flake8-darglint",
        "version": "1.8.0"
      },
      {
        "is_local": false,
        "plugin": "flake8-debugger",
        "version": "4.0.0"
      },
      {
        "is_local": false,
        "plugin": "flake8-docstrings",
        "version": "1.6.0, pydocstyle: 6.0.0"
      },
      {
        "is_local": false,
        "plugin": "flake8-eradicate",
        "version": "1.0.0"
      },
      {
        "is_local": false,
        "plugin": "flake8-string-format",
        "version": "0.3.0"
      },
      {
        "is_local": false,
        "plugin": "flake8.datetimez",
        "version": "20.10.0"
      },
      {
        "is_local": false,
        "plugin": "flake8_commas",
        "version": "2.0.0"
      },
      {
        "is_local": false,
        "plugin": "flake8_isort",
        "version": "4.0.0"
      },
      {
        "is_local": false,
        "plugin": "flake8_quotes",
        "version": "3.2.0"
      },
      {
        "is_local": false,
        "plugin": "mccabe",
        "version": "0.6.1"
      },
      {
        "is_local": false,
        "plugin": "naming",
        "version": "0.11.1"
      },
      {
        "is_local": false,
        "plugin": "pycodestyle",
        "version": "2.7.0"
      },
      {
        "is_local": false,
        "plugin": "pyflakes",
        "version": "2.3.0"
      },
      {
        "is_local": false,
        "plugin": "rst-docstrings",
        "version": "0.2.3"
      },
      {
        "is_local": false,
        "plugin": "wemake_python_styleguide",
        "version": "0.16.0"
      }
    ],
    "version": "3.9.2"
  }
  
  ### pip information
  
  pip 21.3.1
  
  ### OS information
  
  macOS Monterey
  Version 12.0.1
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `wemake_python_styleguide/logic/tree/variables.py`
  Content:
  ```
  1 import ast
  2 from typing import List, Union
  3 
  4 from wemake_python_styleguide.logic import nodes
  5 from wemake_python_styleguide.logic.naming import access
  6 
  7 _VarDefinition = Union[ast.AST, ast.expr]
  8 _LocalVariable = Union[ast.Name, ast.ExceptHandler]
  9 
  10 
  11 def get_variable_name(node: _LocalVariable) -> str:
  12     """Used to get variable names from all definitions."""
  13     if isinstance(node, ast.Name):
  14         return node.id
  15     return getattr(node, 'name', '')
  16 
  17 
  18 def does_shadow_builtin(node: ast.AST) -> bool:
  19     """
  20     We allow attributes and class-level builtin overrides.
  21 
  22     Like: ``self.list = []`` or ``def map(self, function):``
  23 
  24     Why?
  25     Because they cannot harm you since they do not shadow the real builtin.
  26     """
  27     return (
  28         not isinstance(node, ast.Attribute) and
  29         not isinstance(nodes.get_context(node), ast.ClassDef)
  30     )
  31 
  32 
  33 def is_valid_block_variable_definition(node: _VarDefinition) -> bool:
  34     """Is used to check either block variables are correctly defined."""
  35     if isinstance(node, ast.Tuple):
  36         return all(
  37             is_valid_block_variable_definition(var_definition)
  38             for var_definition in node.elts
  39         )
  40     return _is_valid_single(node)
  41 
  42 
  43 def is_valid_unpacking_target(target: ast.expr) -> bool:
  44     """Checks if unpacking target is correct."""
  45     if isinstance(target, ast.Tuple):
  46         return all(
  47             _is_valid_single(element)
  48             for element in target.elts
  49         )
  50     return _is_valid_single(target)
  51 
  52 
  53 def _is_valid_single(node: _VarDefinition) -> bool:
  54     return (
  55         isinstance(node, ast.Name) or
  56         isinstance(node, ast.Starred) and isinstance(node.value, ast.Name)
  57     )
  58 
  59 
  60 def is_getting_element_by_unpacking(targets: List[ast.expr]) -> bool:
  61     """Checks if unpacking targets used to get first or last element."""
  62     if len(targets) != 2:
  63         return False
  64     first_item = (
  65         isinstance(targets[0], ast.Name) and
  66         isinstance(targets[1], ast.Starred) and
  67         _is_unused_variable_name(targets[1].value)
  68     )
  69     last_item = (
  70         isinstance(targets[1], ast.Name) and
  71         isinstance(targets[0], ast.Starred) and
  72         _is_unused_variable_name(targets[0].value)
  73     )
  74     return first_item or last_item
  75 
  76 
  77 def _is_unused_variable_name(node: ast.expr) -> bool:
  78     return isinstance(node, ast.Name) and access.looks_like_unused(node.id)
  79
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/wemake_python_styleguide/logic/tree/variables.py b/wemake_python_styleguide/logic/tree/variables.py
  --- a/wemake_python_styleguide/logic/tree/variables.py
  +++ b/wemake_python_styleguide/logic/tree/variables.py
  @@ -62,12 +62,10 @@
       if len(targets) != 2:
           return False
       first_item = (
  -        isinstance(targets[0], ast.Name) and
           isinstance(targets[1], ast.Starred) and
           _is_unused_variable_name(targets[1].value)
       )
       last_item = (
  -        isinstance(targets[1], ast.Name) and
           isinstance(targets[0], ast.Starred) and
           _is_unused_variable_name(targets[0].value)
       )
  
verification_info: {"golden_diff": "diff --git a/wemake_python_styleguide/logic/tree/variables.py b/wemake_python_styleguide/logic/tree/variables.py\n--- a/wemake_python_styleguide/logic/tree/variables.py\n+++ b/wemake_python_styleguide/logic/tree/variables.py\n@@ -62,12 +62,10 @@\n     if len(targets) != 2:\n         return False\n     first_item = (\n-        isinstance(targets[0], ast.Name) and\n         isinstance(targets[1], ast.Starred) and\n         _is_unused_variable_name(targets[1].value)\n     )\n     last_item = (\n-        isinstance(targets[1], ast.Name) and\n         isinstance(targets[0], ast.Starred) and\n         _is_unused_variable_name(targets[0].value)\n     )\n", "issue": "WPS472 only detecting one pure variable assignment\n### What's wrong\r\n\r\nWPS472 detects `name, *_ = get_address()`. \r\nWhen it comes to slightly more complex value assignments, it does not work:\r\n1. `names[0], *_ = get_address()` \r\n2. `self.name, *_ = get_address()`\r\n3. `(name, street), *_ = get_address()`\r\n\r\nAlso when extracting a second (or more values) the detection fails:\r\n1. `name, street, *_ = get_address()`\r\n2. `name, _, city, *_ = get_address()`\r\n3. `name, _, self.city, *_ = get_address()`\r\n\r\n### How it should be\r\n\r\nIt would be nice if all of the examples would also be detected as WPS472 violations.\r\n\r\n### Flake8 version and plugins\r\n\r\n{\r\n  \"dependencies\": [],\r\n  \"platform\": {\r\n    \"python_implementation\": \"CPython\",\r\n    \"python_version\": \"3.9.6\",\r\n    \"system\": \"Darwin\"\r\n  },\r\n  \"plugins\": [\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8-bandit\",\r\n      \"version\": \"2.1.2\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8-broken-line\",\r\n      \"version\": \"0.3.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8-bugbear\",\r\n      \"version\": \"20.11.1\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8-comprehensions\",\r\n      \"version\": \"3.4.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8-darglint\",\r\n      \"version\": \"1.8.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8-debugger\",\r\n      \"version\": \"4.0.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8-docstrings\",\r\n      \"version\": \"1.6.0, pydocstyle: 6.0.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8-eradicate\",\r\n      \"version\": \"1.0.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8-string-format\",\r\n      \"version\": \"0.3.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8.datetimez\",\r\n      \"version\": \"20.10.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8_commas\",\r\n      \"version\": \"2.0.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8_isort\",\r\n      \"version\": \"4.0.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"flake8_quotes\",\r\n      \"version\": \"3.2.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"mccabe\",\r\n      \"version\": \"0.6.1\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"naming\",\r\n      \"version\": \"0.11.1\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"pycodestyle\",\r\n      \"version\": \"2.7.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"pyflakes\",\r\n      \"version\": \"2.3.0\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"rst-docstrings\",\r\n      \"version\": \"0.2.3\"\r\n    },\r\n    {\r\n      \"is_local\": false,\r\n      \"plugin\": \"wemake_python_styleguide\",\r\n      \"version\": \"0.16.0\"\r\n    }\r\n  ],\r\n  \"version\": \"3.9.2\"\r\n}\r\n\r\n### pip information\r\n\r\npip 21.3.1\r\n\r\n### OS information\r\n\r\nmacOS Monterey\r\nVersion 12.0.1\n", "before_files": [{"content": "import ast\nfrom typing import List, Union\n\nfrom wemake_python_styleguide.logic import nodes\nfrom wemake_python_styleguide.logic.naming import access\n\n_VarDefinition = Union[ast.AST, ast.expr]\n_LocalVariable = Union[ast.Name, ast.ExceptHandler]\n\n\ndef get_variable_name(node: _LocalVariable) -> str:\n    \"\"\"Used to get variable names from all definitions.\"\"\"\n    if isinstance(node, ast.Name):\n        return node.id\n    return getattr(node, 'name', '')\n\n\ndef does_shadow_builtin(node: ast.AST) -> bool:\n    \"\"\"\n    We allow attributes and class-level builtin overrides.\n\n    Like: ``self.list = []`` or ``def map(self, function):``\n\n    Why?\n    Because they cannot harm you since they do not shadow the real builtin.\n    \"\"\"\n    return (\n        not isinstance(node, ast.Attribute) and\n        not isinstance(nodes.get_context(node), ast.ClassDef)\n    )\n\n\ndef is_valid_block_variable_definition(node: _VarDefinition) -> bool:\n    \"\"\"Is used to check either block variables are correctly defined.\"\"\"\n    if isinstance(node, ast.Tuple):\n        return all(\n            is_valid_block_variable_definition(var_definition)\n            for var_definition in node.elts\n        )\n    return _is_valid_single(node)\n\n\ndef is_valid_unpacking_target(target: ast.expr) -> bool:\n    \"\"\"Checks if unpacking target is correct.\"\"\"\n    if isinstance(target, ast.Tuple):\n        return all(\n            _is_valid_single(element)\n            for element in target.elts\n        )\n    return _is_valid_single(target)\n\n\ndef _is_valid_single(node: _VarDefinition) -> bool:\n    return (\n        isinstance(node, ast.Name) or\n        isinstance(node, ast.Starred) and isinstance(node.value, ast.Name)\n    )\n\n\ndef is_getting_element_by_unpacking(targets: List[ast.expr]) -> bool:\n    \"\"\"Checks if unpacking targets used to get first or last element.\"\"\"\n    if len(targets) != 2:\n        return False\n    first_item = (\n        isinstance(targets[0], ast.Name) and\n        isinstance(targets[1], ast.Starred) and\n        _is_unused_variable_name(targets[1].value)\n    )\n    last_item = (\n        isinstance(targets[1], ast.Name) and\n        isinstance(targets[0], ast.Starred) and\n        _is_unused_variable_name(targets[0].value)\n    )\n    return first_item or last_item\n\n\ndef _is_unused_variable_name(node: ast.expr) -> bool:\n    return isinstance(node, ast.Name) and access.looks_like_unused(node.id)\n", "path": "wemake_python_styleguide/logic/tree/variables.py"}], "after_files": [{"content": "import ast\nfrom typing import List, Union\n\nfrom wemake_python_styleguide.logic import nodes\nfrom wemake_python_styleguide.logic.naming import access\n\n_VarDefinition = Union[ast.AST, ast.expr]\n_LocalVariable = Union[ast.Name, ast.ExceptHandler]\n\n\ndef get_variable_name(node: _LocalVariable) -> str:\n    \"\"\"Used to get variable names from all definitions.\"\"\"\n    if isinstance(node, ast.Name):\n        return node.id\n    return getattr(node, 'name', '')\n\n\ndef does_shadow_builtin(node: ast.AST) -> bool:\n    \"\"\"\n    We allow attributes and class-level builtin overrides.\n\n    Like: ``self.list = []`` or ``def map(self, function):``\n\n    Why?\n    Because they cannot harm you since they do not shadow the real builtin.\n    \"\"\"\n    return (\n        not isinstance(node, ast.Attribute) and\n        not isinstance(nodes.get_context(node), ast.ClassDef)\n    )\n\n\ndef is_valid_block_variable_definition(node: _VarDefinition) -> bool:\n    \"\"\"Is used to check either block variables are correctly defined.\"\"\"\n    if isinstance(node, ast.Tuple):\n        return all(\n            is_valid_block_variable_definition(var_definition)\n            for var_definition in node.elts\n        )\n    return _is_valid_single(node)\n\n\ndef is_valid_unpacking_target(target: ast.expr) -> bool:\n    \"\"\"Checks if unpacking target is correct.\"\"\"\n    if isinstance(target, ast.Tuple):\n        return all(\n            _is_valid_single(element)\n            for element in target.elts\n        )\n    return _is_valid_single(target)\n\n\ndef _is_valid_single(node: _VarDefinition) -> bool:\n    return (\n        isinstance(node, ast.Name) or\n        isinstance(node, ast.Starred) and isinstance(node.value, ast.Name)\n    )\n\n\ndef is_getting_element_by_unpacking(targets: List[ast.expr]) -> bool:\n    \"\"\"Checks if unpacking targets used to get first or last element.\"\"\"\n    if len(targets) != 2:\n        return False\n    first_item = (\n        isinstance(targets[1], ast.Starred) and\n        _is_unused_variable_name(targets[1].value)\n    )\n    last_item = (\n        isinstance(targets[0], ast.Starred) and\n        _is_unused_variable_name(targets[0].value)\n    )\n    return first_item or last_item\n\n\ndef _is_unused_variable_name(node: ast.expr) -> bool:\n    return isinstance(node, ast.Name) and access.looks_like_unused(node.id)\n", "path": "wemake_python_styleguide/logic/tree/variables.py"}]}