PyCQA / pydocstyle

docstring style checker
http://pydocstyle.org
MIT License
1.11k stars 189 forks source link

Add support for the XDG Base Directory Specification #520

Open mohkale opened 3 years ago

mohkale commented 3 years ago

Configuration files should be stored under $XDG_CONFIG_HOME (which defaults to ~/.config)

For example: ~/.pydocstyle => $XDG_CONFIG_HOME/pydocstyle

This blog post lists the advantages of using the XDG Base Directory Specification as follows:

Atm pydocstyle seems to be just looking in the current directory,and then each parent directory until a configuration file matching one of these is found: https://github.com/PyCQA/pydocstyle/blob/5118faa7173b0e5bbc230c4adf628758e13605bf/src/pydocstyle/config.py#L81-L90

For example if you're in the directory /foo/bar/baz/bag it'll try:

I'd recommend just adding a trailing check after all of these that looks in $XDG_CONFIG_HOME as well.

S.N. If it's worth anything pycodestyle has XDG support.

sigmavirus24 commented 3 years ago

S.N. If it's worth anything pycodestyle has XDG support.

Yeah, so does Flake8, and it's not something I'd recommend as a maintainer of either of those projects. I've actively tried to remove it and will continue doing so

mohkale commented 3 years ago

@sigmavirus24 why?

EDIT:

Looking at the implementation in pycodestyle, the XDG compliance is isolated to these lines:

https://github.com/PyCQA/pycodestyle/blob/c47f5c1f977c20f16c19bc282834c70c9b40d800/pycodestyle.py#L85-L94

I'm slightly curious why it doesn't fallback to the users home directory when $XDG_CONFIG_HOME/.pycodestyle is unassigned but otherwise this seems like a straightforward implementation.

It should be pretty straightforward in pydocstyle cause from the looks of things we already loop through a collection of paths (the paths from the current directory up) and then through a collection of filenames, returning the first one we find. There might be some complications due to configuration inheritance but otherwise I don't see the issue.

If you have some sort of moral opposition to XDG for some reason, I'd also be fine with literally any solution that doesn't clutter my home directory. For example pylint has $PYLINTRC to specify a config file location.

Lastly this is a tangentially related issue, system libraries don't inherit my global pydocstyle config. So for example If I have a file like this at ~/foo/main.py:

import sys
import time
import json
import codecs
import threading

and I hit go-to-definition on threading I get taken to /usr/lib/python3.9/threading.py and now pydocstyle doesn't check my config at ~/.pydocstyle when linting threading.py so I start getting innocuous errors I'm not interested in (eg. D107). To summarise If a project doesn't setup a local config, pydocstyle should defer to a global config but a global config that relies on the project being relative to your home directory isn't very useful in these situations. A simple fix for this specific situation would be to create the file /.pydocstyle but I think we can all agree that's not an acceptable solution, especially on windows where the root directory is distinct for each mounted drive.

sigmavirus24 commented 3 years ago

Ah you want a fallback. That will be very confusing. By default, pycodestyle and flake8 merge those as the lowest priority configuration items when running the tool (as it merges other configuration values). That is the scenario in which it's a right and awful nightmare.

To be explicit, you're looking for inconsistency amongst tools that that people frequently use together.

mohkale commented 3 years ago

@sigmavirus24

By default, pycodestyle and flake8 merge those as the lowest priority configuration items when running the tool (as it merges other configuration values). That is the scenario in which it's a right and awful nightmare.

Isn't that how a global config should work? It specifies defaults you always want set and then local configs add more project specific configurations. Of course the local configs may also choose to disregard global configs which I don't see any issue with.

If you're saying pydocstyle uses /.pydocstyle even when ~/.pydocstyle is found (merging all configs as it finds them), then great, literally just add $XDG_CONFIG_HOME to the end of the directory search list and you should have (very rudimentary) XDG compliance.

To be explicit, you're looking for inconsistency amongst tools that that people frequently use together.

So... I should open a similair issue on flake8 as well and encourage releasing this feature on new minor versions at the same time?

sigmavirus24 commented 3 years ago

Isn't that how a global config should work? It specifies defaults you always want set and then local configs add more project specific configurations.

For normal tools, that works great. Flake8 and pycodestyle have seen this cause big headaches for folks who have one thing configured locally and then their coworkers see something different, or CI reports something different and they can't figure out why. Global configuration files in this area are a pox for merging on top of

mohkale commented 3 years ago

@sigmavirus24

For normal tools, that works great. Flake8 and pycodestyle have seen this cause big headaches for folks who have one thing configured locally and then their coworkers see something different, or CI reports something different and they can't figure out why. Global configuration files in this area are a pox for merging on top of

I don't have much experience using such tools so feel free to correct any misconceptions, but couldn't such issues be just as easily fixed by adding a --no-global-config option or something to that affect. It seems like the issue you describe is because the tool assumes configuration locations which other users/CI-CD-systems don't have and those configs introduce difficult to reproduce bugs. If that's the case the project should setup a linting command which properly excludes global configs and exclusively specifies the desired configuration path. To summarise I don't see why me having a config at /home/.pydocstyle (notice lack of username) that won't be on a CI/CD host is OK but having one at /home/<username>/.config/pydocstyle is not?

sigmavirus24 commented 3 years ago

If that's the case the project should setup a linting command which properly excludes global configs and exclusively specifies the desired configuration path.

So you're saying that users shouldn't be shooting themselves in the foot? That's not exactly compassionate or user-focused design.

To summarise I don't see why me having a config at /home/.pydocstyle (notice lack of username) that won't be on a CI/CD host is OK but having one at /home/<username>/.config/pydocstyle is not?

That's not what I'm claiming. I'm saying any non-project config should probably only be used if a local project configuration can't be found.

mohkale commented 3 years ago

@sigmavirus24

So you're saying that users shouldn't be shooting themselves in the foot? That's not exactly compassionate or user-focused design.

Lol :rofl:. I meant projects should be configured to allow local testing without global configs. For example my editor will probably be using my global config and the project local config (I'm using pyls with the pydocstyle optional extension), but I should add a Makefile with a lint task to the project that uses this hypothetical --no-global-config option. That makes the results at least a little more reproducable on CI/CD and local machine. Sorry if I wasn't clear enough.

That's not what I'm claiming. I'm saying any non-project config should probably only be used if a local project configuration can't be found.

Okay, I understand that but from my understanding of the docs that's not how pydocstyle currently works (please correct me if I'm wrong on this). Regardless I don't really mind if this is what you'd prefer, it's not exactly like configuration inheritance has personally helped me out before and in retrospect it's probably more hurtful to development because your local setup (and tools eg. IDE) won't match the one associated with a project on CI/CD systems. But I feel we're getting sidetracked. To clarify all I want is a global config that doesn't clutter up my home directory (and ideally doesn't depend on the relative path to my project from the root directory) and if a project local config exists, sure, don't even bother with a global config. My concern is the former the latter is out of bounds for this issue IMO.