-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add different configuration for different sub directories #618
Comments
Original comment by Florian Bruhin (BitBucket: The-Compiler, GitHub: @The-Compiler?): Personally, I'd gladly use this feature when #352 is fixed as well 😄 As I don't use files = []
for dirpath, _dirnames, filenames in os.walk('tests'):
for fn in filenames:
if os.path.splitext(fn)[1] == '.py':
files.append(os.path.join(dirpath, fn))
disabled = [
'attribute-defined-outside-init',
'redefined-outer-name',
'unused-argument',
'missing-docstring',
# #511/
'undefined-variable',
]
no_docstring_rgx = ['^__.*__$', '^setup$']
args = (['--disable={}'.format(','.join(disabled)),
'--no-docstring-rgx=({})'.format('|'.join(no_docstring_rgx))] +
sys.argv[1:] + files)
subprocess.call(['pylint'] + args) |
Original comment by Claudiu Popa (BitBucket: PCManticore, GitHub: @PCManticore): Having specific configuration files per subdirectories would be nice. I'll probably use it myself, The problem is that it probably won't be trivial to do it, since the discovery of Anyway, if you could spent some time on a patch and make this work, that would be really awesome. |
Original comment by Claudiu Popa (BitBucket: PCManticore, GitHub: @PCManticore): By the way, Florian, someone worked on issue #352 at the sprints, but a PR was never made. :( |
Original comment by Fergal Hainey (BitBucket: FerHai): Sounds like adding directories to the config and making the checkers aware of it would be easier than changing how config is loaded. Unless this is a feature the logilab.common dependency would enjoy too? I'm not yet familiar with pylint and dependencies internals, but will take a look. |
Original comment by Florian Bruhin (BitBucket: The-Compiler, GitHub: @The-Compiler?): I started some work on ripping out |
Original comment by Claudiu Popa (BitBucket: PCManticore, GitHub: @PCManticore): Having this feature in logilab.common will not help pylint, since we want to move away from it. |
Original comment by Claudiu Popa (BitBucket: PCManticore, GitHub: @PCManticore): By the way, in the issue #28, Torsten said something about using forests of configuration. That sounds like what we're planning to do here, might be worth pinging him for more details. |
I would like a solution where the project wide pylintrc supports ignoring some Pylint-warnings for certain folders and/or Python modules. Is anybody working on this issue? I could take a crack at it otherwise, but I have no idea where to start. |
No, no one is working currently on this issue, feel free to take a stab at it. But this issue is about introducing support for configurations per subdirectories, which might not necessarily mean support for disabling messages for particular Python modules (it would though mean that you could disable messages in a subdirectory config). Unfortunately, I have no idea right now how can the messages be disabled for particular modules, I have to think of it (probably we can't use disable for that, so we'd need to add a new option, something on the lines of scoped-disabled=a.py:no-member,b.py:unbalanced-tuple-unpacking or something of sorts). |
You are right that this issue is not necessarily (but possibly) related to what I want to achieve. I created a separate issue for folder-specific disables here: #871 |
I'm in need of this feature so I'm looking to implement it but I need to nail down a few details first. Mainly where should I look for configuration files and in what order? My current thinking is to look for and load the files in the opposite order that they are looked for at the moment. So load In terms of the command line I'm thinking we allow passing in In terms of implementation in code, my current plan is to allow a list of config file locations (or a single path) wherever we currently use |
Hi @AWhetter There are two major issues with implementing this feature, as far as I can tell:
In the first case, I think that passing multiple --rcfile won't help that much, since each one of them would probably be tailored for one folder or another, while this feature could be left out to the part that discovers configuration files on disk.
Now this gets into the second part of the issue, which is deciding how to pass each inner object into a checker. So what we know so far is that a checker has a underlying config object and it's not necessarily the duty of the checker to know which config object it should use. What, I think, would be useful to have is this: As far as I can think of it, this seems to be it. There are some rough edges in this proposal, but hopefully we could flesh them out. Let me know what is your opinion about it. |
I agree that multiple I don't like the idea of always needing complete rcfiles. My main motivation for implementing this issue was that say you have a team that lints multiple projects, then the team could have a global config file for linting against the team's standard. But then there may be projects that already have their own conventions and the team would want to be able to override certain aspects of the global configuration for that project. As for lookups the tree idea would work for complete pylintrc files but seems less desirable for override configs. We'd have to parse the global config every time we come across an override file, and then do the same again once we leave the overridden directory. |
So you're saying that we could support the following protocol for a configuration:
So, if I'll call
Inner subdirectories, other than this layout, could potentially have a pylintrc of their own that is included from the project's .pylintrc through an include directive, but that is a separate feature that we can address. I could live with this functionality, as long as we limiting to the closest subdirectories for the root of the project, otherwise, the understanding of what's happening could get fuzzy and I don't want to make this more complicate than it is. Also, I'm thinking that currently this might introduce some unwanted behaviour for users that are having a .pylintrc in their project and, for some reason, they also have a global .pylintrc, which means the per-project .pylintrc of theirs will suddenly be a patch of the global one. We should enforce this behaviour through a flag, that users can disable if they want to have the older feedback of not patching anything, just overriding the configuration. Regarding the implementation, I think it would be probably cleaner to have multiple config objects, corresponding to each directory's .pylintrc. One issue with your stack-based approach is that the configuration is processed before calling the checkers, which means that the processing will get entangled in the checking process, which would make things more fuzzy as well (plus you don't know exactly which directory you're processing until you're not passing a new Module node to the checkers, ideally, the configurations should be processed so far). Let me know if there is anything you'd like to discuss, otherwise we can already start working on this and by it, I mean you. ;-) |
In your example how will we know what is a project level override and what is a directory level override? I'm actually drifting more towards looking for pylintrc overrides on every level. Yes it could get complicated to figure out which rules in which pylintrc are applied to a file, but I think that this is a decision that can be left up to the user. It gives the user more flexibilty, but we should make it clear in documentation that this comes at the cost of complexity. |
Okay, I don't mind having it like that in this case. Also, we should take a look to see what other tools are doing, for instance Rubocop for Ruby and ESLint for javascript. At least in the former's case, I know they have some similar as the plan we're trying to flesh out here, would be interesting to see how they approached this problem. |
So Rubocop has quite an elegant solution. It will find the first configuration file in the directory chain, but within the config file you can choose to include a configuration from elsewhere via either a relative path, absolute path, or even a remote file. It doesn't seem to have a concept of a global config other than the built in default options. See https://github.com/bbatsov/rubocop#inheriting-from-another-configuration-file-in-the-project. ESLint searches for configuration files on every level, similar to what I was suggesting here. See https://github.com/bbatsov/rubocop#inheriting-from-another-configuration-file-in-the-project. I now prefer Rubocop's solution though. I think we can achieve the functionality we are looking for with an "include" option in pylint files (or a similarly named option). So we would continue to search for the nearest pylintrc, and a project subdirectory pylintrc file will have to explicitly include a project level pylintrc file to indicate that it wants to overwrite the settings in that file. This should be much easier for a user to use rather than using the pylintrc in every parent directory because the user is more in control of what overrides what. We can then use the "tree of config files" idea that you suggested here (#618 (comment)) to build config objects for each subdirectory and apply each one appropriately. I don't think that it's a good idea for us to implement remote pylintrc files like Rubocop has because we'd be automatically downloading a python file and evaluating it. So we should stick with absolute and relative paths. The only downside with the includes solution is that, in the case that I described where you might want a team pylintrc file to apply to a range of projects, each project pylintrc file would need to include the path to the team pylintrc file. If the path to the team file changes then many pylintrc files need to be updated. This is maybe a bit of an unusual scenario, but I think it could be fixed with something like a |
I think this approach sounds very good, so I'm +1 for doing it as is. |
We have a project-wide lint config we like. But for tests in the tests dir, we would like to disable Ftr, introducing an |
I started the implementation of this but I felt like I was really shoehorning the code into what already there. So instead I need to do some refactoring in the lead up resolving the actual issue:
It's worth noting that we can skip steps 2, 3, and 4, but we'll see a slight performance hit because of it. So I'll do that and then post the other steps as issues afterwards. |
Sounds good overall. One small comment regarding |
Hello guys, I just want to check if anyone has found an alternative way to do this at the moment? Thank you |
This issue is tracked in project as 'per directory configuration', there's a bunch of issues that are step towards this goal and that everyone can contribute too. |
Thank you for the response @Pierre-Sassoulas |
I'm working on a new approach in: Instead of doing all the refactoring that the discussion here has led to, I think there is a much simpler approach possible which I have outlined in that PR.
With #6789 we already check which namespace we need before checking a file. We only need a good system to iterate over all directories and create Namespaces for them if we encounter a new configuration file. That should be relatively easy now that the parsing of configuration is in one straightforward method. I'd welcome any PRs that tries to implement step 2 😄 |
I did not find if this already discussed, but if you will take a look at how Mypy allows to configure the same, you will see an easy (for the end user) solution: [mypy-my_directory.*,my_another_module.*,something_else.*]
rule_name_that_I_want_to_set_for_the_mentioned_dirs = false
another_rule_only_per_these_dirs = true
Can not be it done for pylint in the same way? Demo pylint config: # Global rules
disable = something, something_else
# Specify rules per specific directories
[pylint-tests,deploy.tests]
disable =
# Do not complain about Pytest fixtures
redefined-outer-name, |
@AIGeneratedUsername I did it through |
A complication I just thought of: if the configuration files can load plugins, what does it mean to have a plugin enabled for one subdirectory and not another? If plugins can't be unloaded at runtime (or perhaps disabled temporarily) it would be hard for that concept to work with different plugin configurations in different contexts with a single invocation of pylint. Edited to add: That could be valuable though. I've been using the pylint-pytest plugin for example, and it would be nice to be super-confident that it's not going to have any impact outside of my test subdirectory. |
Yes, this is definitely a concern that we should take into consideration. |
@nickurak I think at least for the initial version of this feature, we could ignore per folder plugins functionality. |
I think @nickurak makes a good point. We can't really ignore this as subdirectories could trigger the loading of plugins which would affect the rest of the run. We would need to explicitly disable plugins if we want to avoid this. |
Yeah, this is what I meant. Also, I am not sure how dangerous executing per folder plugins could be, I feel like this could be a possible attack vector. |
i see this has been open for awhile. is there trouble getting a dev to fix this issue? what is blocking this for so long |
Originally reported by: Fergal Hainey (BitBucket: FerHai)
I'm using pytest and redefined-outer-name is a false negative in these cases as it's part of pytest's design. I'd like to run pylint over the whole project to flag things automatically before code reviews. I'd like to catch cases of redefined-outer-name outside the tests folder.
I could add comments to the modules but 1. that's a lot of comments and 2. changes will require changing as many comments.
What could be nice is looking up through basedirs of the file being linted for pylintrc files and taking config in closer pylintrcs as higher priority. Or maybe something in the project wide pylintrc to denote some config applies to a directory.
Would this be considered a good idea? I'm open to making a patch if it's considered worthwhile.
The text was updated successfully, but these errors were encountered: