wemake-python-styleguide icon indicating copy to clipboard operation
wemake-python-styleguide copied to clipboard

WPS335 rejects list-of-lists comprehensions

Open astynax opened this issue 3 years ago • 11 comments

What's wrong

I'm trying to produce a list of lists but getting a false-positive warning:

WPS335 Found incorrect `for` loop iter type
 ([x] for x in (1, 2, 3))
 ^

Here is a code

[ l for l in
  ([x] for x in (1, 2, 3))
]

How it should be

It should be possible to produce the list of lists.

Flake8 version and plugins

{
  "dependencies": [],
  "platform": {
    "python_implementation": "CPython",
    "python_version": "3.8.8",
    "system": "Linux"
  },
  "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.5.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_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.1"
    },
    {
      "is_local": false,
      "plugin": "rst-docstrings",
      "version": "0.0.14"
    },
    {
      "is_local": false,
      "plugin": "wemake_python_styleguide",
      "version": "0.15.2"
    }
  ],
  "version": "3.9.2"
}

pip information

pip 20.2.3 from /home/astynax/Projects/hexlet/hexlet-exercise-kit/exercises/course-python-declarative-programming/python_declarative_programming_list_comprehensions_exercise/.venv/lib/python3.8/site-packages/pip (python 3.8) astor==0.8.1 attrs==21.2.0 bandit==1.7.0 darglint==1.8.0 docutils==0.17.1 eradicate==2.0.0 flake8==3.9.2 flake8-bandit==2.1.2 flake8-broken-line==0.3.0 flake8-bugbear==20.11.1 flake8-commas==2.0.0 flake8-comprehensions==3.5.0 flake8-debugger==4.0.0 flake8-docstrings==1.6.0 flake8-eradicate==1.0.0 flake8-isort==4.0.0 flake8-polyfill==1.0.2 flake8-quotes==3.2.0 flake8-rst-docstrings==0.0.14 flake8-string-format==0.3.0 gitdb==4.0.7 GitPython==3.1.14 isort==5.8.0 mccabe==0.6.1 pbr==5.6.0 pep8-naming==0.11.1 pycodestyle==2.7.0 pydocstyle==6.0.0 pyflakes==2.3.1 Pygments==2.9.0 PyYAML==5.4.1 restructuredtext-lint==1.3.2 six==1.16.0 smmap==4.0.0 snowballstemmer==2.1.0 stevedore==3.3.0 testfixtures==6.17.1 typing-extensions==3.10.0.0 wemake-python-styleguide==0.15.2

OS information

Ubuntu Linux 16.04

astynax avatar May 12 '21 09:05 astynax

Yes, this should be allowed for comprehensions.

sobolevn avatar May 12 '21 09:05 sobolevn

Hello, I am a beginner in the Open source world and I found this issue to be good first so I would like to take this issue. So please guide me.

ujju20 avatar May 18 '21 17:05 ujju20

@ujju20 let's focus on https://github.com/wemake-services/wemake-python-styleguide/issues/1825 🙂

sobolevn avatar May 18 '21 19:05 sobolevn

I am looking through the bug reports and now I thing that this is one is invaldid. Your initial example should be written as:

>>> list([x] for x in (1, 2, 3))
[[1], [2], [3]]

Maybe you have other examples in mind?

sobolevn avatar Jun 17 '21 08:06 sobolevn

O, rly? This is just a minimal example! And why it's invalid? One may want to iterate from the subcomprehension! Here is a real example if you want:

def non_empty_truths(list_of_lists):
    return [
        truths for truths in
        ([elem for elem in one_list if elem]  # noqa: WPS335
         for one_list in list_of_lists
         )
        if truths
    ]

And here should be the lists! Not tuples, not genexps, the lists!

astynax avatar Jun 17 '21 11:06 astynax

Doesn't this create an extra generator?

# Same a above but rewritten on less lines
[
    truths
    for truths in ([elem for elem in one_list if elem] for one_list in list_of_lists)
    if truths
]

In many contexts generators are /slow/. In some they're only a little slower than a list, but in others (like when you need length) they're way slower. I'd argue that replacing the generator with a list is also valid.

[
    truths
    for truths in [[elem for elem in one_list if elem] for one_list in list_of_lists]
    if truths
]

You /can/ break this out into two steps and the linter is happy with it. I don't know. seems a bit excessive.

step_one = [[elem for elem in one_list if elem] for one_list in list_of_lists]
[truths for truths in step_one if truths]

Sxderp avatar Sep 30 '21 16:09 Sxderp

Hi there, I'm a newbie searching for an easy-to-solve issue this seems to be a good start for me. If this is still open, please guide me on this

surya-kodeti avatar Jul 11 '22 11:07 surya-kodeti

I support answer by @Sxderp. You dont need an iterator in this case. In the initial example, the example you provided can be simplifies as: list_of_list = [[x] for x in (1, 2, 3)]

kameshwarasekar avatar Jan 28 '24 01:01 kameshwarasekar

Hi, I am new to contributing, Can I take this task up?

CodeCraftsman481 avatar Apr 01 '24 10:04 CodeCraftsman481