-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Better user experience when starting to use pylint on legacy codebase #5403
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I don't know what Qodana and basedmypy are (and could not quite understand from a 1-minute read). What do you mean by "baseline functionality"? Are you interested in a pylint configuration file that would be minimal and hence report less warnings, at least to let you introduce pylint progressively in your code base? I think that it's the best way to introduce pylint on any sizeable project. However, the checkers that you would enable in this basic, limited configuration are going to depend on your style, really. I am not sure that all contributors of Pylint use the same configuration file in their projects and could settle on such a "minimal" configuration. (It also depends on other overlapping tools that may be in use, such as I would suggest picking up a pylint configuration file from an existing project (for example this file from pylint itself) and run pylint. If the output is overwhelming (and it's likely to be!), add checkers to the "disable=" list. Rinse and repeat until you have a reasonable amount of warnings. Fix your code, and then enable back checkers you're interested in, one by one. Fix your code, enable more checkers, fix your code again, and so on, until you have enabled all checkers and disabled only the ones you're really not interested in. |
@dbaty Thanks for the response! Basically baseline saves the output of a run to a file and that file is committed as part of the project, when the tool is run again the errors are matched against the baseline and filtered out of the report. test.py: 1
In my opinion, baseline is the best way to adopt strictness incrementally, because it basically means that the inspections will only apply to new/updated code and not spam you with countless noise. |
How sensitive should this be? We could use We could ignore line numbers in the diff, which would not raise baseline errors as long as they are in the same relative order. Is this a good general approach or is there an existing pylint feature we could leverage? |
There is a way to generate expected pylint output for a python file in the functional tests (ex here: the couple Code reference: |
Since this involves storing detailed results between runs, could we also store a hash of linted files and not rerun pylint on files that have not changed? Or skip all the checkers that do not look at imports. |
It's a good idea but we'd need first to separate between checkers that are dependents on other files and those who do not. For example |
There is a tool called Personally, I prefer my own tool |
https://github.com/mbarkhau/pylint-ignore seems like a very well polished solution to this problem. I opened an issue to discuss it with its maintainer : mbarkhau/pylint-ignore#13 |
Clearly this is a common and annoying problem! Everybody has their own way of coping with it I guess. My approach is the gather a list of all the warnings that are emitted and disable all of them in the config file. Then I can go through and enable (by cutting the disable) the warnings one by one. So what I would personally like is an option to run Pylint and get back a list of all the warnings that would be emitted, rather than a list of every instance of every warning as is normally the case. |
@nickdrozd how about output a generated config file that disables all of the currently existing warnings. |
@KotlinIsland That would work great for my use case at least! |
Building on both suggestions, "looks like to me" that ...
disable=
docstring-first-line-empty, # C0199 - 2 instances
too-many-try-statements, # A1234 - 45 instances
.... the output would look like that? |
Let's not forget that pylint-ignore exists. The creator think that long term it should be a pylint feature. It seems an enormous design work was already done about this problem. Imo the solution is simply to integrate it in pylint after fixing the major problem we find in it (or at first document it or add the tool directly in pylint without real integration). If you care about this issue, please try pylint-ignore so we can have a better idea about the limitations. (I know I also should do that, but I'm using |
I tried out As a side note, the @udifuchs I tried out I would prefer something along the lines of what @KotlinIsland and @stdedos said: a config file with all warnings disabled. That way I can go through one by one and address each warning in turn without getting overwhelmed. |
We can fix this if we integrate it in pylint by putting the extra context in the pylintrc / pyproject.toml. pylint-silent could be documented for those who prefer to add disable directly in the code. |
🙏 I wouldn't want to have the Also, for some reason (valid, I am sure), the creator decided to have full unified diff + "all other managerial info" there. I'm all for the "one true file" approach, and this file is too massive to be merged. |
If you look closely, it's not actually a diff, it's just a copy of the file contents, prefixed with line numbers. This is so |
Whatever gets ignored/silenced, either gets marked in the code (as Idea for a minimal toml format [tool.pylint.ignore]
"W0511-fixme" = [
"src/myproject/filename.py:fe2431a0"
] Here the |
Good point. I'm starting to think that adding disable in the code like pylint-silent does is the easier approach. Making the Maybe we could propose multiple automated approach using what already exist in pylint based on what is done manually right now already:
This would probably satisfy the various granularity need while not forcing us to add another system on top of what already exists. If we want to automate even more we could include a threshold, if it's more then X line disable for a file then we disable at the file level directly. If it's more than Y file disable for the project, then we disable the message at the project level. |
any update on this?
Is there anything I can do to help (either in this repo or in |
Have a look at darker |
Our existing advice from the doc is:
I think pylint-ignore is "too clever" and thus would be hard to maintain. The big conf file would also be a barrier for adoption. The last message is an actionable design proposal (add disable for existing message but with a threshold so it's disabled at the right level: locally, file, or project), so it could be a start. Do you have an opinion @DanielNoord ? If you want to contribute that would be greatly appreciated @nimrodV81 . |
Feels like we might indeed have this as an option, but not sure how difficult it would be to implement. |
I don't think including this in pylint is the right way to do it at this point, there's just too much to know about the internal. One way to do it would be to create an independent one-time use tool that would get the json report from |
thank you @Pierre-Sassoulas for your fast replies |
What is your threshold for 'countless' ? I think a balance can be found between messages not raised when they should because of disable that are too broad and having too much disable littering the code. I'm trying to find what would be acceptable :) |
@Pierre-Sassoulas my current report has ~2000 issues |
I mean, what is an acceptable number of disable to add inline ? 5 per file, 20 per file, 50 for the whole repository ? Is adding a |
@Pierre-Sassoulas first, thank you for taking the time to discuss with me |
You should check out darker, it's kinda exactly what you want, it runs a linter on only the changed parts of code, so you can adopt pylint 100% incrementally. |
Just my 2cents from someone that's integrated Psalm, PHPStan (for PHP) and others: Baseline support is super valuable for legacy codebases in for-profit contexts. Why? It boils down to the costs (developer time) and benefits (developer time):
Alternatives:
Concerning the implementation of a baseline support, it could be easier than it sounds. Without looking at the code yet, I image that at some point, there is a scanner that emits a stream of issues. The receiver then takes each and formats it according to the output spec. The baseline support would be implemented as a filter/converter (e.g. Decorator Pattern) in between. Each message is taken, matched with the baseline and, when new, emitted again. When it's in the baseline, it gets dropped and marked as "found". In the end, any message in the baseline that is not "found" is emitted as "expected but missing". Concerning the configuration, I would like to see the baseline in a single but separate file, which is imported into the main configuration file. This split is advisable, because the base config is manually maintained while the baseline is machine-generated. I'm going to take a look into the code, maybe that's not even too complicated to implement... :) |
Just wanted to share that our solution was to use @udifuchs 's |
I'm not sure about adding pylint-silent as an extra in requirements because there's multiple option to fix this problem. I think we need a design decision that make sense and "one and preferably only one way to do Basically there's:
I'm adding vote emojis on each option so it's easier for people to tell their preferred approach without spamming the issue. |
Uh oh!
There was an error while loading. Please reload this page.
Current problem
I'm trying to adopt pylint (or update to a new version, or enable more checks), but I'm getting >10000 errors in my codebase!
If pylint supported baseline functionality this would be extremely easy.
Desired solution
A baseline like Qodana, basedmypy etc
Additional context / Workaround
The usage of darker provides a good solution to this case.
The text was updated successfully, but these errors were encountered: