-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Implement config file location 'base' to config all environments of an interpreter #11487
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
Changes from 3 commits
b777bcd
4a87ab0
93ade85
81d6053
8d34a11
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,13 +19,14 @@ and how they are related to pip's various command line options. | |
|
||
## Configuration Files | ||
|
||
Configuration files can change the default values for command line option. | ||
They are written using a standard INI style configuration files. | ||
Configuration files can change the default values for command line options. | ||
They are written using standard INI style configuration files. | ||
|
||
pip has 3 "levels" of configuration files: | ||
pip has 4 "levels" of configuration files: | ||
|
||
- `global`: system-wide configuration file, shared across users. | ||
- `user`: per-user configuration file. | ||
- `global`: system-wide configuration file, shared across all users. | ||
- `user`: per-user configuration file, shared across all environments. | ||
- `base` : per-base environment configuration file, shared across all virtualenvs with the same base. (available since pip 23.0) | ||
- `site`: per-environment configuration file; i.e. per-virtualenv. | ||
|
||
### Location | ||
|
@@ -47,8 +48,11 @@ User | |
|
||
The legacy "per-user" configuration file is also loaded, if it exists: {file}`$HOME/.pip/pip.conf`. | ||
|
||
Base | ||
: {file}`\{sys.base_prefix\}/pip.conf` | ||
|
||
Site | ||
: {file}`$VIRTUAL_ENV/pip.conf` | ||
: {file}`\{sys.prefix\}/pip.conf` | ||
``` | ||
|
||
```{tab} MacOS | ||
|
@@ -63,8 +67,11 @@ User | |
|
||
The legacy "per-user" configuration file is also loaded, if it exists: {file}`$HOME/.pip/pip.conf`. | ||
|
||
Base | ||
: {file}`\{sys.base_prefix\}/pip.conf` | ||
|
||
Site | ||
: {file}`$VIRTUAL_ENV/pip.conf` | ||
: {file}`\{sys.prefix\}/pip.conf` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't change this, since There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
``` | ||
|
||
```{tab} Windows | ||
|
@@ -81,8 +88,11 @@ User | |
|
||
The legacy "per-user" configuration file is also loaded, if it exists: {file}`%HOME%\\pip\\pip.ini` | ||
|
||
Base | ||
: {file}`\{sys.base_prefix\}\\pip.ini` | ||
|
||
Site | ||
: {file}`%VIRTUAL_ENV%\\pip.ini` | ||
: {file}`\{sys.prefix\}\\pip.ini` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't change this, since There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree on the understanding, but until I re-read https://docs.python.org/3/library/venv.html#creating-virtual-environments, thought you were technically it is wrong. It turns out that it is indeed documented that
Therefore the CPython documentation that states:
Is sadly misguided - it isn't safe to use that environment variable to determine virtual-environment-ness IMO (and using env-vars to determine that sounds like a bad idea anyway - residual environment variables are a concern there). (btw: Recommended it gets reverted in python/cpython#21970 (comment)) OK that is a bit of an aside. I'm open to reverting to Do you still want me to revert? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As this is documentation, and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the clarity. Commit added to this tune. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
``` | ||
|
||
### `PIP_CONFIG_FILE` | ||
|
@@ -102,6 +112,7 @@ order: | |
- `PIP_CONFIG_FILE`, if given. | ||
- Global | ||
- User | ||
- Base | ||
- Site | ||
|
||
Each file read overrides any values read from previous files, so if the | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
In the case of virtual environments, configuration files are now also included from the base installation. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,12 +36,20 @@ | |
kinds = enum( | ||
USER="user", # User Specific | ||
GLOBAL="global", # System Wide | ||
SITE="site", # [Virtual] Environment Specific | ||
BASE="base", # Base environment specific (e.g. for all venvs with the same base) | ||
SITE="site", # Environment Specific (e.g. per venv) | ||
ENV="env", # from PIP_CONFIG_FILE | ||
ENV_VAR="env-var", # from Environment Variables | ||
) | ||
OVERRIDE_ORDER = kinds.GLOBAL, kinds.USER, kinds.SITE, kinds.ENV, kinds.ENV_VAR | ||
VALID_LOAD_ONLY = kinds.USER, kinds.GLOBAL, kinds.SITE | ||
OVERRIDE_ORDER = ( | ||
kinds.GLOBAL, | ||
kinds.USER, | ||
kinds.BASE, | ||
kinds.SITE, | ||
kinds.ENV, | ||
kinds.ENV_VAR, | ||
) | ||
VALID_LOAD_ONLY = kinds.USER, kinds.GLOBAL, kinds.BASE, kinds.SITE | ||
|
||
logger = getLogger(__name__) | ||
|
||
|
@@ -70,6 +78,7 @@ def get_configuration_files() -> Dict[Kind, List[str]]: | |
os.path.join(path, CONFIG_BASENAME) for path in appdirs.site_config_dirs("pip") | ||
] | ||
|
||
base_config_file = os.path.join(sys.base_prefix, CONFIG_BASENAME) | ||
site_config_file = os.path.join(sys.prefix, CONFIG_BASENAME) | ||
legacy_config_file = os.path.join( | ||
os.path.expanduser("~"), | ||
|
@@ -78,6 +87,7 @@ def get_configuration_files() -> Dict[Kind, List[str]]: | |
) | ||
new_config_file = os.path.join(appdirs.user_config_dir("pip"), CONFIG_BASENAME) | ||
return { | ||
kinds.BASE: [base_config_file], | ||
kinds.GLOBAL: global_config_files, | ||
kinds.SITE: [site_config_file], | ||
kinds.USER: [legacy_config_file, new_config_file], | ||
|
@@ -344,6 +354,8 @@ def iter_config_files(self) -> Iterable[Tuple[Kind, List[str]]]: | |
# The legacy config file is overridden by the new config file | ||
yield kinds.USER, config_files[kinds.USER] | ||
|
||
yield kinds.BASE, config_files[kinds.BASE] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The "base" location should be skipped outside of virtual environments, where There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should also provide a (temporary) opt-out from this, for users who might find this change to be disruptive. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I considered this before opening the PR, but the problem is that we don't know what config files need to be loaded at this point - there may be a I was further dissuaded from my implementation by the todo at the top of the function, which asks for less logic in what config files to choose https://github.com/pypa/pip/pull/11487/files#diff-eadf79f17f8c7b56d3743fb4bb0ef3c2c2e062e493e8c25962f3319ef264f8bfR335.
I agree. I could add something specific to
That would amount to quite a big change though - and might require some thought about doing the config loading in two passes (first to determine the precedence, then to actually load it in the desired order) - this would reduce to a single pass in the case that the precedence isn't overridden. I would be happy to talk about this offline/elsewhere if this is something you would like me to pursue. If you want me to keep it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I took a poke at implementing config-precedence config at pelson@0553eb1. I think it turned out quite well in fact - might be a nice alternative option for allowing users to opt-out of I would be happy to discuss this on a separate issue, or on discord, if this is interesting to pursue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the temporary opt-out comment is withdrawn in #11487 (comment), the remainging discussion is:
In my response, I highlight that this particular function has a comment:
I agree with the suggestion that the function smells, as the function's objective should be to unconditionally enumerate the locations that configuration may come from, with For this reason, I added the BASE config file unconditionally. If we want to optimise and avoid BASE and SITE being loaded if they are the same, then I would put this logic in the |
||
|
||
# finally virtualenv configuration first trumping others | ||
yield kinds.SITE, config_files[kinds.SITE] | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.