You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
glob patterns should not be overriden by specific --per-file-ignores rules #670
Say we want to ignore D102 errors in all files within the tests directory. We can add a rule for each file individually, but it would be more efficient if we could do that just by adding tests/* : N813 to the config file (similar to the way flake8-per-file-ignores plugin works on flake8<3.7.0). see the comments below
changed title from {-Allow glob patterns in paths of --per-file-ignor-}es to {+glob patterns should not be overriden by specific --per-file-ignores rul+}es
@oseiberts11 so to be clear, it sounds like what you expect to happen is that
machinedb/**/*.py: D101, D102, D103
To ignore those three errors in every file matching that glob and then you seem to want to extend the list of ignores for those files for specific files, e.g., machinedb/models/inventory with the errors specified for each of those files. Am I understanding you correctly?
Exactly. That is how it seemed to work with the plugin. (I didn't write the configuration myself, I just noticed that behaviour seems to have changed).
Right, the plugin took a different tact, honestly, that would be harder to replicate here. Basically, it iterated through everything for matches and applied all of them. We could do that, but then we're favoring exact backwards compatibility (which wasn't ever the goal) over simplicity. It would also mean that we're iterative over a list every time rather than thinking through things more simply, and it makes debugging the option harder in the future, i.e., we always prefer the most specific rule there even if multiple might match.
I see a potential solution for people who do want exact backwards compatibility. Maybe you could make it so that if the flake8-per-file-ignores plugin is selected, then the built-in functionality is disabled, and the plugin is used instead. Probably with a warning of some sort which points out that the plugin has mostly but not exactly the same functionality. Then people who are upgrading automatically and unknowingly depend on some old behaviour (I was in that situation) are not affected by any change. When they are actively changing the config for the new situation, they will notice the change, but that is a much better time for it because they are actively fixing things anyway.
I realise that this is pretty much the opposite of how the plugin is handled now, but does that sound doable?
For this example with only 2 lines, that would work well enough. But in practice I have several patterns, and several files with additional ignores.
From what I've seen above, I understand that the way you want it, is to select a single line, without scanning several or all of them. I fear that in the general case this isn't possible. If there are several wildard patterns that match a particular file name, which one are you going to choose? Why?
And in the general case, you cannot just point to "the best pattern" without examining several of them. To give a simple example, with patterns like
and file names like a/b/c/d, a/x/c/d, a/b/x/d, the names will match multiple patterns, and/or they will have different "best" patterns. You cannot (in an obviously understandable way) say ahead of time which pattern is "best". Even if you manage to create a total ordering, for many potential file names you will need to try several patterns anyway until you find a match.
Since trying to explain to a user how this works is too complicated (and I'm not even talking about implementing it), just scanning all patterns and applying all matches is much easer to understand, and much easier to implement.
(There seems to be a bug in the implementation already, viz. that the machinedb/**/*.py pattern didn't seem to match any files at all for me. So I'm pessimistic about more complex cases.)
If we wanted to throw people under the bus and give them a foot-gun at the same time, we could pretty easily just apply every thing, but then things they didn't intend to match end up hiding problems from them they didn't want. This is precisely why I had no original intention to support globbing. It introduces far too much unnecessary complexity and no one will be happy no matter how it's implemented.
First let's document this, to help save the next developer a day lost to learning what to expect. Here's a draft, please comment:
(In --per-file-ignores):
If multiple patterns match a given file, a single pattern is chosen and the ignores from just that rule are applied to the file. The pattern chosen is the alphabetically last pattern which matches the file. This is often the most specific pattern that matched.
so in any unit test files I want to disable E241, and in any models I want to disable N805 (due to sqlalchemy hybrid property expression classmethods). Guess where one of the tests that need E241 disabled is...
If multiple patterns match a given file, a single pattern is chosen and the ignores from just that rule are applied to the file. The pattern chosen is the alphabetically last pattern which matches the file. This is often the most specific pattern that matched.
I'd also like to see this #670 (comment) too in the documentation:
Also regarding the ** glob -- that's because flake8 uses fnmatch globs and not glob globs, so you'd want just machinedb/*.py
I didn't loose a day, but a good two hours for sure. Especially given that the first result in per-file-ignores is https://pypi.org/project/flake8-per-file-ignores/ (which paints a different image).
Activity
asottile commentedon Apr 3, 2021
In GitLab by @asottile on Jan 30, 2019, 07:30
It already works for me (?) do you have a particular repository this isn't working in?
asottile commentedon Apr 3, 2021
In GitLab by @qxv0 on Jan 30, 2019, 08:05
I checked and it seems to me that the problem occurs only in those files which also have another specific ignore rule.
For example if I have both
tests/*: X1andtests/a.py:Y2, then onlyY2errors are ignored ontests/a.py, butX1errors show up which is unexpected.asottile commentedon Apr 3, 2021
In GitLab by @qxv0 on Jan 30, 2019, 08:08
changed title from {-Allow glob patterns in paths of --per-file-ignor-}es to {+glob patterns should not be overriden by specific --per-file-ignores rul+}es
asottile commentedon Apr 3, 2021
In GitLab by @qxv0 on Jan 30, 2019, 08:08
changed the description
asottile commentedon Apr 3, 2021
In GitLab by @asottile on Jan 30, 2019, 08:16
hmmm so the way it's implemented is the first rule that matches a filename is used. In your case you can write:
asottile commentedon Apr 3, 2021
In GitLab by @oseiberts11 on Feb 6, 2019, 02:12
I seem to have a similar problem (3.7.5). In my per-file-ignores I have (among other things but in this order):
First of all, this particular glob pattern doesn't seem to work any more.
Even if I expand this to
then I still get D* errors for sshca.py:
Copying
D101, D102, D103to all the more specific patterns is of course not very nice.Additionally the glob
machinedb/**/*.pyis no longer working.asottile commentedon Apr 3, 2021
In GitLab by @sigmavirus24 on Feb 6, 2019, 04:57
@oseiberts11 so to be clear, it sounds like what you expect to happen is that
To ignore those three errors in every file matching that glob and then you seem to want to extend the list of ignores for those files for specific files, e.g.,
machinedb/models/inventorywith the errors specified for each of those files. Am I understanding you correctly?asottile commentedon Apr 3, 2021
In GitLab by @oseiberts11 on Feb 6, 2019, 07:26
Exactly. That is how it seemed to work with the plugin. (I didn't write the configuration myself, I just noticed that behaviour seems to have changed).
asottile commentedon Apr 3, 2021
In GitLab by @sigmavirus24 on Feb 6, 2019, 17:26
Right, the plugin took a different tact, honestly, that would be harder to replicate here. Basically, it iterated through everything for matches and applied all of them. We could do that, but then we're favoring exact backwards compatibility (which wasn't ever the goal) over simplicity. It would also mean that we're iterative over a list every time rather than thinking through things more simply, and it makes debugging the option harder in the future, i.e., we always prefer the most specific rule there even if multiple might match.
asottile commentedon Apr 3, 2021
In GitLab by @oseiberts11 on Feb 7, 2019, 01:11
I suspected something like that.
I see a potential solution for people who do want exact backwards compatibility. Maybe you could make it so that if the
flake8-per-file-ignoresplugin is selected, then the built-in functionality is disabled, and the plugin is used instead. Probably with a warning of some sort which points out that the plugin has mostly but not exactly the same functionality. Then people who are upgrading automatically and unknowingly depend on some old behaviour (I was in that situation) are not affected by any change. When they are actively changing the config for the new situation, they will notice the change, but that is a much better time for it because they are actively fixing things anyway.I realise that this is pretty much the opposite of how the plugin is handled now, but does that sound doable?
asottile commentedon Apr 3, 2021
In GitLab by @sigmavirus24 on Feb 9, 2019, 05:46
The plugin's page says it's deprecated, I'd rather not encourage folks to use bit-rotting software. Is it too arduous to
asottile commentedon Apr 3, 2021
In GitLab by @oseiberts11 on Feb 15, 2019, 02:57
For this example with only 2 lines, that would work well enough. But in practice I have several patterns, and several files with additional ignores.
From what I've seen above, I understand that the way you want it, is to select a single line, without scanning several or all of them. I fear that in the general case this isn't possible. If there are several wildard patterns that match a particular file name, which one are you going to choose? Why?
And in the general case, you cannot just point to "the best pattern" without examining several of them. To give a simple example, with patterns like
and file names like
a/b/c/d,a/x/c/d,a/b/x/d, the names will match multiple patterns, and/or they will have different "best" patterns. You cannot (in an obviously understandable way) say ahead of time which pattern is "best". Even if you manage to create a total ordering, for many potential file names you will need to try several patterns anyway until you find a match.Since trying to explain to a user how this works is too complicated (and I'm not even talking about implementing it), just scanning all patterns and applying all matches is much easer to understand, and much easier to implement.
(There seems to be a bug in the implementation already, viz. that the
machinedb/**/*.pypattern didn't seem to match any files at all for me. So I'm pessimistic about more complex cases.)asottile commentedon Apr 3, 2021
In GitLab by @asottile on Feb 15, 2019, 03:48
I don't think it's hard to explain, the first matching pattern wins right?
asottile commentedon Apr 3, 2021
In GitLab by @asottile on Feb 15, 2019, 03:57
Also regarding the
**glob -- that's because flake8 usesfnmatchglobs and notglobglobs, so you'd want justmachinedb/*.pyasottile commentedon Apr 3, 2021
In GitLab by @sigmavirus24 on Feb 15, 2019, 04:15
It's the last match sorted alphabetically
https://gitlab.com/pycqa/flake8/blob/dc7b082b96751c8ef7bfc616f8701d432afa7ef7/src/flake8/style_guide.py#L369-374
So it's always consistent and reproducible.
If we wanted to throw people under the bus and give them a foot-gun at the same time, we could pretty easily just apply every thing, but then things they didn't intend to match end up hiding problems from them they didn't want. This is precisely why I had no original intention to support globbing. It introduces far too much unnecessary complexity and no one will be happy no matter how it's implemented.
asottile commentedon Apr 3, 2021
In GitLab by @bob.hyman on May 2, 2020, 16:34
First let's document this, to help save the next developer a day lost to learning what to expect. Here's a draft, please comment:
(In --per-file-ignores):
Is this correct?
Disable warnings related to the use of assert in the tests directory …
Disable warnings related to the use of assert in the tests directory …
ThiefMaster commentedon Mar 29, 2023
I'd really like to see merging of the excludes from multiple patterns that match.
Currently I have this:
so in any unit test files I want to disable E241, and in any models I want to disable N805 (due to sqlalchemy hybrid property expression classmethods). Guess where one of the tests that need E241 disabled is...
stdedos commentedon Aug 23, 2023
Quoting from #670 (comment):
I'd also like to see this #670 (comment) too in the documentation:
I didn't loose a day, but a good two hours for sure. Especially given that the first result in
per-file-ignoresis https://pypi.org/project/flake8-per-file-ignores/ (which paints a different image).